From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by spool.mail.gandi.net (Postfix) with ESMTPS id D4B53941CEF for ; Thu, 14 Mar 2024 19:38:31 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=y7e3BK33DgZ3MFlsjzOBjyR3RhzqI4W3MjakxfUqB3A=; c=relaxed/simple; d=groups.io; h=From:Message-Id:Mime-Version:Subject:Date:In-Reply-To:Cc:To:References:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Resent-Date:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Type; s=20240206; t=1710445110; v=1; b=2XjWD2n3swHsteHAlJ9pfUCH1q0O8va+jy4vOZM6ryPsPQ1yb4fh4zZcRuADvfDo8DCVRItD IzqHtMu/gBArr7FntOhyKBJmQ2YK6Wim0hwM3nNLPoVL5mTZYNVzLOc69ldHZiCk1ZWHJZVwuEV 6xhLiYvsaAp4b0AKdzKax1K+R6eFeYYCjoCzjCeJDcxdRlYXgRhdNZ1zkonvPuVCL/EEjdUPlrM qywgeeo9L1OF0zn7cJg240KrUAPbpGD/qlB+IzUtyiDtQrSLxzlcgXDuM87qOBHtl0Q9cTyJ7rr 3KVVXrJDzm20zt610ozj9M8P7KryRqazDLl6n4tnk+fqA== X-Received: by 127.0.0.2 with SMTP id Bk0IYY7687511x7Tj4UAMplq; Thu, 14 Mar 2024 12:38:30 -0700 X-Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) by mx.groups.io with SMTP id smtpd.web10.2015.1710445108903488991 for ; Thu, 14 Mar 2024 12:38:29 -0700 X-Received: by mail-wr1-f46.google.com with SMTP id ffacd0b85a97d-33ec8f13d36so724777f8f.1 for ; Thu, 14 Mar 2024 12:38:28 -0700 (PDT) X-Gm-Message-State: vViuQu7ZxLWEcyw5f4XYNfkCx7686176AA= X-Google-Smtp-Source: AGHT+IGFwXiboVy39cSvoCO+FTOJ1PZ/SNWoVVvFYjCamTUe+l9cH2l5JCERROOxK0dT4eFouNDu+w== X-Received: by 2002:a5d:5348:0:b0:33e:c2ed:7898 with SMTP id t8-20020a5d5348000000b0033ec2ed7898mr891742wrv.54.1710445106517; Thu, 14 Mar 2024 12:38:26 -0700 (PDT) X-Received: from smtpclient.apple ([195.158.249.30]) by smtp.gmail.com with ESMTPSA id w10-20020adff9ca000000b0033e72e104c5sm1405916wrr.34.2024.03.14.12.38.24 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 14 Mar 2024 12:38:26 -0700 (PDT) From: "Mike Maslenkin" Message-Id: <517B1BB3-9433-4C68-80F3-46BBC1627671@gmail.com> Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3696.100.31\)) Subject: Re: [edk2-devel] [edk2-redfish-client][PATCH 1/2] RedfishClientPkg/Features: support Redfish Secure Boot Date: Thu, 14 Mar 2024 22:38:22 +0300 In-Reply-To: <20240314145300.153086-1-nicklew@nvidia.com> Cc: Abner Chang , Igor Kulchytskyy , Nick Ramirez To: devel@edk2.groups.io, Nickle Wang References: <20240314145300.153086-1-nicklew@nvidia.com> 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 Resent-Date: Thu, 14 Mar 2024 12:38:29 -0700 Reply-To: devel@edk2.groups.io,mike.maslenkin@gmail.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: Content-Type: multipart/alternative; boundary="Apple-Mail=_B03079E5-1E32-477E-9A61-1AAAE6D98DF8" X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20240206 header.b=2XjWD2n3; dmarc=fail reason="SPF not aligned (relaxed), DKIM not aligned (relaxed)" header.from=gmail.com (policy=none); spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce@groups.io --Apple-Mail=_B03079E5-1E32-477E-9A61-1AAAE6D98DF8 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii Hi Nickle, please find my comments below > On 14. 3. 2024., at 17:53, Nickle Wang via groups.io = > wrote: >=20 > Introduce SecureBoot driver to support > /redfish/v1/Systems/SYS/SecureBoot resource. >=20 > Signed-off-by: Nickle Wang > > Cc: Abner Chang > > Cc: Igor Kulchytskyy > > Cc: Nick Ramirez > > --- > .../RedfishClientComponents.dsc.inc | 2 + > RedfishClientPkg/RedfishClientLibs.dsc.inc | 4 + > .../SecureBoot/v1_1_0/Dxe/SecureBootDxe.inf | 60 ++ > .../v1_1_0/Common/SecureBootCommon.h | 40 + > .../v1_1_0/Common/SecureBootCommon.c | 756 ++++++++++++++++ > .../SecureBoot/v1_1_0/Dxe/SecureBootDxe.c | 808 ++++++++++++++++++ > RedfishClientPkg/RedfishClient.fdf.inc | 1 + > 7 files changed, 1671 insertions(+) > create mode 100644 RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/Secure= BootDxe.inf > create mode 100644 RedfishClientPkg/Features/SecureBoot/v1_1_0/Common/Sec= ureBootCommon.h > create mode 100644 RedfishClientPkg/Features/SecureBoot/v1_1_0/Common/Sec= ureBootCommon.c > create mode 100644 RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/Secure= BootDxe.c >=20 > diff --git a/RedfishClientPkg/RedfishClientComponents.dsc.inc b/RedfishCl= ientPkg/RedfishClientComponents.dsc.inc > index ae2a4b025..42fc0c299 100644 > --- a/RedfishClientPkg/RedfishClientComponents.dsc.inc > +++ b/RedfishClientPkg/RedfishClientComponents.dsc.inc > @@ -34,6 +34,7 @@ > RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.inf > RedfishClientPkg/Features/BootOptionCollection/BootOptionCollectionDxe.= inf > RedfishClientPkg/Features/BootOption/v1_0_4/Dxe/BootOptionDxe.inf > + RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/SecureBootDxe.inf >=20 > !include RedfishClientPkg/RedfishJsonStructureDxe.dsc.inc >=20 > @@ -47,3 +48,4 @@ > RedfishClientPkg/Converter/Bios/v1_0_9/RedfishBios_V1_0_9_Dxe.inf > RedfishClientPkg/Converter/BootOptionCollection/RedfishBootOptionCollec= tion_Dxe.inf > RedfishClientPkg/Converter/BootOption/v1_0_4/RedfishBootOption_V1_0_4_D= xe.inf > + RedfishClientPkg/Converter/SecureBoot/v1_1_0/RedfishSecureBoot_V1_1_0_= Dxe.inf > diff --git a/RedfishClientPkg/RedfishClientLibs.dsc.inc b/RedfishClientPk= g/RedfishClientLibs.dsc.inc > index 6599926ab..9126465df 100644 > --- a/RedfishClientPkg/RedfishClientLibs.dsc.inc > +++ b/RedfishClientPkg/RedfishClientLibs.dsc.inc > @@ -25,6 +25,8 @@ > BiosV1_0_9Lib|RedfishClientPkg/ConverterLib/edk2library/Bios/v1_0_9/Lib= .inf > BootOptionCollectionLib|RedfishClientPkg/ConverterLib/edk2library/BootO= ptionCollection/Lib.inf > BootOptionV1_0_4Lib|RedfishClientPkg/ConverterLib/edk2library/BootOptio= n/v1_0_4/Lib.inf > + SecureBootV1_1_0Lib|RedfishClientPkg/ConverterLib/edk2library/SecureBo= ot/v1_1_0/Lib.inf > + > # > # Above modules should be pulled in by build tool. > # > @@ -42,3 +44,5 @@ > RedfishAddendumLib|RedfishClientPkg/Library/RedfishAddendumLib/RedfishA= ddendumLib.inf > RedfishDebugLib|RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.inf > RedfishHttpLib|RedfishPkg/Library/RedfishHttpLib/RedfishHttpLib.inf > + SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/Secure= BootVariableLib.inf > + PlatformPKProtectionLib|SecurityPkg/Library/PlatformPKProtectionLibVar= Policy/PlatformPKProtectionLibVarPolicy.inf > diff --git a/RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/SecureBootDx= e.inf b/RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/SecureBootDxe.inf > new file mode 100644 > index 000000000..1ad8c623f > --- /dev/null > +++ b/RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/SecureBootDxe.inf > @@ -0,0 +1,60 @@ > +## @file > +# > +# (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP
> +# Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights = reserved. > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > + > +[Defines] > + INF_VERSION =3D 0x00010005 > + BASE_NAME =3D SecureBootDxe > + FILE_GUID =3D 5E4025F8-DA42-468A-853E-6A1091D35052 > + MODULE_TYPE =3D DXE_DRIVER > + VERSION_STRING =3D 1.0 > + ENTRY_POINT =3D RedfishResourceEntryPoint > + UNLOAD_IMAGE =3D RedfishResourceUnload > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + SecurityPkg/SecurityPkg.dec > + RedfishPkg/RedfishPkg.dec > + RedfishClientPkg/RedfishClientPkg.dec > + > +[Sources] > + ../Common/SecureBootCommon.h > + ../Common/SecureBootCommon.c > + SecureBootDxe.c > + > +[LibraryClasses] > + BaseMemoryLib > + DebugLib > + EdkIIRedfishResourceConfigLib > + RedfishFeatureUtilityLib > + RedfishVersionLib > + RedfishResourceIdentifyLib > + SecureBootVariableLib > + UefiLib > + UefiDriverEntryPoint > + RedfishAddendumLib > + UefiRuntimeServicesTableLib > + > +[Protocols] > + gEdkIIRedfishConfigHandlerProtocolGuid ## PRODUCED > + gEfiRestJsonStructureProtocolGuid ## CONSUMED > + gEdkIIRedfishResourceConfigProtocolGuid ## PRODUCED > + gEdkIIRedfishFeatureProtocolGuid ## CONSUMED > + > +[Guids] > + gEfiSecureBootEnableDisableGuid ## CONSUMED > + > +[Pcd] > + gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaStringSize > + gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaVersionSize > + gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishSystemRebootRequired > + > +[Depex] > + TRUE > diff --git a/RedfishClientPkg/Features/SecureBoot/v1_1_0/Common/SecureBoo= tCommon.h b/RedfishClientPkg/Features/SecureBoot/v1_1_0/Common/SecureBootCo= mmon.h > new file mode 100644 > index 000000000..0d1824160 > --- /dev/null > +++ b/RedfishClientPkg/Features/SecureBoot/v1_1_0/Common/SecureBootCommon= .h > @@ -0,0 +1,40 @@ > +/** @file > + > + Redfish feature driver implementation - internal header file > + (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP
> + Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights r= eserved. > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef EFI_REDFISH_SECUREBOOT_COMMON_H_ > +#define EFI_REDFISH_SECUREBOOT_COMMON_H_ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +// > +// Schema information. > +// > +#define REDFISH_MANAGED_URI L"Systems/{}/SecureBoot" > +#define REDFISH_DUMMY_CONFIG_LANG L"Systems/{1}/SecureBoot" > +#define MAX_URI_LENGTH 256 > +#define RESOURCE_SCHEMA "SecureBoot" > +#define RESOURCE_SCHEMA_MAJOR "1" > +#define RESOURCE_SCHEMA_MINOR "1" > +#define RESOURCE_SCHEMA_ERRATA "0" > +#define RESOURCE_SCHEMA_VERSION "v1_1_0" > +#define SECURE_BOOT_SETUP_MODE "SetupMode" > +#define SECURE_BOOT_USER_MODE "UserMode" > +#define SECURE_BOOT_ENABLED "Enabled" > +#define SECURE_BOOT_DISABLED "Disabled" > +#define SECURE_BOOT_MODE_STR_LEN 16 > + > +#endif > diff --git a/RedfishClientPkg/Features/SecureBoot/v1_1_0/Common/SecureBoo= tCommon.c b/RedfishClientPkg/Features/SecureBoot/v1_1_0/Common/SecureBootCo= mmon.c > new file mode 100644 > index 000000000..56a45ee72 > --- /dev/null > +++ b/RedfishClientPkg/Features/SecureBoot/v1_1_0/Common/SecureBootCommon= .c > @@ -0,0 +1,756 @@ > +/** @file > + Redfish feature driver implementation - common functions > + > + (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP
> + Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights r= eserved. > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "SecureBootCommon.h" > + > +CHAR8 SecureBootEmptyJson[] =3D "{\"@odata.id \": \"\= ", \"@odata.type\": \"#SecureBoot.v1_1_0.SecureBoot\", \"Id\": \"\", \"Name= \": \"\", \"Attributes\":{}}"; > + > +REDFISH_RESOURCE_COMMON_PRIVATE *mRedfishResourcePrivate = =3D NULL; > +EFI_HANDLE mRedfishResourceConfigProtocolHandle = =3D NULL; > +CHAR16 *mSecureBootSupportedAttributes[SECURE_= BOOT_MODE_STR_LEN] =3D { > + L"SecureBootCurrentBoot", > + L"SecureBootEnable", > + L"SecureBootMode" > +}; > + > +/** > + Read EFI_SECURE_BOOT_ENABLE_NAME variable and return its value to call= er. > + > + @retval BOOLEAN TRUE when EFI_SECURE_BOOT_ENABLE_NAME value is SECU= RE_BOOT_ENABLE > + FALSE when EFI_SECURE_BOOT_ENABLE_NAME value is SEC= URE_BOOT_DISABLE > +**/ > +BOOLEAN > +RedfishReadSecureBootEnable ( > + VOID > + ) > +{ > + UINT8 *Buffer; > + BOOLEAN SecureBootEnableValue; > + > + Buffer =3D NULL; > + SecureBootEnableValue =3D FALSE; > + > + GetVariable2 ( > + EFI_SECURE_BOOT_ENABLE_NAME, > + &gEfiSecureBootEnableDisableGuid, > + (VOID **)&Buffer, > + NULL > + ); > + > + if (Buffer !=3D NULL) { > + if (*Buffer =3D=3D SECURE_BOOT_ENABLE) { > + SecureBootEnableValue =3D TRUE; > + } > + > + FreePool (Buffer); > + } > + > + return SecureBootEnableValue; > +} > + > +/** > + Write EFI_SECURE_BOOT_ENABLE_NAME variable with given value. > + > + @param[in] SecureBootEnableValue Value to write. TRUE is SECURE_B= OOT_ENABLE. > + FALSE is SECURE_BOOT_DISABLE. > + > + @retval EFI_SUCCESS Write value successfully. > + @retval Others Some error happened. > +**/ > +EFI_STATUS > +RedfishWriteSecureBootEnable ( > + BOOLEAN SecureBootEnableValue > + ) > +{ > + EFI_STATUS Status; > + UINT8 VarValue; > + > + VarValue =3D (SecureBootEnableValue ? SECURE_BOOT_ENABLE : SECURE_BOOT= _DISABLE); > + Status =3D gRT->SetVariable ( > + EFI_SECURE_BOOT_ENABLE_NAME, > + &gEfiSecureBootEnableDisableGuid, > + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE= _ACCESS, > + sizeof (VarValue), > + &VarValue > + ); > + > + return Status; > +} > + > +/** > + Consume Redfish resource in given Json data. > + > + @param[in] This Pointer to REDFISH_RESOURCE_COMMON_PR= IVATE instance. > + @param[in] Json The JSON to consume. > + @param[in] HeaderEtag The Etag string returned in HTTP head= er. > + > + @retval EFI_SUCCESS Consume Redfish attribute successfull= y. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +RedfishConsumeResourceCommon ( > + IN REDFISH_RESOURCE_COMMON_PRIVATE *Private, > + IN CHAR8 *Json, > + IN CHAR8 *HeaderEtag OPTIONAL > + ) > +{ > + EFI_STATUS Status; > + EFI_REDFISH_SECUREBOOT_V1_1_0 *SecureBoot; > + EFI_REDFISH_SECUREBOOT_V1_1_0_CS *SecureBootCs; > + BOOLEAN SecureBootEnableDisable; > + > + if ((Private =3D=3D NULL) || IS_EMPTY_STRING (Json)) { > + return EFI_INVALID_PARAMETER; > + } > + > + SecureBoot =3D NULL; > + SecureBootCs =3D NULL; > + SecureBootEnableDisable =3D RedfishReadSecureBootEnable (); > + > + Status =3D Private->JsonStructProtocol->ToStructure ( > + Private->JsonStructProtocol, > + NULL, > + Json, > + (EFI_REST_JSON_STRUCTURE_HEADE= R **)&SecureBoot > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: ToStructure() failed: %r\n", __func__, Sta= tus)); > + return Status; > + } > + > + SecureBootCs =3D SecureBoot->SecureBoot; > + > + // > + // Check ETAG to see if we need to consume it > + // > + if (CheckEtag (Private->Uri, HeaderEtag, SecureBootCs->odata_etag)) { > + // > + // No change > + // > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: ETAG: %s has no change, ignore con= sume action\n", __func__, Private->Uri)); > + Status =3D EFI_ALREADY_STARTED; > + goto ON_RELEASE; > + } > + > + // > + // Secure boot enable > + // > + if (SecureBootCs->SecureBootEnable !=3D NULL) { > + if (SecureBootEnableDisable !=3D *SecureBootCs->SecureBootEnable) { > + // > + // Write value to "SecureBootEnable" variable. AuthVariableLib wil= l enable or disable secure boot > + // based on "SecureBootEnable" value. > + // > + Status =3D RedfishWriteSecureBootEnable (*SecureBootCs->SecureBoot= Enable); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: write secure boot enable disable faile= d: %r\n", __func__, Status)); > + } else { > + REDFISH_ENABLE_SYSTEM_REBOOT (); > + } > + } else { > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: secure boot mode is not changed\= n", __func__)); > + } > + } > + > +ON_RELEASE: > + > + // > + // Release resource. > + // > + Private->JsonStructProtocol->DestoryStructure ( > + Private->JsonStructProtocol, > + (EFI_REST_JSON_STRUCTURE_HEADER *)Secur= eBoot > + ); > + > + return EFI_SUCCESS; > +} > + > +/** > + Provision Redfish resource. This function reads secure boot variable a= nd convert it > + to Redfish attribute. > + > + @param[in] JsonStructProtocol Pointer to Json structure protocol. > + @param[in] InputJson Jason data on input. > + @param[in] ResourceId Resource ID. This is optional. > + @param[in] ConfigureLang Configure language for this Redfish r= esource. > + @param[in] ProvisionMode TRUE when this is to provision Redfis= h attribute to > + Redfish service. FALSE is to update R= edfish attribute > + to Redfish service. > + @param[out] ResultJson Json data on output. > + > + @retval EFI_SUCCESS Provision Redfish attribute successfu= lly. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +ProvisioningSecureBootProperties ( > + IN EFI_REST_JSON_STRUCTURE_PROTOCOL *JsonStructProtocol, > + IN CHAR8 *InputJson, > + IN CHAR8 *ResourceId OPTIONAL, > + IN EFI_STRING ConfigureLang, > + IN BOOLEAN ProvisionMode, > + OUT CHAR8 **ResultJson > + ) > +{ > + EFI_REDFISH_SECUREBOOT_V1_1_0 *SecureBoot; > + EFI_REDFISH_SECUREBOOT_V1_1_0_CS *SecureBootCs; > + EFI_STATUS Status; > + BOOLEAN PropertyChanged; > + CHAR8 *AsciiStringValue; > + INT32 *IntegerValue; > + UINT8 SetupMode; > + BOOLEAN SecureBootEnabled; > + BOOLEAN SecureBootEnableDisable; > + > + if ((JsonStructProtocol =3D=3D NULL) || (ResultJson =3D=3D NULL) || IS= _EMPTY_STRING (InputJson) || IS_EMPTY_STRING (ConfigureLang)) { > + return EFI_INVALID_PARAMETER; > + } > + > + DEBUG ((REDFISH_DEBUG_TRACE, "%a provision for %s with: %s\n", __func_= _, ConfigureLang, (ProvisionMode ? L"Provision resource" : L"Update resourc= e"))); > + > + *ResultJson =3D NULL; > + PropertyChanged =3D FALSE; > + AsciiStringValue =3D NULL; > + SecureBootEnableDisable =3D RedfishReadSecureBootEnable (); > + SecureBootEnabled =3D IsSecureBootEnabled (); > + > + SecureBoot =3D NULL; > + Status =3D JsonStructProtocol->ToStructure ( > + JsonStructProtocol, > + NULL, > + InputJson, > + (EFI_REST_JSON_STRUCTURE_HEADER **)= &SecureBoot > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: ToStructure failure: %r\n", __func__, Stat= us)); > + return Status; > + } > + > + SecureBootCs =3D SecureBoot->SecureBoot; > + > + // > + // ID > + // > + if (SecureBootCs->Id !=3D NULL) { > + SecureBootCs->Id =3D NULL; > + } > + > + // > + // Name > + // > + if (SecureBootCs->Name !=3D NULL) { > + SecureBootCs->Name =3D NULL; > + } > + > + // > + // Secure boot variables that we will handle here > + // > + // EFI_SETUP_MODE_NAME (gEfiGlobalVariableGuid) > + // EFI_SECURE_BOOT_MODE_NAME (gEfiGlobalVariableGuid) > + // EFI_SECURE_BOOT_ENABLE_NAME (gEfiSecureBootEnableDisableGuid) > + // > + > + // > + // Current Boot > + // > + if (PropertyChecker (SecureBootCs->SecureBootCurrentBoot, ProvisionMod= e)) { > + AsciiStringValue =3D AllocateZeroPool (SECURE_BOOT_MODE_STR_LEN * si= zeof (CHAR8)); > + if (AsciiStringValue !=3D NULL) { > + AsciiSPrint (AsciiStringValue, SECURE_BOOT_MODE_STR_LEN, "%a", (Se= cureBootEnabled ? SECURE_BOOT_ENABLED : SECURE_BOOT_DISABLED)); > + if (ProvisionMode || (AsciiStrCmp (SecureBootCs->SecureBootCurrent= Boot, AsciiStringValue) !=3D 0)) { > + SecureBootCs->SecureBootCurrentBoot =3D AsciiStringValue; > + PropertyChanged =3D TRUE; > + } > + } else { > + DEBUG ((DEBUG_ERROR, "%a: out of resource\n", __func__)); > + } > + } > + > + // > + // Secure boot enable > + // > + if (PropertyChecker (SecureBootCs->SecureBootEnable, ProvisionMode)) { > + if (ProvisionMode || (*SecureBootCs->SecureBootEnable !=3D SecureBoo= tEnableDisable)) { > + IntegerValue =3D AllocatePool (sizeof (*IntegerValue)); > + if (IntegerValue !=3D NULL) { > + *IntegerValue =3D (SecureBootEnableDisable ? 0x= 01 : 0x00); > + SecureBootCs->SecureBootEnable =3D IntegerValue; > + PropertyChanged =3D TRUE; > + } else { > + DEBUG ((DEBUG_ERROR, "%a: out of resource\n", __func__)); > + } > + } > + } > + > + // > + // Secure boot mode > + // > + if (PropertyChecker (SecureBootCs->SecureBootMode, ProvisionMode)) { > + Status =3D GetSetupMode (&SetupMode); > + if (!EFI_ERROR (Status)) { > + AsciiStringValue =3D AllocateZeroPool (SECURE_BOOT_MODE_STR_LEN *s= izeof (CHAR8)); > + if (AsciiStringValue !=3D NULL) { > + AsciiSPrint (AsciiStringValue, SECURE_BOOT_MODE_STR_LEN *sizeof = (CHAR8), "%a", (SetupMode =3D=3D USER_MODE ? SECURE_BOOT_USER_MODE : SECURE= _BOOT_SETUP_MODE)); > + if (ProvisionMode || (AsciiStrCmp (SecureBootCs->SecureBootMode,= AsciiStringValue) !=3D 0)) { > + SecureBootCs->SecureBootMode =3D AsciiStringValue; > + PropertyChanged =3D TRUE; > + } > + } > + } else { > + DEBUG ((DEBUG_ERROR, "%a: cannot read setup mode: %r\n", __func__,= Status)); > + } > + } > + > + // > + // Convert C structure back to JSON text. > + // > + Status =3D JsonStructProtocol->ToJson ( > + JsonStructProtocol, > + (EFI_REST_JSON_STRUCTURE_HEADER *)Secur= eBoot, > + ResultJson > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: ToJson() failed: %r\n", __func__, Status))= ; > + return Status; SecureBoot structure leak. It is released below. > + } > + > + // > + // Release resource. > + // > + JsonStructProtocol->DestoryStructure ( > + JsonStructProtocol, > + (EFI_REST_JSON_STRUCTURE_HEADER *)SecureBoot > + ); > + > + return (PropertyChanged ? EFI_SUCCESS : EFI_NOT_FOUND); > +} > + > +/** > + Provision Redfish resource and upload data to Redfish service. This fu= nction > + checks OEM data and platform addendum data before sending data to Redf= ish service. > + > + @param[in] Private Pointer to private data. > + > + @retval EFI_SUCCESS Provision Redfish resource successful= ly. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +ProvisioningSecureBootResource ( > + IN REDFISH_RESOURCE_COMMON_PRIVATE *Private > + ) > +{ > + EFI_STATUS Status; > + CHAR8 *Json; > + CHAR8 *JsonWithAddendum; > + REDFISH_RESPONSE Response; > + > + if (Private =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); > + Json =3D NULL; > + > + Status =3D ProvisioningSecureBootProperties ( > + Private->JsonStructProtocol, > + SecureBootEmptyJson, > + NULL, > + REDFISH_DUMMY_CONFIG_LANG, > + TRUE, > + &Json > + ); > + if (EFI_ERROR (Status)) { > + if (Status =3D=3D EFI_NOT_FOUND) { > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: provisioning existing resource f= or %s ignored. Nothing changed\n", __func__, REDFISH_DUMMY_CONFIG_LANG)); > + Status =3D EFI_SUCCESS; > + } else { > + DEBUG ((DEBUG_ERROR, "%a: provisioning existing resource for %s fa= iled: %r\n", __func__, REDFISH_DUMMY_CONFIG_LANG, Status)); > + } > + > + goto ON_RELEASE; > + } > + > + // > + // Check and see if platform has OEM data or not > + // > + Status =3D RedfishGetOemData ( > + Private->Uri, > + RESOURCE_SCHEMA, > + RESOURCE_SCHEMA_VERSION, > + Json, > + &JsonWithAddendum > + ); > + if (!EFI_ERROR (Status) && (JsonWithAddendum !=3D NULL)) { > + FreePool (Json); > + Json =3D JsonWithAddendum; > + JsonWithAddendum =3D NULL; > + } > + > + // > + // Check and see if platform has addendum data or not > + // > + Status =3D RedfishGetAddendumData ( > + Private->Uri, > + RESOURCE_SCHEMA, > + RESOURCE_SCHEMA_VERSION, > + Json, > + &JsonWithAddendum > + ); > + if (!EFI_ERROR (Status) && (JsonWithAddendum !=3D NULL)) { > + FreePool (Json); > + Json =3D JsonWithAddendum; > + JsonWithAddendum =3D NULL; > + } > + > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: provisioning existing resource for %= s\n", __func__, REDFISH_DUMMY_CONFIG_LANG)); > + > + // > + // PATCH back to instance > + // > + Status =3D RedfishHttpPatchResource (Private->RedfishService, Private-= >Uri, Json, &Response); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: patch resource for %s failed: %r\n", __fun= c__, REDFISH_DUMMY_CONFIG_LANG, Status)); > + } > + > +ON_RELEASE: > + > + if (Json !=3D NULL) { > + FreePool (Json); > + } > + > + RedfishHttpFreeResponse (&Response); > + > + return Status; > +} > + > +/** > + Provisioning redfish resource to Redfish service. > + > + @param[in] Private Pointer to private data. > + @param[in] ResourceExist TRUE if resource exists, PUT method w= ill be used. > + FALSE if resource does not exist POST= method is used. Actually ProvisioningSecureBootResource uses PATCH only. > + > + @retval EFI_SUCCESS Provision resource successfully. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +RedfishProvisioningResourceCommon ( > + IN REDFISH_RESOURCE_COMMON_PRIVATE *Private, > + IN BOOLEAN ResourceExist > + ) > +{ > + if (Private =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + return ProvisioningSecureBootResource (Private); > +} > + > +/** > + Check resource from given Json data. > + > + @param[in] This Pointer to REDFISH_RESOURCE_COMMON_PR= IVATE instance. > + @param[in] Json The JSON data to check. > + @param[in] HeaderEtag The Etag string returned in HTTP head= er. > + > + @retval EFI_SUCCESS Check resource successfully. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +RedfishCheckResourceCommon ( > + IN REDFISH_RESOURCE_COMMON_PRIVATE *Private, > + IN CHAR8 *Json, > + IN CHAR8 *HeaderEtag OPTIONAL > + ) > +{ > + UINTN Index; > + EFI_STATUS Status; > + UINTN Count; > + EFI_STRING Property; > + > + if ((Private =3D=3D NULL) || IS_EMPTY_STRING (Json)) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Check ETAG to see if we need to check it > + // > + if (CheckEtag (Private->Uri, HeaderEtag, NULL)) { > + // > + // No change > + // > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: ETAG: %s has no change, ignore che= ck action\n", __func__, Private->Uri)); > + return EFI_SUCCESS; > + } > + > + Count =3D sizeof (mSecureBootSupportedAttributes) / sizeof (mSecureBoo= tSupportedAttributes[0]); > + if (Count =3D=3D 0) { > + return EFI_UNSUPPORTED; > + } > + > + Status =3D EFI_SUCCESS; > + for (Index =3D 0; Index < Count; Index++) { > + Property =3D mSecureBootSupportedAttributes[Index]; > + if (Property =3D=3D NULL) { > + continue; > + } > + > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: [%d] check attribute for: %s\n", _= _func__, Index, Property)); > + if (!MatchPropertyWithJsonContext (Property, Json)) { > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: property is missing: %s\n", __fu= nc__, Property)); > + Status =3D EFI_NOT_FOUND; > + } > + } > + > + return Status; > +} > + > +/** > + Update resource to Redfish service. > + > + @param[in] Private Pointer to REDFISH_RESOURCE_COMMON_PR= IVATE instance. > + @param[in] Json The JSON data to be updated. > + > + @retval EFI_SUCCESS Update resource successfully. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +RedfishUpdateResourceCommon ( > + IN REDFISH_RESOURCE_COMMON_PRIVATE *Private, > + IN CHAR8 *InputJson > + ) > +{ > + EFI_STATUS Status; > + CHAR8 *Json; > + CHAR8 *JsonWithAddendum; > + REDFISH_RESPONSE Response; > + > + if ((Private =3D=3D NULL) || IS_EMPTY_STRING (InputJson)) { > + return EFI_INVALID_PARAMETER; > + } > + > + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); > + Json =3D NULL; > + > + Status =3D ProvisioningSecureBootProperties ( > + Private->JsonStructProtocol, > + SecureBootEmptyJson, > + NULL, > + REDFISH_DUMMY_CONFIG_LANG, > + TRUE, > + &Json > + ); > + if (EFI_ERROR (Status)) { > + if (Status =3D=3D EFI_NOT_FOUND) { > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: update resource for %s ignored. = Nothing changed\n", __func__, REDFISH_DUMMY_CONFIG_LANG)); > + Status =3D EFI_SUCCESS; > + } else { > + DEBUG ((DEBUG_ERROR, "%a: update resource for %s failed: %r\n", __= func__, REDFISH_DUMMY_CONFIG_LANG, Status)); > + } > + > + goto ON_RELEASE; > + } > + > + // > + // Check and see if platform has OEM data or not > + // > + Status =3D RedfishGetOemData ( > + Private->Uri, > + RESOURCE_SCHEMA, > + RESOURCE_SCHEMA_VERSION, > + Json, > + &JsonWithAddendum > + ); > + if (!EFI_ERROR (Status) && (JsonWithAddendum !=3D NULL)) { > + FreePool (Json); > + Json =3D JsonWithAddendum; > + JsonWithAddendum =3D NULL; > + } > + > + // > + // Check and see if platform has addendum data or not > + // > + Status =3D RedfishGetAddendumData ( > + Private->Uri, > + RESOURCE_SCHEMA, > + RESOURCE_SCHEMA_VERSION, > + Json, > + &JsonWithAddendum > + ); > + if (!EFI_ERROR (Status) && (JsonWithAddendum !=3D NULL)) { > + FreePool (Json); > + Json =3D JsonWithAddendum; > + JsonWithAddendum =3D NULL; > + } > + > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: update resource for %s\n", __func__,= REDFISH_DUMMY_CONFIG_LANG)); > + > + // > + // PATCH back to instance > + // > + Status =3D RedfishHttpPatchResource (Private->RedfishService, Private-= >Uri, Json, &Response); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: patch resource for %s failed: %r\n", __fun= c__, REDFISH_DUMMY_CONFIG_LANG, Status)); > + } > + > +ON_RELEASE: > + > + if (Json !=3D NULL) { > + FreePool (Json); > + } > + > + RedfishHttpFreeResponse (&Response); > + > + return Status; > +} > + > +/** > + Identify resource in given Json data. > + > + @param[in] Private Pointer to REDFISH_RESOURCE_COMMON_PR= IVATE instance. > + @param[in] Json The JSON to be identified. > + > + @retval EFI_SUCCESS Identify resource successfully. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +RedfishIdentifyResourceCommon ( > + IN REDFISH_RESOURCE_COMMON_PRIVATE *Private, > + IN CHAR8 *Json > + ) > +{ > + BOOLEAN Supported; > + > + Supported =3D RedfishIdentifyResource (Private->Uri, Private->Json); > + if (Supported) { > + // > + // Keep URI and ConfigLang mapping > + // > + RedfishSetRedfishUri (REDFISH_DUMMY_CONFIG_LANG, Private->Uri); > + } > + > + return (Supported ? EFI_SUCCESS : EFI_UNSUPPORTED); > +} > + > +/** > + Handle Redfish resource in Uri. > + > + @param[in] Private Pointer to REDFISH_RESOURCE_COMMON_PR= IVATE instance. > + @param[in] Uri URI to Redfish resource that we like = to process. > + > + @retval EFI_SUCCESS Handle resource successfully. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +HandleResource ( > + IN REDFISH_RESOURCE_COMMON_PRIVATE *Private, > + IN EFI_STRING Uri > + ) > +{ > + EFI_STATUS Status; > + REDFISH_SCHEMA_INFO SchemaInfo; > + EFI_STRING ConfigLang; > + > + if ((Private =3D=3D NULL) || IS_EMPTY_STRING (Uri)) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Resource match > + // > + > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: process resource for: %s\n", __func_= _, Uri)); > + > + Status =3D GetRedfishSchemaInfo (Private->RedfishService, Private->Jso= nStructProtocol, Uri, NULL, &SchemaInfo); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to get schema information from: %s = %r\n", __func__, Uri, Status)); > + return Status; > + } > + > + // > + // Check and see if this is target resource that we want to handle. > + // Some resource is handled by other provider so we have to make sure = this first. > + // > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: Identify for %s\n", __func__, Uri)); > + ConfigLang =3D RedfishGetConfigLanguage (Uri); > + if (ConfigLang =3D=3D NULL) { > + Status =3D EdkIIRedfishResourceConfigIdentify (&SchemaInfo, Uri, NUL= L, Private->InformationExchange); > + if (EFI_ERROR (Status)) { > + if (Status =3D=3D EFI_UNSUPPORTED) { > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: \"%s\" is not handled by us\n"= , __func__, Uri)); > + return EFI_SUCCESS; > + } else if (Status =3D=3D EFI_NOT_FOUND) { > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: \"%s\" has nothing to handle\n= ", __func__, Uri)); > + return EFI_SUCCESS; > + } > + > + DEBUG ((DEBUG_ERROR, "%a: fail to identify resource: \"%s\": %r\n"= , __func__, Uri, Status)); > + return Status; > + } > + } else { > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: history record found: %s\n", __fun= c__, ConfigLang)); > + FreePool (ConfigLang); > + } > + > + // > + // Check and see if target property exist or not even when collection = member exists. > + // If not, we sill do provision. %s/sill/still > + // > + DEBUG ((REDFISH_DEBUG_TRACE, "%a Check for %s\n", __func__, Uri)); > + Status =3D EdkIIRedfishResourceConfigCheck (&SchemaInfo, Uri, NULL); > + if (EFI_ERROR (Status)) { > + if (Status =3D=3D EFI_UNSUPPORTED) { > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: \"%s\" is not handled by us\n", = __func__, Uri)); > + return EFI_SUCCESS; > + } > + > + // > + // The target property does not exist, do the provision to create pr= operty. > + // > + DEBUG ((REDFISH_DEBUG_TRACE, "%a provision for %s\n", __func__, Uri)= ); > + Status =3D EdkIIRedfishResourceConfigProvisioning (&SchemaInfo, Uri,= NULL, Private->InformationExchange, FALSE); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to provision with GET mode: %r\n"= , __func__, Status)); > + } > + > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: process resource for: %s finished\= n", __func__, Uri)); > + > + return Status; > + } > + > + // > + // Consume first. > + // > + DEBUG ((REDFISH_DEBUG_TRACE, "%a consume for %s\n", __func__, Uri)); > + Status =3D EdkIIRedfishResourceConfigConsume (&SchemaInfo, Uri, NULL); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to consume resource for: %s: %r\n",= __func__, Uri, Status)); > + } > + > + // > + // Patch. > + // > + DEBUG ((REDFISH_DEBUG_TRACE, "%a update for %s\n", __func__, Uri)); > + Status =3D EdkIIRedfishResourceConfigUpdate (&SchemaInfo, Uri, NULL); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to update resource for: %s: %r\n", = __func__, Uri, Status)); > + } > + > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: process resource for: %s finished\n"= , __func__, Uri)); > + > + return Status; > +} > diff --git a/RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/SecureBootDx= e.c b/RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/SecureBootDxe.c > new file mode 100644 > index 000000000..a0f4f3d14 > --- /dev/null > +++ b/RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/SecureBootDxe.c > @@ -0,0 +1,808 @@ > +/** @file > + Redfish feature driver implementation - SecureBoot > + > + (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP
> + Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserv= ed. > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "../Common/SecureBootCommon.h" > + > +extern REDFISH_RESOURCE_COMMON_PRIVATE *mRedfishResourcePrivate; > +extern EFI_HANDLE mRedfishResourceConfigProtocolHa= ndle; > + > +EFI_STATUS > +HandleResource ( > + IN REDFISH_RESOURCE_COMMON_PRIVATE *Private, > + IN EFI_STRING Uri > + ); > + > +/** > + Provisioning redfish resource by given URI. > + > + @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCO= L instance. > + @param[in] Uri Target URI to create resource. > + @param[in] PostMode TRUE if the resource does not exist, = post method is used. > + FALSE if the resource exist but prope= rty is missing, put method is used. > + > + @retval EFI_SUCCESS Value is returned successfully. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +EFIAPI > +RedfishResourceProvisioningResource ( > + IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This, > + IN EFI_STRING Uri, > + IN BOOLEAN PostMode > + ) > +{ > + REDFISH_RESOURCE_COMMON_PRIVATE *Private; > + EFI_STATUS Status; > + REDFISH_RESPONSE Response; > + > + if ((This =3D=3D NULL) || IS_EMPTY_STRING (Uri)) { > + return EFI_INVALID_PARAMETER; > + } > + > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: provisioning in %s mode\n", __func__= , (PostMode ? L"POST" : L"PATCH"))); This message conflicts with PostMode parameter description. > + > + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); > + Private =3D REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTOCO= L (This); > + > + if (Private->RedfishService =3D=3D NULL) { > + return EFI_NOT_READY; > + } > + > + Status =3D RedfishHttpGetResource (Private->RedfishService, Uri, NULL,= &Response, TRUE); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: get resource from: %s failed\n", __func__,= Uri)); > + return Status; > + } > + > + Private->Uri =3D Uri; > + Private->Payload =3D Response.Payload; > + ASSERT (Private->Payload !=3D NULL); > + > + Status =3D RedfishProvisioningResourceCommon (Private, !PostMode); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to provision resource to: %s: %r\n"= , __func__, Uri, Status)); > + } else { > + // > + // Get latest ETag on URI and keep it in variable. > + // > + SetEtagFromUri (Private->RedfishService, Private->Uri, TRUE); > + } > + > + // > + // Release resource > + // > + RedfishHttpFreeResponse (&Response); > + Private->Payload =3D NULL; > + > + return Status; > +} > + > +/** > + Consume resource from given URI. > + > + @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCO= L instance. > + @param[in] Uri The target URI to consume. > + > + @retval EFI_SUCCESS Value is returned successfully. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +EFIAPI > +RedfishResourceConsumeResource ( > + IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This, > + IN EFI_STRING Uri > + ) > +{ > + REDFISH_RESOURCE_COMMON_PRIVATE *Private; > + EFI_STATUS Status; > + REDFISH_RESPONSE Response; > + EFI_STRING PendingSettingUri; > + REDFISH_RESPONSE PendingSettingResponse; > + REDFISH_RESPONSE *ExpectedResponse; > + CHAR8 *Etag; > + > + if ((This =3D=3D NULL) || IS_EMPTY_STRING (Uri)) { > + return EFI_INVALID_PARAMETER; > + } > + > + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); > + ZeroMem (&PendingSettingResponse, sizeof (REDFISH_RESPONSE)); > + Private =3D REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTOCO= L (This); > + > + if (Private->RedfishService =3D=3D NULL) { > + return EFI_NOT_READY; > + } > + > + Status =3D RedfishHttpGetResource (Private->RedfishService, Uri, NULL,= &Response, TRUE); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: get resource from: %s failed\n", __func__,= Uri)); > + return Status; > + } > + > + // > + // Check and see if "@Redfish.Settings" exist or not. > + // > + PendingSettingUri =3D NULL; > + Status =3D GetPendingSettings ( > + Private->RedfishService, > + Response.Payload, > + &PendingSettingResponse, > + &PendingSettingUri > + ); > + if (!EFI_ERROR (Status)) { > + DEBUG ((REDFISH_DEBUG_TRACE, "%a: @Redfish.Settings found: %s\n", __= func__, PendingSettingUri)); > + Private->Uri =3D PendingSettingUri; > + ExpectedResponse =3D &PendingSettingResponse; > + } else { > + Private->Uri =3D Uri; > + ExpectedResponse =3D &Response; > + } > + > + Private->Payload =3D ExpectedResponse->Payload; > + ASSERT (Private->Payload !=3D NULL); > + > + Private->Json =3D JsonDumpString (RedfishJsonInPayload (Private->Paylo= ad), EDKII_JSON_COMPACT); > + ASSERT (Private->Json !=3D NULL); > + > + // > + // Searching for etag in HTTP response header > + // > + Etag =3D NULL; > + Status =3D GetHttpResponseEtag (ExpectedResponse, &Etag); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __= func__)); > + } > + > + Status =3D RedfishConsumeResourceCommon (Private, Private->Json, Etag)= ; > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to consume resource from: %s: %r\n"= , __func__, Private->Uri, Status)); > + } > + > + // > + // Release resource > + // > + RedfishHttpFreeResponse (&Response); > + RedfishHttpFreeResponse (&PendingSettingResponse); > + Private->Payload =3D NULL; > + > + if (Private->Json !=3D NULL) { > + FreePool (Private->Json); > + Private->Json =3D NULL; > + } > + > + if (Etag !=3D NULL) { > + FreePool (Etag); > + } > + > + if (PendingSettingUri !=3D NULL) { > + FreePool (PendingSettingUri); > + } > + > + return Status; > +} > + > +/** > + Get information about this protocol. > + > + @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCO= L instance. > + @param[out] Schema Supported schema. > + @param[out] Major Supported major number. > + @param[out] Minor Supported minor number. > + @param[out] Errata Supported errata number. > + > + @retval EFI_SUCCESS Value is returned successfully. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +EFIAPI > +RedfishResourceGetInfo ( > + IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This, > + OUT REDFISH_SCHEMA_INFO *Info > + ) > +{ > + if ((This =3D=3D NULL) || (Info =3D=3D NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + AsciiStrCpyS (Info->Schema, REDFISH_SCHEMA_STRING_SIZE, RESOURCE_SCHEM= A); > + AsciiStrCpyS (Info->Major, REDFISH_SCHEMA_VERSION_SIZE, RESOURCE_SCHEM= A_MAJOR); > + AsciiStrCpyS (Info->Minor, REDFISH_SCHEMA_VERSION_SIZE, RESOURCE_SCHEM= A_MINOR); > + AsciiStrCpyS (Info->Errata, REDFISH_SCHEMA_VERSION_SIZE, RESOURCE_SCHE= MA_ERRATA); > + > + return EFI_SUCCESS; > +} > + > +/** > + Update resource to given URI. > + > + @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCO= L instance. > + @param[in] Uri The target URI to consume. > + > + @retval EFI_SUCCESS Value is returned successfully. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +EFIAPI > +RedfishResourceUpdate ( > + IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This, > + IN EFI_STRING Uri > + ) > +{ > + REDFISH_RESOURCE_COMMON_PRIVATE *Private; > + EFI_STATUS Status; > + REDFISH_RESPONSE Response; > + > + if ((This =3D=3D NULL) || IS_EMPTY_STRING (Uri)) { > + return EFI_INVALID_PARAMETER; > + } > + > + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); > + Private =3D REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTOCO= L (This); > + > + if (Private->RedfishService =3D=3D NULL) { > + return EFI_NOT_READY; > + } > + > + Status =3D RedfishHttpGetResource (Private->RedfishService, Uri, NULL,= &Response, TRUE); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: get resource from: %s failed\n", __func__,= Uri)); > + return Status; > + } > + > + Private->Uri =3D Uri; > + Private->Payload =3D Response.Payload; > + ASSERT (Private->Payload !=3D NULL); > + > + Private->Json =3D JsonDumpString (RedfishJsonInPayload (Private->Paylo= ad), EDKII_JSON_COMPACT); > + ASSERT (Private->Json !=3D NULL); > + > + Status =3D RedfishUpdateResourceCommon (Private, Private->Json); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to update resource to: %s: %r\n", _= _func__, Uri, Status)); > + } else { > + // > + // Get latest ETag on URI and keep it in variable. > + // > + SetEtagFromUri (Private->RedfishService, Private->Uri, TRUE); > + } > + > + // > + // Release resource > + // > + RedfishHttpFreeResponse (&Response); > + Private->Payload =3D NULL; > + > + if (Private->Json !=3D NULL) { > + FreePool (Private->Json); > + Private->Json =3D NULL; > + } > + > + return Status; > +} > + > +/** > + Check resource on given URI. > + > + @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCO= L instance. > + @param[in] Uri The target URI to consume. > + > + @retval EFI_SUCCESS Value is returned successfully. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +EFIAPI > +RedfishResourceCheck ( > + IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This, > + IN EFI_STRING Uri > + ) > +{ > + REDFISH_RESOURCE_COMMON_PRIVATE *Private; > + EFI_STATUS Status; > + REDFISH_RESPONSE Response; > + CHAR8 *Etag; > + > + if ((This =3D=3D NULL) || IS_EMPTY_STRING (Uri)) { > + return EFI_INVALID_PARAMETER; > + } > + > + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); > + Private =3D REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTOCO= L (This); > + > + if (Private->RedfishService =3D=3D NULL) { > + return EFI_NOT_READY; > + } > + > + Status =3D RedfishHttpGetResource (Private->RedfishService, Uri, NULL,= &Response, TRUE); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: get resource from: %s failed\n", __func__,= Uri)); > + return Status; > + } > + > + Private->Uri =3D Uri; > + Private->Payload =3D Response.Payload; > + ASSERT (Private->Payload !=3D NULL); > + > + Private->Json =3D JsonDumpString (RedfishJsonInPayload (Private->Paylo= ad), EDKII_JSON_COMPACT); > + ASSERT (Private->Json !=3D NULL); > + > + // > + // Find etag in HTTP response header > + // > + Etag =3D NULL; > + Status =3D GetHttpResponseEtag (&Response, &Etag); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __= func__)); > + } > + > + Status =3D RedfishCheckResourceCommon (Private, Private->Json, Etag); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to check resource from: %s: %r\n", = __func__, Uri, Status)); > + } > + > + // > + // Release resource > + // > + if (Etag !=3D NULL) { > + FreePool (Etag); > + } > + > + RedfishHttpFreeResponse (&Response); > + Private->Payload =3D NULL; > + > + if (Private->Json !=3D NULL) { > + FreePool (Private->Json); > + Private->Json =3D NULL; > + } > + > + return Status; > +} > + > +/** > + Identify resource on given URI. > + > + @param[in] This Pointer to EDKII_REDFISH_RESOURCE_CON= FIG_PROTOCOL instance. > + @param[in] Uri The target URI to consume. > + > + @retval EFI_SUCCESS This is target resource which we want= to handle. > + @retval EFI_UNSUPPORTED This is not the target resource. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +EFIAPI > +RedfishResourceIdentify ( > + IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This, > + IN EFI_STRING Uri > + ) > +{ > + REDFISH_RESOURCE_COMMON_PRIVATE *Private; > + EFI_STATUS Status; > + REDFISH_RESPONSE Response; > + > + if ((This =3D=3D NULL) || IS_EMPTY_STRING (Uri)) { > + return EFI_INVALID_PARAMETER; > + } > + > + ZeroMem (&Response, sizeof (REDFISH_RESPONSE)); > + Private =3D REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTOCO= L (This); > + > + if (Private->RedfishService =3D=3D NULL) { > + return EFI_NOT_READY; > + } > + > + Status =3D RedfishHttpGetResource (Private->RedfishService, Uri, NULL,= &Response, TRUE); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: get resource from: %s failed\n", __func__,= Uri)); > + return Status; > + } > + > + Private->Uri =3D Uri; > + Private->Payload =3D Response.Payload; > + ASSERT (Private->Payload !=3D NULL); > + > + Private->Json =3D JsonDumpString (RedfishJsonInPayload (Private->Paylo= ad), EDKII_JSON_COMPACT); > + ASSERT (Private->Json !=3D NULL); > + > + Status =3D RedfishIdentifyResourceCommon (Private, Private->Json); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: identify %s failed: %r\n", __func__, Uri, = Status)); > + } > + > + // > + // Release resource > + // > + RedfishHttpFreeResponse (&Response); > + Private->Payload =3D NULL; > + > + if (Private->Json !=3D NULL) { > + FreePool (Private->Json); > + Private->Json =3D NULL; > + } > + > + return Status; > +} > + > +EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL mRedfishResourceConfig =3D { > + RedfishResourceProvisioningResource, > + RedfishResourceConsumeResource, > + RedfishResourceUpdate, > + RedfishResourceCheck, > + RedfishResourceIdentify, > + RedfishResourceGetInfo > +}; > + > +/** > + Initialize a Redfish configure handler. > + > + This function will be called by the Redfish config driver to initializ= e each Redfish configure > + handler. > + > + @param[in] This Pointer to EDKII_REDFISH_CONFIG_= HANDLER_PROTOCOL instance. > + @param[in] RedfishConfigServiceInfo Redfish service information. > + > + @retval EFI_SUCCESS The handler has been initialized = successfully. > + @retval EFI_DEVICE_ERROR Failed to create or configure the= REST EX protocol instance. > + @retval EFI_ALREADY_STARTED This handler has already been ini= tialized. > + @retval Other Error happens during the initiali= zation. > + > +**/ > +EFI_STATUS > +EFIAPI > +RedfishResourceInit ( > + IN EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *This, > + IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo > + ) > +{ > + REDFISH_RESOURCE_COMMON_PRIVATE *Private; > + > + Private =3D REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_CONFIG_PROTOCOL = (This); > + > + Private->RedfishService =3D RedfishCreateService (RedfishConfigService= Info); > + if (Private->RedfishService =3D=3D NULL) { > + return EFI_DEVICE_ERROR; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Stop a Redfish configure handler. > + > + @param[in] This Pointer to EDKII_REDFISH_CONFIG_HANDL= ER_PROTOCOL instance. > + > + @retval EFI_SUCCESS This handler has been stoped successf= ully. > + @retval Others Some error happened. > + > +**/ > +EFI_STATUS > +EFIAPI > +RedfishResourceStop ( > + IN EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *This > + ) > +{ > + REDFISH_RESOURCE_COMMON_PRIVATE *Private; > + > + Private =3D REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_CONFIG_PROTOCOL = (This); > + > + if (Private->Event !=3D NULL) { > + gBS->CloseEvent (Private->Event); > + Private->Event =3D NULL; > + } > + > + if (Private->RedfishService !=3D NULL) { > + RedfishCleanupService (Private->RedfishService); > + Private->RedfishService =3D NULL; > + } > + > + return EFI_SUCCESS; > +} > + > +EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL mRedfishConfigHandler =3D { > + RedfishResourceInit, > + RedfishResourceStop > +}; > + > +/** > + Callback function when gEfiRestJsonStructureProtocolGuid is installed. > + > + @param[in] Event Event whose notification function is being invoked= . > + @param[in] Context Pointer to the notification function's context. > +**/ > +VOID > +EFIAPI > +EfiRestJsonStructureProtocolIsReady ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + EFI_STATUS Status; > + > + if (mRedfishResourcePrivate =3D=3D NULL) { > + return; > + } > + > + if (mRedfishResourcePrivate->JsonStructProtocol !=3D NULL) { > + return; > + } > + > + Status =3D gBS->LocateProtocol ( > + &gEfiRestJsonStructureProtocolGuid, > + NULL, > + (VOID **)&mRedfishResourcePrivate->JsonStructProtocol > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to locate gEfiRestJsonStructureProt= ocolGuid: %r\n", __func__, Status)); > + } > + > + gBS->CloseEvent (Event); > +} > + > +/** > + Unloads an image. > + > + @param ImageHandle Handle that identifies the image to be u= nloaded. > + > + @retval EFI_SUCCESS The image has been unloaded. > + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle. > + > +**/ > +EFI_STATUS > +EFIAPI > +RedfishResourceUnload ( > + IN EFI_HANDLE ImageHandle > + ) > +{ > + EFI_STATUS Status; > + EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *ConfigHandler; > + > + if (mRedfishResourcePrivate =3D=3D NULL) { > + return EFI_NOT_READY; > + } > + > + ConfigHandler =3D NULL; > + > + // > + // Firstly, find ConfigHandler Protocol interface in this ImageHandle. > + // > + Status =3D gBS->OpenProtocol ( > + ImageHandle, > + &gEdkIIRedfishConfigHandlerProtocolGuid, > + (VOID **)&ConfigHandler, > + NULL, > + NULL, > + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL > + ); > + if (EFI_ERROR (Status) || (ConfigHandler =3D=3D NULL)) { > + return Status; > + } > + > + ConfigHandler->Stop (ConfigHandler); > + > + // > + // Last, uninstall ConfigHandler Protocol and resource protocol. > + // > + Status =3D gBS->UninstallMultipleProtocolInterfaces ( > + ImageHandle, > + &gEdkIIRedfishConfigHandlerProtocolGuid, > + ConfigHandler, > + &gEdkIIRedfishResourceConfigProtocolGuid, > + &mRedfishResourcePrivate->RedfishResourceConfig, > + NULL > + ); > + > + FreePool (mRedfishResourcePrivate); > + mRedfishResourcePrivate =3D NULL; > + > + return Status; > +} > + > +/** > + The callback function provided by Redfish Feature driver. > + > + @param[in] This Pointer to EDKII_REDFISH_FEATURE_PR= OTOCOL instance. > + @param[in] FeatureAction The action Redfish feature driver s= hould take. > + @param[in] Uri The collection URI. > + @param[in] Context The context of Redfish feature driv= er. > + @param[in,out] InformationExchange The pointer to RESOURCE_INFORMATION= _EXCHANGE > + > + @retval EFI_SUCCESS Redfish feature driver callback is ex= ecuted successfully. > + @retval Others Some errors happened. > + > + @retval EFI_SUCCESS Redfish feature driver callback is ex= ecuted successfully. > + @retval Others Some errors happened. > + > +**/ > +EFI_STATUS > +EFIAPI > +RedfishExternalResourceResourceFeatureCallback ( > + IN EDKII_REDFISH_FEATURE_PROTOCOL *This, > + IN FEATURE_CALLBACK_ACTION FeatureAction, > + IN VOID *Context, > + IN OUT RESOURCE_INFORMATION_EXCHANGE *InformationExchange > + ) > +{ > + EFI_STATUS Status; > + REDFISH_SERVICE RedfishService; > + REDFISH_RESOURCE_COMMON_PRIVATE *Private; > + EFI_STRING ResourceUri; > + EFI_STRING SecureBootUri; > + > + if (FeatureAction !=3D CallbackActionStartOperation) { > + return EFI_UNSUPPORTED; > + } > + > + Private =3D (REDFISH_RESOURCE_COMMON_PRIVATE *)Context; > + > + RedfishService =3D Private->RedfishService; > + if (RedfishService =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a: no Redfish service configured\n", __func__= )); > + return EFI_NOT_READY; > + } > + > + // > + // Save in private structure. > + // > + Private->InformationExchange =3D InformationExchange; > + > + // > + // Find Redfish version on Redfish ser > + // > + Private->RedfishVersion =3D RedfishGetVersion (RedfishService); > + > + // > + // Create the full URI from Redfish service root. > + // > + ResourceUri =3D (EFI_STRING)AllocateZeroPool (MAX_URI_LENGTH * sizeof = (CHAR16)); > + if (ResourceUri =3D=3D NULL) { > + DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for full URI.\n", = __func__)); > + return EFI_OUT_OF_RESOURCES; > + } > + > + StrCatS (ResourceUri, MAX_URI_LENGTH, Private->RedfishVersion); > + StrCatS (ResourceUri, MAX_URI_LENGTH, InformationExchange->SendInforma= tion.FullUri); > + > + // > + // Initialize collection path > + // > + SecureBootUri =3D RedfishGetUri (ResourceUri); > + if (SecureBootUri =3D=3D NULL) { > + ASSERT (FALSE); > + FreePool (ResourceUri); > + return EFI_OUT_OF_RESOURCES; > + } > + > + Status =3D HandleResource (Private, SecureBootUri); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: process external resource: %s failed: %r\n= ", __func__, SecureBootUri, Status)); > + } > + > + FreePool (SecureBootUri); > + FreePool (ResourceUri); > + return Status; > +} > + > +/** > + Callback function when gEdkIIRedfishFeatureProtocolGuid is installed. > + > + @param[in] Event Event whose notification function is being invoked= . > + @param[in] Context Pointer to the notification function's context. > +**/ > +VOID > +EFIAPI > +EdkIIRedfishFeatureProtocolIsReady ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + EFI_STATUS Status; > + EDKII_REDFISH_FEATURE_PROTOCOL *FeatureProtocol; > + > + if (mRedfishResourcePrivate =3D=3D NULL) { > + return; > + } > + > + if (mRedfishResourcePrivate->FeatureProtocol !=3D NULL) { > + return; > + } > + > + Status =3D gBS->LocateProtocol ( > + &gEdkIIRedfishFeatureProtocolGuid, > + NULL, > + (VOID **)&FeatureProtocol > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to locate gEdkIIRedfishFeatureProto= colGuid: %r\n", __func__, Status)); > + gBS->CloseEvent (Event); > + return; > + } > + > + Status =3D FeatureProtocol->Register ( > + FeatureProtocol, > + REDFISH_MANAGED_URI, > + RedfishExternalResourceResourceFeatureCall= back, > + (VOID *)mRedfishResourcePrivate > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to register %s: %r\n", __func__, RE= DFISH_MANAGED_URI, Status)); > + } > + > + mRedfishResourcePrivate->FeatureProtocol =3D FeatureProtocol; > + > + gBS->CloseEvent (Event); > +} > + > +/** > + This is the declaration of an EFI image entry point. This entry point = is > + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers incl= uding > + both device drivers and bus drivers. It initialize the global variable= s and > + publish the driver binding protocol. > + > + @param[in] ImageHandle The firmware allocated handle for the UE= FI image. > + @param[in] SystemTable A pointer to the EFI System Table. > + > + @retval EFI_SUCCESS The operation completed successfully. > + @retval EFI_ACCESS_DENIED EFI_ISCSI_INITIATOR_NAME_PROTOCOL was in= stalled unexpectedly. > + @retval Others Other errors as indicated. > +**/ > +EFI_STATUS > +EFIAPI > +RedfishResourceEntryPoint ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + VOID *Registration; > + > + if (mRedfishResourcePrivate !=3D NULL) { > + return EFI_ALREADY_STARTED; > + } > + > + mRedfishResourceConfigProtocolHandle =3D ImageHandle; > + > + mRedfishResourcePrivate =3D AllocateZeroPool (sizeof (REDFISH_RESOURCE= _COMMON_PRIVATE)); > + CopyMem (&mRedfishResourcePrivate->ConfigHandler, &mRedfishConfigHandl= er, sizeof (EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL)); > + CopyMem (&mRedfishResourcePrivate->RedfishResourceConfig, &mRedfishRes= ourceConfig, sizeof (EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL)); > + > + // > + // Publish config handler protocol and resource protocol. > + // > + Status =3D gBS->InstallMultipleProtocolInterfaces ( > + &ImageHandle, > + &gEdkIIRedfishConfigHandlerProtocolGuid, > + &mRedfishResourcePrivate->ConfigHandler, > + &gEdkIIRedfishResourceConfigProtocolGuid, > + &mRedfishResourcePrivate->RedfishResourceConfig, > + NULL > + ); > + > + EfiCreateProtocolNotifyEvent ( > + &gEfiRestJsonStructureProtocolGuid, > + TPL_CALLBACK, > + EfiRestJsonStructureProtocolIsReady, > + NULL, > + &Registration > + ); > + > + EfiCreateProtocolNotifyEvent ( > + &gEdkIIRedfishFeatureProtocolGuid, > + TPL_CALLBACK, > + EdkIIRedfishFeatureProtocolIsReady, > + (VOID *)mRedfishResourcePrivate, > + &Registration > + ); > + > + return Status; > +} > diff --git a/RedfishClientPkg/RedfishClient.fdf.inc b/RedfishClientPkg/Re= dfishClient.fdf.inc > index 59b8acba1..154f641b2 100644 > --- a/RedfishClientPkg/RedfishClient.fdf.inc > +++ b/RedfishClientPkg/RedfishClient.fdf.inc > @@ -25,6 +25,7 @@ > INF RedfishClientPkg/HiiToRedfishBiosDxe/HiiToRedfishBiosDxe.inf > INF RedfishClientPkg/Features/BootOptionCollection/BootOptionCollection= Dxe.inf > INF RedfishClientPkg/Features/BootOption/v1_0_4/Dxe/BootOptionDxe.inf > + INF RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/SecureBootDxe.inf >=20 > !include RedfishClientPkg/RedfishJsonStructureDxe.fdf.inc > # > --=20 > 2.34.1 >=20 Regards, Mike -=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 (#116774): https://edk2.groups.io/g/devel/message/116774 Mute This Topic: https://groups.io/mt/104927848/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- --Apple-Mail=_B03079E5-1E32-477E-9A61-1AAAE6D98DF8 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=us-ascii
Hi Nickle,

please find my comments below

On 14. 3. 2024., at 17:53, Nickle Wang via groups.io <nicklew=3Dnvidia.com@group= s.io> wrote:

Int= roduce SecureBoot driver to support
/redfish/v1/Systems/SYS/S= ecureBoot resource.

Signed-off-by: Nickle Wang= <nic= klew@nvidia.com>
Cc: Abner Chang <abner.chang@amd.com&= gt;
Cc: Igor Kulchytskyy <igork@ami.com>
Cc: Nick = Ramirez <nramirez@nvidia.com>
---
.../Redf= ishClientComponents.dsc.inc         = ;  |   2 +
RedfishClientPkg/RedfishClien= tLibs.dsc.inc    |   4 +
.../Secure= Boot/v1_1_0/Dxe/SecureBootDxe.inf   |  60 ++
= .../v1_1_0/Common/SecureBootCommon.h       &n= bsp;  |  40 +
.../v1_1_0/Common/SecureBootCom= mon.c          | 756 +++++++++= +++++++
.../SecureBoot/v1_1_0/Dxe/SecureBootDxe.c  &nbs= p;  | 808 ++++++++++++++++++
RedfishClientPkg/Redf= ishClient.fdf.inc        |   1= +
7 files changed, 1671 insertions(+)
create= mode 100644 RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/SecureBootDxe.= inf
create mode 100644 RedfishClientPkg/Features/SecureBoot/= v1_1_0/Common/SecureBootCommon.h
create mode 100644 RedfishC= lientPkg/Features/SecureBoot/v1_1_0/Common/SecureBootCommon.c
create mode 100644 RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/Secure= BootDxe.c

diff --git a/RedfishClientPkg/Redfis= hClientComponents.dsc.inc b/RedfishClientPkg/RedfishClientComponents.dsc.in= c
index ae2a4b025..42fc0c299 100644
--- a/Redfi= shClientPkg/RedfishClientComponents.dsc.inc
+++ b/RedfishClie= ntPkg/RedfishClientComponents.dsc.inc
@@ -34,6 +34,7 @@
  RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.inf=
  RedfishClientPkg/Features/BootOptionCollection/= BootOptionCollectionDxe.inf
  RedfishClientPkg/Fea= tures/BootOption/v1_0_4/Dxe/BootOptionDxe.inf
+  Redfish= ClientPkg/Features/SecureBoot/v1_1_0/Dxe/SecureBootDxe.inf
  !include RedfishClientPkg/RedfishJsonStructureDxe= .dsc.inc

@@ -47,3 +48,4 @@
&nbs= p; RedfishClientPkg/Converter/Bios/v1_0_9/RedfishBios_V1_0_9_Dxe.inf   RedfishClientPkg/Converter/BootOptionCollection/R= edfishBootOptionCollection_Dxe.inf
  RedfishClient= Pkg/Converter/BootOption/v1_0_4/RedfishBootOption_V1_0_4_Dxe.inf
+  RedfishClientPkg/Converter/SecureBoot/v1_1_0/RedfishSecureBoo= t_V1_1_0_Dxe.inf
diff --git a/RedfishClientPkg/RedfishClientL= ibs.dsc.inc b/RedfishClientPkg/RedfishClientLibs.dsc.inc
inde= x 6599926ab..9126465df 100644
--- a/RedfishClientPkg/RedfishC= lientLibs.dsc.inc
+++ b/RedfishClientPkg/RedfishClientLibs.ds= c.inc
@@ -25,6 +25,8 @@
  BiosV1_0_9= Lib|RedfishClientPkg/ConverterLib/edk2library/Bios/v1_0_9/Lib.inf
  BootOptionCollectionLib|RedfishClientPkg/ConverterLib/ed= k2library/BootOptionCollection/Lib.inf
  BootOptio= nV1_0_4Lib|RedfishClientPkg/ConverterLib/edk2library/BootOption/v1_0_4/Lib.= inf
+  SecureBootV1_1_0Lib|RedfishClientPkg/ConverterLib= /edk2library/SecureBoot/v1_1_0/Lib.inf
+
 = ; #
  # Above modules should be pulled in by = build tool.
  #
@@ -42,3 +44,5 @@   RedfishAddendumLib|RedfishClientPkg/Library/Redfis= hAddendumLib/RedfishAddendumLib.inf
  RedfishDebug= Lib|RedfishPkg/Library/RedfishDebugLib/RedfishDebugLib.inf
&= nbsp; RedfishHttpLib|RedfishPkg/Library/RedfishHttpLib/RedfishHttpLib.= inf
+  SecureBootVariableLib|SecurityPkg/Library/SecureB= ootVariableLib/SecureBootVariableLib.inf
+  PlatformPKPr= otectionLib|SecurityPkg/Library/PlatformPKProtectionLibVarPolicy/PlatformPK= ProtectionLibVarPolicy.inf
diff --git a/RedfishClientPkg/Feat= ures/SecureBoot/v1_1_0/Dxe/SecureBootDxe.inf b/RedfishClientPkg/Features/Se= cureBoot/v1_1_0/Dxe/SecureBootDxe.inf
new file mode 100644index 000000000..1ad8c623f
--- /dev/null
+++ b/RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/SecureBootDxe.i= nf
@@ -0,0 +1,60 @@
+## @file
+#<= br class=3D"">+#  (C) Copyright 2020-2022 Hewlett Packard Enterprise D= evelopment LP<BR>
+#  Copyright (c) 2022-2024, NVI= DIA CORPORATION & AFFILIATES. All rights reserved.
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[= Defines]
+  INF_VERSION      &n= bsp;        =3D 0x00010005
+  BASE_NAME         &nb= sp;       =3D SecureBootDxe
+  FILE_GUID          &= nbsp;      =3D 5E4025F8-DA42-468A-853E-6A1091= D35052
+  MODULE_TYPE      &nbs= p;        =3D DXE_DRIVER
+  VERSION_STRING        &nbs= p;   =3D 1.0
+  ENTRY_POINT   &= nbsp;           =3D = RedfishResourceEntryPoint
+  UNLOAD_IMAGE   &n= bsp;          =3D Redfish= ResourceUnload
+
+[Packages]
+ &n= bsp;MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec+  SecurityPkg/SecurityPkg.dec
+  Redf= ishPkg/RedfishPkg.dec
+  RedfishClientPkg/RedfishClientP= kg.dec
+
+[Sources]
+  ../Co= mmon/SecureBootCommon.h
+  ../Common/SecureBootCommon.c<= br class=3D"">+  SecureBootDxe.c
+
+[Libra= ryClasses]
+  BaseMemoryLib
+  DebugL= ib
+  EdkIIRedfishResourceConfigLib
+ &nbs= p;RedfishFeatureUtilityLib
+  RedfishVersionLib
+  RedfishResourceIdentifyLib
+  SecureBootVa= riableLib
+  UefiLib
+  UefiDriverEnt= ryPoint
+  RedfishAddendumLib
+  Uefi= RuntimeServicesTableLib
+
+[Protocols]
+  gEdkIIRedfishConfigHandlerProtocolGuid    &nbs= p;     ## PRODUCED
+  gEfiRestJ= sonStructureProtocolGuid         &n= bsp;     ## CONSUMED
+  gEdkIIR= edfishResourceConfigProtocolGuid        =  ## PRODUCED
+  gEdkIIRedfishFeatureProtocolGuid &n= bsp;            = ;  ## CONSUMED
+
+[Guids]
+  gEfiSecureBootEnableDisableGuid      &n= bsp;          ## CONSUMED=
+
+[Pcd]
+  gEfiRedfishClie= ntPkgTokenSpaceGuid.PcdMaxRedfishSchemaStringSize
+  gEf= iRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaVersionSize
+  gEfiRedfishClientPkgTokenSpaceGuid.PcdRedfishSystemRebootRequired=
+
+[Depex]
+  TRUE
diff --git a/RedfishClientPkg/Features/SecureBoot/v1_1_0/Common/Secur= eBootCommon.h b/RedfishClientPkg/Features/SecureBoot/v1_1_0/Common/SecureBo= otCommon.h
new file mode 100644
index 000000000= ..0d1824160
--- /dev/null
+++ b/RedfishClientPk= g/Features/SecureBoot/v1_1_0/Common/SecureBootCommon.h
@@ -0,= 0 +1,40 @@
+/** @file
+
+  R= edfish feature driver implementation - internal header file
+=  (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<= ;BR>
+  Copyright (c) 2022-2024, NVIDIA CORPORATION &= amp; AFFILIATES. All rights reserved.
+
+  = ;SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_SECUREBOOT_COMMON_= H_
+#define EFI_REDFISH_SECUREBOOT_COMMON_H_
+<= br class=3D"">+#include <Guid/ImageAuthentication.h>
+#= include <Guid/GlobalVariable.h>
+#include <Guid/Auth= enticatedVariableFormat.h>
+#include <RedfishJsonStruct= ure/SecureBoot/v1_1_0/EfiSecureBootV1_1_0.h>
+#include <= ;RedfishResourceCommon.h>
+#include <UefiSecureBoot.h&g= t;
+#include <Library/UefiRuntimeServicesTableLib.h>+#include <Library/SecureBootVariableLib.h>
+
+//
+// Schema information.
+/= /
+#define REDFISH_MANAGED_URI      =   L"Systems/{}/SecureBoot"
+#define REDFISH_DUMMY_C= ONFIG_LANG  L"Systems/{1}/SecureBoot"
+#define MAX_URI_L= ENGTH            &nb= sp;256
+#define RESOURCE_SCHEMA      = ;      "SecureBoot"
+#define RE= SOURCE_SCHEMA_MAJOR      "1"
+#defin= e RESOURCE_SCHEMA_MINOR      "1"
+#d= efine RESOURCE_SCHEMA_ERRATA     "0"
+#de= fine RESOURCE_SCHEMA_VERSION    "v1_1_0"
+#def= ine SECURE_BOOT_SETUP_MODE     "SetupMode"
+#define SECURE_BOOT_USER_MODE      "UserMode"+#define SECURE_BOOT_ENABLED      &nb= sp; "Enabled"
+#define SECURE_BOOT_DISABLED   =     "Disabled"
+#define SECURE_BOOT_MODE_= STR_LEN   16
+
+#endif
= diff --git a/RedfishClientPkg/Features/SecureBoot/v1_1_0/Common/SecureBootC= ommon.c b/RedfishClientPkg/Features/SecureBoot/v1_1_0/Common/SecureBootComm= on.c
new file mode 100644
index 000000000..56a4= 5ee72
--- /dev/null
+++ b/RedfishClientPkg/Feat= ures/SecureBoot/v1_1_0/Common/SecureBootCommon.c
@@ -0,0 +1,7= 56 @@
+/** @file
+  Redfish feature driver= implementation - common functions
+
+  (C= ) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>+  Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFI= LIATES. All rights reserved.
+
+  SPDX-Lic= ense-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SecureBootCommon.h"
++CHAR8  SecureBootEmptyJson[] =3D "{\"@odata.id\": \"\", \"@odata.type= \": \"#SecureBoot.v1_1_0.SecureBoot\", \"Id\": \"\", \"Name\": \"\", \"Attr= ibutes\":{}}";
+
+REDFISH_RESOURCE_COMMON_PRIVA= TE  *mRedfishResourcePrivate        = ;            &n= bsp;            = ; =3D NULL;
+EFI_HANDLE      &n= bsp;            = ;    mRedfishResourceConfigProtocolHandle   &= nbsp;           &nbs= p;      =3D NULL;
+CHAR16  = ;            &n= bsp;            = ;*mSecureBootSupportedAttributes[SECURE_BOOT_MODE_STR_LEN] =3D {
+  L"SecureBootCurrentBoot",
+  L"SecureBootE= nable",
+  L"SecureBootMode"
+};
+
+/**
+  Read EFI_SECURE_BOOT_ENABL= E_NAME variable and return its value to caller.
+
+  @retval BOOLEAN    TRUE when EFI_SECURE_BOOT_ENAB= LE_NAME value is SECURE_BOOT_ENABLE
+     = ;            &n= bsp;   FALSE when EFI_SECURE_BOOT_ENABLE_NAME value is SECUR= E_BOOT_DISABLE
+**/
+BOOLEAN
+Red= fishReadSecureBootEnable (
+  VOID
+  = ;)
+{
+  UINT8    *Buffer;<= br class=3D"">+  BOOLEAN  SecureBootEnableValue;
+<= br class=3D"">+  Buffer        &nbs= p;       =3D NULL;
+  = ;SecureBootEnableValue =3D FALSE;
+
+  Get= Variable2 (
+    EFI_SECURE_BOOT_ENABLE_NAME,<= br class=3D"">+    &gEfiSecureBootEnableDisableGuid,
+    (VOID **)&Buffer,
+  =   NULL
+    );
+
+  if (Buffer !=3D NULL) {
+    = if (*Buffer =3D=3D SECURE_BOOT_ENABLE) {
+    =   SecureBootEnableValue =3D TRUE;
+   &nb= sp;}
+
+    FreePool (Buffer);+  }
+
+  return SecureB= ootEnableValue;
+}
+
+/**
+  Write EFI_SECURE_BOOT_ENABLE_NAME variable with given value.=
+
+  @param[in]   SecureBootEna= bleValue    Value to write. TRUE is SECURE_BOOT_ENABLE.
+           &nb= sp;            =             &nb= sp;   FALSE is SECURE_BOOT_DISABLE.
+
+  @retval EFI_SUCCESS        = ;      Write value successfully.
+  @retval Others         &n= bsp;         Some error happen= ed.
+**/
+EFI_STATUS
+RedfishWrit= eSecureBootEnable (
+  BOOLEAN  SecureBootEnableVal= ue
+  )
+{
+  EFI_STATU= S  Status;
+  UINT8      &= nbsp;VarValue;
+
+  VarValue =3D (SecureBo= otEnableValue ? SECURE_BOOT_ENABLE : SECURE_BOOT_DISABLE);
+ =  Status   =3D gRT->SetVariable (
+  &n= bsp;            = ;     EFI_SECURE_BOOT_ENABLE_NAME,
+=             &n= bsp;      &gEfiSecureBootEnableDisableGui= d,
+          &n= bsp;         EFI_VARIABLE_NON_= VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+   &nb= sp;            =     sizeof (VarValue),
+   &nbs= p;            &= nbsp;   &VarValue
+    &nbs= p;            &= nbsp;  );
+
+  return Status;+}
+
+/**
+  Con= sume Redfish resource in given Json data.
+
+ &= nbsp;@param[in]   This        =         Pointer to REDFISH_RESOURCE= _COMMON_PRIVATE instance.
+  @param[in]   Json=             &n= bsp;  The JSON to consume.
+  @param[in]  = ; HeaderEtag          The= Etag string returned in HTTP header.
+
+  = ;@retval EFI_SUCCESS          =     Consume Redfish attribute successfully.
+  @retval Others         &= nbsp;         Some error happe= ned.
+
+**/
+EFI_STATUS
+RedfishConsumeResourceCommon (
+  IN  REDFIS= H_RESOURCE_COMMON_PRIVATE  *Private,
+  IN  CH= AR8             = ;            &n= bsp;  *Json,
+  IN  CHAR8   &nb= sp;            =             *He= aderEtag OPTIONAL
+  )
+{
+ =  EFI_STATUS          &nbs= p;            &= nbsp;Status;
+  EFI_REDFISH_SECUREBOOT_V1_1_0  &nbs= p;  *SecureBoot;
+  EFI_REDFISH_SECUREBOOT_V1_= 1_0_CS  *SecureBootCs;
+  BOOLEAN    = ;            &n= bsp;          SecureBootE= nableDisable;
+
+  if ((Private =3D=3D NUL= L) || IS_EMPTY_STRING (Json)) {
+    return EF= I_INVALID_PARAMETER;
+  }
+
= +  SecureBoot          &n= bsp;   =3D NULL;
+  SecureBootCs  &n= bsp;         =3D NULL;
+  SecureBootEnableDisable =3D RedfishReadSecureBootEnable ();<= br class=3D"">+
+  Status =3D Private->JsonStructProt= ocol->ToStructure (
+       =             &nb= sp;            =           Private->Jso= nStructProtocol,
+        =             &nb= sp;            =          NULL,
+=             &n= bsp;            = ;            &n= bsp;   Json,
+      &= nbsp;           &nbs= p;            &= nbsp;          (EFI_REST_= JSON_STRUCTURE_HEADER **)&SecureBoot
+    =             &nb= sp;            =             &nb= sp;);
+  if (EFI_ERROR (Status)) {
+  = ;  DEBUG ((DEBUG_ERROR, "%a: ToStructure() failed: %r\n", __func_= _, Status));
+    return Status;
+  }
+
+  SecureBootCs =3D SecureBoo= t->SecureBoot;
+
+  //
+ =  // Check ETAG to see if we need to consume it
+  /= /
+  if (CheckEtag (Private->Uri, HeaderEtag, SecureB= ootCs->odata_etag)) {
+    //
+    // No change
+    //
+    DEBUG ((REDFISH_DEBUG_TRACE, "%a: ETAG: %s ha= s no change, ignore consume action\n", __func__, Private->Uri));
+    Status =3D EFI_ALREADY_STARTED;
+ =    goto ON_RELEASE;
+  }
+<= br class=3D"">+  //
+  // Secure boot enable
+  //
+  if (SecureBootCs->SecureBootEna= ble !=3D NULL) {
+    if (SecureBootEnableDisa= ble !=3D *SecureBootCs->SecureBootEnable) {
+   =    //
+      // Write= value to "SecureBootEnable" variable. AuthVariableLib will enable or disab= le secure boot
+      // based on "S= ecureBootEnable" value.
+      //+      Status =3D RedfishWriteSecureBo= otEnable (*SecureBootCs->SecureBootEnable);
+   =    if (EFI_ERROR (Status)) {
+   &nb= sp;    DEBUG ((DEBUG_ERROR, "%a: write secure boot enab= le disable failed: %r\n", __func__, Status));
+   &= nbsp;  } else {
+      &nb= sp; REDFISH_ENABLE_SYSTEM_REBOOT ();
+    = ;  }
+    } else {
+ &= nbsp;    DEBUG ((REDFISH_DEBUG_TRACE, "%a: secure boot = mode is not changed\n", __func__));
+    }
+  }
+
+ON_RELEASE:
+
+  //
+  // Release resource.+  //
+  Private->JsonStructProtocol= ->DestoryStructure (
+       = ;            &n= bsp;            = ; Private->JsonStructProtocol,
+    &n= bsp;            = ;            &n= bsp;   (EFI_REST_JSON_STRUCTURE_HEADER *)SecureBoot
+            &= nbsp;           &nbs= p;        );
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Provision Redfish resource. This functio= n reads secure boot variable and convert it
+  to Redfis= h attribute.
+
+  @param[in]   J= sonStructProtocol  Pointer to Json structure protocol.
+=  @param[in]   InputJson       = ;    Jason data on input.
+  @param[= in]   ResourceId         =  Resource ID. This is optional.
+  @param[in]  = ; ConfigureLang       Configure language= for this Redfish resource.
+  @param[in]   Pr= ovisionMode       TRUE when this is to provis= ion Redfish attribute to
+      &nbs= p;            &= nbsp;           &nbs= p;   Redfish service. FALSE is to update Redfish attribute+           =             &nb= sp;           to Red= fish service.
+  @param[out]  ResultJson  &nbs= p;       Json data on output.
+
+  @retval EFI_SUCCESS     &= nbsp;        Provision Redfish attr= ibute successfully.
+  @retval Others    =             &nb= sp;  Some error happened.
+
+**/
+EFI_STATUS
+ProvisioningSecureBootProperties (
+  IN  EFI_REST_JSON_STRUCTURE_PROTOCOL  *JsonStr= uctProtocol,
+  IN  CHAR8     &= nbsp;           &nbs= p;           *InputJ= son,
+  IN  CHAR8      &nb= sp;            =           *ResourceId OPT= IONAL,
+  IN  EFI_STRING     &n= bsp;            = ;      ConfigureLang,
+  I= N  BOOLEAN           = ;            &n= bsp;   ProvisionMode,
+  OUT CHAR8  =             &nb= sp;            =   **ResultJson
+  )
+{
+  EFI_REDFISH_SECUREBOOT_V1_1_0     *Secure= Boot;
+  EFI_REDFISH_SECUREBOOT_V1_1_0_CS  *SecureB= ootCs;
+  EFI_STATUS       = ;            &n= bsp;    Status;
+  BOOLEAN  &nb= sp;            =             Pro= pertyChanged;
+  CHAR8      &nb= sp;            =           *AsciiStringVal= ue;
+  INT32        &= nbsp;           &nbs= p;        *IntegerValue;
+  UINT8          &= nbsp;           &nbs= p;      SetupMode;
+  BOOL= EAN             = ;            &n= bsp; SecureBootEnabled;
+  BOOLEAN   &nbs= p;            &= nbsp;          SecureBoot= EnableDisable;
+
+  if ((JsonStructProtoco= l =3D=3D NULL) || (ResultJson =3D=3D NULL) || IS_EMPTY_STRING (InputJson) |= | IS_EMPTY_STRING (ConfigureLang)) {
+    retu= rn EFI_INVALID_PARAMETER;
+  }
+
+  DEBUG ((REDFISH_DEBUG_TRACE, "%a provision for %s with: %s\n"= , __func__, ConfigureLang, (ProvisionMode ? L"Provision resource" : L"Updat= e resource")));
+
+  *ResultJson  &nb= sp;          =3D NULL;+  PropertyChanged       &nb= sp; =3D FALSE;
+  AsciiStringValue   &nbs= p;    =3D NULL;
+  SecureBootEnableD= isable =3D RedfishReadSecureBootEnable ();
+  SecureBoot= Enabled       =3D IsSecureBootEnabled ();
+
+  SecureBoot =3D NULL;
+ &nb= sp;Status     =3D JsonStructProtocol->ToStructure (<= br class=3D"">+           = ;            &n= bsp;            = ; JsonStructProtocol,
+      &n= bsp;            = ;            &n= bsp;     NULL,
+    &= nbsp;           &nbs= p;            &= nbsp;       InputJson,
+ &= nbsp;           &nbs= p;            &= nbsp;          (EFI_REST_= JSON_STRUCTURE_HEADER **)&SecureBoot
+    =             &nb= sp;            =         );
+  if= (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERR= OR, "%a: ToStructure failure: %r\n", __func__, Status));
+ &n= bsp;  return Status;
+  }
+
+  SecureBootCs =3D SecureBoot->SecureBoot;
+
+  //
+  // ID
+ &nb= sp;//
+  if (SecureBootCs->Id !=3D NULL) {
+    SecureBootCs->Id =3D NULL;
+ &nb= sp;}
+
+  //
+  // Name=
+  //
+  if (SecureBootCs->Name != =3D NULL) {
+    SecureBootCs->Name =3D NUL= L;
+  }
+
+  //
+  // Secure boot variables that we will handle here
+  //
+  // EFI_SETUP_MODE_NAME (gEfiGlobalVa= riableGuid)
+  // EFI_SECURE_BOOT_MODE_NAME (gEfiGlobalV= ariableGuid)
+  // EFI_SECURE_BOOT_ENABLE_NAME (gEfiSecu= reBootEnableDisableGuid)
+  //
+
+  //
+  // Current Boot
+ &nbs= p;//
+  if (PropertyChecker (SecureBootCs->SecureBoot= CurrentBoot, ProvisionMode)) {
+    AsciiStrin= gValue =3D AllocateZeroPool (SECURE_BOOT_MODE_STR_LEN * sizeof (CHAR8));+    if (AsciiStringValue !=3D NULL) {
+      AsciiSPrint (AsciiStringValue, SECURE= _BOOT_MODE_STR_LEN, "%a", (SecureBootEnabled ? SECURE_BOOT_ENABLED : SECURE= _BOOT_DISABLED));
+      if (Provisi= onMode || (AsciiStrCmp (SecureBootCs->SecureBootCurrentBoot, AsciiString= Value) !=3D 0)) {
+        = ;SecureBootCs->SecureBootCurrentBoot =3D AsciiStringValue;
+        PropertyChanged   &n= bsp;            = ;     =3D TRUE;
+    =   }
+    } else {
+ &n= bsp;    DEBUG ((DEBUG_ERROR, "%a: out of resource\n", _= _func__));
+    }
+  }
+
+  //
+  // Secure boot e= nable
+  //
+  if (PropertyChecker (S= ecureBootCs->SecureBootEnable, ProvisionMode)) {
+  &= nbsp; if (ProvisionMode || (*SecureBootCs->SecureBootEnable !=3D Se= cureBootEnableDisable)) {
+      Int= egerValue =3D AllocatePool (sizeof (*IntegerValue));
+  =     if (IntegerValue !=3D NULL) {
+  = ;      *IntegerValue     =             &nb= sp;=3D (SecureBootEnableDisable ? 0x01 : 0x00);
+   = ;     SecureBootCs->SecureBootEnable =3D Intege= rValue;
+        PropertyC= hanged            &n= bsp;   =3D TRUE;
+     &nb= sp;} else {
+        DEBUG= ((DEBUG_ERROR, "%a: out of resource\n", __func__));
+  =     }
+    }
+  }
+
+  //
+  /= / Secure boot mode
+  //
+  if (Prope= rtyChecker (SecureBootCs->SecureBootMode, ProvisionMode)) {
+    Status =3D GetSetupMode (&SetupMode);
+    if (!EFI_ERROR (Status)) {
+  &nb= sp;   AsciiStringValue =3D AllocateZeroPool (SECURE_BOOT_MOD= E_STR_LEN *sizeof (CHAR8));
+      i= f (AsciiStringValue !=3D NULL) {
+     &n= bsp;  AsciiSPrint (AsciiStringValue, SECURE_BOOT_MODE_STR_LEN *si= zeof (CHAR8), "%a", (SetupMode =3D=3D USER_MODE ? SECURE_BOOT_USER_MODE : S= ECURE_BOOT_SETUP_MODE));
+      &nbs= p; if (ProvisionMode || (AsciiStrCmp (SecureBootCs->SecureBootMode,= AsciiStringValue) !=3D 0)) {
+      = ;    SecureBootCs->SecureBootMode =3D AsciiStringVal= ue;
+          P= ropertyChanged           =    =3D TRUE;
+      &= nbsp; }
+      }
= +    } else {
+      = DEBUG ((DEBUG_ERROR, "%a: cannot read setup mode: %r\n", __func__, Status))= ;
+    }
+  }
+
+  //
+  // Convert C structure ba= ck to JSON text.
+  //
+  Status =3D = JsonStructProtocol->ToJson (
+     &nb= sp;            =             &nb= sp;  JsonStructProtocol,
+     =             &nb= sp;            =    (EFI_REST_JSON_STRUCTURE_HEADER *)SecureBoot,
+            &nbs= p;            &= nbsp;       ResultJson
+ &= nbsp;           &nbs= p;            &= nbsp;      );
+  if (EFI_E= RROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a= : ToJson() failed: %r\n", __func__, Status));
+   &= nbsp;return Status;



  SecureBoot structure leak.= It is released below.

+  }
+
+  //
+  // Release resource.
+ &n= bsp;//
+  JsonStructProtocol->DestoryStructure (
+           &nb= sp;            = JsonStructProtocol,
+       &nb= sp;            =     (EFI_REST_JSON_STRUCTURE_HEADER *)SecureBoot
+            = ;            );=
+
+  return (PropertyChanged ? EFI_SUCCES= S : EFI_NOT_FOUND);
+}
+
+/**
+  Provision Redfish resource and upload data to Redfish se= rvice. This function
+  checks OEM data and platform add= endum data before sending data to Redfish service.
+
+  @param[in]   Private   Pointer to private= data.
+
+  @retval EFI_SUCCESS  &nbs= p;           Provisi= on Redfish resource successfully.
+  @retval Others &nbs= p;            &= nbsp;    Some error happened.
+
+**/
+EFI_STATUS
+ProvisioningSecureBootR= esource (
+  IN  REDFISH_RESOURCE_COMMON_PRIVATE &n= bsp;*Private
+  )
+{
+  = ;EFI_STATUS        Status;
+  CHAR8           =   *Json;
+  CHAR8     &nbs= p;       *JsonWithAddendum;
+  REDFISH_RESPONSE  Response;
+
+ =  if (Private =3D=3D NULL) {
+    return E= FI_INVALID_PARAMETER;
+  }
+
+  ZeroMem (&Response, sizeof (REDFISH_RESPONSE));
= +  Json =3D NULL;
+
+  Status =3D Pro= visioningSecureBootProperties (
+     &nb= sp;       Private->JsonStructProtocol= ,
+          &nb= sp;  SecureBootEmptyJson,
+     = ;        NULL,
+ &nbs= p;           REDFISH= _DUMMY_CONFIG_LANG,
+       &nb= sp;     TRUE,
+    &n= bsp;        &Json
+             = );
+  if (EFI_ERROR (Status)) {
+  &n= bsp; if (Status =3D=3D EFI_NOT_FOUND) {
+   &n= bsp;  DEBUG ((REDFISH_DEBUG_TRACE, "%a: provisioning existing res= ource for %s ignored. Nothing changed\n", __func__, REDFISH_DUMMY_CONFIG_LA= NG));
+      Status =3D EFI_SUCCESS;=
+    } else {
+   &nb= sp;  DEBUG ((DEBUG_ERROR, "%a: provisioning existing resource for= %s failed: %r\n", __func__, REDFISH_DUMMY_CONFIG_LANG, Status));
+    }
+
+   &nb= sp;goto ON_RELEASE;
+  }
+
+=  //
+  // Check and see if platform has OEM data o= r not
+  //
+  Status =3D RedfishGetO= emData (
+         &n= bsp;   Private->Uri,
+    &n= bsp;        RESOURCE_SCHEMA,
+            = ; RESOURCE_SCHEMA_VERSION,
+     &nb= sp;       Json,
+  &n= bsp;          &JsonWi= thAddendum
+         =     );
+  if (!EFI_ERROR (Status) &a= mp;& (JsonWithAddendum !=3D NULL)) {
+    = FreePool (Json);
+    Json    &= nbsp;        =3D JsonWithAddendum;<= br class=3D"">+    JsonWithAddendum =3D NULL;
= +  }
+
+  //
+  //= Check and see if platform has addendum data or not
+  /= /
+  Status =3D RedfishGetAddendumData (
+=             Pr= ivate->Uri,
+        &n= bsp;    RESOURCE_SCHEMA,
+   &n= bsp;         RESOURCE_SCHEMA_V= ERSION,
+         &nb= sp;   Json,
+      &n= bsp;      &JsonWithAddendum
+             = );
+  if (!EFI_ERROR (Status) && (JsonWithAddend= um !=3D NULL)) {
+    FreePool (Json);
+    Json        &= nbsp;    =3D JsonWithAddendum;
+  &n= bsp; JsonWithAddendum =3D NULL;
+  }
= +
+  DEBUG ((REDFISH_DEBUG_TRACE, "%a: provisioning exis= ting resource for %s\n", __func__, REDFISH_DUMMY_CONFIG_LANG));
+
+  //
+  // PATCH back to instan= ce
+  //
+  Status =3D RedfishHttpPat= chResource (Private->RedfishService, Private->Uri, Json, &Respons= e);
+  if (EFI_ERROR (Status)) {
+  &= nbsp; DEBUG ((DEBUG_ERROR, "%a: patch resource for %s failed: %r\n", _= _func__, REDFISH_DUMMY_CONFIG_LANG, Status));
+  }
+
+ON_RELEASE:
+
+  = ;if (Json !=3D NULL) {
+    FreePool (Json);+  }
+
+  RedfishHttpFre= eResponse (&Response);
+
+  return Sta= tus;
+}
+
+/**
+ &n= bsp;Provisioning redfish resource to Redfish service.
+
+  @param[in]   Private     &nb= sp;       Pointer to private data.
+  @param[in]   ResourceExist    &nb= sp;  TRUE if resource exists, PUT method will be used.
+            &= nbsp;           &nbs= p;          FALSE if reso= urce does not exist POST method is used.


=
Actually ProvisioningSecureBo= otResource uses PATCH only.

+
+  @retval EFI_SUCCESS &nb= sp;            = Provision resource successfully.
+  @retval Others  = ;            &n= bsp;    Some error happened.
+
+**/
+EFI_STATUS
+RedfishProvisioningReso= urceCommon (
+  IN     REDFISH_RESOU= RCE_COMMON_PRIVATE  *Private,
+  IN   &nb= sp; BOOLEAN          &nbs= p;            &= nbsp;  ResourceExist
+  )
+{
+  if (Private =3D=3D NULL) {
+   &= nbsp;return EFI_INVALID_PARAMETER;
+  }
+<= br class=3D"">+  return ProvisioningSecureBootResource (Private);
+}
+
+/**
+  Check= resource from given Json data.
+
+  @para= m[in]   This         &nbs= p;      Pointer to REDFISH_RESOURCE_COMMON_PR= IVATE instance.
+  @param[in]   Json  &nb= sp;            =  The JSON data to check.
+  @param[in]   = HeaderEtag          The Etag s= tring returned in HTTP header.
+
+  @retva= l EFI_SUCCESS           &= nbsp;  Check resource successfully.
+  @retval= Others            &= nbsp;      Some error happened.
+
+**/
+EFI_STATUS
+RedfishCheck= ResourceCommon (
+  IN     REDFISH_R= ESOURCE_COMMON_PRIVATE  *Private,
+  IN   = ;  CHAR8          &n= bsp;            = ;     *Json,
+  IN   =   CHAR8          &nb= sp;            =      *HeaderEtag OPTIONAL
+  )<= br class=3D"">+{
+  UINTN      =  Index;
+  EFI_STATUS  Status;
+=  UINTN       Count;
+ &nb= sp;EFI_STRING  Property;
+
+  if ((Pr= ivate =3D=3D NULL) || IS_EMPTY_STRING (Json)) {
+   = ; return EFI_INVALID_PARAMETER;
+  }
= +
+  //
+  // Check ETAG to see if we= need to check it
+  //
+  if (CheckE= tag (Private->Uri, HeaderEtag, NULL)) {
+   &nbs= p;//
+    // No change
+  &= nbsp; //
+    DEBUG ((REDFISH_DEBUG_TRACE= , "%a: ETAG: %s has no change, ignore check action\n", __func__, Private-&g= t;Uri));
+    return EFI_SUCCESS;
+  }
+
+  Count =3D sizeof (mSecure= BootSupportedAttributes) / sizeof (mSecureBootSupportedAttributes[0]);
+  if (Count =3D=3D 0) {
+    r= eturn EFI_UNSUPPORTED;
+  }
+
+  Status =3D EFI_SUCCESS;
+  for (Index =3D 0; I= ndex < Count; Index++) {
+    Property =3D = mSecureBootSupportedAttributes[Index];
+    if= (Property =3D=3D NULL) {
+      con= tinue;
+    }
+
+ =    DEBUG ((REDFISH_DEBUG_TRACE, "%a: [%d] check attribute fo= r: %s\n", __func__, Index, Property));
+    if= (!MatchPropertyWithJsonContext (Property, Json)) {
+  &= nbsp;   DEBUG ((REDFISH_DEBUG_TRACE, "%a: property is missin= g: %s\n", __func__, Property));
+     &nb= sp;Status =3D EFI_NOT_FOUND;
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Update = resource to Redfish service.
+
+  @param[i= n]   Private         &nbs= p;   Pointer to REDFISH_RESOURCE_COMMON_PRIVATE instance.+  @param[in]   Json     &nb= sp;          The JSON dat= a to be updated.
+
+  @retval EFI_SUCCESS =             &nb= sp;Update resource successfully.
+  @retval Others  = ;            &n= bsp;    Some error happened.
+
+**/
+EFI_STATUS
+RedfishUpdateResourceCo= mmon (
+  IN     REDFISH_RESOURCE_CO= MMON_PRIVATE  *Private,
+  IN    &nb= sp;CHAR8            =             &nb= sp;   *InputJson
+  )
+{+  EFI_STATUS        St= atus;
+  CHAR8        = ;     *Json;
+  CHAR8  &nb= sp;          *JsonWithAdd= endum;
+  REDFISH_RESPONSE  Response;
+
+  if ((Private =3D=3D NULL) || IS_EMPTY_STRING (Inpu= tJson)) {
+    return EFI_INVALID_PARAMETER;+  }
+
+  ZeroMem (&= Response, sizeof (REDFISH_RESPONSE));
+  Json =3D NULL;<= br class=3D"">+
+  Status =3D ProvisioningSecureBootProp= erties (
+         &n= bsp;   Private->JsonStructProtocol,
+  = ;           SecureBo= otEmptyJson,
+        &nbs= p;    NULL,
+     &nb= sp;       REDFISH_DUMMY_CONFIG_LANG,
+           &n= bsp; TRUE,
+        &= nbsp;    &Json
+    &n= bsp;        );
+ &nbs= p;if (EFI_ERROR (Status)) {
+    if (Status = =3D=3D EFI_NOT_FOUND) {
+      DEBUG= ((REDFISH_DEBUG_TRACE, "%a: update resource for %s ignored. Nothing change= d\n", __func__, REDFISH_DUMMY_CONFIG_LANG));
+   &n= bsp;  Status =3D EFI_SUCCESS;
+    }= else {
+      DEBUG ((DEBUG_ERROR, = "%a: update resource for %s failed: %r\n", __func__, REDFISH_DUMMY_CONFIG_L= ANG, Status));
+    }
+
+    goto ON_RELEASE;
+  }
+
+  //
+  // Check and see if = platform has OEM data or not
+  //
+  = ;Status =3D RedfishGetOemData (
+     &nb= sp;       Private->Uri,
+             = RESOURCE_SCHEMA,
+        =      RESOURCE_SCHEMA_VERSION,
+ &nbs= p;           Json,+           =   &JsonWithAddendum
+     &= nbsp;       );
+  if = (!EFI_ERROR (Status) && (JsonWithAddendum !=3D NULL)) {
+    FreePool (Json);
+    J= son             = ;=3D JsonWithAddendum;
+    JsonWithAddendum = =3D NULL;
+  }
+
+  //<= br class=3D"">+  // Check and see if platform has addendum data or not=
+  //
+  Status =3D RedfishGetAddend= umData (
+         &n= bsp;   Private->Uri,
+    &n= bsp;        RESOURCE_SCHEMA,
+            = ; RESOURCE_SCHEMA_VERSION,
+     &nb= sp;       Json,
+  &n= bsp;          &JsonWi= thAddendum
+         =     );
+  if (!EFI_ERROR (Status) &a= mp;& (JsonWithAddendum !=3D NULL)) {
+    = FreePool (Json);
+    Json    &= nbsp;        =3D JsonWithAddendum;<= br class=3D"">+    JsonWithAddendum =3D NULL;
= +  }
+
+  DEBUG ((REDFISH_DEBUG_TRACE= , "%a: update resource for %s\n", __func__, REDFISH_DUMMY_CONFIG_LANG));+
+  //
+  // PATCH back = to instance
+  //
+  Status =3D Redfi= shHttpPatchResource (Private->RedfishService, Private->Uri, Json, &am= p;Response);
+  if (EFI_ERROR (Status)) {
= +    DEBUG ((DEBUG_ERROR, "%a: patch resource for %s failed:= %r\n", __func__, REDFISH_DUMMY_CONFIG_LANG, Status));
+ &nbs= p;}
+
+ON_RELEASE:
+
+  if (Json !=3D NULL) {
+    FreePool = (Json);
+  }
+
+  Redfi= shHttpFreeResponse (&Response);
+
+  r= eturn Status;
+}
+
+/**
+  Identify resource in given Json data.
+
+  @param[in]   Private      = ;       Pointer to REDFISH_RESOURCE_COMM= ON_PRIVATE instance.
+  @param[in]   Json &nbs= p;            &= nbsp; The JSON to be identified.
+
+  = ;@retval EFI_SUCCESS          =     Identify resource successfully.
+ &nb= sp;@retval Others          &nb= sp;        Some error happened.
+
+**/
+EFI_STATUS
+Re= dfishIdentifyResourceCommon (
+  IN    &n= bsp;REDFISH_RESOURCE_COMMON_PRIVATE  *Private,
+  I= N     CHAR8        &= nbsp;           &nbs= p;       *Json
+  )+{
+  BOOLEAN  Supported;
+
+  Supported =3D RedfishIdentifyResource (Private-&g= t;Uri, Private->Json);
+  if (Supported) {
+    //
+    // Keep URI = and ConfigLang mapping
+    //
+=    RedfishSetRedfishUri (REDFISH_DUMMY_CONFIG_LANG, Private= ->Uri);
+  }
+
+  re= turn (Supported ? EFI_SUCCESS : EFI_UNSUPPORTED);
+}
+
+/**
+  Handle Redfish resource in= Uri.
+
+  @param[in]   Private =             Poi= nter to REDFISH_RESOURCE_COMMON_PRIVATE instance.
+  @pa= ram[in]   Uri         &nb= sp;       URI to Redfish resource that w= e like to process.
+
+  @retval EFI_SUCCES= S             &= nbsp;Handle resource successfully.
+  @retval Others &nb= sp;            =      Some error happened.
+
+**/
+EFI_STATUS
+HandleResource (
+  IN  REDFISH_RESOURCE_COMMON_PRIVATE  *Private,+  IN  EFI_STRING       = ;            &n= bsp;   Uri
+  )
+{
+  EFI_STATUS         &n= bsp; Status;
+  REDFISH_SCHEMA_INFO  SchemaInf= o;
+  EFI_STRING       &nb= sp;   ConfigLang;
+
+  if (= (Private =3D=3D NULL) || IS_EMPTY_STRING (Uri)) {
+  &nb= sp; return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Resource match
+  //
+
+  DEBUG ((REDFISH_DE= BUG_TRACE, "%a: process resource for: %s\n", __func__, Uri));
+
+  Status =3D GetRedfishSchemaInfo (Private->Redfi= shService, Private->JsonStructProtocol, Uri, NULL, &SchemaInfo);
+  if (EFI_ERROR (Status)) {
+   &n= bsp;DEBUG ((DEBUG_ERROR, "%a: failed to get schema information from: %s %r\= n", __func__, Uri, Status));
+    return Statu= s;
+  }
+
+  //
+  // Check and see if this is target resource that we want to = handle.
+  // Some resource is handled by other provider= so we have to make sure this first.
+  //
+  DEBUG ((REDFISH_DEBUG_TRACE, "%a: Identify for %s\n", __func__, Ur= i));
+  ConfigLang =3D RedfishGetConfigLanguage (Uri);+  if (ConfigLang =3D=3D NULL) {
+  &n= bsp; Status =3D EdkIIRedfishResourceConfigIdentify (&SchemaInfo, U= ri, NULL, Private->InformationExchange);
+   &nb= sp;if (EFI_ERROR (Status)) {
+      = if (Status =3D=3D EFI_UNSUPPORTED) {
+    &nbs= p;   DEBUG ((REDFISH_DEBUG_TRACE, "%a: \"%s\" is not handled= by us\n", __func__, Uri));
+      &= nbsp; return EFI_SUCCESS;
+     &nbs= p;} else if (Status =3D=3D EFI_NOT_FOUND) {
+   &nb= sp;    DEBUG ((REDFISH_DEBUG_TRACE, "%a: \"%s\" has not= hing to handle\n", __func__, Uri));
+     = ;   return EFI_SUCCESS;
+    &n= bsp; }
+
+      D= EBUG ((DEBUG_ERROR, "%a: fail to identify resource: \"%s\": %r\n", __func__= , Uri, Status));
+      return Statu= s;
+    }
+  } else {
+    DEBUG ((REDFISH_DEBUG_TRACE, "%a: history reco= rd found: %s\n", __func__, ConfigLang));
+    = FreePool (ConfigLang);
+  }
+
+  //
+  // Check and see if target property exis= t or not even when collection member exists.
+  // If no= t, we sill do provision.

%s/sill/still

+  //
+ &nbs= p;DEBUG ((REDFISH_DEBUG_TRACE, "%a Check for %s\n", __func__, Uri));
+  Status =3D EdkIIRedfishResourceConfigCheck (&SchemaInfo= , Uri, NULL);
+  if (EFI_ERROR (Status)) {
+    if (Status =3D=3D EFI_UNSUPPORTED) {
+ &= nbsp;    DEBUG ((REDFISH_DEBUG_TRACE, "%a: \"%s\" is no= t handled by us\n", __func__, Uri));
+    &nbs= p; return EFI_SUCCESS;
+    }
+
+    //
+    = ;// The target property does not exist, do the provision to create property= .
+    //
+    DE= BUG ((REDFISH_DEBUG_TRACE, "%a provision for %s\n", __func__, Uri));
+    Status =3D EdkIIRedfishResourceConfigProvisioni= ng (&SchemaInfo, Uri, NULL, Private->InformationExchange, FALSE);+    if (EFI_ERROR (Status)) {
+ &= nbsp;    DEBUG ((DEBUG_ERROR, "%a: failed to provision = with GET mode: %r\n", __func__, Status));
+    = ;}
+
+    DEBUG ((REDFISH_DEBUG_= TRACE, "%a: process resource for: %s finished\n", __func__, Uri));
+
+    return Status;
+ &n= bsp;}
+
+  //
+  // Con= sume first.
+  //
+  DEBUG ((REDFISH_= DEBUG_TRACE, "%a consume for %s\n", __func__, Uri));
+  = Status =3D EdkIIRedfishResourceConfigConsume (&SchemaInfo, Uri, NULL);<= br class=3D"">+  if (EFI_ERROR (Status)) {
+   = ; DEBUG ((DEBUG_ERROR, "%a: failed to consume resource for: %s: %r\n",= __func__, Uri, Status));
+  }
+
+  //
+  // Patch.
+  //+  DEBUG ((REDFISH_DEBUG_TRACE, "%a update for %s\n", __f= unc__, Uri));
+  Status =3D EdkIIRedfishResourceConfigUp= date (&SchemaInfo, Uri, NULL);
+  if (EFI_ERROR (Sta= tus)) {
+    DEBUG ((DEBUG_ERROR, "%a: failed = to update resource for: %s: %r\n", __func__, Uri, Status));
+=  }
+
+  DEBUG ((REDFISH_DEBUG_TRACE,= "%a: process resource for: %s finished\n", __func__, Uri));
= +
+  return Status;
+}
diff = --git a/RedfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/SecureBootDxe.c b/R= edfishClientPkg/Features/SecureBoot/v1_1_0/Dxe/SecureBootDxe.c
new file mode 100644
index 000000000..a0f4f3d14
--- /dev/null
+++ b/RedfishClientPkg/Features/SecureBoot/v= 1_1_0/Dxe/SecureBootDxe.c
@@ -0,0 +1,808 @@
+/*= * @file
+  Redfish feature driver implementation - Secur= eBoot
+
+  (C) Copyright 2020-2022 Hewlett= Packard Enterprise Development LP<BR>
+  Copyrigh= t (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+  SPDX-License-Identifier: BSD-2-Clause-Pate= nt
+
+**/
+
+#inclu= de "../Common/SecureBootCommon.h"
+
+extern RED= FISH_RESOURCE_COMMON_PRIVATE  *mRedfishResourcePrivate;
= +extern EFI_HANDLE          &n= bsp;            = ;mRedfishResourceConfigProtocolHandle;
+
+EFI_S= TATUS
+HandleResource (
+  IN  REDFIS= H_RESOURCE_COMMON_PRIVATE  *Private,
+  IN  EF= I_STRING            =            Uri
+  );
+
+/**
+ &nbs= p;Provisioning redfish resource by given URI.
+
+  @param[in]   This       &n= bsp;        Pointer to EFI_HP_REDFI= SH_HII_PROTOCOL instance.
+  @param[in]   Uri =             &nb= sp;   Target URI to create resource.
+  @= param[in]   PostMode        &n= bsp;   TRUE if the resource does not exist, post method is u= sed.
+          =             &nb= sp;            = FALSE if the resource exist but property is missing, put method is used.+
+  @retval EFI_SUCCESS    &= nbsp;         Value is returne= d successfully.
+  @retval Others    &nbs= p;            &= nbsp; Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishResourceProvi= sioningResource (
+  IN     EDKII_RE= DFISH_RESOURCE_CONFIG_PROTOCOL  *This,
+  IN  =    EFI_STRING        &nbs= p;            &= nbsp;        Uri,
+ &= nbsp;IN     BOOLEAN       = ;            &n= bsp;            = ; PostMode
+  )
+{
+ &n= bsp;REDFISH_RESOURCE_COMMON_PRIVATE  *Private;
+  E= FI_STATUS            = ;           Status;<= br class=3D"">+  REDFISH_RESPONSE       =           Response;
+
+  if ((This =3D=3D NULL) || IS_EMPTY_STRING = (Uri)) {
+    return EFI_INVALID_PARAMETER;+  }
+
+  DEBUG ((REDFISH= _DEBUG_TRACE, "%a: provisioning in %s mode\n", __func__, (PostMode ? L"POST= " : L"PATCH")));


This message conflicts with PostMode parameter descri= ption.

+
+  ZeroMem (&Response, sizeof (REDFISH_RESP= ONSE));
+  Private =3D REDFISH_RESOURCE_COMMON_PRIVATE_D= ATA_FROM_RESOURCE_PROTOCOL (This);
+
+  if= (Private->RedfishService =3D=3D NULL) {
+   &nb= sp;return EFI_NOT_READY;
+  }
+
+  Status =3D RedfishHttpGetResource (Private->RedfishService= , Uri, NULL, &Response, TRUE);
+  if (EFI_ERROR (Sta= tus)) {
+    DEBUG ((DEBUG_ERROR, "%a: get res= ource from: %s failed\n", __func__, Uri));
+   &nbs= p;return Status;
+  }
+
+ &n= bsp;Private->Uri     =3D Uri;
+  = Private->Payload =3D Response.Payload;
+  ASSERT (Pri= vate->Payload !=3D NULL);
+
+  Status = =3D RedfishProvisioningResourceCommon (Private, !PostMode);
+=  if (EFI_ERROR (Status)) {
+    DEBUG ((= DEBUG_ERROR, "%a: failed to provision resource to: %s: %r\n", __func__, Uri= , Status));
+  } else {
+   &nbs= p;//
+    // Get latest ETag on URI and keep i= t in variable.
+    //
+  &= nbsp; SetEtagFromUri (Private->RedfishService, Private->Uri, TRU= E);
+  }
+
+  //
+  // Release resource
+  //
= +  RedfishHttpFreeResponse (&Response);
+  Priv= ate->Payload =3D NULL;
+
+  return Stat= us;
+}
+
+/**
+ &nb= sp;Consume resource from given URI.
+
+  @= param[in]   This         =        Pointer to EFI_HP_REDFISH_HII_PRO= TOCOL instance.
+  @param[in]   Uri  &nbs= p;            &= nbsp; The target URI to consume.
+
+  = ;@retval EFI_SUCCESS          =     Value is returned successfully.
+ &nb= sp;@retval Others          &nb= sp;        Some error happened.
+
+**/
+EFI_STATUS
+EF= IAPI
+RedfishResourceConsumeResource (
+  = IN     EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  *Th= is,
+  IN     EFI_STRING   = ;            &n= bsp;            = ;  Uri
+  )
+{
+ &= nbsp;REDFISH_RESOURCE_COMMON_PRIVATE  *Private;
+  = EFI_STATUS           &nbs= p;           Status;=
+  REDFISH_RESPONSE       = ;          Response;
+  EFI_STRING        &nbs= p;            &= nbsp; PendingSettingUri;
+  REDFISH_RESPONSE  =             &nb= sp;  PendingSettingResponse;
+  REDFISH_RESPON= SE             =     *ExpectedResponse;
+  CHAR8 &nbs= p;            &= nbsp;           &nbs= p; *Etag;
+
+  if ((This =3D=3D NULL)= || IS_EMPTY_STRING (Uri)) {
+    return EFI_I= NVALID_PARAMETER;
+  }
+
+ &= nbsp;ZeroMem (&Response, sizeof (REDFISH_RESPONSE));
+ &n= bsp;ZeroMem (&PendingSettingResponse, sizeof (REDFISH_RESPONSE));
+  Private =3D REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESO= URCE_PROTOCOL (This);
+
+  if (Private->= ;RedfishService =3D=3D NULL) {
+    return EFI= _NOT_READY;
+  }
+
+  S= tatus =3D RedfishHttpGetResource (Private->RedfishService, Uri, NULL, &a= mp;Response, TRUE);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: get resource from: %s = failed\n", __func__, Uri));
+    return Status= ;
+  }
+
+  //
+  // Check and see if "@Redfish.Settings" exist or not.
+  //
+  PendingSettingUri =3D NULL;
+  Status          = ;  =3D GetPendingSettings (
+    &nb= sp;            =        Private->RedfishService,
+           &nbs= p;            R= esponse.Payload,
+        =             &nb= sp;   &PendingSettingResponse,
+  &nb= sp;            =          &PendingSettingUr= i
+          &nb= sp;            =  );
+  if (!EFI_ERROR (Status)) {
+ &= nbsp;  DEBUG ((REDFISH_DEBUG_TRACE, "%a: @Redfish.Settings found:= %s\n", __func__, PendingSettingUri));
+    Pr= ivate->Uri     =3D PendingSettingUri;
= +    ExpectedResponse =3D &PendingSettingResponse;
+  } else {
+    Private->Uri=     =3D Uri;
+    Expecte= dResponse =3D &Response;
+  }
+
+  Private->Payload =3D ExpectedResponse->Payload;
+  ASSERT (Private->Payload !=3D NULL);
++  Private->Json =3D JsonDumpString (RedfishJsonInPaylo= ad (Private->Payload), EDKII_JSON_COMPACT);
+  ASSERT= (Private->Json !=3D NULL);
+
+  //
+  // Searching for etag in HTTP response header
+  //
+  Etag   =3D NULL;
+  Status =3D GetHttpResponseEtag (ExpectedResponse, &Etag);=
+  if (EFI_ERROR (Status)) {
+  &nbs= p; DEBUG ((DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", _= _func__));
+  }
+
+  St= atus =3D RedfishConsumeResourceCommon (Private, Private->Json, Etag);+  if (EFI_ERROR (Status)) {
+   &= nbsp;DEBUG ((DEBUG_ERROR, "%a: failed to consume resource from: %s: %r\n", = __func__, Private->Uri, Status));
+  }
= +
+  //
+  // Release resource
+  //
+  RedfishHttpFreeResponse (&Resp= onse);
+  RedfishHttpFreeResponse (&PendingSettingRe= sponse);
+  Private->Payload =3D NULL;
= +
+  if (Private->Json !=3D NULL) {
+ &= nbsp;  FreePool (Private->Json);
+   &= nbsp;Private->Json =3D NULL;
+  }
+
+  if (Etag !=3D NULL) {
+    = FreePool (Etag);
+  }
+
+ &n= bsp;if (PendingSettingUri !=3D NULL) {
+    Fr= eePool (PendingSettingUri);
+  }
+
+  return Status;
+}
+
+/**
+  Get information about this protocol.
+
+  @param[in]   This    = ;            Po= inter to EFI_HP_REDFISH_HII_PROTOCOL instance.
+  @param= [out]  Schema          &n= bsp;   Supported schema.
+  @param[out] &= nbsp;Major           &nbs= p;   Supported major number.
+  @param[ou= t]  Minor           =     Supported minor number.
+  @para= m[out]  Errata          &= nbsp;   Supported errata number.
+
+  @retval EFI_SUCCESS        &n= bsp;     Value is returned successfully.
+  @retval Others        &nbs= p;          Some error ha= ppened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishResourceGetInfo (
+ &nb= sp;IN     EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  = *This,
+  OUT    REDFISH_SCHEMA_INFO &nbs= p;            &= nbsp;      *Info
+  )
+{
+  if ((This =3D=3D NULL) || (Info =3D=3D N= ULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AsciiStrCpyS (In= fo->Schema, REDFISH_SCHEMA_STRING_SIZE, RESOURCE_SCHEMA);
= +  AsciiStrCpyS (Info->Major, REDFISH_SCHEMA_VERSION_SIZE, RESOURCE= _SCHEMA_MAJOR);
+  AsciiStrCpyS (Info->Minor, REDFISH= _SCHEMA_VERSION_SIZE, RESOURCE_SCHEMA_MINOR);
+  AsciiSt= rCpyS (Info->Errata, REDFISH_SCHEMA_VERSION_SIZE, RESOURCE_SCHEMA_ERRATA= );
+
+  return EFI_SUCCESS;
= +}
+
+/**
+  Update resource= to given URI.
+
+  @param[in]   = ;This            &nb= sp;   Pointer to EFI_HP_REDFISH_HII_PROTOCOL instance.
+  @param[in]   Uri      &= nbsp;          The target= URI to consume.
+
+  @retval EFI_SUCCESS =             &nb= sp;Value is returned successfully.
+  @retval Others &nb= sp;            =      Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+R= edfishResourceUpdate (
+  IN     EDK= II_REDFISH_RESOURCE_CONFIG_PROTOCOL  *This,
+  IN &= nbsp;   EFI_STRING        = ;            &n= bsp;         Uri
+  )
+{
+  REDFISH_RESOURCE_COMMON_P= RIVATE  *Private;
+  EFI_STATUS    &= nbsp;           &nbs= p;      Status;
+  REDFISH= _RESPONSE            = ;     Response;
+
+ &n= bsp;if ((This =3D=3D NULL) || IS_EMPTY_STRING (Uri)) {
+ &nbs= p;  return EFI_INVALID_PARAMETER;
+  }
+
+  ZeroMem (&Response, sizeof (REDFISH_RESP= ONSE));
+  Private =3D REDFISH_RESOURCE_COMMON_PRIVATE_D= ATA_FROM_RESOURCE_PROTOCOL (This);
+
+  if= (Private->RedfishService =3D=3D NULL) {
+   &nb= sp;return EFI_NOT_READY;
+  }
+
+  Status =3D RedfishHttpGetResource (Private->RedfishService= , Uri, NULL, &Response, TRUE);
+  if (EFI_ERROR (Sta= tus)) {
+    DEBUG ((DEBUG_ERROR, "%a: get res= ource from: %s failed\n", __func__, Uri));
+   &nbs= p;return Status;
+  }
+
+ &n= bsp;Private->Uri     =3D Uri;
+  = Private->Payload =3D Response.Payload;
+  ASSERT (Pri= vate->Payload !=3D NULL);
+
+  Private-= >Json =3D JsonDumpString (RedfishJsonInPayload (Private->Payload), ED= KII_JSON_COMPACT);
+  ASSERT (Private->Json !=3D NULL= );
+
+  Status =3D RedfishUpdateResourceCo= mmon (Private, Private->Json);
+  if (EFI_ERROR (Stat= us)) {
+    DEBUG ((DEBUG_ERROR, "%a: failed t= o update resource to: %s: %r\n", __func__, Uri, Status));
+ &= nbsp;} else {
+    //
+  &n= bsp; // Get latest ETag on URI and keep it in variable.
= +    //
+    SetEtagFromUri (Pr= ivate->RedfishService, Private->Uri, TRUE);
+  }+
+  //
+  // Release re= source
+  //
+  RedfishHttpFreeRespon= se (&Response);
+  Private->Payload =3D NULL;
+
+  if (Private->Json !=3D NULL) {
+    FreePool (Private->Json);
+ &n= bsp;  Private->Json =3D NULL;
+  }
+
+  return Status;
+}
+
+/**
+  Check resource on given URI.+
+  @param[in]   This   = ;            &n= bsp;Pointer to EFI_HP_REDFISH_HII_PROTOCOL instance.
+  = @param[in]   Uri         =         The target URI to consume.<= br class=3D"">+
+  @retval EFI_SUCCESS    = ;          Value is retur= ned successfully.
+  @retval Others    &n= bsp;            = ;  Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishResourceChe= ck (
+  IN     EDKII_REDFISH_RESOURC= E_CONFIG_PROTOCOL  *This,
+  IN    &= nbsp;EFI_STRING           = ;            &n= bsp;      Uri
+  )
+{
+  REDFISH_RESOURCE_COMMON_PRIVATE  *Priv= ate;
+  EFI_STATUS       &= nbsp;           &nbs= p;   Status;
+  REDFISH_RESPONSE  &n= bsp;            = ;  Response;
+  CHAR8     =             &nb= sp;          *Etag;
+
+  if ((This =3D=3D NULL) || IS_EMPTY_STRING = (Uri)) {
+    return EFI_INVALID_PARAMETER;+  }
+
+  ZeroMem (&R= esponse, sizeof (REDFISH_RESPONSE));
+  Private =3D REDF= ISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTOCOL (This);
+
+  if (Private->RedfishService =3D=3D NULL) {+    return EFI_NOT_READY;
+  = ;}
+
+  Status =3D RedfishHttpGetResource = (Private->RedfishService, Uri, NULL, &Response, TRUE);
+  if (EFI_ERROR (Status)) {
+    DEBUG = ((DEBUG_ERROR, "%a: get resource from: %s failed\n", __func__, Uri));
+    return Status;
+  }
+
+  Private->Uri     =3D = Uri;
+  Private->Payload =3D Response.Payload;
+  ASSERT (Private->Payload !=3D NULL);
+
+  Private->Json =3D JsonDumpString (RedfishJsonInPayloa= d (Private->Payload), EDKII_JSON_COMPACT);
+  ASSERT = (Private->Json !=3D NULL);
+
+  //
+  // Find etag in HTTP response header
+ &nbs= p;//
+  Etag   =3D NULL;
+  = ;Status =3D GetHttpResponseEtag (&Response, &Etag);
+=  if (EFI_ERROR (Status)) {
+    DEBUG ((= DEBUG_ERROR, "%a: failed to get ETag from HTTP header\n", __func__));
+  }
+
+  Status =3D Redfish= CheckResourceCommon (Private, Private->Json, Etag);
+ &nbs= p;if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG= _ERROR, "%a: failed to check resource from: %s: %r\n", __func__, Uri, Statu= s));
+  }
+
+  //
+  // Release resource
+  //
+  if (Etag !=3D NULL) {
+    FreePool (= Etag);
+  }
+
+  Redfis= hHttpFreeResponse (&Response);
+  Private->Payloa= d =3D NULL;
+
+  if (Private->Json !=3D= NULL) {
+    FreePool (Private->Json);
+    Private->Json =3D NULL;
+ &= nbsp;}
+
+  return Status;
+= }
+
+/**
+  Identify resourc= e on given URI.
+
+  @param[in]  &nbs= p;This            &n= bsp;   Pointer to EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL ins= tance.
+  @param[in]   Uri    &= nbsp;           &nbs= p;The target URI to consume.
+
+  @retval = EFI_SUCCESS           &nb= sp;  This is target resource which we want to handle.
+  @retval EFI_UNSUPPORTED       &nbs= p;  This is not the target resource.
+  @retva= l Others            =        Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishResourceIdentify (
+  IN   &= nbsp; EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  *This,
+  IN     EFI_STRING     &nb= sp;            =             Uri=
+  )
+{
+  REDFISH_RES= OURCE_COMMON_PRIVATE  *Private;
+  EFI_STATUS  = ;            &n= bsp;        Status;
+=  REDFISH_RESPONSE         &nb= sp;       Response;
+
+  if ((This =3D=3D NULL) || IS_EMPTY_STRING (Uri)) {
+    return EFI_INVALID_PARAMETER;
+ &= nbsp;}
+
+  ZeroMem (&Response, sizeof= (REDFISH_RESPONSE));
+  Private =3D REDFISH_RESOURCE_CO= MMON_PRIVATE_DATA_FROM_RESOURCE_PROTOCOL (This);
+
+  if (Private->RedfishService =3D=3D NULL) {
+=    return EFI_NOT_READY;
+  }
+
+  Status =3D RedfishHttpGetResource (Private-&g= t;RedfishService, Uri, NULL, &Response, TRUE);
+  if= (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERR= OR, "%a: get resource from: %s failed\n", __func__, Uri));
+ =    return Status;
+  }
++  Private->Uri     =3D Uri;
+  Private->Payload =3D Response.Payload;
+ &= nbsp;ASSERT (Private->Payload !=3D NULL);
+
= +  Private->Json =3D JsonDumpString (RedfishJsonInPayload (Private-= >Payload), EDKII_JSON_COMPACT);
+  ASSERT (Private-&g= t;Json !=3D NULL);
+
+  Status =3D Redfish= IdentifyResourceCommon (Private, Private->Json);
+  i= f (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ER= ROR, "%a: identify %s failed: %r\n", __func__, Uri, Status));
+  }
+
+  //
+  /= / Release resource
+  //
+  RedfishHt= tpFreeResponse (&Response);
+  Private->Payload = =3D NULL;
+
+  if (Private->Json !=3D N= ULL) {
+    FreePool (Private->Json);
+    Private->Json =3D NULL;
+ &nb= sp;}
+
+  return Status;
+}<= br class=3D"">+
+EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL  = ;mRedfishResourceConfig =3D {
+  RedfishResourceProvisio= ningResource,
+  RedfishResourceConsumeResource,
+  RedfishResourceUpdate,
+  RedfishResource= Check,
+  RedfishResourceIdentify,
+  = ;RedfishResourceGetInfo
+};
+
+/*= *
+  Initialize a Redfish configure handler.
+
+  This function will be called by the Redfish conf= ig driver to initialize each Redfish configure
+  handle= r.
+
+  @param[in]   This  =             &nb= sp;      Pointer to EDKII_REDFISH_CONFIG_HAND= LER_PROTOCOL instance.
+  @param[in]   Redfish= ConfigServiceInfo Redfish service information.
+
+  @retval EFI_SUCCESS        &nb= sp;         The handler has be= en initialized successfully.
+  @retval EFI_DEVICE_ERROR=             Fa= iled to create or configure the REST EX protocol instance.
+ =  @retval EFI_ALREADY_STARTED        = ;  This handler has already been initialized.
+ &nb= sp;@retval Other          &nbs= p;            &= nbsp;Error happens during the initialization.
+
+**/
+EFI_STATUS
+EFIAPI
+Redfis= hResourceInit (
+  IN  EDKII_REDFISH_CONFIG_HANDLER= _PROTOCOL  *This,
+  IN  REDFISH_CONFIG_SERVIC= E_INFORMATION     *RedfishConfigServiceInfo
+  )
+{
+  REDFISH_RESOURCE_COMMON= _PRIVATE  *Private;
+
+  Private =3D = REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_CONFIG_PROTOCOL (This);
+
+  Private->RedfishService =3D RedfishCreateS= ervice (RedfishConfigServiceInfo);
+  if (Private->Re= dfishService =3D=3D NULL) {
+    return EFI_DE= VICE_ERROR;
+  }
+
+  r= eturn EFI_SUCCESS;
+}
+
+/**
+  Stop a Redfish configure handler.
+
+  @param[in]   This      &n= bsp;         Pointer to EDKII_= REDFISH_CONFIG_HANDLER_PROTOCOL instance.
+
+ &= nbsp;@retval EFI_SUCCESS         &n= bsp;    This handler has been stoped successfully.
+  @retval Others        =            Some erro= r happened.
+
+**/
+EFI_STATUS+EFIAPI
+RedfishResourceStop (
+ &n= bsp;IN  EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL  *This
+  )
+{
+  REDFISH_RESOURCE_COMMON_= PRIVATE  *Private;
+
+  Private =3D R= EDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_CONFIG_PROTOCOL (This);
+
+  if (Private->Event !=3D NULL) {
+    gBS->CloseEvent (Private->Event);
+    Private->Event =3D NULL;
+  = ;}
+
+  if (Private->RedfishService != =3D NULL) {
+    RedfishCleanupService (Privat= e->RedfishService);
+    Private->Redfis= hService =3D NULL;
+  }
+
+ =  return EFI_SUCCESS;
+}
+
+E= DKII_REDFISH_CONFIG_HANDLER_PROTOCOL  mRedfishConfigHandler =3D {
+  RedfishResourceInit,
+  RedfishResourc= eStop
+};
+
+/**
+ =  Callback function when gEfiRestJsonStructureProtocolGuid is installed= .
+
+  @param[in] Event    = Event whose notification function is being invoked.
+  @= param[in] Context  Pointer to the notification function's context.
+**/
+VOID
+EFIAPI
+Ef= iRestJsonStructureProtocolIsReady (
+  IN  EFI_EVEN= T  Event,
+  IN  VOID     =   *Context
+  )
+{
+  EFI_STATUS  Status;
+
+  if = (mRedfishResourcePrivate =3D=3D NULL) {
+    r= eturn;
+  }
+
+  if (mR= edfishResourcePrivate->JsonStructProtocol !=3D NULL) {
+ &= nbsp;  return;
+  }
+
+  Status =3D gBS->LocateProtocol (
+  &nb= sp;            =    &gEfiRestJsonStructureProtocolGuid,
+ &= nbsp;           &nbs= p;    NULL,
+     &nb= sp;            = (VOID **)&mRedfishResourcePrivate->JsonStructProtocol
= +             &= nbsp;    );
+  if (EFI_ERROR (Status= )) {
+    DEBUG ((DEBUG_ERROR, "%a: failed to = locate gEfiRestJsonStructureProtocolGuid: %r\n", __func__, Status));
+  }
+
+  gBS->CloseEvent = (Event);
+}
+
+/**
= +  Unloads an image.
+
+  @param &nbs= p;ImageHandle           H= andle that identifies the image to be unloaded.
+
+  @retval EFI_SUCCESS        &n= bsp;  The image has been unloaded.
+  @retval = EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishResourceUnload (
+  IN EFI_HANDLE &nbs= p;ImageHandle
+  )
+{
+ &nbs= p;EFI_STATUS           &n= bsp;            = ;     Status;
+  EDKII_REDFISH_= CONFIG_HANDLER_PROTOCOL  *ConfigHandler;
+
+  if (mRedfishResourcePrivate =3D=3D NULL) {
+  &= nbsp; return EFI_NOT_READY;
+  }
++  ConfigHandler =3D NULL;
+
+=  //
+  // Firstly, find ConfigHandler Protocol int= erface in this ImageHandle.
+  //
+  = Status =3D gBS->OpenProtocol (
+     &= nbsp;           &nbs= p;ImageHandle,
+        &n= bsp;         &gEdkIIRedfis= hConfigHandlerProtocolGuid,
+      &= nbsp;           (VOI= D **)&ConfigHandler,
+      &nbs= p;           NULL,+           =        NULL,
+   = ;            &n= bsp;  EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+  =             &nb= sp;   );
+  if (EFI_ERROR (Status) || (Co= nfigHandler =3D=3D NULL)) {
+    return Status= ;
+  }
+
+  ConfigHandl= er->Stop (ConfigHandler);
+
+  //
+  // Last, uninstall ConfigHandler Protocol and resource pro= tocol.
+  //
+  Status =3D gBS->Un= installMultipleProtocolInterfaces (
+     = ;            &n= bsp;ImageHandle,
+        =           &gEdkIIRedf= ishConfigHandlerProtocolGuid,
+      = ;            Co= nfigHandler,
+        &nbs= p;         &gEdkIIRedfishR= esourceConfigProtocolGuid,
+      &n= bsp;           &= mRedfishResourcePrivate->RedfishResourceConfig,
+  &n= bsp;            = ;   NULL
+       = ;           );
+
+  FreePool (mRedfishResourcePrivate);
+  mRedfishResourcePrivate =3D NULL;
+
+  return Status;
+}
+
+/**
+  The callback function provided by Redfish Featu= re driver.
+
+  @param[in]   &nb= sp; This           &= nbsp;    Pointer to EDKII_REDFISH_FEATURE_PROTOCOL inst= ance.
+  @param[in]     FeatureActio= n       The action Redfish feature driver sho= uld take.
+  @param[in]     Uri &nbs= p;            &= nbsp;  The collection URI.
+  @param[in]  = ;   Context         =     The context of Redfish feature driver.
+  @param[in,out] InformationExchange The pointer to RESOURCE_INFORM= ATION_EXCHANGE
+
+  @retval EFI_SUCCESS &n= bsp;            = ;Redfish feature driver callback is executed successfully.
+ =  @retval Others          =          Some errors happened.=
+
+  @retval EFI_SUCCESS   &nbs= p;          Redfish featu= re driver callback is executed successfully.
+  @retval = Others            &n= bsp;      Some errors happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishExternalResourceResourceFeatureCallback (
+ =  IN     EDKII_REDFISH_FEATURE_PROTOCOL  *This= ,
+  IN     FEATURE_CALLBACK_ACTION =         FeatureAction,
+  IN     VOID      &nb= sp;            =          *Context,
+  IN OUT RESOURCE_INFORMATION_EXCHANGE   *InformationExc= hange
+  )
+{
+  EFI_ST= ATUS            &nbs= p;          Status;
+  REDFISH_SERVICE        =           RedfishService;=
+  REDFISH_RESOURCE_COMMON_PRIVATE  *Private;
+  EFI_STRING        &nbs= p;            &= nbsp; ResourceUri;
+  EFI_STRING    =             &nb= sp;      SecureBootUri;
+
+  if (FeatureAction !=3D CallbackActionStartOperation) {
+    return EFI_UNSUPPORTED;
+ &nbs= p;}
+
+  Private =3D (REDFISH_RESOURCE_COM= MON_PRIVATE *)Context;
+
+  RedfishService= =3D Private->RedfishService;
+  if (RedfishService = =3D=3D NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: = no Redfish service configured\n", __func__));
+   &= nbsp;return EFI_NOT_READY;
+  }
+
+  //
+  // Save in private structure.
+  //
+  Private->InformationExchange = =3D InformationExchange;
+
+  //
+  // Find Redfish version on Redfish ser
+  = //
+  Private->RedfishVersion =3D RedfishGetVersion (= RedfishService);
+
+  //
+ &= nbsp;// Create the full URI from Redfish service root.
+ &nbs= p;//
+  ResourceUri =3D (EFI_STRING)AllocateZeroPool (MA= X_URI_LENGTH * sizeof (CHAR16));
+  if (ResourceUri =3D= =3D NULL) {
+    DEBUG ((DEBUG_ERROR, "%a: Fai= l to allocate memory for full URI.\n", __func__));
+  &n= bsp; return EFI_OUT_OF_RESOURCES;
+  }
+
+  StrCatS (ResourceUri, MAX_URI_LENGTH, Private->= ;RedfishVersion);
+  StrCatS (ResourceUri, MAX_URI_LENGT= H, InformationExchange->SendInformation.FullUri);
+
+  //
+  // Initialize collection path
+  //
+  SecureBootUri =3D RedfishGetUri = (ResourceUri);
+  if (SecureBootUri =3D=3D NULL) {
+    ASSERT (FALSE);
+   &n= bsp;FreePool (ResourceUri);
+    return EFI_OU= T_OF_RESOURCES;
+  }
+
+ &nb= sp;Status =3D HandleResource (Private, SecureBootUri);
+ &nbs= p;if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG= _ERROR, "%a: process external resource: %s failed: %r\n", __func__, SecureB= ootUri, Status));
+  }
+
+ &= nbsp;FreePool (SecureBootUri);
+  FreePool (ResourceUri)= ;
+  return Status;
+}
+
+/**
+  Callback function when gEdkIIRedfishF= eatureProtocolGuid is installed.
+
+  @par= am[in] Event    Event whose notification function is being i= nvoked.
+  @param[in] Context  Pointer to the notif= ication function's context.
+**/
+VOID
+EFIAPI
+EdkIIRedfishFeatureProtocolIsReady (
+  IN  EFI_EVENT  Event,
+  IN &nbs= p;VOID       *Context
+  )=
+{
+  EFI_STATUS     =             &nb= sp;    Status;
+  EDKII_REDFISH_FEAT= URE_PROTOCOL  *FeatureProtocol;
+
+  = if (mRedfishResourcePrivate =3D=3D NULL) {
+   &nbs= p;return;
+  }
+
+  if = (mRedfishResourcePrivate->FeatureProtocol !=3D NULL) {
+ &= nbsp;  return;
+  }
+
+  Status =3D gBS->LocateProtocol (
+  &nb= sp;            =    &gEdkIIRedfishFeatureProtocolGuid,
+ &n= bsp;            = ;    NULL,
+     &nbs= p;            (= VOID **)&FeatureProtocol
+      =             );<= br class=3D"">+  if (EFI_ERROR (Status)) {
+   = ; DEBUG ((DEBUG_ERROR, "%a: failed to locate gEdkIIRedfishFeatureProto= colGuid: %r\n", __func__, Status));
+    gBS-&= gt;CloseEvent (Event);
+    return;
+  }
+
+  Status =3D FeaturePro= tocol->Register (
+       &n= bsp;            = ;          FeatureProtoco= l,
+          &n= bsp;            = ;       REDFISH_MANAGED_URI,
+            &nbs= p;            &= nbsp;    RedfishExternalResourceResourceFeatureCallback= ,
+          &nb= sp;            =        (VOID *)mRedfishResourcePrivate+           =             &nb= sp;      );
+  if (EFI_ERR= OR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: = failed to register %s: %r\n", __func__, REDFISH_MANAGED_URI, Status));
+  }
+
+  mRedfishResourceP= rivate->FeatureProtocol =3D FeatureProtocol;
+
+  gBS->CloseEvent (Event);
+}
+
+/**
+  This is the declaration of an EFI ima= ge entry point. This entry point is
+  the same for UEFI= Applications, UEFI OS Loaders, and UEFI Drivers including
+ =  both device drivers and bus drivers. It initialize the global variabl= es and
+  publish the driver binding protocol.
+
+  @param[in]   ImageHandle  &nbs= p;   The firmware allocated handle for the UEFI image.
+  @param[in]   SystemTable     = ; A pointer to the EFI System Table.
+
+ &= nbsp;@retval EFI_SUCCESS         &n= bsp; The operation completed successfully.
+  @retv= al EFI_ACCESS_DENIED     EFI_ISCSI_INITIATOR_NAME_PROTO= COL was installed unexpectedly.
+  @retval Others  =             &nb= sp; Other errors as indicated.
+**/
+EFI_S= TATUS
+EFIAPI
+RedfishResourceEntryPoint (
+  IN EFI_HANDLE        I= mageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable+  )
+{
+  EFI_STATUS &nb= sp;Status;
+  VOID       &= nbsp;*Registration;
+
+  if (mRedfishResou= rcePrivate !=3D NULL) {
+    return EFI_ALREAD= Y_STARTED;
+  }
+
+  mR= edfishResourceConfigProtocolHandle =3D ImageHandle;
+
+  mRedfishResourcePrivate =3D AllocateZeroPool (sizeof (REDFIS= H_RESOURCE_COMMON_PRIVATE));
+  CopyMem (&mRedfishRe= sourcePrivate->ConfigHandler, &mRedfishConfigHandler, sizeof (EDKII_= REDFISH_CONFIG_HANDLER_PROTOCOL));
+  CopyMem (&mRed= fishResourcePrivate->RedfishResourceConfig, &mRedfishResourceConfig,= sizeof (EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL));
+
+  //
+  // Publish config handler protocol a= nd resource protocol.
+  //
+  Status= =3D gBS->InstallMultipleProtocolInterfaces (
+  &nbs= p;            &= nbsp;  &ImageHandle,
+     =             &nb= sp;&gEdkIIRedfishConfigHandlerProtocolGuid,
+   = ;            &n= bsp;  &mRedfishResourcePrivate->ConfigHandler,
+            &nbs= p;     &gEdkIIRedfishResourceConfigProtocolGui= d,
+          &n= bsp;       &mRedfishResourcePrivate-= >RedfishResourceConfig,
+      &n= bsp;           NULL<= br class=3D"">+           = ;       );
+
+  EfiCreateProtocolNotifyEvent (
+    &= amp;gEfiRestJsonStructureProtocolGuid,
+    TP= L_CALLBACK,
+    EfiRestJsonStructureProtocolI= sReady,
+    NULL,
+   = ; &Registration
+    );
+
+  EfiCreateProtocolNotifyEvent (
+ &nb= sp;  &gEdkIIRedfishFeatureProtocolGuid,
+  = ;  TPL_CALLBACK,
+    EdkIIRedfishFe= atureProtocolIsReady,
+    (VOID *)mRedfishRes= ourcePrivate,
+    &Registration
+    );
+
+  return S= tatus;
+}
diff --git a/RedfishClientPkg/Redfish= Client.fdf.inc b/RedfishClientPkg/RedfishClient.fdf.inc
index= 59b8acba1..154f641b2 100644
--- a/RedfishClientPkg/RedfishCl= ient.fdf.inc
+++ b/RedfishClientPkg/RedfishClient.fdf.inc
@@ -25,6 +25,7 @@
  INF RedfishClientPk= g/HiiToRedfishBiosDxe/HiiToRedfishBiosDxe.inf
  IN= F RedfishClientPkg/Features/BootOptionCollection/BootOptionCollectionDxe.in= f
  INF RedfishClientPkg/Features/BootOption/v1_0_= 4/Dxe/BootOptionDxe.inf
+  INF RedfishClientPkg/Features= /SecureBoot/v1_1_0/Dxe/SecureBootDxe.inf

&nbs= p; !include RedfishClientPkg/RedfishJsonStructureDxe.fdf.inc
  #
--
2.34.1
<= /div>



Regards,
Mike
=
_._,_._,_

Groups.io Links:

=20 You receive all messages sent to this group. =20 =20

View/Reply Online (#116774) | =20 | Mute= This Topic | New Topic
Your Subscriptio= n | Contact Group Owner | Unsubscribe [rebecca@openfw.io]

_._,_._,_
--Apple-Mail=_B03079E5-1E32-477E-9A61-1AAAE6D98DF8--