From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM12-MW2-obe.outbound.protection.outlook.com (NAM12-MW2-obe.outbound.protection.outlook.com [40.107.244.131]) by mx.groups.io with SMTP id smtpd.web08.9763.1637167798630383019 for ; Wed, 17 Nov 2021 08:49:58 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@os.amperecomputing.com header.s=selector2 header.b=qhmpcN/A; spf=pass (domain: os.amperecomputing.com, ip: 40.107.244.131, mailfrom: nhi@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=l20s1RcsTfiPe4quHAHrJEsmz/awSlv8yoAspyh1Eewk82labED7fELcVpDg1Hr2qQdyQ+ZYv3/ep+iZ/dLkfYIOy81y1DZ6cL8JJa243CFxoU9vTaQCetLfV1v/XWJ005+uL8eaT8/ashKGCLx6Z81euwK8VNGxvGrLDK64Ha8VdjCL/og+b5YzCkcoKmfvnVHI296D3Zmw8RwwNmvv2ScyF2Ig28ji4qZTxzjMFQS0M5VN9K7NqAu9m6TsDF9z6oYPsBpfyqfRTPecp4n7x2wSo5rLLxfFfLK1UPopXcPxXjbRNbzJtElbd0PqB7fRY8pGe6/qbk/YE2kV5epUVg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=LpzvWe/aGpLfl0PiWZZADuaBPC2Bum6I9pjWKkqyIMs=; b=SpcbMPqLBovoC0cLi+7tFHrcb//2uLnueji7fVll9xHFnZszeLXM4aDo0dF8O+jxDYf3+hUnSiPgOgsflfS4XqJd0NPt1oLSIEIaw6W6M0les4q5wUQulxzFkR+g2HgmC2XXJRd9GI8kWnrNzPGGT2LyeLXxcn6WvontMPSFyL9dpID0uJKIaxsCqOp0TAFrKjAPPuQLL/3OioV6mOO1YjBb/HHoM8JPq/M6mMgubjMIPSpcJzC0XR7hp/RsXZsnMr+/h4f2GtUW/RGQcXY7pYRbuuN103r+ptn7eOhtxsYK0Gf1r/NaWk26EfgTYLS6HEAPLQLJIebMJehF9+ORxA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=os.amperecomputing.com; dmarc=pass action=none header.from=os.amperecomputing.com; dkim=pass header.d=os.amperecomputing.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=os.amperecomputing.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=LpzvWe/aGpLfl0PiWZZADuaBPC2Bum6I9pjWKkqyIMs=; b=qhmpcN/AyOlEu2Kvrivu7Zq84fFyT5db6chHF2BEOs8lGprCaVuZ6Hb6WF5jPR9AEVwRELzujXjG/APOLMnXfsQ2pbr6rsxA/4cxA3YjT9BhBE5q5BOa0ClC8jFsJ8UbkXrbdV3vOTTecHD04vq6IlbUaR5MGjRhva6fMBPDzQk= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=os.amperecomputing.com; Received: from PH0PR01MB7287.prod.exchangelabs.com (2603:10b6:510:10a::21) by PH0PR01MB6454.prod.exchangelabs.com (2603:10b6:510:1b::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.20; Wed, 17 Nov 2021 16:49:57 +0000 Received: from PH0PR01MB7287.prod.exchangelabs.com ([fe80::254c:9533:7f35:aee]) by PH0PR01MB7287.prod.exchangelabs.com ([fe80::254c:9533:7f35:aee%4]) with mapi id 15.20.4713.019; Wed, 17 Nov 2021 16:49:56 +0000 From: "Nhi Pham" To: devel@edk2.groups.io CC: patches@amperecomputing.com, nhi@os.amperecomputing.com, vunguyen@os.amperecomputing.com, Thang Nguyen , Chuong Tran , Phong Vo , Leif Lindholm , Michael D Kinney , Ard Biesheuvel , Nate DeSimone Subject: [edk2-platforms][PATCH v5 07/30] AmpereAltraPkg: Support UEFI non-volatile variable Date: Wed, 17 Nov 2021 23:47:04 +0700 Message-ID: <20211117164727.10922-8-nhi@os.amperecomputing.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211117164727.10922-1-nhi@os.amperecomputing.com> References: <20211117164727.10922-1-nhi@os.amperecomputing.com> X-ClientProxiedBy: HKAPR04CA0001.apcprd04.prod.outlook.com (2603:1096:203:d0::11) To PH0PR01MB7287.prod.exchangelabs.com (2603:10b6:510:10a::21) Return-Path: nhi@os.amperecomputing.com MIME-Version: 1.0 Received: from sw004.amperecomputing.com (118.69.219.201) by HKAPR04CA0001.apcprd04.prod.outlook.com (2603:1096:203:d0::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4713.21 via Frontend Transport; Wed, 17 Nov 2021 16:49:53 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 076c067a-08fd-4e8e-b2a3-08d9a9ea4940 X-MS-TrafficTypeDiagnostic: PH0PR01MB6454: X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:10000; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: nu2XEBR9fSB/CRSCUFlxf0oDKOt2zfRDk4nr5FLN/ObiVKT/IGVIqdyOJ73zA9RcZwVff8pTU3bWUCatkeU6pxMWMm0EwIaP+6vi++4QeFE2HDqrG0/B6PAPEsTJbZSCXq2TckPpe0LNhn7JvOXcaPmDh0WcgSm1rencga2SEXVMwsHmk5WucijhPVYHkUEFb7KWqzLZPC9JHuWKSpNZPsWChBr3TwVLb/ZXZYKMrOoZ7cjKeaHnX6tZV2I11dcSoD6xuHHDh5gOslZnz+lmuuu5LTCQ1PswI1WMyN1KH/YlhhlKLBzUC/Fc+7d5HeDzxTQ1QbYN1G8rDSarAK5FI4pBerkbY6Jr76MLrUsLaSuJeQaALx4fbVJrGulB2wBnHjuLeWQLdClE4Y7pWs018uk8ZL0n5xbfwPBChG8tsuv7NJ5o2nz5w/wnJIYUfmylyT7IDitc8QVcrSAI6lJd5cXJncX66z156yJ2T+ZxoDPnqh2K0sPPPpPcjxMjXFMITA6hk+GSzk4L10rRgoKTABOcLrjoRYC3AwniIW2OnZvxmXYXnzY+y3fCjaf3ZFDflUQEl/oVuNeQKce+NHjZ7ZQzB6C81jOLxL78J27hqgR6cYBhkoSOnjVtHL5f7yPPphNZPJu/BnMHi04fFrs50q1KrZ3elxc1U1HfQ5tATdapHVZ9dil45U6OEYowS2qQGP6ile+7YP2Xtkgpxzn8mzZH0+RcoeioQGmoJL8m1q4= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH0PR01MB7287.prod.exchangelabs.com;PTR:;CAT:NONE;SFS:(4636009)(366004)(6666004)(8936002)(66476007)(52116002)(186003)(86362001)(2906002)(1076003)(83380400001)(54906003)(4326008)(66556008)(26005)(38100700002)(38350700002)(19627235002)(30864003)(6506007)(6916009)(6486002)(2616005)(956004)(5660300002)(6512007)(316002)(8676002)(66946007)(508600001)(44824005);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?9pWQyyElWrksTwzSqBHyk8zGMqMOXEfhA1Mm7n10pheYJigFCvMplPztPXR7?= =?us-ascii?Q?o2M1iUBHwp2zCJ326aIiYN4BN6t/I8KcxB+/e8dBG4OVtRril0MzmiIgEmC6?= =?us-ascii?Q?557VDN8A3aPlzyLVMz2afFEV5QBlBqPKARGXIwsPH/S972TIdbLkh1/yjJqq?= =?us-ascii?Q?caduaLvkoC9iX7BwqnkBG12gKaSwUeq68QqXV2GsIreuCTTxcrWwn6fj2eR1?= =?us-ascii?Q?txY7DZaiX9B5bH1zLa1t+OQsHZc+I/0HCYhXWRDJvw353A7406icZfAAWbpX?= =?us-ascii?Q?FZN0RC/jzEP77J2yQIU2xa0/PvyhMSVFoycI/C/VzCUdWuqNpvYIJl0UH6vQ?= =?us-ascii?Q?oLL+FOJd8TGEWROLbzdwBSDd2QuYU1wdAyXkXV9Nmb+/bze9hfxtDbO0jlVC?= =?us-ascii?Q?F/hju+HgZxDT7x35KAMn3tf7rFGhdmTDh7Qe6JlHTiSCiGl1zg4RuPyIcllh?= =?us-ascii?Q?5YyeUIZZ3auTOyDOy10XTjERGq8+HrIj+tUwTqOMJiuZGgIEekzkITnPemU2?= =?us-ascii?Q?6+DHyzubkhtU52YNYBup8Ct7JMY4yfWRSedgZg2dCjNCk0NYrR2yncuWiCMB?= =?us-ascii?Q?wcPLdnGzd6YMX6+vOlry3XrMdUVACiukg9wkGJyKgnCFvM247E+aaYV1vKuE?= =?us-ascii?Q?QEWHFpU+dMi+Y7iVO85tujkPRZrT7dhiYeMdYDMeC1zafvFiJmY+tAC0loAW?= =?us-ascii?Q?WOko5CvXrCagdYtVV6OOWECcSUaNZzFUDo44jxxBxxc9ihKHmYl7ncifua0I?= =?us-ascii?Q?Zw4CdlXjRjjSHdcMuq0UTrha2Cqs2LigYFTc/36B7C/hiV6NFeLJtb+wiR6Z?= =?us-ascii?Q?OpOJ3HVeG6mQ5Oom82NRBDpqbZfjaIbRhSrVvy8jdpt3OZRH67+tm4sQgBPU?= =?us-ascii?Q?EWtkVnaPyHiqpLiw/qqOQv6LGHmV9qUMtvegz/RPp3P7ZaxUeOuv2Qb0kzyR?= =?us-ascii?Q?XLjiUnWFj/3uLIUxODiostNHVgdahlesBrj8l1To7ZCuIwjZgE88X0r22H83?= =?us-ascii?Q?1uomkIt533FqijEjhr+QDUn53CzZUDDtdyFzFobvRc3OvrxhR+kdLplcEbIQ?= =?us-ascii?Q?HOoC/aag8b34pmprBjgNc895QLsoTBUUpXhvRCHq0r/8an1YwRVBEgQ6C166?= =?us-ascii?Q?Ie5B0RWQwbw3YZxnP7nVlkx2Q7DD86ZpRgqaHSbfNkl27Tv6/mTqdC9FSfkG?= =?us-ascii?Q?lMOTm6MFATJkYZkzlnL7bk8By8GeoVq4k3CKPyZ2iK5PDAkrNm5t9cSukqzn?= =?us-ascii?Q?RvLxJrPNp6qLCva1kfrJxBU9XFqkQLpcJMDjMun67gQWN4BK6C8JlzBur0/X?= =?us-ascii?Q?gnCyxhLl7x9mSHOWWA5LiL8SZ6daKFrPWLgCAmVaWTbfqkt9SOVhLy0Ow7LF?= =?us-ascii?Q?DMy9pPkRHGteYWVOoferimleczZpHGNfD/ll9uPZdoYoDusubfugVl3k4Xf8?= =?us-ascii?Q?S0DwEvdfECM6Qk7fxXaSr7q47htvkFYhv9FQcgha3jTNeVWhq3nsJpTDtqlb?= =?us-ascii?Q?EZHZhUMdGBn0hQiPJbo4HzXO97EtJNlsrSKHrNm4VF4cWLyNNinEYyqTAB6K?= =?us-ascii?Q?Lo+1vstlhJvjtSEqgChtshuBJ/xYUAeyc0S3r0jKYEcKqhSSlVmknPOfxqk2?= =?us-ascii?Q?cq+De/HHMBvQZbc7m9X0AQtnNWxPa5OH2UuE8dgNuM+L92jzW8W55/wSdb4r?= =?us-ascii?Q?jMpOSw=3D=3D?= X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-Network-Message-Id: 076c067a-08fd-4e8e-b2a3-08d9a9ea4940 X-MS-Exchange-CrossTenant-AuthSource: PH0PR01MB7287.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Nov 2021 16:49:56.9001 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3bc2b170-fd94-476d-b0ce-4229bdc904a7 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: +qFyAMtO5lgPewOE/mgHc/LxTVaWRlwSZSPWv2OhsY0a/krZRSPvWqKR3SyPs59pt8bf8BcRzxST/g92PEAxdEipN4gQDadlBftqIr+MBRs= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR01MB6454 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain From: Vu Nguyen This change supports storing the UEFI non-volatile varibles on the Flash through below modules: * FlashPei driver helps to restore the saved variables from flash on each boot. * FlashFvbDxe driver provides the implementation for the gEfiFirmwareVolumeBlock protocol Cc: Thang Nguyen Cc: Chuong Tran Cc: Phong Vo Cc: Leif Lindholm Cc: Michael D Kinney Cc: Ard Biesheuvel Cc: Nate DeSimone Signed-off-by: Nhi Pham Reviewed-by: Leif Lindholm --- Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec | 5 + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 6 +- Platform/Ampere/JadePkg/Jade.dsc | 5 + Platform/Ampere/JadePkg/Jade.fdf | 62 ++= - Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf | 54 ++ Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf | 49 ++ Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c | 525 ++= ++++++++++++++++++ Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.c | 125 ++= +++ 8 files changed, 827 insertions(+), 4 deletions(-) diff --git a/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec b/Silicon= /Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec index 6ebdf7db0a57..c6827d0cad7e 100644 --- a/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec +++ b/Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec @@ -31,6 +31,11 @@ [Guids] [Ppis] =20 [PcdsFixedAtBuild] + # + # NVRAM + # + gAmpereTokenSpaceGuid.PcdPlatformConfigUuid|"C416535D-970B-41B9-859A-3CA= F0FAF198C"|VOID*|0x00000010 + # # SMpro PMpro Pcds # diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon= /Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc index 3ffad43d1696..d6adcb8d77cf 100644 --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc @@ -523,8 +523,10 @@ [Components.common] ArmPlatformPkg/PlatformPei/PlatformPeim.inf Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf + Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf ArmPkg/Drivers/CpuPei/CpuPei.inf UefiCpuPkg/CpuIoPei/CpuIoPei.inf + MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf MdeModulePkg/Universal/Variable/Pei/VariablePei.inf MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf { @@ -578,9 +580,9 @@ [Components.common] # # Environment Variables Protocol # + Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf { - - gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeas= urementLibNull.inf diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jad= e.dsc index 7b70c5d6b5fb..0dd30dc14841 100644 --- a/Platform/Ampere/JadePkg/Jade.dsc +++ b/Platform/Ampere/JadePkg/Jade.dsc @@ -51,6 +51,7 @@ [Defines] DEFINE FIRMWARE_VER =3D 0.01.001 DEFINE SECURE_BOOT_ENABLE =3D FALSE DEFINE INCLUDE_TFTP_COMMAND =3D TRUE + DEFINE PLATFORM_CONFIG_UUID =3D 84BC921F-9D4A-4D1D-A1A1-1AE13EDD07E5 =20 # # Network definition @@ -83,6 +84,10 @@ [LibraryClasses] ##########################################################################= ###### [PcdsFeatureFlag.common] [PcdsFixedAtBuild.common] + # + # Platform config UUID + # + gAmpereTokenSpaceGuid.PcdPlatformConfigUuid|"$(PLATFORM_CONFIG_UUID)" =20 !if $(SECURE_BOOT_ENABLE) =3D=3D TRUE # Override the default values from SecurityPkg to ensure images diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jad= e.fdf index 459a1475ada1..de37415cd5c0 100644 --- a/Platform/Ampere/JadePkg/Jade.fdf +++ b/Platform/Ampere/JadePkg/Jade.fdf @@ -26,7 +26,7 @@ [FD.BL33_JADE_UEFI] ErasePolarity =3D 1 =20 # This one is tricky, it must be: BlockSize * NumBlocks =3D Size -BlockSize =3D 0x10000 +BlockSize =3D 0x10000|gAmpereTokenSpaceGuid.PcdFvBlockSize NumBlocks =3D 0x7C =20 ##########################################################################= ###### @@ -56,8 +56,61 @@ [FD.BL33_JADE_UEFI] =20 # # NV Variables -# Placeholder +# Offset: 0x00740000 +# Size: 0x00080000 # +0x00740000|0x00030000 +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|gEfiMdeModu= lePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize +DATA =3D { + ## This is the EFI_FIRMWARE_VOLUME_HEADER + # ZeroVector [] + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + # FileSystemGuid: gEfiSystemNvDataFvGuid =3D + # { 0xFFF12B8D, 0x7696, 0x4C8B, + # { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }} + 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C, + 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50, + # FvLength: 0x80000 + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + # Signature "_FVH" # Attributes + 0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00, + # HeaderLength # CheckSum # ExtHeaderOffset #Reserved #Revision + 0x48, 0x00, 0x2D, 0x09, 0x00, 0x00, 0x00, 0x02, + # Blockmap[0]: 0x2 Blocks * 0x40000 Bytes / Block + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + # Blockmap[1]: End + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ## This is the VARIABLE_STORE_HEADER + # It is compatible with SECURE_BOOT_ENABLE =3D=3D FALSE as well. + # Signature: gEfiAuthenticatedVariableGuid =3D + # { 0xaaf32c78, 0x947b, 0x439a, + # { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 }} + 0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43, + 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92, + # Size: 0x30000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariabl= eSize) - + # 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) =3D 0x2FFB8 + # This can speed up the Variable Dispatch a bit. + 0xB8, 0xFF, 0x02, 0x00, + # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32 + 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} + +0x00770000|0x00010000 +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64|gEfiMdeMo= dulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize +DATA =3D { + # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature =3D gEdkiiWorkingBl= ockSignatureGuid =3D + # { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0= x1b, 0x95 }} + 0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49, + 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95, + # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Res= erved + 0x2c, 0xaf, 0x2c, 0x64, 0xFE, 0xFF, 0xFF, 0xFF, + # WriteQueueSize: UINT64 Size: 0x10000 - 0x20 (FTW_WORKING_HEADER) =3D 0= xFFE0 + 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} + +0x00780000|0x00040000 +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64|gEfiMdeModu= lePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize =20 ##########################################################################= ###### # @@ -101,9 +154,11 @@ [FV.FVMAIN_COMPACT] INF ArmPlatformPkg/PlatformPei/PlatformPeim.inf INF Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf INF ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf + INF Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf INF Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressPeim/= BootProgressPeim.inf INF ArmPkg/Drivers/CpuPei/CpuPei.inf INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf + INF MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.i= nf INF MdeModulePkg/Universal/Variable/Pei/VariablePei.inf INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRo= uterPei.inf INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.in= f @@ -144,6 +199,7 @@ [FV.FvMain] INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandle= rRuntimeDxe.inf INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf INF ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf + INF Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf } =20 INF MdeModulePkg/Core/Dxe/DxeMain.inf @@ -173,6 +229,8 @@ [FV.FvMain] # Environment Variables Protocol # INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf + INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.i= nf + INF Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf =20 # # Multiple Console IO support diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.= inf b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf new file mode 100644 index 000000000000..008fd2315ffe --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf @@ -0,0 +1,54 @@ +## @file +# +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x0001001B + BASE_NAME =3D FlashFvbDxe + FILE_GUID =3D 9E6EA240-DF80-11EA-8B6E-0800200C9A66 + MODULE_TYPE =3D DXE_RUNTIME_DRIVER + VERSION_STRING =3D 0.1 + ENTRY_POINT =3D FlashFvbDxeInitialize + +[Sources] + FlashFvbDxe.c + +[Packages] + ArmPkg/ArmPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec + Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec + +[LibraryClasses] + DebugLib + FlashLib + PcdLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeLib + +[FixedPcd] + gAmpereTokenSpaceGuid.PcdFvBlockSize + + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 + +[Guids] + gEfiEventVirtualAddressChangeGuid + gSpiNorMmGuid + +[Protocols] + gEfiFirmwareVolumeBlockProtocolGuid ## PRODUCES + gEfiMmCommunication2ProtocolGuid ## CONSUMES + +[Depex] + gEfiMmCommunication2ProtocolGuid diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf b/= Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf new file mode 100644 index 000000000000..2b329c5d0987 --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf @@ -0,0 +1,49 @@ +## @file +# +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x0001001B + BASE_NAME =3D FlashPei + FILE_GUID =3D 967CFBD0-DF81-11EA-8B6E-0800200C9A66 + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D FlashPeiEntryPoint + +[Sources] + FlashPei.c + +[Packages] + ArmPkg/ArmPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec + Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec + +[LibraryClasses] + ArmSmcLib + BaseMemoryLib + DebugLib + FlashLib + MmCommunicationLib + PcdLib + PeimEntryPoint + +[FixedPcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 + + gAmpereTokenSpaceGuid.PcdPlatformConfigUuid + +[Depex] + TRUE diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.= c b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c new file mode 100644 index 000000000000..009694703ddd --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c @@ -0,0 +1,525 @@ +/** @file + + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +// +// These temporary buffers are used to calculate and convert linear virtua= l +// to physical address +// +STATIC UINT64 mNvFlashBase; +STATIC UINT32 mNvFlashSize; +STATIC UINT32 mFlashBlockSize; +STATIC UINT64 mNvStorageBase; +STATIC UINT64 mNvStorageSize; + +/** + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers in + lib to virtual mode. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +FlashFvbAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EfiConvertPointer (0x0, (VOID **)&mNvStorageBase); +} + +/** + The GetAttributes() function retrieves the attributes and + current settings of the block. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL inst= ance. + + @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the + attributes and current settings are + returned. Type EFI_FVB_ATTRIBUTES_2 is defined + in EFI_FIRMWARE_VOLUME_HEADER. + + @retval EFI_SUCCESS The firmware volume attributes were + returned. + +**/ +EFI_STATUS +EFIAPI +FlashFvbDxeGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + ASSERT (Attributes !=3D NULL); + + *Attributes =3D EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled + EFI_FVB2_READ_STATUS | // Reads are currently enabl= ed + EFI_FVB2_WRITE_STATUS | // Writes are currently enab= led + EFI_FVB2_WRITE_ENABLED_CAP | // Writes may be enabled + EFI_FVB2_STICKY_WRITE | // A block erase is required= to flip bits into EFI_FVB2_ERASE_POLARITY + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped + EFI_FVB2_ALIGNMENT | + EFI_FVB2_ERASE_POLARITY; // After erasure all bits ta= ke this value (i.e. '1') + + return EFI_SUCCESS; +} + +/** + The SetAttributes() function sets configurable firmware volume + attributes and returns the new settings of the firmware volume. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL in= stance. + + @param Attributes On input, Attributes is a pointer to + EFI_FVB_ATTRIBUTES_2 that contains the + desired firmware volume settings. On + successful return, it contains the new + settings of the firmware volume. Type + EFI_FVB_ATTRIBUTES_2 is defined in + EFI_FIRMWARE_VOLUME_HEADER. + + @retval EFI_SUCCESS The firmware volume attributes were return= ed. + + @retval EFI_INVALID_PARAMETER The attributes requested are in + conflict with the capabilities + as declared in the firmware + volume header. + +**/ +EFI_STATUS +EFIAPI +FlashFvbDxeSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + return EFI_SUCCESS; // ignore for now +} + +/** + The GetPhysicalAddress() function retrieves the base address of + a memory-mapped firmware volume. This function should be called + only for memory-mapped firmware volumes. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instan= ce. + + @param Address Pointer to a caller-allocated + EFI_PHYSICAL_ADDRESS that, on successful + return from GetPhysicalAddress(), contains the + base address of the firmware volume. + + @retval EFI_SUCCESS The firmware volume base address was returned. + + @retval EFI_UNSUPPORTED The firmware volume is not memory mapped. + +**/ +EFI_STATUS +EFIAPI +FlashFvbDxeGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + ASSERT (Address !=3D NULL); + + *Address =3D (EFI_PHYSICAL_ADDRESS)mNvStorageBase; + + return EFI_SUCCESS; +} + +/** + The GetBlockSize() function retrieves the size of the requested + block. It also returns the number of additional blocks with + the identical size. The GetBlockSize() function is used to + retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER). + + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL = instance. + + @param Lba Indicates the block for which to return the size. + + @param BlockSize Pointer to a caller-allocated UINTN in which + the size of the block is returned. + + @param NumberOfBlocks Pointer to a caller-allocated UINTN in + which the number of consecutive blocks, + starting with Lba, is returned. All + blocks in this range have a size of + BlockSize. + + + @retval EFI_SUCCESS The firmware volume base address was ret= urned. + + @retval EFI_INVALID_PARAMETER The requested LBA is out of range. + +**/ +EFI_STATUS +EFIAPI +FlashFvbDxeGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumberOfBlocks + ) +{ + UINTN TotalNvStorageBlocks; + + ASSERT (BlockSize !=3D NULL); + ASSERT (NumberOfBlocks !=3D NULL); + + TotalNvStorageBlocks =3D mNvStorageSize / mFlashBlockSize; + + if (TotalNvStorageBlocks <=3D (UINTN)Lba) { + DEBUG ((DEBUG_ERROR, "The requested LBA is out of range\n")); + return EFI_INVALID_PARAMETER; + } + + *NumberOfBlocks =3D TotalNvStorageBlocks - (UINTN)Lba; + *BlockSize =3D mFlashBlockSize; + + return EFI_SUCCESS; +} + +/** + Reads the specified number of bytes into a buffer from the specified blo= ck. + + The Read() function reads the requested number of bytes from the + requested block and stores them in the provided buffer. + Implementations should be mindful that the firmware volume + might be in the ReadDisabled state. If it is in this state, + the Read() function must return the status code + EFI_ACCESS_DENIED without modifying the contents of the + buffer. The Read() function must also prevent spanning block + boundaries. If a read is requested that would span a block + boundary, the read must read up to the boundary but not + beyond. The output parameter NumBytes must be set to correctly + indicate the number of bytes actually read. The caller must be + aware that a read may be partially completed. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instan= ce. + + @param Lba The starting logical block index + from which to read. + + @param Offset Offset into the block at which to begin reading. + + @param NumBytes Pointer to a UINTN. At entry, *NumBytes + contains the total size of the buffer. At + exit, *NumBytes contains the total number of + bytes read. + + @param Buffer Pointer to a caller-allocated buffer that will + be used to hold the data that is read. + + @retval EFI_SUCCESS The firmware volume was read successfully, + and contents are in Buffer. + + @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA + boundary. On output, NumBytes + contains the total number of bytes + returned in Buffer. + + @retval EFI_ACCESS_DENIED The firmware volume is in the + ReadDisabled state. + + @retval EFI_DEVICE_ERROR The block device is not + functioning correctly and could + not be read. + +**/ +EFI_STATUS +EFIAPI +FlashFvbDxeRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN OUT UINT8 *Buffer + ) +{ + EFI_STATUS Status; + + ASSERT (NumBytes !=3D NULL); + ASSERT (Buffer !=3D NULL); + + if (Offset + *NumBytes > mFlashBlockSize) { + return EFI_BAD_BUFFER_SIZE; + } + + Status =3D FlashReadCommand ( + mNvFlashBase + Lba * mFlashBlockSize + Offset, + Buffer, + *NumBytes + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to do flash read\n")); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Writes the specified number of bytes from the input buffer to the block. + + The Write() function writes the specified number of bytes from + the provided buffer to the specified block and offset. If the + firmware volume is sticky write, the caller must ensure that + all the bits of the specified range to write are in the + EFI_FVB_ERASE_POLARITY state before calling the Write() + function, or else the result will be unpredictable. This + unpredictability arises because, for a sticky-write firmware + volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY + state but cannot flip it back again. Before calling the + Write() function, it is recommended for the caller to first call + the EraseBlocks() function to erase the specified block to + write. A block erase cycle will transition bits from the + (NOT)EFI_FVB_ERASE_POLARITY state back to the + EFI_FVB_ERASE_POLARITY state. Implementations should be + mindful that the firmware volume might be in the WriteDisabled + state. If it is in this state, the Write() function must + return the status code EFI_ACCESS_DENIED without modifying the + contents of the firmware volume. The Write() function must + also prevent spanning block boundaries. If a write is + requested that spans a block boundary, the write must store up + to the boundary but not beyond. The output parameter NumBytes + must be set to correctly indicate the number of bytes actually + written. The caller must be aware that a write may be + partially completed. All writes, partial or otherwise, must be + fully flushed to the hardware before the Write() service + returns. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instan= ce. + + @param Lba The starting logical block index to write to. + + @param Offset Offset into the block at which to begin writing. + + @param NumBytes The pointer to a UINTN. At entry, *NumBytes + contains the total size of the buffer. At + exit, *NumBytes contains the total number of + bytes actually written. + + @param Buffer The pointer to a caller-allocated buffer that + contains the source for the write. + + @retval EFI_SUCCESS The firmware volume was written successfully= . + + @retval EFI_BAD_BUFFER_SIZE The write was attempted across an + LBA boundary. On output, NumBytes + contains the total number of bytes + actually written. + + @retval EFI_ACCESS_DENIED The firmware volume is in the + WriteDisabled state. + + @retval EFI_DEVICE_ERROR The block device is malfunctioning + and could not be written. + +**/ +EFI_STATUS +EFIAPI +FlashFvbDxeWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + + ASSERT (NumBytes !=3D NULL); + ASSERT (Buffer !=3D NULL); + + if (Offset + *NumBytes > mFlashBlockSize) { + return EFI_BAD_BUFFER_SIZE; + } + + Status =3D FlashWriteCommand ( + mNvFlashBase + Lba * mFlashBlockSize + Offset, + Buffer, + *NumBytes + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to do flash write\n")); + return EFI_DEVICE_ERROR; + } + + return Status; +} + +/** + Erases and initializes a firmware volume block. + + The EraseBlocks() function erases one or more blocks as denoted + by the variable argument list. The entire parameter list of + blocks must be verified before erasing any blocks. If a block is + requested that does not exist within the associated firmware + volume (it has a larger index than the last block of the + firmware volume), the EraseBlocks() function must return the + status code EFI_INVALID_PARAMETER without modifying the contents + of the firmware volume. Implementations should be mindful that + the firmware volume might be in the WriteDisabled state. If it + is in this state, the EraseBlocks() function must return the + status code EFI_ACCESS_DENIED without modifying the contents of + the firmware volume. All calls to EraseBlocks() must be fully + flushed to the hardware before the EraseBlocks() service + returns. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL + instance. + + @param ... The variable argument list is a list of tuples. + Each tuple describes a range of LBAs to erase + and consists of the following: + - An EFI_LBA that indicates the starting LBA + - A UINTN that indicates the number of blocks to + erase. + + The list is terminated with an + EFI_LBA_LIST_TERMINATOR. For example, the + following indicates that two ranges of blocks + (5-7 and 10-11) are to be erased: EraseBlocks + (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR); + + @retval EFI_SUCCESS The erase request successfully + completed. + + @retval EFI_ACCESS_DENIED The firmware volume is in the + WriteDisabled state. + @retval EFI_DEVICE_ERROR The block device is not functioning + correctly and could not be written. + The firmware device may have been + partially erased. + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed + in the variable argument list do + not exist in the firmware volume. + +**/ +EFI_STATUS +EFIAPI +FlashFvbDxeErase ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + ... + ) +{ + VA_LIST Args; + EFI_LBA Start; + UINTN Length; + EFI_STATUS Status; + + Status =3D EFI_SUCCESS; + + VA_START (Args, This); + + for (Start =3D VA_ARG (Args, EFI_LBA); + Start !=3D EFI_LBA_LIST_TERMINATOR; + Start =3D VA_ARG (Args, EFI_LBA)) + { + Length =3D VA_ARG (Args, UINTN); + Status =3D FlashEraseCommand ( + mNvFlashBase + Start * mFlashBlockSize, + Length * mFlashBlockSize + ); + } + + VA_END (Args); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to do flash erase\n")); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL mFlashFvbProtocol =3D { + FlashFvbDxeGetAttributes, + FlashFvbDxeSetAttributes, + FlashFvbDxeGetPhysicalAddress, + FlashFvbDxeGetBlockSize, + FlashFvbDxeRead, + FlashFvbDxeWrite, + FlashFvbDxeErase +}; + +EFI_STATUS +EFIAPI +FlashFvbDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE FvbHandle =3D NULL; + EFI_EVENT VirtualAddressChangeEvent; + + // Get NV store FV info + mFlashBlockSize =3D FixedPcdGet32 (PcdFvBlockSize); + mNvStorageBase =3D PcdGet64 (PcdFlashNvStorageVariableBase64); + mNvStorageSize =3D FixedPcdGet32 (PcdFlashNvStorageVariableSize) + + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize); + + DEBUG (( + DEBUG_INFO, + "%a: Using NV store FV in-memory copy at 0x%lx with size 0x%x\n", + __FUNCTION__, + mNvStorageBase, + mNvStorageSize + )); + + // Get NV Flash information + Status =3D FlashGetNvRamInfo (&mNvFlashBase, &mNvFlashSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to get Flash info\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + if (mNvFlashSize >=3D (mNvStorageSize * 2)) { + DEBUG ((DEBUG_INFO, "%a: NV store on Flash is valid\n", __FUNCTION__))= ; + } else { + DEBUG ((DEBUG_ERROR, "%a: NV store on Flash is invalid\n", __FUNCTION_= _)); + return EFI_DEVICE_ERROR; + } + + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + FlashFvbAddressChangeEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &VirtualAddressChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &FvbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + &mFlashFvbProtocol, + NULL + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to install Firmware Volume Block protocol= \n")); + return Status; + } + + return EFI_SUCCESS; +} diff --git a/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.c b/Si= licon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.c new file mode 100644 index 000000000000..3da7df3907dc --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.c @@ -0,0 +1,125 @@ +/** @file + + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +/** + Entry point function for the PEIM + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @return EFI_SUCCESS If we installed our PPI + +**/ +EFI_STATUS +EFIAPI +FlashPeiEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + CHAR8 BuildUuid[PcdGetSize (PcdPlatformConfigUuid)]; + CHAR8 StoredUuid[PcdGetSize (PcdPlatformConfigUuid)]; + EFI_STATUS Status; + UINTN FWNvRamStartOffset; + UINT32 FWNvRamSize; + UINTN NvRamAddress; + UINT32 NvRamSize; + + CopyMem ((VOID *)BuildUuid, PcdGetPtr (PcdPlatformConfigUuid), sizeof (B= uildUuid)); + + NvRamAddress =3D PcdGet64 (PcdFlashNvStorageVariableBase64); + NvRamSize =3D FixedPcdGet32 (PcdFlashNvStorageVariableSize) + + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize); + + DEBUG (( + DEBUG_INFO, + "%a: Using NV store FV in-memory copy at 0x%lx with size 0x%x\n", + __FUNCTION__, + NvRamAddress, + NvRamSize + )); + + Status =3D FlashGetNvRamInfo (&FWNvRamStartOffset, &FWNvRamSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to get Flash NVRAM info %r\n", __FUNC= TION__, Status)); + return Status; + } + + if (FWNvRamSize < (NvRamSize * 2 + sizeof (BuildUuid))) { + // + // NVRAM size provided by FW is not enough + // + return EFI_INVALID_PARAMETER; + } + + // + // We stored BUILD UUID build at the offset NVRAM_SIZE * 2 + // + Status =3D FlashReadCommand ( + FWNvRamStartOffset + NvRamSize * 2, + (UINT8 *)StoredUuid, + sizeof (StoredUuid) + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (CompareMem ((VOID *)StoredUuid, (VOID *)BuildUuid, sizeof (BuildUuid= )) !=3D 0) { + DEBUG ((DEBUG_INFO, "BUILD UUID Changed, Update Storage with NVRAM FV\= n")); + + Status =3D FlashEraseCommand (FWNvRamStartOffset, NvRamSize * 2 + size= of (BuildUuid)); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D FlashWriteCommand ( + FWNvRamStartOffset, + (UINT8 *)NvRamAddress, + NvRamSize + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Write new BUILD UUID to the Flash + // + Status =3D FlashWriteCommand ( + FWNvRamStartOffset + NvRamSize * 2, + (UINT8 *)BuildUuid, + sizeof (BuildUuid) + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + DEBUG ((DEBUG_INFO, "Identical UUID, copy stored NVRAM to RAM\n")); + + Status =3D FlashReadCommand ( + FWNvRamStartOffset, + (UINT8 *)NvRamAddress, + NvRamSize + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} --=20 2.17.1