From nobody Mon Sep 16 20:07:06 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+114071+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1705676272584911.2742205553792; Fri, 19 Jan 2024 06:57:52 -0800 (PST) Return-Path: DKIM-Signature: a=rsa-sha256; bh=o0Z5QgtyWUQ04MCPHhPZmqD9QQUin4Urai+Ad2Yn4pc=; c=relaxed/simple; d=groups.io; h=ARC-Seal:ARC-Message-Signature:ARC-Authentication-Results:Received-SPF:From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding:Content-Type; s=20140610; t=1705676272; v=1; b=vaECy4bPTBvqu6tCgz4uhNqnJJRvZhD4Goupn5J0uWUM/h5xCg7idHOXZgdrdoKSQ7mO7JlB jinuraHOVDr0F7qiSapYdKNNLOf44nMim4xSMpojnT4om/03v6PPqMbORlim1nxlrYbeXThV1M4 2VeIEw7hovP7Tjabv7e7LyU0= X-Received: by 127.0.0.2 with SMTP id b0RSYY1788612xxCkU7N8lQM; Fri, 19 Jan 2024 06:57:52 -0800 X-Received: from NAM11-DM6-obe.outbound.protection.outlook.com (NAM11-DM6-obe.outbound.protection.outlook.com [40.107.223.84]) by mx.groups.io with SMTP id smtpd.web10.5980.1705560758383726157 for ; Wed, 17 Jan 2024 22:52:38 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=d3ZrRmHSU89FBOZcoIHLnWApvwVCFsa2l5c6a/x4f/Ad7S7Fa1Gi2yRFlN8R2tEvUOhYmL5j5WJYqE+k9UQ4DciGwNKl4W5HBoBQ3iFbz8IZaQTDchzze+rCUzYbB8FCwDPyRBVoYJX/PF/S3yDRy8mpIxlrCjgH7vUuaHTgV0e8IBhDHk9cR62npb5X8/W3qPxi/kCgM6qVE4yal99ijtpGzh7Yx7ZMBf1wOLO+yTDH/18UDNn7zkk0hc9J9oHZDzlr/z+YRlEjj34IYmxYiBsXa5UnZPThg18yNcbI4GdWrzA4Ke2nyDxNGnGImt2x31f+eXOFokHmXsb+dCEaBw== 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=R+LWNHoUqpYJPwEf+oN8+SGTzSDBvrik6RHAocDW4bw=; b=DUfIqeH7rgiGdZ0/NyA5VZpLGHTaxQPWb8v6+KMTpvOw9xmHgPFwQRkB0y7tWsB0WNkhnk+Gggwnqob87Gqv+5nHKiHbtkO6s67THDdLbA8468GldXWkzRKrQfoBcJ8M1xzF8T13kBEf6ZeycvBgBa4Gai/ditAw5KUGg9jjuofk8wQ6i2148izTu+9vCngVc5OvPpTkbdee/kooYW7J7HR8t7vjq8J6ZKE6Ee+EmGCrrqo74epAQSIr2oCpX8jeiKcfcF5ts6eqcV+4Xtt2NkgzKcjpiORl8njvxCvD8DWqwiygM2lZXeRuZ3cZVeGVq0JWvuYxsilq09oBp7U63w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) X-Received: from MW4PR03CA0217.namprd03.prod.outlook.com (2603:10b6:303:b9::12) by CY8PR12MB7636.namprd12.prod.outlook.com (2603:10b6:930:9f::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7202.24; Thu, 18 Jan 2024 06:52:32 +0000 X-Received: from CO1PEPF000044F3.namprd05.prod.outlook.com (2603:10b6:303:b9:cafe::71) by MW4PR03CA0217.outlook.office365.com (2603:10b6:303:b9::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7202.24 via Frontend Transport; Thu, 18 Jan 2024 06:52:32 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+114071+1787277+3901457@groups.io; helo=mail02.groups.io; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB03.amd.com; pr=C X-Received: from SATLEXMB03.amd.com (165.204.84.17) by CO1PEPF000044F3.mail.protection.outlook.com (10.167.241.73) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.7202.16 via Frontend Transport; Thu, 18 Jan 2024 06:52:32 +0000 X-Received: from SATLEXMB08.amd.com (10.181.40.132) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.34; Thu, 18 Jan 2024 00:52:30 -0600 X-Received: from SATLEXMB03.amd.com (10.181.40.144) by SATLEXMB08.amd.com (10.181.40.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.32; Wed, 17 Jan 2024 22:52:29 -0800 X-Received: from SHA-LX-MINGXZHA.amd.com (10.180.168.240) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server id 15.1.2507.34 via Frontend Transport; Thu, 18 Jan 2024 00:52:28 -0600 From: "duke.zhai via groups.io" To: CC: Eric Xing , Duke Zhai , Igniculus Fu , Abner Chang Subject: [edk2-devel] [PATCH 21/33] AMD/VanGoghBoard: Check in SignedCapsule. Date: Thu, 18 Jan 2024 14:50:34 +0800 Message-ID: <20240118065046.961-22-duke.zhai@amd.com> In-Reply-To: <20240118065046.961-1-duke.zhai@amd.com> References: <20240118065046.961-1-duke.zhai@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PEPF000044F3:EE_|CY8PR12MB7636:EE_ X-MS-Office365-Filtering-Correlation-Id: c1b0ea2e-4cc7-41db-650c-08dc17f20ba9 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Message-Info: eChd5L46OpJq+cJ0wG8tAvenY58owQ98J8OapgryhkL/w4suDTHOEaPaLy4bHiO+jZNtNCGcEKABQrZBCJk4Pe4hlNCOi5tGjggHJr9UirmSWZb9VjJ/mEyH0Fgfa/ephW18kDN/W4pI+6hcIpCKUINtEfpJ3igvIkJP73OD0BjGBhY4grPMpaJysJQ+/aDJUa5GHWHuA4nbku0wB8GP91u94rY2k2WIDlAbrFzc5X1M8ssikRQoW3Rd/tmT2CZL2JDbT60hq/nJKPncCl9wxpZBWP1Jqawu+JsNf7iju0tbk9QaLoajpSbZyJWLiAmBNdgXFLntub3y6ntYyDbYb3YEeQlRu7nLXRxJr9Twe0hY4wRwwP42Ih7zpqiZrGD9HZoVVEoAWOFD0kZmXPLINweHahYkT2AOS326MOCicPPtzLLB66PNPqS31/r6382tuGSr0ATBxNTazeN+SQ2MCWKsCOTMIxeYUPUlIHp5oQxIg1I9uOtk8IcoO0WNq7RvKYp5NJksoWm+1eZp9yPNgLCn9x/mUpjIfiKgk/aPQ3/jBAZY1FmvBPFezvXh7YHUj3YWytQY3gRjmMLx5SlimV/8Gs4W8/D3+WUFD0AdH5uTJ9uaTuAGNPg++YyznM4m+6n+fWCZbRaKt23LNdO2KVWhovwv71lNcmEBx1b8fP4C2gFpqoibvVOCEaQIobNFuKiQXDj+lmrCNC0hqzgbxIVCK1f6V+Bzs/AttqZp+F+08g5NRvJpjRizdm0clZMpmmd5/rF0b6pWvxywyJyY2QjTXpff67MGETKgYfFgVndVuMZ1C0UjJMpKdqAPCECtueKqFcTC58WGmGgZ+9sb9A== X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Jan 2024 06:52:32.3380 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: c1b0ea2e-4cc7-41db-650c-08dc17f20ba9 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB03.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CO1PEPF000044F3.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY8PR12MB7636 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,duke.zhai@amd.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: XNgBufOLHG1nph019uBy7DRlx1787277AA= Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1705676273052100006 Content-Type: text/plain; charset="utf-8" From: Duke Zhai BZ #:4640 Initial SignedCapsule module for Signed Capsule. Produce FMP instance to update system firmware. Signed-off-by: Ken Yao Cc: Eric Xing Cc: Duke Zhai Cc: Igniculus Fu Cc: Abner Chang --- .../BaseTools/Source/Python/GenFds/Capsule.py | 261 +++ .../SystemFirmwareUpdate/ParseConfigProfile.c | 231 +++ .../SystemFirmwareCommonDxe.c | 386 +++++ .../SystemFirmwareUpdate/SystemFirmwareDxe.h | 435 +++++ .../SystemFirmwareUpdateDxe.c | 1448 +++++++++++++++++ .../SystemFirmwareUpdateDxe.inf | 91 ++ .../SystemFirmwareUpdateDxe.uni | 31 + .../SystemFirmwareUpdateDxeExtra.uni | 30 + .../Include/OtaCapsuleUpdate.h | 38 + 9 files changed, 2951 insertions(+) create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Sourc= e/Python/GenFds/Capsule.py create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePk= g/Universal/SystemFirmwareUpdate/ParseConfigProfile.c create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePk= g/Universal/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePk= g/Universal/SystemFirmwareUpdate/SystemFirmwareDxe.h create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePk= g/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePk= g/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePk= g/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni create mode 100644 Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePk= g/Universal/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni create mode 100644 Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/OtaC= apsuleUpdate.h diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Pytho= n/GenFds/Capsule.py b/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Sou= rce/Python/GenFds/Capsule.py new file mode 100644 index 0000000000..248eb25889 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Override/edk2/BaseTools/Source/Python/GenFd= s/Capsule.py @@ -0,0 +1,261 @@ +#/************************************************************************= ***** +#* +#* Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+#* SPDX-License-Identifier: BSD-2-Clause-Patent +#*************************************************************************= ***** +# + +# This file includes code originally published under the following license. + +## @file +# generate capsule +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +## +# Import Modules +# +from __future__ import absolute_import +from .GenFdsGlobalVariable import GenFdsGlobalVariable, FindExtendTool +from CommonDataClass.FdfClass import CapsuleClassObject +import Common.LongFilePathOs as os +from io import BytesIO +from Common.Misc import SaveFileOnChange, PackGUID +import uuid +from struct import pack +from Common import EdkLogger +from Common.BuildToolError import GENFDS_ERROR +from Common.DataType import TAB_LINE_BREAK + +WIN_CERT_REVISION =3D 0x0200 +WIN_CERT_TYPE_EFI_GUID =3D 0x0EF1 +EFI_CERT_TYPE_PKCS7_GUID =3D uuid.UUID('{4aafd29d-68df-49ee-8aa9-347d37566= 5a7}') +EFI_CERT_TYPE_RSA2048_SHA256_GUID =3D uuid.UUID('{a7717414-c616-4977-9420-= 844712a735bf}') + +## create inf file describes what goes into capsule and call GenFv to gene= rate capsule +# +# +class Capsule (CapsuleClassObject): + ## The constructor + # + # @param self The object pointer + # + def __init__(self): + CapsuleClassObject.__init__(self) + # For GenFv + self.BlockSize =3D None + # For GenFv + self.BlockNum =3D None + self.CapsuleName =3D None + + ## Generate FMP capsule + # + # @retval string Generated Capsule file path + # + def GenFmpCapsule(self): + # + # Generate capsule header + # typedef struct { + # EFI_GUID CapsuleGuid; + # UINT32 HeaderSize; + # UINT32 Flags; + # UINT32 CapsuleImageSize; + # } EFI_CAPSULE_HEADER; + # + Header =3D BytesIO() + # + # Use FMP capsule GUID: 6DCBD5ED-E82D-4C44-BDA1-7194199AD92A + # + Header.write(PackGUID('6DCBD5ED-E82D-4C44-BDA1-7194199AD92A'.split= ('-'))) + HdrSize =3D 0 + if 'CAPSULE_HEADER_SIZE' in self.TokensDict: + Header.write(pack('=3DI', int(self.TokensDict['CAPSULE_HEADER_= SIZE'], 16))) + HdrSize =3D int(self.TokensDict['CAPSULE_HEADER_SIZE'], 16) + else: + Header.write(pack('=3DI', 0x20)) + HdrSize =3D 0x20 + Flags =3D 0 + if 'CAPSULE_FLAGS' in self.TokensDict: + for flag in self.TokensDict['CAPSULE_FLAGS'].split(','): + flag =3D flag.strip() + if flag =3D=3D 'PopulateSystemTable': + Flags |=3D 0x00010000 | 0x00020000 + elif flag =3D=3D 'PersistAcrossReset': + Flags |=3D 0x00010000 + elif flag =3D=3D 'InitiateReset': + Flags |=3D 0x00040000 + if 'OEM_CAPSULE_FLAGS' in self.TokensDict: + Flags |=3D int(self.TokensDict['OEM_CAPSULE_FLAGS'],16) + Header.write(pack('=3DI', Flags)) + # + # typedef struct { + # UINT32 Version; + # UINT16 EmbeddedDriverCount; + # UINT16 PayloadItemCount; + # // UINT64 ItemOffsetList[]; + # } EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER; + # + FwMgrHdr =3D BytesIO() + if 'CAPSULE_HEADER_INIT_VERSION' in self.TokensDict: + FwMgrHdr.write(pack('=3DI', int(self.TokensDict['CAPSULE_HEADE= R_INIT_VERSION'], 16))) + else: + FwMgrHdr.write(pack('=3DI', 0x00000001)) + FwMgrHdr.write(pack('=3DHH', len(self.CapsuleDataList), len(self.F= mpPayloadList))) + FwMgrHdrSize =3D 4+2+2+8*(len(self.CapsuleDataList)+len(self.FmpPa= yloadList)) + + # + # typedef struct _WIN_CERTIFICATE { + # UINT32 dwLength; + # UINT16 wRevision; + # UINT16 wCertificateType; + # //UINT8 bCertificate[ANYSIZE_ARRAY]; + # } WIN_CERTIFICATE; + # + # typedef struct _WIN_CERTIFICATE_UEFI_GUID { + # WIN_CERTIFICATE Hdr; + # EFI_GUID CertType; + # //UINT8 CertData[ANYSIZE_ARRAY]; + # } WIN_CERTIFICATE_UEFI_GUID; + # + # typedef struct { + # UINT64 MonotonicCount; + # WIN_CERTIFICATE_UEFI_GUID AuthInfo; + # } EFI_FIRMWARE_IMAGE_AUTHENTICATION; + # + # typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 { + # EFI_GUID HashType; + # UINT8 PublicKey[256]; + # UINT8 Signature[256]; + # } EFI_CERT_BLOCK_RSA_2048_SHA256; + # + + PreSize =3D FwMgrHdrSize + Content =3D BytesIO() + for driver in self.CapsuleDataList: + FileName =3D driver.GenCapsuleSubItem() + FwMgrHdr.write(pack('=3DQ', PreSize)) + PreSize +=3D os.path.getsize(FileName) + File =3D open(FileName, 'rb') + Content.write(File.read()) + File.close() + for fmp in self.FmpPayloadList: + if fmp.Existed: + FwMgrHdr.write(pack('=3DQ', PreSize)) + PreSize +=3D len(fmp.Buffer) + Content.write(fmp.Buffer) + continue + if fmp.ImageFile: + for Obj in fmp.ImageFile: + fmp.ImageFile =3D Obj.GenCapsuleSubItem() + if fmp.VendorCodeFile: + for Obj in fmp.VendorCodeFile: + fmp.VendorCodeFile =3D Obj.GenCapsuleSubItem() + if fmp.Certificate_Guid: + ExternalTool, ExternalOption =3D FindExtendTool([], GenFds= GlobalVariable.ArchList, fmp.Certificate_Guid) + CmdOption =3D '' + CapInputFile =3D fmp.ImageFile + if not os.path.isabs(fmp.ImageFile): + CapInputFile =3D os.path.join(GenFdsGlobalVariable.Wor= kSpaceDir, fmp.ImageFile) + CapOutputTmp =3D os.path.join(GenFdsGlobalVariable.FvDir, = self.UiCapsuleName) + '.tmp' + if ExternalTool is None: + EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found= with GUID %s" % fmp.Certificate_Guid) + else: + CmdOption +=3D ExternalTool + if ExternalOption: + CmdOption =3D CmdOption + ' ' + ExternalOption + CmdOption +=3D ' -e ' + ' --monotonic-count ' + str(fmp.Mo= notonicCount) + ' -o ' + CapOutputTmp + ' ' + CapInputFile + CmdList =3D CmdOption.split() + GenFdsGlobalVariable.CallExternalTool(CmdList, "Failed to = generate FMP auth capsule") + if uuid.UUID(fmp.Certificate_Guid) =3D=3D EFI_CERT_TYPE_PK= CS7_GUID: + dwLength =3D 4 + 2 + 2 + 16 + os.path.getsize(CapOutpu= tTmp) - os.path.getsize(CapInputFile) + else: + dwLength =3D 4 + 2 + 2 + 16 + 16 + 256 + 256 + fmp.ImageFile =3D CapOutputTmp + AuthData =3D [fmp.MonotonicCount, dwLength, WIN_CERT_REVIS= ION, WIN_CERT_TYPE_EFI_GUID, fmp.Certificate_Guid] + fmp.Buffer =3D fmp.GenCapsuleSubItem(AuthData) + else: + fmp.Buffer =3D fmp.GenCapsuleSubItem() + FwMgrHdr.write(pack('=3DQ', PreSize)) + PreSize +=3D len(fmp.Buffer) + Content.write(fmp.Buffer) + BodySize =3D len(FwMgrHdr.getvalue()) + len(Content.getvalue()) + Header.write(pack('=3DI', HdrSize + BodySize)) + # + # The real capsule header structure is 28 bytes + # + Header.write(b'\x00'*(HdrSize-28)) + Header.write(FwMgrHdr.getvalue()) + Header.write(Content.getvalue()) + # + # Generate FMP capsule file + # + CapOutputFile =3D os.path.join(GenFdsGlobalVariable.FvDir, self.Ui= CapsuleName) + '.Cap' + SaveFileOnChange(CapOutputFile, Header.getvalue(), True) + return CapOutputFile + + ## Generate capsule + # + # @param self The object pointer + # @retval string Generated Capsule file path + # + def GenCapsule(self): + if self.UiCapsuleName.upper() + 'cap' in GenFdsGlobalVariable.Imag= eBinDict: + return GenFdsGlobalVariable.ImageBinDict[self.UiCapsuleName.up= per() + 'cap'] + + GenFdsGlobalVariable.InfLogger( "\nGenerate %s Capsule" %self.UiCa= psuleName) + if ('CAPSULE_GUID' in self.TokensDict and + uuid.UUID(self.TokensDict['CAPSULE_GUID']) =3D=3D uuid.UUID('6= DCBD5ED-E82D-4C44-BDA1-7194199AD92A')): + return self.GenFmpCapsule() + + CapInfFile =3D self.GenCapInf() + CapInfFile.append("[files]" + TAB_LINE_BREAK) + CapFileList =3D [] + for CapsuleDataObj in self.CapsuleDataList: + CapsuleDataObj.CapsuleName =3D self.CapsuleName + FileName =3D CapsuleDataObj.GenCapsuleSubItem() + CapsuleDataObj.CapsuleName =3D None + CapFileList.append(FileName) + CapInfFile.append("EFI_FILE_NAME =3D " + \ + FileName + \ + TAB_LINE_BREAK) + SaveFileOnChange(self.CapInfFileName, ''.join(CapInfFile), False) + # + # Call GenFv tool to generate capsule + # + CapOutputFile =3D os.path.join(GenFdsGlobalVariable.FvDir, self.Ui= CapsuleName) + CapOutputFile =3D CapOutputFile + '.Cap' + GenFdsGlobalVariable.GenerateFirmwareVolume( + CapOutputFile, + [self.CapInfFileName], + Capsule=3DTrue, + FfsList=3DCapFileList + ) + + GenFdsGlobalVariable.VerboseLogger( "\nGenerate %s Capsule Success= fully" %self.UiCapsuleName) + GenFdsGlobalVariable.SharpCounter =3D 0 + GenFdsGlobalVariable.ImageBinDict[self.UiCapsuleName.upper() + 'ca= p'] =3D CapOutputFile + return CapOutputFile + + ## Generate inf file for capsule + # + # @param self The object pointer + # @retval file inf file object + # + def GenCapInf(self): + self.CapInfFileName =3D os.path.join(GenFdsGlobalVariable.FvDir, + self.UiCapsuleName + "_Cap" + '.inf') + CapInfFile =3D [] + + CapInfFile.append("[options]" + TAB_LINE_BREAK) + + for Item in self.TokensDict: + CapInfFile.append("EFI_" + \ + Item + \ + ' =3D ' + \ + self.TokensDict[Item] + \ + TAB_LINE_BREAK) + + return CapInfFile diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Unive= rsal/SystemFirmwareUpdate/ParseConfigProfile.c b/Platform/AMD/VanGoghBoard/= Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/ParseConfigPr= ofile.c new file mode 100644 index 0000000000..b57586a267 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/Sy= stemFirmwareUpdate/ParseConfigProfile.c @@ -0,0 +1,231 @@ +/** @file + Implements ParseConfigProfile.c + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** @file + Parse the INI configuration file and pass the information to the update = driver + so that the driver can perform update accordingly. + + Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions + of the BSD License which accompanies this distribution. The + full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include "SystemFirmwareDxe.h" +#include +#include + +#define MAX_LINE_LENGTH 512 + +/** + Parse Config data file to get the updated data array. + + @param[in] DataBuffer Config raw file buffer. + @param[in] BufferSize Size of raw buffer. + @param[in, out] ConfigHeader Pointer to the config header. + @param[in, out] UpdateArray Pointer to the config of update data. + + @retval EFI_NOT_FOUND No config data is found. + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS Parse the config file successfully. + +**/ +EFI_STATUS +ParseUpdateDataFile ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize, + IN OUT CONFIG_HEADER *ConfigHeader, + IN OUT UPDATE_CONFIG_DATA **UpdateArray + ) +{ + EFI_STATUS Status; + CHAR8 *SectionName; + CHAR8 Entry[MAX_LINE_LENGTH]; + UINTN Num; + UINT64 Num64; + UINTN Index; + EFI_GUID FileGuid; + VOID *Context; + + // + // First process the data buffer and get all sections and entries + // + Context =3D OpenIniFile (DataBuffer, BufferSize); + if (Context =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Now get NumOfUpdate + // + Status =3D GetDecimalUintnFromDataFile ( + Context, + "Head", + "NumOfUpdate", + &Num + ); + if (EFI_ERROR (Status) || (Num =3D=3D 0)) { + DEBUG ((DEBUG_ERROR, "NumOfUpdate not found\n")); + CloseIniFile (Context); + return EFI_NOT_FOUND; + } + + ConfigHeader->NumOfUpdates =3D Num; + *UpdateArray =3D AllocateZeroPool ((sizeof (UPDATE_CONFIG_= DATA) * Num)); + if (*UpdateArray =3D=3D NULL) { + CloseIniFile (Context); + return EFI_OUT_OF_RESOURCES; + } + + for (Index =3D 0; Index < ConfigHeader->NumOfUpdates; Index++) { + // + // Get the section name of each update + // + AsciiStrCpyS (Entry, MAX_LINE_LENGTH, "Update"); + AsciiValueToStringS ( + Entry + AsciiStrnLenS (Entry, MAX_LINE_LENGTH), + MAX_LINE_LENGTH - AsciiStrnLenS (Entry, MAX_LINE_LENGTH), + 0, + Index, + 0 + ); + Status =3D GetStringFromDataFile ( + Context, + "Head", + Entry, + &SectionName + ); + if (EFI_ERROR (Status) || (SectionName =3D=3D NULL)) { + DEBUG ((DEBUG_ERROR, "[%d] %a not found\n", Index, Entry)); + CloseIniFile (Context); + return EFI_NOT_FOUND; + } + + // + // The section name of this update has been found. + // Now looks for all the config data of this update + // + (*UpdateArray)[Index].Index =3D Index; + + // + // FirmwareType + // + Status =3D GetDecimalUintnFromDataFile ( + Context, + SectionName, + "FirmwareType", + &Num + ); + if (EFI_ERROR (Status)) { + CloseIniFile (Context); + DEBUG ((DEBUG_ERROR, "[%d] FirmwareType not found\n", Index)); + return EFI_NOT_FOUND; + } + + (*UpdateArray)[Index].FirmwareType =3D (PLATFORM_FIRMWARE_TYPE)Num; + + // + // AddressType + // + Status =3D GetDecimalUintnFromDataFile ( + Context, + SectionName, + "AddressType", + &Num + ); + if (EFI_ERROR (Status)) { + CloseIniFile (Context); + DEBUG ((DEBUG_ERROR, "[%d] AddressType not found\n", Index)); + return EFI_NOT_FOUND; + } + + (*UpdateArray)[Index].AddressType =3D (FLASH_ADDRESS_TYPE)Num; + + // + // BaseAddress + // + Status =3D GetHexUint64FromDataFile ( + Context, + SectionName, + "BaseAddress", + &Num64 + ); + if (EFI_ERROR (Status)) { + CloseIniFile (Context); + DEBUG ((DEBUG_ERROR, "[%d] BaseAddress not found\n", Index)); + return EFI_NOT_FOUND; + } + + (*UpdateArray)[Index].BaseAddress =3D (EFI_PHYSICAL_ADDRESS)Num64; + + // + // FileBuid + // + Status =3D GetGuidFromDataFile ( + Context, + SectionName, + "FileGuid", + &FileGuid + ); + if (EFI_ERROR (Status)) { + CloseIniFile (Context); + DEBUG ((DEBUG_ERROR, "[%d] FileGuid not found\n", Index)); + return EFI_NOT_FOUND; + } + + CopyGuid (&((*UpdateArray)[Index].FileGuid), &FileGuid); + + // + // Length + // + Status =3D GetHexUintnFromDataFile ( + Context, + SectionName, + "Length", + &Num + ); + if (EFI_ERROR (Status)) { + CloseIniFile (Context); + DEBUG ((DEBUG_ERROR, "[%d] Length not found\n", Index)); + return EFI_NOT_FOUND; + } + + (*UpdateArray)[Index].Length =3D (UINTN)Num; + + // + // ImageOffset + // + Status =3D GetHexUintnFromDataFile ( + Context, + SectionName, + "ImageOffset", + &Num + ); + if (EFI_ERROR (Status)) { + CloseIniFile (Context); + DEBUG ((DEBUG_ERROR, "[%d] ImageOffset not found\n", Index)); + return EFI_NOT_FOUND; + } + + (*UpdateArray)[Index].ImageOffset =3D (UINTN)Num; + } + + // + // Now all configuration data got. Free those temporary buffers + // + CloseIniFile (Context); + + return EFI_SUCCESS; +} diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Unive= rsal/SystemFirmwareUpdate/SystemFirmwareCommonDxe.c b/Platform/AMD/VanGoghB= oard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFi= rmwareCommonDxe.c new file mode 100644 index 0000000000..d3640cb3d9 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/Sy= stemFirmwareUpdate/SystemFirmwareCommonDxe.c @@ -0,0 +1,386 @@ +/** @file + Implements SystemFirmwareCommonDxe.C + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* This file includes code originally published under the following licens= e. */ + +/** @file + Produce FMP instance for system firmware. + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include "SystemFirmwareDxe.h" + +EFI_GUID gSystemFmpLastAttemptVariableGuid =3D SYSTEM_FMP_LAST_ATTEMPT_VA= RIABLE_GUID; +EFI_GUID gSystemFmpProtocolGuid =3D SYSTEM_FMP_PROTOCOL_GUID; + +EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol =3D { + FmpGetImageInfo, + FmpGetImage, + FmpSetImage, + FmpCheckImage, + FmpGetPackageInfo, + FmpSetPackageInfo +}; + +/** + Returns information about the current firmware image(s) of the device. + + This function allows a copy of the current firmware image to be created = and saved. + The saved copy could later been used, for example, in firmware image rec= overy or rollback. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEM= ENT_PROTOCOL instance. + @param[in, out] ImageInfoSize A pointer to the size, in bytes, of t= he ImageInfo buffer. + On input, this is the size of the buf= fer allocated by the caller. + On output, it is the size of the buff= er returned by the firmware + if the buffer was large enough, or th= e size of the buffer needed + to contain the image(s) information i= f the buffer was too small. + @param[in, out] ImageInfo A pointer to the buffer in which firm= ware places the current image(s) + information. The information is an ar= ray of EFI_FIRMWARE_IMAGE_DESCRIPTORs. + @param[out] DescriptorVersion A pointer to the location in which fi= rmware returns the version number + associated with the EFI_FIRMWARE_IMAG= E_DESCRIPTOR. + @param[out] DescriptorCount A pointer to the location in which fi= rmware returns the number of + descriptors or firmware images within= this device. + @param[out] DescriptorSize A pointer to the location in which fi= rmware returns the size, in bytes, + of an individual EFI_FIRMWARE_IMAGE_D= ESCRIPTOR. + @param[out] PackageVersion A version number that represents all = the firmware images in the device. + The format is vendor specific and new= version must have a greater value + than the old version. If PackageVersi= on is not supported, the value is + 0xFFFFFFFF. A value of 0xFFFFFFFE ind= icates that package version comparison + is to be performed using PackageVersi= onName. A value of 0xFFFFFFFD indicates + that package version update is in pro= gress. + @param[out] PackageVersionName A pointer to a pointer to a null-term= inated string representing the + package version name. The buffer is a= llocated by this function with + AllocatePool(), and it is the caller'= s responsibility to free it with a call + to FreePool(). + + @retval EFI_SUCCESS The device was successfully updated w= ith the new image. + @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. T= he current buffer size + needed to hold the image(s) informati= on is returned in ImageInfoSize. + @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL. + @retval EFI_DEVICE_ERROR Valid information could not be return= ed. Possible corrupted image. + +**/ +EFI_STATUS +EFIAPI +FmpGetImageInfo ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN OUT UINTN *ImageInfoSize, + IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo, + OUT UINT32 *DescriptorVersion, + OUT UINT8 *DescriptorCount, + OUT UINTN *DescriptorSize, + OUT UINT32 *PackageVersion, + OUT CHAR16 **PackageVersionName + ) +{ + SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate; + EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor; + + SystemFmpPrivate =3D SYSTEM_FMP_PRIVATE_DATA_FROM_FMP (This); + + if (ImageInfoSize =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if (*ImageInfoSize < sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR) * SystemFmpP= rivate->DescriptorCount) { + *ImageInfoSize =3D sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR) * SystemFmpP= rivate->DescriptorCount; + return EFI_BUFFER_TOO_SMALL; + } + + if ((ImageInfo =3D=3D NULL) || + (DescriptorVersion =3D=3D NULL) || + (DescriptorCount =3D=3D NULL) || + (DescriptorSize =3D=3D NULL) || + (PackageVersion =3D=3D NULL) || + (PackageVersionName =3D=3D NULL)) + { + return EFI_INVALID_PARAMETER; + } + + *ImageInfoSize =3D sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR) * SystemFm= pPrivate->DescriptorCount; + *DescriptorSize =3D sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR); + *DescriptorCount =3D SystemFmpPrivate->DescriptorCount; + *DescriptorVersion =3D EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; + + // + // supports 1 ImageInfo descriptor + // + ImageDescriptor =3D SystemFmpPrivate->ImageDescriptor; + ImageInfo->ImageIndex =3D ImageDescriptor->ImageIndex; + CopyGuid (&ImageInfo->ImageTypeId, &ImageDescriptor->ImageTypeId); + ImageInfo->ImageId =3D ImageDescriptor->ImageId; + if (ImageDescriptor->ImageIdNameStringOffset !=3D 0) { + ImageInfo->ImageIdName =3D (CHAR16 *)((UINTN)ImageDescriptor + ImageDe= scriptor->ImageIdNameStringOffset); + } else { + ImageInfo->ImageIdName =3D NULL; + } + + ImageInfo->Version =3D ImageDescriptor->Version; + if (ImageDescriptor->VersionNameStringOffset !=3D 0) { + ImageInfo->VersionName =3D (CHAR16 *)((UINTN)ImageDescriptor + ImageDe= scriptor->VersionNameStringOffset); + } else { + ImageInfo->VersionName =3D NULL; + } + + ImageInfo->Size =3D (UINTN)ImageDescriptor->Size; + ImageInfo->AttributesSupported =3D ImageDescriptor->AttributesSu= pported; + ImageInfo->AttributesSetting =3D ImageDescriptor->AttributesSe= tting; + ImageInfo->Compatibilities =3D ImageDescriptor->Compatibilit= ies; + ImageInfo->LowestSupportedImageVersion =3D ImageDescriptor->LowestSuppor= tedImageVersion; + ImageInfo->LastAttemptVersion =3D SystemFmpPrivate->LastAttempt= .LastAttemptVersion; + ImageInfo->LastAttemptStatus =3D SystemFmpPrivate->LastAttempt= .LastAttemptStatus; + ImageInfo->HardwareInstance =3D ImageDescriptor->HardwareInst= ance; + + // + // package version + // + *PackageVersion =3D ImageDescriptor->PackageVersion; + if (ImageDescriptor->PackageVersionNameStringOffset !=3D 0) { + *PackageVersionName =3D (VOID *)((UINTN)ImageDescriptor + ImageDescrip= tor->PackageVersionNameStringOffset); + *PackageVersionName =3D AllocateCopyPool (StrSize (*PackageVersionName= ), *PackageVersionName); + } else { + *PackageVersionName =3D NULL; + } + + return EFI_SUCCESS; +} + +/** + Retrieves a copy of the current firmware image of the device. + + This function allows a copy of the current firmware image to be created = and saved. + The saved copy could later been used, for example, in firmware image rec= overy or rollback. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_= PROTOCOL instance. + @param[in] ImageIndex A unique number identifying the firmware = image(s) within the device. + The number is between 1 and DescriptorCou= nt. + @param[in,out] Image Points to the buffer where the current im= age is copied to. + @param[in,out] ImageSize On entry, points to the size of the buffe= r pointed to by Image, in bytes. + On return, points to the length of the im= age, in bytes. + + @retval EFI_SUCCESS The device was successfully updated with = the new image. + @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too = small to hold the + image. The current buffer size needed to = hold the image is returned + in ImageSize. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_NOT_FOUND The current image is not copied to the bu= ffer. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATION The operation could not be performed due = to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpGetImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN OUT VOID *Image, + IN OUT UINTN *ImageSize + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Checks if the firmware image is valid for the device. + + This function allows firmware update application to validate the firmwar= e image without + invoking the SetImage() first. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_= PROTOCOL instance. + @param[in] ImageIndex A unique number identifying the firmware = image(s) within the device. + The number is between 1 and DescriptorCou= nt. + @param[in] Image Points to the new image. + @param[in] ImageSize Size of the new image in bytes. + @param[out] ImageUpdatable Indicates if the new image is valid for u= pdate. It also provides, + if available, additional information if t= he image is invalid. + + @retval EFI_SUCCESS The image was successfully checked. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATION The operation could not be performed due = to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpCheckImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN CONST VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *ImageUpdatable + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Returns information about the firmware package. + + This function returns package information. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAG= EMENT_PROTOCOL instance. + @param[out] PackageVersion A version number that represents al= l the firmware images in the device. + The format is vendor specific and n= ew version must have a greater value + than the old version. If PackageVer= sion is not supported, the value is + 0xFFFFFFFF. A value of 0xFFFFFFFE i= ndicates that package version + comparison is to be performed using= PackageVersionName. A value of + 0xFFFFFFFD indicates that package v= ersion update is in progress. + @param[out] PackageVersionName A pointer to a pointer to a null-te= rminated string representing + the package version name. The buffe= r is allocated by this function with + AllocatePool(), and it is the calle= r's responsibility to free it with a + call to FreePool(). + @param[out] PackageVersionNameMaxLen The maximum length of package versi= on name if device supports update of + package version name. A value of 0 = indicates the device does not support + update of package version name. Len= gth is the number of Unicode characters, + including the terminating null char= acter. + @param[out] AttributesSupported Package attributes that are support= ed by this device. See 'Package Attribute + Definitions' for possible returned = values of this parameter. A value of 1 + indicates the attribute is supporte= d and the current setting value is + indicated in AttributesSetting. A v= alue of 0 indicates the attribute is not + supported and the current setting v= alue in AttributesSetting is meaningless. + @param[out] AttributesSetting Package attributes. See 'Package At= tribute Definitions' for possible returned + values of this parameter + + @retval EFI_SUCCESS The package information was success= fully returned. + @retval EFI_UNSUPPORTED The operation is not supported. + +**/ +EFI_STATUS +EFIAPI +FmpGetPackageInfo ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + OUT UINT32 *PackageVersion, + OUT CHAR16 **PackageVersionName, + OUT UINT32 *PackageVersionNameMaxLen, + OUT UINT64 *AttributesSupported, + OUT UINT64 *AttributesSetting + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Updates information about the firmware package. + + This function updates package information. + This function returns EFI_UNSUPPORTED if the package information is not = updatable. + VendorCode enables vendor to implement vendor-specific package informati= on update policy. + Null if the caller did not specify this policy or use the default policy. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_= PROTOCOL instance. + @param[in] Image Points to the authentication image. + Null if authentication is not required. + @param[in] ImageSize Size of the authentication image in bytes. + 0 if authentication is not required. + @param[in] VendorCode This enables vendor to implement vendor-s= pecific firmware + image update policy. + Null indicates the caller did not specify= this policy or use + the default policy. + @param[in] PackageVersion The new package version. + @param[in] PackageVersionName A pointer to the new null-terminated Unic= ode string representing + the package version name. + The string length is equal to or less tha= n the value returned in + PackageVersionNameMaxLen. + + @retval EFI_SUCCESS The device was successfully updated with = the new package + information. + @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer t= han the value + returned in PackageVersionNameMaxLen. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATION The operation could not be performed due = to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpSetPackageInfo ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode, + IN UINT32 PackageVersion, + IN CONST CHAR16 *PackageVersionName + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Initialize SystemFmpDriver private data structure. + + @param[in] SystemFmpPrivate private data structure to be initialized. + + @return EFI_SUCCESS private data is initialized. +**/ +EFI_STATUS +InitializePrivateData ( + IN SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate + ) +{ + EFI_STATUS VarStatus; + UINTN VarSize; + + SystemFmpPrivate->Signature =3D SYSTEM_FMP_PRIVATE_DATA_SIGNATURE; + SystemFmpPrivate->Handle =3D NULL; + SystemFmpPrivate->DescriptorCount =3D 1; + CopyMem (&SystemFmpPrivate->Fmp, &mFirmwareManagementProtocol, sizeof (E= FI_FIRMWARE_MANAGEMENT_PROTOCOL)); + + SystemFmpPrivate->ImageDescriptor =3D PcdGetPtr (PcdEdkiiSystemFirmwareI= mageDescriptor); + + SystemFmpPrivate->LastAttempt.LastAttemptVersion =3D 0x0; + SystemFmpPrivate->LastAttempt.LastAttemptStatus =3D 0x0; + VarSize =3D sizeof (SystemFmpPr= ivate->LastAttempt); + VarStatus =3D gRT->GetVariable ( + SYSTEM_FMP_LAS= T_ATTEMPT_VARIABLE_NAME, + &gSystemFmpLas= tAttemptVariableGuid, + NULL, + &VarSize, + &SystemFmpPriv= ate->LastAttempt + ); + DEBUG ((DEBUG_INFO, "GetLastAttemp - %r\n", VarStatus)); + DEBUG ((DEBUG_INFO, "GetLastAttemp Version - 0x%x, State - 0x%x\n", Syst= emFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate->LastAttempt= .LastAttemptStatus)); + + return EFI_SUCCESS; +} + +/** + Return if this FMP is a system FMP or a device FMP, based upon FmpImageI= nfo. + + @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR + + @retval TRUE It is a system FMP. + @retval FALSE It is a device FMP. +**/ +BOOLEAN +IsSystemFmp ( + IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo + ) +{ + GUID *Guid; + UINTN Count; + UINTN Index; + + Guid =3D PcdGetPtr (PcdSystemFmpCapsuleImageTypeIdGuid); + Count =3D PcdGetSize (PcdSystemFmpCapsuleImageTypeIdGuid) / sizeof (GUID= ); + + for (Index =3D 0; Index < Count; Index++, Guid++) { + if (CompareGuid (&FmpImageInfo->ImageTypeId, Guid)) { + return TRUE; + } + } + + return FALSE; +} diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Unive= rsal/SystemFirmwareUpdate/SystemFirmwareDxe.h b/Platform/AMD/VanGoghBoard/O= verride/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFirmware= Dxe.h new file mode 100644 index 0000000000..8164f66958 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/Sy= stemFirmwareUpdate/SystemFirmwareDxe.h @@ -0,0 +1,435 @@ +/** @file + Implementation of SystemFirmwareDxe.h + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* This file includes code originally published under the following licens= e. */ + +/** @file + System Firmware update header file. + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#ifndef _SYSTEM_FIRMWARE_UPDATE_H_ +#define _SYSTEM_FIRMWARE_UPDATE_H_ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + UINT32 LastAttemptVersion; + UINT32 LastAttemptStatus; +} SYSTEM_FMP_LAST_ATTEMPT_VARIABLE; + +#define SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME L"SystemLastAttempVar" + +#define SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_GUID {0x2f564d6f, 0xcc2c, 0x4838= , { 0xb9, 0xa8, 0xbe, 0x59, 0x48, 0xb0, 0x3d, 0x59 }} + +#define SYSTEM_FMP_PRIVATE_DATA_SIGNATURE SIGNATURE_32('S', 'Y', 'S', 'F') + +#define SYSTEM_FMP_PROTOCOL_GUID {0x6d16624a, 0x26a6, 0x4cb4, { 0x84, 0xf= a, 0x6, 0x78, 0x5a, 0x7e, 0x82, 0x6a }} + +// +// SYSTEM FMP private data structure. +// + +struct _SYSTEM_FMP_PRIVATE_DATA { + UINT32 Signature; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL Fmp; + EFI_HANDLE Handle; + UINT8 DescriptorCount; + EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor; + SYSTEM_FMP_LAST_ATTEMPT_VARIABLE LastAttempt; +}; + +typedef struct _SYSTEM_FMP_PRIVATE_DATA SYSTEM_FMP_PRIVATE_DATA; + +/** + Returns a pointer to the SYSTEM_FMP_PRIVATE_DATA structure from the inpu= t a as Fmp. + + If the signatures matches, then a pointer to the data structure that con= tains + a specified field of that data structure is returned. + + @param a Pointer to the field specified by ServiceBinding = within + a data structure of type SYSTEM_FMP_PRIVATE_DATA. + +**/ +#define SYSTEM_FMP_PRIVATE_DATA_FROM_FMP(a) \ + CR ( \ + (a), \ + SYSTEM_FMP_PRIVATE_DATA, \ + Fmp, \ + SYSTEM_FMP_PRIVATE_DATA_SIGNATURE \ + ) + +// +// Update data +// + +typedef struct { + UINTN NumOfUpdates; +} CONFIG_HEADER; + +typedef struct { + UINTN Index; + PLATFORM_FIRMWARE_TYPE FirmwareType; + FLASH_ADDRESS_TYPE AddressType; + EFI_GUID FileGuid; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINTN Length; + UINTN ImageOffset; +} UPDATE_CONFIG_DATA; + +// +// System Firmware Update SMM Communication +// + +#define SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_FUNCTION_SET_IMAGE 1 + +typedef struct { + UINTN Function; + EFI_STATUS ReturnStatus; + // UINT8 Data[]; +} SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_HEAD; + +#define ABORT_REASON_MAX_SIZE 0x40 // UnicodeStringSize inc= luding final L'\0' + +#define CAPSULE_IMAGE_ADDITIONAL_MAX_SIZE (0x20020 + 0xA0000) // Addtion= al size for Capsule Header, FV block alignment + DispatchImage. + +typedef struct { + UINT8 ImageIndex; + UINTN ImageSize; + UINTN AbortReasonSize; + UINT32 LastAttemptVersion; + UINT32 LastAttemptStatus; + // UINT8 Data[AbortReasonMaxSize + ImageSize]; +} SYSTEM_FIRMWARE_UPDATE_COMMUNICATION_SET_IMAGE; + +/* +Name Offset(byte) Size(byte) Comments +SlotA_Priority 0x0 4 Read and Write the Slot A = priority +SlotA_UpdateRetries 0x4 4 Read and Write the Slot A = retries +SlotA_GlitchRetries 0x8 4 Read only, Slot A glitch +SlotB_Priority 0xC 4 Read and Write the Slot B = priority +SlotB_UpdateRetries 0x10 4 Read and Write the Slot B = retries +SlotB_GlitchRetries 0x14 4 Read only, Slot B glitch + +*/ +typedef struct { + UINT32 SlotA_Priority; + UINT32 SlotA_UpdateRetries; + UINT32 SlotA_GlitchRetries; + UINT32 SlotB_Priority; + UINT32 SlotB_UpdateRetries; + UINT32 SlotB_GlitchRetries; +} IMAGE_SLOT_HEADER_INFO; + +/** + Returns information about the current firmware image(s) of the device. + + This function allows a copy of the current firmware image to be created = and saved. + The saved copy could later been used, for example, in firmware image rec= overy or rollback. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEM= ENT_PROTOCOL instance. + @param[in, out] ImageInfoSize A pointer to the size, in bytes, of t= he ImageInfo buffer. + On input, this is the size of the buf= fer allocated by the caller. + On output, it is the size of the buff= er returned by the firmware + if the buffer was large enough, or th= e size of the buffer needed + to contain the image(s) information i= f the buffer was too small. + @param[in, out] ImageInfo A pointer to the buffer in which firm= ware places the current image(s) + information. The information is an ar= ray of EFI_FIRMWARE_IMAGE_DESCRIPTORs. + @param[out] DescriptorVersion A pointer to the location in which fi= rmware returns the version number + associated with the EFI_FIRMWARE_IMAG= E_DESCRIPTOR. + @param[out] DescriptorCount A pointer to the location in which fi= rmware returns the number of + descriptors or firmware images within= this device. + @param[out] DescriptorSize A pointer to the location in which fi= rmware returns the size, in bytes, + of an individual EFI_FIRMWARE_IMAGE_D= ESCRIPTOR. + @param[out] PackageVersion A version number that represents all = the firmware images in the device. + The format is vendor specific and new= version must have a greater value + than the old version. If PackageVersi= on is not supported, the value is + 0xFFFFFFFF. A value of 0xFFFFFFFE ind= icates that package version comparison + is to be performed using PackageVersi= onName. A value of 0xFFFFFFFD indicates + that package version update is in pro= gress. + @param[out] PackageVersionName A pointer to a pointer to a null-term= inated string representing the + package version name. The buffer is a= llocated by this function with + AllocatePool(), and it is the caller'= s responsibility to free it with a call + to FreePool(). + + @retval EFI_SUCCESS The device was successfully updated w= ith the new image. + @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. T= he current buffer size + needed to hold the image(s) informati= on is returned in ImageInfoSize. + @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL. + @retval EFI_DEVICE_ERROR Valid information could not be return= ed. Possible corrupted image. + +**/ +EFI_STATUS +EFIAPI +FmpGetImageInfo ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN OUT UINTN *ImageInfoSize, + IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo, + OUT UINT32 *DescriptorVersion, + OUT UINT8 *DescriptorCount, + OUT UINTN *DescriptorSize, + OUT UINT32 *PackageVersion, + OUT CHAR16 **PackageVersionName + ); + +/** + Retrieves a copy of the current firmware image of the device. + + This function allows a copy of the current firmware image to be created = and saved. + The saved copy could later been used, for example, in firmware image rec= overy or rollback. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_= PROTOCOL instance. + @param[in] ImageIndex A unique number identifying the firmware = image(s) within the device. + The number is between 1 and DescriptorCou= nt. + @param[in,out] Image Points to the buffer where the current im= age is copied to. + @param[in,out] ImageSize On entry, points to the size of the buffe= r pointed to by Image, in bytes. + On return, points to the length of the im= age, in bytes. + + @retval EFI_SUCCESS The device was successfully updated with = the new image. + @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too = small to hold the + image. The current buffer size needed to = hold the image is returned + in ImageSize. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_NOT_FOUND The current image is not copied to the bu= ffer. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATION The operation could not be performed due = to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpGetImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN OUT VOID *Image, + IN OUT UINTN *ImageSize + ); + +/** + Updates the firmware image of the device. + + This function updates the hardware with the new firmware image. + This function returns EFI_UNSUPPORTED if the firmware image is not updat= able. + If the firmware image is updatable, the function should perform the foll= owing minimal validations + before proceeding to do the firmware image update. + - Validate the image authentication if image has attribute + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns + EFI_SECURITY_VIOLATION if the validation fails. + - Validate the image is a supported image for this device. The function = returns EFI_ABORTED if + the image is unsupported. The function can optionally provide more det= ailed information on + why the image is not a supported image. + - Validate the data from VendorCode if not null. Image validation must b= e performed before + VendorCode data validation. VendorCode data is ignored or considered i= nvalid if image + validation failed. The function returns EFI_ABORTED if the data is inv= alid. + + VendorCode enables vendor to implement vendor-specific firmware image up= date policy. Null if + the caller did not specify the policy or use the default policy. As an e= xample, vendor can implement + a policy to allow an option to force a firmware image update when the ab= ort reason is due to the new + firmware image version is older than the current firmware image version = or bad image checksum. + Sensitive operations such as those wiping the entire firmware image and = render the device to be + non-functional should be encoded in the image itself rather than passed = with the VendorCode. + AbortReason enables vendor to have the option to provide a more detailed= description of the abort + reason to the caller. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_= PROTOCOL instance. + @param[in] ImageIndex A unique number identifying the firmware = image(s) within the device. + The number is between 1 and DescriptorCou= nt. + @param[in] Image Points to the new image. + @param[in] ImageSize Size of the new image in bytes. + @param[in] VendorCode This enables vendor to implement vendor-s= pecific firmware image update policy. + Null indicates the caller did not specify= the policy or use the default policy. + @param[in] Progress A function used by the driver to report t= he progress of the firmware update. + @param[out] AbortReason A pointer to a pointer to a null-terminat= ed string providing more + details for the aborted operation. The bu= ffer is allocated by this function + with AllocatePool(), and it is the caller= 's responsibility to free it with a + call to FreePool(). + + @retval EFI_SUCCESS The device was successfully updated with = the new image. + @retval EFI_ABORTED The operation is aborted. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATION The operation could not be performed due = to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpSetImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, + OUT CHAR16 **AbortReason + ); + +/** + Checks if the firmware image is valid for the device. + + This function allows firmware update application to validate the firmwar= e image without + invoking the SetImage() first. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_= PROTOCOL instance. + @param[in] ImageIndex A unique number identifying the firmware = image(s) within the device. + The number is between 1 and DescriptorCou= nt. + @param[in] Image Points to the new image. + @param[in] ImageSize Size of the new image in bytes. + @param[out] ImageUpdatable Indicates if the new image is valid for u= pdate. It also provides, + if available, additional information if t= he image is invalid. + + @retval EFI_SUCCESS The image was successfully checked. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATION The operation could not be performed due = to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpCheckImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN CONST VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *ImageUpdatable + ); + +/** + Returns information about the firmware package. + + This function returns package information. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAG= EMENT_PROTOCOL instance. + @param[out] PackageVersion A version number that represents al= l the firmware images in the device. + The format is vendor specific and n= ew version must have a greater value + than the old version. If PackageVer= sion is not supported, the value is + 0xFFFFFFFF. A value of 0xFFFFFFFE i= ndicates that package version + comparison is to be performed using= PackageVersionName. A value of + 0xFFFFFFFD indicates that package v= ersion update is in progress. + @param[out] PackageVersionName A pointer to a pointer to a null-te= rminated string representing + the package version name. The buffe= r is allocated by this function with + AllocatePool(), and it is the calle= r's responsibility to free it with a + call to FreePool(). + @param[out] PackageVersionNameMaxLen The maximum length of package versi= on name if device supports update of + package version name. A value of 0 = indicates the device does not support + update of package version name. Len= gth is the number of Unicode characters, + including the terminating null char= acter. + @param[out] AttributesSupported Package attributes that are support= ed by this device. See 'Package Attribute + Definitions' for possible returned = values of this parameter. A value of 1 + indicates the attribute is supporte= d and the current setting value is + indicated in AttributesSetting. A v= alue of 0 indicates the attribute is not + supported and the current setting v= alue in AttributesSetting is meaningless. + @param[out] AttributesSetting Package attributes. See 'Package At= tribute Definitions' for possible returned + values of this parameter + + @retval EFI_SUCCESS The package information was success= fully returned. + @retval EFI_UNSUPPORTED The operation is not supported. + +**/ +EFI_STATUS +EFIAPI +FmpGetPackageInfo ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + OUT UINT32 *PackageVersion, + OUT CHAR16 **PackageVersionName, + OUT UINT32 *PackageVersionNameMaxLen, + OUT UINT64 *AttributesSupported, + OUT UINT64 *AttributesSetting + ); + +/** + Updates information about the firmware package. + + This function updates package information. + This function returns EFI_UNSUPPORTED if the package information is not = updatable. + VendorCode enables vendor to implement vendor-specific package informati= on update policy. + Null if the caller did not specify this policy or use the default policy. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_= PROTOCOL instance. + @param[in] Image Points to the authentication image. + Null if authentication is not required. + @param[in] ImageSize Size of the authentication image in bytes. + 0 if authentication is not required. + @param[in] VendorCode This enables vendor to implement vendor-s= pecific firmware + image update policy. + Null indicates the caller did not specify= this policy or use + the default policy. + @param[in] PackageVersion The new package version. + @param[in] PackageVersionName A pointer to the new null-terminated Unic= ode string representing + the package version name. + The string length is equal to or less tha= n the value returned in + PackageVersionNameMaxLen. + + @retval EFI_SUCCESS The device was successfully updated with = the new package + information. + @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer t= han the value + returned in PackageVersionNameMaxLen. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATION The operation could not be performed due = to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpSetPackageInfo ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode, + IN UINT32 PackageVersion, + IN CONST CHAR16 *PackageVersionName + ); + +/** + Initialize SystemFmpDriver private data structure. + + @param[in] SystemFmpPrivate private data structure to be initialized. + + @return EFI_SUCCESS private data is initialized. +**/ +EFI_STATUS +InitializePrivateData ( + IN SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate + ); + +extern EFI_GUID gSystemFmpLastAttemptVariableGuid; +extern EFI_GUID mCurrentImageTypeId; +extern EFI_GUID gSystemFmpProtocolGuid; + +#endif diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Unive= rsal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.c b/Platform/AMD/VanGoghB= oard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/SystemFi= rmwareUpdateDxe.c new file mode 100644 index 0000000000..61e23b4564 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/Sy= stemFirmwareUpdate/SystemFirmwareUpdateDxe.c @@ -0,0 +1,1448 @@ +/** @file + Implements SystemFirmwareUpdateDxe.c + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* This file includes code originally published under the following licens= e. */ + +/** @file + SetImage instance to update system firmware. + + Caution: This module requires additional review when modified. + This module will have external input - capsule image. + This external input must be validated carefully to avoid security issue = like + buffer overflow, integer overflow. + + FmpSetImage() will receive untrusted input and do basic validation. + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include "SystemFirmwareDxe.h" + +// +// SystemFmp driver private data +// +SYSTEM_FMP_PRIVATE_DATA *mSystemFmpPrivate =3D NULL; + +EFI_GUID mCurrentImageTypeId; + +BOOLEAN mNvRamUpdated =3D FALSE; + +UINT8 mUpdateSlot =3D 0; + +/** + Parse Config data file to get the updated data array. + + @param[in] DataBuffer Config raw file buffer. + @param[in] BufferSize Size of raw buffer. + @param[in, out] ConfigHeader Pointer to the config header. + @param[in, out] UpdateArray Pointer to the config of update data. + + @retval EFI_NOT_FOUND No config data is found. + @retval EFI_OUT_OF_RESOURCES No enough memory is allocated. + @retval EFI_SUCCESS Parse the config file successfully. + +**/ +EFI_STATUS +ParseUpdateDataFile ( + IN UINT8 *DataBuffer, + IN UINTN BufferSize, + IN OUT CONFIG_HEADER *ConfigHeader, + IN OUT UPDATE_CONFIG_DATA **UpdateArray + ); + +/** + Update System Firmware image component. + + @param[in] SystemFirmwareImage Points to the System Firmware image. + @param[in] SystemFirmwareImageSize The length of the System Firmware im= age in bytes. + @param[in] ConfigData Points to the component configuratio= n structure. + @param[out] LastAttemptVersion The last attempt version, which will= be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[out] LastAttemptStatus The last attempt status, which will = be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[in] Progress A function used by the driver to rep= ort the progress of the firmware update. + @param[in] StartPercentage The start completion percentage valu= e that may be used to report progress during the flash write operation. + @param[in] EndPercentage The end completion percentage value = that may be used to report progress during the flash write operation. + + @retval EFI_SUCCESS The System Firmware image is updated. + @retval EFI_WRITE_PROTECTED The flash device is read only. +**/ +EFI_STATUS +PerformUpdate ( + IN VOID *SystemFirmwareImage, + IN UINTN SystemFirmwareImageSiz= e, + IN UPDATE_CONFIG_DATA *ConfigData, + OUT UINT32 *LastAttemptVersion, + OUT UINT32 *LastAttemptStatus, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, + IN UINTN StartPercentage, + IN UINTN EndPercentage + ) +{ + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO, "PlatformUpdate:")); + DEBUG ((DEBUG_INFO, " BaseAddress - 0x%lx,", ConfigData->BaseAddress)); + DEBUG ((DEBUG_INFO, " ImageOffset - 0x%x,", ConfigData->ImageOffset)); + DEBUG ((DEBUG_INFO, " Legnth - 0x%x\n", ConfigData->Length)); + if (Progress !=3D NULL) { + Progress (StartPercentage); + } + + Status =3D PerformFlashWriteWithProgress ( + ConfigData->FirmwareType, + ConfigData->BaseAddress, + ConfigData->AddressType, + (VOID *)((UINTN)SystemFirmwareImage + (UINTN)ConfigData->Imag= eOffset), + ConfigData->Length, + Progress, + StartPercentage, + EndPercentage + ); + if (Progress !=3D NULL) { + Progress (EndPercentage); + } + + if (!EFI_ERROR (Status)) { + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_SUCCESS; + if (ConfigData->FirmwareType =3D=3D PlatformFirmwareTypeNvRam) { + mNvRamUpdated =3D TRUE; + } + } else { + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; + } + + return Status; +} + +/** + Get layout of system firmware image. + + @param[in] SystemFirmwareImage Points to the System firmware image. + @param[out] SlotAOffset Points to the offste of slot A image. + @param[out] SlotBOffset Points to the offste of slot B image. + + @retval EFI_SUCCESS Get system firmware image layout suc= cessfully. + @retval others Some error occurs when executing thi= s routine. + +**/ +EFI_STATUS +GetImageLayout ( + IN VOID *SystemFirmwareImage, + OUT UINT32 *SlotAOffset, + OUT UINT32 *SlotBOffset, + OUT UINT8 *ActiveSlot + ) +{ + FIRMWARE_ENTRY_TABLEV2 *EfsAddressPtr; + PSP_DIRECTORY *PspL1DirectoryPtr; + UINT32 SlotCount; + UINT32 Index; + IMAGE_SLOT_HEADER *IshSlotAInfoPtr; + IMAGE_SLOT_HEADER *IshSlotBInfoPtr; + + if (SystemFirmwareImage =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((SlotAOffset =3D=3D NULL) || (SlotBOffset =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check EFS structure of firmware image + // + EfsAddressPtr =3D (FIRMWARE_ENTRY_TABLEV2 *)(UINTN)((UINT8 *)SystemFirmw= areImage + EFS_LOCATION); + if (EfsAddressPtr->Signature !=3D FIRMWARE_TABLE_SIGNATURE) { + DEBUG ((DEBUG_ERROR, "EFS signature incorrect.\n")); + return EFI_NOT_FOUND; + } + + // + // Check PSP_L1_DIRECTORY of firmware image + // + DEBUG ((DEBUG_INFO, "Base Address for PSP directory: 0x%x\n", EfsAddress= Ptr->PspDirBase)); + PspL1DirectoryPtr =3D (PSP_DIRECTORY *)(UINTN)((UINT8 *)SystemFirmwareIm= age + EfsAddressPtr->PspDirBase); + if ((PspL1DirectoryPtr->Header.Cookie !=3D PSP_DIRECTORY_HEADER_SIGNATUR= E) || + (!IS_VALID_ADDR32 (EfsAddressPtr->PspDirBase)) || + (!ALIGN_4K_CHECK (EfsAddressPtr->PspDirBase)) || + (PspL1DirectoryPtr->Header.TotalEntries =3D=3D 0) || + (PspL1DirectoryPtr->Header.TotalEntries > MAX_IMAGE_SLOT_COUNT) + ) + { + DEBUG ((DEBUG_ERROR, "PSP L1 directory address, slot count or signatur= e error!\n")); + return EFI_NOT_FOUND; + } + + // + // Check Image Slot entries of firmware image + // + SlotCount =3D PspL1DirectoryPtr->Header.TotalEntries; + for (Index =3D 0; Index < SlotCount; Index++) { + if (((PspL1DirectoryPtr->PspEntry[Index].Type.Value !=3D PSP_REGION_A_= DIR) && + (PspL1DirectoryPtr->PspEntry[Index].Type.Value !=3D PSP_REGION_B_= DIR)) || + (!IS_VALID_ADDR32 (PspL1DirectoryPtr->PspEntry[Index].Location)) || + (!ALIGN_4K_CHECK (PspL1DirectoryPtr->PspEntry[Index].Location)) || + (((PspL1DirectoryPtr->PspEntry[Index].Location) & 0xFFFFFFFF000000= 00) !=3D 0) + ) + { + DEBUG ((DEBUG_ERROR, "PSP L1 directory slot %d data error!\n", Index= )); + return EFI_NOT_FOUND; + } + } + + // + // Get offset of specific slot + // + IshSlotAInfoPtr =3D (IMAGE_SLOT_HEADER *)(UINTN)((UINT8 *)SystemFirmware= Image + PspL1DirectoryPtr->PspEntry[0].Location); + *SlotAOffset =3D IshSlotAInfoPtr->ImageSlotAddr; + DEBUG ((DEBUG_ERROR, "Slot A image offset: 0x%x\n", *SlotAOffset)); + + IshSlotBInfoPtr =3D (IMAGE_SLOT_HEADER *)(UINTN)((UINT8 *)SystemFirmware= Image + PspL1DirectoryPtr->PspEntry[1].Location); + *SlotBOffset =3D IshSlotBInfoPtr->ImageSlotAddr; + DEBUG ((DEBUG_ERROR, "Slot B image offset: 0x%x\n", *SlotBOffset)); + + if ((*SlotAOffset =3D=3D 0) || (*SlotBOffset =3D=3D 0)) { + return EFI_NOT_FOUND; + } + + if (ActiveSlot !=3D NULL) { + if (IshSlotAInfoPtr->Priority > IshSlotBInfoPtr->Priority) { + *ActiveSlot =3D SLOT_A; + } else { + *ActiveSlot =3D SLOT_B; + } + } + + return EFI_SUCCESS; +} + +/** + Verify layout of OTA Capsule firmware image, and return offset and size = of required update slot. + + @param[in] SystemFirmwareImage Points to the System firmware image. + @param[in] UpdateSlot The slot number need to be updated. + @param[out] UpdateOffset The firmware image offset need to up= dated. + @param[out] UpdateSize The firmware image size need to upda= ted. + + @retval EFI_SUCCESS Verify OTA capsule image and get upd= ated offset/size successfully. + @retval others Some error occurs when executing thi= s routine. + +**/ +EFI_STATUS +VerifyImageLayout ( + IN VOID *SystemFirmwareImage, + IN UINT8 UpdateSlot, + OUT UINT32 *UpdateOffset, + OUT UINT32 *UpdateSize + ) +{ + EFI_STATUS Status; + UINT32 OtaSlotAOffset; + UINT32 OtaSlotBOffset; + UINT32 FlashSlotAOffset; + UINT32 FlashSlotBOffset; + UINT8 CurrentActiveSlot; + + if (SystemFirmwareImage =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((UpdateOffset =3D=3D NULL) || (UpdateSize =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + OtaSlotAOffset =3D 0; + OtaSlotBOffset =3D 0; + FlashSlotAOffset =3D 0; + FlashSlotBOffset =3D 0; + + // + // Get image layout of OTA Capsule + // + DEBUG ((DEBUG_INFO, "Get image layout of OTA Capsule.\n")); + Status =3D GetImageLayout (SystemFirmwareImage, &OtaSlotAOffset, &OtaSlo= tBOffset, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GetImageLayout of Capsule failed: %r\n", Status)= ); + return Status; + } + + // + // Get image layout of firmware in flash ROM + // + DEBUG ((DEBUG_INFO, "Get image layout of flash ROM.\n")); + Status =3D GetImageLayout ((VOID *)(UINTN)(PcdGet32 (PcdFlashAreaBaseAdd= ress)), &FlashSlotAOffset, &FlashSlotBOffset, &CurrentActiveSlot); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GetImageLayout of Flash failed: %r\n", Status)); + return Status; + } + + // + // Check current active slot and update slot + // + // - if (CurrentActiveSlot =3D=3D mUpdateSlot) { + // - DEBUG ((DEBUG_ERROR, "Can't update Capsule on current active slot= . CurrentActiveSlot: %d, UpdateSlot: %d\n", CurrentActiveSlot, mUpdateSlot)= ); + // - return EFI_INVALID_PARAMETER; + // - } + // + // Compare layout of OTA capsule image and flash firmware + // + if ((OtaSlotAOffset !=3D FlashSlotAOffset) || (OtaSlotBOffset !=3D Flash= SlotBOffset)) { + DEBUG ((DEBUG_ERROR, "Layout is different between Capsule and Flash.\n= ")); + return EFI_NOT_FOUND; + } + + if (UpdateSlot =3D=3D SLOT_A) { + *UpdateOffset =3D OtaSlotAOffset; + } else if (UpdateSlot =3D=3D SLOT_B) { + *UpdateOffset =3D OtaSlotBOffset; + } else { + DEBUG ((DEBUG_ERROR, "Invalid update slot number: %d\n", UpdateSlot)); + return EFI_INVALID_PARAMETER; + } + + // - *UpdateSize =3D (UINT32) DivU64x64Remainder ((UINTN) PcdGet32 (Pcd= FlashAreaSize) - OtaSlotAOffset, 2, NULL); + *UpdateSize =3D (UINT32)((UINTN)PcdGet32 (PcdFlashAreaSize) - OtaSlotAOf= fset); + + return EFI_SUCCESS; +} + +/** + Get OTA Capsule firmware image info. + + @param[in] SystemFirmwareImage Points to the System firmware image. + @param[in] SystemFirmwareImageSize The length of the System Firmware im= age in bytes. + @param[out] OtaCapsuleOffset The firmware image offset need to up= dated. + @param[out] OtaCapsuleSize The firmware image size need to upda= ted. + + @retval EFI_SUCCESS Get OTA Capsule firmware image info = successfully. + @retval others Some error occurs when executing thi= s routine. + +**/ +EFI_STATUS +GetOtaCapsuleInfo ( + IN VOID *SystemFirmwareImage, + IN UINTN SystemFirmwareImageSize, + OUT UINT32 *OtaCapsuleOffset, + OUT UINT32 *OtaCapsuleSize + ) +{ + EFI_STATUS Status; + OTA_CAPSULE_UPDATE OtaCapsuleUpdateVal; + // - UINTN VarSize; + UINT32 UpdateOffset; + UINT32 UpdateSize; + + if ((OtaCapsuleOffset =3D=3D NULL) || (OtaCapsuleSize =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + DEBUG ((DEBUG_INFO, "GetOtaCapsuleInfo:")); + DEBUG ((DEBUG_INFO, " Legnth - 0x%x\n", SystemFirmwareImageSize)); + + // - if (SystemFirmwareImageSize !=3D (UINTN) PcdGet32 (PcdFlashAreaSiz= e)) { + // - return EFI_INVALID_PARAMETER; + // - } + if (SystemFirmwareImageSize !=3D (UINTN)(PcdGet32 (PcdFlashAreaSize)*2))= { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&OtaCapsuleUpdateVal, sizeof (OTA_CAPSULE_UPDATE)); + + /* + VarSize =3D sizeof (OTA_CAPSULE_UPDATE); + Status =3D gRT->GetVariable ( + OTA_CAPSULE_VAR_NAME, + &gOtaCapsuleUpdateGuid, + NULL, + &VarSize, + (VOID *) &OtaCapsuleUpdateVal + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GetOtaCapsuleInfo: GetVariable failed: %r\n", = Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, "UpdateFlag: 0x%x, UpdateSlot: 0x%x\n", OtaCapsule= UpdateVal.UpdateFlag, OtaCapsuleUpdateVal.UpdateSlot)); + + mUpdateSlot =3D OtaCapsuleUpdateVal.UpdateSlot; + if (mUpdateSlot >=3D MAX_SLOT_NUM) { + DEBUG ((DEBUG_ERROR, "Invalid Slot number: %d\n", mUpdateSlot)); + return EFI_NOT_FOUND; + } + */ + mUpdateSlot =3D 0; + + Status =3D VerifyImageLayout (SystemFirmwareImage, mUpdateSlot, &UpdateO= ffset, &UpdateSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "VerifyImageLayout failed: %r\n", Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, "UpdateSlot: %d, UpdateOffset: 0x%x, UpdateSize: 0x%= x\n", mUpdateSlot, UpdateOffset, UpdateSize)); + + *OtaCapsuleOffset =3D UpdateOffset; + *OtaCapsuleSize =3D UpdateSize; + + return EFI_SUCCESS; +} + +/** + Get OTA Capsule firmware image info. + + @param[in] SystemFirmwareImage Points to the System firmware image. + @param[in] SystemFirmwareImageSize The length of the System Firmware im= age in bytes. + @param[out] OtaCapsuleOffset The firmware image offset need to up= dated. + @param[out] OtaCapsuleSize The firmware image size need to upda= ted. + + @retval EFI_SUCCESS Get OTA Capsule firmware image info = successfully. + @retval others Some error occurs when executing thi= s routine. + +**/ +EFI_STATUS +GetOtaCapsuleInfoSlotB ( + IN VOID *SystemFirmwareImage, + IN UINTN SystemFirmwareImageSize, + OUT UINT32 *OtaCapsuleOffset, + OUT UINT32 *OtaCapsuleSize + ) +{ + EFI_STATUS Status; + OTA_CAPSULE_UPDATE OtaCapsuleUpdateVal; + // - UINTN VarSize; + UINT32 UpdateOffset; + UINT32 UpdateSize; + + // - if ((OtaCapsuleOffset =3D=3D NULL) || (OtaCapsuleSize =3D=3D NULL)= ) { + // - return EFI_INVALID_PARAMETER; + // - } + + DEBUG ((DEBUG_INFO, "GetOtaCapsuleInfo:")); + DEBUG ((DEBUG_INFO, " Legnth - 0x%x\n", SystemFirmwareImageSize)); + // - if (SystemFirmwareImageSize !=3D (UINTN) PcdGet32 (PcdFlashAreaSiz= e)) { + // - return EFI_INVALID_PARAMETER; + // - } + // - if (SystemFirmwareImageSize !=3D (UINTN) (PcdGet32 (PcdFlashAreaSi= ze)*2)) { + // - return EFI_INVALID_PARAMETER; + // - } + ZeroMem (&OtaCapsuleUpdateVal, sizeof (OTA_CAPSULE_UPDATE)); + + /* + VarSize =3D sizeof (OTA_CAPSULE_UPDATE); + Status =3D gRT->GetVariable ( + OTA_CAPSULE_VAR_NAME, + &gOtaCapsuleUpdateGuid, + NULL, + &VarSize, + (VOID *) &OtaCapsuleUpdateVal + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GetOtaCapsuleInfo: GetVariable failed: %r\n", = Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, "UpdateFlag: 0x%x, UpdateSlot: 0x%x\n", OtaCapsule= UpdateVal.UpdateFlag, OtaCapsuleUpdateVal.UpdateSlot)); + + mUpdateSlot =3D OtaCapsuleUpdateVal.UpdateSlot; + if (mUpdateSlot >=3D MAX_SLOT_NUM) { + DEBUG ((DEBUG_ERROR, "Invalid Slot number: %d\n", mUpdateSlot)); + return EFI_NOT_FOUND; + } + */ + mUpdateSlot =3D 1; + + Status =3D VerifyImageLayout (SystemFirmwareImage, mUpdateSlot, &UpdateO= ffset, &UpdateSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "VerifyImageLayout failed: %r\n", Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, "UpdateSlot: %d, UpdateOffset: 0x%x, UpdateSize: 0x%= x\n", mUpdateSlot, UpdateOffset, UpdateSize)); + + *OtaCapsuleOffset =3D UpdateOffset; + *OtaCapsuleSize =3D UpdateSize; + + return EFI_SUCCESS; +} + +/** + Update active slot information in ISH. + + @param[in] SlotNum The slot number will be set as activ= e. + + @retval EFI_SUCCESS Set active slto successfully. + @retval others Some error occurs when executing thi= s routine. + +**/ +EFI_STATUS +UpdateAbActiveSlot ( + IN UINT8 SlotNum + ) +{ + EFI_STATUS Status; + IMAGE_SLOT_HEADER_INFO IshInfo; + UINTN VarSize; + + DEBUG ((DEBUG_INFO, "UpdateAbActiveSlot...\n")); + + if (SlotNum >=3D MAX_SLOT_NUM) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&IshInfo, sizeof (IMAGE_SLOT_HEADER_INFO)); + + VarSize =3D sizeof (IMAGE_SLOT_HEADER_INFO); + Status =3D gRT->GetVariable ( + ISH_VAR_NAME, + &gABSupportUpdateIshGuid, + NULL, + &VarSize, + (VOID *)&IshInfo + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Get A/B slot info failed: %r\n", Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, "Get IshInfo.SlotA_Priority: 0x%x\n", IshInfo.S= lotA_Priority)); + DEBUG ((DEBUG_INFO, "Get IshInfo.SlotA_UpdateRetries: 0x%x\n", IshInfo.S= lotA_UpdateRetries)); + DEBUG ((DEBUG_INFO, "Get IshInfo.SlotA_GlitchRetries: 0x%x\n", IshInfo.S= lotA_GlitchRetries)); + DEBUG ((DEBUG_INFO, "Get IshInfo.SlotB_Priority: 0x%x\n", IshInfo.S= lotB_Priority)); + DEBUG ((DEBUG_INFO, "Get IshInfo.SlotB_UpdateRetries: 0x%x\n", IshInfo.S= lotB_UpdateRetries)); + DEBUG ((DEBUG_INFO, "Get IshInfo.SlotB_GlitchRetries: 0x%x\n\n", IshInfo= .SlotB_GlitchRetries)); + + if (SlotNum =3D=3D SLOT_A) { + // Slot A + if (IshInfo.SlotB_Priority =3D=3D MAX_UINT32) { + IshInfo.SlotA_Priority =3D PcdGet32 (PcdFlashAbImageSlotDefaultPrior= ity); + IshInfo.SlotB_Priority =3D IshInfo.SlotA_Priority - 1; + } else { + IshInfo.SlotA_Priority =3D MAX (IshInfo.SlotA_Priority, IshInfo.Slot= B_Priority) + 1; + } + + IshInfo.SlotA_UpdateRetries =3D 0xFF; + } else if (SlotNum =3D=3D SLOT_B) { + // Slot B + if (IshInfo.SlotA_Priority =3D=3D MAX_UINT32) { + IshInfo.SlotB_Priority =3D PcdGet32 (PcdFlashAbImageSlotDefaultPrior= ity); + IshInfo.SlotA_Priority =3D IshInfo.SlotB_Priority - 1; + } else { + IshInfo.SlotB_Priority =3D MAX (IshInfo.SlotA_Priority, IshInfo.Slot= B_Priority) + 1; + } + + IshInfo.SlotB_UpdateRetries =3D 0xFF; + } + + DEBUG ((DEBUG_INFO, "Set IshInfo.SlotA_Priority: 0x%x\n", IshInfo.S= lotA_Priority)); + DEBUG ((DEBUG_INFO, "Set IshInfo.SlotA_UpdateRetries: 0x%x\n", IshInfo.S= lotA_UpdateRetries)); + DEBUG ((DEBUG_INFO, "Set IshInfo.SlotA_GlitchRetries: 0x%x\n", IshInfo.S= lotA_GlitchRetries)); + DEBUG ((DEBUG_INFO, "Set IshInfo.SlotB_Priority: 0x%x\n", IshInfo.S= lotB_Priority)); + DEBUG ((DEBUG_INFO, "Set IshInfo.SlotB_UpdateRetries: 0x%x\n", IshInfo.S= lotB_UpdateRetries)); + DEBUG ((DEBUG_INFO, "Set IshInfo.SlotB_GlitchRetries: 0x%x\n", IshInfo.S= lotB_GlitchRetries)); + + Status =3D gRT->SetVariable ( + ISH_VAR_NAME, + &gABSupportUpdateIshGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_A= CCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (IMAGE_SLOT_HEADER_INFO), + (VOID *)&IshInfo + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Set Slot info failed: %r\n", Status)); + return Status; + } + + return Status; +} + +/** + Update System Firmware image. + + @param[in] SystemFirmwareImage Points to the System Firmware image. + @param[in] SystemFirmwareImageSize The length of the System Firmware im= age in bytes. + @param[in] ConfigImage Points to the config file image. + @param[in] ConfigImageSize The length of the config file image = in bytes. + @param[out] LastAttemptVersion The last attempt version, which will= be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[out] LastAttemptStatus The last attempt status, which will = be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[in] Progress A function used by the driver to rep= ort the progress of the firmware update. + + @retval EFI_SUCCESS The System Firmware image is updated. + @retval EFI_WRITE_PROTECTED The flash device is read only. +**/ +EFI_STATUS +UpdateImage ( + IN VOID *SystemFirmwareImage, + IN UINTN SystemFirmwareImageSiz= e, + IN VOID *ConfigImage, + IN UINTN ConfigImageSize, + OUT UINT32 *LastAttemptVersion, + OUT UINT32 *LastAttemptStatus, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress + ) +{ + EFI_STATUS Status; + UPDATE_CONFIG_DATA *ConfigData; + UPDATE_CONFIG_DATA *UpdateConfigData; + CONFIG_HEADER ConfigHeader; + UINTN Index; + UINTN TotalSize; + UINTN BytesWritten; + UINTN StartPercentage; + UINTN EndPercentage; + UINT32 OtaCapsuleOffset; + UINT32 OtaCapsuleSize; + UINT32 ECImageSize; + UINT32 ECImageOffset; + + if (ConfigImage =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "PlatformUpdate (NoConfig):")); + // ASSUME the whole System Firmware include NVRAM region. + StartPercentage =3D 0; + EndPercentage =3D 100; + if (Progress !=3D NULL) { + Progress (StartPercentage); + } + + ECImageSize =3D 0x20000; + ECImageOffset =3D 0x0; + + DEBUG ((DEBUG_INFO, " BaseAddress - 0x%x,", ECImageOffset)); + DEBUG ((DEBUG_INFO, " Length - 0x%x\n", ECImageSize)); + + Status =3D PerformFlashWriteWithProgress ( + PlatformFirmwareTypeNvRam, + (EFI_PHYSICAL_ADDRESS)ECImageOffset, + FlashAddressTypeRelativeAddress, + (VOID *)((UINT8 *)SystemFirmwareImage + ECImageOffset), + ECImageSize, + Progress, + StartPercentage, + EndPercentage + ); + if (Progress !=3D NULL) { + Progress (EndPercentage); + } + + if (!EFI_ERROR (Status)) { + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_SUCCESS; + mNvRamUpdated =3D TRUE; + } else { + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; + } + + StartPercentage =3D 0; + EndPercentage =3D 100; + if (Progress !=3D NULL) { + Progress (StartPercentage); + } + + Status =3D GetOtaCapsuleInfo (SystemFirmwareImage, SystemFirmwareImage= Size, &OtaCapsuleOffset, &OtaCapsuleSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GetOtaCapsuleInfo failed: %r\n", Status)); + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; + return Status; + } + + DEBUG ((DEBUG_INFO, " BaseAddress - 0x%x,", OtaCapsuleOffset)); + DEBUG ((DEBUG_INFO, " Length - 0x%x\n", OtaCapsuleSize)); + + Status =3D PerformFlashWriteWithProgress ( + PlatformFirmwareTypeNvRam, + (EFI_PHYSICAL_ADDRESS)OtaCapsuleOffset, + FlashAddressTypeRelativeAddress, + (VOID *)((UINT8 *)SystemFirmwareImage + OtaCapsuleOffset), + OtaCapsuleSize, + Progress, + StartPercentage, + EndPercentage + ); + if (Progress !=3D NULL) { + Progress (EndPercentage); + } + + if (!EFI_ERROR (Status)) { + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_SUCCESS; + mNvRamUpdated =3D TRUE; + } else { + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; + } + + Status =3D GetOtaCapsuleInfoSlotB (SystemFirmwareImage, SystemFirmware= ImageSize, &OtaCapsuleOffset, &OtaCapsuleSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GetOtaCapsuleInfo failed: %r\n", Status)); + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; + return Status; + } + + DEBUG ((DEBUG_INFO, " BaseAddress - 0x%x,", OtaCapsuleOffset)); + DEBUG ((DEBUG_INFO, " Length - 0x%x\n", OtaCapsuleSize)); + + Status =3D PerformFlashWriteWithProgress ( + PlatformFirmwareTypeNvRam, + (EFI_PHYSICAL_ADDRESS)OtaCapsuleOffset, + FlashAddressTypeRelativeAddress, + (VOID *)((UINT8 *)SystemFirmwareImage + OtaCapsuleOffset), + OtaCapsuleSize, + Progress, + StartPercentage, + EndPercentage + ); + if (Progress !=3D NULL) { + Progress (EndPercentage); + } + + if (!EFI_ERROR (Status)) { + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_SUCCESS; + mNvRamUpdated =3D TRUE; + } else { + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; + } + + return Status; + } + + DEBUG ((DEBUG_INFO, "PlatformUpdate (With Config):\n")); + ConfigData =3D NULL; + ZeroMem (&ConfigHeader, sizeof (ConfigHeader)); + Status =3D ParseUpdateDataFile ( + ConfigImage, + ConfigImageSize, + &ConfigHeader, + &ConfigData + ); + DEBUG ((DEBUG_INFO, "ParseUpdateDataFile - %r\n", Status)); + if (EFI_ERROR (Status)) { + *LastAttemptStatus =3D LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; + return EFI_INVALID_PARAMETER; + } + + DEBUG ((DEBUG_INFO, "ConfigHeader.NumOfUpdates - 0x%x\n", ConfigHeader.N= umOfUpdates)); + DEBUG ((DEBUG_INFO, "PcdEdkiiSystemFirmwareFileGuid - %g\n", PcdGetPtr (= PcdEdkiiSystemFirmwareFileGuid))); + + TotalSize =3D 0; + for (Index =3D 0; Index < ConfigHeader.NumOfUpdates; Index++) { + if (CompareGuid (&ConfigData[Index].FileGuid, PcdGetPtr (PcdEdkiiSyste= mFirmwareFileGuid))) { + TotalSize =3D TotalSize + ConfigData[Index].Length; + } + } + + BytesWritten =3D 0; + Index =3D 0; + UpdateConfigData =3D ConfigData; + while (Index < ConfigHeader.NumOfUpdates) { + if (CompareGuid (&UpdateConfigData->FileGuid, PcdGetPtr (PcdEdkiiSyste= mFirmwareFileGuid))) { + DEBUG ((DEBUG_INFO, "FileGuid - %g (processing)\n", &UpdateConfigDat= a->FileGuid)); + StartPercentage =3D (BytesWritten * 100) / TotalSize; + EndPercentage =3D ((BytesWritten + UpdateConfigData->Length) * 100= ) / TotalSize; + Status =3D PerformUpdate ( + SystemFirmwareImage, + SystemFirmwareImageSize, + UpdateConfigData, + LastAttemptVersion, + LastAttemptStatus, + Progress, + StartPercentage, + EndPercentage + ); + // + // Shall updates be serialized so that if an update is not successfu= lly completed, + // the remaining updates won't be performed. + // + if (EFI_ERROR (Status)) { + break; + } + } else { + DEBUG ((DEBUG_INFO, "FileGuid - %g (ignored)\n", &UpdateConfigData->= FileGuid)); + } + + BytesWritten +=3D UpdateConfigData->Length; + + Index++; + UpdateConfigData++; + } + + return Status; +} + +/** + Authenticate and update System Firmware image. + + Caution: This function may receive untrusted input. + + @param[in] Image The EDKII system FMP capsule image. + @param[in] ImageSize The size of the EDKII system FMP capsule = image in bytes. + @param[out] LastAttemptVersion The last attempt version, which will be r= ecorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[out] LastAttemptStatus The last attempt status, which will be re= corded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. + @param[in] Progress A function used by the driver to report t= he progress of the firmware update. + + @retval EFI_SUCCESS EDKII system FMP capsule passes authenti= cation and the System Firmware image is updated. + @retval EFI_SECURITY_VIOLATION EDKII system FMP capsule fails authentic= ation and the System Firmware image is not updated. + @retval EFI_WRITE_PROTECTED The flash device is read only. +**/ +EFI_STATUS +SystemFirmwareAuthenticatedUpdate ( + IN VOID *Image, + IN UINTN ImageSize, + OUT UINT32 *LastAttemptVersion, + OUT UINT32 *LastAttemptStatus, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress + ) +{ + EFI_STATUS Status; + VOID *SystemFirmwareImage; + UINTN SystemFirmwareImageSize; + VOID *ConfigImage; + UINTN ConfigImageSize; + VOID *AuthenticatedImage; + UINTN AuthenticatedImageSize; + + AuthenticatedImage =3D NULL; + AuthenticatedImageSize =3D 0; + + DEBUG ((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate...\n")); + + Status =3D CapsuleAuthenticateSystemFirmware (Image, ImageSize, FALSE, L= astAttemptVersion, LastAttemptStatus, &AuthenticatedImage, &AuthenticatedIm= ageSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "SystemFirmwareAuthenticateImage - %r\n", Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, "ExtractSystemFirmwareImage ...\n")); + ExtractSystemFirmwareImage (AuthenticatedImage, AuthenticatedImageSize, = &SystemFirmwareImage, &SystemFirmwareImageSize); + DEBUG ((DEBUG_INFO, "ExtractConfigImage ...\n")); + ExtractConfigImage (AuthenticatedImage, AuthenticatedImageSize, &ConfigI= mage, &ConfigImageSize); + + DEBUG ((DEBUG_INFO, "UpdateImage ...\n")); + Status =3D UpdateImage (SystemFirmwareImage, SystemFirmwareImageSize, Co= nfigImage, ConfigImageSize, LastAttemptVersion, LastAttemptStatus, Progress= ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "UpdateImage - %r\n", Status)); + return Status; + } + + #if 0 + // DO NOT KNOW THE REASON to update A/B Active Slot. + // Removed FOR NOW. + + // + // Update A/B active slot info + // + Status =3D UpdateAbActiveSlot (mUpdateSlot); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "UpdateAbActiveSlot failed: %r\n", Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate Done\n")); + #endif + return Status; +} + +/** + + This code finds variable in storage blocks (Volatile or Non-Volatile). + + @param[in] VariableName Name of Variable to be found. + @param[in] VendorGuid Variable vendor GUID. + @param[out] Attributes Attribute value of the variab= le found. + @param[in, out] DataSize Size of Data found. If size i= s less than the + data, this value contains the= required size. + @param[out] Data Data pointer. + + @return EFI_INVALID_PARAMETER Invalid parameter. + @return EFI_SUCCESS Find the specified variable. + @return EFI_NOT_FOUND Not found. + @return EFI_BUFFER_TO_SMALL DataSize is too small for the result. + +**/ +EFI_STATUS +EFIAPI +GetVariableHook ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +{ + DEBUG ((DEBUG_INFO, "GetVariableHook - %S, %g\n", VariableName, VendorGu= id)); + return EFI_NOT_AVAILABLE_YET; +} + +/** + + This code Finds the Next available variable. + + @param[in, out] VariableNameSize Size of the variable name. + @param[in, out] VariableName Pointer to variable name. + @param[in, out] VendorGuid Variable Vendor Guid. + + @return EFI_INVALID_PARAMETER Invalid parameter. + @return EFI_SUCCESS Find the specified variable. + @return EFI_NOT_FOUND Not found. + @return EFI_BUFFER_TO_SMALL DataSize is too small for the result. + +**/ +EFI_STATUS +EFIAPI +GetNextVariableNameHook ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ) +{ + DEBUG ((DEBUG_INFO, "GetNextVariableNameHook - %S, %g\n", VariableName, = VendorGuid)); + return EFI_NOT_AVAILABLE_YET; +} + +/** + + This code sets variable in storage blocks (Volatile or Non-Volatile). + + @param[in] VariableName Name of Variable to be found. + @param[in] VendorGuid Variable vendor GUID. + @param[in] Attributes Attribute value of the varia= ble found + @param[in] DataSize Size of Data found. If size = is less than the + data, this value contains th= e required size. + @param[in] Data Data pointer. + + @return EFI_INVALID_PARAMETER Invalid parameter. + @return EFI_SUCCESS Set successfully. + @return EFI_OUT_OF_RESOURCES Resource not enough to set varia= ble. + @return EFI_NOT_FOUND Not found. + @return EFI_WRITE_PROTECTED Variable is read-only. + +**/ +EFI_STATUS +EFIAPI +SetVariableHook ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +{ + DEBUG ((DEBUG_INFO, "SetVariableHook - %S, %g, 0x%x (0x%x)\n", VariableN= ame, VendorGuid, Attributes, DataSize)); + return EFI_NOT_AVAILABLE_YET; +} + +/** + + This code returns information about the EFI variables. + + @param[in] Attributes Attributes bitmask to specify= the type of variables + on which to return informatio= n. + @param[out] MaximumVariableStorageSize Pointer to the maximum size o= f the storage space available + for the EFI variables associa= ted with the attributes specified. + @param[out] RemainingVariableStorageSize Pointer to the remaining size= of the storage space available + for EFI variables associated = with the attributes specified. + @param[out] MaximumVariableSize Pointer to the maximum size o= f an individual EFI variables + associated with the attribute= s specified. + + @return EFI_SUCCESS Query successfully. + +**/ +EFI_STATUS +EFIAPI +QueryVariableInfoHook ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ) +{ + DEBUG ((DEBUG_INFO, "QueryVariableInfoHook - 0x%x\n", Attributes)); + return EFI_NOT_AVAILABLE_YET; +} + +/** + Updates the firmware image of the device. + + This function updates the hardware with the new firmware image. + This function returns EFI_UNSUPPORTED if the firmware image is not updat= able. + If the firmware image is updatable, the function should perform the foll= owing minimal validations + before proceeding to do the firmware image update. + - Validate the image authentication if image has attribute + IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns + EFI_SECURITY_VIOLATION if the validation fails. + - Validate the image is a supported image for this device. The function = returns EFI_ABORTED if + the image is unsupported. The function can optionally provide more det= ailed information on + why the image is not a supported image. + - Validate the data from VendorCode if not null. Image validation must b= e performed before + VendorCode data validation. VendorCode data is ignored or considered i= nvalid if image + validation failed. The function returns EFI_ABORTED if the data is inv= alid. + + VendorCode enables vendor to implement vendor-specific firmware image up= date policy. Null if + the caller did not specify the policy or use the default policy. As an e= xample, vendor can implement + a policy to allow an option to force a firmware image update when the ab= ort reason is due to the new + firmware image version is older than the current firmware image version = or bad image checksum. + Sensitive operations such as those wiping the entire firmware image and = render the device to be + non-functional should be encoded in the image itself rather than passed = with the VendorCode. + AbortReason enables vendor to have the option to provide a more detailed= description of the abort + reason to the caller. + + @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_= PROTOCOL instance. + @param[in] ImageIndex A unique number identifying the firmware = image(s) within the device. + The number is between 1 and DescriptorCou= nt. + @param[in] Image Points to the new image. + @param[in] ImageSize Size of the new image in bytes. + @param[in] VendorCode This enables vendor to implement vendor-s= pecific firmware image update policy. + Null indicates the caller did not specify= the policy or use the default policy. + @param[in] Progress A function used by the driver to report t= he progress of the firmware update. + @param[out] AbortReason A pointer to a pointer to a null-terminat= ed string providing more + details for the aborted operation. The bu= ffer is allocated by this function + with AllocatePool(), and it is the caller= 's responsibility to free it with a + call to FreePool(). + + @retval EFI_SUCCESS The device was successfully updated with = the new image. + @retval EFI_ABORTED The operation is aborted. + @retval EFI_INVALID_PARAMETER The Image was NULL. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SECURITY_VIOLATION The operation could not be performed due = to an authentication failure. + +**/ +EFI_STATUS +EFIAPI +FmpSetImage ( + IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This, + IN UINT8 ImageIndex, + IN CONST VOID *Image, + IN UINTN ImageSize, + IN CONST VOID *VendorCode, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, + OUT CHAR16 **AbortReason + ) +{ + EFI_STATUS Status; + EFI_STATUS VarStatus; + SYSTEM_FMP_PRIVATE_DATA *SystemFmpPrivate; + + if ((Image =3D=3D NULL) || (ImageSize =3D=3D 0) || (AbortReason =3D=3D N= ULL)) { + return EFI_INVALID_PARAMETER; + } + + SystemFmpPrivate =3D SYSTEM_FMP_PRIVATE_DATA_FROM_FMP (This); + *AbortReason =3D NULL; + + if ((ImageIndex =3D=3D 0) || (ImageIndex > SystemFmpPrivate->DescriptorC= ount)) { + return EFI_INVALID_PARAMETER; + } + + Status =3D SystemFirmwareAuthenticatedUpdate ((VOID *)Image, ImageSize, = &SystemFmpPrivate->LastAttempt.LastAttemptVersion, &SystemFmpPrivate->LastA= ttempt.LastAttemptStatus, Progress); + DEBUG ((DEBUG_INFO, "SetImage - LastAttempt Version - 0x%x, State - 0x%x= \n", SystemFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate->La= stAttempt.LastAttemptStatus)); + + // + // If NVRAM is updated, we should no longer touch variable services, bec= ause + // the current variable driver may not manage the new NVRAM region. + // + if (mNvRamUpdated) { + DEBUG ((DEBUG_INFO, "NvRamUpdated, Update Variable Serivces\n")); + gRT->GetVariable =3D GetVariableHook; + gRT->GetNextVariableName =3D GetNextVariableNameHook; + gRT->SetVariable =3D SetVariableHook; + gRT->QueryVariableInfo =3D QueryVariableInfoHook; + + gRT->Hdr.CRC32 =3D 0; + gBS->CalculateCrc32 ( + (UINT8 *)&gRT->Hdr, + gRT->Hdr.HeaderSize, + &gRT->Hdr.CRC32 + ); + } + + VarStatus =3D gRT->SetVariable ( + SYSTEM_FMP_LAST_ATTEMPT_VARIABLE_NAME, + &gSystemFmpLastAttemptVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_= ACCESS, + sizeof (SystemFmpPrivate->LastAttempt), + &SystemFmpPrivate->LastAttempt + ); + DEBUG ((DEBUG_INFO, "SetLastAttemp - %r\n", VarStatus)); + + return Status; +} + +/** + Get the set of EFI_FIRMWARE_IMAGE_DESCRIPTOR structures from an FMP Prot= ocol. + + @param[in] Handle Handle with an FMP Protocol or a System F= MP + Protocol. + @param[in] ProtocolGuid Pointer to the FMP Protocol GUID or Syste= m FMP + Protocol GUID. + @param[out] FmpImageInfoCount Pointer to the number of + EFI_FIRMWARE_IMAGE_DESCRIPTOR structures. + @param[out] DescriptorSize Pointer to the size, in bytes, of each + EFI_FIRMWARE_IMAGE_DESCRIPTOR structure. + + @return NULL No EFI_FIRMWARE_IMAGE_DESCRIPTOR structures found. + @return !NULL Pointer to a buffer of EFI_FIRMWARE_IMAGE_DESCRIPTOR stru= ctures + allocated using AllocatePool(). Caller must free buffer = with + FreePool(). +**/ +EFI_FIRMWARE_IMAGE_DESCRIPTOR * +GetFmpImageDescriptors ( + IN EFI_HANDLE Handle, + IN EFI_GUID *ProtocolGuid, + OUT UINT8 *FmpImageInfoCount, + OUT UINTN *DescriptorSize + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; + UINTN ImageInfoSize; + EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf; + UINT32 FmpImageInfoDescriptorVer; + UINT32 PackageVersion; + CHAR16 *PackageVersionName; + + *FmpImageInfoCount =3D 0; + *DescriptorSize =3D 0; + + Status =3D gBS->HandleProtocol ( + Handle, + ProtocolGuid, + (VOID **)&Fmp + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // Determine the size required for the set of EFI_FIRMWARE_IMAGE_DESCRIP= TORs. + // + ImageInfoSize =3D 0; + Status =3D Fmp->GetImageInfo ( + Fmp, // FMP Pointer + &ImageInfoSize, // Buffer Size (in th= is case 0) + NULL, // NULL so we can get= size + &FmpImageInfoDescriptorVer, // DescriptorVersion + FmpImageInfoCount, // DescriptorCount + DescriptorSize, // DescriptorSize + &PackageVersion, // PackageVersion + &PackageVersionName // PackageVersionName + ); + if (Status !=3D EFI_BUFFER_TOO_SMALL) { + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Unexpected Failure. St= atus =3D %r\n", Status)); + return NULL; + } + + // + // Allocate buffer for the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs. + // + FmpImageInfoBuf =3D NULL; + FmpImageInfoBuf =3D AllocateZeroPool (ImageInfoSize); + if (FmpImageInfoBuf =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failed to allocate memo= ry for descriptors.\n")); + return NULL; + } + + // + // Retrieve the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs. + // + PackageVersionName =3D NULL; + Status =3D Fmp->GetImageInfo ( + Fmp, + &ImageInfoSize, // ImageInfoSize + FmpImageInfoBuf, // ImageInfo + &FmpImageInfoDescriptorVer, // DescriptorVer= sion + FmpImageInfoCount, // DescriptorCou= nt + DescriptorSize, // DescriptorSize + &PackageVersion, // PackageVersion + &PackageVersionName // PackageVersio= nName + ); + + // + // Free unused PackageVersionName return buffer + // + if (PackageVersionName !=3D NULL) { + FreePool (PackageVersionName); + PackageVersionName =3D NULL; + } + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failure in GetImageInfo= . Status =3D %r\n", Status)); + if (FmpImageInfoBuf !=3D NULL) { + FreePool (FmpImageInfoBuf); + } + + return NULL; + } + + return FmpImageInfoBuf; +} + +/** + Search for handles with an FMP protocol whose EFI_FIRMWARE_IMAGE_DESCRIP= TOR + ImageTypeId matches the ImageTypeId produced by this module. + + @param[in] ProtocolGuid Pointer to the GUID of the protocol to search. + @param[out] HandleCount Pointer to the number of returned handles. + + @return NULL No matching handles found. + @return !NULL Pointer to a buffer of handles allocated using AllocatePo= ol(). + Caller must free buffer with FreePool(). +**/ +EFI_HANDLE * +FindMatchingFmpHandles ( + IN EFI_GUID *ProtocolGuid, + OUT UINTN *HandleCount + ) +{ + EFI_STATUS Status; + UINTN TempHandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + UINTN Index2; + UINTN Index3; + EFI_FIRMWARE_IMAGE_DESCRIPTOR *OriginalFmpImageInfoBuf; + EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf; + UINT8 FmpImageInfoCount; + UINTN DescriptorSize; + BOOLEAN MatchFound; + + *HandleCount =3D 0; + TempHandleCount =3D 0; + HandleBuffer =3D NULL; + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + ProtocolGuid, + NULL, + &TempHandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + for (Index =3D 0; Index < TempHandleCount; Index++) { + OriginalFmpImageInfoBuf =3D GetFmpImageDescriptors ( + HandleBuffer[Index], + ProtocolGuid, + &FmpImageInfoCount, + &DescriptorSize + ); + + // + // Loop through the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs. + // + MatchFound =3D FALSE; + if (OriginalFmpImageInfoBuf !=3D NULL) { + FmpImageInfoBuf =3D OriginalFmpImageInfoBuf; + + for (Index2 =3D 0; Index2 < FmpImageInfoCount; Index2++) { + for (Index3 =3D 0; Index3 < mSystemFmpPrivate->DescriptorCount; In= dex3++) { + MatchFound =3D CompareGuid ( + &FmpImageInfoBuf->ImageTypeId, + &mSystemFmpPrivate->ImageDescriptor[Index3].Image= TypeId + ); + if (MatchFound) { + break; + } + } + + if (MatchFound) { + break; + } + + // + // Increment the buffer pointer ahead by the size of the descriptor + // + FmpImageInfoBuf =3D (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)(((UINT8 *)Fm= pImageInfoBuf) + DescriptorSize); + } + + if (MatchFound) { + HandleBuffer[*HandleCount] =3D HandleBuffer[Index]; + (*HandleCount)++; + } + + FreePool (OriginalFmpImageInfoBuf); + } + } + + if ((*HandleCount) =3D=3D 0) { + // + // No any matching handle. + // + FreePool (HandleBuffer); + return NULL; + } + + return HandleBuffer; +} + +/** + Uninstall System FMP Protocol instances that may have been installed by + SystemFirmwareUpdateDxe drivers dispatches by other capsules. + + @retval EFI_SUCCESS All System FMP Protocols found were uninstalled. + @return Other One or more System FMP Protocols could not be unins= talled. + +**/ +EFI_STATUS +UninstallMatchingSystemFmpProtocols ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_FIRMWARE_MANAGEMENT_PROTOCOL *SystemFmp; + + // + // Uninstall SystemFmpProtocol instances that may have been produced by + // the SystemFirmwareUpdate drivers in FVs dispatched by other capsules. + // + HandleBuffer =3D FindMatchingFmpHandles ( + &gSystemFmpProtocolGuid, + &HandleCount + ); + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Found %d matching System F= MP instances\n", HandleCount)); + + for (Index =3D 0; Index < HandleCount; Index++) { + Status =3D gBS->HandleProtocol ( + HandleBuffer[Index], + &gSystemFmpProtocolGuid, + (VOID **)&SystemFmp + ); + if (EFI_ERROR (Status)) { + continue; + } + + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Uninstall SystemFmp prod= uced by another capsule\n")); + Status =3D gBS->UninstallProtocolInterface ( + HandleBuffer[Index], + &gSystemFmpProtocolGuid, + SystemFmp + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failed to uninstall S= ystemFmp %r. Exiting.\n", Status)); + FreePool (HandleBuffer); + return Status; + } + } + + if (HandleBuffer !=3D NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; +} + +/** + System FMP module entrypoint + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS System FMP module is initialized. + @retval EFI_OUT_OF_RESOURCES There are not enough resources avaulable to + initialize this module. + @retval Other System FMP Protocols could not be uninstal= led. + @retval Other System FMP Protocol could not be installed. + @retval Other FMP Protocol could not be installed. +**/ +EFI_STATUS +EFIAPI +SystemFirmwareUpdateMainDxe ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + + // + // Initialize SystemFmpPrivateData + // + mSystemFmpPrivate =3D AllocateZeroPool (sizeof (SYSTEM_FMP_PRIVATE_DATA)= ); + if (mSystemFmpPrivate =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status =3D InitializePrivateData (mSystemFmpPrivate); + if (EFI_ERROR (Status)) { + FreePool (mSystemFmpPrivate); + mSystemFmpPrivate =3D NULL; + return Status; + } + + // + // Uninstall SystemFmpProtocol instances that may have been produced by + // the SystemFirmwareUpdate drivers in FVs dispatched by other capsules. + // + Status =3D UninstallMatchingSystemFmpProtocols (); + if (EFI_ERROR (Status)) { + FreePool (mSystemFmpPrivate); + mSystemFmpPrivate =3D NULL; + return Status; + } + + // + // Look for a handle with matching Firmware Management Protocol + // + HandleCount =3D 0; + HandleBuffer =3D FindMatchingFmpHandles ( + &gEfiFirmwareManagementProtocolGuid, + &HandleCount + ); + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Found %d matching FMP inst= ances\n", HandleCount)); + + switch (HandleCount) { + case 0: + // + // Install FMP protocol onto a new handle. + // + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Install FMP onto a new= handle\n")); + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &mSystemFmpPrivate->Handle, + &gEfiFirmwareManagementProtocolGuid, + &mSystemFmpPrivate->Fmp, + NULL + ); + break; + case 1: + // + // Install System FMP protocol onto handle with matching FMP Protocol + // + DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Install System FMP ont= o matching FMP handle\n")); + mSystemFmpPrivate->Handle =3D HandleBuffer[0]; + Status =3D gBS->InstallMultipleProtocolInterfaces= ( + &HandleBuffer[0], + &gSystemFmpProtocolGuid, + &mSystemFmpPrivate->Fmp, + NULL + ); + break; + default: + // + // More than one matching handle is not expected. Unload driver. + // + DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: More than one matchin= g FMP handle. Unload driver.\n")); + Status =3D EFI_DEVICE_ERROR; + break; + } + + if (HandleBuffer !=3D NULL) { + FreePool (HandleBuffer); + } + + if (EFI_ERROR (Status)) { + FreePool (mSystemFmpPrivate); + mSystemFmpPrivate =3D NULL; + } + + return Status; +} diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Unive= rsal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.inf b/Platform/AMD/VanGog= hBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/System= FirmwareUpdateDxe.inf new file mode 100644 index 0000000000..aff752007d --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/Sy= stemFirmwareUpdate/SystemFirmwareUpdateDxe.inf @@ -0,0 +1,91 @@ +## @file +# System Firmware Update Dxe +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +## @file +# SystemFirmware FMP update driver. +# +# Produce FMP instance to update system firmware. +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may = be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D SystemFirmwareUpdateDxe + MODULE_UNI_FILE =3D SystemFirmwareUpdateDxe.uni + FILE_GUID =3D 0A2FBD15-1C25-407E-8915-60C5652BC2AA + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D SystemFirmwareUpdateMainDxe + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D X64 +# + +[Sources] + SystemFirmwareDxe.h + SystemFirmwareCommonDxe.c + SystemFirmwareUpdateDxe.c + ParseConfigProfile.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + VanGoghCommonPkg/AmdCommonPkg.dec + SignedCapsulePkg/SignedCapsulePkg.dec + ChachaniBoardPkg/Project.dec + AgesaPublic/AgesaPublic.dec + +[LibraryClasses] + BaseLib + UefiLib + BaseMemoryLib + DebugLib + PcdLib + MemoryAllocationLib + UefiBootServicesTableLib + HobLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + DxeServicesLib + EdkiiSystemCapsuleLib + PlatformFlashAccessLib + IniParsingLib + PrintLib + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSystemFmpCapsuleImageTypeIdGuid = ## CONSUMES + gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareFileGuid = ## CONSUMES + gEfiSignedCapsulePkgTokenSpaceGuid.PcdEdkiiSystemFirmwareImageDescriptor= ## CONSUMES + gPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress = ## CONSUMES + gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize = ## CONSUMES + gPlatformPkgTokenSpaceGuid.PcdFlashAbImageSlotDefaultPriority = ## CONSUMES + +[Guids] + gOtaCapsuleUpdateGuid + gABSupportUpdateIshGuid + +[Protocols] + gEfiFirmwareManagementProtocolGuid ## PRODUCES + +[Depex] + gEfiVariableArchProtocolGuid + +[UserExtensions.TianoCore."ExtraFiles"] + SystemFirmwareUpdateDxeExtra.uni + diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Unive= rsal/SystemFirmwareUpdate/SystemFirmwareUpdateDxe.uni b/Platform/AMD/VanGog= hBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/System= FirmwareUpdateDxe.uni new file mode 100644 index 0000000000..3b96e42e14 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/Sy= stemFirmwareUpdate/SystemFirmwareUpdateDxe.uni @@ -0,0 +1,31 @@ +// /** @file +// SystemFirmwareUpdateDxe Localized Strings and Content +// +// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ +// This file includes code originally published under the following licens= e. + +// /** @file +// SystemFirmware FMP update driver. +// +// Produce FMP instance to update system firmware. +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the B= SD License +// which accompanies this distribution. The full text of the license may = be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "SystemFirmware FM= P update driver." + +#string STR_MODULE_DESCRIPTION #language en-US "Produce FMP insta= nce to update system firmware." diff --git a/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Unive= rsal/SystemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni b/Platform/AMD/V= anGoghBoard/Override/edk2/SignedCapsulePkg/Universal/SystemFirmwareUpdate/S= ystemFirmwareUpdateDxeExtra.uni new file mode 100644 index 0000000000..68206af750 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Override/edk2/SignedCapsulePkg/Universal/Sy= stemFirmwareUpdate/SystemFirmwareUpdateDxeExtra.uni @@ -0,0 +1,30 @@ +// /** @file +// SystemFirmwareUpdateDxeExtra Localized Strings and Content +// +// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ +// This file includes code originally published under the following licens= e. + +// /** @file +// SystemFirmwareUpdateDxe Localized Strings and Content +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the B= SD License +// which accompanies this distribution. The full text of the license may = be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"SystemFirmwareUpdate DXE Driver" + + diff --git a/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/OtaCapsuleU= pdate.h b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/OtaCapsuleUpda= te.h new file mode 100644 index 0000000000..6f10bc9c82 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/VanGoghCommonPkg/Include/OtaCapsuleUpdate.h @@ -0,0 +1,38 @@ +/** @file + Implements OtaCapsuleUpdate.h + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _OTA_CAPSULE_UPDATE_H_ +#define _OTA_CAPSULE_UPDATE_H_ + +#pragma pack (1) +// +// OTA for BIOS Capsule update +// +typedef struct { + UINT8 UpdateFlag; // 0: No update required; 1: update required + UINT8 UpdateSlot; // 0: Slot A; 1: Slot B +} OTA_CAPSULE_UPDATE; + +#pragma pack () + +// +// Variable Name for OTA BIOS Update +// +#define OTA_CAPSULE_VAR_NAME L"OtaCapsuleVar" + +// +// Variable Name for ISH update. (The variable name is ignored in ISH upda= te function) +// +#define ISH_VAR_NAME L"IshVar" + +#define MAX_SLOT_NUM 2 +#define SLOT_A 0 +#define SLOT_B 1 + +#define EFS_LOCATION 0x20000 + +#endif -- 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114071): https://edk2.groups.io/g/devel/message/114071 Mute This Topic: https://groups.io/mt/103831194/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-