From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM11-CO1-obe.outbound.protection.outlook.com (NAM11-CO1-obe.outbound.protection.outlook.com [40.107.220.101]) by mx.groups.io with SMTP id smtpd.web11.4135.1607505890267561965 for ; Wed, 09 Dec 2020 01:24:50 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@os.amperecomputing.com header.s=selector2 header.b=A9Bvl/fJ; spf=pass (domain: os.amperecomputing.com, ip: 40.107.220.101, mailfrom: nhi@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=lS44VRcgSekJZ3HnPEkMSw//XKj7JynPc/Iy3iFlbw4cuxErD/kqAecvJ7rGCPdNyj/ItGErXjpbkaMuStkX1x94JYViiPOv648NyuuZDZC9mEZI1KeAxdbmuSe04EkXvBSL9HCQi30K3xWBtASGUu6FfGPhpcRP+udxEUMVmMRus7fTqH9MK0fCxePYyNi2gJjrl4aHBK6JoGp59uLpxi1ziiEKTBFd/Lo58y5jvB4BbjVtAZDV9pTdsQOcP+VyJdA9H8BQEueWZoDSeKA2yfryIRUBbunQKs28tNkiHoepTAD16gC44iAnqYzcoaCQbZy74y+IJAIDyljUrVKFuw== 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-SenderADCheck; bh=o/LO73WjyZPpJScZDBO6KFgZWB4eHyMMXMUt2hVkzz8=; b=oeQlWQ+cxuA7wBFHhvjHkaAloQFoVLVieZ33X0NsbF/CYeY0IfDYTvQa2zBWEMziyUK4WbLaqMLGWJAsI7x7oyGjpftH5dcd+PfrVBB/ml1rLzfn7pU6O7mg90YuwArK734y+MpZkV+K6jZvPiZDwRza+n0DGnVINv79tP/b/jhTGSiiukGg6X+DjfwgRtD8e417yM9kpTOYm9dfbWOa7yUYZGxmgYC3dASgMNZwOoWJDrtun8UXq4QlZMXg1V1BHhn9j+NB3KSuW1kUVTEFZUx0U1aEVDqAKvKi3jBVaxXZe0aou/RN5WhOEP0PYy+M9WXbNAzY4DgMbW/d7u52og== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=os.amperecomputing.com; dmarc=pass action=none header.from=os.amperecomputing.com; dkim=pass header.d=os.amperecomputing.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=os.amperecomputing.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=o/LO73WjyZPpJScZDBO6KFgZWB4eHyMMXMUt2hVkzz8=; b=A9Bvl/fJGlLakFlhMK9S8ZMx+zxdphDRAnNMvK0TrwVt398BAaXBTjKizMq3j3qeyatIseP8OFyMRaofsu1XpE8Baky9NEBl+abYTxRD0ycEEZR+R8fdmwwxVLDRsE9hCxArUuIG21Ua7licP2zfQ7rJ/QDIod3s4r+7mKIAIfw= Authentication-Results: edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=none action=none header.from=os.amperecomputing.com; Received: from DM6PR01MB5849.prod.exchangelabs.com (2603:10b6:5:205::20) by DM6PR01MB5609.prod.exchangelabs.com (2603:10b6:5:157::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3632.21; Wed, 9 Dec 2020 09:24:48 +0000 Received: from DM6PR01MB5849.prod.exchangelabs.com ([fe80::c814:9a08:5c2e:4076]) by DM6PR01MB5849.prod.exchangelabs.com ([fe80::c814:9a08:5c2e:4076%5]) with mapi id 15.20.3632.023; Wed, 9 Dec 2020 09:24:48 +0000 From: "Nhi Pham" To: devel@edk2.groups.io Cc: Nhi Pham Subject: [edk2-platforms][PATCH 25/34] AmpereAltraPkg: Implement PlatformFlashAccessLib instance Date: Wed, 9 Dec 2020 16:25:22 +0700 Message-Id: <20201209092531.30867-26-nhi@os.amperecomputing.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201209092531.30867-1-nhi@os.amperecomputing.com> References: <20201209092531.30867-1-nhi@os.amperecomputing.com> X-Originating-IP: [118.69.219.201] X-ClientProxiedBy: HK0PR01CA0054.apcprd01.prod.exchangelabs.com (2603:1096:203:a6::18) To DM6PR01MB5849.prod.exchangelabs.com (2603:10b6:5:205::20) Return-Path: nhi@os.amperecomputing.com MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from sw004.amperecomputing.com (118.69.219.201) by HK0PR01CA0054.apcprd01.prod.exchangelabs.com (2603:1096:203:a6::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3654.12 via Frontend Transport; Wed, 9 Dec 2020 09:24:47 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: c525e399-6d95-4dba-117d-08d89c24468b X-MS-TrafficTypeDiagnostic: DM6PR01MB5609: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:9508; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: ANm2D8VPE69Ssx46/c4xcH9vOdtQP1awtZaXnE74ODQhN12tGkH7QiP63Pu9jAMP8iX2jgjA/tScFNkVto3JjfvfNd7OEtrzsGmUwxF4M5FLa6/bu44BgMqFb2ytPBl8mgiWAHout1yWfg/3IX7Xu1DiBqq3RIt5F/IBrwgC1wVTShr8GpdB7y/c0wlpRoB4vNhf2oIbOcDwt9mk1uoW6vVJagfvvlgW9lbBL11HvovjC+WZFtII/4IooCX3SmzjkMjQgzHU3H89ZVnXPfsEsfX1OffBa7LbMQSCs6luPmhNtVY15bpO+n5o2lVpASxgSXj29QENsHnvMSNCFn7z0EXeuBborjN+Io4sGCKAZJ3ZL3PkDiGjDr0OMDOiwXiU X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM6PR01MB5849.prod.exchangelabs.com;PTR:;CAT:NONE;SFS:(4636009)(376002)(136003)(346002)(366004)(5660300002)(956004)(508600001)(52116002)(30864003)(66946007)(6916009)(2616005)(1076003)(86362001)(6512007)(66476007)(26005)(8936002)(16526019)(107886003)(6666004)(186003)(6486002)(8676002)(6506007)(83380400001)(2906002)(34490700003)(66556008)(4326008);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData: =?us-ascii?Q?mqG6sdPn1Dcp8iKwEVbaesX49f+E1yq3qkKkLmVdudbzBQsayMe84xAQtyhz?= =?us-ascii?Q?1eW/jx+sdsz9X3JHCxhNyvw/JsAeyzs3lq1u8u4dV/A4uiQIEZH7NCCsi+Bq?= =?us-ascii?Q?rHmeP7o12WR2R91hOtJErNLsaQGgOm3P03jjofLDOzWg+msXFOTysdl9qy7T?= =?us-ascii?Q?0zGKbN2sc+OBbUVoW4R8nkNSTTS8okVuYn7wSBMzawwzHNBUVmn+eSOGLrrH?= =?us-ascii?Q?WOWSt/W9Tr5rEd3I+chWjqmWTo+DPSNkRMZPRzgfi6GDTjuF+qEsIzxwnFmU?= =?us-ascii?Q?WoKp0jYkDrGXNZ1HyJGlVbh4KGBzoV8TtAe9B0vm5smCfej4dVBr6M+lDg/u?= =?us-ascii?Q?sCWh5M7GdVCekTbQ7No1YOJmnORFvpf4Y2RGlSm3uu5hMB0fF+sFX3p95bOk?= =?us-ascii?Q?K0k8fooCfHoJ0FamQcWOnSpnL5aMYLN6YilYMBr2F2DSp/3cijBTnj/RzNJG?= =?us-ascii?Q?4pv77T1TKLtNyzcFSJAquwN4GCxH+pqyiB0mBsf5xxSW134mvmNRT1y9Zv5q?= =?us-ascii?Q?hcxl+Lh+/xuV4jA1lyuWvHyLyrsMxO7dvns5PbSkNuJEuEBtK6NB1brT95Lr?= =?us-ascii?Q?lu5O4LRIRNaOnkmYBO+y4EWzfKepdfKS25JL66UdJ1nFlUSP/Ql7CP9/7u+d?= =?us-ascii?Q?hzZvhnDe+PGrmn8zCcoAPmY0tXePDbhO6g7hF1CasF8XBYzKnaQSoro9vKdX?= =?us-ascii?Q?tpkaMZJG8WUOKIkoXcO4BR4LyHPJe1l2b88gm4e7LXvLRyfTKjCLjVY5fqKz?= =?us-ascii?Q?rQ/EB0KDFMs2KjO6O2mw8OMGDvIxTpAP47wpSbehO3Y0zKD7FSe5w+OyO5WZ?= =?us-ascii?Q?vHTqHWxs/NFMlQW7GIpybXUWvEYX2R2VW+dWoaQMe71yHPskYCgD/iRlhzA4?= =?us-ascii?Q?IMGEisWVgx9fSqcwb92gimfTlM1N3m4fnUhain1rdxmol4HppdkzeduTl7K6?= =?us-ascii?Q?OEn+lXOetncFkZpWlMxgoxQw/AgZloPEllAlkwlAkFjpYOU5xNlYu4OpVF7u?= =?us-ascii?Q?1mcr?= X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-AuthSource: DM6PR01MB5849.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Dec 2020 09:24:48.8120 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3bc2b170-fd94-476d-b0ce-4229bdc904a7 X-MS-Exchange-CrossTenant-Network-Message-Id: c525e399-6d95-4dba-117d-08d89c24468b X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: fi0U1fLKuAMcPzhrh83MVqnICdvRz2V29/D4Lss+gUDHUueerhuk3dYG8grttY1Aum5/cFl2MbAH8xbgeP+J2gyHXeVq+1gmGS2uhe3mRD4= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR01MB5609 Content-Type: text/plain This library provides API functions to perform flash write operation via Secure UEFI MM interface. The platform flash device is controlled by Arm Trusted Firmware (ATF) in the secure world. UEFI can not write directly an update image to the flash device. So, this instance of PlatformFlashAccessLib is implemented to transfer the update image to ATF secure world via the Firmware Update SMC service. Then that service will proceed the update. Signed-off-by: Nhi Pham --- Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf | 37 +++ Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c | 318 ++++++++++++++++++++ 2 files changed, 355 insertions(+) diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf b/Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf new file mode 100644 index 000000000000..fddc0dfbb916 --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.inf @@ -0,0 +1,37 @@ +## @file +# Platform flash device access library. +# +# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2020, Ampere Computing LLC. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = PlatformFlashAccessLib + FILE_GUID = C2821AC7-331A-48FC-90C2-6660ED40EB25 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformFlashAccessLib|DXE_DRIVER + +[Sources] + PlatformFlashAccessLib.c + +[Packages] + MdePkg/MdePkg.dec + SignedCapsulePkg/SignedCapsulePkg.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + UefiBootServicesTableLib + +[Protocols] + gEfiMmCommunicationProtocolGuid + +[Depex] + TRUE diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c b/Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c new file mode 100644 index 000000000000..ecb08431ac01 --- /dev/null +++ b/Silicon/Ampere/AmpereAltraPkg/Library/PlatformFlashAccessLib/PlatformFlashAccessLib.c @@ -0,0 +1,318 @@ +/** @file + Platform flash device access library. + + Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) 2020, Ampere Computing LLC. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include + +EFI_MM_COMMUNICATION_PROTOCOL *mMmCommunication = NULL; + +#define EFI_MM_MAX_PAYLOAD_U64_E 10 +#define EFI_MM_MAX_PAYLOAD_SIZE (EFI_MM_MAX_PAYLOAD_U64_E * sizeof (UINT64)) + +/* FWU MM GUID */ +STATIC CONST EFI_GUID mFwuMmGuid = { 0x452240CD, 0xB3B3, 0x4695, { 0x9A, 0x63, 0xDF, 0xEC, 0x50, 0x82, 0xE7, 0x7A } }; + +typedef struct { + /* Allows for disambiguation of the message format */ + EFI_GUID HeaderGuid; + /* + * Describes the size of Data (in bytes) and does not include the size + * of the header + */ + UINTN MsgLength; +} EFI_MM_COMM_HEADER_NOPAYLOAD; + +typedef struct { + UINT64 Data[EFI_MM_MAX_PAYLOAD_U64_E]; +} EFI_MM_COMM_FWU_PAYLOAD; + +typedef struct { + EFI_MM_COMM_HEADER_NOPAYLOAD EfiMmHdr; + EFI_MM_COMM_FWU_PAYLOAD PayLoad; +} EFI_MM_COMM_REQUEST; + +EFI_MM_COMM_REQUEST mEfiMmSysFwuReq; + +typedef struct { + UINT64 Status; + UINT64 Progress; +} EFI_MM_COMMUNICATE_FWU_RES; + +#define FWU_MM_RES_SUCCESS 0xAABBCC00 +#define FWU_MM_RES_IN_PROGRESS 0xAABBCC01 +#define FWU_MM_RES_SECURITY_VIOLATION 0xAABBCC02 +#define FWU_MM_RES_OUT_OF_RESOURCES 0xAABBCC03 +#define FWU_MM_RES_IO_ERROR 0xAABBCC04 +#define FWU_MM_RES_FAIL 0xAABBCCFF + +/* + * The ARM Trusted Firmware (ATF) defined image types to support updating + * various firmware via SMC Firmware Update service. + * The value of definition here must be the same in ATF code. + */ +#define FWU_IMG_TYPE_INVALID 0 +#define FWU_IMG_TYPE_ATFBIOS 2 // ARM Trusted Firmware and UEFI Image +#define FWU_IMG_TYPE_MAX 5 + +/* + * According to PLATFORM_FIRMWARE_TYPE, + * Type 0x80000000 ~ 0xFFFFFFFF is reserved for OEM. + * A type of firmware image is determined by FirmwareType value + * in the Configuration of Firmware Update. + * Formula: FirmwareType = ImageType + 0x80000000 + */ +#define FIRMWARE_TYPE_OEM_OFFSET 0x80000000 + +/* + * Size of Firmware Descriptor File Volume + */ +#define FIRMWARE_DESCRIPTOR_SIZE 0x10000 + +VOID +UefiMmCreateSysFwuReq ( + VOID *Data, + UINT64 Size + ) +{ + CopyGuid (&mEfiMmSysFwuReq.EfiMmHdr.HeaderGuid, &mFwuMmGuid); + mEfiMmSysFwuReq.EfiMmHdr.MsgLength = Size; + + if (Size != 0) { + ASSERT (Data != NULL); + ASSERT (Size <= EFI_MM_MAX_PAYLOAD_SIZE); + + CopyMem (&mEfiMmSysFwuReq.PayLoad.Data, Data, Size); + } +} + +EFI_STATUS +MmFlashUpdate ( + IN UINT32 ImageType, + IN VOID *FirmwareImage, + IN UINT64 ImageSize, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, + IN UINTN StartPercentage, + IN UINTN EndPercentage + ) +{ + EFI_MM_COMMUNICATE_FWU_RES *MmFwuStatus; + UINTN ProgressUpdate = StartPercentage; + UINTN Size; + UINT64 MmData[5]; + EFI_STATUS Status; + + if (FirmwareImage == NULL) { + DEBUG ((DEBUG_ERROR, "%a:%d Invalid inputs.\n", __FUNCTION__, __LINE__)); + return EFI_INVALID_PARAMETER; + } + + DEBUG ((DEBUG_INFO, "%a:%d Image: %p Size 0x%lx\n", + __FUNCTION__, __LINE__, FirmwareImage, ImageSize)); + + if (mMmCommunication == NULL) { + Status = gBS->LocateProtocol( + &gEfiMmCommunicationProtocolGuid, + NULL, + (VOID **) &mMmCommunication); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Can't locate gEfiMmCommunicationProtocolGuid.\n", __FUNCTION__)); + return Status; + } + } + + MmData[0] = ImageType; + MmData[1] = ImageSize; + MmData[2] = (UINT64) FirmwareImage; + MmData[3] = 1; // MM yield for progress reporting. + + while (TRUE) { + UefiMmCreateSysFwuReq ((VOID *) &MmData, sizeof (MmData)); + + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); + Status = mMmCommunication->Communicate ( + mMmCommunication, + (VOID *) &mEfiMmSysFwuReq, + &Size + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a:%d MM communication error - %r\n", + __FUNCTION__, __LINE__, Status)); + return EFI_DEVICE_ERROR; + } + + /* Return data in the first double word of payload */ + MmFwuStatus = (EFI_MM_COMMUNICATE_FWU_RES *) mEfiMmSysFwuReq.PayLoad.Data; + if (MmFwuStatus->Status == FWU_MM_RES_IN_PROGRESS) { + if (NULL != Progress) { + Progress (ProgressUpdate); + } + + ProgressUpdate = StartPercentage + + (((EndPercentage - StartPercentage) * (MmFwuStatus->Progress)) / 100); + continue; + } + break; + } + + switch (MmFwuStatus->Status) { + case FWU_MM_RES_SUCCESS: + if (NULL != Progress) { + Progress (EndPercentage); + } + Status = EFI_SUCCESS; + break; + + case FWU_MM_RES_SECURITY_VIOLATION: + DEBUG ((DEBUG_ERROR, "%a:%d Failed to update - Security Violation!\n", + __FUNCTION__, __LINE__)); + Status = EFI_SECURITY_VIOLATION; + break; + + case FWU_MM_RES_OUT_OF_RESOURCES: + DEBUG ((DEBUG_ERROR, "%a:%d Failed to update - Insufficient resources!\n", + __FUNCTION__, __LINE__)); + Status = EFI_OUT_OF_RESOURCES; + break; + + case FWU_MM_RES_IO_ERROR: + DEBUG ((DEBUG_ERROR, "%a:%d Failed to update - IO Error!\n", + __FUNCTION__, __LINE__)); + Status = EFI_DEVICE_ERROR; + break; + + default: + DEBUG ((DEBUG_ERROR, "%a:%d Failed to update - Unknown Error!\n", + __FUNCTION__, __LINE__)); + Status = EFI_INVALID_PARAMETER; + break; + } + + return Status; +} + +/** + Perform flash write operation with progress indicator. The start and end + completion percentage values are passed into this function. If the requested + flash write operation is broken up, then completion percentage between the + start and end values may be passed to the provided Progress function. The + caller of this function is required to call the Progress function for the + start and end completion percentage values. This allows the Progress, + StartPercentage, and EndPercentage parameters to be ignored if the requested + flash write operation can not be broken up + + @param[in] FirmwareType The type of firmware. + @param[in] FlashAddress The address of flash device to be accessed. + @param[in] FlashAddressType The type of flash device address. + @param[in] Buffer The pointer to the data buffer. + @param[in] Length The length of data buffer in bytes. + @param[in] Progress A function used report the progress of the + firmware update. This is an optional parameter + that may be NULL. + @param[in] StartPercentage The start completion percentage value 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 operation returns successfully. + @retval EFI_WRITE_PROTECTED The flash device is read only. + @retval EFI_UNSUPPORTED The flash device access is unsupported. + @retval EFI_INVALID_PARAMETER The input parameter is not valid. +**/ +EFI_STATUS +EFIAPI +PerformFlashWriteWithProgress ( + IN PLATFORM_FIRMWARE_TYPE FirmwareType, + IN EFI_PHYSICAL_ADDRESS FlashAddress, + IN FLASH_ADDRESS_TYPE FlashAddressType, + IN VOID *Buffer, + IN UINTN Length, + IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL + IN UINTN StartPercentage, + IN UINTN EndPercentage + ) +{ + UINT32 ImageType; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + /* + * As per the design of firmware capsule, the Firmware Descriptor File + * Volume which is used to provide description of firmware update is + * attached at the beginning of the firmware file. It must be removed + * before writing. + */ + if (Length <= FIRMWARE_DESCRIPTOR_SIZE) { + DEBUG ((DEBUG_ERROR, "%a %d The length of firmware image is invalid.\n", + __FUNCTION__, __LINE__)); + return EFI_INVALID_PARAMETER; + } + Length -= FIRMWARE_DESCRIPTOR_SIZE; + Buffer += FIRMWARE_DESCRIPTOR_SIZE; + + ImageType = FirmwareType - FIRMWARE_TYPE_OEM_OFFSET; + if (ImageType >= FWU_IMG_TYPE_MAX) { + return EFI_INVALID_PARAMETER; + } + + return MmFlashUpdate ( + ImageType, + Buffer, + Length, + Progress, + StartPercentage, + EndPercentage + ); +} + +/** + Perform flash write operation. + + @param[in] FirmwareType The type of firmware. + @param[in] FlashAddress The address of flash device to be accessed. + @param[in] FlashAddressType The type of flash device address. + @param[in] Buffer The pointer to the data buffer. + @param[in] Length The length of data buffer in bytes. + + @retval EFI_SUCCESS The operation returns successfully. + @retval EFI_WRITE_PROTECTED The flash device is read only. + @retval EFI_UNSUPPORTED The flash device access is unsupported. + @retval EFI_INVALID_PARAMETER The input parameter is not valid. +**/ +EFI_STATUS +EFIAPI +PerformFlashWrite ( + IN PLATFORM_FIRMWARE_TYPE FirmwareType, + IN EFI_PHYSICAL_ADDRESS FlashAddress, + IN FLASH_ADDRESS_TYPE FlashAddressType, + IN VOID *Buffer, + IN UINTN Length + ) +{ + return PerformFlashWriteWithProgress ( + FirmwareType, + FlashAddress, + FlashAddressType, + Buffer, + Length, + NULL, + 0, + 0 + ); +} -- 2.17.1