Date   

[PATCH v2] IntelFsp2Pkg: FSPI_UPD is not mandatory.

Chiu, Chasel
 

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3993
FSPI_UPD is required only When platforms implemented FSP_I component.
Updated the scripts to allow FSPI_UPD not present scenario.
Also fixed FSP_GLOBAL_DATA structure alignment issue and unnecessary
non-backward compatibility change in previous FSP_I patch.

Cc: Nate DeSimone <nathaniel.l.desimone@...>
Cc: Star Zeng <star.zeng@...>
Signed-off-by: Chasel Chiu <chasel.chiu@...>
---
IntelFsp2Pkg/Include/FspGlobalData.h | 43 +++++++++++++++++++++-----------=
-----------
IntelFsp2Pkg/Tools/GenCfgOpt.py | 14 ++++++++++----
2 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/IntelFsp2Pkg/Include/FspGlobalData.h b/IntelFsp2Pkg/Include/Fs=
pGlobalData.h
index cf94f7b6a5..32c6d460e4 100644
--- a/IntelFsp2Pkg/Include/FspGlobalData.h
+++ b/IntelFsp2Pkg/Include/FspGlobalData.h
@@ -42,58 +42,57 @@ typedef struct {
#define FSP_PERFORMANCE_DATA_TIMER_MASK 0xFFFFFFFFFFFFFF=0D
=0D
typedef struct {=0D
- UINT32 Signature;=0D
- UINT8 Version;=0D
- UINT8 Reserved1[3];=0D
+ UINT32 Signature;=0D
+ UINT8 Version;=0D
+ UINT8 Reserved1[3];=0D
///=0D
/// Offset 0x08=0D
///=0D
- UINTN CoreStack;=0D
- UINTN Reserved2;=0D
+ UINTN CoreStack;=0D
+ VOID *SmmInitUpdPtr;=0D
///=0D
/// IA32: Offset 0x10; X64: Offset 0x18=0D
///=0D
- UINT32 StatusCode;=0D
- UINT8 ApiIdx;=0D
+ UINT32 StatusCode;=0D
+ UINT8 ApiIdx;=0D
///=0D
/// 0: FSP in API mode; 1: FSP in DISPATCH mode=0D
///=0D
- UINT8 FspMode;=0D
- UINT8 OnSeparateStack;=0D
- UINT8 Reserved3;=0D
- UINT32 NumberOfPhases;=0D
- UINT32 PhasesExecuted;=0D
- UINT32 Reserved4[8];=0D
+ UINT8 FspMode;=0D
+ UINT8 OnSeparateStack;=0D
+ UINT8 Reserved2;=0D
+ UINT32 NumberOfPhases;=0D
+ UINT32 PhasesExecuted;=0D
+ UINT32 Reserved3[8];=0D
///=0D
/// IA32: Offset 0x40; X64: Offset 0x48=0D
/// Start of UINTN and pointer section=0D
- /// All UINTN and pointer members must be put in this section=0D
- /// except CoreStack and Reserved2. In addition, the number of=0D
- /// UINTN and pointer members must be even for natural alignment=0D
- /// in both IA32 and X64.=0D
+ /// All UINTN and pointer members are put in this section=0D
+ /// for maintaining natural alignment for both IA32 and X64 builds.=0D
///=0D
FSP_PLAT_DATA PlatformData;=0D
VOID *TempRamInitUpdPtr;=0D
VOID *MemoryInitUpdPtr;=0D
VOID *SiliconInitUpdPtr;=0D
- VOID *SmmInitUpdPtr;=0D
///=0D
- /// IA32: Offset 0x68; X64: Offset 0x98=0D
+ /// IA32: Offset 0x64; X64: Offset 0x90=0D
/// To store function parameters pointer=0D
/// so it can be retrieved after stack switched.=0D
///=0D
VOID *FunctionParameterPtr;=0D
FSP_INFO_HEADER *FspInfoHeader;=0D
VOID *UpdDataPtr;=0D
- UINTN Reserved5;=0D
///=0D
/// End of UINTN and pointer section=0D
+ /// At this point, next field offset must be either *0h or *8h to=0D
+ /// meet natural alignment requirement.=0D
///=0D
- UINT8 Reserved6[16];=0D
+ UINT8 Reserved4[16];=0D
UINT32 PerfSig;=0D
UINT16 PerfLen;=0D
- UINT16 Reserved7;=0D
+ UINT16 Reserved5;=0D
UINT32 PerfIdx;=0D
+ UINT32 Reserved6;=0D
UINT64 PerfData[32];=0D
} FSP_GLOBAL_DATA;=0D
=0D
diff --git a/IntelFsp2Pkg/Tools/GenCfgOpt.py b/IntelFsp2Pkg/Tools/GenCfgOpt=
.py
index 128b896592..71c48f10e0 100644
--- a/IntelFsp2Pkg/Tools/GenCfgOpt.py
+++ b/IntelFsp2Pkg/Tools/GenCfgOpt.py
@@ -959,8 +959,13 @@ EndList
UpdTxtFile =3D ''=0D
FvDir =3D self._FvDir=0D
if GuidList[Index] not in self._MacroDict:=0D
- self.Error =3D "%s definition is missing in DSC file" % (G=
uidList[Index])=0D
- return 1=0D
+ NoFSPI =3D False=0D
+ if GuidList[Index] =3D=3D 'FSP_I_UPD_TOOL_GUID':=0D
+ NoFSPI =3D True=0D
+ continue=0D
+ else:=0D
+ self.Error =3D "%s definition is missing in DSC file" =
% (GuidList[Index])=0D
+ return 1=0D
=0D
if UpdTxtFile =3D=3D '':=0D
UpdTxtFile =3D os.path.join(FvDir, self._MacroDict[GuidLis=
t[Index]] + '.txt')=0D
@@ -1296,7 +1301,8 @@ EndList
elif '_S' in SignatureStr[6:6+2]:=0D
TxtBody.append("#define FSPS_UPD_SIGNATURE =
%s /* '%s' */\n\n" % (Item['value'], SignatureStr))=0D
elif '_I' in SignatureStr[6:6+2]:=0D
- TxtBody.append("#define FSPI_UPD_SIGNATURE =
%s /* '%s' */\n\n" % (Item['value'], SignatureStr))=0D
+ if NoFSPI =3D=3D True:=0D
+ TxtBody.append("#define FSPI_UPD_SIGNATURE =
%s /* '%s' */\n\n" % (Item['value'], SignatureStr))=0D
TxtBody.append("\n")=0D
=0D
for Region in ['UPD']:=0D
@@ -1702,7 +1708,7 @@ EndList
=0D
=0D
def Usage():=0D
- print ("GenCfgOpt Version 0.58")=0D
+ print ("GenCfgOpt Version 0.59")=0D
print ("Usage:")=0D
print (" GenCfgOpt UPDTXT PlatformDscFile BuildFvDir =
[-D Macros]")=0D
print (" GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile =
[-D Macros]")=0D
--=20
2.35.0.windows.1


[PATCH v2 6/6] DynamicTablesPkg: AcpiSsdtPcieLibArm: Added case handling for PCI config

Kun Qin
 

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3998

This change added a switch case handling for PCI_SS_CONFIG during SSDT
generation. This will allow PCI config case return EFI_SUCCESS instead of
EFI_INVALID_PARAMETER.

Cc: Sami Mujawar <Sami.Mujawar@...>
Cc: Alexei Fedorov <Alexei.Fedorov@...>

Co-authored-by: Joe Lopez <joelopez@...>
Signed-off-by: Kun Qin <kuqin12@...>
Reviewed-by: Pierre Gondois <pierre.gondois@...>
---

Notes:
v2:
- Added Reviewed-by tag [Pierre]

DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c |=
5 +++++
1 file changed, 5 insertions(+)

diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieG=
enerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieG=
enerator.c
index c03550baabf2..2749cfabed6c 100644
--- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerato=
r.c
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerato=
r.c
@@ -603,6 +603,11 @@ GeneratePciCrs (
);=0D
break;=0D
=0D
+ case PCI_SS_CONFIG:=0D
+ // Do nothing=0D
+ Status =3D EFI_SUCCESS;=0D
+ break;=0D
+=0D
default:=0D
Status =3D EFI_INVALID_PARAMETER;=0D
} // switch=0D
--=20
2.37.1.windows.1


[PATCH v2 5/6] DynamicTablesPkg: AcpiSsdtPcieLibArm: Added function to reserve ECAM space

Kun Qin
 

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3998

Certain OSes will complain if the ECAM config space is not reserved in
the ACPI namespace.

This change adds a function to reserve PNP motherboard resources for a
given PCI node.

Co-authored-by: Joe Lopez <joelopez@...>
Signed-off-by: Kun Qin <kuqin12@...>
---

Notes:
v2:
- Only create RES0 after config space checking [Pierre]

DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c |=
169 ++++++++++++++++++++
1 file changed, 169 insertions(+)

diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieG=
enerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieG=
enerator.c
index ceffe2838c03..c03550baabf2 100644
--- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerato=
r.c
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerato=
r.c
@@ -616,6 +616,167 @@ GeneratePciCrs (
return Status;=0D
}=0D
=0D
+/** Generate a Pci Resource Template to hold Address Space Info=0D
+=0D
+ @param [in] PciNode RootNode of the AML tree.=0D
+ @param [in, out] CrsNode CRS node of the AML tree to populate.=0D
+=0D
+ @retval EFI_SUCCESS The function completed successfully.=0D
+ @retval EFI_INVALID_PARAMETER Invalid input parameter.=0D
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.=0D
+**/=0D
+STATIC=0D
+EFI_STATUS=0D
+EFIAPI=0D
+PopulateBasicPciResObjects (=0D
+ IN AML_OBJECT_NODE_HANDLE PciNode,=0D
+ IN OUT AML_OBJECT_NODE_HANDLE *CrsNode=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT32 EisaId;=0D
+ AML_OBJECT_NODE_HANDLE ResNode;=0D
+=0D
+ if (CrsNode =3D=3D NULL) {=0D
+ ASSERT (0);=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ // ASL: Device (PCIx) {}=0D
+ Status =3D AmlCodeGenDevice ("RES0", PciNode, &ResNode);=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT (0);=0D
+ return Status;=0D
+ }=0D
+=0D
+ // ASL: Name (_HID, EISAID ("PNP0C02"))=0D
+ Status =3D AmlGetEisaIdFromString ("PNP0C02", &EisaId); /* PNP Motherboa=
rd Resources */=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT (0);=0D
+ return Status;=0D
+ }=0D
+=0D
+ Status =3D AmlCodeGenNameInteger ("_HID", EisaId, ResNode, NULL);=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT (0);=0D
+ return Status;=0D
+ }=0D
+=0D
+ // ASL: Name (_CRS, ResourceTemplate () {})=0D
+ Status =3D AmlCodeGenNameResourceTemplate ("_CRS", ResNode, CrsNode);=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT (0);=0D
+ return Status;=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/** Generate a Pci Resource Template to hold Address Space Info=0D
+=0D
+ @param [in] Generator The SSDT Pci generator.=0D
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager=0D
+ Protocol interface.=0D
+ @param [in] PciInfo Pci device information.=0D
+ @param [in, out] PciNode RootNode of the AML tree to populate.=
=0D
+=0D
+ @retval EFI_SUCCESS The function completed successfully.=0D
+ @retval EFI_INVALID_PARAMETER Invalid parameter.=0D
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.=0D
+**/=0D
+STATIC=0D
+EFI_STATUS=0D
+EFIAPI=0D
+GeneratePciRes (=0D
+ IN ACPI_PCI_GENERATOR *Generator,=
=0D
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtoc=
ol,=0D
+ IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,=0D
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ AML_OBJECT_NODE_HANDLE CrsNode;=0D
+ BOOLEAN Translation;=0D
+ UINT32 Index;=0D
+ CM_ARM_OBJ_REF *RefInfo;=0D
+ UINT32 RefCount;=0D
+ CM_ARM_PCI_ADDRESS_MAP_INFO *AddrMapInfo;=0D
+ BOOLEAN IsPosDecode;=0D
+=0D
+ // Get the array of CM_ARM_OBJ_REF referencing the=0D
+ // CM_ARM_PCI_ADDRESS_MAP_INFO objects.=0D
+ Status =3D GetEArmObjCmRef (=0D
+ CfgMgrProtocol,=0D
+ PciInfo->AddressMapToken,=0D
+ &RefInfo,=0D
+ &RefCount=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT (0);=0D
+ return Status;=0D
+ }=0D
+=0D
+ for (Index =3D 0; Index < RefCount; Index++) {=0D
+ // Get CM_ARM_PCI_ADDRESS_MAP_INFO structures one by one.=0D
+ Status =3D GetEArmObjPciAddressMapInfo (=0D
+ CfgMgrProtocol,=0D
+ RefInfo[Index].ReferenceToken,=0D
+ &AddrMapInfo,=0D
+ NULL=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT (0);=0D
+ return Status;=0D
+ }=0D
+=0D
+ Translation =3D (AddrMapInfo->CpuAddress !=3D AddrMapInfo->PciAddress)=
;=0D
+ if (AddrMapInfo->CpuAddress >=3D AddrMapInfo->PciAddress) {=0D
+ IsPosDecode =3D TRUE;=0D
+ } else {=0D
+ IsPosDecode =3D FALSE;=0D
+ }=0D
+=0D
+ switch (AddrMapInfo->SpaceCode) {=0D
+ case PCI_SS_CONFIG:=0D
+ Status =3D PopulateBasicPciResObjects (PciNode, &CrsNode);=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT (0);=0D
+ break;=0D
+ }=0D
+=0D
+ Status =3D AmlCodeGenRdQWordMemory (=0D
+ FALSE,=0D
+ IsPosDecode,=0D
+ TRUE,=0D
+ TRUE,=0D
+ FALSE, // non-cacheable=0D
+ TRUE,=0D
+ 0,=0D
+ AddrMapInfo->PciAddress,=0D
+ AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,=
=0D
+ Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->Pc=
iAddress : 0,=0D
+ AddrMapInfo->AddressSize,=0D
+ 0,=0D
+ NULL,=0D
+ 0,=0D
+ TRUE,=0D
+ CrsNode,=0D
+ NULL=0D
+ );=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ } // switch=0D
+=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT (0);=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
/** Generate a Pci device.=0D
=0D
@param [in] Generator The SSDT Pci generator.=0D
@@ -702,9 +863,17 @@ GeneratePciDevice (
return Status;=0D
}=0D
=0D
+ // Add the PNP Motherboard Resources Device to reserve ECAM space=0D
+ Status =3D GeneratePciRes (Generator, CfgMgrProtocol, PciInfo, PciNode);=
=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT (0);=0D
+ return Status;=0D
+ }=0D
+=0D
// Add the template _OSC method.=0D
Status =3D AddOscMethod (PciInfo, PciNode);=0D
ASSERT_EFI_ERROR (Status);=0D
+=0D
return Status;=0D
}=0D
=0D
--=20
2.37.1.windows.1


[PATCH v2 4/6] DynamicTablesPkg: DynamicTableManagerDxe: Added check for installed tables

Kun Qin
 

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3997

This change added an extra step to allow check for installed ACPI tables.

For FADT, MADT, GTDT, DSDT, DBG2 and SPCR tables, either pre-installed or
supplied through AcpiTableInfo can be accepted.

An extra check for FADT ACPI table existence during installation step is
also added.

Cc: Sami Mujawar <Sami.Mujawar@...>
Cc: Alexei Fedorov <Alexei.Fedorov@...>

Co-authored-by: Joe Lopez <joelopez@...>
Signed-off-by: Kun Qin <kuqin12@...>
---

Notes:
v2:
- Function description updates [Sami]
- Refactorized the table verification [Pierre]

DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c =
| 182 +++++++++++---------
DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf=
| 1 +
2 files changed, 103 insertions(+), 80 deletions(-)

diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableMa=
nagerDxe.c b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableMa=
nagerDxe.c
index ed62299f9bbd..4ad7c0c8dbfa 100644
--- a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDx=
e.c
+++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDx=
e.c
@@ -10,6 +10,7 @@
#include <Library/DebugLib.h>=0D
#include <Library/PcdLib.h>=0D
#include <Library/UefiBootServicesTableLib.h>=0D
+#include <Protocol/AcpiSystemDescriptionTable.h>=0D
#include <Protocol/AcpiTable.h>=0D
=0D
// Module specific include files.=0D
@@ -22,6 +23,29 @@
#include <Protocol/DynamicTableFactoryProtocol.h>=0D
#include <SmbiosTableGenerator.h>=0D
=0D
+#define ACPI_TABLE_PRESENT_INFO_LIST BIT0=0D
+#define ACPI_TABLE_PRESENT_INSTALLED BIT1=0D
+=0D
+#define ACPI_TABLE_VERIFY_FADT 0=0D
+#define ACPI_TABLE_VERIFY_COUNT 6=0D
+=0D
+typedef struct {=0D
+ ESTD_ACPI_TABLE_ID EstdTableId;=0D
+ UINT32 AcpiTableSignature;=0D
+ CHAR8 AcpiTableName[sizeof (UINT32) + 1];=0D
+ BOOLEAN IsMandatory;=0D
+ UINT16 Presence;=0D
+} ACPI_TABLE_PRESENCE_INFO;=0D
+=0D
+ACPI_TABLE_PRESENCE_INFO mAcpiVerifyTables[ACPI_TABLE_VERIFY_COUNT] =3D {=
=0D
+ { EStdAcpiTableIdFadt, EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATU=
RE, "FADT", TRUE, 0 },=0D
+ { EStdAcpiTableIdMadt, EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGN=
ATURE, "MADT", TRUE, 0 },=0D
+ { EStdAcpiTableIdGtdt, EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGN=
ATURE, "GTDT", TRUE, 0 },=0D
+ { EStdAcpiTableIdDsdt, EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TA=
BLE_SIGNATURE, "DSDT", TRUE, 0 },=0D
+ { EStdAcpiTableIdDbg2, EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE, =
"DBG2", FALSE, 0 },=0D
+ { EStdAcpiTableIdSpcr, EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABL=
E_SIGNATURE, "SPCR", FALSE, 0 },=0D
+};=0D
+=0D
/** This macro expands to a function that retrieves the ACPI Table=0D
List from the Configuration Manager.=0D
*/=0D
@@ -395,6 +419,7 @@ BuildAndInstallAcpiTable (
=0D
@retval EFI_SUCCESS Success.=0D
@retval EFI_NOT_FOUND If mandatory table is not found.=0D
+ @retval EFI_ALREADY_STARTED If mandatory table found in AcpiTableInfo =
is already installed.=0D
**/=0D
STATIC=0D
EFI_STATUS=0D
@@ -404,75 +429,68 @@ VerifyMandatoryTablesArePresent (
IN UINT32 AcpiTableCount=0D
)=0D
{=0D
- EFI_STATUS Status;=0D
- BOOLEAN FadtFound;=0D
- BOOLEAN MadtFound;=0D
- BOOLEAN GtdtFound;=0D
- BOOLEAN DsdtFound;=0D
- BOOLEAN Dbg2Found;=0D
- BOOLEAN SpcrFound;=0D
+ EFI_STATUS Status;=0D
+ UINTN Handle;=0D
+ UINTN Index;=0D
+ UINTN InstalledTableIndex;=0D
+ EFI_ACPI_DESCRIPTION_HEADER *DescHeader;=0D
+ EFI_ACPI_TABLE_VERSION Version;=0D
+ EFI_ACPI_SDT_PROTOCOL *AcpiSdt;=0D
=0D
- Status =3D EFI_SUCCESS;=0D
- FadtFound =3D FALSE;=0D
- MadtFound =3D FALSE;=0D
- GtdtFound =3D FALSE;=0D
- DsdtFound =3D FALSE;=0D
- Dbg2Found =3D FALSE;=0D
- SpcrFound =3D FALSE;=0D
ASSERT (AcpiTableInfo !=3D NULL);=0D
=0D
+ Status =3D EFI_SUCCESS;=0D
+=0D
+ // Check against the statically initialized ACPI tables to see if they a=
re in ACPI info list=0D
while (AcpiTableCount-- !=3D 0) {=0D
- switch (AcpiTableInfo[AcpiTableCount].AcpiTableSignature) {=0D
- case EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:=0D
- FadtFound =3D TRUE;=0D
- break;=0D
- case EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:=0D
- MadtFound =3D TRUE;=0D
- break;=0D
- case EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE:=0D
- GtdtFound =3D TRUE;=0D
- break;=0D
- case EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:=
=0D
- DsdtFound =3D TRUE;=0D
- break;=0D
- case EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE:=0D
- Dbg2Found =3D TRUE;=0D
- break;=0D
- case EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:=0D
- SpcrFound =3D TRUE;=0D
- break;=0D
- default:=0D
- break;=0D
+ for (Index =3D 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {=0D
+ if (AcpiTableInfo[AcpiTableCount].AcpiTableSignature =3D=3D mAcpiVer=
ifyTables[Index].AcpiTableSignature) {=0D
+ mAcpiVerifyTables[Index].Presence |=3D ACPI_TABLE_PRESENT_INFO_LIS=
T;=0D
+ }=0D
}=0D
}=0D
=0D
- // We need at least the FADT, MADT, GTDT and the DSDT tables to boot=0D
- if (!FadtFound) {=0D
- DEBUG ((DEBUG_ERROR, "ERROR: FADT Table not found\n"));=0D
- Status =3D EFI_NOT_FOUND;=0D
- }=0D
+ // They also might be published already, so we can search from there=0D
+ AcpiSdt =3D NULL;=0D
+ Status =3D gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID *=
*)&AcpiSdt);=0D
=0D
- if (!MadtFound) {=0D
- DEBUG ((DEBUG_ERROR, "ERROR: MADT Table not found.\n"));=0D
- Status =3D EFI_NOT_FOUND;=0D
+ if (EFI_ERROR (Status) || (AcpiSdt =3D=3D NULL)) {=0D
+ DEBUG ((DEBUG_WARN, "WARNING: Failed to locate ACPI SDT protocol (0x%p=
) - %r\n", AcpiSdt, Status));=0D
+ goto EvaluatePresence;=0D
}=0D
=0D
- if (!GtdtFound) {=0D
- DEBUG ((DEBUG_ERROR, "ERROR: GTDT Table not found.\n"));=0D
- Status =3D EFI_NOT_FOUND;=0D
- }=0D
+ for (Index =3D 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {=0D
+ Handle =3D 0;=0D
+ InstalledTableIndex =3D 0;=0D
+ do {=0D
+ Status =3D AcpiSdt->GetAcpiTable (InstalledTableIndex, (EFI_ACPI_SDT=
_HEADER **)&DescHeader, &Version, &Handle);=0D
+ if (EFI_ERROR (Status)) {=0D
+ break;=0D
+ }=0D
=0D
- if (!DsdtFound) {=0D
- DEBUG ((DEBUG_ERROR, "ERROR: DSDT Table not found.\n"));=0D
- Status =3D EFI_NOT_FOUND;=0D
- }=0D
+ InstalledTableIndex++;=0D
+ } while (DescHeader->Signature !=3D mAcpiVerifyTables[Index].AcpiTable=
Signature);=0D
=0D
- if (!Dbg2Found) {=0D
- DEBUG ((DEBUG_WARN, "WARNING: DBG2 Table not found.\n"));=0D
+ if (!EFI_ERROR (Status)) {=0D
+ mAcpiVerifyTables[Index].Presence |=3D ACPI_TABLE_PRESENT_INSTALLED;=
=0D
+ }=0D
}=0D
=0D
- if (!SpcrFound) {=0D
- DEBUG ((DEBUG_WARN, "WARNING: SPCR Table not found.\n"));=0D
+EvaluatePresence:=0D
+ for (Index =3D 0; Index < ACPI_TABLE_VERIFY_COUNT; Index++) {=0D
+ if (mAcpiVerifyTables[Index].Presence =3D=3D 0) {=0D
+ if (mAcpiVerifyTables[Index].IsMandatory) {=0D
+ DEBUG ((DEBUG_ERROR, "ERROR: %a Table not found.\n", mAcpiVerifyTa=
bles[Index].AcpiTableName));=0D
+ Status =3D EFI_NOT_FOUND;=0D
+ } else {=0D
+ DEBUG ((DEBUG_WARN, "WARNING: %a Table not found.\n", mAcpiVerifyT=
ables[Index].AcpiTableName));=0D
+ }=0D
+ } else if (mAcpiVerifyTables[Index].Presence =3D=3D=0D
+ (ACPI_TABLE_PRESENT_INFO_LIST | ACPI_TABLE_PRESENT_INSTALLE=
D))=0D
+ {=0D
+ DEBUG ((DEBUG_ERROR, "ERROR: %a Table found while already published.=
\n", mAcpiVerifyTables[Index].AcpiTableName));=0D
+ Status =3D EFI_ALREADY_STARTED;=0D
+ }=0D
}=0D
=0D
return Status;=0D
@@ -489,8 +507,9 @@ VerifyMandatoryTablesArePresent (
@param [in] CfgMgrProtocol Pointer to the Configuration Manager=0D
Protocol Interface.=0D
=0D
- @retval EFI_SUCCESS Success.=0D
- @retval EFI_NOT_FOUND If a mandatory table or a generator is not found.=
=0D
+ @retval EFI_SUCCESS Success.=0D
+ @retval EFI_NOT_FOUND If a mandatory table or a generator is not=
found.=0D
+ @retval EFI_ALREADY_STARTED If mandatory table found in AcpiTableInfo =
is already installed.=0D
**/=0D
STATIC=0D
EFI_STATUS=0D
@@ -562,7 +581,7 @@ ProcessAcpiTables (
if (EFI_ERROR (Status)) {=0D
DEBUG ((=0D
DEBUG_ERROR,=0D
- "ERROR: Failed to find mandatory ACPI Table(s)."=0D
+ "ERROR: Failed to verify mandatory ACPI Table(s) presence."=0D
" Status =3D %r\n",=0D
Status=0D
));=0D
@@ -570,29 +589,32 @@ ProcessAcpiTables (
}=0D
=0D
// Add the FADT Table first.=0D
- for (Idx =3D 0; Idx < AcpiTableCount; Idx++) {=0D
- if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) =3D=3D=0D
- AcpiTableInfo[Idx].TableGeneratorId)=0D
- {=0D
- Status =3D BuildAndInstallAcpiTable (=0D
- TableFactoryProtocol,=0D
- CfgMgrProtocol,=0D
- AcpiTableProtocol,=0D
- &AcpiTableInfo[Idx]=0D
- );=0D
- if (EFI_ERROR (Status)) {=0D
- DEBUG ((=0D
- DEBUG_ERROR,=0D
- "ERROR: Failed to find build and install ACPI FADT Table." \=0D
- " Status =3D %r\n",=0D
- Status=0D
- ));=0D
- return Status;=0D
- }=0D
+ if ((mAcpiVerifyTables[ACPI_TABLE_VERIFY_FADT].Presence & ACPI_TABLE_PRE=
SENT_INSTALLED) =3D=3D 0) {=0D
+ // FADT is not yet installed=0D
+ for (Idx =3D 0; Idx < AcpiTableCount; Idx++) {=0D
+ if (CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdFadt) =3D=3D=0D
+ AcpiTableInfo[Idx].TableGeneratorId)=0D
+ {=0D
+ Status =3D BuildAndInstallAcpiTable (=0D
+ TableFactoryProtocol,=0D
+ CfgMgrProtocol,=0D
+ AcpiTableProtocol,=0D
+ &AcpiTableInfo[Idx]=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((=0D
+ DEBUG_ERROR,=0D
+ "ERROR: Failed to find build and install ACPI FADT Table." \=0D
+ " Status =3D %r\n",=0D
+ Status=0D
+ ));=0D
+ return Status;=0D
+ }=0D
=0D
- break;=0D
- }=0D
- } // for=0D
+ break;=0D
+ }=0D
+ } // for=0D
+ }=0D
=0D
// Add remaining ACPI Tables=0D
for (Idx =3D 0; Idx < AcpiTableCount; Idx++) {=0D
diff --git a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableMa=
nagerDxe.inf b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTable=
ManagerDxe.inf
index 028c3d413cf8..5ca98c8b4895 100644
--- a/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDx=
e.inf
+++ b/DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDx=
e.inf
@@ -36,6 +36,7 @@ [LibraryClasses]
=0D
[Protocols]=0D
gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED=
=0D
+ gEfiAcpiSdtProtocolGuid # PROTOCOL ALWAYS_CONSUMED=
=0D
=0D
gEdkiiConfigurationManagerProtocolGuid # PROTOCOL ALWAYS_CONSUMED=
=0D
gEdkiiDynamicTableFactoryProtocolGuid # PROTOCOL ALWAYS_CONSUMED=
=0D
--=20
2.37.1.windows.1


[PATCH v2 3/6] DynamicTablesPkg: DynamicPlatRepoLib: Adding more token fixers

Kun Qin
 

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3996

This change added more token fixers for other node types, including
NamedComponentNode, RootComplexNode, and SmmuV3Node.

The corresponding entries for tokenFixer functions table is also updated.

Cc: Sami Mujawar <Sami.Mujawar@...>
Cc: Alexei Fedorov <Alexei.Fedorov@...>

Co-authored-by: Joe Lopez <joelopez@...>
Signed-off-by: Kun Qin <kuqin12@...>
Reviewed-by: Sami Mujawar <sami.mujawar@...>
Reviewed-by: Pierre Gondois <pierre.gondois@...>
---

Notes:
v2:
- Added Reviewed-by tag [Sami]
- Added Reviewed-by tag [Pierre]

DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.c | =
78 +++++++++++++++++++-
1 file changed, 75 insertions(+), 3 deletions(-)

diff --git a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTok=
enFixer.c b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectToke=
nFixer.c
index 84e4bb7e3bc8..345acab53f74 100644
--- a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer=
.c
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer=
.c
@@ -64,6 +64,78 @@ TokenFixerItsGroup (
return EFI_SUCCESS;=0D
}=0D
=0D
+/** EArmObjNamedComponent token fixer.=0D
+=0D
+ CmObjectToken fixer function that updates the Tokens in the CmObjects.=0D
+=0D
+ @param [in] CmObject Pointer to the Configuration Manager Object.=0D
+ @param [in] Token Token to be updated in the CmObject.=0D
+=0D
+ @retval EFI_SUCCESS Success.=0D
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.=0D
+ @retval EFI_UNSUPPORTED Not supported.=0D
+**/=0D
+STATIC=0D
+EFI_STATUS=0D
+EFIAPI=0D
+TokenFixerNamedComponentNode (=0D
+ IN CM_OBJ_DESCRIPTOR *CmObject,=0D
+ IN CM_OBJECT_TOKEN Token=0D
+ )=0D
+{=0D
+ ASSERT (CmObject !=3D NULL);=0D
+ ((CM_ARM_NAMED_COMPONENT_NODE *)CmObject->Data)->Token =3D Token;=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/** EArmObjRootComplex token fixer.=0D
+=0D
+ CmObjectToken fixer function that updates the Tokens in the CmObjects.=0D
+=0D
+ @param [in] CmObject Pointer to the Configuration Manager Object.=0D
+ @param [in] Token Token to be updated in the CmObject.=0D
+=0D
+ @retval EFI_SUCCESS Success.=0D
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.=0D
+ @retval EFI_UNSUPPORTED Not supported.=0D
+**/=0D
+STATIC=0D
+EFI_STATUS=0D
+EFIAPI=0D
+TokenFixerRootComplexNode (=0D
+ IN CM_OBJ_DESCRIPTOR *CmObject,=0D
+ IN CM_OBJECT_TOKEN Token=0D
+ )=0D
+{=0D
+ ASSERT (CmObject !=3D NULL);=0D
+ ((CM_ARM_ROOT_COMPLEX_NODE *)CmObject->Data)->Token =3D Token;=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/** EArmObjSmmuV3 token fixer.=0D
+=0D
+ CmObjectToken fixer function that updates the Tokens in the CmObjects.=0D
+=0D
+ @param [in] CmObject Pointer to the Configuration Manager Object.=0D
+ @param [in] Token Token to be updated in the CmObject.=0D
+=0D
+ @retval EFI_SUCCESS Success.=0D
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.=0D
+ @retval EFI_UNSUPPORTED Not supported.=0D
+**/=0D
+STATIC=0D
+EFI_STATUS=0D
+EFIAPI=0D
+TokenFixerSmmuV3Node (=0D
+ IN CM_OBJ_DESCRIPTOR *CmObject,=0D
+ IN CM_OBJECT_TOKEN Token=0D
+ )=0D
+{=0D
+ ASSERT (CmObject !=3D NULL);=0D
+ ((CM_ARM_SMMUV3_NODE *)CmObject->Data)->Token =3D Token;=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
/** TokenFixer functions table.=0D
=0D
A CmObj having a CM_OBJECT_TOKEN field might need to have its=0D
@@ -90,10 +162,10 @@ CM_OBJECT_TOKEN_FIXER TokenFixer[EArmObjMax] =3D {
NULL, ///< 16 - Hypervisor Vendor Id=0D
NULL, ///< 17 - Fixed feature flags for FADT=
=0D
TokenFixerItsGroup, ///< 18 - ITS Group=0D
- TokenFixerNotImplemented, ///< 19 - Named Component=0D
- TokenFixerNotImplemented, ///< 20 - Root Complex=0D
+ TokenFixerNamedComponentNode, ///< 19 - Named Component=0D
+ TokenFixerRootComplexNode, ///< 20 - Root Complex=0D
TokenFixerNotImplemented, ///< 21 - SMMUv1 or SMMUv2=0D
- TokenFixerNotImplemented, ///< 22 - SMMUv3=0D
+ TokenFixerSmmuV3Node, ///< 22 - SMMUv3=0D
TokenFixerNotImplemented, ///< 23 - PMCG=0D
NULL, ///< 24 - GIC ITS Identifier Array=0D
NULL, ///< 25 - ID Mapping Array=0D
--=20
2.37.1.windows.1


[PATCH v2 2/6] DynamicTablesPkg: DynamicPlatRepoLib: Fix incorrect dereferencing

Kun Qin
 

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3996

The content of token should be derived from the data section of the
`CmObject` instead of the object itself.

This change fixed the issue by dereferencing the token value from the
data buffer of input CmObject.

Cc: Sami Mujawar <Sami.Mujawar@...>
Cc: Alexei Fedorov <Alexei.Fedorov@...>

Co-authored-by: Joe Lopez <joelopez@...>
Signed-off-by: Kun Qin <kuqin12@...>
Reviewed-by: Sami Mujawar <sami.mujawar@...>
Reviewed-by: Pierre Gondois <pierre.gondois@...>
---

Notes:
v2:
- Added Reviewed-by tag [Sami]
- Added Reviewed-by tag [Pierre]

DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.c | =
2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTok=
enFixer.c b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectToke=
nFixer.c
index 80d0aa17bc1a..84e4bb7e3bc8 100644
--- a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer=
.c
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer=
.c
@@ -60,7 +60,7 @@ TokenFixerItsGroup (
)=0D
{=0D
ASSERT (CmObject !=3D NULL);=0D
- ((CM_ARM_ITS_GROUP_NODE *)CmObject)->Token =3D Token;=0D
+ ((CM_ARM_ITS_GROUP_NODE *)CmObject->Data)->Token =3D Token;=0D
return EFI_SUCCESS;=0D
}=0D
=0D
--=20
2.37.1.windows.1


[PATCH v2 1/6] DynamicTablesPkg: DynamicPlatRepoLib: Added MemoryAllocationLib to inf

Kun Qin
 

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3996

The DynamicPlatRepoLib has multiple reference to MemoryAllocationLib,
such as DynamicPlatRepo.c and TokenMapper.c. Not including it in the
library inf file could lead to potential build break.

This change added the MemoryAllocationLib into this inf file.

Cc: Sami Mujawar <Sami.Mujawar@...>
Cc: Alexei Fedorov <Alexei.Fedorov@...>

Co-authored-by: Joe Lopez <joelopez@...>
Signed-off-by: Kun Qin <kuqin12@...>
Reviewed-by: Sami Mujawar <sami.mujawar@...>
Reviewed-by: Pierre Gondois <pierre.gondois@...>
---

Notes:
v2:
- Added Reviewed-by tag [Sami]
- Added Reviewed-by tag [Pierre]

DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf =
| 1 +
1 file changed, 1 insertion(+)

diff --git a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlat=
RepoLib.inf b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPla=
tRepoLib.inf
index 9a3cc87fd91d..8423352550c2 100644
--- a/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib=
.inf
+++ b/DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib=
.inf
@@ -31,3 +31,4 @@ [Packages]
[LibraryClasses]=0D
AcpiHelperLib=0D
BaseLib=0D
+ MemoryAllocationLib=0D
--=20
2.37.1.windows.1


[PATCH v2 0/6] Enhance DynamicTablesPkg modules

Kun Qin
 

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3996
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3997
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3998

This patch series is a follow-up of previous submission:
https://edk2.groups.io/g/devel/message/91497

The main changes between v1 and v2 patches are:
- Added reviewed-by collected from previous iteration
- Updated mandatory tables presence verification routine
- Added checks of config space before creating RES0 nodes

Current DynamicTablesPkg provide great support for creating dynamic ACPI
tables during boot time.

However, there are some modules needs minor tweaks to expand support and
compatibility for OS requirements and platform needs.

This patch series proposes a few fixes to resolve minor issues discovered
in DynamicPlatRepoLib, AcpiSsdtPcieLibArm and DynamicTableManagerDxe.

Patch v2 branch: https://github.com/kuqin12/edk2/tree/dynamic_update_v2

Cc: Sami Mujawar <Sami.Mujawar@...>
Cc: Alexei Fedorov <Alexei.Fedorov@...>
Cc: Pierre Gondois <pierre.gondois@...>

Kun Qin (6):
DynamicTablesPkg: DynamicPlatRepoLib: Added MemoryAllocationLib to inf
DynamicTablesPkg: DynamicPlatRepoLib: Fix incorrect dereferencing
DynamicTablesPkg: DynamicPlatRepoLib: Adding more token fixers
DynamicTablesPkg: DynamicTableManagerDxe: Added check for installed
tables
DynamicTablesPkg: AcpiSsdtPcieLibArm: Added function to reserve ECAM
space
DynamicTablesPkg: AcpiSsdtPcieLibArm: Added case handling for PCI
config

DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.c | 182 +++++++++++---------
DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c | 174 +++++++++++++++++++
DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/CmObjectTokenFixer.c | 80 ++++++++-
DynamicTablesPkg/Drivers/DynamicTableManagerDxe/DynamicTableManagerDxe.inf | 1 +
DynamicTablesPkg/Library/Common/DynamicPlatRepoLib/DynamicPlatRepoLib.inf | 1 +
5 files changed, 354 insertions(+), 84 deletions(-)

--
2.37.1.windows.1


Re: [edk2-staging][PATCH v3 15/15] edk2-staging/RedfishClientPkg: Introduce Bios feature driver

Chang, Abner
 

[AMD Official Use Only - General]

Reviewed-by: Abner Chang <abner.chang@...>

-----Original Message-----
From: Nickle Wang <nickle.wang@...>
Sent: Wednesday, July 27, 2022 9:38 AM
To: devel@edk2.groups.io
Cc: Chang, Abner <Abner.Chang@...>; Yang, Atom
<Atom.Yang@...>; Nick Ramirez <nramirez@...>
Subject: [edk2-staging][PATCH v3 15/15] edk2-staging/RedfishClientPkg:
Introduce Bios feature driver

[CAUTION: External Email]

Introduce new feature driver to support Bios version 1.0.9 schema.
Update corresponding FDF and DSC file to enable this feature driver.

Signed-off-by: Nickle Wang <nickle.wang@...>
Cc: Abner Chang <abner.chang@...>
Cc: Yang Atom <Atom.Yang@...>
Cc: Nick Ramirez <nramirez@...>
---
.../Features/Bios/v1_0_9/Common/BiosCommon.c | 741
++++++++++++++++
.../Features/Bios/v1_0_9/Common/BiosCommon.h | 30 +
.../Features/Bios/v1_0_9/Dxe/BiosDxe.c | 789 ++++++++++++++++++
.../Features/Bios/v1_0_9/Dxe/BiosDxe.inf | 52 ++
RedfishClientPkg/RedfishClient.fdf.inc | 2 +
.../RedfishClientComponents.dsc.inc | 2 +
RedfishClientPkg/RedfishClientLibs.dsc.inc | 6 +-
7 files changed, 1621 insertions(+), 1 deletion(-)
create mode 100644
RedfishClientPkg/Features/Bios/v1_0_9/Common/BiosCommon.c
create mode 100644
RedfishClientPkg/Features/Bios/v1_0_9/Common/BiosCommon.h
create mode 100644 RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c
create mode 100644
RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.inf

diff --git a/RedfishClientPkg/Features/Bios/v1_0_9/Common/BiosCommon.c
b/RedfishClientPkg/Features/Bios/v1_0_9/Common/BiosCommon.c
new file mode 100644
index 0000000000..d910d0d8a9
--- /dev/null
+++ b/RedfishClientPkg/Features/Bios/v1_0_9/Common/BiosCommon.c
@@ -0,0 +1,741 @@
+/** @file
+ Redfish feature driver implementation - common functions
+
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BiosCommon.h"
+
+CHAR8 BiosEmptyJson[] = "{\"@odata.id\": \"\", \"@odata.type\":
\"#Bios.v1_0_9.Bios\", \"Id\": \"\", \"Name\": \"\", \"Attributes\":{}}";
+
+REDFISH_RESOURCE_COMMON_PRIVATE *mRedfishResourcePrivate =
NULL;
+
+/**
+ Consume resource from given URI.
+
+ @param[in] This Pointer to
REDFISH_RESOURCE_COMMON_PRIVATE instance.
+ @param[in] Json The JSON to consume.
+ @param[in] HeaderEtag The Etag string returned in HTTP header.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @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_BIOS_V1_0_9 *Bios;
+ EFI_REDFISH_BIOS_V1_0_9_CS *BiosCs;
+ EFI_STRING ConfigureLang;
+ RedfishCS_Type_EmptyProp_CS_Data *EmptyPropCs;
+
+
+ if (Private == NULL || IS_EMPTY_STRING (Json)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Bios = NULL;
+ BiosCs = NULL;
+ ConfigureLang = NULL;
+
+ Status = Private->JsonStructProtocol->ToStructure (
+ Private->JsonStructProtocol,
+ NULL,
+ Json,
+ (EFI_REST_JSON_STRUCTURE_HEADER **)&Bios
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, ToStructure() failed: %r\n",
__FUNCTION__, Status));
+ return Status;
+ }
+
+ BiosCs = Bios->Bios;
+
+ //
+ // Check ETAG to see if we need to consume it
+ //
+ if (CheckEtag (Private->Uri, HeaderEtag, BiosCs->odata_etag)) {
+ //
+ // No change
+ //
+ DEBUG ((DEBUG_INFO, "%a, ETAG: %s has no change, ignore consume
action\n", __FUNCTION__, Private->Uri));
+ Status = EFI_ALREADY_STARTED;
+ goto ON_RELEASE;
+ }
+
+ //
+ // Handle ATTRIBUTEREGISTRY
+ //
+ if (BiosCs->AttributeRegistry != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (BiosCs->odata_id,
"AttributeRegistry");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, BiosCs->AttributeRegistry);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle ATTRIBUTES
+ //
+ if (BiosCs->Attributes == NULL) {
+ BiosCs->Attributes = AllocateZeroPool (sizeof
(RedfishBios_V1_0_9_Attributes_CS));
+ ASSERT (BiosCs->Attributes != NULL);
+ }
+
+ //
+ // Handle ATTRIBUTES->EmptyProperty
+ //
+ if (BiosCs->Attributes != NULL) {
+ //
+ // Validate empty property.
+ //
+ if (BiosCs->Attributes->Prop.ForwardLink == &BiosCs->Attributes->Prop)
{
+ goto ON_RELEASE;
+ }
+ EmptyPropCs = (RedfishCS_Type_EmptyProp_CS_Data *)BiosCs-
Attributes->Prop.ForwardLink;
+ if (EmptyPropCs->Header.ResourceType == RedfishCS_Type_JSON) {
+ DEBUG ((DEBUG_ERROR, "%a, Empty property with
RedfishCS_Type_JSON type resource is not supported yet. (%s)\n",
__FUNCTION__, Private->Uri));
+ goto ON_RELEASE;
+ }
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (BiosCs->odata_id, "Attributes");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsVagueType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, EmptyPropCs->KeyValuePtr,
EmptyPropCs->NunmOfProperties);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+
+ON_RELEASE:
+
+ //
+ // Release resource.
+ //
+ Private->JsonStructProtocol->DestoryStructure (
+ Private->JsonStructProtocol,
+ (EFI_REST_JSON_STRUCTURE_HEADER *)Bios
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ProvisioningBiosProperties (
+ 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_BIOS_V1_0_9 *Bios;
+ EFI_REDFISH_BIOS_V1_0_9_CS *BiosCs;
+ EFI_STATUS Status;
+ BOOLEAN PropertyChanged;
+ CHAR8 *AsciiStringValue;
+ RedfishCS_EmptyProp_KeyValue *PropertyVagueValues;
+ UINT32 VagueValueNumber;
+
+
+
+ if (JsonStructProtocol == NULL || ResultJson == NULL ||
IS_EMPTY_STRING (InputJson) || IS_EMPTY_STRING (ConfigureLang)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a provision for %s with: %s\n",
__FUNCTION__, ConfigureLang, (ProvisionMode ? L"Provision resource" :
L"Update resource")));
+
+ *ResultJson = NULL;
+ PropertyChanged = FALSE;
+
+ Bios = NULL;
+ Status = JsonStructProtocol->ToStructure (
+ JsonStructProtocol,
+ NULL,
+ InputJson,
+ (EFI_REST_JSON_STRUCTURE_HEADER **)&Bios
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, ToStructure failure: %r\n", __FUNCTION__,
Status));
+ return Status;
+ }
+
+ BiosCs = Bios->Bios;
+
+ //
+ // ID
+ //
+ if (BiosCs->Id == NULL && !IS_EMPTY_STRING (ResourceId)) {
+ BiosCs->Id = AllocateCopyPool (AsciiStrSize (ResourceId), ResourceId);
+ }
+
+ //
+ // Handle ATTRIBUTEREGISTRY
+ //
+ if (PropertyChecker (BiosCs->AttributeRegistry, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"AttributeRegistry", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (BiosCs->AttributeRegistry,
AsciiStringValue) != 0) {
+ BiosCs->AttributeRegistry = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle ATTRIBUTES
+ //
+ if (BiosCs->Attributes != NULL) {
+ //
+ // Handle ATTRIBUTES
+ //
+ if (PropertyChecker (BiosCs->Attributes, ProvisionMode)) {
+ PropertyVagueValues = GetPropertyVagueValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"Attributes", ConfigureLang,
&VagueValueNumber);
+ if (PropertyVagueValues != NULL) {
+ if (ProvisionMode || !CompareRedfishPropertyVagueValues (
+ ((RedfishCS_Type_EmptyProp_CS_Data *)BiosCs-
Attributes->Prop.ForwardLink)->KeyValuePtr,
+ ((RedfishCS_Type_EmptyProp_CS_Data *)BiosCs-
Attributes->Prop.ForwardLink)->NunmOfProperties,
+ PropertyVagueValues,
+ VagueValueNumber)) {
+ //
+ // Use the properties on system to replace the one on Redfish service.
+ //
+ ((RedfishCS_Type_EmptyProp_CS_Data *)BiosCs->Attributes-
Prop.ForwardLink)->KeyValuePtr = PropertyVagueValues;
+ ((RedfishCS_Type_EmptyProp_CS_Data *)BiosCs->Attributes-
Prop.ForwardLink)->NunmOfProperties = VagueValueNumber;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ }
+
+
+ //
+ // Convert C structure back to JSON text.
+ //
+ Status = JsonStructProtocol->ToJson (
+ JsonStructProtocol,
+ (EFI_REST_JSON_STRUCTURE_HEADER *)Bios,
+ ResultJson
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, ToJson() failed: %r\n", __FUNCTION__,
Status));
+ return Status;
+ }
+
+ //
+ // Release resource.
+ //
+ JsonStructProtocol->DestoryStructure (
+ JsonStructProtocol,
+ (EFI_REST_JSON_STRUCTURE_HEADER *)Bios
+ );
+
+ return (PropertyChanged ? EFI_SUCCESS : EFI_NOT_FOUND);
+}
+
+EFI_STATUS
+ProvisioningBiosResource (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
+ IN UINTN Index,
+ IN EFI_STRING ConfigureLang
+ )
+{
+ CHAR8 *Json;
+ EFI_STATUS Status;
+ EFI_STRING NewResourceLocation;
+ CHAR8 *EtagStr;
+ CHAR8 ResourceId[16];
+
+ if (IS_EMPTY_STRING (ConfigureLang) || Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EtagStr = NULL;
+ AsciiSPrint (ResourceId, sizeof (ResourceId), "%d", Index);
+
+ Status = ProvisioningBiosProperties (
+ Private->JsonStructProtocol,
+ BiosEmptyJson,
+ ResourceId,
+ ConfigureLang,
+ TRUE,
+ &Json
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, provisioning resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ return Status;
+ }
+
+ Status = CreatePayloadToPostResource (Private->RedfishService, Private-
Payload, Json, &NewResourceLocation, &EtagStr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, post Bios resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ goto RELEASE_RESOURCE;
+ }
+
+ ASSERT (NewResourceLocation != NULL);
+
+ //
+ // Keep location of new resource.
+ //
+ if (NewResourceLocation != NULL) {
+ RedfisSetRedfishUri (ConfigureLang, NewResourceLocation);
+ }
+
+ //
+ // Handle Etag
+ //
+ if (EtagStr != NULL) {
+ SetEtagWithUri (EtagStr, NewResourceLocation);
+ FreePool (EtagStr);
+ }
+
+RELEASE_RESOURCE:
+
+ if (NewResourceLocation != NULL) {
+ FreePool (NewResourceLocation);
+ }
+
+ if (Json != NULL) {
+ FreePool (Json);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+ProvisioningBiosResources (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
UnifiedConfigureLangList;
+
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = RedfishFeatureGetUnifiedArrayTypeConfigureLang
(RESOURCE_SCHEMA, RESOURCE_SCHEMA_VERSION,
REDPATH_ARRAY_PATTERN, &UnifiedConfigureLangList);
+ if (EFI_ERROR (Status) || UnifiedConfigureLangList.Count == 0) {
+ DEBUG ((DEBUG_ERROR, "%a, No HII question found with configure
language: %s: %r\n", __FUNCTION__, REDPATH_ARRAY_PATTERN, Status));
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Set the configuration language in the
RESOURCE_INFORMATION_EXCHANGE.
+ // This information is sent back to the parent resource (e.g. the collection
driver).
+ //
+ EdkIIRedfishResourceSetConfigureLang (&UnifiedConfigureLangList);
+
+ for (Index = 0; Index < UnifiedConfigureLangList.Count; Index++) {
+ DEBUG ((DEBUG_INFO, "[%d] create Bios resource from: %s\n",
UnifiedConfigureLangList.List[Index].Index,
UnifiedConfigureLangList.List[Index].ConfigureLang));
+ ProvisioningBiosResource (Private,
UnifiedConfigureLangList.List[Index].Index,
UnifiedConfigureLangList.List[Index].ConfigureLang);
+ FreePool (UnifiedConfigureLangList.List[Index].ConfigureLang);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+ProvisioningBiosExistResource (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING ConfigureLang;
+ CHAR8 *EtagStr;
+ CHAR8 *Json;
+
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EtagStr = NULL;
+ Json = NULL;
+ ConfigureLang = NULL;
+
+ ConfigureLang = RedfishGetConfigLanguage (Private->Uri);
+ if (ConfigureLang == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = ProvisioningBiosProperties (
+ Private->JsonStructProtocol,
+ BiosEmptyJson,
+ NULL,
+ ConfigureLang,
+ TRUE,
+ &Json
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, provisioning existing resource
for %s ignored. Nothing changed\n", __FUNCTION__, ConfigureLang));
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, provisioning existing resource for %s
failed: %r\n", __FUNCTION__, ConfigureLang, Status));
+ }
+ goto ON_RELEASE;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, provisioning existing resource for
%s\n", __FUNCTION__, ConfigureLang));
+ //
+ // PUT back to instance
+ //
+ Status = CreatePayloadToPatchResource (Private->RedfishService, Private-
Payload, Json, &EtagStr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, patch resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ //
+ // Handle Etag
+ //
+ if (EtagStr != NULL) {
+ SetEtagWithUri (EtagStr, Private->Uri);
+ FreePool (EtagStr);
+ }
+
+ON_RELEASE:
+
+ if (Json != NULL) {
+ FreePool (Json);
+ }
+
+ if (ConfigureLang != NULL) {
+ FreePool (ConfigureLang);
+ }
+
+ return Status;
+}
+
+/**
+ Provisioning redfish resource by given URI.
+
+ @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCOL
instance.
+ @param[in] ResourceExist TRUE if resource exists, PUT method will be
used.
+ FALSE if resource does not exist POST method is used.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishProvisioningResourceCommon (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
+ IN BOOLEAN ResourceExist
+ )
+{
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return (ResourceExist ? ProvisioningBiosExistResource (Private) :
ProvisioningBiosResources (Private));
+}
+
+/**
+ Check resource from given URI.
+
+ @param[in] This Pointer to
REDFISH_RESOURCE_COMMON_PRIVATE instance.
+ @param[in] Json The JSON to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishCheckResourceCommon (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
+ IN CHAR8 *Json
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_STRING *ConfigureLangList;
+ UINTN Count;
+ EFI_STRING Property;
+
+ if (Private == NULL || IS_EMPTY_STRING (Json)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = RedfishPlatformConfigGetConfigureLang (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, REDPATH_ARRAY_PATTERN,
&ConfigureLangList, &Count);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a,
BiosConfigToRedfishGetConfigureLangRegex failed: %r\n", __FUNCTION__,
Status));
+ return Status;
+ }
+
+ if (Count == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = EFI_SUCCESS;
+ for (Index = 0; Index < Count; Index++) {
+
+ Property = GetPropertyFromConfigureLang (Private->Uri,
ConfigureLangList[Index]);
+ if (Property == NULL) {
+ continue;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a, [%d] check attribute for: %s\n",
__FUNCTION__, Index, Property));
+ if (!MatchPropertyWithJsonContext (Property, Json)) {
+ DEBUG ((DEBUG_INFO, "%a, property is missing: %s\n", __FUNCTION__,
Property));
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+ FreePool (ConfigureLangList);
+
+ return Status;
+}
+
+/**
+ Update resource to given URI.
+
+ @param[in] This Pointer to
REDFISH_RESOURCE_COMMON_PRIVATE instance.
+ @param[in] Json The JSON to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishUpdateResourceCommon (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
+ IN CHAR8 *InputJson
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *Json;
+ EFI_STRING ConfigureLang;
+ CHAR8 *EtagStr;
+
+ if (Private == NULL || IS_EMPTY_STRING (InputJson)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EtagStr = NULL;
+ Json = NULL;
+ ConfigureLang = NULL;
+
+ ConfigureLang = RedfishGetConfigLanguage (Private->Uri);
+ if (ConfigureLang == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = ProvisioningBiosProperties (
+ Private->JsonStructProtocol,
+ InputJson,
+ NULL,
+ ConfigureLang,
+ FALSE,
+ &Json
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, update resource for %s ignored.
Nothing changed\n", __FUNCTION__, ConfigureLang));
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, update resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+ goto ON_RELEASE;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, update resource for %s\n",
__FUNCTION__, ConfigureLang));
+ //
+ // PUT back to instance
+ //
+ Status = CreatePayloadToPatchResource (Private->RedfishService, Private-
Payload, Json, &EtagStr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, patch resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ //
+ // Handle Etag
+ //
+ if (EtagStr != NULL) {
+ SetEtagWithUri (EtagStr, Private->Uri);
+ FreePool (EtagStr);
+ }
+
+ON_RELEASE:
+
+ if (Json != NULL) {
+ FreePool (Json);
+ }
+
+ if (ConfigureLang != NULL) {
+ FreePool (ConfigureLang);
+ }
+
+ return Status;
+}
+
+/**
+ Identify resource from given URI.
+
+ @param[in] This Pointer to
REDFISH_RESOURCE_COMMON_PRIVATE instance.
+ @param[in] Json The JSON to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishIdentifyResourceCommon (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
+ IN CHAR8 *Json
+ )
+{
+ BOOLEAN Supported;
+ EFI_STATUS Status;
+ EFI_STRING EndOfChar;
+ REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST ConfigLangList;
+
+ Supported = RedfishIdentifyResource (Private->Uri, Private->Json);
+ if (Supported) {
+ Status = RedfishFeatureGetUnifiedArrayTypeConfigureLang
(RESOURCE_SCHEMA, RESOURCE_SCHEMA_VERSION,
REDPATH_ARRAY_PATTERN, &ConfigLangList);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a,
BiosConfigToRedfishGetConfigureLangRegex failed: %r\n", __FUNCTION__,
Status));
+ return Status;
+ }
+
+ if (ConfigLangList.Count == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //EndOfChar = StrStr (ConfigLangList.List[0].ConfigureLang, L"}");
+ Status = IsRedpathArray (ConfigLangList.List[0].ConfigureLang, NULL,
&EndOfChar);
+ if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
+ ASSERT (FALSE);
+ return EFI_DEVICE_ERROR;
+ }
+ if (Status != EFI_SUCCESS) {
+ //
+ // This is not the collection redpath.
+ //
+ GetRedpathNodeByIndex (ConfigLangList.List[0].ConfigureLang, 0,
&EndOfChar);
+ }
+ *(++EndOfChar) = '\0';
+ //
+ // Keep URI and ConfigLang mapping
+ //
+ RedfisSetRedfishUri (ConfigLangList.List[0].ConfigureLang, Private->Uri);
+ //
+ // Set the configuration language in the
RESOURCE_INFORMATION_EXCHANGE.
+ // This information is sent back to the parent resource (e.g. the collection
driver).
+ //
+ EdkIIRedfishResourceSetConfigureLang (&ConfigLangList);
+ DestroyConfiglanguageList (&ConfigLangList);
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+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 == NULL || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Resource match
+ //
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, process resource for: %s\n",
__FUNCTION__, Uri));
+
+ Status = GetRedfishSchemaInfo (Private->RedfishService, Private-
JsonStructProtocol, Uri, &SchemaInfo);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to get schema information from: %s
%r\n", __FUNCTION__, 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, "%s Identify for %s\n", __FUNCTION__,
Uri));
+ ConfigLang = RedfishGetConfigLanguage (Uri);
+ if (ConfigLang == NULL) {
+ Status = EdkIIRedfishResourceConfigIdentify (&SchemaInfo, Uri, Private-
InformationExchange);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_UNSUPPORTED) {
+ DEBUG ((DEBUG_INFO, "%a, \"%s\" is not handled by us\n",
__FUNCTION__, Uri));
+ return EFI_SUCCESS;
+ }
+
+ DEBUG ((DEBUG_ERROR, "%a, fail to identify resource: \"%s\": %r\n",
__FUNCTION__, Uri, Status));
+ return Status;
+ }
+ } else {
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, history record found: %s\n",
__FUNCTION__, ConfigLang));
+ FreePool (ConfigLang);
+ }
+
+ //
+ // Check and see if target property exist or not even when collection
memeber exists.
+ // If not, we sill do provision.
+ //
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a Check for %s\n", __FUNCTION__,
Uri));
+ Status = EdkIIRedfishResourceConfigCheck (&SchemaInfo, Uri);
+ if (EFI_ERROR (Status)) {
+ //
+ // The target property does not exist, do the provision to create property.
+ //
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a provision for %s\n",
__FUNCTION__, Uri));
+ Status = EdkIIRedfishResourceConfigProvisionging (&SchemaInfo, Uri,
Private->InformationExchange, FALSE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to provision with GET mode: %r\n",
__FUNCTION__, Status));
+ }
+
+ return Status;
+ }
+
+ //
+ // Consume first.
+ //
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a consume for %s\n",
__FUNCTION__, Uri));
+ Status = EdkIIRedfishResourceConfigConsume (&SchemaInfo, Uri);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to consume resoruce for: %s: %r\n",
__FUNCTION__, Uri, Status));
+ }
+
+ //
+ // Patch.
+ //
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a update for %s\n", __FUNCTION__,
Uri));
+ Status = EdkIIRedfishResourceConfigUpdate (&SchemaInfo, Uri);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to update resoruce for: %s: %r\n",
__FUNCTION__, Uri, Status));
+ }
+
+ return Status;
+}
diff --git a/RedfishClientPkg/Features/Bios/v1_0_9/Common/BiosCommon.h
b/RedfishClientPkg/Features/Bios/v1_0_9/Common/BiosCommon.h
new file mode 100644
index 0000000000..321ded7637
--- /dev/null
+++ b/RedfishClientPkg/Features/Bios/v1_0_9/Common/BiosCommon.h
@@ -0,0 +1,30 @@
+/** @file
+
+ Redfish feature driver implementation - internal header file
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_BIOS_COMMON_H_
+#define EFI_REDFISH_BIOS_COMMON_H_
+
+#include <RedfishJsonStructure/Bios/v1_0_9/EfiBiosV1_0_9.h>
+#include <RedfishResourceCommon.h>
+
+//
+// Schema information.
+//
+#define REDFISH_MANAGED_URI L"Systems/{}/Bios"
+#define MAX_URI_LENGTH 256
+#define RESOURCE_SCHEMA "Bios"
+#define RESOURCE_SCHEMA_MAJOR "1"
+#define RESOURCE_SCHEMA_MINOR "0"
+#define RESOURCE_SCHEMA_ERRATA "9"
+#define RESOURCE_SCHEMA_VERSION "v1_0_9"
+#define REDPATH_ARRAY_PATTERN L"/Bios/.*"
+#define REDPATH_ARRAY_PREFIX L"/Bios/"
+#define RESOURCE_SCHEMA_FULL "x-uefi-redfish-Bios.v1_0_9"
+#define REDFISH_SCHEMA_NAME "ComputerSystem"
+
+#endif
diff --git a/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c
b/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c
new file mode 100644
index 0000000000..a478061cde
--- /dev/null
+++ b/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.c
@@ -0,0 +1,789 @@
+/** @file
+ Redfish feature driver implementation - Bios
+
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "../Common/BiosCommon.h"
+
+extern REDFISH_RESOURCE_COMMON_PRIVATE
*mRedfishResourcePrivate;
+
+EFI_STATUS
+HandleResource (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
+ IN EFI_STRING Uri
+ );
+
+EFI_HANDLE medfishResourceConfigProtocolHandle;
+
+/**
+ Provising redfish resource by given URI.
+
+ @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCOL
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 property is missing, put
method is used.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+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 == NULL || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a, provisioning in %s mode\n", __FUNCTION__,
(PostMode ? L"POST" : L"PATCH")));
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);
+
+ if (Private->RedfishService == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
+ return Status;
+ }
+
+ Private->Uri = Uri;
+ Private->Payload = Response.Payload;
+ ASSERT (Private->Payload != NULL);
+
+ Status = RedfishProvisioningResourceCommon (Private, !PostMode);
+
+ //
+ // Release resource
+ //
+ if (Private->Payload != NULL) {
+ RedfishFreeResponse (
+ Response.StatusCode,
+ Response.HeaderCount,
+ Response.Headers,
+ Response.Payload
+ );
+ Private->Payload = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ Consume resource from given URI.
+
+ @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCOL
instance.
+ @param[in] Uri The target URI to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishResourceConsumeResource (
+ 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 == NULL || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);
+
+ if (Private->RedfishService == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
+ return Status;
+ }
+
+ Private->Uri = Uri;
+ Private->Payload = Response.Payload;
+ ASSERT (Private->Payload != NULL);
+
+ Private->Json = JsonDumpString (RedfishJsonInPayload (Private->Payload),
EDKII_JSON_COMPACT);
+ ASSERT (Private->Json != NULL);
+
+ //
+ // Find etag in HTTP response header
+ //
+ Etag = NULL;
+ Status = GetEtagAndLocation (&Response, &Etag, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to get ETag from HTTP header\n",
__FUNCTION__));
+ }
+
+ Status = RedfishConsumeResourceCommon (Private, Private->Json, Etag);
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_ALREADY_STARTED) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to consume resource from: %s:
%r\n", __FUNCTION__, Uri, Status));
+ }
+ } else {
+ //
+ // Keep etag after consuming pending settings.
+ //
+ if (Etag != NULL) {
+ SetEtagWithUri (Etag, Private->Uri);
+ }
+ }
+
+ //
+ // Release resource
+ //
+ if (Private->Payload != NULL) {
+ RedfishFreeResponse (
+ Response.StatusCode,
+ Response.HeaderCount,
+ Response.Headers,
+ Response.Payload
+ );
+ Private->Payload = NULL;
+ }
+
+ if (Private->Json != NULL) {
+ FreePool (Private->Json);
+ Private->Json = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ Get information about this protocol.
+
+ @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCOL
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
+RedfishResourceGetInfo (
+ IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This,
+ OUT REDFISH_SCHEMA_INFO *Info
+ )
+{
+ REDFISH_RESOURCE_COMMON_PRIVATE *Private;
+
+ if (This == NULL || Info == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);
+
+ AsciiStrCpyS (Info->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);
+ AsciiStrCpyS (Info->Errata, REDFISH_SCHEMA_VERSION_SIZE,
RESOURCE_SCHEMA_ERRATA);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update resource to given URI.
+
+ @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCOL
instance.
+ @param[in] Uri The target URI to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+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 == NULL || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);
+
+ if (Private->RedfishService == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
+ return Status;
+ }
+
+ Private->Uri = Uri;
+ Private->Payload = Response.Payload;
+ ASSERT (Private->Payload != NULL);
+
+ Private->Json = JsonDumpString (RedfishJsonInPayload (Private->Payload),
EDKII_JSON_COMPACT);
+ ASSERT (Private->Json != NULL);
+
+ Status = RedfishUpdateResourceCommon (Private, Private->Json);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to update resource from: %s: %r\n",
__FUNCTION__, Uri, Status));
+ }
+
+ //
+ // Release resource
+ //
+ if (Private->Payload != NULL) {
+ RedfishFreeResponse (
+ Response.StatusCode,
+ Response.HeaderCount,
+ Response.Headers,
+ Response.Payload
+ );
+ Private->Payload = NULL;
+ }
+
+ if (Private->Json != NULL) {
+ FreePool (Private->Json);
+ Private->Json = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ Check resource on given URI.
+
+ @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCOL
instance.
+ @param[in] Uri The target URI to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishResourceCheck (
+ IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This,
+ IN EFI_STRING Uri
+ )
+{
+ REDFISH_RESOURCE_COMMON_PRIVATE *Private;
+ EFI_STATUS Status;
+ REDFISH_RESPONSE Response;
+
+ if (This == NULL || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);
+
+ if (Private->RedfishService == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
+ return Status;
+ }
+
+ Private->Uri = Uri;
+ Private->Payload = Response.Payload;
+ ASSERT (Private->Payload != NULL);
+
+ Private->Json = JsonDumpString (RedfishJsonInPayload (Private->Payload),
EDKII_JSON_COMPACT);
+ ASSERT (Private->Json != NULL);
+
+ Status = RedfishCheckResourceCommon (Private, Private->Json);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to check resource from: %s: %r\n",
__FUNCTION__, Uri, Status));
+ }
+
+ //
+ // Release resource
+ //
+ if (Private->Payload != NULL) {
+ RedfishFreeResponse (
+ Response.StatusCode,
+ Response.HeaderCount,
+ Response.Headers,
+ Response.Payload
+ );
+ Private->Payload = NULL;
+ }
+
+ if (Private->Json != NULL) {
+ FreePool (Private->Json);
+ Private->Json = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ Identify resource on given URI.
+
+ @param[in] This Pointer to
EDKII_REDFISH_RESOURCE_CONFIG_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
+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 == NULL || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);
+
+ if (Private->RedfishService == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
+ return Status;
+ }
+
+ Private->Uri = Uri;
+ Private->Payload = Response.Payload;
+ ASSERT (Private->Payload != NULL);
+
+ Private->Json = JsonDumpString (RedfishJsonInPayload (Private->Payload),
EDKII_JSON_COMPACT);
+ ASSERT (Private->Json != NULL);
+
+ Status = RedfishIdentifyResourceCommon (Private, Private->Json);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, identify %s failed: %r\n", __FUNCTION__,
Uri, Status));
+ }
+ //
+ // Release resource
+ //
+ if (Private->Payload != NULL) {
+ RedfishFreeResponse (
+ Response.StatusCode,
+ Response.HeaderCount,
+ Response.Headers,
+ Response.Payload
+ );
+ Private->Payload = NULL;
+ }
+
+ if (Private->Json != NULL) {
+ FreePool (Private->Json);
+ Private->Json = NULL;
+ }
+
+ return Status;
+}
+
+EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL mRedfishResourceConfig
= {
+ RedfishResourceProvisioningResource,
+ RedfishResourceConsumeResource,
+ RedfishResourceUpdate,
+ RedfishResourceCheck,
+ RedfishResourceIdentify,
+ RedfishResourceGetInfo
+};
+
+/**
+ Initialize a Redfish configure handler.
+
+ This function will be called by the Redfish config driver to initialize each
Redfish configure
+ handler.
+
+ @param[in] This Pointer to
EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL instance.
+ @param[in] RedfishConfigServiceInfo Redfish service informaion.
+
+ @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
initialized.
+ @retval Other Error happens during the initialization.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishResourceInit (
+ IN EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *This,
+ IN REDFISH_CONFIG_SERVICE_INFORMATION
*RedfishConfigServiceInfo
+ )
+{
+ REDFISH_RESOURCE_COMMON_PRIVATE *Private;
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_CONFIG_PROTOCO
L (This);
+
+ Private->RedfishService = RedfishCreateService
(RedfishConfigServiceInfo);
+ if (Private->RedfishService == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Stop a Redfish configure handler.
+
+ @param[in] This Pointer to
EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL instance.
+
+ @retval EFI_SUCCESS This handler has been stoped successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishResourceStop (
+ IN EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *This
+ )
+{
+ REDFISH_RESOURCE_COMMON_PRIVATE *Private;
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_CONFIG_PROTOCO
L (This);
+
+ if (Private->Event != NULL) {
+ gBS->CloseEvent (Private->Event);
+ Private->Event = NULL;
+ }
+
+ if (Private->RedfishService != NULL) {
+ RedfishCleanupService (Private->RedfishService);
+ Private->RedfishService = NULL;
+ }
+
+ if (Private->Payload != NULL) {
+ RedfishCleanupPayload (Private->Payload);
+ Private->Payload = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL mRedfishConfigHandler = {
+ 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
+EfiRestJasonStructureProtocolIsReady
+ (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ if (mRedfishResourcePrivate == NULL) {
+ return;
+ }
+
+ if (mRedfishResourcePrivate->JsonStructProtocol != NULL) {
+ return;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiRestJsonStructureProtocolGuid,
+ NULL,
+ (VOID **)&mRedfishResourcePrivate->JsonStructProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to locate
gEfiRestJsonStructureProtocolGuid: %r\n", __FUNCTION__, Status));
+ }
+
+ gBS->CloseEvent (Event);
+}
+
+/**
+ Unloads an image.
+
+ @param ImageHandle Handle that identifies the image to be
unloaded.
+
+ @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 == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ ConfigHandler = NULL;
+
+ //
+ // Firstly, find ConfigHandler Protocol interface in this ImageHandle.
+ //
+ Status = gBS->OpenProtocol (
+ ImageHandle,
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ (VOID **) &ConfigHandler,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+ );
+ if (EFI_ERROR (Status) || ConfigHandler == NULL) {
+ return Status;
+ }
+
+ ConfigHandler->Stop (ConfigHandler);
+
+ //
+ // Last, uninstall ConfigHandler Protocol and resource protocol.
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ImageHandle,
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ ConfigHandler,
+ &gEdkIIRedfishResourceConfigProtocolGuid,
+ &mRedfishResourcePrivate->RedfishResourceConfig,
+ NULL
+ );
+
+ FreePool (mRedfishResourcePrivate);
+ mRedfishResourcePrivate = NULL;
+
+ return Status;
+}
+
+/**
+ The callback function provided by Redfish Feature driver.
+
+ @param[in] This Pointer to EDKII_REDFISH_FEATURE_PROTOCOL
instance.
+ @param[in] FeatureAction The action Redfish feature driver should
take.
+ @param[in] Uri The collection URI.
+ @param[in] Context The context of Redfish feature driver.
+ @param[in,out] InformationExchange The pointer to
RESOURCE_INFORMATION_EXCHANGE
+
+ @retval EFI_SUCCESS Redfish feature driver callback is executed
successfully.
+ @retval Others Some errors happened.
+
+ @retval EFI_SUCCESS Redfish feature driver callback is executed
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;
+
+ if (FeatureAction != CallbackActionStartOperation) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Private = (REDFISH_RESOURCE_COMMON_PRIVATE *)Context;
+
+ RedfishService = Private->RedfishService;
+ if (RedfishService == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Save in private structure.
+ //
+ Private->InformationExchange = InformationExchange;
+
+ //
+ // Find Redfish version on BMC
+ //
+ Private->RedfishVersion = RedfishGetVersion (RedfishService);
+
+ //
+ // Create the full URI from Redfish service root.
+ //
+ ResourceUri = (EFI_STRING)AllocateZeroPool (MAX_URI_LENGTH *
sizeof(CHAR16));
+ if (ResourceUri == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for full URI.\n",
__FUNCTION__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ StrCatS (ResourceUri, MAX_URI_LENGTH, Private->RedfishVersion);
+ StrCatS (ResourceUri, MAX_URI_LENGTH, InformationExchange-
SendInformation.FullUri);
+
+ //
+ // Initialize collection path
+ //
+ Private->Uri = RedfishGetUri (ResourceUri);
+ if (Private->Uri == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = HandleResource (Private, Private->Uri);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, process external resource: %a failed:
%r\n", __FUNCTION__, Private->Uri, Status));
+ }
+
+ FreePool (Private->Uri);
+ 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 == NULL) {
+ return;
+ }
+
+ if (mRedfishResourcePrivate->FeatureProtocol != NULL) {
+ return;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEdkIIRedfishFeatureProtocolGuid,
+ NULL,
+ (VOID **)&FeatureProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to locate
gEdkIIRedfishFeatureProtocolGuid: %r\n", __FUNCTION__, Status));
+ gBS->CloseEvent (Event);
+ return;
+ }
+
+ Status = FeatureProtocol->Register (
+ FeatureProtocol,
+ REDFISH_MANAGED_URI,
+ RedfishExternalResourceResourceFeatureCallback,
+ (VOID *)mRedfishResourcePrivate
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to register %s: %r\n",
__FUNCTION__, REDFISH_MANAGED_URI, Status));
+ }
+
+ mRedfishResourcePrivate->FeatureProtocol = 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 including
+ both device drivers and bus drivers. It initialize the global variables and
+ publish the driver binding protocol.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI
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 installed 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 != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ medfishResourceConfigProtocolHandle = ImageHandle;
+
+ mRedfishResourcePrivate = AllocateZeroPool (sizeof
(REDFISH_RESOURCE_COMMON_PRIVATE));
+ CopyMem (&mRedfishResourcePrivate->ConfigHandler,
&mRedfishConfigHandler, sizeof
(EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL));
+ CopyMem (&mRedfishResourcePrivate->RedfishResourceConfig,
&mRedfishResourceConfig, sizeof
(EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL));
+
+ //
+ // Publish config handler protocol and resource protocol.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ &mRedfishResourcePrivate->ConfigHandler,
+ &gEdkIIRedfishResourceConfigProtocolGuid,
+ &mRedfishResourcePrivate->RedfishResourceConfig,
+ NULL
+ );
+
+ EfiCreateProtocolNotifyEvent (
+ &gEfiRestJsonStructureProtocolGuid,
+ TPL_CALLBACK,
+ EfiRestJasonStructureProtocolIsReady,
+ NULL,
+ &Registration
+ );
+
+ EfiCreateProtocolNotifyEvent (
+ &gEdkIIRedfishFeatureProtocolGuid,
+ TPL_CALLBACK,
+ EdkIIRedfishFeatureProtocolIsReady,
+ (VOID *)mRedfishResourcePrivate,
+ &Registration
+ );
+
+ return Status;
+}
diff --git a/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.inf
b/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.inf
new file mode 100644
index 0000000000..8c01a3b877
--- /dev/null
+++ b/RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.inf
@@ -0,0 +1,52 @@
+## @file
+#
+# (C) Copyright 2020-2022 Hewlett Packard Enterprise Development
LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BiosDxe
+ FILE_GUID = d6c99bb0-ca18-45aa-8be6-a60c3ba5ecd8
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishResourceEntryPoint
+ UNLOAD_IMAGE = RedfishResourceUnload
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+ RedfishClientPkg/RedfishClientPkg.dec
+
+[Sources]
+ ../Common/BiosCommon.h
+ ../Common/BiosCommon.c
+ BiosDxe.c
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ EdkIIRedfishResourceConfigLib
+ RedfishLib
+ RedfishFeatureUtilityLib
+ RedfishVersionLib
+ RedfishResourceIdentifyLib
+ UefiLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEdkIIRedfishConfigHandlerProtocolGuid ## PRODUCED
+ gEfiRestJsonStructureProtocolGuid ## CONSUMED
+ gEdkIIRedfishResourceConfigProtocolGuid ## PRODUCED
+ gEdkIIRedfishFeatureProtocolGuid ## CONSUMED
+
+[Pcd]
+ gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaStringSize
+ gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaVersionSize
+
+[Depex]
+ TRUE
diff --git a/RedfishClientPkg/RedfishClient.fdf.inc
b/RedfishClientPkg/RedfishClient.fdf.inc
index 90240efbf7..fa4e53898b 100644
--- a/RedfishClientPkg/RedfishClient.fdf.inc
+++ b/RedfishClientPkg/RedfishClient.fdf.inc
@@ -18,6 +18,7 @@
INF
RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf
INF
RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystem
Dxe.inf
INF
RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyste
mCollectionDxe.inf
+ INF RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.inf

!include RedfishClientPkg/RedfishJsonStructureDxe.fdf.inc
#
@@ -27,4 +28,5 @@
INF
RedfishClientPkg/Converter/MemoryCollection/RedfishMemoryCollection_
Dxe.inf
INF
RedfishClientPkg/Converter/ComputerSystem/v1_5_0/RedfishComputerSys
tem_V1_5_0_Dxe.inf
INF
RedfishClientPkg/Converter/ComputerSystemCollection/RedfishComputerS
ystemCollection_Dxe.inf
+ INF
RedfishClientPkg/Converter/Bios/v1_0_9/RedfishBios_V1_0_9_Dxe.inf
!endif
diff --git a/RedfishClientPkg/RedfishClientComponents.dsc.inc
b/RedfishClientPkg/RedfishClientComponents.dsc.inc
index 084796e4b5..e83f4bc9bf 100644
--- a/RedfishClientPkg/RedfishClientComponents.dsc.inc
+++ b/RedfishClientPkg/RedfishClientComponents.dsc.inc
@@ -27,6 +27,7 @@

RedfishResourceIdentifyLib|RedfishClientPkg/Library/RedfishResourceIdenti
fyLibComuterSystem/v1_5_0/RedfishResourceIdentifyLibComuterSystem.in
f
}

RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyste
mCollectionDxe.inf
+ RedfishClientPkg/Features/Bios/v1_0_9/Dxe/BiosDxe.inf

!include RedfishClientPkg/RedfishJsonStructureDxe.dsc.inc

@@ -37,3 +38,4 @@

RedfishClientPkg/Converter/MemoryCollection/RedfishMemoryCollection_
Dxe.inf

RedfishClientPkg/Converter/ComputerSystem/v1_5_0/RedfishComputerSys
tem_V1_5_0_Dxe.inf

RedfishClientPkg/Converter/ComputerSystemCollection/RedfishComputerS
ystemCollection_Dxe.inf
+ RedfishClientPkg/Converter/Bios/v1_0_9/RedfishBios_V1_0_9_Dxe.inf
diff --git a/RedfishClientPkg/RedfishClientLibs.dsc.inc
b/RedfishClientPkg/RedfishClientLibs.dsc.inc
index 05ad09ef5e..fe0c4b0885 100644
--- a/RedfishClientPkg/RedfishClientLibs.dsc.inc
+++ b/RedfishClientPkg/RedfishClientLibs.dsc.inc
@@ -15,12 +15,16 @@
!endif

#
- # Below two modules should be pulled in by build tool.
+ # Below modules should be pulled in by build tool.
#

MemoryV1_7_1Lib|RedfishClientPkg/ConverterLib/edk2library/Memory/v1
_7_1/Lib.inf

MemoryCollectionLib|RedfishClientPkg/ConverterLib/edk2library/MemoryC
ollection/Lib.inf

ComputerSystemV1_5_0Lib|RedfishClientPkg/ConverterLib/edk2library/Co
mputerSystem/v1_5_0/Lib.inf

ComputerSystemCollectionLib|RedfishClientPkg/ConverterLib/edk2library/C
omputerSystemCollection/Lib.inf
+
BiosV1_0_9Lib|RedfishClientPkg/ConverterLib/edk2library/Bios/v1_0_9/Lib.i
nf
+ #
+ # Above modules should be pulled in by build tool.
+ #

NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf
--
2.32.0.windows.2


Re: [edk2-staging][PATCH v3 14/15] edk2-staging/RedfishClientPkg: Introduce Computer System feature driver

Chang, Abner
 

[AMD Official Use Only - General]

Reviewed-by: Abner Chang <abner.chang@...>

-----Original Message-----
From: Nickle Wang <nickle.wang@...>
Sent: Wednesday, July 27, 2022 9:38 AM
To: devel@edk2.groups.io
Cc: Chang, Abner <Abner.Chang@...>; Yang, Atom
<Atom.Yang@...>; Nick Ramirez <nramirez@...>
Subject: [edk2-staging][PATCH v3 14/15] edk2-staging/RedfishClientPkg:
Introduce Computer System feature driver

[CAUTION: External Email]

Introduce new feature driver to support Computer System version 1.5.0
schema. Update corresponding FDF and DSC file to enable this feature
driver.

Signed-off-by: Nickle Wang <nickle.wang@...>
Cc: Abner Chang <abner.chang@...>
Cc: Yang Atom <Atom.Yang@...>
Cc: Nick Ramirez <nramirez@...>
---
.../v1_5_0/Common/ComputerSystemCommon.c | 1614
+++++++++++++++++
.../v1_5_0/Common/ComputerSystemCommon.h | 27 +
.../v1_5_0/Dxe/ComputerSystemDxe.c | 645 +++++++
.../v1_5_0/Dxe/ComputerSystemDxe.inf | 51 +
RedfishClientPkg/RedfishClient.fdf.inc | 2 +
.../RedfishClientComponents.dsc.inc | 7 +-
RedfishClientPkg/RedfishClientLibs.dsc.inc | 1 +
7 files changed, 2346 insertions(+), 1 deletion(-)
create mode 100644
RedfishClientPkg/Features/ComputerSystem/v1_5_0/Common/ComputerSy
stemCommon.c
create mode 100644
RedfishClientPkg/Features/ComputerSystem/v1_5_0/Common/ComputerSy
stemCommon.h
create mode 100644
RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystem
Dxe.c
create mode 100644
RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystem
Dxe.inf

diff --git
a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Common/Computer
SystemCommon.c
b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Common/Computer
SystemCommon.c
new file mode 100644
index 0000000000..0a9c746f3b
--- /dev/null
+++
b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Common/Computer
SystemCommon.c
@@ -0,0 +1,1614 @@
+/** @file
+ Redfish feature driver implementation - common functions
+
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "ComputerSystemCommon.h"
+
+CHAR8 ComputerSystemEmptyJson[] = "{\"@odata.id\": \"\",
\"@odata.type\": \"#ComputerSystem.v1_5_0.ComputerSystem\", \"Id\":
\"\", \"Name\": \"\", \"Boot\":{}}";
+
+REDFISH_RESOURCE_COMMON_PRIVATE *mRedfishResourcePrivate =
NULL;
+
+/**
+ Consume resource from given URI.
+
+ @param[in] This Pointer to
REDFISH_RESOURCE_COMMON_PRIVATE instance.
+ @param[in] Json The JSON to consume.
+ @param[in] HeaderEtag The Etag string returned in HTTP header.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @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_COMPUTERSYSTEM_V1_5_0 *ComputerSystem;
+ EFI_REDFISH_COMPUTERSYSTEM_V1_5_0_CS *ComputerSystemCs;
+ EFI_STRING ConfigureLang;
+
+
+ if (Private == NULL || IS_EMPTY_STRING (Json)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ComputerSystem = NULL;
+ ComputerSystemCs = NULL;
+ ConfigureLang = NULL;
+
+ Status = Private->JsonStructProtocol->ToStructure (
+ Private->JsonStructProtocol,
+ NULL,
+ Json,
+ (EFI_REST_JSON_STRUCTURE_HEADER
**)&ComputerSystem
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, ToStructure() failed: %r\n",
__FUNCTION__, Status));
+ return Status;
+ }
+
+ ComputerSystemCs = ComputerSystem->ComputerSystem;
+
+ //
+ // Check ETAG to see if we need to consume it
+ //
+ if (CheckEtag (Private->Uri, HeaderEtag, NULL)) {
+ //
+ // No change
+ //
+ DEBUG ((DEBUG_INFO, "%a, ETAG: %s has no change, ignore consume
action\n", __FUNCTION__, Private->Uri));
+ Status = EFI_ALREADY_STARTED;
+ goto ON_RELEASE;
+ }
+
+ //
+ // Handle ASSETTAG
+ //
+ if (ComputerSystemCs->AssetTag != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"AssetTag");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
AssetTag);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // BIOS will be handled by feature driver.
+ //
+
+ //
+ // Handle BIOSVERSION
+ //
+ if (ComputerSystemCs->BiosVersion != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"BiosVersion");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
BiosVersion);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle BOOT
+ //
+ if (ComputerSystemCs->Boot == NULL) {
+ ComputerSystemCs->Boot = AllocateZeroPool (sizeof
(RedfishComputerSystem_V1_5_0_Boot_CS));
+ ASSERT (ComputerSystemCs->Boot != NULL);
+ }
+
+ //
+ // Handle BOOT->BOOTNEXT
+ //
+ if (ComputerSystemCs->Boot->BootNext != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"Boot/BootNext");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs->Boot-
BootNext);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle BOOT->BOOTORDER
+ //
+ if (ComputerSystemCs->Boot->BootOrder != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"Boot/BootOrder");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringArrayType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs->Boot-
BootOrder);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle BOOT->BOOTSOURCEOVERRIDEENABLED
+ //
+ if (ComputerSystemCs->Boot->BootSourceOverrideEnabled != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"Boot/BootSourceOverrideEnabled");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs->Boot-
BootSourceOverrideEnabled);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle BOOT->BOOTSOURCEOVERRIDEMODE
+ //
+ if (ComputerSystemCs->Boot->BootSourceOverrideMode != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"Boot/BootSourceOverrideMode");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs->Boot-
BootSourceOverrideMode);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle BOOT->BOOTSOURCEOVERRIDETARGET
+ //
+ if (ComputerSystemCs->Boot->BootSourceOverrideTarget != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"Boot/BootSourceOverrideTarget");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs->Boot-
BootSourceOverrideTarget);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle BOOT->UEFITARGETBOOTSOURCEOVERRIDE
+ //
+ if (ComputerSystemCs->Boot->UefiTargetBootSourceOverride != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"Boot/UefiTargetBootSourceOverride");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs->Boot-
UefiTargetBootSourceOverride);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // ETHERNETINTERFACES will be handled by collection driver.
+ //
+
+ //
+ // Handle HOSTNAME
+ //
+ if (ComputerSystemCs->HostName != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"HostName");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
HostName);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle HOSTWATCHDOGTIMER
+ //
+ if (ComputerSystemCs->HostWatchdogTimer == NULL) {
+ ComputerSystemCs->HostWatchdogTimer = AllocateZeroPool (sizeof
(RedfishComputerSystem_V1_5_0_WatchdogTimer_CS));
+ ASSERT (ComputerSystemCs->HostWatchdogTimer != NULL);
+ }
+
+ //
+ // Handle HOSTWATCHDOGTIMER->FUNCTIONENABLED
+ //
+ if (ComputerSystemCs->HostWatchdogTimer->FunctionEnabled != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"HostWatchdogTimer/FunctionEnabled");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsBooleanType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang,
(BOOLEAN)*ComputerSystemCs->HostWatchdogTimer->FunctionEnabled);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle HOSTWATCHDOGTIMER->TIMEOUTACTION
+ //
+ if (ComputerSystemCs->HostWatchdogTimer->TimeoutAction != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"HostWatchdogTimer/TimeoutAction");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
HostWatchdogTimer->TimeoutAction);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle HOSTWATCHDOGTIMER->WARNINGACTION
+ //
+ if (ComputerSystemCs->HostWatchdogTimer->WarningAction != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"HostWatchdogTimer/WarningAction");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
HostWatchdogTimer->WarningAction);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle HOSTEDSERVICES
+ //
+ if (ComputerSystemCs->HostedServices == NULL) {
+ ComputerSystemCs->HostedServices = AllocateZeroPool (sizeof
(RedfishComputerSystem_V1_5_0_HostedServices_CS));
+ ASSERT (ComputerSystemCs->HostedServices != NULL);
+ }
+
+ //
+ // Handle HOSTINGROLES
+ //
+//
+// ****** Warning ******
+// Unsupported array type:
+//
+
+ //
+ // Handle INDICATORLED
+ //
+ if (ComputerSystemCs->IndicatorLED != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"IndicatorLED");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
IndicatorLED);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // LOGSERVICES will be handled by collection driver.
+ //
+
+ //
+ // Handle MANUFACTURER
+ //
+ if (ComputerSystemCs->Manufacturer != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"Manufacturer");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
Manufacturer);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // MEMORY will be handled by collection driver.
+ //
+
+ //
+ // Handle MEMORYSUMMARY
+ //
+ if (ComputerSystemCs->MemorySummary == NULL) {
+ ComputerSystemCs->MemorySummary = AllocateZeroPool (sizeof
(RedfishComputerSystem_V1_5_0_MemorySummary_CS));
+ ASSERT (ComputerSystemCs->MemorySummary != NULL);
+ }
+
+ //
+ // Handle MEMORYSUMMARY->MEMORYMIRRORING
+ //
+ if (ComputerSystemCs->MemorySummary->MemoryMirroring != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"MemorySummary/MemoryMirroring");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
MemorySummary->MemoryMirroring);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle MEMORYSUMMARY->TOTALSYSTEMMEMORYGIB
+ //
+ if (ComputerSystemCs->MemorySummary->TotalSystemMemoryGiB !=
NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"MemorySummary/TotalSystemMemoryGiB");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang,
(UINTN)*ComputerSystemCs->MemorySummary-
TotalSystemMemoryGiB);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle MEMORYSUMMARY->TOTALSYSTEMPERSISTENTMEMORYGIB
+ //
+ if (ComputerSystemCs->MemorySummary-
TotalSystemPersistentMemoryGiB != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"MemorySummary/TotalSystemPersistentMemoryGiB");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang,
(UINTN)*ComputerSystemCs->MemorySummary-
TotalSystemPersistentMemoryGiB);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle MODEL
+ //
+ if (ComputerSystemCs->Model != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"Model");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs->Model);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // NETWORKINTERFACES will be handled by collection driver.
+ //
+
+ //
+ // Handle PCIEDEVICES
+ //
+//
+// ****** Warning ******
+// Unsupported array type:
+//
+
+ //
+ // Handle PCIEFUNCTIONS
+ //
+//
+// ****** Warning ******
+// Unsupported array type:
+//
+
+ //
+ // Handle PARTNUMBER
+ //
+ if (ComputerSystemCs->PartNumber != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"PartNumber");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
PartNumber);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle POWERSTATE
+ //
+ if (ComputerSystemCs->PowerState != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"PowerState");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
PowerState);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle PROCESSORSUMMARY
+ //
+ if (ComputerSystemCs->ProcessorSummary == NULL) {
+ ComputerSystemCs->ProcessorSummary = AllocateZeroPool (sizeof
(RedfishComputerSystem_V1_5_0_ProcessorSummary_CS));
+ ASSERT (ComputerSystemCs->ProcessorSummary != NULL);
+ }
+
+ //
+ // Handle PROCESSORSUMMARY->COUNT
+ //
+ if (ComputerSystemCs->ProcessorSummary->Count != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"ProcessorSummary/Count");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang,
(UINTN)*ComputerSystemCs->ProcessorSummary->Count);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle PROCESSORSUMMARY->LOGICALPROCESSORCOUNT
+ //
+ if (ComputerSystemCs->ProcessorSummary->LogicalProcessorCount !=
NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"ProcessorSummary/LogicalProcessorCount");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang,
(UINTN)*ComputerSystemCs->ProcessorSummary->LogicalProcessorCount);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle PROCESSORSUMMARY->MODEL
+ //
+ if (ComputerSystemCs->ProcessorSummary->Model != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"ProcessorSummary/Model");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
ProcessorSummary->Model);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // PROCESSORS will be handled by collection driver.
+ //
+
+ //
+ // Handle REDUNDANCY
+ //
+//
+// ****** Warning ******
+// Unsupported array type:
+//
+
+ //
+ // Handle SKU
+ //
+ if (ComputerSystemCs->SKU != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"SKU");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs->SKU);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // SECUREBOOT will be handled by feature driver.
+ //
+
+ //
+ // Handle SERIALNUMBER
+ //
+ if (ComputerSystemCs->SerialNumber != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"SerialNumber");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
SerialNumber);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // SIMPLESTORAGE will be handled by collection driver.
+ //
+
+ //
+ // STORAGE will be handled by collection driver.
+ //
+
+ //
+ // Handle SUBMODEL
+ //
+ if (ComputerSystemCs->SubModel != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"SubModel");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
SubModel);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle SYSTEMTYPE
+ //
+ if (ComputerSystemCs->SystemType != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (ComputerSystemCs->odata_id,
"SystemType");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, ComputerSystemCs-
SystemType);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle TRUSTEDMODULES
+ //
+//
+// ****** Warning ******
+// Unsupported array type:
+//
+
+
+ON_RELEASE:
+
+ //
+ // Release resource.
+ //
+ Private->JsonStructProtocol->DestoryStructure (
+ Private->JsonStructProtocol,
+ (EFI_REST_JSON_STRUCTURE_HEADER *)ComputerSystem
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ProvisioningComputerSystemProperties (
+ 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_COMPUTERSYSTEM_V1_5_0 *ComputerSystem;
+ EFI_REDFISH_COMPUTERSYSTEM_V1_5_0_CS *ComputerSystemCs;
+ EFI_STATUS Status;
+ BOOLEAN PropertyChanged;
+ CHAR8 *AsciiStringValue;
+ CHAR8 **AsciiStringArrayValue;
+ UINTN ArraySize;
+ BOOLEAN *BooleanValue;
+ INT32 *IntegerValue;
+ INT64 *NumericValue;
+
+
+
+ if (JsonStructProtocol == NULL || ResultJson == NULL ||
IS_EMPTY_STRING (InputJson) || IS_EMPTY_STRING (ConfigureLang)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a provision for %s with: %s\n",
__FUNCTION__, ConfigureLang, (ProvisionMode ? L"Provision resource" :
L"Update resource")));
+
+ *ResultJson = NULL;
+ PropertyChanged = FALSE;
+
+ ComputerSystem = NULL;
+ Status = JsonStructProtocol->ToStructure (
+ JsonStructProtocol,
+ NULL,
+ InputJson,
+ (EFI_REST_JSON_STRUCTURE_HEADER
**)&ComputerSystem
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, ToStructure failure: %r\n", __FUNCTION__,
Status));
+ return Status;
+ }
+
+ ComputerSystemCs = ComputerSystem->ComputerSystem;
+
+ //
+ // ID
+ //
+ if (ComputerSystemCs->Id == NULL && !IS_EMPTY_STRING (ResourceId))
{
+ ComputerSystemCs->Id = AllocateCopyPool (AsciiStrSize (ResourceId),
ResourceId);
+ }
+
+ //
+ // Handle ASSETTAG
+ //
+ if (PropertyChecker (ComputerSystemCs->AssetTag, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"AssetTag", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->AssetTag,
AsciiStringValue) != 0) {
+ ComputerSystemCs->AssetTag = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle BIOSVERSION
+ //
+ if (PropertyChecker (ComputerSystemCs->BiosVersion, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"BiosVersion", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->BiosVersion,
AsciiStringValue) != 0) {
+ ComputerSystemCs->BiosVersion = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle BOOT
+ //
+ if (ComputerSystemCs->Boot != NULL) {
+ //
+ // Handle BOOT->BOOTNEXT
+ //
+ if (PropertyChecker (ComputerSystemCs->Boot->BootNext,
ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"Boot/BootNext", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->Boot-
BootNext, AsciiStringValue) != 0) {
+ ComputerSystemCs->Boot->BootNext = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle BOOT->BOOTORDER
+ //
+ if (PropertyChecker (ComputerSystemCs->Boot->BootOrder,
ProvisionMode)) {
+ AsciiStringArrayValue = GetPropertyStringArrayValue
(RESOURCE_SCHEMA, RESOURCE_SCHEMA_VERSION, L"Boot/BootOrder",
ConfigureLang, &ArraySize);
+ if (AsciiStringArrayValue != NULL) {
+ if (ProvisionMode || !CompareRedfishStringArrayValues
(ComputerSystemCs->Boot->BootOrder, AsciiStringArrayValue, ArraySize)) {
+ AddRedfishCharArray (&ComputerSystemCs->Boot->BootOrder,
AsciiStringArrayValue, ArraySize);
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle BOOT->BOOTSOURCEOVERRIDEENABLED
+ //
+ if (PropertyChecker (ComputerSystemCs->Boot-
BootSourceOverrideEnabled, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"Boot/BootSourceOverrideEnabled",
ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->Boot-
BootSourceOverrideEnabled, AsciiStringValue) != 0) {
+ ComputerSystemCs->Boot->BootSourceOverrideEnabled =
AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle BOOT->BOOTSOURCEOVERRIDEMODE
+ //
+ if (PropertyChecker (ComputerSystemCs->Boot-
BootSourceOverrideMode, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"Boot/BootSourceOverrideMode",
ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->Boot-
BootSourceOverrideMode, AsciiStringValue) != 0) {
+ ComputerSystemCs->Boot->BootSourceOverrideMode =
AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle BOOT->BOOTSOURCEOVERRIDETARGET
+ //
+ if (PropertyChecker (ComputerSystemCs->Boot-
BootSourceOverrideTarget, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"Boot/BootSourceOverrideTarget",
ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->Boot-
BootSourceOverrideTarget, AsciiStringValue) != 0) {
+ ComputerSystemCs->Boot->BootSourceOverrideTarget =
AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle BOOT->UEFITARGETBOOTSOURCEOVERRIDE
+ //
+ if (PropertyChecker (ComputerSystemCs->Boot-
UefiTargetBootSourceOverride, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"Boot/UefiTargetBootSourceOverride",
ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->Boot-
UefiTargetBootSourceOverride, AsciiStringValue) != 0) {
+ ComputerSystemCs->Boot->UefiTargetBootSourceOverride =
AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ }
+
+ //
+ // Handle HOSTNAME
+ //
+ if (PropertyChecker (ComputerSystemCs->HostName, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"HostName", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->HostName,
AsciiStringValue) != 0) {
+ ComputerSystemCs->HostName = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle HOSTWATCHDOGTIMER
+ //
+ if (ComputerSystemCs->HostWatchdogTimer != NULL) {
+ //
+ // Handle HOSTWATCHDOGTIMER->FUNCTIONENABLED
+ //
+ if (PropertyChecker (ComputerSystemCs->HostWatchdogTimer-
FunctionEnabled, ProvisionMode)) {
+ BooleanValue = GetPropertyBooleanValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"HostWatchdogTimer/FunctionEnabled",
ConfigureLang);
+ if (BooleanValue != NULL) {
+ if (ProvisionMode || *ComputerSystemCs->HostWatchdogTimer-
FunctionEnabled != *BooleanValue) {
+ IntegerValue = AllocatePool (sizeof (*IntegerValue));
+ if (IntegerValue != NULL) {
+ *IntegerValue = (BooleanValue ? 0x01 : 0x00);
+ ComputerSystemCs->HostWatchdogTimer->FunctionEnabled =
IntegerValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ }
+ //
+ // Handle HOSTWATCHDOGTIMER->TIMEOUTACTION
+ //
+ if (PropertyChecker (ComputerSystemCs->HostWatchdogTimer-
TimeoutAction, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"HostWatchdogTimer/TimeoutAction",
ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs-
HostWatchdogTimer->TimeoutAction, AsciiStringValue) != 0) {
+ ComputerSystemCs->HostWatchdogTimer->TimeoutAction =
AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle HOSTWATCHDOGTIMER->WARNINGACTION
+ //
+ if (PropertyChecker (ComputerSystemCs->HostWatchdogTimer-
WarningAction, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"HostWatchdogTimer/WarningAction",
ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs-
HostWatchdogTimer->WarningAction, AsciiStringValue) != 0) {
+ ComputerSystemCs->HostWatchdogTimer->WarningAction =
AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ }
+
+ //
+ // Handle HOSTEDSERVICES
+ //
+ if (ComputerSystemCs->HostedServices != NULL) {
+ }
+
+ //
+ // Handle HOSTINGROLES
+ //
+//// ****** Warning ******
+// Unsupported array type:
+//
+
+ //
+ // Handle INDICATORLED
+ //
+ if (PropertyChecker (ComputerSystemCs->IndicatorLED, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"IndicatorLED", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->IndicatorLED,
AsciiStringValue) != 0) {
+ ComputerSystemCs->IndicatorLED = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle MANUFACTURER
+ //
+ if (PropertyChecker (ComputerSystemCs->Manufacturer, ProvisionMode))
{
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"Manufacturer", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->Manufacturer,
AsciiStringValue) != 0) {
+ ComputerSystemCs->Manufacturer = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle MEMORYSUMMARY
+ //
+ if (ComputerSystemCs->MemorySummary != NULL) {
+ //
+ // Handle MEMORYSUMMARY->MEMORYMIRRORING
+ //
+ if (PropertyChecker (ComputerSystemCs->MemorySummary-
MemoryMirroring, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"MemorySummary/MemoryMirroring",
ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs-
MemorySummary->MemoryMirroring, AsciiStringValue) != 0) {
+ ComputerSystemCs->MemorySummary->MemoryMirroring =
AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle MEMORYSUMMARY->TOTALSYSTEMMEMORYGIB
+ //
+ if (PropertyChecker (ComputerSystemCs->MemorySummary-
TotalSystemMemoryGiB, ProvisionMode)) {
+ NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
L"MemorySummary/TotalSystemMemoryGiB", ConfigureLang);
+ if (NumericValue != NULL) {
+ if (ProvisionMode || *ComputerSystemCs->MemorySummary-
TotalSystemMemoryGiB != *NumericValue) {
+ ComputerSystemCs->MemorySummary->TotalSystemMemoryGiB =
NumericValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle MEMORYSUMMARY->TOTALSYSTEMPERSISTENTMEMORYGIB
+ //
+ if (PropertyChecker (ComputerSystemCs->MemorySummary-
TotalSystemPersistentMemoryGiB, ProvisionMode)) {
+ NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
L"MemorySummary/TotalSystemPersistentMemoryGiB", ConfigureLang);
+ if (NumericValue != NULL) {
+ if (ProvisionMode || *ComputerSystemCs->MemorySummary-
TotalSystemPersistentMemoryGiB != *NumericValue) {
+ ComputerSystemCs->MemorySummary-
TotalSystemPersistentMemoryGiB = NumericValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ }
+
+ //
+ // Handle MODEL
+ //
+ if (PropertyChecker (ComputerSystemCs->Model, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"Model", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->Model,
AsciiStringValue) != 0) {
+ ComputerSystemCs->Model = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle PCIEDEVICES
+ //
+//// ****** Warning ******
+// Unsupported array type:
+//
+
+ //
+ // Handle PCIEFUNCTIONS
+ //
+//// ****** Warning ******
+// Unsupported array type:
+//
+
+ //
+ // Handle PARTNUMBER
+ //
+ if (PropertyChecker (ComputerSystemCs->PartNumber, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"PartNumber", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->PartNumber,
AsciiStringValue) != 0) {
+ ComputerSystemCs->PartNumber = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle POWERSTATE
+ //
+ if (PropertyChecker (ComputerSystemCs->PowerState, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"PowerState", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->PowerState,
AsciiStringValue) != 0) {
+ ComputerSystemCs->PowerState = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle PROCESSORSUMMARY
+ //
+ if (ComputerSystemCs->ProcessorSummary != NULL) {
+ //
+ // Handle PROCESSORSUMMARY->COUNT
+ //
+ if (PropertyChecker (ComputerSystemCs->ProcessorSummary->Count,
ProvisionMode)) {
+ NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"ProcessorSummary/Count",
ConfigureLang);
+ if (NumericValue != NULL) {
+ if (ProvisionMode || *ComputerSystemCs->ProcessorSummary-
Count != *NumericValue) {
+ ComputerSystemCs->ProcessorSummary->Count = NumericValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle PROCESSORSUMMARY->LOGICALPROCESSORCOUNT
+ //
+ if (PropertyChecker (ComputerSystemCs->ProcessorSummary-
LogicalProcessorCount, ProvisionMode)) {
+ NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
L"ProcessorSummary/LogicalProcessorCount", ConfigureLang);
+ if (NumericValue != NULL) {
+ if (ProvisionMode || *ComputerSystemCs->ProcessorSummary-
LogicalProcessorCount != *NumericValue) {
+ ComputerSystemCs->ProcessorSummary->LogicalProcessorCount =
NumericValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle PROCESSORSUMMARY->MODEL
+ //
+ if (PropertyChecker (ComputerSystemCs->ProcessorSummary->Model,
ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"ProcessorSummary/Model",
ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs-
ProcessorSummary->Model, AsciiStringValue) != 0) {
+ ComputerSystemCs->ProcessorSummary->Model = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ }
+
+ //
+ // Handle REDUNDANCY
+ //
+//// ****** Warning ******
+// Unsupported array type:
+//
+
+ //
+ // Handle SKU
+ //
+ if (PropertyChecker (ComputerSystemCs->SKU, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"SKU", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->SKU,
AsciiStringValue) != 0) {
+ ComputerSystemCs->SKU = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle SERIALNUMBER
+ //
+ if (PropertyChecker (ComputerSystemCs->SerialNumber, ProvisionMode))
{
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"SerialNumber", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->SerialNumber,
AsciiStringValue) != 0) {
+ ComputerSystemCs->SerialNumber = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle SUBMODEL
+ //
+ if (PropertyChecker (ComputerSystemCs->SubModel, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"SubModel", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->SubModel,
AsciiStringValue) != 0) {
+ ComputerSystemCs->SubModel = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle SYSTEMTYPE
+ //
+ if (PropertyChecker (ComputerSystemCs->SystemType, ProvisionMode)) {
+ AsciiStringValue = GetPropertyStringValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"SystemType", ConfigureLang);
+ if (AsciiStringValue != NULL) {
+ if (ProvisionMode || AsciiStrCmp (ComputerSystemCs->SystemType,
AsciiStringValue) != 0) {
+ ComputerSystemCs->SystemType = AsciiStringValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ //
+ // Handle TRUSTEDMODULES
+ //
+//// ****** Warning ******
+// Unsupported array type:
+//
+
+
+ //
+ // Convert C structure back to JSON text.
+ //
+ Status = JsonStructProtocol->ToJson (
+ JsonStructProtocol,
+ (EFI_REST_JSON_STRUCTURE_HEADER *)ComputerSystem,
+ ResultJson
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, ToJson() failed: %r\n", __FUNCTION__,
Status));
+ return Status;
+ }
+
+ //
+ // Release resource.
+ //
+ JsonStructProtocol->DestoryStructure (
+ JsonStructProtocol,
+ (EFI_REST_JSON_STRUCTURE_HEADER *)ComputerSystem
+ );
+
+ return (PropertyChanged ? EFI_SUCCESS : EFI_NOT_FOUND);
+}
+
+EFI_STATUS
+ProvisioningComputerSystemResource (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
+ IN UINTN Index,
+ IN EFI_STRING ConfigureLang
+ )
+{
+ CHAR8 *Json;
+ EFI_STATUS Status;
+ EFI_STRING NewResourceLocation;
+ CHAR8 *EtagStr;
+ CHAR8 ResourceId[16];
+
+ if (IS_EMPTY_STRING (ConfigureLang) || Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EtagStr = NULL;
+ AsciiSPrint (ResourceId, sizeof (ResourceId), "%d", Index);
+
+ Status = ProvisioningComputerSystemProperties (
+ Private->JsonStructProtocol,
+ ComputerSystemEmptyJson,
+ ResourceId,
+ ConfigureLang,
+ TRUE,
+ &Json
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, provisioning resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ return Status;
+ }
+
+ Status = CreatePayloadToPostResource (Private->RedfishService, Private-
Payload, Json, &NewResourceLocation, &EtagStr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, post ComputerSystem resource for %s
failed: %r\n", __FUNCTION__, ConfigureLang, Status));
+ goto RELEASE_RESOURCE;
+ }
+
+ ASSERT (NewResourceLocation != NULL);
+
+ //
+ // Keep location of new resource.
+ //
+ if (NewResourceLocation != NULL) {
+ RedfisSetRedfishUri (ConfigureLang, NewResourceLocation);
+ }
+
+ //
+ // Handle Etag
+ //
+ if (EtagStr != NULL) {
+ SetEtagWithUri (EtagStr, NewResourceLocation);
+ FreePool (EtagStr);
+ }
+
+RELEASE_RESOURCE:
+
+ if (NewResourceLocation != NULL) {
+ FreePool (NewResourceLocation);
+ }
+
+ if (Json != NULL) {
+ FreePool (Json);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+ProvisioningComputerSystemResources (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
UnifiedConfigureLangList;
+
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = RedfishFeatureGetUnifiedArrayTypeConfigureLang
(RESOURCE_SCHEMA, RESOURCE_SCHEMA_VERSION,
REDPATH_ARRAY_PATTERN, &UnifiedConfigureLangList);
+ if (EFI_ERROR (Status) || UnifiedConfigureLangList.Count == 0) {
+ DEBUG ((DEBUG_ERROR, "%a, No HII question found with configure
language: %s: %r\n", __FUNCTION__, REDPATH_ARRAY_PATTERN, Status));
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Set the configuration language in the
RESOURCE_INFORMATION_EXCHANGE.
+ // This information is sent back to the parent resource (e.g. the collection
driver).
+ //
+ EdkIIRedfishResourceSetConfigureLang (&UnifiedConfigureLangList);
+
+ for (Index = 0; Index < UnifiedConfigureLangList.Count; Index++) {
+ DEBUG ((DEBUG_INFO, "[%d] create ComputerSystem resource from:
%s\n", UnifiedConfigureLangList.List[Index].Index,
UnifiedConfigureLangList.List[Index].ConfigureLang));
+ ProvisioningComputerSystemResource (Private,
UnifiedConfigureLangList.List[Index].Index,
UnifiedConfigureLangList.List[Index].ConfigureLang);
+ FreePool (UnifiedConfigureLangList.List[Index].ConfigureLang);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+ProvisioningComputerSystemExistResource (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING ConfigureLang;
+ CHAR8 *EtagStr;
+ CHAR8 *Json;
+
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EtagStr = NULL;
+ Json = NULL;
+ ConfigureLang = NULL;
+
+ ConfigureLang = RedfishGetConfigLanguage (Private->Uri);
+ if (ConfigureLang == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = ProvisioningComputerSystemProperties (
+ Private->JsonStructProtocol,
+ ComputerSystemEmptyJson,
+ NULL,
+ ConfigureLang,
+ TRUE,
+ &Json
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, provisioning existing resource
for %s ignored. Nothing changed\n", __FUNCTION__, ConfigureLang));
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, provisioning existing resource for %s
failed: %r\n", __FUNCTION__, ConfigureLang, Status));
+ }
+ goto ON_RELEASE;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, provisioning existing resource for
%s\n", __FUNCTION__, ConfigureLang));
+ //
+ // PUT back to instance
+ //
+ Status = CreatePayloadToPatchResource (Private->RedfishService, Private-
Payload, Json, &EtagStr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, patch resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ //
+ // Handle Etag
+ //
+ if (EtagStr != NULL) {
+ SetEtagWithUri (EtagStr, Private->Uri);
+ FreePool (EtagStr);
+ }
+
+ON_RELEASE:
+
+ if (Json != NULL) {
+ FreePool (Json);
+ }
+
+ if (ConfigureLang != NULL) {
+ FreePool (ConfigureLang);
+ }
+
+ return Status;
+}
+
+/**
+ Provisioning redfish resource by given URI.
+
+ @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCOL
instance.
+ @param[in] ResourceExist TRUE if resource exists, PUT method will be
used.
+ FALSE if resource does not exist POST method is used.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishProvisioningResourceCommon (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
+ IN BOOLEAN ResourceExist
+ )
+{
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return (ResourceExist ? ProvisioningComputerSystemExistResource
(Private) : ProvisioningComputerSystemResources (Private));
+}
+
+/**
+ Check resource from given URI.
+
+ @param[in] This Pointer to
REDFISH_RESOURCE_COMMON_PRIVATE instance.
+ @param[in] Json The JSON to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishCheckResourceCommon (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
+ IN CHAR8 *Json
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_STRING *ConfigureLangList;
+ UINTN Count;
+ EFI_STRING Property;
+
+ if (Private == NULL || IS_EMPTY_STRING (Json)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = RedfishPlatformConfigGetConfigureLang (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, REDPATH_ARRAY_PATTERN,
&ConfigureLangList, &Count);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a,
BiosConfigToRedfishGetConfigureLangRegex failed: %r\n", __FUNCTION__,
Status));
+ return Status;
+ }
+
+ if (Count == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = EFI_SUCCESS;
+ for (Index = 0; Index < Count; Index++) {
+
+ Property = GetPropertyFromConfigureLang (Private->Uri,
ConfigureLangList[Index]);
+ if (Property == NULL) {
+ continue;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a, [%d] check attribute for: %s\n",
__FUNCTION__, Index, Property));
+ if (!MatchPropertyWithJsonContext (Property, Json)) {
+ DEBUG ((DEBUG_INFO, "%a, property is missing: %s\n", __FUNCTION__,
Property));
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+ FreePool (ConfigureLangList);
+
+ return Status;
+}
+
+/**
+ Update resource to given URI.
+
+ @param[in] This Pointer to
REDFISH_RESOURCE_COMMON_PRIVATE instance.
+ @param[in] Json The JSON to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishUpdateResourceCommon (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
+ IN CHAR8 *InputJson
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *Json;
+ EFI_STRING ConfigureLang;
+ CHAR8 *EtagStr;
+
+ if (Private == NULL || IS_EMPTY_STRING (InputJson)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EtagStr = NULL;
+ Json = NULL;
+ ConfigureLang = NULL;
+
+ ConfigureLang = RedfishGetConfigLanguage (Private->Uri);
+ if (ConfigureLang == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = ProvisioningComputerSystemProperties (
+ Private->JsonStructProtocol,
+ InputJson,
+ NULL,
+ ConfigureLang,
+ FALSE,
+ &Json
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, update resource for %s ignored.
Nothing changed\n", __FUNCTION__, ConfigureLang));
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, update resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+ goto ON_RELEASE;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, update resource for %s\n",
__FUNCTION__, ConfigureLang));
+ //
+ // PUT back to instance
+ //
+ Status = CreatePayloadToPatchResource (Private->RedfishService, Private-
Payload, Json, &EtagStr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, patch resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ //
+ // Handle Etag
+ //
+ if (EtagStr != NULL) {
+ SetEtagWithUri (EtagStr, Private->Uri);
+ FreePool (EtagStr);
+ }
+
+ON_RELEASE:
+
+ if (Json != NULL) {
+ FreePool (Json);
+ }
+
+ if (ConfigureLang != NULL) {
+ FreePool (ConfigureLang);
+ }
+
+ return Status;
+}
+
+/**
+ Identify resource from given URI.
+
+ @param[in] This Pointer to
REDFISH_RESOURCE_COMMON_PRIVATE instance.
+ @param[in] Json The JSON to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishIdentifyResourceCommon (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
+ IN CHAR8 *Json
+ )
+{
+ BOOLEAN Supported;
+ EFI_STATUS Status;
+ EFI_STRING EndOfChar;
+ REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST ConfigLangList;
+
+ Supported = RedfishIdentifyResource (Private->Uri, Private->Json);
+ if (Supported) {
+ Status = RedfishFeatureGetUnifiedArrayTypeConfigureLang
(RESOURCE_SCHEMA, RESOURCE_SCHEMA_VERSION,
REDPATH_ARRAY_PATTERN, &ConfigLangList);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a,
BiosConfigToRedfishGetConfigureLangRegex failed: %r\n", __FUNCTION__,
Status));
+ return Status;
+ }
+
+ if (ConfigLangList.Count == 0) {
+ return EFI_SUCCESS;
+ }
+
+ EndOfChar = StrStr (ConfigLangList.List[0].ConfigureLang, L"}");
+ if (EndOfChar == NULL) {
+ ASSERT (FALSE);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //EndOfChar = StrStr (ConfigLangList.List[0].ConfigureLang, L"}");
+ Status = IsRedpathArray (ConfigLangList.List[0].ConfigureLang, NULL,
&EndOfChar);
+ if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
+ ASSERT (FALSE);
+ return EFI_DEVICE_ERROR;
+ }
+ if (Status != EFI_SUCCESS) {
+ //
+ // This is not the collection redpath.
+ //
+ GetRedpathNodeByIndex (ConfigLangList.List[0].ConfigureLang, 0,
&EndOfChar);
+ }
+ *(++EndOfChar) = '\0';
+ //
+ // Keep URI and ConfigLang mapping
+ //
+ RedfisSetRedfishUri (ConfigLangList.List[0].ConfigureLang, Private->Uri);
+ //
+ // Set the configuration language in the
RESOURCE_INFORMATION_EXCHANGE.
+ // This information is sent back to the parent resource (e.g. the collection
driver).
+ //
+ EdkIIRedfishResourceSetConfigureLang (&ConfigLangList);
+ DestroyConfiglanguageList (&ConfigLangList);
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
diff --git
a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Common/Computer
SystemCommon.h
b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Common/Computer
SystemCommon.h
new file mode 100644
index 0000000000..64efc7fd99
--- /dev/null
+++
b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Common/Computer
SystemCommon.h
@@ -0,0 +1,27 @@
+/** @file
+
+ Redfish feature driver implementation - internal header file
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_COMPUTERSYSTEM_COMMON_H_
+#define EFI_REDFISH_COMPUTERSYSTEM_COMMON_H_
+
+#include
<RedfishJsonStructure/ComputerSystem/v1_5_0/EfiComputerSystemV1_5_
0.h>
+#include <RedfishResourceCommon.h>
+
+//
+// Schema information.
+//
+#define RESOURCE_SCHEMA "ComputerSystem"
+#define RESOURCE_SCHEMA_MAJOR "1"
+#define RESOURCE_SCHEMA_MINOR "5"
+#define RESOURCE_SCHEMA_ERRATA "0"
+#define RESOURCE_SCHEMA_VERSION "v1_5_0"
+#define REDPATH_ARRAY_PATTERN L"/Systems/\\{.*\\}/"
+#define REDPATH_ARRAY_PREFIX L"/Systems/"
+#define RESOURCE_SCHEMA_FULL "x-uefi-redfish-
ComputerSystem.v1_5_0"
+
+#endif
diff --git
a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSyste
mDxe.c
b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSyst
emDxe.c
new file mode 100644
index 0000000000..c2a638d7c0
--- /dev/null
+++
b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSyst
emDxe.c
@@ -0,0 +1,645 @@
+/** @file
+ Redfish feature driver implementation - ComputerSystem
+
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "../Common/ComputerSystemCommon.h"
+
+extern REDFISH_RESOURCE_COMMON_PRIVATE
*mRedfishResourcePrivate;
+
+EFI_HANDLE medfishResourceConfigProtocolHandle;
+
+/**
+ Provising redfish resource by given URI.
+
+ @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCOL
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 property is missing, put
method is used.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+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 == NULL || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a, provisioning in %s mode\n", __FUNCTION__,
(PostMode ? L"POST" : L"PATCH")));
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);
+
+ if (Private->RedfishService == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
+ return Status;
+ }
+
+ Private->Uri = Uri;
+ Private->Payload = Response.Payload;
+ ASSERT (Private->Payload != NULL);
+
+ Status = RedfishProvisioningResourceCommon (Private, !PostMode);
+
+ //
+ // Release resource
+ //
+ if (Private->Payload != NULL) {
+ RedfishFreeResponse (
+ Response.StatusCode,
+ Response.HeaderCount,
+ Response.Headers,
+ Response.Payload
+ );
+ Private->Payload = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ Consume resource from given URI.
+
+ @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCOL
instance.
+ @param[in] Uri The target URI to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishResourceConsumeResource (
+ 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 == NULL || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);
+
+ if (Private->RedfishService == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
+ return Status;
+ }
+
+ Private->Uri = Uri;
+ Private->Payload = Response.Payload;
+ ASSERT (Private->Payload != NULL);
+
+ Private->Json = JsonDumpString (RedfishJsonInPayload (Private->Payload),
EDKII_JSON_COMPACT);
+ ASSERT (Private->Json != NULL);
+
+ //
+ // Find etag in HTTP response header
+ //
+ Etag = NULL;
+ Status = GetEtagAndLocation (&Response, &Etag, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to get ETag from HTTP header\n",
__FUNCTION__));
+ }
+
+ Status = RedfishConsumeResourceCommon (Private, Private->Json, Etag);
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_ALREADY_STARTED) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to consume resource from: %s:
%r\n", __FUNCTION__, Uri, Status));
+ }
+ } else {
+ //
+ // Keep etag after consuming pending settings.
+ //
+ if (Etag != NULL) {
+ SetEtagWithUri (Etag, Private->Uri);
+ }
+ }
+
+ //
+ // Release resource
+ //
+ if (Private->Payload != NULL) {
+ RedfishFreeResponse (
+ Response.StatusCode,
+ Response.HeaderCount,
+ Response.Headers,
+ Response.Payload
+ );
+ Private->Payload = NULL;
+ }
+
+ if (Private->Json != NULL) {
+ FreePool (Private->Json);
+ Private->Json = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ Get information about this protocol.
+
+ @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCOL
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
+RedfishResourceGetInfo (
+ IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This,
+ OUT REDFISH_SCHEMA_INFO *Info
+ )
+{
+ REDFISH_RESOURCE_COMMON_PRIVATE *Private;
+
+ if (This == NULL || Info == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);
+
+ AsciiStrCpyS (Info->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);
+ AsciiStrCpyS (Info->Errata, REDFISH_SCHEMA_VERSION_SIZE,
RESOURCE_SCHEMA_ERRATA);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update resource to given URI.
+
+ @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCOL
instance.
+ @param[in] Uri The target URI to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+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 == NULL || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);
+
+ if (Private->RedfishService == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
+ return Status;
+ }
+
+ Private->Uri = Uri;
+ Private->Payload = Response.Payload;
+ ASSERT (Private->Payload != NULL);
+
+ Private->Json = JsonDumpString (RedfishJsonInPayload (Private->Payload),
EDKII_JSON_COMPACT);
+ ASSERT (Private->Json != NULL);
+
+ Status = RedfishUpdateResourceCommon (Private, Private->Json);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to update resource from: %s: %r\n",
__FUNCTION__, Uri, Status));
+ }
+
+ //
+ // Release resource
+ //
+ if (Private->Payload != NULL) {
+ RedfishFreeResponse (
+ Response.StatusCode,
+ Response.HeaderCount,
+ Response.Headers,
+ Response.Payload
+ );
+ Private->Payload = NULL;
+ }
+
+ if (Private->Json != NULL) {
+ FreePool (Private->Json);
+ Private->Json = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ Check resource on given URI.
+
+ @param[in] This Pointer to EFI_HP_REDFISH_HII_PROTOCOL
instance.
+ @param[in] Uri The target URI to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishResourceCheck (
+ IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This,
+ IN EFI_STRING Uri
+ )
+{
+ REDFISH_RESOURCE_COMMON_PRIVATE *Private;
+ EFI_STATUS Status;
+ REDFISH_RESPONSE Response;
+
+ if (This == NULL || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);
+
+ if (Private->RedfishService == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
+ return Status;
+ }
+
+ Private->Uri = Uri;
+ Private->Payload = Response.Payload;
+ ASSERT (Private->Payload != NULL);
+
+ Private->Json = JsonDumpString (RedfishJsonInPayload (Private->Payload),
EDKII_JSON_COMPACT);
+ ASSERT (Private->Json != NULL);
+
+ Status = RedfishCheckResourceCommon (Private, Private->Json);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to check resource from: %s: %r\n",
__FUNCTION__, Uri, Status));
+ }
+
+ //
+ // Release resource
+ //
+ if (Private->Payload != NULL) {
+ RedfishFreeResponse (
+ Response.StatusCode,
+ Response.HeaderCount,
+ Response.Headers,
+ Response.Payload
+ );
+ Private->Payload = NULL;
+ }
+
+ if (Private->Json != NULL) {
+ FreePool (Private->Json);
+ Private->Json = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ Identify resource on given URI.
+
+ @param[in] This Pointer to
EDKII_REDFISH_RESOURCE_CONFIG_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
+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 == NULL || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);
+
+ if (Private->RedfishService == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
+ return Status;
+ }
+
+ Private->Uri = Uri;
+ Private->Payload = Response.Payload;
+ ASSERT (Private->Payload != NULL);
+
+ Private->Json = JsonDumpString (RedfishJsonInPayload (Private->Payload),
EDKII_JSON_COMPACT);
+ ASSERT (Private->Json != NULL);
+
+ Status = RedfishIdentifyResourceCommon (Private, Private->Json);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, identify %s failed: %r\n", __FUNCTION__,
Uri, Status));
+ }
+ //
+ // Release resource
+ //
+ if (Private->Payload != NULL) {
+ RedfishFreeResponse (
+ Response.StatusCode,
+ Response.HeaderCount,
+ Response.Headers,
+ Response.Payload
+ );
+ Private->Payload = NULL;
+ }
+
+ if (Private->Json != NULL) {
+ FreePool (Private->Json);
+ Private->Json = NULL;
+ }
+
+ return Status;
+}
+
+EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL mRedfishResourceConfig
= {
+ RedfishResourceProvisioningResource,
+ RedfishResourceConsumeResource,
+ RedfishResourceUpdate,
+ RedfishResourceCheck,
+ RedfishResourceIdentify,
+ RedfishResourceGetInfo
+};
+
+/**
+ Initialize a Redfish configure handler.
+
+ This function will be called by the Redfish config driver to initialize each
Redfish configure
+ handler.
+
+ @param[in] This Pointer to
EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL instance.
+ @param[in] RedfishConfigServiceInfo Redfish service informaion.
+
+ @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
initialized.
+ @retval Other Error happens during the initialization.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishResourceInit (
+ IN EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *This,
+ IN REDFISH_CONFIG_SERVICE_INFORMATION
*RedfishConfigServiceInfo
+ )
+{
+ REDFISH_RESOURCE_COMMON_PRIVATE *Private;
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_CONFIG_PROTOCO
L (This);
+
+ Private->RedfishService = RedfishCreateService
(RedfishConfigServiceInfo);
+ if (Private->RedfishService == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Stop a Redfish configure handler.
+
+ @param[in] This Pointer to
EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL instance.
+
+ @retval EFI_SUCCESS This handler has been stoped successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishResourceStop (
+ IN EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *This
+ )
+{
+ REDFISH_RESOURCE_COMMON_PRIVATE *Private;
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_CONFIG_PROTOCO
L (This);
+
+ if (Private->Event != NULL) {
+ gBS->CloseEvent (Private->Event);
+ Private->Event = NULL;
+ }
+
+ if (Private->RedfishService != NULL) {
+ RedfishCleanupService (Private->RedfishService);
+ Private->RedfishService = NULL;
+ }
+
+ if (Private->Payload != NULL) {
+ RedfishCleanupPayload (Private->Payload);
+ Private->Payload = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL mRedfishConfigHandler = {
+ 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
+EfiRestJasonStructureProtocolIsReady
+ (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ if (mRedfishResourcePrivate == NULL) {
+ return;
+ }
+
+ if (mRedfishResourcePrivate->JsonStructProtocol != NULL) {
+ return;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiRestJsonStructureProtocolGuid,
+ NULL,
+ (VOID **)&mRedfishResourcePrivate->JsonStructProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to locate
gEfiRestJsonStructureProtocolGuid: %r\n", __FUNCTION__, Status));
+ }
+
+ gBS->CloseEvent (Event);
+}
+
+/**
+ Unloads an image.
+
+ @param ImageHandle Handle that identifies the image to be
unloaded.
+
+ @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 == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ ConfigHandler = NULL;
+
+ //
+ // Firstly, find ConfigHandler Protocol interface in this ImageHandle.
+ //
+ Status = gBS->OpenProtocol (
+ ImageHandle,
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ (VOID **) &ConfigHandler,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+ );
+ if (EFI_ERROR (Status) || ConfigHandler == NULL) {
+ return Status;
+ }
+
+ ConfigHandler->Stop (ConfigHandler);
+
+ //
+ // Last, uninstall ConfigHandler Protocol and resource protocol.
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ImageHandle,
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ ConfigHandler,
+ &gEdkIIRedfishResourceConfigProtocolGuid,
+ &mRedfishResourcePrivate->RedfishResourceConfig,
+ NULL
+ );
+
+ FreePool (mRedfishResourcePrivate);
+ mRedfishResourcePrivate = NULL;
+
+ return Status;
+}
+
+
+/**
+ 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 including
+ both device drivers and bus drivers. It initialize the global variables and
+ publish the driver binding protocol.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI
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 installed 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 != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ medfishResourceConfigProtocolHandle = ImageHandle;
+
+ mRedfishResourcePrivate = AllocateZeroPool (sizeof
(REDFISH_RESOURCE_COMMON_PRIVATE));
+ CopyMem (&mRedfishResourcePrivate->ConfigHandler,
&mRedfishConfigHandler, sizeof
(EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL));
+ CopyMem (&mRedfishResourcePrivate->RedfishResourceConfig,
&mRedfishResourceConfig, sizeof
(EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL));
+
+ //
+ // Publish config handler protocol and resource protocol.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ &mRedfishResourcePrivate->ConfigHandler,
+ &gEdkIIRedfishResourceConfigProtocolGuid,
+ &mRedfishResourcePrivate->RedfishResourceConfig,
+ NULL
+ );
+
+ EfiCreateProtocolNotifyEvent (
+ &gEfiRestJsonStructureProtocolGuid,
+ TPL_CALLBACK,
+ EfiRestJasonStructureProtocolIsReady,
+ NULL,
+ &Registration
+ );
+
+ return Status;
+}
diff --git
a/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSyste
mDxe.inf
b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSyst
emDxe.inf
new file mode 100644
index 0000000000..67412f5f31
--- /dev/null
+++
b/RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSyst
emDxe.inf
@@ -0,0 +1,51 @@
+## @file
+#
+# (C) Copyright 2020-2022 Hewlett Packard Enterprise Development
LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ComputerSystemDxe
+ FILE_GUID = 584bae05-d78d-4df9-b5e9-3e987a99480a
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishResourceEntryPoint
+ UNLOAD_IMAGE = RedfishResourceUnload
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+ RedfishClientPkg/RedfishClientPkg.dec
+
+[Sources]
+ ../Common/ComputerSystemCommon.h
+ ../Common/ComputerSystemCommon.c
+ ComputerSystemDxe.c
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ EdkIIRedfishResourceConfigLib
+ RedfishLib
+ RedfishFeatureUtilityLib
+ RedfishResourceIdentifyLib
+ UefiLib
+ UefiDriverEntryPoint
+
+
+[Protocols]
+ gEdkIIRedfishConfigHandlerProtocolGuid ## PRODUCED
+ gEfiRestJsonStructureProtocolGuid ## CONSUMED
+ gEdkIIRedfishResourceConfigProtocolGuid ## PRODUCED
+
+[Pcd]
+ gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaStringSize
+ gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaVersionSize
+
+[Depex]
+ TRUE
diff --git a/RedfishClientPkg/RedfishClient.fdf.inc
b/RedfishClientPkg/RedfishClient.fdf.inc
index 7d5de56591..90240efbf7 100644
--- a/RedfishClientPkg/RedfishClient.fdf.inc
+++ b/RedfishClientPkg/RedfishClient.fdf.inc
@@ -16,6 +16,7 @@
INF
RedfishClientPkg/RedfishConfigLangMapDxe/RedfishConfigLangMapDxe.inf
INF RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf
INF
RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf
+ INF
RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystem
Dxe.inf
INF
RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyste
mCollectionDxe.inf

!include RedfishClientPkg/RedfishJsonStructureDxe.fdf.inc
@@ -24,5 +25,6 @@
#
INF
RedfishClientPkg/Converter/Memory/v1_7_1/RedfishMemory_V1_7_1_Dx
e.inf
INF
RedfishClientPkg/Converter/MemoryCollection/RedfishMemoryCollection_
Dxe.inf
+ INF
RedfishClientPkg/Converter/ComputerSystem/v1_5_0/RedfishComputerSys
tem_V1_5_0_Dxe.inf
INF
RedfishClientPkg/Converter/ComputerSystemCollection/RedfishComputerS
ystemCollection_Dxe.inf
!endif
diff --git a/RedfishClientPkg/RedfishClientComponents.dsc.inc
b/RedfishClientPkg/RedfishClientComponents.dsc.inc
index d4a33385f6..084796e4b5 100644
--- a/RedfishClientPkg/RedfishClientComponents.dsc.inc
+++ b/RedfishClientPkg/RedfishClientComponents.dsc.inc
@@ -16,11 +16,16 @@
RedfishClientPkg/RedfishFeatureCoreDxe/RedfishFeatureCoreDxe.inf
RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.inf

RedfishClientPkg/RedfishConfigLangMapDxe/RedfishConfigLangMapDxe.inf
+!endif
#
# Below two modules should be pulled in by build tool.
#
RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf

RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf
+
RedfishClientPkg/Features/ComputerSystem/v1_5_0/Dxe/ComputerSystem
Dxe.inf {
+ <LibraryClasses>
+
RedfishResourceIdentifyLib|RedfishClientPkg/Library/RedfishResourceIdenti
fyLibComuterSystem/v1_5_0/RedfishResourceIdentifyLibComuterSystem.in
f
+ }

RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyste
mCollectionDxe.inf

!include RedfishClientPkg/RedfishJsonStructureDxe.dsc.inc
@@ -30,5 +35,5 @@
#

RedfishClientPkg/Converter/Memory/v1_7_1/RedfishMemory_V1_7_1_Dx
e.inf

RedfishClientPkg/Converter/MemoryCollection/RedfishMemoryCollection_
Dxe.inf
-!endif
+
RedfishClientPkg/Converter/ComputerSystem/v1_5_0/RedfishComputerSys
tem_V1_5_0_Dxe.inf

RedfishClientPkg/Converter/ComputerSystemCollection/RedfishComputerS
ystemCollection_Dxe.inf
diff --git a/RedfishClientPkg/RedfishClientLibs.dsc.inc
b/RedfishClientPkg/RedfishClientLibs.dsc.inc
index 21595613f5..05ad09ef5e 100644
--- a/RedfishClientPkg/RedfishClientLibs.dsc.inc
+++ b/RedfishClientPkg/RedfishClientLibs.dsc.inc
@@ -19,6 +19,7 @@
#

MemoryV1_7_1Lib|RedfishClientPkg/ConverterLib/edk2library/Memory/v1
_7_1/Lib.inf

MemoryCollectionLib|RedfishClientPkg/ConverterLib/edk2library/MemoryC
ollection/Lib.inf
+
ComputerSystemV1_5_0Lib|RedfishClientPkg/ConverterLib/edk2library/Co
mputerSystem/v1_5_0/Lib.inf

ComputerSystemCollectionLib|RedfishClientPkg/ConverterLib/edk2library/C
omputerSystemCollection/Lib.inf

NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
--
2.32.0.windows.2


Re: [edk2-staging][PATCH v3 13/15] edk2-staging/RedfishClientPkg: Introduce Computer System collection driver

Chang, Abner
 

[AMD Official Use Only - General]

Reviewed-by: Abner Chang <abner.chang@...>

-----Original Message-----
From: Nickle Wang <nickle.wang@...>
Sent: Wednesday, July 27, 2022 9:38 AM
To: devel@edk2.groups.io
Cc: Chang, Abner <Abner.Chang@...>; Yang, Atom
<Atom.Yang@...>; Nick Ramirez <nramirez@...>
Subject: [edk2-staging][PATCH v3 13/15] edk2-staging/RedfishClientPkg:
Introduce Computer System collection driver

[CAUTION: External Email]

Introduce new feature driver to support Computer System Collection
schema. Update corresponding FDF and DSC file to enable this feature driver.

Signed-off-by: Nickle Wang <nickle.wang@...>
Cc: Abner Chang <abner.chang@...>
Cc: Yang Atom <Atom.Yang@...>
Cc: Nick Ramirez <nramirez@...>
---
.../ComputerSystemCollectionDxe.c | 667 ++++++++++++++++++
.../ComputerSystemCollectionDxe.h | 21 +
.../ComputerSystemCollectionDxe.inf | 56 ++
RedfishClientPkg/RedfishClient.fdf.inc | 2 +
.../RedfishClientComponents.dsc.inc | 2 +
RedfishClientPkg/RedfishClientLibs.dsc.inc | 1 +
6 files changed, 749 insertions(+)
create mode 100644
RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyste
mCollectionDxe.c
create mode 100644
RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyste
mCollectionDxe.h
create mode 100644
RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyste
mCollectionDxe.inf

diff --git
a/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyst
emCollectionDxe.c
b/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyst
emCollectionDxe.c
new file mode 100644
index 0000000000..dbf5ab3395
--- /dev/null
+++
b/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyst
+++ emCollectionDxe.c
@@ -0,0 +1,667 @@
+/** @file
+
+ Redfish feature driver implementation - ComputerSystemCollection
+
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "ComputerSystemCollectionDxe.h"
+
+REDFISH_COLLECTION_PRIVATE *mRedfishCollectionPrivate = NULL;
+
+EFI_STATUS
+HandleResource (
+ IN REDFISH_COLLECTION_PRIVATE *Private,
+ IN EFI_STRING Uri
+ )
+{
+ EFI_STATUS Status;
+ REDFISH_SCHEMA_INFO SchemaInfo;
+ EFI_STRING ConfigLang;
+ EFI_STRING ReturnedConfigLang;
+ UINTN Index;
+
+ if (Private == NULL || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Resource match
+ //
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, process resource for: %s\n",
+ __FUNCTION__, Uri));
+
+ Status = GetRedfishSchemaInfo (Private->RedfishService,
+ Private->JsonStructProtocol, Uri, &SchemaInfo); if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to get schema information from: %s
%r\n", __FUNCTION__, 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, "%s Identify for %s\n", __FUNCTION__,
+ Uri)); ConfigLang = RedfishGetConfigLanguage (Uri); if (ConfigLang
+ == NULL) {
+ Status = EdkIIRedfishResourceConfigIdentify (&SchemaInfo, Uri, Private-
InformationExchange);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_UNSUPPORTED) {
+ DEBUG ((DEBUG_INFO, "%a, \"%s\" is not handled by us\n",
__FUNCTION__, Uri));
+ return EFI_SUCCESS;
+ }
+
+ DEBUG ((DEBUG_ERROR, "%a, fail to identify resource: \"%s\": %r\n",
__FUNCTION__, Uri, Status));
+ return Status;
+ }
+ } else {
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, history record found: %s\n",
__FUNCTION__, ConfigLang));
+ //
+ // Set exchange information
+ //
+ Status = GetArrayIndexFromArrayTypeConfigureLang (ConfigLang,
&ReturnedConfigLang, &Index);
+ if (!EFI_ERROR (Status) || Status == EFI_NOT_FOUND) {
+ Private->InformationExchange->ReturnedInformation.Type =
InformationTypeCollectionMemberConfigLanguage;
+ Private->InformationExchange-
ReturnedInformation.ConfigureLanguageList.Count = 1;
+ Private->InformationExchange-
ReturnedInformation.ConfigureLanguageList.List =
+ AllocateZeroPool(sizeof
+ (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG));
+
+ if (Private->InformationExchange-
ReturnedInformation.ConfigureLanguageList.List == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG.\n", __FUNCTION__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Private->InformationExchange-
ReturnedInformation.ConfigureLanguageList.List [0].Index = Index;
+ Private->InformationExchange-
ReturnedInformation.ConfigureLanguageList.List [0].ConfigureLang =
+ (EFI_STRING)AllocateCopyPool(StrSize(ReturnedConfigLang), (VOID
*)ReturnedConfigLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a,
GetArrayIndexFromArrayTypeConfigureLang fail: %r\n", __FUNCTION__,
Status));
+ }
+ FreePool (ConfigLang);
+ }
+
+ //
+ // Check and see if target property exist or not even when collection
memeber exists.
+ // If not, we sill do provision.
+ //
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a Check for %s\n", __FUNCTION__,
+ Uri)); Status = EdkIIRedfishResourceConfigCheck (&SchemaInfo, Uri);
+ if (EFI_ERROR (Status)) {
+ //
+ // The target property does not exist, do the provision to create property.
+ //
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a provision for %s\n",
__FUNCTION__, Uri));
+ Status = EdkIIRedfishResourceConfigProvisionging (&SchemaInfo, Uri,
Private->InformationExchange, FALSE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to provision with GET mode: %r\n",
__FUNCTION__, Status));
+ }
+
+ return Status;
+ }
+
+ //
+ // Consume first.
+ //
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a consume for %s\n",
__FUNCTION__,
+ Uri)); Status = EdkIIRedfishResourceConfigConsume (&SchemaInfo, Uri);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to consume resoruce for: %s:
+ %r\n", __FUNCTION__, Uri, Status)); }
+
+ //
+ // Patch.
+ //
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a update for %s\n", __FUNCTION__,
+ Uri)); Status = EdkIIRedfishResourceConfigUpdate (&SchemaInfo, Uri);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to update resoruce for: %s: %r\n",
+ __FUNCTION__, Uri, Status)); }
+
+ return Status;
+}
+
+EFI_STATUS
+HandleCollectionResource (
+ IN REDFISH_COLLECTION_PRIVATE *Private
+ )
+{
+ EFI_STATUS Status;
+ EFI_REDFISH_COMPUTERSYSTEMCOLLECTION *Collection;
+ EFI_REDFISH_COMPUTERSYSTEMCOLLECTION_CS *CollectionCs;
+ RedfishCS_Link *List;
+ RedfishCS_Header *Header;
+ RedfishCS_Type_Uri_Data *UriData;
+ EFI_STRING MemberUri;
+
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Private->JsonStructProtocol == NULL || Private->CollectionJson ==
NULL) {
+ return EFI_NOT_READY;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, process collection for: %s\n",
+ __FUNCTION__, Private->CollectionUri));
+
+ //
+ // Convert JSON text to C structure.
+ //
+ Status = Private->JsonStructProtocol->ToStructure (
+ Private->JsonStructProtocol,
+ NULL,
+ Private->CollectionJson,
+ (EFI_REST_JSON_STRUCTURE_HEADER **)&Collection
+ ); if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, ToStructure() failed: %r\n",
__FUNCTION__, Status));
+ return Status;
+ }
+
+ CollectionCs = Collection->ComputerSystemCollection;
+
+ if (*CollectionCs->Membersodata_count == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (IsLinkEmpty (&CollectionCs->Members)) {
+ return EFI_NOT_FOUND;
+ }
+
+ List = GetFirstLink (&CollectionCs->Members); while (TRUE) {
+
+ Header = (RedfishCS_Header *)List;
+ if (Header->ResourceType == RedfishCS_Type_Uri) {
+ UriData = (RedfishCS_Type_Uri_Data *)Header;
+ MemberUri = NULL;
+ MemberUri = StrAsciiToUnicode (UriData->Uri);
+ ASSERT (MemberUri != NULL);
+ if (MemberUri != NULL) {
+ Status = HandleResource (Private, MemberUri);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, process ComputerSystemCollection
resource: %a failed: %r\n", __FUNCTION__, UriData->Uri, Status));
+ }
+
+ FreePool (MemberUri);
+ }
+ }
+
+ if (IsLinkAtEnd (&CollectionCs->Members, List)) {
+ break;
+ }
+
+ List = GetNextLink (&CollectionCs->Members, List); }
+
+ //
+ // Release resource.
+ //
+ Private->JsonStructProtocol->DestoryStructure
+ (Private->JsonStructProtocol, (EFI_REST_JSON_STRUCTURE_HEADER
+ *)Collection);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateCollectionResource (
+ IN REDFISH_COLLECTION_PRIVATE *Private
+ )
+{
+ EFI_STATUS Status;
+ REDFISH_SCHEMA_INFO SchemaInfo;
+
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, create resource for collection for:
+ %s\n", __FUNCTION__, Private->CollectionUri));
+
+ Status = GetSupportedSchemaVersion (REDFISH_SCHEMA_NAME,
+ &SchemaInfo); if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to find supported schema from HII
database: %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, supported schema: %a
%a.%a.%a\n",
+ __FUNCTION__, SchemaInfo.Schema, SchemaInfo.Major,
SchemaInfo.Minor,
+ SchemaInfo.Errata));
+
+ Status = EdkIIRedfishResourceConfigProvisionging (&SchemaInfo,
+ Private->CollectionUri, Private->InformationExchange, TRUE); if
(EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to create resoruce for: %s: %r\n",
+ __FUNCTION__, Private->CollectionUri, Status)); }
+
+ return Status;
+}
+
+EFI_STATUS
+ReleaseCollectionResource (
+ IN REDFISH_COLLECTION_PRIVATE *Private
+ )
+{
+
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Release resource
+ //
+ if (Private->RedResponse.Payload != NULL) {
+ RedfishFreeResponse (
+ Private->RedResponse.StatusCode,
+ Private->RedResponse.HeaderCount,
+ Private->RedResponse.Headers,
+ Private->RedResponse.Payload
+ );
+ Private->RedResponse.StatusCode = NULL;
+ Private->RedResponse.HeaderCount = 0;
+ Private->RedResponse.Headers = NULL;
+ Private->RedResponse.Payload = NULL; }
+
+ if (Private->CollectionJson != NULL) {
+ FreePool (Private->CollectionJson);
+ Private->CollectionJson = NULL;
+ }
+
+ if (Private->RedfishVersion != NULL) {
+ FreePool (Private->RedfishVersion);
+ Private->RedfishVersion = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CollectionHandler (
+ IN REDFISH_COLLECTION_PRIVATE *Private
+ )
+{
+ EFI_STATUS Status;
+
+ if (Private == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, collection handler for %s\n",
+ __FUNCTION__, Private->CollectionUri));
+
+ //
+ // Query collection from Redfish service.
+ //
+ Status = GetResourceByUri (Private->RedfishService,
+ Private->CollectionUri, &Private->RedResponse); if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, unable to get resource from: %s :%r\n",
__FUNCTION__, Private->CollectionUri, Status));
+ goto ON_RELEASE;
+ }
+
+ Private->CollectionPayload = Private->RedResponse.Payload; ASSERT
+ (Private->CollectionPayload != NULL);
+
+ Private->CollectionJson = JsonDumpString (RedfishJsonInPayload
+ (Private->CollectionPayload), EDKII_JSON_COMPACT); ASSERT
+ (Private->CollectionJson != NULL);
+
+ Status = HandleCollectionResource (Private); if (EFI_ERROR (Status)
+ && Status == EFI_NOT_FOUND) {
+ Status = CreateCollectionResource (Private); }
+
+ON_RELEASE:
+
+ ReleaseCollectionResource (Private);
+
+ return Status;
+}
+
+/**
+ The callback function provided by Redfish Feature driver.
+
+ @param[in] This Pointer to EDKII_REDFISH_FEATURE_PROTOCOL
instance.
+ @param[in] FeatureAction The action Redfish feature driver should
take.
+ @param[in] Uri The collection URI.
+ @param[in] Context The context of Redfish feature driver.
+ @param[in,out] InformationExchange The pointer to
+ RESOURCE_INFORMATION_EXCHANGE
+
+ @retval EFI_SUCCESS Redfish feature driver callback is executed
successfully.
+ @retval Others Some errors happened.
+
+ @retval EFI_SUCCESS Redfish feature driver callback is executed
successfully.
+ @retval Others Some errors happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCollectionFeatureCallback (
+ 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_COLLECTION_PRIVATE *Private;
+ EFI_STRING ResourceUri;
+
+ if (FeatureAction != CallbackActionStartOperation) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Private = (REDFISH_COLLECTION_PRIVATE *)Context;
+
+ RedfishService = Private->RedfishService; if (RedfishService ==
+ NULL) {
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Save in private structure.
+ //
+ Private->InformationExchange = InformationExchange;
+
+ //
+ // Find Redfish version on BMC
+ //
+ Private->RedfishVersion = RedfishGetVersion (RedfishService);
+
+ //
+ // Create the full URI from Redfish service root.
+ //
+ ResourceUri = (EFI_STRING)AllocateZeroPool (MAX_URI_LENGTH *
+ sizeof(CHAR16)); if (ResourceUri == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for full URI.\n",
__FUNCTION__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ StrCatS (ResourceUri, MAX_URI_LENGTH, Private->RedfishVersion);
+ StrCatS (ResourceUri, MAX_URI_LENGTH,
+ InformationExchange->SendInformation.FullUri);
+
+ //
+ // Initialize collection path
+ //
+ Private->CollectionUri = RedfishGetUri (ResourceUri); if
+ (Private->CollectionUri == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = CollectionHandler (Private); if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, CollectionHandler failure: %r\n",
+ __FUNCTION__, Status)); }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize a Redfish configure handler.
+
+ This function will be called by the Redfish config driver to
+ initialize each Redfish configure handler.
+
+ @param[in] This Pointer to
EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL instance.
+ @param[in] RedfishConfigServiceInfo Redfish service informaion.
+
+ @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
initialized.
+ @retval Other Error happens during the initialization.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCollectionInit (
+ IN EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *This,
+ IN REDFISH_CONFIG_SERVICE_INFORMATION
*RedfishConfigServiceInfo
+ )
+{
+ REDFISH_COLLECTION_PRIVATE *Private;
+
+ Private = REDFISH_COLLECTION_PRIVATE_DATA_FROM_PROTOCOL (This);
+
+ Private->RedfishService = RedfishCreateService
+ (RedfishConfigServiceInfo); if (Private->RedfishService == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Stop a Redfish configure handler.
+
+ @param[in] This Pointer to
EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL instance.
+
+ @retval EFI_SUCCESS This handler has been stoped successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCollectionStop (
+ IN EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *This
+ )
+{
+ REDFISH_COLLECTION_PRIVATE *Private;
+
+ Private = REDFISH_COLLECTION_PRIVATE_DATA_FROM_PROTOCOL (This);
+
+ if (Private->RedfishService != NULL) {
+ RedfishCleanupService (Private->RedfishService);
+ Private->RedfishService = NULL;
+ }
+
+ ReleaseCollectionResource (Private);
+
+ if (Private->FeatureProtocol != NULL) {
+ Private->FeatureProtocol->Unregister (
+ Private->FeatureProtocol,
+ REDFISH_MANAGED_URI,
+ NULL
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ 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
+EfiRestJasonStructureProtocolIsReady
+ (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ if (mRedfishCollectionPrivate == NULL) {
+ return;
+ }
+
+ if (mRedfishCollectionPrivate->JsonStructProtocol != NULL) {
+ return;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEfiRestJsonStructureProtocolGuid,
+ NULL,
+ (VOID **)&mRedfishCollectionPrivate->JsonStructProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to locate
+ gEfiRestJsonStructureProtocolGuid: %r\n", __FUNCTION__, Status)); }
+
+ gBS->CloseEvent (Event);
+}
+
+/**
+ 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 (mRedfishCollectionPrivate == NULL) {
+ return;
+ }
+
+ if (mRedfishCollectionPrivate->FeatureProtocol != NULL) {
+ return;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gEdkIIRedfishFeatureProtocolGuid,
+ NULL,
+ (VOID **)&FeatureProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to locate
gEdkIIRedfishFeatureProtocolGuid: %r\n", __FUNCTION__, Status));
+ gBS->CloseEvent (Event);
+ return;
+ }
+
+ Status = FeatureProtocol->Register (
+ FeatureProtocol,
+ REDFISH_MANAGED_URI,
+ RedfishCollectionFeatureCallback,
+ (VOID *)mRedfishCollectionPrivate
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to register %s: %r\n",
+ __FUNCTION__, REDFISH_MANAGED_URI, Status)); }
+
+ mRedfishCollectionPrivate->FeatureProtocol = FeatureProtocol;
+
+ gBS->CloseEvent (Event);
+}
+
+/**
+ Unloads an image.
+
+ @param ImageHandle Handle that identifies the image to be
unloaded.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+ @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image
handle.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCollectionUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *ConfigHandler;
+
+ if (mRedfishCollectionPrivate == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ ConfigHandler = NULL;
+
+ //
+ // Firstly, find ConfigHandler Protocol interface in this ImageHandle.
+ //
+ Status = gBS->OpenProtocol (
+ ImageHandle,
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ (VOID **) &ConfigHandler,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+ );
+ if (EFI_ERROR (Status) || ConfigHandler == NULL) {
+ return Status;
+ }
+
+ ConfigHandler->Stop (ConfigHandler);
+
+ //
+ // Last, uninstall ConfigHandler Protocol.
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ImageHandle,
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ ConfigHandler,
+ NULL
+ );
+
+ FreePool (mRedfishCollectionPrivate); mRedfishCollectionPrivate =
+ NULL;
+
+ return Status;
+}
+
+EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL mRedfishConfigHandler = {
+ RedfishCollectionInit,
+ RedfishCollectionStop
+};
+
+/**
+ 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
+including
+ both device drivers and bus drivers. It initialize the global
+variables and
+ publish the driver binding protocol.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI
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 installed unexpectedly.
+ @retval Others Other errors as indicated.
+**/
+EFI_STATUS
+EFIAPI
+RedfishCollectionEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ VOID *Registration;
+
+ if (mRedfishCollectionPrivate != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ mRedfishCollectionPrivate = AllocateZeroPool (sizeof
+ (REDFISH_COLLECTION_PRIVATE)); CopyMem
+ (&mRedfishCollectionPrivate->ConfigHandler, &mRedfishConfigHandler,
+ sizeof (EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL));
+
+ Status = gBS->InstallProtocolInterface (
+ &ImageHandle,
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mRedfishCollectionPrivate->ConfigHandler
+ );
+
+ EfiCreateProtocolNotifyEvent (
+ &gEfiRestJsonStructureProtocolGuid,
+ TPL_CALLBACK,
+ EfiRestJasonStructureProtocolIsReady,
+ NULL,
+ &Registration
+ );
+
+ EfiCreateProtocolNotifyEvent (
+ &gEdkIIRedfishFeatureProtocolGuid,
+ TPL_CALLBACK,
+ EdkIIRedfishFeatureProtocolIsReady,
+ NULL,
+ &Registration
+ );
+
+ return Status;
+}
diff --git
a/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyst
emCollectionDxe.h
b/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyst
emCollectionDxe.h
new file mode 100644
index 0000000000..a4778c1012
--- /dev/null
+++
b/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyst
+++ emCollectionDxe.h
@@ -0,0 +1,21 @@
+/** @file
+
+ Redfish feature driver implementation - internal header file
+
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_COMPUTERSYSTEM_COLLECTION_H_
+#define EFI_REDFISH_COMPUTERSYSTEM_COLLECTION_H_
+
+#include
+<RedfishJsonStructure/ComputerSystemCollection/EfiComputerSystemColl
ect
+ion.h>
+#include <RedfishCollectionCommon.h>
+
+#define REDFISH_SCHEMA_NAME "ComputerSystem"
+#define REDFISH_MANAGED_URI L"Systems/{}"
+#define MAX_URI_LENGTH 256
+
+#endif
diff --git
a/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyst
emCollectionDxe.inf
b/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyst
emCollectionDxe.inf
new file mode 100644
index 0000000000..107d6c0769
--- /dev/null
+++
b/RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyst
+++ emCollectionDxe.inf
@@ -0,0 +1,56 @@
+## @file
+#
+# Redfish ComputerSystemCollection collection driver.
+#
+# (C) Copyright 2020-2022 Hewlett Packard Enterprise Development
+LP<BR> # # SPDX-License-Identifier: BSD-2-Clause-Patent # ##
+
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ComputerSystemCollectionDxe
+ FILE_GUID = df883f2e-9f58-4514-9cc9-06cbe6f63073
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishCollectionEntryPoint
+ UNLOAD_IMAGE = RedfishCollectionUnload
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+ RedfishClientPkg/RedfishClientPkg.dec
+
+[Sources]
+ ComputerSystemCollectionDxe.h
+ ComputerSystemCollectionDxe.c
+
+[LibraryClasses]
+ DebugLib
+ BaseMemoryLib
+ ConverterCommonLib
+ MemoryAllocationLib
+ RedfishFeatureUtilityLib
+ RedfishLib
+ UefiLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ EdkIIRedfishResourceConfigLib
+ RedfishVersionLib
+
+[Protocols]
+ gEdkIIRedfishConfigHandlerProtocolGuid ## CONSUMED
+ gEfiRestJsonStructureProtocolGuid ## CONSUMED
+ gEdkIIRedfishFeatureProtocolGuid ## CONSUMED
+
+[Guids]
+
+[Pcd]
+ gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaStringSize
+ gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaVersionSize
+
+[Depex]
+ TRUE
diff --git a/RedfishClientPkg/RedfishClient.fdf.inc
b/RedfishClientPkg/RedfishClient.fdf.inc
index 5c4b9670b0..7d5de56591 100644
--- a/RedfishClientPkg/RedfishClient.fdf.inc
+++ b/RedfishClientPkg/RedfishClient.fdf.inc
@@ -16,6 +16,7 @@
INF
RedfishClientPkg/RedfishConfigLangMapDxe/RedfishConfigLangMapDxe.inf
INF RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf
INF
RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf
+ INF
RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyste
mCollectionDxe.inf

!include RedfishClientPkg/RedfishJsonStructureDxe.fdf.inc
#
@@ -23,4 +24,5 @@
#
INF
RedfishClientPkg/Converter/Memory/v1_7_1/RedfishMemory_V1_7_1_Dx
e.inf
INF
RedfishClientPkg/Converter/MemoryCollection/RedfishMemoryCollection_
Dxe.inf
+ INF
RedfishClientPkg/Converter/ComputerSystemCollection/RedfishComputerS
ystemCollection_Dxe.inf
!endif
diff --git a/RedfishClientPkg/RedfishClientComponents.dsc.inc
b/RedfishClientPkg/RedfishClientComponents.dsc.inc
index 031d87558e..d4a33385f6 100644
--- a/RedfishClientPkg/RedfishClientComponents.dsc.inc
+++ b/RedfishClientPkg/RedfishClientComponents.dsc.inc
@@ -21,6 +21,7 @@
#
RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf

RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf
+
RedfishClientPkg/Features/ComputerSystemCollectionDxe/ComputerSyste
mCollectionDxe.inf

!include RedfishClientPkg/RedfishJsonStructureDxe.dsc.inc

@@ -30,3 +31,4 @@

RedfishClientPkg/Converter/Memory/v1_7_1/RedfishMemory_V1_7_1_Dx
e.inf

RedfishClientPkg/Converter/MemoryCollection/RedfishMemoryCollection_
Dxe.inf
!endif
+
RedfishClientPkg/Converter/ComputerSystemCollection/RedfishComputerS
ystemCollection_Dxe.inf
diff --git a/RedfishClientPkg/RedfishClientLibs.dsc.inc
b/RedfishClientPkg/RedfishClientLibs.dsc.inc
index 413b83a732..21595613f5 100644
--- a/RedfishClientPkg/RedfishClientLibs.dsc.inc
+++ b/RedfishClientPkg/RedfishClientLibs.dsc.inc
@@ -19,6 +19,7 @@
#

MemoryV1_7_1Lib|RedfishClientPkg/ConverterLib/edk2library/Memory/v1
_7_1/Lib.inf

MemoryCollectionLib|RedfishClientPkg/ConverterLib/edk2library/MemoryC
ollection/Lib.inf
+
ComputerSystemCollectionLib|RedfishClientPkg/ConverterLib/edk2library/C
omputerSystemCollection/Lib.inf

NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf
--
2.32.0.windows.2


Re: [edk2-staging][PATCH v3 12/15] edk2-staging/RedfishClientPkg: Rename Memory feature driver

Chang, Abner
 

[AMD Official Use Only - General]

This is the auto-gen file. I just give my review tag.

Reviewed-by: Abner Chang <abner.chang@...>

-----Original Message-----
From: Nickle Wang <nickle.wang@...>
Sent: Wednesday, July 27, 2022 9:38 AM
To: devel@edk2.groups.io
Cc: Chang, Abner <Abner.Chang@...>; Yang, Atom
<Atom.Yang@...>; Nick Ramirez <nramirez@...>
Subject: [edk2-staging][PATCH v3 12/15] edk2-staging/RedfishClientPkg:
Rename Memory feature driver

[CAUTION: External Email]

Rename Memory driver by removing Redfish prefix. Update memory feature
driver and support all properties under Memory schema. Also support
"Identify" action in this driver. Corresponding changes are made to
honor newly introduced library and protocol.

Signed-off-by: Nickle Wang <nickle.wang@...>
Cc: Abner Chang <abner.chang@...>
Cc: Yang Atom <Atom.Yang@...>
Cc: Nick Ramirez <nramirez@...>
---
.../{RedfishMemoryCommon.c => MemoryCommon.c} | 1194 ++++++++++-
------
.../{RedfishMemoryCommon.h => MemoryCommon.h} | 2 +-
.../Dxe/{RedfishMemoryDxe.c => MemoryDxe.c} | 138 +-
.../{RedfishMemoryDxe.inf => MemoryDxe.inf} | 21 +-
.../Include/RedfishResourceCommon.h | 38 +-
RedfishClientPkg/RedfishClient.fdf.inc | 2 +-
.../RedfishClientComponents.dsc.inc | 2 +-
7 files changed, 839 insertions(+), 558 deletions(-)
rename
RedfishClientPkg/Features/Memory/V1_7_1/Common/{RedfishMemoryCo
mmon.c => MemoryCommon.c} (64%)
rename
RedfishClientPkg/Features/Memory/V1_7_1/Common/{RedfishMemoryCo
mmon.h => MemoryCommon.h} (89%)
rename
RedfishClientPkg/Features/Memory/V1_7_1/Dxe/{RedfishMemoryDxe.c =>
MemoryDxe.c} (75%)
rename
RedfishClientPkg/Features/Memory/V1_7_1/Dxe/{RedfishMemoryDxe.inf
=> MemoryDxe.inf} (57%)

diff --git
a/RedfishClientPkg/Features/Memory/V1_7_1/Common/RedfishMemoryCo
mmon.c
b/RedfishClientPkg/Features/Memory/V1_7_1/Common/MemoryCommon.
c
similarity index 64%
rename from
RedfishClientPkg/Features/Memory/V1_7_1/Common/RedfishMemoryCom
mon.c
rename to
RedfishClientPkg/Features/Memory/V1_7_1/Common/MemoryCommon.c
index 11f738f71c..745c5f9847 100644
---
a/RedfishClientPkg/Features/Memory/V1_7_1/Common/RedfishMemoryCo
mmon.c
+++
b/RedfishClientPkg/Features/Memory/V1_7_1/Common/MemoryCommon.
c
@@ -1,45 +1,54 @@
/** @file
Redfish feature driver implementation - common functions

- (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

**/

-#include "RedfishMemoryCommon.h"
+#include "MemoryCommon.h"

CHAR8 MemoryEmptyJson[] = "{\"@odata.id\": \"\", \"@odata.type\":
\"#Memory.v1_7_1.Memory\", \"Id\": \"\", \"Name\": \"\"}";

REDFISH_RESOURCE_COMMON_PRIVATE *mRedfishResourcePrivate =
NULL;

+/**
+ Consume resource from given URI.
+
+ @param[in] This Pointer to
REDFISH_RESOURCE_COMMON_PRIVATE instance.
+ @param[in] Json The JSON to consume.
+ @param[in] HeaderEtag The Etag string returned in HTTP header.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
EFI_STATUS
RedfishConsumeResourceCommon (
IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
- IN CHAR8 *MemoryJson
+ IN CHAR8 *Json,
+ IN CHAR8 *HeaderEtag OPTIONAL
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
EFI_REDFISH_MEMORY_V1_7_1 *Memory;
EFI_REDFISH_MEMORY_V1_7_1_CS *MemoryCs;
- EFI_STRING ConfigureLang;
- CHAR8 *Arraykey;
- CHAR8 *EtagInDb;
+ EFI_STRING ConfigureLang;
+

- if (Private == NULL || IS_EMPTY_STRING (MemoryJson)) {
+ if (Private == NULL || IS_EMPTY_STRING (Json)) {
return EFI_INVALID_PARAMETER;
}

- Memory= NULL;
+ Memory = NULL;
MemoryCs = NULL;
ConfigureLang = NULL;
- Arraykey = NULL;
- EtagInDb = NULL;

Status = Private->JsonStructProtocol->ToStructure (
Private->JsonStructProtocol,
NULL,
- MemoryJson,
+ Json,
(EFI_REST_JSON_STRUCTURE_HEADER **)&Memory
);
if (EFI_ERROR (Status)) {
@@ -52,24 +61,13 @@ RedfishConsumeResourceCommon (
//
// Check ETAG to see if we need to consume it
//
- EtagInDb = GetEtagWithUri (Private->Uri);
- if (EtagInDb != NULL && MemoryCs->odata_etag != NULL) {
- if (AsciiStrCmp (EtagInDb, MemoryCs->odata_etag) == 0) {
- //
- // No change
- //
- DEBUG ((DEBUG_INFO, "%a, ETAG: [%a] no change, ignore consume
action\n", __FUNCTION__, EtagInDb));
- goto ON_RELEASE;
- }
- }
-
- //
- // Find array key from URI
- //
- Status = GetArraykeyFromUri (Private->Uri, &Arraykey);
- if (EFI_ERROR (Status)) {
- ASSERT (FALSE);
- return Status;
+ if (CheckEtag (Private->Uri, HeaderEtag, MemoryCs->odata_etag)) {
+ //
+ // No change
+ //
+ DEBUG ((DEBUG_INFO, "%a, ETAG: %s has no change, ignore consume
action\n", __FUNCTION__, Private->Uri));
+ Status = EFI_ALREADY_STARTED;
+ goto ON_RELEASE;
}

//
@@ -77,9 +75,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->AllocationAlignmentMiB != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "AllocationAlignmentMiB", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"AllocationAlignmentMiB");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
AllocationAlignmentMiB);
if (EFI_ERROR (Status)) {
@@ -88,7 +86,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -97,9 +95,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->AllocationIncrementMiB != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "AllocationIncrementMiB", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"AllocationIncrementMiB");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
AllocationIncrementMiB);
if (EFI_ERROR (Status)) {
@@ -108,18 +106,42 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle ALLOWEDSPEEDSMHZ
+ //
+ if (MemoryCs->AllowedSpeedsMHz != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"AllowedSpeedsMHz");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsNumericArrayType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs-
AllowedSpeedsMHz);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

+ //
+ // ASSEMBLY will be handled by feature driver.
+ //
+
//
// Handle BASEMODULETYPE
//
if (MemoryCs->BaseModuleType != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "BaseModuleType", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"BaseModuleType");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs-
BaseModuleType);
if (EFI_ERROR (Status)) {
@@ -128,7 +150,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -137,9 +159,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->BusWidthBits != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "BusWidthBits", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"BusWidthBits");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
BusWidthBits);
if (EFI_ERROR (Status)) {
@@ -148,7 +170,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -157,9 +179,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->CacheSizeMiB != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "CacheSizeMiB", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"CacheSizeMiB");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
CacheSizeMiB);
if (EFI_ERROR (Status)) {
@@ -168,7 +190,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -177,9 +199,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->CapacityMiB != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "CapacityMiB", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"CapacityMiB");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
CapacityMiB);
if (EFI_ERROR (Status)) {
@@ -188,7 +210,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -197,9 +219,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->ConfigurationLocked != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "ConfigurationLocked", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"ConfigurationLocked");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsBooleanType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (BOOLEAN)*MemoryCs-
ConfigurationLocked);
if (EFI_ERROR (Status)) {
@@ -208,7 +230,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -217,9 +239,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->DataWidthBits != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "DataWidthBits", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"DataWidthBits");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
DataWidthBits);
if (EFI_ERROR (Status)) {
@@ -228,7 +250,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -237,9 +259,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->DeviceID != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "DeviceID", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id, "DeviceID");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs->DeviceID);
if (EFI_ERROR (Status)) {
@@ -248,7 +270,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -257,9 +279,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->DeviceLocator != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "DeviceLocator", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"DeviceLocator");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs->DeviceLocator);
if (EFI_ERROR (Status)) {
@@ -268,7 +290,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -277,9 +299,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->ErrorCorrection != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "ErrorCorrection", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"ErrorCorrection");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs->ErrorCorrection);
if (EFI_ERROR (Status)) {
@@ -288,7 +310,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -297,9 +319,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->FirmwareApiVersion != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "FirmwareApiVersion", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"FirmwareApiVersion");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs-
FirmwareApiVersion);
if (EFI_ERROR (Status)) {
@@ -308,7 +330,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -317,9 +339,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->FirmwareRevision != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "FirmwareRevision", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"FirmwareRevision");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs-
FirmwareRevision);
if (EFI_ERROR (Status)) {
@@ -328,7 +350,27 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle FUNCTIONCLASSES
+ //
+ if (MemoryCs->FunctionClasses != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"FunctionClasses");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsStringArrayType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs-
FunctionClasses);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -337,9 +379,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->IsRankSpareEnabled != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "IsRankSpareEnabled", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"IsRankSpareEnabled");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsBooleanType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (BOOLEAN)*MemoryCs-
IsRankSpareEnabled);
if (EFI_ERROR (Status)) {
@@ -348,7 +390,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -357,9 +399,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->IsSpareDeviceEnabled != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "IsSpareDeviceEnabled", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"IsSpareDeviceEnabled");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsBooleanType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (BOOLEAN)*MemoryCs-
IsSpareDeviceEnabled);
if (EFI_ERROR (Status)) {
@@ -368,18 +410,22 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

+ //
+ // LOCATION is not handled. Defined in
https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fredfis
h.dmtf.org%2Fschemas%2Fv1%2FResource.json&amp;data=05%7C01%7Cab
ner.chang%40amd.com%7Cc5c18ad2dddb46daeae308da6f70b35f%7C3dd896
1fe4884e608e11a82d994e183d%7C0%7C0%7C637944827102439368%7CUnkn
own%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik
1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=xlnkJ1Se7yQrRJ
48%2BKqY%2FeKKhwnhyrqiswP9J5GBpuI%3D&amp;reserved=0
+ //
+
//
// Handle LOGICALSIZEMIB
//
if (MemoryCs->LogicalSizeMiB != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "LogicalSizeMiB", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"LogicalSizeMiB");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
LogicalSizeMiB);
if (EFI_ERROR (Status)) {
@@ -388,7 +434,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -397,9 +443,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->Manufacturer != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "Manufacturer", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"Manufacturer");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs->Manufacturer);
if (EFI_ERROR (Status)) {
@@ -408,7 +454,27 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
+ }
+ }
+
+ //
+ // Handle MAXTDPMILLIWATTS
+ //
+ if (MemoryCs->MaxTDPMilliWatts != NULL) {
+ //
+ // Find corresponding configure language for collection resource.
+ //
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"MaxTDPMilliWatts");
+ if (ConfigureLang != NULL) {
+ Status = ApplyFeatureSettingsNumericArrayType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs-
MaxTDPMilliWatts);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply setting for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ FreePool (ConfigureLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -417,9 +483,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->MemoryDeviceType != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "MemoryDeviceType", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"MemoryDeviceType");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs-
MemoryDeviceType);
if (EFI_ERROR (Status)) {
@@ -428,14 +494,14 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

//
// Handle MEMORYLOCATION
//
- if(MemoryCs->MemoryLocation == NULL) {
+ if (MemoryCs->MemoryLocation == NULL) {
MemoryCs->MemoryLocation = AllocateZeroPool (sizeof
(RedfishMemory_V1_7_1_MemoryLocation_CS));
ASSERT (MemoryCs->MemoryLocation != NULL);
}
@@ -445,9 +511,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->MemoryLocation->Channel != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "MemoryLocation/Channel", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"MemoryLocation/Channel");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
MemoryLocation->Channel);
if (EFI_ERROR (Status)) {
@@ -456,7 +522,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -465,9 +531,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->MemoryLocation->MemoryController != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "MemoryLocation/MemoryController",
Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"MemoryLocation/MemoryController");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
MemoryLocation->MemoryController);
if (EFI_ERROR (Status)) {
@@ -476,7 +542,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -485,9 +551,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->MemoryLocation->Slot != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "MemoryLocation/Slot", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"MemoryLocation/Slot");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
MemoryLocation->Slot);
if (EFI_ERROR (Status)) {
@@ -496,7 +562,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -505,9 +571,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->MemoryLocation->Socket != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "MemoryLocation/Socket", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"MemoryLocation/Socket");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
MemoryLocation->Socket);
if (EFI_ERROR (Status)) {
@@ -516,18 +582,26 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

+ //
+ // Handle MEMORYMEDIA
+ //
+//
+// ****** Warning ******
+// Unsupported array type:
+//
+
//
// Handle MEMORYSUBSYSTEMCONTROLLERMANUFACTURERID
//
if (MemoryCs->MemorySubsystemControllerManufacturerID != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
"MemorySubsystemControllerManufacturerID", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"MemorySubsystemControllerManufacturerID");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs-
MemorySubsystemControllerManufacturerID);
if (EFI_ERROR (Status)) {
@@ -536,7 +610,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -545,9 +619,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->MemorySubsystemControllerProductID != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "MemorySubsystemControllerProductID",
Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"MemorySubsystemControllerProductID");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs-
MemorySubsystemControllerProductID);
if (EFI_ERROR (Status)) {
@@ -556,7 +630,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -565,9 +639,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->MemoryType != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "MemoryType", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"MemoryType");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs->MemoryType);
if (EFI_ERROR (Status)) {
@@ -576,18 +650,22 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

+ //
+ // METRICS will be handled by feature driver.
+ //
+
//
// Handle MODULEMANUFACTURERID
//
if (MemoryCs->ModuleManufacturerID != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "ModuleManufacturerID", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"ModuleManufacturerID");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs-
ModuleManufacturerID);
if (EFI_ERROR (Status)) {
@@ -596,7 +674,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -605,9 +683,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->ModuleProductID != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "ModuleProductID", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"ModuleProductID");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs-
ModuleProductID);
if (EFI_ERROR (Status)) {
@@ -616,7 +694,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -625,9 +703,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->NonVolatileSizeMiB != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "NonVolatileSizeMiB", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"NonVolatileSizeMiB");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
NonVolatileSizeMiB);
if (EFI_ERROR (Status)) {
@@ -636,18 +714,26 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

+ //
+ // Handle OPERATINGMEMORYMODES
+ //
+//
+// ****** Warning ******
+// Unsupported array type:
+//
+
//
// Handle OPERATINGSPEEDMHZ
//
if (MemoryCs->OperatingSpeedMhz != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "OperatingSpeedMhz", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"OperatingSpeedMhz");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
OperatingSpeedMhz);
if (EFI_ERROR (Status)) {
@@ -656,7 +742,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -665,9 +751,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->PartNumber != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "PartNumber", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"PartNumber");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs->PartNumber);
if (EFI_ERROR (Status)) {
@@ -676,7 +762,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -685,9 +771,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->PersistentRegionNumberLimit != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "PersistentRegionNumberLimit", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"PersistentRegionNumberLimit");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
PersistentRegionNumberLimit);
if (EFI_ERROR (Status)) {
@@ -696,7 +782,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -705,9 +791,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->PersistentRegionSizeLimitMiB != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "PersistentRegionSizeLimitMiB", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"PersistentRegionSizeLimitMiB");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
PersistentRegionSizeLimitMiB);
if (EFI_ERROR (Status)) {
@@ -716,7 +802,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -725,9 +811,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->PersistentRegionSizeMaxMiB != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "PersistentRegionSizeMaxMiB", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"PersistentRegionSizeMaxMiB");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
PersistentRegionSizeMaxMiB);
if (EFI_ERROR (Status)) {
@@ -736,14 +822,14 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

//
// Handle POWERMANAGEMENTPOLICY
//
- if(MemoryCs->PowerManagementPolicy == NULL) {
+ if (MemoryCs->PowerManagementPolicy == NULL) {
MemoryCs->PowerManagementPolicy = AllocateZeroPool (sizeof
(RedfishMemory_V1_7_1_PowerManagementPolicy_CS));
ASSERT (MemoryCs->PowerManagementPolicy != NULL);
}
@@ -753,9 +839,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->PowerManagementPolicy-
AveragePowerBudgetMilliWatts != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
"PowerManagementPolicy/AveragePowerBudgetMilliWatts", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"PowerManagementPolicy/AveragePowerBudgetMilliWatts");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
PowerManagementPolicy->AveragePowerBudgetMilliWatts);
if (EFI_ERROR (Status)) {
@@ -764,7 +850,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -773,9 +859,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->PowerManagementPolicy->MaxTDPMilliWatts != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
"PowerManagementPolicy/MaxTDPMilliWatts", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"PowerManagementPolicy/MaxTDPMilliWatts");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
PowerManagementPolicy->MaxTDPMilliWatts);
if (EFI_ERROR (Status)) {
@@ -784,7 +870,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -793,9 +879,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->PowerManagementPolicy->PeakPowerBudgetMilliWatts !=
NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
"PowerManagementPolicy/PeakPowerBudgetMilliWatts", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"PowerManagementPolicy/PeakPowerBudgetMilliWatts");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
PowerManagementPolicy->PeakPowerBudgetMilliWatts);
if (EFI_ERROR (Status)) {
@@ -804,7 +890,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -813,9 +899,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->PowerManagementPolicy->PolicyEnabled != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "PowerManagementPolicy/PolicyEnabled",
Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"PowerManagementPolicy/PolicyEnabled");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsBooleanType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (BOOLEAN)*MemoryCs-
PowerManagementPolicy->PolicyEnabled);
if (EFI_ERROR (Status)) {
@@ -824,7 +910,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -833,9 +919,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->RankCount != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "RankCount", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id, "RankCount");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
RankCount);
if (EFI_ERROR (Status)) {
@@ -844,14 +930,22 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

+ //
+ // Handle REGIONS
+ //
+//
+// ****** Warning ******
+// Unsupported array type:
+//
+
//
// Handle SECURITYCAPABILITIES
//
- if(MemoryCs->SecurityCapabilities == NULL) {
+ if (MemoryCs->SecurityCapabilities == NULL) {
MemoryCs->SecurityCapabilities = AllocateZeroPool (sizeof
(RedfishMemory_V1_7_1_SecurityCapabilities_CS));
ASSERT (MemoryCs->SecurityCapabilities != NULL);
}
@@ -861,9 +955,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->SecurityCapabilities->ConfigurationLockCapable != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
"SecurityCapabilities/ConfigurationLockCapable", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"SecurityCapabilities/ConfigurationLockCapable");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsBooleanType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (BOOLEAN)*MemoryCs-
SecurityCapabilities->ConfigurationLockCapable);
if (EFI_ERROR (Status)) {
@@ -872,7 +966,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -881,9 +975,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->SecurityCapabilities->DataLockCapable != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "SecurityCapabilities/DataLockCapable",
Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"SecurityCapabilities/DataLockCapable");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsBooleanType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (BOOLEAN)*MemoryCs-
SecurityCapabilities->DataLockCapable);
if (EFI_ERROR (Status)) {
@@ -892,7 +986,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -901,9 +995,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->SecurityCapabilities->MaxPassphraseCount != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "SecurityCapabilities/MaxPassphraseCount",
Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"SecurityCapabilities/MaxPassphraseCount");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
SecurityCapabilities->MaxPassphraseCount);
if (EFI_ERROR (Status)) {
@@ -912,7 +1006,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -921,9 +1015,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->SecurityCapabilities->PassphraseCapable != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "SecurityCapabilities/PassphraseCapable",
Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"SecurityCapabilities/PassphraseCapable");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsBooleanType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (BOOLEAN)*MemoryCs-
SecurityCapabilities->PassphraseCapable);
if (EFI_ERROR (Status)) {
@@ -932,7 +1026,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -941,9 +1035,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->SecurityCapabilities->PassphraseLockLimit != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "SecurityCapabilities/PassphraseLockLimit",
Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"SecurityCapabilities/PassphraseLockLimit");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
SecurityCapabilities->PassphraseLockLimit);
if (EFI_ERROR (Status)) {
@@ -952,18 +1046,26 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

+ //
+ // Handle SECURITYCAPABILITIES->SECURITYSTATES
+ //
+//
+// ****** Warning ******
+// Unsupported array type:
+//
+
//
// Handle SECURITYSTATE
//
if (MemoryCs->SecurityState != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "SecurityState", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"SecurityState");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs->SecurityState);
if (EFI_ERROR (Status)) {
@@ -972,7 +1074,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -981,9 +1083,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->SerialNumber != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "SerialNumber", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"SerialNumber");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs->SerialNumber);
if (EFI_ERROR (Status)) {
@@ -992,7 +1094,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -1001,9 +1103,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->SpareDeviceCount != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "SpareDeviceCount", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"SpareDeviceCount");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
SpareDeviceCount);
if (EFI_ERROR (Status)) {
@@ -1012,7 +1114,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -1021,9 +1123,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->SubsystemDeviceID != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "SubsystemDeviceID", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"SubsystemDeviceID");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs-
SubsystemDeviceID);
if (EFI_ERROR (Status)) {
@@ -1032,7 +1134,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -1041,9 +1143,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->SubsystemVendorID != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "SubsystemVendorID", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"SubsystemVendorID");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs-
SubsystemVendorID);
if (EFI_ERROR (Status)) {
@@ -1052,7 +1154,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -1061,9 +1163,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->VendorID != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "VendorID", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id, "VendorID");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsStringType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, MemoryCs->VendorID);
if (EFI_ERROR (Status)) {
@@ -1072,7 +1174,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -1081,9 +1183,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->VolatileRegionNumberLimit != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "VolatileRegionNumberLimit", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"VolatileRegionNumberLimit");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
VolatileRegionNumberLimit);
if (EFI_ERROR (Status)) {
@@ -1092,7 +1194,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -1101,9 +1203,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->VolatileRegionSizeLimitMiB != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "VolatileRegionSizeLimitMiB", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"VolatileRegionSizeLimitMiB");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
VolatileRegionSizeLimitMiB);
if (EFI_ERROR (Status)) {
@@ -1112,7 +1214,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -1121,9 +1223,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->VolatileRegionSizeMaxMiB != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "VolatileRegionSizeMaxMiB", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"VolatileRegionSizeMaxMiB");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
VolatileRegionSizeMaxMiB);
if (EFI_ERROR (Status)) {
@@ -1132,7 +1234,7 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}

@@ -1141,9 +1243,9 @@ RedfishConsumeResourceCommon (
//
if (MemoryCs->VolatileSizeMiB != NULL) {
//
- // Find corresponding redpath for collection resource.
+ // Find corresponding configure language for collection resource.
//
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, "VolatileSizeMiB", Arraykey);
+ ConfigureLang = GetConfigureLang (MemoryCs->odata_id,
"VolatileSizeMiB");
if (ConfigureLang != NULL) {
Status = ApplyFeatureSettingsNumericType (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, ConfigureLang, (UINTN)*MemoryCs-
VolatileSizeMiB);
if (EFI_ERROR (Status)) {
@@ -1152,26 +1254,16 @@ RedfishConsumeResourceCommon (

FreePool (ConfigureLang);
} else {
- DEBUG ((DEBUG_ERROR, "%a, can not get configure language for key:
%a\n", __FUNCTION__, Arraykey));
+ DEBUG ((DEBUG_ERROR, "%a, can not get configure language for URI:
%s\n", __FUNCTION__, Private->Uri));
}
}


-
- //
ON_RELEASE:

//
// Release resource.
//
- if (EtagInDb != NULL) {
- FreePool (EtagInDb);
- }
-
- if (Arraykey != NULL) {
- FreePool (Arraykey);
- }
-
Private->JsonStructProtocol->DestoryStructure (
Private->JsonStructProtocol,
(EFI_REST_JSON_STRUCTURE_HEADER *)Memory
@@ -1183,7 +1275,7 @@ ON_RELEASE:
EFI_STATUS
ProvisioningMemoryProperties (
IN EFI_REST_JSON_STRUCTURE_PROTOCOL *JsonStructProtocol,
- IN CHAR8 *IputJson,
+ IN CHAR8 *InputJson,
IN CHAR8 *ResourceId, OPTIONAL
IN EFI_STRING ConfigureLang,
IN BOOLEAN ProvisionMode,
@@ -1193,28 +1285,31 @@ ProvisioningMemoryProperties (
EFI_REDFISH_MEMORY_V1_7_1 *Memory;
EFI_REDFISH_MEMORY_V1_7_1_CS *MemoryCs;
EFI_STATUS Status;
+ BOOLEAN PropertyChanged;
INT64 *NumericValue;
- INT32 *IntegerValue;
- BOOLEAN *BooleanValue;
+ INT64 *NumericArrayValue;
+ UINTN ArraySize;
CHAR8 *AsciiStringValue;
- BOOLEAN PropertyChanged;
- BOOLEAN UnusedProperty;
+ BOOLEAN *BooleanValue;
+ INT32 *IntegerValue;
+ CHAR8 **AsciiStringArrayValue;
+

- if (JsonStructProtocol == NULL || ResultJson == NULL || IS_EMPTY_STRING
(IputJson) || IS_EMPTY_STRING (ConfigureLang)) {
+
+ if (JsonStructProtocol == NULL || ResultJson == NULL ||
IS_EMPTY_STRING (InputJson) || IS_EMPTY_STRING (ConfigureLang)) {
return EFI_INVALID_PARAMETER;
}

- DEBUG ((REDFISH_DEBUG_TRACE, "%a provision for %s with: %s\n",
__FUNCTION__, ConfigureLang, (ProvisionMode ? L"Provision all resource" :
L"Provision existing resource")));
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a provision for %s with: %s\n",
__FUNCTION__, ConfigureLang, (ProvisionMode ? L"Provision resource" :
L"Update resource")));

*ResultJson = NULL;
PropertyChanged = FALSE;
- UnusedProperty = TRUE;

Memory = NULL;
Status = JsonStructProtocol->ToStructure (
JsonStructProtocol,
NULL,
- IputJson,
+ InputJson,
(EFI_REST_JSON_STRUCTURE_HEADER **)&Memory
);
if (EFI_ERROR (Status)) {
@@ -1243,7 +1338,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle ALLOCATIONINCREMENTMIB
//
@@ -1256,7 +1350,18 @@ ProvisioningMemoryProperties (
}
}
}
-
+ //
+ // Handle ALLOWEDSPEEDSMHZ
+ //
+ if (PropertyChecker (MemoryCs->AllowedSpeedsMHz, ProvisionMode)) {
+ NumericArrayValue = GetPropertyNumericArrayValue
(RESOURCE_SCHEMA, RESOURCE_SCHEMA_VERSION,
L"AllowedSpeedsMHz", ConfigureLang, &ArraySize);
+ if (NumericArrayValue != NULL) {
+ if (ProvisionMode || !CompareRedfishNumericArrayValues (MemoryCs-
AllowedSpeedsMHz, NumericArrayValue, ArraySize)) {
+ AddRedfishNumericArray (&MemoryCs->AllowedSpeedsMHz,
NumericArrayValue, ArraySize);
+ PropertyChanged = TRUE;
+ }
+ }
+ }
//
// Handle BASEMODULETYPE
//
@@ -1269,7 +1374,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle BUSWIDTHBITS
//
@@ -1282,7 +1386,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle CACHESIZEMIB
//
@@ -1295,7 +1398,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle CAPACITYMIB
//
@@ -1308,7 +1410,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle CONFIGURATIONLOCKED
//
@@ -1320,11 +1421,11 @@ ProvisioningMemoryProperties (
if (IntegerValue != NULL) {
*IntegerValue = (BooleanValue ? 0x01 : 0x00);
MemoryCs->ConfigurationLocked = IntegerValue;
+ PropertyChanged = TRUE;
}
}
}
}
-
//
// Handle DATAWIDTHBITS
//
@@ -1337,7 +1438,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle DEVICEID
//
@@ -1350,7 +1450,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle DEVICELOCATOR
//
@@ -1363,7 +1462,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle ERRORCORRECTION
//
@@ -1376,7 +1474,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle FIRMWAREAPIVERSION
//
@@ -1389,7 +1486,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle FIRMWAREREVISION
//
@@ -1402,7 +1498,18 @@ ProvisioningMemoryProperties (
}
}
}
-
+ //
+ // Handle FUNCTIONCLASSES
+ //
+ if (PropertyChecker (MemoryCs->FunctionClasses, ProvisionMode)) {
+ AsciiStringArrayValue = GetPropertyStringArrayValue
(RESOURCE_SCHEMA, RESOURCE_SCHEMA_VERSION, L"FunctionClasses",
ConfigureLang, &ArraySize);
+ if (AsciiStringArrayValue != NULL) {
+ if (ProvisionMode || !CompareRedfishStringArrayValues (MemoryCs-
FunctionClasses, AsciiStringArrayValue, ArraySize)) {
+ AddRedfishCharArray (&MemoryCs->FunctionClasses,
AsciiStringArrayValue, ArraySize);
+ PropertyChanged = TRUE;
+ }
+ }
+ }
//
// Handle ISRANKSPAREENABLED
//
@@ -1414,11 +1521,11 @@ ProvisioningMemoryProperties (
if (IntegerValue != NULL) {
*IntegerValue = (BooleanValue ? 0x01 : 0x00);
MemoryCs->IsRankSpareEnabled = IntegerValue;
+ PropertyChanged = TRUE;
}
}
}
}
-
//
// Handle ISSPAREDEVICEENABLED
//
@@ -1430,11 +1537,11 @@ ProvisioningMemoryProperties (
if (IntegerValue != NULL) {
*IntegerValue = (BooleanValue ? 0x01 : 0x00);
MemoryCs->IsSpareDeviceEnabled = IntegerValue;
+ PropertyChanged = TRUE;
}
}
}
}
-
//
// Handle LOGICALSIZEMIB
//
@@ -1447,7 +1554,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle MANUFACTURER
//
@@ -1460,7 +1566,18 @@ ProvisioningMemoryProperties (
}
}
}
-
+ //
+ // Handle MAXTDPMILLIWATTS
+ //
+ if (PropertyChecker (MemoryCs->MaxTDPMilliWatts, ProvisionMode)) {
+ NumericArrayValue = GetPropertyNumericArrayValue
(RESOURCE_SCHEMA, RESOURCE_SCHEMA_VERSION, L"MaxTDPMilliWatts",
ConfigureLang, &ArraySize);
+ if (NumericArrayValue != NULL) {
+ if (ProvisionMode || !CompareRedfishNumericArrayValues (MemoryCs-
MaxTDPMilliWatts, NumericArrayValue, ArraySize)) {
+ AddRedfishNumericArray (&MemoryCs->MaxTDPMilliWatts,
NumericArrayValue, ArraySize);
+ PropertyChanged = TRUE;
+ }
+ }
+ }
//
// Handle MEMORYDEVICETYPE
//
@@ -1473,78 +1590,66 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle MEMORYLOCATION
//
- if(MemoryCs->MemoryLocation == NULL) {
- MemoryCs->MemoryLocation = AllocateZeroPool (sizeof
(RedfishMemory_V1_7_1_MemoryLocation_CS));
- ASSERT (MemoryCs->MemoryLocation != NULL);
- UnusedProperty = TRUE;
- } else {
- UnusedProperty = FALSE;
- }
-
- //
- // Handle MEMORYLOCATION->CHANNEL
- //
- if (PropertyChecker (MemoryCs->MemoryLocation->Channel,
ProvisionMode)) {
- NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"MemoryLocation/Channel",
ConfigureLang);
- if (NumericValue != NULL) {
- if (ProvisionMode || *MemoryCs->MemoryLocation->Channel !=
*NumericValue) {
- MemoryCs->MemoryLocation->Channel = NumericValue;
- PropertyChanged = TRUE;
- UnusedProperty = FALSE;
+ if (MemoryCs->MemoryLocation != NULL) {
+ //
+ // Handle MEMORYLOCATION->CHANNEL
+ //
+ if (PropertyChecker (MemoryCs->MemoryLocation->Channel,
ProvisionMode)) {
+ NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"MemoryLocation/Channel",
ConfigureLang);
+ if (NumericValue != NULL) {
+ if (ProvisionMode || *MemoryCs->MemoryLocation->Channel !=
*NumericValue) {
+ MemoryCs->MemoryLocation->Channel = NumericValue;
+ PropertyChanged = TRUE;
+ }
}
}
- }
-
- //
- // Handle MEMORYLOCATION->MEMORYCONTROLLER
- //
- if (PropertyChecker (MemoryCs->MemoryLocation->MemoryController,
ProvisionMode)) {
- NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"MemoryLocation/MemoryController",
ConfigureLang);
- if (NumericValue != NULL) {
- if (ProvisionMode || *MemoryCs->MemoryLocation-
MemoryController != *NumericValue) {
- MemoryCs->MemoryLocation->MemoryController = NumericValue;
- PropertyChanged = TRUE;
- UnusedProperty = FALSE;
+ //
+ // Handle MEMORYLOCATION->MEMORYCONTROLLER
+ //
+ if (PropertyChecker (MemoryCs->MemoryLocation->MemoryController,
ProvisionMode)) {
+ NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"MemoryLocation/MemoryController",
ConfigureLang);
+ if (NumericValue != NULL) {
+ if (ProvisionMode || *MemoryCs->MemoryLocation-
MemoryController != *NumericValue) {
+ MemoryCs->MemoryLocation->MemoryController = NumericValue;
+ PropertyChanged = TRUE;
+ }
}
}
- }
-
- //
- // Handle MEMORYLOCATION->SLOT
- //
- if (PropertyChecker (MemoryCs->MemoryLocation->Slot, ProvisionMode))
{
- NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"MemoryLocation/Slot", ConfigureLang);
- if (NumericValue != NULL) {
- if (ProvisionMode || *MemoryCs->MemoryLocation->Slot !=
*NumericValue) {
- MemoryCs->MemoryLocation->Slot = NumericValue;
- PropertyChanged = TRUE;
- UnusedProperty = FALSE;
+ //
+ // Handle MEMORYLOCATION->SLOT
+ //
+ if (PropertyChecker (MemoryCs->MemoryLocation->Slot,
ProvisionMode)) {
+ NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"MemoryLocation/Slot", ConfigureLang);
+ if (NumericValue != NULL) {
+ if (ProvisionMode || *MemoryCs->MemoryLocation->Slot !=
*NumericValue) {
+ MemoryCs->MemoryLocation->Slot = NumericValue;
+ PropertyChanged = TRUE;
+ }
}
}
- }
-
- //
- // Handle MEMORYLOCATION->SOCKET
- //
- if (PropertyChecker (MemoryCs->MemoryLocation->Socket,
ProvisionMode)) {
- NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"MemoryLocation/Socket", ConfigureLang);
- if (NumericValue != NULL) {
- if (ProvisionMode || *MemoryCs->MemoryLocation->Socket !=
*NumericValue) {
- MemoryCs->MemoryLocation->Socket = NumericValue;
- PropertyChanged = TRUE;
- UnusedProperty = FALSE;
+ //
+ // Handle MEMORYLOCATION->SOCKET
+ //
+ if (PropertyChecker (MemoryCs->MemoryLocation->Socket,
ProvisionMode)) {
+ NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"MemoryLocation/Socket", ConfigureLang);
+ if (NumericValue != NULL) {
+ if (ProvisionMode || *MemoryCs->MemoryLocation->Socket !=
*NumericValue) {
+ MemoryCs->MemoryLocation->Socket = NumericValue;
+ PropertyChanged = TRUE;
+ }
}
}
}

- if (UnusedProperty) {
- FreePool (MemoryCs->MemoryLocation);
- MemoryCs->MemoryLocation = NULL;
- }
+ //
+ // Handle MEMORYMEDIA
+ //
+//// ****** Warning ******
+// Unsupported array type:
+//

//
// Handle MEMORYSUBSYSTEMCONTROLLERMANUFACTURERID
@@ -1558,7 +1663,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle MEMORYSUBSYSTEMCONTROLLERPRODUCTID
//
@@ -1571,7 +1675,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle MEMORYTYPE
//
@@ -1584,7 +1687,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle MODULEMANUFACTURERID
//
@@ -1597,7 +1699,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle MODULEPRODUCTID
//
@@ -1610,7 +1711,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle NONVOLATILESIZEMIB
//
@@ -1623,6 +1723,12 @@ ProvisioningMemoryProperties (
}
}
}
+ //
+ // Handle OPERATINGMEMORYMODES
+ //
+//// ****** Warning ******
+// Unsupported array type:
+//

//
// Handle OPERATINGSPEEDMHZ
@@ -1636,7 +1742,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle PARTNUMBER
//
@@ -1649,7 +1754,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle PERSISTENTREGIONNUMBERLIMIT
//
@@ -1662,7 +1766,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle PERSISTENTREGIONSIZELIMITMIB
//
@@ -1675,7 +1778,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle PERSISTENTREGIONSIZEMAXMIB
//
@@ -1688,83 +1790,64 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle POWERMANAGEMENTPOLICY
//
- if(MemoryCs->PowerManagementPolicy == NULL) {
- MemoryCs->PowerManagementPolicy = AllocateZeroPool (sizeof
(RedfishMemory_V1_7_1_PowerManagementPolicy_CS));
- ASSERT (MemoryCs->PowerManagementPolicy != NULL);
- UnusedProperty = TRUE;
- } else {
- UnusedProperty = FALSE;
- }
-
- //
- // Handle POWERMANAGEMENTPOLICY-
AVERAGEPOWERBUDGETMILLIWATTS
- //
- if (PropertyChecker (MemoryCs->PowerManagementPolicy-
AveragePowerBudgetMilliWatts, ProvisionMode)) {
- NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
L"PowerManagementPolicy/AveragePowerBudgetMilliWatts",
ConfigureLang);
- if (NumericValue != NULL) {
- if (ProvisionMode || *MemoryCs->PowerManagementPolicy-
AveragePowerBudgetMilliWatts != *NumericValue) {
- MemoryCs->PowerManagementPolicy-
AveragePowerBudgetMilliWatts = NumericValue;
- PropertyChanged = TRUE;
- UnusedProperty = FALSE;
+ if (MemoryCs->PowerManagementPolicy != NULL) {
+ //
+ // Handle POWERMANAGEMENTPOLICY-
AVERAGEPOWERBUDGETMILLIWATTS
+ //
+ if (PropertyChecker (MemoryCs->PowerManagementPolicy-
AveragePowerBudgetMilliWatts, ProvisionMode)) {
+ NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
L"PowerManagementPolicy/AveragePowerBudgetMilliWatts",
ConfigureLang);
+ if (NumericValue != NULL) {
+ if (ProvisionMode || *MemoryCs->PowerManagementPolicy-
AveragePowerBudgetMilliWatts != *NumericValue) {
+ MemoryCs->PowerManagementPolicy-
AveragePowerBudgetMilliWatts = NumericValue;
+ PropertyChanged = TRUE;
+ }
}
}
- }
-
- //
- // Handle POWERMANAGEMENTPOLICY->MAXTDPMILLIWATTS
- //
- if (PropertyChecker (MemoryCs->PowerManagementPolicy-
MaxTDPMilliWatts, ProvisionMode)) {
- NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
L"PowerManagementPolicy/MaxTDPMilliWatts", ConfigureLang);
- if (NumericValue != NULL) {
- if (ProvisionMode || *MemoryCs->PowerManagementPolicy-
MaxTDPMilliWatts != *NumericValue) {
- MemoryCs->PowerManagementPolicy->MaxTDPMilliWatts =
NumericValue;
- PropertyChanged = TRUE;
- UnusedProperty = FALSE;
+ //
+ // Handle POWERMANAGEMENTPOLICY->MAXTDPMILLIWATTS
+ //
+ if (PropertyChecker (MemoryCs->PowerManagementPolicy-
MaxTDPMilliWatts, ProvisionMode)) {
+ NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
L"PowerManagementPolicy/MaxTDPMilliWatts", ConfigureLang);
+ if (NumericValue != NULL) {
+ if (ProvisionMode || *MemoryCs->PowerManagementPolicy-
MaxTDPMilliWatts != *NumericValue) {
+ MemoryCs->PowerManagementPolicy->MaxTDPMilliWatts =
NumericValue;
+ PropertyChanged = TRUE;
+ }
}
}
- }
-
- //
- // Handle POWERMANAGEMENTPOLICY-
PEAKPOWERBUDGETMILLIWATTS
- //
- if (PropertyChecker (MemoryCs->PowerManagementPolicy-
PeakPowerBudgetMilliWatts, ProvisionMode)) {
- NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
L"PowerManagementPolicy/PeakPowerBudgetMilliWatts", ConfigureLang);
- if (NumericValue != NULL) {
- if (ProvisionMode || *MemoryCs->PowerManagementPolicy-
PeakPowerBudgetMilliWatts != *NumericValue) {
- MemoryCs->PowerManagementPolicy->PeakPowerBudgetMilliWatts =
NumericValue;
- PropertyChanged = TRUE;
- UnusedProperty = FALSE;
+ //
+ // Handle POWERMANAGEMENTPOLICY-
PEAKPOWERBUDGETMILLIWATTS
+ //
+ if (PropertyChecker (MemoryCs->PowerManagementPolicy-
PeakPowerBudgetMilliWatts, ProvisionMode)) {
+ NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
L"PowerManagementPolicy/PeakPowerBudgetMilliWatts", ConfigureLang);
+ if (NumericValue != NULL) {
+ if (ProvisionMode || *MemoryCs->PowerManagementPolicy-
PeakPowerBudgetMilliWatts != *NumericValue) {
+ MemoryCs->PowerManagementPolicy->PeakPowerBudgetMilliWatts
= NumericValue;
+ PropertyChanged = TRUE;
+ }
}
}
- }
-
- //
- // Handle POWERMANAGEMENTPOLICY->POLICYENABLED
- //
- if (PropertyChecker (MemoryCs->PowerManagementPolicy-
PolicyEnabled, ProvisionMode)) {
- BooleanValue = GetPropertyBooleanValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"PowerManagementPolicy/PolicyEnabled",
ConfigureLang);
- if (BooleanValue != NULL) {
- if (ProvisionMode || *MemoryCs->PowerManagementPolicy-
PolicyEnabled != *BooleanValue) {
- IntegerValue = AllocatePool (sizeof (*IntegerValue));
- if (IntegerValue != NULL) {
- *IntegerValue = (BooleanValue ? 0x01 : 0x00);
- MemoryCs->PowerManagementPolicy->PolicyEnabled = IntegerValue;
- PropertyChanged = TRUE;
- UnusedProperty = FALSE;
+ //
+ // Handle POWERMANAGEMENTPOLICY->POLICYENABLED
+ //
+ if (PropertyChecker (MemoryCs->PowerManagementPolicy-
PolicyEnabled, ProvisionMode)) {
+ BooleanValue = GetPropertyBooleanValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"PowerManagementPolicy/PolicyEnabled",
ConfigureLang);
+ if (BooleanValue != NULL) {
+ if (ProvisionMode || *MemoryCs->PowerManagementPolicy-
PolicyEnabled != *BooleanValue) {
+ IntegerValue = AllocatePool (sizeof (*IntegerValue));
+ if (IntegerValue != NULL) {
+ *IntegerValue = (BooleanValue ? 0x01 : 0x00);
+ MemoryCs->PowerManagementPolicy->PolicyEnabled =
IntegerValue;
+ PropertyChanged = TRUE;
+ }
}
}
}
}

- if (UnusedProperty) {
- FreePool (MemoryCs->PowerManagementPolicy);
- MemoryCs->PowerManagementPolicy = NULL;
- }
-
//
// Handle RANKCOUNT
//
@@ -1777,103 +1860,96 @@ ProvisioningMemoryProperties (
}
}
}
-
//
- // Handle SECURITYCAPABILITIES
+ // Handle REGIONS
//
- if(MemoryCs->SecurityCapabilities == NULL) {
- MemoryCs->SecurityCapabilities = AllocateZeroPool (sizeof
(RedfishMemory_V1_7_1_SecurityCapabilities_CS));
- ASSERT (MemoryCs->SecurityCapabilities != NULL);
- UnusedProperty = TRUE;
- } else {
- UnusedProperty = FALSE;
- }
+//// ****** Warning ******
+// Unsupported array type:
+//

//
- // Handle SECURITYCAPABILITIES->CONFIGURATIONLOCKCAPABLE
+ // Handle SECURITYCAPABILITIES
//
- if (PropertyChecker (MemoryCs->SecurityCapabilities-
ConfigurationLockCapable, ProvisionMode)) {
- BooleanValue = GetPropertyBooleanValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
L"SecurityCapabilities/ConfigurationLockCapable", ConfigureLang);
- if (BooleanValue != NULL) {
- if (ProvisionMode || *MemoryCs->SecurityCapabilities-
ConfigurationLockCapable != *BooleanValue) {
- IntegerValue = AllocatePool (sizeof (*IntegerValue));
- if (IntegerValue != NULL) {
- *IntegerValue = (BooleanValue ? 0x01 : 0x00);
- MemoryCs->SecurityCapabilities->ConfigurationLockCapable =
IntegerValue;
- PropertyChanged = TRUE;
- UnusedProperty = FALSE;
+ if (MemoryCs->SecurityCapabilities != NULL) {
+ //
+ // Handle SECURITYCAPABILITIES->CONFIGURATIONLOCKCAPABLE
+ //
+ if (PropertyChecker (MemoryCs->SecurityCapabilities-
ConfigurationLockCapable, ProvisionMode)) {
+ BooleanValue = GetPropertyBooleanValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
L"SecurityCapabilities/ConfigurationLockCapable", ConfigureLang);
+ if (BooleanValue != NULL) {
+ if (ProvisionMode || *MemoryCs->SecurityCapabilities-
ConfigurationLockCapable != *BooleanValue) {
+ IntegerValue = AllocatePool (sizeof (*IntegerValue));
+ if (IntegerValue != NULL) {
+ *IntegerValue = (BooleanValue ? 0x01 : 0x00);
+ MemoryCs->SecurityCapabilities->ConfigurationLockCapable =
IntegerValue;
+ PropertyChanged = TRUE;
+ }
}
}
}
- }
-
- //
- // Handle SECURITYCAPABILITIES->DATALOCKCAPABLE
- //
- if (PropertyChecker (MemoryCs->SecurityCapabilities->DataLockCapable,
ProvisionMode)) {
- BooleanValue = GetPropertyBooleanValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"SecurityCapabilities/DataLockCapable",
ConfigureLang);
- if (BooleanValue != NULL) {
- if (ProvisionMode || *MemoryCs->SecurityCapabilities-
DataLockCapable != *BooleanValue) {
- IntegerValue = AllocatePool (sizeof (*IntegerValue));
- if (IntegerValue != NULL) {
- *IntegerValue = (BooleanValue ? 0x01 : 0x00);
- MemoryCs->SecurityCapabilities->DataLockCapable = IntegerValue;
+ //
+ // Handle SECURITYCAPABILITIES->DATALOCKCAPABLE
+ //
+ if (PropertyChecker (MemoryCs->SecurityCapabilities->DataLockCapable,
ProvisionMode)) {
+ BooleanValue = GetPropertyBooleanValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"SecurityCapabilities/DataLockCapable",
ConfigureLang);
+ if (BooleanValue != NULL) {
+ if (ProvisionMode || *MemoryCs->SecurityCapabilities-
DataLockCapable != *BooleanValue) {
+ IntegerValue = AllocatePool (sizeof (*IntegerValue));
+ if (IntegerValue != NULL) {
+ *IntegerValue = (BooleanValue ? 0x01 : 0x00);
+ MemoryCs->SecurityCapabilities->DataLockCapable = IntegerValue;
+ PropertyChanged = TRUE;
+ }
+ }
+ }
+ }
+ //
+ // Handle SECURITYCAPABILITIES->MAXPASSPHRASECOUNT
+ //
+ if (PropertyChecker (MemoryCs->SecurityCapabilities-
MaxPassphraseCount, ProvisionMode)) {
+ NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
L"SecurityCapabilities/MaxPassphraseCount", ConfigureLang);
+ if (NumericValue != NULL) {
+ if (ProvisionMode || *MemoryCs->SecurityCapabilities-
MaxPassphraseCount != *NumericValue) {
+ MemoryCs->SecurityCapabilities->MaxPassphraseCount =
NumericValue;
PropertyChanged = TRUE;
- UnusedProperty = FALSE;
}
}
}
- }
-
- //
- // Handle SECURITYCAPABILITIES->MAXPASSPHRASECOUNT
- //
- if (PropertyChecker (MemoryCs->SecurityCapabilities-
MaxPassphraseCount, ProvisionMode)) {
- NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION,
L"SecurityCapabilities/MaxPassphraseCount", ConfigureLang);
- if (NumericValue != NULL) {
- if (ProvisionMode || *MemoryCs->SecurityCapabilities-
MaxPassphraseCount != *NumericValue) {
- MemoryCs->SecurityCapabilities->MaxPassphraseCount =
NumericValue;
- PropertyChanged = TRUE;
- UnusedProperty = FALSE;
+ //
+ // Handle SECURITYCAPABILITIES->PASSPHRASECAPABLE
+ //
+ if (PropertyChecker (MemoryCs->SecurityCapabilities-
PassphraseCapable, ProvisionMode)) {
+ BooleanValue = GetPropertyBooleanValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"SecurityCapabilities/PassphraseCapable",
ConfigureLang);
+ if (BooleanValue != NULL) {
+ if (ProvisionMode || *MemoryCs->SecurityCapabilities-
PassphraseCapable != *BooleanValue) {
+ IntegerValue = AllocatePool (sizeof (*IntegerValue));
+ if (IntegerValue != NULL) {
+ *IntegerValue = (BooleanValue ? 0x01 : 0x00);
+ MemoryCs->SecurityCapabilities->PassphraseCapable = IntegerValue;
+ PropertyChanged = TRUE;
+ }
+ }
}
}
- }
-
- //
- // Handle SECURITYCAPABILITIES->PASSPHRASECAPABLE
- //
- if (PropertyChecker (MemoryCs->SecurityCapabilities->PassphraseCapable,
ProvisionMode)) {
- BooleanValue = GetPropertyBooleanValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"SecurityCapabilities/PassphraseCapable",
ConfigureLang);
- if (BooleanValue != NULL) {
- if (ProvisionMode || *MemoryCs->SecurityCapabilities-
PassphraseCapable != *BooleanValue) {
- IntegerValue = AllocatePool (sizeof (*IntegerValue));
- if (IntegerValue != NULL) {
- *IntegerValue = (BooleanValue ? 0x01 : 0x00);
- MemoryCs->SecurityCapabilities->PassphraseCapable = IntegerValue;
+ //
+ // Handle SECURITYCAPABILITIES->PASSPHRASELOCKLIMIT
+ //
+ if (PropertyChecker (MemoryCs->SecurityCapabilities-
PassphraseLockLimit, ProvisionMode)) {
+ NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"SecurityCapabilities/PassphraseLockLimit",
ConfigureLang);
+ if (NumericValue != NULL) {
+ if (ProvisionMode || *MemoryCs->SecurityCapabilities-
PassphraseLockLimit != *NumericValue) {
+ MemoryCs->SecurityCapabilities->PassphraseLockLimit =
NumericValue;
PropertyChanged = TRUE;
- UnusedProperty = FALSE;
}
}
}
- }
-
- //
- // Handle SECURITYCAPABILITIES->PASSPHRASELOCKLIMIT
+ //
+ // Handle SECURITYCAPABILITIES->SECURITYSTATES
+ //
+ //// ****** Warning ******
+ // Unsupported array type:
//
- if (PropertyChecker (MemoryCs->SecurityCapabilities-
PassphraseLockLimit, ProvisionMode)) {
- NumericValue = GetPropertyNumericValue (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, L"SecurityCapabilities/PassphraseLockLimit",
ConfigureLang);
- if (NumericValue != NULL) {
- if (ProvisionMode || *MemoryCs->SecurityCapabilities-
PassphraseLockLimit != *NumericValue) {
- MemoryCs->SecurityCapabilities->PassphraseLockLimit = NumericValue;
- PropertyChanged = TRUE;
- UnusedProperty = FALSE;
- }
- }
- }

- if (UnusedProperty) {
- FreePool (MemoryCs->SecurityCapabilities);
- MemoryCs->SecurityCapabilities = NULL;
}

//
@@ -1888,7 +1964,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle SERIALNUMBER
//
@@ -1901,7 +1976,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle SPAREDEVICECOUNT
//
@@ -1914,7 +1988,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle SUBSYSTEMDEVICEID
//
@@ -1927,7 +2000,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle SUBSYSTEMVENDORID
//
@@ -1940,7 +2012,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle VENDORID
//
@@ -1953,7 +2024,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle VOLATILEREGIONNUMBERLIMIT
//
@@ -1966,7 +2036,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle VOLATILEREGIONSIZELIMITMIB
//
@@ -1979,7 +2048,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle VOLATILEREGIONSIZEMAXMIB
//
@@ -1992,7 +2060,6 @@ ProvisioningMemoryProperties (
}
}
}
-
//
// Handle VOLATILESIZEMIB
//
@@ -2006,8 +2073,6 @@ ProvisioningMemoryProperties (
}
}

-
-
//
// Convert C structure back to JSON text.
//
@@ -2039,18 +2104,17 @@ ProvisioningMemoryResource (
IN EFI_STRING ConfigureLang
)
{
- CHAR8 *MemoryJson;
+ CHAR8 *Json;
EFI_STATUS Status;
- CHAR8 *NewResourceLocation;
- CHAR8 *NewKey;
+ EFI_STRING NewResourceLocation;
CHAR8 *EtagStr;
CHAR8 ResourceId[16];
- CHAR8 NewUri[255];

if (IS_EMPTY_STRING (ConfigureLang) || Private == NULL) {
return EFI_INVALID_PARAMETER;
}

+ EtagStr = NULL;
AsciiSPrint (ResourceId, sizeof (ResourceId), "%d", Index);

Status = ProvisioningMemoryProperties (
@@ -2059,54 +2123,45 @@ ProvisioningMemoryResource (
ResourceId,
ConfigureLang,
TRUE,
- &MemoryJson
+ &Json
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a, provisioning resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
return Status;
}

- Status = CreatePayloadToPostResource (Private->RedfishService, Private-
Payload, MemoryJson, &NewResourceLocation, &EtagStr);
+ Status = CreatePayloadToPostResource (Private->RedfishService, Private-
Payload, Json, &NewResourceLocation, &EtagStr);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, post memory resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ DEBUG ((DEBUG_ERROR, "%a, post Memory resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
goto RELEASE_RESOURCE;
}

- NewUri[0] = '\0';
+ ASSERT (NewResourceLocation != NULL);

//
// Keep location of new resource.
//
if (NewResourceLocation != NULL) {
- //
- // Find key
- //
- NewKey = AsciiStrStr (NewResourceLocation, RESOURCE_SCHEMA);
- if (NewKey != NULL) {
- NewKey += 6;
- //
- // skip '/'
- //
- if (NewKey[0] == '/') {
- NewKey++;
- }
- SetConfigureLangWithkey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, NewKey, Index);
- AsciiSPrint (NewUri, sizeof (NewUri), "%a[%a]", Private->Uri, NewKey);
- FreePool (NewResourceLocation);
- }
+ RedfisSetRedfishUri (ConfigureLang, NewResourceLocation);
}

//
// Handle Etag
//
if (EtagStr != NULL) {
- SetEtagWithUri (EtagStr, NewUri);
+ SetEtagWithUri (EtagStr, NewResourceLocation);
FreePool (EtagStr);
}

RELEASE_RESOURCE:

- FreePool (MemoryJson);
+ if (NewResourceLocation != NULL) {
+ FreePool (NewResourceLocation);
+ }
+
+ if (Json != NULL) {
+ FreePool (Json);
+ }

return Status;
}
@@ -2126,12 +2181,17 @@ ProvisioningMemoryResources (

Status = RedfishFeatureGetUnifiedArrayTypeConfigureLang
(RESOURCE_SCHEMA, RESOURCE_SCHEMA_VERSION,
REDPATH_ARRAY_PATTERN, &UnifiedConfigureLangList);
if (EFI_ERROR (Status) || UnifiedConfigureLangList.Count == 0) {
- DEBUG ((DEBUG_ERROR, "%a, No HII question found with redpath: %s:
%r\n", __FUNCTION__, REDPATH_ARRAY_PATTERN, Status));
+ DEBUG ((DEBUG_ERROR, "%a, No HII question found with configure
language: %s: %r\n", __FUNCTION__, REDPATH_ARRAY_PATTERN, Status));
return EFI_NOT_FOUND;
}
+ //
+ // Set the configuration language in the
RESOURCE_INFORMATION_EXCHANGE.
+ // This information is sent back to the parent resource (e.g. the collection
driver).
+ //
+ EdkIIRedfishResourceSetConfigureLang (&UnifiedConfigureLangList);

for (Index = 0; Index < UnifiedConfigureLangList.Count; Index++) {
- DEBUG ((DEBUG_INFO, "[%d] create memory resource from: %s\n",
UnifiedConfigureLangList.List[Index].Index,
UnifiedConfigureLangList.List[Index].ConfigureLang));
+ DEBUG ((DEBUG_INFO, "[%d] create Memory resource from: %s\n",
UnifiedConfigureLangList.List[Index].Index,
UnifiedConfigureLangList.List[Index].ConfigureLang));
ProvisioningMemoryResource (Private,
UnifiedConfigureLangList.List[Index].Index,
UnifiedConfigureLangList.List[Index].ConfigureLang);
FreePool (UnifiedConfigureLangList.List[Index].ConfigureLang);
}
@@ -2145,14 +2205,69 @@ ProvisioningMemoryExistResource (
IN REDFISH_RESOURCE_COMMON_PRIVATE *Private
)
{
+ EFI_STATUS Status;
+ EFI_STRING ConfigureLang;
+ CHAR8 *EtagStr;
+ CHAR8 *Json;
+
if (Private == NULL) {
return EFI_INVALID_PARAMETER;
}

- Private->Json = JsonDumpString (RedfishJsonInPayload (Private->Payload),
EDKII_JSON_COMPACT);
- ASSERT (Private->Json != NULL);
+ EtagStr = NULL;
+ Json = NULL;
+ ConfigureLang = NULL;
+
+ ConfigureLang = RedfishGetConfigLanguage (Private->Uri);
+ if (ConfigureLang == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = ProvisioningMemoryProperties (
+ Private->JsonStructProtocol,
+ MemoryEmptyJson,
+ NULL,
+ ConfigureLang,
+ TRUE,
+ &Json
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, provisioning existing resource
for %s ignored. Nothing changed\n", __FUNCTION__, ConfigureLang));
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, provisioning existing resource for %s
failed: %r\n", __FUNCTION__, ConfigureLang, Status));
+ }
+ goto ON_RELEASE;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, provisioning existing resource for
%s\n", __FUNCTION__, ConfigureLang));
+ //
+ // PUT back to instance
+ //
+ Status = CreatePayloadToPatchResource (Private->RedfishService, Private-
Payload, Json, &EtagStr);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, patch resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+
+ //
+ // Handle Etag
+ //
+ if (EtagStr != NULL) {
+ SetEtagWithUri (EtagStr, Private->Uri);
+ FreePool (EtagStr);
+ }
+
+ON_RELEASE:

- return RedfishUpdateResourceCommon (Private, Private->Json);
+ if (Json != NULL) {
+ FreePool (Json);
+ }
+
+ if (ConfigureLang != NULL) {
+ FreePool (ConfigureLang);
+ }
+
+ return Status;
}

/**
@@ -2200,9 +2315,6 @@ RedfishCheckResourceCommon (
EFI_STRING *ConfigureLangList;
UINTN Count;
EFI_STRING Property;
- CHAR8 *PropertyAscii;
- UINTN BuffSize;
- CHAR8 *Match;

if (Private == NULL || IS_EMPTY_STRING (Json)) {
return EFI_INVALID_PARAMETER;
@@ -2221,27 +2333,16 @@ RedfishCheckResourceCommon (
Status = EFI_SUCCESS;
for (Index = 0; Index < Count; Index++) {

- Property = GetPropertyFromConfigureLang (ConfigureLangList[Index]);
+ Property = GetPropertyFromConfigureLang (Private->Uri,
ConfigureLangList[Index]);
if (Property == NULL) {
continue;
}

- DEBUG ((DEBUG_INFO, "[%d] check resource from: %s\n", Index,
Property));
-
- BuffSize = StrLen (Property) + 1;
- PropertyAscii = AllocatePool (BuffSize);
- UnicodeStrToAsciiStrS (Property, PropertyAscii, BuffSize);
-
- //
- // check to see if it is partial match.
- //
- Match = AsciiStrStr (Json, PropertyAscii);
- if (Match == NULL || AsciiStrnCmp (Match, PropertyAscii, AsciiStrLen
(PropertyAscii)) != 0) {
+ DEBUG ((DEBUG_INFO, "%a, [%d] check attribute for: %s\n",
__FUNCTION__, Index, Property));
+ if (!MatchPropertyWithJsonContext (Property, Json)) {
+ DEBUG ((DEBUG_INFO, "%a, property is missing: %s\n", __FUNCTION__,
Property));
Status = EFI_NOT_FOUND;
- DEBUG ((DEBUG_ERROR, "%a, property %a is missing\n",
__FUNCTION__, PropertyAscii));
}
-
- FreePool (PropertyAscii);
}

FreePool (ConfigureLangList);
@@ -2249,7 +2350,6 @@ RedfishCheckResourceCommon (
return Status;
}

-
/**
Update resource to given URI.

@@ -2263,40 +2363,34 @@ RedfishCheckResourceCommon (
EFI_STATUS
RedfishUpdateResourceCommon (
IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
- IN CHAR8 *Json
+ IN CHAR8 *InputJson
)
{
EFI_STATUS Status;
- CHAR8 *MemoryJson;
- CHAR8 *ArrayKey;
+ CHAR8 *Json;
EFI_STRING ConfigureLang;
CHAR8 *EtagStr;

- if (Private == NULL || IS_EMPTY_STRING (Json)) {
+ if (Private == NULL || IS_EMPTY_STRING (InputJson)) {
return EFI_INVALID_PARAMETER;
}

- MemoryJson = NULL;
+ EtagStr = NULL;
+ Json = NULL;
ConfigureLang = NULL;
- ArrayKey = NULL;

- Status = GetArraykeyFromUri (Private->Uri, &ArrayKey);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- ConfigureLang = GetConfigureLangByKey (RESOURCE_SCHEMA,
RESOURCE_SCHEMA_VERSION, NULL, ArrayKey);
+ ConfigureLang = RedfishGetConfigLanguage (Private->Uri);
if (ConfigureLang == NULL) {
return EFI_NOT_FOUND;
}

Status = ProvisioningMemoryProperties (
Private->JsonStructProtocol,
- Json,
+ InputJson,
NULL,
ConfigureLang,
FALSE,
- &MemoryJson
+ &Json
);
if (EFI_ERROR (Status)) {
if (Status == EFI_NOT_FOUND) {
@@ -2311,9 +2405,9 @@ RedfishUpdateResourceCommon (
//
// PUT back to instance
//
- Status = CreatePayloadToPatchResource (Private->RedfishService, Private-
Payload, MemoryJson, &EtagStr);
+ Status = CreatePayloadToPatchResource (Private->RedfishService, Private-
Payload, Json, &EtagStr);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, post memory resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ DEBUG ((DEBUG_ERROR, "%a, patch resource for %s failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
}

//
@@ -2326,17 +2420,81 @@ RedfishUpdateResourceCommon (

ON_RELEASE:

- if (MemoryJson != NULL) {
- FreePool (MemoryJson);
+ if (Json != NULL) {
+ FreePool (Json);
}

if (ConfigureLang != NULL) {
FreePool (ConfigureLang);
}

- if (ArrayKey != NULL) {
- FreePool (ArrayKey);
+ return Status;
+}
+
+/**
+ Identify resource from given URI.
+
+ @param[in] This Pointer to
REDFISH_RESOURCE_COMMON_PRIVATE instance.
+ @param[in] Json The JSON to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishIdentifyResourceCommon (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
+ IN CHAR8 *Json
+ )
+{
+ BOOLEAN Supported;
+ EFI_STATUS Status;
+ EFI_STRING EndOfChar;
+ REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST ConfigLangList;
+
+ Supported = RedfishIdentifyResource (Private->Uri, Private->Json);
+ if (Supported) {
+ Status = RedfishFeatureGetUnifiedArrayTypeConfigureLang
(RESOURCE_SCHEMA, RESOURCE_SCHEMA_VERSION,
REDPATH_ARRAY_PATTERN, &ConfigLangList);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a,
BiosConfigToRedfishGetConfigureLangRegex failed: %r\n", __FUNCTION__,
Status));
+ return Status;
+ }
+
+ if (ConfigLangList.Count == 0) {
+ return EFI_SUCCESS;
+ }
+
+ EndOfChar = StrStr (ConfigLangList.List[0].ConfigureLang, L"}");
+ if (EndOfChar == NULL) {
+ ASSERT (FALSE);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //EndOfChar = StrStr (ConfigLangList.List[0].ConfigureLang, L"}");
+ Status = IsRedpathArray (ConfigLangList.List[0].ConfigureLang, NULL,
&EndOfChar);
+ if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
+ ASSERT (FALSE);
+ return EFI_DEVICE_ERROR;
+ }
+ if (Status != EFI_SUCCESS) {
+ //
+ // This is not the collection redpath.
+ //
+ GetRedpathNodeByIndex (ConfigLangList.List[0].ConfigureLang, 0,
&EndOfChar);
+ }
+ *(++EndOfChar) = '\0';
+ //
+ // Keep URI and ConfigLang mapping
+ //
+ RedfisSetRedfishUri (ConfigLangList.List[0].ConfigureLang, Private->Uri);
+ //
+ // Set the configuration language in the
RESOURCE_INFORMATION_EXCHANGE.
+ // This information is sent back to the parent resource (e.g. the collection
driver).
+ //
+ EdkIIRedfishResourceSetConfigureLang (&ConfigLangList);
+ DestroyConfiglanguageList (&ConfigLangList);
+ return EFI_SUCCESS;
}

- return Status;
+ return EFI_UNSUPPORTED;
}
\ No newline at end of file
diff --git
a/RedfishClientPkg/Features/Memory/V1_7_1/Common/RedfishMemoryCo
mmon.h
b/RedfishClientPkg/Features/Memory/V1_7_1/Common/MemoryCommon.
h
similarity index 89%
rename from
RedfishClientPkg/Features/Memory/V1_7_1/Common/RedfishMemoryCom
mon.h
rename to
RedfishClientPkg/Features/Memory/V1_7_1/Common/MemoryCommon.h
index e2a4f45681..05c58b3553 100644
---
a/RedfishClientPkg/Features/Memory/V1_7_1/Common/RedfishMemoryCo
mmon.h
+++
b/RedfishClientPkg/Features/Memory/V1_7_1/Common/MemoryCommon.
h
@@ -20,7 +20,7 @@
#define RESOURCE_SCHEMA_MINOR "7"
#define RESOURCE_SCHEMA_ERRATA "1"
#define RESOURCE_SCHEMA_VERSION "v1_7_1"
-#define REDPATH_ARRAY_PATTERN L"/Memory/{.*}/"
+#define REDPATH_ARRAY_PATTERN L"/Memory/\\{.*\\}/"
#define REDPATH_ARRAY_PREFIX L"/Memory/"
#define RESOURCE_SCHEMA_FULL "x-uefi-redfish-Memory.v1_7_1"

diff --git
a/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/RedfishMemoryDxe.c
b/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c
similarity index 75%
rename from
RedfishClientPkg/Features/Memory/V1_7_1/Dxe/RedfishMemoryDxe.c
rename to RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c
index d1fbf2c237..0a9d344d6f 100644
---
a/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/RedfishMemoryDxe.c
+++ b/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.c
@@ -1,16 +1,18 @@
/** @file
Redfish feature driver implementation - Memory

- (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

**/

-#include "../Common/RedfishMemoryCommon.h"
+#include "../Common/MemoryCommon.h"

extern REDFISH_RESOURCE_COMMON_PRIVATE
*mRedfishResourcePrivate;

+EFI_HANDLE medfishResourceConfigProtocolHandle;
+
/**
Provising redfish resource by given URI.

@@ -26,8 +28,8 @@ extern REDFISH_RESOURCE_COMMON_PRIVATE
*mRedfishResourcePrivate;
EFI_STATUS
RedfishResourceProvisioningResource (
IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This,
- IN CHAR8 *Uri,
- IN BOOLEAN PostMode
+ IN EFI_STRING Uri,
+ IN BOOLEAN PostMode
)
{
REDFISH_RESOURCE_COMMON_PRIVATE *Private;
@@ -38,9 +40,7 @@ RedfishResourceProvisioningResource (
return EFI_INVALID_PARAMETER;
}

- if (!PostMode) {
- return EFI_UNSUPPORTED;
- }
+ DEBUG ((DEBUG_INFO, "%a, provisioning in %s mode\n", __FUNCTION__,
(PostMode ? L"POST" : L"PATCH")));

Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);

@@ -48,9 +48,9 @@ RedfishResourceProvisioningResource (
return EFI_NOT_READY;
}

- Status = GetResourceByPath (Private->RedfishService, Uri, &Response);
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, get resource from: %a failed\n",
__FUNCTION__, Uri));
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
return Status;
}

@@ -58,7 +58,7 @@ RedfishResourceProvisioningResource (
Private->Payload = Response.Payload;
ASSERT (Private->Payload != NULL);

- Status = RedfishProvisioningResourceCommon (Private, FALSE);
+ Status = RedfishProvisioningResourceCommon (Private, !PostMode);

//
// Release resource
@@ -89,12 +89,13 @@ RedfishResourceProvisioningResource (
EFI_STATUS
RedfishResourceConsumeResource (
IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This,
- IN CHAR8 *Uri
+ IN EFI_STRING Uri
)
{
REDFISH_RESOURCE_COMMON_PRIVATE *Private;
EFI_STATUS Status;
REDFISH_RESPONSE Response;
+ CHAR8 *Etag;

if (This == NULL || IS_EMPTY_STRING (Uri)) {
return EFI_INVALID_PARAMETER;
@@ -106,9 +107,9 @@ RedfishResourceConsumeResource (
return EFI_NOT_READY;
}

- Status = GetResourceByPath (Private->RedfishService, Uri, &Response);
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, get resource from: %a failed\n",
__FUNCTION__, Uri));
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
return Status;
}

@@ -119,9 +120,27 @@ RedfishResourceConsumeResource (
Private->Json = JsonDumpString (RedfishJsonInPayload (Private->Payload),
EDKII_JSON_COMPACT);
ASSERT (Private->Json != NULL);

- Status = RedfishConsumeResourceCommon (Private, Private->Json);
+ //
+ // Find etag in HTTP response header
+ //
+ Etag = NULL;
+ Status = GetEtagAndLocation (&Response, &Etag, NULL);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, failed to consume resource from: %a %r\n",
__FUNCTION__, Uri, Status));
+ DEBUG ((DEBUG_ERROR, "%a, failed to get ETag from HTTP header\n",
__FUNCTION__));
+ }
+
+ Status = RedfishConsumeResourceCommon (Private, Private->Json, Etag);
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_ALREADY_STARTED) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to consume resource from: %s:
%r\n", __FUNCTION__, Uri, Status));
+ }
+ } else {
+ //
+ // Keep etag after consuming pending settings.
+ //
+ if (Etag != NULL) {
+ SetEtagWithUri (Etag, Private->Uri);
+ }
}

//
@@ -193,7 +212,7 @@ RedfishResourceGetInfo (
EFI_STATUS
RedfishResourceUpdate (
IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This,
- IN CHAR8 *Uri
+ IN EFI_STRING Uri
)
{
REDFISH_RESOURCE_COMMON_PRIVATE *Private;
@@ -210,9 +229,9 @@ RedfishResourceUpdate (
return EFI_NOT_READY;
}

- Status = GetResourceByPath (Private->RedfishService, Uri, &Response);
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, get resource from: %a failed\n",
__FUNCTION__, Uri));
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
return Status;
}

@@ -225,7 +244,7 @@ RedfishResourceUpdate (

Status = RedfishUpdateResourceCommon (Private, Private->Json);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, failed to update resource from: %a %r\n",
__FUNCTION__, Uri, Status));
+ DEBUG ((DEBUG_ERROR, "%a, failed to update resource from: %s: %r\n",
__FUNCTION__, Uri, Status));
}

//
@@ -262,7 +281,7 @@ RedfishResourceUpdate (
EFI_STATUS
RedfishResourceCheck (
IN EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *This,
- IN CHAR8 *Uri
+ IN EFI_STRING Uri
)
{
REDFISH_RESOURCE_COMMON_PRIVATE *Private;
@@ -279,9 +298,9 @@ RedfishResourceCheck (
return EFI_NOT_READY;
}

- Status = GetResourceByPath (Private->RedfishService, Uri, &Response);
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, get resource from: %a failed\n",
__FUNCTION__, Uri));
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
return Status;
}

@@ -294,7 +313,7 @@ RedfishResourceCheck (

Status = RedfishCheckResourceCommon (Private, Private->Json);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, failed to check resource from: %a %r\n",
__FUNCTION__, Uri, Status));
+ DEBUG ((DEBUG_ERROR, "%a, failed to check resource from: %s: %r\n",
__FUNCTION__, Uri, Status));
}

//
@@ -318,11 +337,82 @@ RedfishResourceCheck (
return Status;
}

+/**
+ Identify resource on given URI.
+
+ @param[in] This Pointer to
EDKII_REDFISH_RESOURCE_CONFIG_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
+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 == NULL || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private =
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_RESOURCE_PROTO
COL (This);
+
+ if (Private->RedfishService == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Status = GetResourceByUri (Private->RedfishService, Uri, &Response);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, get resource from: %s failed\n",
__FUNCTION__, Uri));
+ return Status;
+ }
+
+ Private->Uri = Uri;
+ Private->Payload = Response.Payload;
+ ASSERT (Private->Payload != NULL);
+
+ Private->Json = JsonDumpString (RedfishJsonInPayload (Private->Payload),
EDKII_JSON_COMPACT);
+ ASSERT (Private->Json != NULL);
+
+ Status = RedfishIdentifyResourceCommon (Private, Private->Json);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, identify %s failed: %r\n", __FUNCTION__,
Uri, Status));
+ }
+ //
+ // Release resource
+ //
+ if (Private->Payload != NULL) {
+ RedfishFreeResponse (
+ Response.StatusCode,
+ Response.HeaderCount,
+ Response.Headers,
+ Response.Payload
+ );
+ Private->Payload = NULL;
+ }
+
+ if (Private->Json != NULL) {
+ FreePool (Private->Json);
+ Private->Json = NULL;
+ }
+
+ return Status;
+}
+
EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL mRedfishResourceConfig =
{
RedfishResourceProvisioningResource,
RedfishResourceConsumeResource,
RedfishResourceUpdate,
RedfishResourceCheck,
+ RedfishResourceIdentify,
RedfishResourceGetInfo
};

@@ -525,6 +615,8 @@ RedfishResourceEntryPoint (
return EFI_ALREADY_STARTED;
}

+ medfishResourceConfigProtocolHandle = ImageHandle;
+
mRedfishResourcePrivate = AllocateZeroPool (sizeof
(REDFISH_RESOURCE_COMMON_PRIVATE));
CopyMem (&mRedfishResourcePrivate->ConfigHandler,
&mRedfishConfigHandler, sizeof
(EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL));
CopyMem (&mRedfishResourcePrivate->RedfishResourceConfig,
&mRedfishResourceConfig, sizeof
(EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL));
diff --git
a/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/RedfishMemoryDxe.inf
b/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf
similarity index 57%
rename from
RedfishClientPkg/Features/Memory/V1_7_1/Dxe/RedfishMemoryDxe.inf
rename to
RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf
index 30746adaed..ae2e8e8f74 100644
---
a/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/RedfishMemoryDxe.inf
+++ b/RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf
@@ -1,6 +1,6 @@
## @file
#
-# (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+# (C) Copyright 2020-2022 Hewlett Packard Enterprise Development
LP<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -9,8 +9,8 @@

[Defines]
INF_VERSION = 0x00010005
- BASE_NAME = RedfishMemoryDxe
- FILE_GUID = f5594d13-ca13-485f-ac3a-80c5074dd8c0
+ BASE_NAME = MemoryDxe
+ FILE_GUID = 69a1a994-ec14-4dd0-ba0d-d1b51b7bab51
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = RedfishResourceEntryPoint
@@ -23,22 +23,25 @@
RedfishClientPkg/RedfishClientPkg.dec

[Sources]
- ../Common/RedfishMemoryCommon.h
- ../Common/RedfishMemoryCommon.c
- RedfishMemoryDxe.c
+ ../Common/MemoryCommon.h
+ ../Common/MemoryCommon.c
+ MemoryDxe.c

[LibraryClasses]
BaseMemoryLib
DebugLib
+ EdkIIRedfishResourceConfigLib
RedfishLib
RedfishFeatureUtilityLib
+ RedfishResourceIdentifyLib
UefiLib
UefiDriverEntryPoint

+
[Protocols]
- gEdkIIRedfishConfigHandlerProtocolGuid ## PRODUCED
- gEfiRestJsonStructureProtocolGuid ## CONSUMED
- gEdkIIRedfishResourceConfigProtocolGuid ## PRODUCED
+ gEdkIIRedfishConfigHandlerProtocolGuid ## PRODUCED
+ gEfiRestJsonStructureProtocolGuid ## CONSUMED
+ gEdkIIRedfishResourceConfigProtocolGuid ## PRODUCED

[Pcd]
gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaStringSize
diff --git a/RedfishClientPkg/Include/RedfishResourceCommon.h
b/RedfishClientPkg/Include/RedfishResourceCommon.h
index 1ba992bb69..af4b809121 100644
--- a/RedfishClientPkg/Include/RedfishResourceCommon.h
+++ b/RedfishClientPkg/Include/RedfishResourceCommon.h
@@ -1,7 +1,7 @@
/** @file
Redfish feature driver common header file.

- (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -11,8 +11,8 @@
#define EFI_REDFISH_RESOURCE_COMMON_H_

#define MAX_RED_PATH_LEN 128
-#define IS_EMPTY_STRING(a) ((a) == NULL || (a)[0] == '\0')
-#define REDFISH_DEBUG_TRACE DEBUG_INFO
+
+#include <RedfishBase.h>

//
// Libraries
@@ -23,14 +23,18 @@
#include <Library/PrintLib.h>
#include <Library/PcdLib.h>
#include <Library/RedfishLib.h>
+#include <Library/RedfishVersionLib.h>
#include <Library/RedfishFeatureUtilityLib.h>
#include <Library/RedfishPlatformConfigLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Library/RedfishResourceIdentifyLib.h>
+#include <Library/EdkIIRedfishResourceConfigLib.h>

//
// Protocols
//
+#include <Protocol/EdkIIRedfishFeature.h>
#include <Protocol/EdkIIRedfishConfigHandler.h>
#include <Protocol/EdkIIRedfishResourceConfigProtocol.h>
#include <Protocol/RestJsonStructure.h>
@@ -43,9 +47,15 @@ typedef struct
_REDFISH_RESOURCE_COMMON_PRIVATE {
EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL RedfishResourceConfig;
EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL ConfigHandler;
EFI_EVENT Event;
- CHAR8 *Uri;
+ EFI_STRING Uri;
CHAR8 *Json;
REDFISH_PAYLOAD Payload;
+ //
+ // Below are used for the external resource.
+ //
+ EDKII_REDFISH_FEATURE_PROTOCOL *FeatureProtocol;
+ RESOURCE_INFORMATION_EXCHANGE *InformationExchange;
+ EFI_STRING RedfishVersion;
} REDFISH_RESOURCE_COMMON_PRIVATE;

#define
REDFISH_RESOURCE_COMMON_PRIVATE_DATA_FROM_CONFIG_PROTOCO
L(This) \
@@ -60,6 +70,7 @@ typedef struct
_REDFISH_RESOURCE_COMMON_PRIVATE {

@param[in] This Pointer to
REDFISH_RESOURCE_COMMON_PRIVATE instance.
@param[in] Json The JSON to consume.
+ @param[in] HeaderEtag The Etag string returned in HTTP header.

@retval EFI_SUCCESS Value is returned successfully.
@retval Others Some error happened.
@@ -68,7 +79,8 @@ typedef struct
_REDFISH_RESOURCE_COMMON_PRIVATE {
EFI_STATUS
RedfishConsumeResourceCommon (
IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
- IN CHAR8 *Json
+ IN CHAR8 *Json,
+ IN CHAR8 *HeaderEtag OPTIONAL
);

/**
@@ -120,4 +132,20 @@ RedfishUpdateResourceCommon (
IN CHAR8 *Json
);

+/**
+ Identify resource from given URI.
+
+ @param[in] This Pointer to
REDFISH_RESOURCE_COMMON_PRIVATE instance.
+ @param[in] Json The JSON to consume.
+
+ @retval EFI_SUCCESS Value is returned successfully.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+RedfishIdentifyResourceCommon (
+ IN REDFISH_RESOURCE_COMMON_PRIVATE *Private,
+ IN CHAR8 *Json
+ );
+
#endif
diff --git a/RedfishClientPkg/RedfishClient.fdf.inc
b/RedfishClientPkg/RedfishClient.fdf.inc
index 3619d2a20f..5c4b9670b0 100644
--- a/RedfishClientPkg/RedfishClient.fdf.inc
+++ b/RedfishClientPkg/RedfishClient.fdf.inc
@@ -14,7 +14,7 @@
INF RedfishClientPkg/RedfishFeatureCoreDxe/RedfishFeatureCoreDxe.inf
INF RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.inf
INF
RedfishClientPkg/RedfishConfigLangMapDxe/RedfishConfigLangMapDxe.inf
- INF
RedfishClientPkg/Features/Memory/V1_7_1/Dxe/RedfishMemoryDxe.inf
+ INF RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf
INF
RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf

!include RedfishClientPkg/RedfishJsonStructureDxe.fdf.inc
diff --git a/RedfishClientPkg/RedfishClientComponents.dsc.inc
b/RedfishClientPkg/RedfishClientComponents.dsc.inc
index 5f1aff3c4b..031d87558e 100644
--- a/RedfishClientPkg/RedfishClientComponents.dsc.inc
+++ b/RedfishClientPkg/RedfishClientComponents.dsc.inc
@@ -19,7 +19,7 @@
#
# Below two modules should be pulled in by build tool.
#
- RedfishClientPkg/Features/Memory/V1_7_1/Dxe/RedfishMemoryDxe.inf
+ RedfishClientPkg/Features/Memory/V1_7_1/Dxe/MemoryDxe.inf

RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf

!include RedfishClientPkg/RedfishJsonStructureDxe.dsc.inc
--
2.32.0.windows.2


Re: [edk2-staging][PATCH v3 11/15] edk2-staging/RedfishClientPkg: Rename RedfishMemoryCollection driver

Chang, Abner
 

[AMD Official Use Only - General]

Reviewed-by: Abner Chang <abner.chang@...>

-----Original Message-----
From: Nickle Wang <nickle.wang@...>
Sent: Wednesday, July 27, 2022 9:38 AM
To: devel@edk2.groups.io
Cc: Chang, Abner <Abner.Chang@...>; Yang, Atom
<Atom.Yang@...>; Nick Ramirez <nramirez@...>
Subject: [edk2-staging][PATCH v3 11/15] edk2-staging/RedfishClientPkg:
Rename RedfishMemoryCollection driver

[CAUTION: External Email]

Rename RedfishMemoryCollectionDxe by removing Redfish prefix. Update
memory collection driver to support "Identify" action and also have code
refactoring to support Redfish operation.

Signed-off-by: Nickle Wang <nickle.wang@...>
Cc: Abner Chang <abner.chang@...>
Cc: Yang Atom <Atom.Yang@...>
Cc: Nick Ramirez <nramirez@...>
---
.../MemoryCollectionDxe.c} | 259 +++++++++---------
.../MemoryCollectionDxe.h} | 7 +-
.../MemoryCollectionDxe.inf} | 19 +-
.../Include/RedfishCollectionCommon.h | 14 +-
RedfishClientPkg/RedfishClient.fdf.inc | 2 +-
.../RedfishClientComponents.dsc.inc | 2 +-
6 files changed, 164 insertions(+), 139 deletions(-) rename
RedfishClientPkg/Features/{RedfishMemoryCollectionDxe/RedfishMemoryC
ollectionDxe.c => MemoryCollectionDxe/MemoryCollectionDxe.c} (66%)
rename
RedfishClientPkg/Features/{RedfishMemoryCollectionDxe/RedfishMemoryC
ollectionDxe.h => MemoryCollectionDxe/MemoryCollectionDxe.h} (64%)
rename
RedfishClientPkg/Features/{RedfishMemoryCollectionDxe/RedfishMemoryC
ollectionDxe.inf => MemoryCollectionDxe/MemoryCollectionDxe.inf} (71%)

diff --git
a/RedfishClientPkg/Features/RedfishMemoryCollectionDxe/RedfishMemory
CollectionDxe.c
b/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.
c
similarity index 66%
rename from
RedfishClientPkg/Features/RedfishMemoryCollectionDxe/RedfishMemoryC
ollectionDxe.c
rename to
RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.c
index d97f0f161e..43426a78af 100644
---
a/RedfishClientPkg/Features/RedfishMemoryCollectionDxe/RedfishMemory
CollectionDxe.c
+++
b/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.
+++ c
@@ -1,67 +1,98 @@
/** @file
- Redfish feature driver implementation - memory collection

- (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+ Redfish feature driver implementation - MemoryCollection
+
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

**/

-#include "RedfishMemoryCollectionDxe.h"
+#include "MemoryCollectionDxe.h"

REDFISH_COLLECTION_PRIVATE *mRedfishCollectionPrivate = NULL;

EFI_STATUS
-ProcessResource (
+HandleResource (
IN REDFISH_COLLECTION_PRIVATE *Private,
- IN CHAR8 *Uri
+ IN EFI_STRING Uri
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL
*RedfishResrouceProtocol;
- REDFISH_SCHEMA_INFO SchemaInfo;
+ EFI_STATUS Status;
+ REDFISH_SCHEMA_INFO SchemaInfo;
+ EFI_STRING ConfigLang;
+ EFI_STRING ReturnedConfigLang;
+ UINTN Index;

if (Private == NULL || IS_EMPTY_STRING (Uri)) {
return EFI_INVALID_PARAMETER;
}

- DEBUG ((REDFISH_DEBUG_TRACE, "%a, process resource for: %a\n",
__FUNCTION__, Uri));
+ //
+ // Resource match
+ //
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, process resource for: %s\n",
+ __FUNCTION__, Uri));

Status = GetRedfishSchemaInfo (Private->RedfishService, Private-
JsonStructProtocol, Uri, &SchemaInfo);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, failed to get schema information from: %a
%r\n", __FUNCTION__, Uri, Status));
+ DEBUG ((DEBUG_ERROR, "%a, failed to get schema information from: %s
+ %r\n", __FUNCTION__, 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, "%s Identify for %s\n", __FUNCTION__,
+ Uri)); ConfigLang = RedfishGetConfigLanguage (Uri); if (ConfigLang
+ == NULL) {
+ Status = EdkIIRedfishResourceConfigIdentify (&SchemaInfo, Uri, Private-
InformationExchange);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_UNSUPPORTED) {
+ DEBUG ((DEBUG_INFO, "%a, \"%s\" is not handled by us\n",
__FUNCTION__, Uri));
+ return EFI_SUCCESS;
+ }

- RedfishResrouceProtocol = GetRedfishResourceConfigProtocol (
- SchemaInfo.Schema,
- SchemaInfo.Major,
- SchemaInfo.Minor,
- SchemaInfo.Errata
- );
- if (RedfishResrouceProtocol == NULL) {
- return EFI_DEVICE_ERROR;
+ DEBUG ((DEBUG_ERROR, "%a, fail to identify resource: \"%s\": %r\n",
__FUNCTION__, Uri, Status));
+ return Status;
+ }
+ } else {
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, history record found: %s\n",
__FUNCTION__, ConfigLang));
+ //
+ // Set exchange information
+ //
+ Status = GetArrayIndexFromArrayTypeConfigureLang (ConfigLang,
&ReturnedConfigLang, &Index);
+ if (!EFI_ERROR (Status) || Status == EFI_NOT_FOUND) {
+ Private->InformationExchange->ReturnedInformation.Type =
InformationTypeCollectionMemberConfigLanguage;
+ Private->InformationExchange-
ReturnedInformation.ConfigureLanguageList.Count = 1;
+ Private->InformationExchange-
ReturnedInformation.ConfigureLanguageList.List =
+ AllocateZeroPool(sizeof
+ (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG));
+
+ if (Private->InformationExchange-
ReturnedInformation.ConfigureLanguageList.List == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG.\n", __FUNCTION__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Private->InformationExchange-
ReturnedInformation.ConfigureLanguageList.List [Index].Index = Index;
+ Private->InformationExchange-
ReturnedInformation.ConfigureLanguageList.List [Index].ConfigureLang =
+ (EFI_STRING)AllocateCopyPool(StrSize(ReturnedConfigLang), (VOID
*)ReturnedConfigLang);
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a,
GetArrayIndexFromArrayTypeConfigureLang fail: %r\n", __FUNCTION__,
Status));
+ }
+ FreePool (ConfigLang);
}

//
// Check and see if target property exist or not even when collection
memeber exists.
// If not, we sill do provision.
//
- DEBUG ((REDFISH_DEBUG_TRACE, "%a Check for %a\n", __FUNCTION__,
Uri));
- Status = RedfishResrouceProtocol->Check (
- RedfishResrouceProtocol,
- Uri
- );
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a Check for %s\n", __FUNCTION__,
+ Uri)); Status = EdkIIRedfishResourceConfigCheck (&SchemaInfo, Uri);
if (EFI_ERROR (Status)) {
//
// The target property does not exist, do the provision to create property.
//
- DEBUG ((REDFISH_DEBUG_TRACE, "%a provision for %a\n",
__FUNCTION__, Uri));
- Status = RedfishResrouceProtocol->Provisioning (
- RedfishResrouceProtocol,
- Uri,
- FALSE
- );
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a provision for %s\n",
__FUNCTION__, Uri));
+ Status = EdkIIRedfishResourceConfigProvisionging (&SchemaInfo, Uri,
+ Private->InformationExchange, FALSE);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a, failed to provision with GET mode: %r\n",
__FUNCTION__, Status));
}
@@ -72,41 +103,36 @@ ProcessResource (
//
// Consume first.
//
- DEBUG ((REDFISH_DEBUG_TRACE, "%a consume for %a\n",
__FUNCTION__, Uri));
- Status = RedfishResrouceProtocol->Consume (
- RedfishResrouceProtocol,
- Uri
- );
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a consume for %s\n",
__FUNCTION__,
+ Uri)); Status = EdkIIRedfishResourceConfigConsume (&SchemaInfo, Uri);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, failed to consume resoruce for: %a %r\n",
__FUNCTION__, Uri, Status));
+ DEBUG ((DEBUG_ERROR, "%a, failed to consume resoruce for: %s:
+ %r\n", __FUNCTION__, Uri, Status));
}

//
// Patch.
//
- DEBUG ((REDFISH_DEBUG_TRACE, "%a update for %a\n", __FUNCTION__,
Uri));
- Status = RedfishResrouceProtocol->Update (
- RedfishResrouceProtocol,
- Uri
- );
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a update for %s\n", __FUNCTION__,
+ Uri)); Status = EdkIIRedfishResourceConfigUpdate (&SchemaInfo, Uri);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, failed to update resoruce for: %s: %r\n",
+ __FUNCTION__, Uri, Status)); }

return Status;
}

EFI_STATUS
-ProcessCollection (
+HandleCollectionResource (
IN REDFISH_COLLECTION_PRIVATE *Private
)
{
EFI_STATUS Status;
- EFI_REDFISH_MEMORYCOLLECTION *Memory;
+ EFI_REDFISH_MEMORYCOLLECTION *Collection;
EFI_REDFISH_MEMORYCOLLECTION_CS *CollectionCs;
RedfishCS_Link *List;
RedfishCS_Header *Header;
RedfishCS_Type_Uri_Data *UriData;
- CHAR8 *ConfigureLang;
- UINTN Size;
- UINTN Count;
+ EFI_STRING MemberUri;

if (Private == NULL) {
return EFI_INVALID_PARAMETER;
@@ -116,7 +142,7 @@ ProcessCollection (
return EFI_NOT_READY;
}

- DEBUG ((REDFISH_DEBUG_TRACE, "%a, process collection for: %a\n",
__FUNCTION__, Private->CollectionPath));
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, process collection for: %s\n",
+ __FUNCTION__, Private->CollectionUri));

//
// Convert JSON text to C structure.
@@ -125,14 +151,14 @@ ProcessCollection (
Private->JsonStructProtocol,
NULL,
Private->CollectionJson,
- (EFI_REST_JSON_STRUCTURE_HEADER **)&Memory
+
+ (EFI_REST_JSON_STRUCTURE_HEADER **)&Collection
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a, ToStructure() failed: %r\n", __FUNCTION__,
Status));
return Status;
}

- CollectionCs = Memory->MemoryCollection;
+ CollectionCs = Collection->MemoryCollection;

if (*CollectionCs->Membersodata_count == 0) {
return EFI_NOT_FOUND;
@@ -142,23 +168,22 @@ ProcessCollection (
return EFI_NOT_FOUND;
}

- Count = 0;
List = GetFirstLink (&CollectionCs->Members);
while (TRUE) {

Header = (RedfishCS_Header *)List;
if (Header->ResourceType == RedfishCS_Type_Uri) {
UriData = (RedfishCS_Type_Uri_Data *)Header;
-
- ++Count;
- Size = AsciiStrLen (Private->CollectionPath) + 5;
- ConfigureLang = AllocatePool (Size);
- ASSERT (ConfigureLang != NULL);
- AsciiSPrint (ConfigureLang, Size, "%a[%d]", Private->CollectionPath,
Count);
-
- Status = ProcessResource (Private, ConfigureLang);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, process memory resource: %a failed:
%r\n", __FUNCTION__, UriData->Uri, Status));
+ MemberUri = NULL;
+ MemberUri = StrAsciiToUnicode (UriData->Uri);
+ ASSERT (MemberUri != NULL);
+ if (MemberUri != NULL) {
+ Status = HandleResource (Private, MemberUri);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, process MemoryCollection resource:
%a failed: %r\n", __FUNCTION__, UriData->Uri, Status));
+ }
+
+ FreePool (MemberUri);
}
}

@@ -172,25 +197,24 @@ ProcessCollection (
//
// Release resource.
//
- Private->JsonStructProtocol->DestoryStructure (Private-
JsonStructProtocol, (EFI_REST_JSON_STRUCTURE_HEADER *)Memory);
+ Private->JsonStructProtocol->DestoryStructure
+ (Private->JsonStructProtocol, (EFI_REST_JSON_STRUCTURE_HEADER
+ *)Collection);

return EFI_SUCCESS;
}

EFI_STATUS
-CreateCollection (
+CreateCollectionResource (
IN REDFISH_COLLECTION_PRIVATE *Private
)
{
EFI_STATUS Status;
- EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL
*RedfishResrouceProtocol;
REDFISH_SCHEMA_INFO SchemaInfo;

if (Private == NULL) {
return EFI_INVALID_PARAMETER;
}

- DEBUG ((REDFISH_DEBUG_TRACE, "%a, create resource for collection for:
%a\n", __FUNCTION__, Private->CollectionPath));
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, create resource for collection for:
+ %s\n", __FUNCTION__, Private->CollectionUri));

Status = GetSupportedSchemaVersion (REDFISH_SCHEMA_NAME,
&SchemaInfo);
if (EFI_ERROR (Status)) {
@@ -200,18 +224,9 @@ CreateCollection (

DEBUG ((REDFISH_DEBUG_TRACE, "%a, supported schema: %a
%a.%a.%a\n", __FUNCTION__, SchemaInfo.Schema, SchemaInfo.Major,
SchemaInfo.Minor, SchemaInfo.Errata));

- RedfishResrouceProtocol = GetRedfishResourceConfigProtocol
(SchemaInfo.Schema, SchemaInfo.Major, SchemaInfo.Minor,
SchemaInfo.Errata);
- if (RedfishResrouceProtocol == NULL) {
- return EFI_DEVICE_ERROR;
- }
-
- Status = RedfishResrouceProtocol->Provisioning (
- RedfishResrouceProtocol,
- Private->CollectionPath,
- TRUE
- );
+ Status = EdkIIRedfishResourceConfigProvisionging (&SchemaInfo,
+ Private->CollectionUri, Private->InformationExchange, TRUE);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, failed to create resoruce for: %a %r\n",
__FUNCTION__, Private->CollectionPath, Status));
+ DEBUG ((DEBUG_ERROR, "%a, failed to create resoruce for: %s: %r\n",
+ __FUNCTION__, Private->CollectionUri, Status));
}

return Status;
@@ -248,6 +263,11 @@ ReleaseCollectionResource (
Private->CollectionJson = NULL;
}

+ if (Private->RedfishVersion != NULL) {
+ FreePool (Private->RedfishVersion);
+ Private->RedfishVersion = NULL;
+ }
+
return EFI_SUCCESS;
}

@@ -257,49 +277,19 @@ CollectionHandler (
)
{
EFI_STATUS Status;
- CHAR8 *SystemRootPath;
- CHAR8 *PathBuffer;
- UINTN BufferSize;

if (Private == NULL) {
return EFI_INVALID_PARAMETER;
}

- SystemRootPath = NULL;
- PathBuffer = NULL;
-
- SystemRootPath = RedfishGetSystemRootPath ();
- if (SystemRootPath == NULL) {
- DEBUG ((DEBUG_ERROR, "%a, can not find system root path\n",
__FUNCTION__));
- return EFI_DEVICE_ERROR;
- }
-
- BufferSize = AsciiStrSize (SystemRootPath) + AsciiStrSize
(REDFISH_SCHEMA_NAME);
- PathBuffer = AllocatePool (BufferSize);
- if (PathBuffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_RELEASE;
- }
-
- AsciiSPrint (PathBuffer, BufferSize, "%a/%a", SystemRootPath,
REDFISH_SCHEMA_NAME);
-
- DEBUG ((REDFISH_DEBUG_TRACE, "%a, collection handler for %a\n",
__FUNCTION__, PathBuffer));
-
- //
- // Initialize collection path
- //
- Private->CollectionPath = RedfishBuildPathWithSystemUuid (PathBuffer,
TRUE, NULL);
- if (Private->CollectionPath == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_RELEASE;
- }
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, collection handler for %s\n",
+ __FUNCTION__, Private->CollectionUri));

//
// Query collection from Redfish service.
//
- Status = GetResourceByPath (Private->RedfishService, Private-
CollectionPath, &Private->RedResponse);
+ Status = GetResourceByUri (Private->RedfishService,
+ Private->CollectionUri, &Private->RedResponse);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, unable to get resource from: %a :%r\n",
__FUNCTION__, Private->CollectionPath, Status));
+ DEBUG ((DEBUG_ERROR, "%a, unable to get resource from: %s :%r\n",
+ __FUNCTION__, Private->CollectionUri, Status));
goto ON_RELEASE;
}

@@ -309,21 +299,13 @@ CollectionHandler (
Private->CollectionJson = JsonDumpString (RedfishJsonInPayload (Private-
CollectionPayload), EDKII_JSON_COMPACT);
ASSERT (Private->CollectionJson != NULL);

- Status = ProcessCollection (Private);
+ Status = HandleCollectionResource (Private);
if (EFI_ERROR (Status) && Status == EFI_NOT_FOUND) {
- Status = CreateCollection (Private);
+ Status = CreateCollectionResource (Private);
}

ON_RELEASE:

- if (SystemRootPath != NULL) {
- FreePool (SystemRootPath);
- }
-
- if (PathBuffer != NULL) {
- FreePool (PathBuffer);
- }
-
ReleaseCollectionResource (Private);

return Status;
@@ -334,10 +316,12 @@ ON_RELEASE:

@param[in] This Pointer to EDKII_REDFISH_FEATURE_PROTOCOL
instance.
@param[in] FeatureAction The action Redfish feature driver should
take.
+ @param[in] Uri The collection URI.
@param[in] Context The context of Redfish feature driver.
- @param[in,out] InformationReturned The pointer to retrive the pointer to
- FEATURE_RETURNED_INFOMATION. The memory block
of this
- information should be freed by caller.
+ @param[in,out] InformationExchange The pointer to
+ RESOURCE_INFORMATION_EXCHANGE
+
+ @retval EFI_SUCCESS Redfish feature driver callback is executed
successfully.
+ @retval Others Some errors happened.

@retval EFI_SUCCESS Redfish feature driver callback is executed
successfully.
@retval Others Some errors happened.
@@ -349,12 +333,13 @@ RedfishCollectionFeatureCallback (
IN EDKII_REDFISH_FEATURE_PROTOCOL *This,
IN FEATURE_CALLBACK_ACTION FeatureAction,
IN VOID *Context,
- IN OUT FEATURE_RETURNED_INFORMATION **InformationReturned
+ IN OUT RESOURCE_INFORMATION_EXCHANGE *InformationExchange
)
{
EFI_STATUS Status;
REDFISH_SERVICE RedfishService;
REDFISH_COLLECTION_PRIVATE *Private;
+ EFI_STRING ResourceUri;

if (FeatureAction != CallbackActionStartOperation) {
return EFI_UNSUPPORTED;
@@ -367,6 +352,36 @@ RedfishCollectionFeatureCallback (
return EFI_NOT_READY;
}

+ //
+ // Save in private structure.
+ //
+ Private->InformationExchange = InformationExchange;
+
+ //
+ // Find Redfish version on BMC
+ //
+ Private->RedfishVersion = RedfishGetVersion (RedfishService);
+
+ //
+ // Create the full URI from Redfish service root.
+ //
+ ResourceUri = (EFI_STRING)AllocateZeroPool (MAX_URI_LENGTH *
+ sizeof(CHAR16)); if (ResourceUri == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for full URI.\n",
__FUNCTION__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ StrCatS (ResourceUri, MAX_URI_LENGTH, Private->RedfishVersion);
+ StrCatS (ResourceUri, MAX_URI_LENGTH,
+ InformationExchange->SendInformation.FullUri);
+
+ //
+ // Initialize collection path
+ //
+ Private->CollectionUri = RedfishGetUri (ResourceUri); if
+ (Private->CollectionUri == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
Status = CollectionHandler (Private);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a, CollectionHandler failure: %r\n",
__FUNCTION__, Status)); @@ -549,7 +564,7 @@ RedfishCollectionUnload (
)
{
EFI_STATUS Status;
- EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *ConfigHandler;
+ EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *ConfigHandler;

if (mRedfishCollectionPrivate == NULL) {
return EFI_NOT_READY;
diff --git
a/RedfishClientPkg/Features/RedfishMemoryCollectionDxe/RedfishMemory
CollectionDxe.h
b/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.
h
similarity index 64%
rename from
RedfishClientPkg/Features/RedfishMemoryCollectionDxe/RedfishMemoryC
ollectionDxe.h
rename to
RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.h
index 83ca836941..75b4a123ff 100644
---
a/RedfishClientPkg/Features/RedfishMemoryCollectionDxe/RedfishMemory
CollectionDxe.h
+++
b/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.
+++ h
@@ -1,7 +1,8 @@
/** @file
+
Redfish feature driver implementation - internal header file

- (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -14,5 +15,7 @@
#include <RedfishCollectionCommon.h>

#define REDFISH_SCHEMA_NAME "Memory"
-#define REDFISH_MANAGED_URI
L"/redfish/v1/systems/{1}/memory"
+#define REDFISH_MANAGED_URI
L"Chassis/{}/Memory/{};Systems/{}/Memory/{}"
+#define MAX_URI_LENGTH 256
+
#endif
diff --git
a/RedfishClientPkg/Features/RedfishMemoryCollectionDxe/RedfishMemory
CollectionDxe.inf
b/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.i
nf
similarity index 71%
rename from
RedfishClientPkg/Features/RedfishMemoryCollectionDxe/RedfishMemoryC
ollectionDxe.inf
rename to
RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf
index e7bcf49bdb..05e05712e7 100644
---
a/RedfishClientPkg/Features/RedfishMemoryCollectionDxe/RedfishMemory
CollectionDxe.inf
+++
b/RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.
+++ inf
@@ -1,15 +1,18 @@
## @file
#
-# (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+# Redfish MemoryCollection collection driver.
+#
+# (C) Copyright 2020-2022 Hewlett Packard Enterprise Development
+LP<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent # ##

+
[Defines]
INF_VERSION = 0x00010005
- BASE_NAME = RedfishMemoryCollectionDxe
- FILE_GUID = 9323359C-11E2-49BC-B501-D6280B6DAE1A
+ BASE_NAME = MemoryCollectionDxe
+ FILE_GUID = 22facf8f-a007-462c-9be4-638043a26858
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = RedfishCollectionEntryPoint
@@ -22,8 +25,8 @@
RedfishClientPkg/RedfishClientPkg.dec

[Sources]
- RedfishMemoryCollectionDxe.h
- RedfishMemoryCollectionDxe.c
+ MemoryCollectionDxe.h
+ MemoryCollectionDxe.c

[LibraryClasses]
DebugLib
@@ -35,19 +38,19 @@
UefiLib
UefiDriverEntryPoint
UefiBootServicesTableLib
+ EdkIIRedfishResourceConfigLib
+ RedfishVersionLib

[Protocols]
gEdkIIRedfishConfigHandlerProtocolGuid ## CONSUMED
gEfiRestJsonStructureProtocolGuid ## CONSUMED
- gEdkIIRedfishResourceConfigProtocolGuid ## CONSUMED
gEdkIIRedfishFeatureProtocolGuid ## CONSUMED

[Guids]
- gEfiEventReadyToBootGuid

[Pcd]
gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaStringSize
gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaVersionSize

[Depex]
- TRUE
\ No newline at end of file
+ TRUE
diff --git a/RedfishClientPkg/Include/RedfishCollectionCommon.h
b/RedfishClientPkg/Include/RedfishCollectionCommon.h
index 05a0f672f3..d4adcedd1f 100644
--- a/RedfishClientPkg/Include/RedfishCollectionCommon.h
+++ b/RedfishClientPkg/Include/RedfishCollectionCommon.h
@@ -1,7 +1,7 @@
/** @file
Redfish feature driver collection common header file.

- (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -10,6 +10,8 @@
#ifndef EFI_REDFISH_COLLECTION_COMMON_H_ #define
EFI_REDFISH_COLLECTION_COMMON_H_

+#include <RedfishBase.h>
+
//
// Libraries
//
@@ -22,28 +24,30 @@
#include <Library/RedfishFeatureUtilityLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Library/EdkIIRedfishResourceConfigLib.h>
+#include <Library/RedfishVersionLib.h>

//
// Protocols
//
#include <Protocol/EdkIIRedfishConfigHandler.h>
-#include <Protocol/EdkIIRedfishResourceConfigProtocol.h>
#include <Protocol/EdkIIRedfishFeature.h> #include
<Protocol/RestJsonStructure.h> #include <Protocol/RestEx.h>

-#define IS_EMPTY_STRING(a) ((a) == NULL || (a)[0] == '\0')
-#define REDFISH_DEBUG_TRACE DEBUG_INFO
+#define REDFISH_MAX_COLLECTION_INDEX_LEN 8

typedef struct _REDFISH_COLLECTION_PRIVATE {
EFI_REST_JSON_STRUCTURE_PROTOCOL *JsonStructProtocol;
EDKII_REDFISH_FEATURE_PROTOCOL *FeatureProtocol;
REDFISH_SERVICE RedfishService;
+ RESOURCE_INFORMATION_EXCHANGE *InformationExchange;
EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL ConfigHandler;
- CHAR8 *CollectionPath;
+ EFI_STRING CollectionUri;
CHAR8 *CollectionJson;
REDFISH_PAYLOAD CollectionPayload;
REDFISH_RESPONSE RedResponse;
+ EFI_STRING RedfishVersion;
} REDFISH_COLLECTION_PRIVATE;

#define REDFISH_COLLECTION_PRIVATE_DATA_FROM_PROTOCOL(This) \
diff --git a/RedfishClientPkg/RedfishClient.fdf.inc
b/RedfishClientPkg/RedfishClient.fdf.inc
index 6292de4e81..3619d2a20f 100644
--- a/RedfishClientPkg/RedfishClient.fdf.inc
+++ b/RedfishClientPkg/RedfishClient.fdf.inc
@@ -15,7 +15,7 @@
INF RedfishClientPkg/RedfishETagDxe/RedfishETagDxe.inf
INF
RedfishClientPkg/RedfishConfigLangMapDxe/RedfishConfigLangMapDxe.inf
INF
RedfishClientPkg/Features/Memory/V1_7_1/Dxe/RedfishMemoryDxe.inf
- INF
RedfishClientPkg/Features/RedfishMemoryCollectionDxe/RedfishMemoryC
ollectionDxe.inf
+ INF
+
RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf

!include RedfishClientPkg/RedfishJsonStructureDxe.fdf.inc
#
diff --git a/RedfishClientPkg/RedfishClientComponents.dsc.inc
b/RedfishClientPkg/RedfishClientComponents.dsc.inc
index ee4602fe79..5f1aff3c4b 100644
--- a/RedfishClientPkg/RedfishClientComponents.dsc.inc
+++ b/RedfishClientPkg/RedfishClientComponents.dsc.inc
@@ -20,7 +20,7 @@
# Below two modules should be pulled in by build tool.
#
RedfishClientPkg/Features/Memory/V1_7_1/Dxe/RedfishMemoryDxe.inf
-
RedfishClientPkg/Features/RedfishMemoryCollectionDxe/RedfishMemoryC
ollectionDxe.inf
+
RedfishClientPkg/Features/MemoryCollectionDxe/MemoryCollectionDxe.inf

!include RedfishClientPkg/RedfishJsonStructureDxe.dsc.inc

--
2.32.0.windows.2


Re: [PATCH v2 1/2] MdeModulePkg: Add EDKII_PCI_DEVICE_PPI definition

Wu, Hao A
 

As previously mentioned in https://edk2.groups.io/g/devel/message/90345, the PPI interface looks good from the device controllers perspective:
Reviewed-by: Hao A Wu <hao.a.wu@...>

Sorry Ray and Liming, do you have additional comments for this newly introduced EDKII_PCI_DEVICE_PPI?

Best Regards,
Hao Wu

-----Original Message-----
From: Czajkowski, Maciej <maciej.czajkowski@...>
Sent: Wednesday, July 27, 2022 8:28 PM
To: devel@edk2.groups.io
Cc: Wu, Hao A <hao.a.wu@...>; Ni, Ray <ray.ni@...>; Gao,
Liming <gaoliming@...>
Subject: [PATCH v2 1/2] MdeModulePkg: Add EDKII_PCI_DEVICE_PPI
definition

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3907

This commit introduces EDKII_PCI_DEVICE_PPI. The purpose of this PPI is to
provide a way of accessing PCI devices to drvice drivers such as
NvmExpressPei or AhciPei.

Cc: Hao A Wu <hao.a.wu@...>
Cc: Ray Ni <ray.ni@...>
Cc: Liming Gao <gaoliming@...>
Signed-off-by: Maciej Czajkowski <maciej.czajkowski@...>
Acked-by: Hao A Wu <hao.a.wu@...>
---

Notes:
v2 changes:
- added acked-by tag
- minor change - modified header guard to follow coding style

MdeModulePkg/Include/Ppi/PciDevice.h | 32 ++++++++++++++++++++
MdeModulePkg/MdeModulePkg.dec | 3 ++
2 files changed, 35 insertions(+)

diff --git a/MdeModulePkg/Include/Ppi/PciDevice.h
b/MdeModulePkg/Include/Ppi/PciDevice.h
new file mode 100644
index 000000000000..6750ae6ce394
--- /dev/null
+++ b/MdeModulePkg/Include/Ppi/PciDevice.h
@@ -0,0 +1,32 @@
+/** @file++ Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>+
SPDX-License-Identifier: BSD-2-Clause-Patent++**/++#ifndef
EDKII_PCI_DEVICE_PPI_H_+#define EDKII_PCI_DEVICE_PPI_H_++#include
<Protocol/PciIo.h>+#include <Protocol/DevicePath.h>++///+/// Global ID for
the EDKII_PCI_DEVICE_PPI_GUID.+///+#define
EDKII_PCI_DEVICE_PPI_GUID \+ { \+ 0x1597ab4f, 0xd542, 0x4efe, { 0x9a,
0xf7, 0xb2, 0x44, 0xec, 0x54, 0x4c, 0x0b } \+ }++///+/// PCI Device PPI
structure.+///+typedef struct {+ EFI_PCI_IO_PROTOCOL PciIo;+
EFI_DEVICE_PATH_PROTOCOL *DevicePath;+}
EDKII_PCI_DEVICE_PPI;++extern EFI_GUID
gEdkiiPeiPciDevicePpiGuid;++#endif // EDKII_PCI_DEVICE_PPI_H_diff --git
a/MdeModulePkg/MdeModulePkg.dec
b/MdeModulePkg/MdeModulePkg.dec
index 2bcb9f9453af..7d989108324a 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -509,6 +509,9 @@ [Ppis]
## Include/Ppi/NvmExpressPassThru.h
gEdkiiPeiNvmExpressPassThruPpiGuid = { 0x6af31b2c, 0x3be, 0x46c1, { 0xb1,
0x2d, 0xea, 0x4a, 0x36, 0xdf, 0xa7, 0x4c } } + ## Include/Ppi/PciDevice.h+
gEdkiiPeiPciDevicePpiGuid = { 0x1597ab4f, 0xd542, 0x4efe, { 0x9a,
0xf7, 0xb2, 0x44, 0xec, 0x54, 0x4c, 0x0b } }+ ## Include/Ppi/CapsuleOnDisk.h
gEdkiiPeiCapsuleOnDiskPpiGuid = { 0x71a9ea61, 0x5a35, 0x4a5d, { 0xac,
0xef, 0x9c, 0xf8, 0x6d, 0x6d, 0x67, 0xe0 } }
gEdkiiPeiBootInCapsuleOnDiskModePpiGuid = { 0xb08a11e4, 0xe2b7,
0x4b75, { 0xb5, 0x15, 0xaf, 0x61, 0x6, 0x68, 0xbf, 0xd1 } }--
2.27.0.windows.1


Re: [PATCH v2 2/2] MdeModulePkg/AhciPei: Use PCI_DEVICE_PPI to manage AHCI device

Wu, Hao A
 

1. In the AHCI PEIM entrypoint, after registering the PPI callbacks for:
* gEdkiiPeiAtaAhciHostControllerPpiGuid and
* gEdkiiPeiPciDevicePpiGuid
My take is that there is no need to locate above PPI instances already installed within system (codes in entry point that come after the callback registration).
The current implementation of PeiServicesNotifyPpi (details can be referred at MdeModulePkg\Core\Pei\Ppi\Ppi.c - InternalPeiNotifyPpi) will invoke the callback functions for all the matched PPI instances already installed.
Could you help to double confirm on this in your unit test? Sorry for missing this on the V1 patch.

2. Please help to move the function declaration for:
AtaAhciHostControllerPpiInstallationCallback()
AtaAhciPciDevicePpiInstallationCallback()
from AhciPei.c to AhciPei.h to keep consistency.

3. The function description comments for:
AtaAhciHostControllerPpiInstallationCallback()
AtaAhciPciDevicePpiInstallationCallback()
do not exactly match between their declaration and definition.

4. During the enabling of the HC in function AtaAhciInitPrivateDataFromPciDevice():
Status = PciDevice->PciIo.Attributes (
&PciDevice->PciIo,
EfiPciIoAttributeOperationSet,
EFI_PCI_DEVICE_ENABLE,
NULL
);
Could you help to update the flow to align with AtaAtapiPassThru DXE counterpart when enabling the controller?
MdeModulePkg\Bus\Ata\AtaAtapiPassThru\AtaAtapiPassThru.c - AtaAtapiPassThruStart():
Status = PciIo->Attributes (
PciIo,
EfiPciIoAttributeOperationSupported,
0,
&EnabledPciAttributes
);
if (!EFI_ERROR (Status)) {
EnabledPciAttributes &= (UINT64)EFI_PCI_DEVICE_ENABLE;
Status = PciIo->Attributes (
PciIo,
EfiPciIoAttributeOperationEnable,
EnabledPciAttributes,
NULL
);
}

5. DEBUG ((DEBUG_ERROR, "%a: Using AtaAhciHostControllerPpi to initialize private data.\n", __FUNCTION__));
-> DEBUG ((DEBUG_INFO, "%a: Using AtaAhciHostControllerPpi to initialize private data.\n", __FUNCTION__));

6. I think for AtaAhciInitPrivateDataFromPciDevices(), the below code snippet:
//
// Override the status to continue the for loop
//
Status = EFI_SUCCESS;
is no longer needed. Could you help to check?


Best Regards,
Hao Wu

-----Original Message-----
From: Czajkowski, Maciej <maciej.czajkowski@...>
Sent: Wednesday, July 27, 2022 8:28 PM
To: devel@edk2.groups.io
Cc: Wu, Hao A <hao.a.wu@...>; Ni, Ray <ray.ni@...>; Gao,
Liming <gaoliming@...>
Subject: [PATCH v2 2/2] MdeModulePkg/AhciPei: Use PCI_DEVICE_PPI to
manage AHCI device

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3907

This change modifies AhciPei library to allow usage both
EDKII_PCI_DEVICE_PPI and EDKII_PEI_ATA_AHCI_HOST_CONTROLLER_PPI
to manage ATA HDD working under AHCI mode.

Cc: Hao A Wu <hao.a.wu@...>
Cc: Ray Ni <ray.ni@...>
Cc: Liming Gao <gaoliming@...>
Signed-off-by: Maciej Czajkowski <maciej.czajkowski@...>
---

Notes:
v2 changes:
- added missing function descriptions
- moved controller initialization from PCI_DEVICE_PPI to seperate funciton
in order to reduce code duplication
- added DevicePathLib BASE instance to the MdeModulePkg.dec to allow
PEIMs to consume it

MdeModulePkg/Bus/Ata/AhciPei/AhciPei.c | 585 ++++++++++++++------
MdeModulePkg/Bus/Ata/AhciPei/DevicePath.c | 44 --
MdeModulePkg/Bus/Ata/AhciPei/AhciPei.h | 17 +-
MdeModulePkg/Bus/Ata/AhciPei/AhciPei.inf | 5 +-
MdeModulePkg/MdeModulePkg.dsc | 1 +
5 files changed, 430 insertions(+), 222 deletions(-)

diff --git a/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.c
b/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.c
index 208b7e9a3606..8ad98dc76bc1 100644
--- a/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.c
+++ b/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.c
@@ -9,6 +9,47 @@
**/ #include "AhciPei.h"+#include <Ppi/PciDevice.h>+#include
<Library/DevicePathLib.h>+#include <IndustryStandard/Pci.h>++/**+
Callback for EDKII_ATA_AHCI_HOST_CONTROLLER_PPI installation.++
@param[in] PeiServices Pointer to PEI Services Table.+ @param[in]
NotifyDescriptor Pointer to the descriptor for the Notification+
event that caused this function to execute.+ @param[in] Ppi Pointer
to the PPI data associated with this function.++ @retval EFI_SUCCESS The
function completes
successfully++**/+EFI_STATUS+EFIAPI+AtaAhciHostControllerPpiInstallation
Callback (+ IN EFI_PEI_SERVICES **PeiServices,+ IN
EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,+ IN VOID
*Ppi+ );++/**+ Callback for EDKII_PCI_DEVICE_PPI installation.++
@param[in] PeiServices Pointer to PEI Services Table.+ @param[in]
NotifyDescriptor Pointer to the descriptor for the Notification+
event that caused this function to execute.+ @param[in] Ppi Pointer
to the PPI data associated with this function.++ @retval EFI_SUCCESS The
function completes
successfully++**/+EFI_STATUS+EFIAPI+AtaAhciPciDevicePpiInstallationCallb
ack (+ IN EFI_PEI_SERVICES **PeiServices,+ IN
EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,+ IN VOID
*Ppi+ ); EFI_PEI_PPI_DESCRIPTOR mAhciAtaPassThruPpiListTemplate =
{ (EFI_PEI_PPI_DESCRIPTOR_PPI |
EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),@@ -40,6 +81,18 @@
EFI_PEI_NOTIFY_DESCRIPTOR mAhciEndOfPeiNotifyListTemplate = {
AhciPeimEndOfPei }; +EFI_PEI_NOTIFY_DESCRIPTOR
mAtaAhciHostControllerNotify = {+
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),+
&gEdkiiPeiAtaAhciHostControllerPpiGuid,+
AtaAhciHostControllerPpiInstallationCallback+};++EFI_PEI_NOTIFY_DESCRIPT
OR mPciDevicePpiNotify = {+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),+
&gEdkiiPeiPciDevicePpiGuid,+ AtaAhciPciDevicePpiInstallationCallback+};+
/** Free the DMA resources allocated by an ATA AHCI controller. @@ -
111,33 +164,30 @@ AhciPeimEndOfPei (
} /**- Entry point of the PEIM.+ Initialize and install PrivateData PPIs. -
@param[in] FileHandle Handle of the file being invoked.- @param[in]
PeiServices Describes the list of possible PEI Services.-- @retval
EFI_SUCCESS PPI successfully installed.+ @param[in] MmioBase
MMIO base address of specific AHCI controller+ @param[in] DevicePath
A pointer to the EFI_DEVICE_PATH_PROTOCOL+ structure.+
@param[in] DevicePathLength Length of the device path. + @retval
EFI_SUCCESS AHCI controller initialized and PPIs installed+ @retval others
Failed to initialize AHCI controller **/ EFI_STATUS-EFIAPI-AtaAhciPeimEntry
(- IN EFI_PEI_FILE_HANDLE FileHandle,- IN CONST EFI_PEI_SERVICES
**PeiServices+AtaAhciInitPrivateData (+ IN UINTN MmioBase,+
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,+ IN UINTN
DevicePathLength ) {- EFI_STATUS Status;- EFI_BOOT_MODE
BootMode;- EDKII_ATA_AHCI_HOST_CONTROLLER_PPI *AhciHcPpi;- UINT8
Controller;- UINTN MmioBase;- UINTN
DevicePathLength;- EFI_DEVICE_PATH_PROTOCOL *DevicePath;-
UINT32 PortBitMap;- PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private;- UINT8 NumberOfPorts;+ EFI_STATUS
Status;+ UINT32 PortBitMap;+ UINT8
NumberOfPorts;+ PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;+
EFI_BOOT_MODE BootMode; - DEBUG ((DEBUG_INFO, "%a:
Enters.\n", __FUNCTION__));+ DEBUG ((DEBUG_INFO, "Initializing private
data for ATA\n")); // // Get the current boot mode.@@ -149,19 +199,149
@@ AtaAhciPeimEntry (
} //- // Locate the ATA AHCI host controller PPI.- //- Status =
PeiServicesLocatePpi (- &gEdkiiPeiAtaAhciHostControllerPpiGuid,-
0,- NULL,- (VOID **)&AhciHcPpi- );+ // Check validity of
the device path of the ATA AHCI controller.+ //+ Status =
AhciIsHcDevicePathValid (DevicePath, DevicePathLength);+ if (EFI_ERROR
(Status)) {+ DEBUG ((+ DEBUG_ERROR,+ "%a: The device path is
invalid.\n",+ __FUNCTION__+ ));+ return Status;+ }++ //+ // For S3
resume performance consideration, not all ports on an ATA AHCI+ //
controller will be enumerated/initialized. The driver consumes the+ //
content within S3StorageDeviceInitList LockBox to get the ports that+ // will
be enumerated/initialized during S3 resume.+ //+ if (BootMode ==
BOOT_ON_S3_RESUME) {+ NumberOfPorts = AhciS3GetEumeratePorts
(DevicePath, DevicePathLength, &PortBitMap);+ if (NumberOfPorts == 0)
{+ return EFI_SUCCESS;+ }+ } else {+ PortBitMap = MAX_UINT32;+ }++
//+ // Memory allocation for controller private data.+ //+ Private =
AllocateZeroPool (sizeof (PEI_AHCI_CONTROLLER_PRIVATE_DATA));+ if
(Private == NULL) {+ DEBUG ((+ DEBUG_ERROR,+ "%a: Fail to allocate
private data.\n",+ __FUNCTION__+ ));+ return
EFI_OUT_OF_RESOURCES;+ }++ //+ // Initialize controller private data.+ //+
Private->Signature =
AHCI_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;+ Private->MmioBase
= MmioBase;+ Private->DevicePathLength = DevicePathLength;+ Private-
DevicePath = DevicePath;+ Private->PortBitMap = PortBitMap;+
InitializeListHead (&Private->DeviceList);++ Status = AhciModeInitialization
(Private); if (EFI_ERROR (Status)) {- DEBUG ((DEBUG_ERROR, "%a: Failed to
locate AtaAhciHostControllerPpi.\n", __FUNCTION__));- return
EFI_UNSUPPORTED;+ return Status;+ }++ Private-
AtaPassThruMode.Attributes =
EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL |+
EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL;+ Private-
AtaPassThruMode.IoAlign = sizeof (UINTN);+ Private-
AtaPassThruPpi.Revision = EDKII_PEI_ATA_PASS_THRU_PPI_REVISION;+
Private->AtaPassThruPpi.Mode = &Private->AtaPassThruMode;+
Private->AtaPassThruPpi.PassThru = AhciAtaPassThruPassThru;+ Private-
AtaPassThruPpi.GetNextPort = AhciAtaPassThruGetNextPort;+ Private-
AtaPassThruPpi.GetNextDevice = AhciAtaPassThruGetNextDevice;+
Private->AtaPassThruPpi.GetDevicePath = AhciAtaPassThruGetDevicePath;+
CopyMem (+ &Private->AtaPassThruPpiList,+
&mAhciAtaPassThruPpiListTemplate,+ sizeof
(EFI_PEI_PPI_DESCRIPTOR)+ );+ Private->AtaPassThruPpiList.Ppi =
&Private->AtaPassThruPpi;+ PeiServicesInstallPpi (&Private-
AtaPassThruPpiList);++ Private->BlkIoPpi.GetNumberOfBlockDevices =
AhciBlockIoGetDeviceNo;+ Private->BlkIoPpi.GetBlockDeviceMediaInfo =
AhciBlockIoGetMediaInfo;+ Private->BlkIoPpi.ReadBlocks =
AhciBlockIoReadBlocks;+ CopyMem (+ &Private->BlkIoPpiList,+
&mAhciBlkIoPpiListTemplate,+ sizeof (EFI_PEI_PPI_DESCRIPTOR)+ );+
Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;+ PeiServicesInstallPpi
(&Private->BlkIoPpiList);++ Private->BlkIo2Ppi.Revision =
EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;+ Private-
BlkIo2Ppi.GetNumberOfBlockDevices = AhciBlockIoGetDeviceNo2;+
Private->BlkIo2Ppi.GetBlockDeviceMediaInfo = AhciBlockIoGetMediaInfo2;+
Private->BlkIo2Ppi.ReadBlocks = AhciBlockIoReadBlocks2;+ CopyMem
(+ &Private->BlkIo2PpiList,+ &mAhciBlkIo2PpiListTemplate,+ sizeof
(EFI_PEI_PPI_DESCRIPTOR)+ );+ Private->BlkIo2PpiList.Ppi = &Private-
BlkIo2Ppi;+ PeiServicesInstallPpi (&Private->BlkIo2PpiList);++ if (Private-
TrustComputingDevices != 0) {+ DEBUG ((+ DEBUG_INFO,+ "%a:
Security Security Command PPI will be produced.\n",+
__FUNCTION__+ ));+ Private->StorageSecurityPpi.Revision =
EDKII_STORAGE_SECURITY_PPI_REVISION;+ Private-
StorageSecurityPpi.GetNumberofDevices =
AhciStorageSecurityGetDeviceNo;+ Private-
StorageSecurityPpi.GetDevicePath =
AhciStorageSecurityGetDevicePath;+ Private-
StorageSecurityPpi.ReceiveData = AhciStorageSecurityReceiveData;+
Private->StorageSecurityPpi.SendData =
AhciStorageSecuritySendData;+ CopyMem (+ &Private-
StorageSecurityPpiList,+ &mAhciStorageSecurityPpiListTemplate,+
sizeof (EFI_PEI_PPI_DESCRIPTOR)+ );+ Private-
StorageSecurityPpiList.Ppi = &Private->StorageSecurityPpi;+
PeiServicesInstallPpi (&Private->StorageSecurityPpiList); } + CopyMem (+
&Private->EndOfPeiNotifyList,+ &mAhciEndOfPeiNotifyListTemplate,+
sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)+ );+ PeiServicesNotifyPpi (&Private-
EndOfPeiNotifyList);++ return EFI_SUCCESS;+}++/**+ Initialize AHCI
controller from EDKII_ATA_AHCI_HOST_CONTROLLER_PPI instance.++
@param[in] AhciHcPpi Pointer to the AHCI Host Controller PPI instance.++
@retval EFI_SUCCESS PPI successfully
installed.+**/+EFI_STATUS+AtaAhciInitPrivateDataFromHostControllerPpi (+
IN EDKII_ATA_AHCI_HOST_CONTROLLER_PPI *AhciHcPpi+ )+{+ UINT8
Controller;+ UINTN MmioBase;+ UINTN
DevicePathLength;+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;+
EFI_STATUS Status;+ Controller = 0; MmioBase = 0; while (TRUE)
{@@ -193,65 +373,7 @@ AtaAhciPeimEntry (
return Status; } - //- // Check validity of the device path of the ATA
AHCI controller.- //- Status = AhciIsHcDevicePathValid (DevicePath,
DevicePathLength);- if (EFI_ERROR (Status)) {- DEBUG ((-
DEBUG_ERROR,- "%a: The device path is invalid for Controller %d.\n",-
__FUNCTION__,- Controller- ));- Controller++;- continue;- }--
//- // For S3 resume performance consideration, not all ports on an ATA
AHCI- // controller will be enumerated/initialized. The driver consumes the-
// content within S3StorageDeviceInitList LockBox to get the ports that- //
will be enumerated/initialized during S3 resume.- //- if (BootMode ==
BOOT_ON_S3_RESUME) {- NumberOfPorts = AhciS3GetEumeratePorts
(DevicePath, DevicePathLength, &PortBitMap);- if (NumberOfPorts == 0)
{- //- // No ports need to be enumerated for this controller.- //-
Controller++;- continue;- }- } else {- PortBitMap = MAX_UINT32;-
}-- //- // Memory allocation for controller private data.- //- Private =
AllocateZeroPool (sizeof (PEI_AHCI_CONTROLLER_PRIVATE_DATA));- if
(Private == NULL) {- DEBUG ((- DEBUG_ERROR,- "%a: Fail to allocate
private data for Controller %d.\n",- __FUNCTION__,- Controller-
));- return EFI_OUT_OF_RESOURCES;- }-- //- // Initialize controller
private data.- //- Private->Signature =
AHCI_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;- Private->MmioBase
= MmioBase;- Private->DevicePathLength = DevicePathLength;- Private-
DevicePath = DevicePath;- Private->PortBitMap = PortBitMap;-
InitializeListHead (&Private->DeviceList);-- Status = AhciModeInitialization
(Private);+ Status = AtaAhciInitPrivateData (MmioBase, DevicePath,
DevicePathLength); if (EFI_ERROR (Status)) { DEBUG
(( DEBUG_ERROR,@@ -260,86 +382,229 @@ AtaAhciPeimEntry (
Controller, Status ));- Controller++;- continue;- }--
Private->AtaPassThruMode.Attributes =
EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL |-
EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL;- Private-
AtaPassThruMode.IoAlign = sizeof (UINTN);- Private-
AtaPassThruPpi.Revision = EDKII_PEI_ATA_PASS_THRU_PPI_REVISION;-
Private->AtaPassThruPpi.Mode = &Private->AtaPassThruMode;-
Private->AtaPassThruPpi.PassThru = AhciAtaPassThruPassThru;- Private-
AtaPassThruPpi.GetNextPort = AhciAtaPassThruGetNextPort;- Private-
AtaPassThruPpi.GetNextDevice = AhciAtaPassThruGetNextDevice;-
Private->AtaPassThruPpi.GetDevicePath = AhciAtaPassThruGetDevicePath;-
CopyMem (- &Private->AtaPassThruPpiList,-
&mAhciAtaPassThruPpiListTemplate,- sizeof (EFI_PEI_PPI_DESCRIPTOR)-
);- Private->AtaPassThruPpiList.Ppi = &Private->AtaPassThruPpi;-
PeiServicesInstallPpi (&Private->AtaPassThruPpiList);-- Private-
BlkIoPpi.GetNumberOfBlockDevices = AhciBlockIoGetDeviceNo;- Private-
BlkIoPpi.GetBlockDeviceMediaInfo = AhciBlockIoGetMediaInfo;- Private-
BlkIoPpi.ReadBlocks = AhciBlockIoReadBlocks;- CopyMem (-
&Private->BlkIoPpiList,- &mAhciBlkIoPpiListTemplate,- sizeof
(EFI_PEI_PPI_DESCRIPTOR)- );- Private->BlkIoPpiList.Ppi = &Private-
BlkIoPpi;- PeiServicesInstallPpi (&Private->BlkIoPpiList);-- Private-
BlkIo2Ppi.Revision =
EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;- Private-
BlkIo2Ppi.GetNumberOfBlockDevices = AhciBlockIoGetDeviceNo2;-
Private->BlkIo2Ppi.GetBlockDeviceMediaInfo = AhciBlockIoGetMediaInfo2;-
Private->BlkIo2Ppi.ReadBlocks = AhciBlockIoReadBlocks2;- CopyMem
(- &Private->BlkIo2PpiList,- &mAhciBlkIo2PpiListTemplate,- sizeof
(EFI_PEI_PPI_DESCRIPTOR)- );- Private->BlkIo2PpiList.Ppi = &Private-
BlkIo2Ppi;- PeiServicesInstallPpi (&Private->BlkIo2PpiList);-- if (Private-
TrustComputingDevices != 0) {+ } else { DEBUG (( DEBUG_INFO,-
"%a: Security Security Command PPI will be produced for Controller %d.\n",+
"%a: Controller %d has been successfully initialized.\n", __FUNCTION__,
Controller ));- Private->StorageSecurityPpi.Revision =
EDKII_STORAGE_SECURITY_PPI_REVISION;- Private-
StorageSecurityPpi.GetNumberofDevices =
AhciStorageSecurityGetDeviceNo;- Private-
StorageSecurityPpi.GetDevicePath =
AhciStorageSecurityGetDevicePath;- Private-
StorageSecurityPpi.ReceiveData = AhciStorageSecurityReceiveData;-
Private->StorageSecurityPpi.SendData = AhciStorageSecuritySendData;-
CopyMem (- &Private->StorageSecurityPpiList,-
&mAhciStorageSecurityPpiListTemplate,- sizeof
(EFI_PEI_PPI_DESCRIPTOR)- );- Private->StorageSecurityPpiList.Ppi =
&Private->StorageSecurityPpi;- PeiServicesInstallPpi (&Private-
StorageSecurityPpiList); } - CopyMem (- &Private-
EndOfPeiNotifyList,- &mAhciEndOfPeiNotifyListTemplate,- sizeof
(EFI_PEI_NOTIFY_DESCRIPTOR)- );- PeiServicesNotifyPpi (&Private-
EndOfPeiNotifyList);-- DEBUG ((- DEBUG_INFO,- "%a: Controller %d
has been successfully initialized.\n",- __FUNCTION__,- Controller- ));
Controller++; } return EFI_SUCCESS; }++/**+ Callback for
EDKII_ATA_AHCI_HOST_CONTROLLER_PPI installation.++ @param[in]
PeiServices Pointer to PEI Services Table.+ @param[in] NotifyDescriptor
Pointer to the descriptor for the Notification+ event that
caused this function to execute.+ @param[in] Ppi Pointer to the PPI
data associated with this function.++ @retval EFI_SUCCESS The
function completes successfully+ @retval Others Cannot initialize
AHCI controller for given
device+**/+EFI_STATUS+EFIAPI+AtaAhciHostControllerPpiInstallationCallbac
k (+ IN EFI_PEI_SERVICES **PeiServices,+ IN
EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,+ IN VOID
*Ppi+ )+{+ EDKII_ATA_AHCI_HOST_CONTROLLER_PPI *AhciHcPpi;++ if (Ppi
== NULL) {+ return EFI_INVALID_PARAMETER;+ }++ AhciHcPpi =
(EDKII_ATA_AHCI_HOST_CONTROLLER_PPI *)Ppi;++ return
AtaAhciInitPrivateDataFromHostControllerPpi (AhciHcPpi);+}++/**+ Initialize
AHCI controller from fiven PCI_DEVICE_PPI.++ @param[in] PciDevice
Pointer to the PCI Device PPI instance.++ @retval EFI_SUCCESS The
function completes successfully+ @retval Others Cannot initialize AHCI
controller for given
device+**/+EFI_STATUS+AtaAhciInitPrivateDataFromPciDevice (+
EDKII_PCI_DEVICE_PPI *PciDevice+ )+{+ EFI_STATUS Status;+
PCI_TYPE00 PciData;+ UINTN MmioBase;+
EFI_DEVICE_PATH_PROTOCOL *DevicePath;+ UINTN
DevicePathLength;++ //+ // Now further check the PCI header: Base Class
(offset 0x0B) and+ // Sub Class (offset 0x0A). This controller should be an
SATA controller+ //+ Status = PciDevice->PciIo.Pci.Read (+
&PciDevice->PciIo,+ EfiPciIoWidthUint8,+
PCI_CLASSCODE_OFFSET,+ sizeof (PciData.Hdr.ClassCode),+
PciData.Hdr.ClassCode+ );+ if (EFI_ERROR (Status)) {+
return EFI_UNSUPPORTED;+ }++ if (!IS_PCI_IDE (&PciData)
&& !IS_PCI_SATADPA (&PciData)) {+ return EFI_UNSUPPORTED;+ }++
Status = PciDevice->PciIo.Attributes (+ &PciDevice->PciIo,+
EfiPciIoAttributeOperationSet,+ EFI_PCI_DEVICE_ENABLE,+
NULL+ );+ if (EFI_ERROR (Status)) {+ return
EFI_UNSUPPORTED;+ }++ Status = PciDevice->PciIo.Pci.Read (+
&PciDevice->PciIo,+ EfiPciIoWidthUint32,+
0x24,+ sizeof (UINTN),+
&MmioBase+ );+ if (EFI_ERROR (Status)) {+ return
EFI_UNSUPPORTED;+ }++ DevicePathLength = GetDevicePathSize
(PciDevice->DevicePath);+ DevicePath = PciDevice->DevicePath;++
Status = AtaAhciInitPrivateData (MmioBase, DevicePath,
DevicePathLength);+ if (EFI_ERROR (Status)) {+ DEBUG ((+
DEBUG_INFO,+ "%a: Failed to init controller, with Status - %r\n",+
__FUNCTION__,+ Status+ ));+ }++ return EFI_SUCCESS;+}++/**+
Callback for EDKII_PCI_DEVICE_PPI installation.++ @param[in] PeiServices
Pointer to PEI Services Table.+ @param[in] NotifyDescriptor Pointer to the
descriptor for the Notification+ event that caused this
function to execute.+ @param[in] Ppi Pointer to the PPI data
associated with this function.++ @retval EFI_SUCCESS The function
completes successfully+ @retval Others Cannot initialize AHCI
controller for given
device+**/+EFI_STATUS+EFIAPI+AtaAhciPciDevicePpiInstallationCallback (+
IN EFI_PEI_SERVICES **PeiServices,+ IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDescriptor,+ IN VOID *Ppi+ )+{+ EDKII_PCI_DEVICE_PPI
*PciDevice;++ PciDevice = (EDKII_PCI_DEVICE_PPI *)Ppi;++ return
AtaAhciInitPrivateDataFromPciDevice (PciDevice);+}++/**+ Initialize AHCI
controller from EDKII_ATA_AHCI_HOST_CONTROLLER_PPI instances found in
the system.++ @retval EFI_SUCCESS The function completes
successfully+**/+EFI_STATUS+AtaAhciInitPrivateDataFromPciDevices (+
VOID+ )+{+ EFI_STATUS Status;+ UINTN ControllerIndex;+
EDKII_PCI_DEVICE_PPI *PciDevice;++ Status = EFI_SUCCESS;+ for
(ControllerIndex = 0; Status != EFI_NOT_FOUND; ControllerIndex++) {+
Status = PeiServicesLocatePpi (+ &gEdkiiPeiPciDevicePpiGuid,+
ControllerIndex,+ NULL,+ (VOID **)&PciDevice+ );+ if
(EFI_ERROR (Status)) {+ continue;+ }++
AtaAhciInitPrivateDataFromPciDevice (PciDevice);++ //+ // Override the
status to continue the for loop+ //+ Status = EFI_SUCCESS;+ }++ return
EFI_SUCCESS;+}++/**+ Entry point of the PEIM.++ @param[in] FileHandle
Handle of the file being invoked.+ @param[in] PeiServices Describes the
list of possible PEI Services.++ @retval EFI_SUCCESS PPI successfully
installed.++**/+EFI_STATUS+EFIAPI+AtaAhciPeimEntry (+ IN
EFI_PEI_FILE_HANDLE FileHandle,+ IN CONST EFI_PEI_SERVICES
**PeiServices+ )+{+ EFI_STATUS Status;+
EDKII_ATA_AHCI_HOST_CONTROLLER_PPI *AhciHcPpi;++ DEBUG
((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));++ PeiServicesNotifyPpi
(&mAtaAhciHostControllerNotify);++ PeiServicesNotifyPpi
(&mPciDevicePpiNotify);++ AtaAhciInitPrivateDataFromPciDevices ();++ //+
// Locate the ATA AHCI host controller PPI.+ //+ Status =
PeiServicesLocatePpi (+ &gEdkiiPeiAtaAhciHostControllerPpiGuid,+
0,+ NULL,+ (VOID **)&AhciHcPpi+ );+ if (!EFI_ERROR
(Status)) {+ DEBUG ((DEBUG_ERROR, "%a: Using AtaAhciHostControllerPpi
to initialize private data.\n", __FUNCTION__));+ Status =
AtaAhciInitPrivateDataFromHostControllerPpi (AhciHcPpi);+ }++ return
Status;+}diff --git a/MdeModulePkg/Bus/Ata/AhciPei/DevicePath.c
b/MdeModulePkg/Bus/Ata/AhciPei/DevicePath.c
index 81f8743d40d8..cf0955929dde 100644
--- a/MdeModulePkg/Bus/Ata/AhciPei/DevicePath.c
+++ b/MdeModulePkg/Bus/Ata/AhciPei/DevicePath.c
@@ -38,50 +38,6 @@ EFI_DEVICE_PATH_PROTOCOL
mAhciEndDevicePathNodeTemplate = {
} }; -/**- Returns the 16-bit Length field of a device path node.-- Returns
the 16-bit Length field of the device path node specified by Node.- Node is
not required to be aligned on a 16-bit boundary, so it is recommended- that
a function such as ReadUnaligned16() be used to extract the contents of-
the Length field.-- If Node is NULL, then ASSERT().-- @param Node A
pointer to a device path node data structure.-- @return The 16-bit Length
field of the device path node specified by Node.--**/-UINTN-
DevicePathNodeLength (- IN CONST VOID *Node- )-{- ASSERT (Node !=
NULL);- return ReadUnaligned16 ((UINT16
*)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]);-}--/**- Returns
a pointer to the next node in a device path.-- If Node is NULL, then
ASSERT().-- @param Node A pointer to a device path node data structure.-
- @return a pointer to the device path node that follows the device path
node- specified by Node.--**/-EFI_DEVICE_PATH_PROTOCOL *-
NextDevicePathNode (- IN CONST VOID *Node- )-{- ASSERT (Node !=
NULL);- return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) +
DevicePathNodeLength (Node));-}- /** Get the size of the current device
path instance. diff --git a/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.h
b/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.h
index 43ad4639bd77..7332c4051a0c 100644
--- a/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.h
+++ b/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.h
@@ -29,6 +29,7 @@
#include <Library/BaseMemoryLib.h> #include <Library/IoLib.h> #include
<Library/TimerLib.h>+#include <Library/DevicePathLib.h> // // Structure
forward declarations@@ -631,22 +632,6 @@ TrustTransferAtaDevice (
OUT UINTN *TransferLengthOut ); -/**- Returns a pointer to
the next node in a device path.-- If Node is NULL, then ASSERT().-- @param
Node A pointer to a device path node data structure.-- @return a pointer
to the device path node that follows the device path node- specified by
Node.--**/-EFI_DEVICE_PATH_PROTOCOL *-NextDevicePathNode (- IN
CONST VOID *Node- );- /** Get the size of the current device path
instance. diff --git a/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.inf
b/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.inf
index 912ff7a8ba4f..788660b33299 100644
--- a/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.inf
+++ b/MdeModulePkg/Bus/Ata/AhciPei/AhciPei.inf
@@ -50,11 +50,13 @@ [LibraryClasses]
TimerLib LockBoxLib PeimEntryPoint+ DevicePathLib [Ppis]
gEdkiiPeiAtaAhciHostControllerPpiGuid ## CONSUMES
gEdkiiIoMmuPpiGuid ## CONSUMES
gEfiEndOfPeiSignalPpiGuid ## CONSUMES+
gEdkiiPeiPciDevicePpiGuid ## CONSUMES
gEdkiiPeiAtaPassThruPpiGuid ## SOMETIMES_PRODUCES
gEfiPeiVirtualBlockIoPpiGuid ## SOMETIMES_PRODUCES
gEfiPeiVirtualBlockIo2PpiGuid ## SOMETIMES_PRODUCES@@ -65,8
+67,7 @@ [Guids]
[Depex] gEfiPeiMemoryDiscoveredPpiGuid AND-
gEfiPeiMasterBootModePpiGuid AND-
gEdkiiPeiAtaAhciHostControllerPpiGuid+ gEfiPeiMasterBootModePpiGuid
[UserExtensions.TianoCore."ExtraFiles"] AhciPeiExtra.unidiff --git
a/MdeModulePkg/MdeModulePkg.dsc
b/MdeModulePkg/MdeModulePkg.dsc
index 90a0a7ec4a7c..45a8ec84ad69 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -117,6 +117,7 @@ [LibraryClasses.common.PEIM]

MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemory
AllocationLib.inf
ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiEx
tractGuidedSectionLib.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
+
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibBase.i
nf [LibraryClasses.common.DXE_CORE]
HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf--
2.27.0.windows.1


Re: [edk2-staging][PATCH v3 10/15] edk2-staging/RedfishClientPkg: Update Redfish feature utility library

Chang, Abner
 

[AMD Official Use Only - General]

BTW, you don't have to resend the v4 for this.

Reviewed-by: Abner Chang <abner.chang@...>

-----Original Message-----
From: Chang, Abner
Sent: Thursday, July 28, 2022 11:14 AM
To: Nickle Wang <nickle.wang@...>; devel@edk2.groups.io
Cc: Yang, Atom <Atom.Yang@...>; Nick Ramirez
<nramirez@...>
Subject: RE: [edk2-staging][PATCH v3 10/15] edk2-staging/RedfishClientPkg:
Update Redfish feature utility library

[AMD Official Use Only - General]

Please search [Chang, Abner] for the comment.

-----Original Message-----
From: Nickle Wang <nickle.wang@...>
Sent: Wednesday, July 27, 2022 9:38 AM
To: devel@edk2.groups.io
Cc: Chang, Abner <Abner.Chang@...>; Yang, Atom
<Atom.Yang@...>; Nick Ramirez <nramirez@...>
Subject: [edk2-staging][PATCH v3 10/15] edk2-staging/RedfishClientPkg:
Update Redfish feature utility library

[CAUTION: External Email]

Update Redfish feature utility library in order to support array type
of resource. Some helper functions are introduced to get Redfish data.
Also expose RedfishCsCommon.h so that feature utility library can work
with Redfish C data structure without redundant structure conversion.

Signed-off-by: Nickle Wang <nickle.wang@...>
Cc: Abner Chang <abner.chang@...>
Cc: Yang Atom <Atom.Yang@...>
Cc: Nick Ramirez <nramirez@...>
---
.../Library/RedfishFeatureUtilityLib.h | 756 +++-
.../RedfishJsonStructure/RedfishCsCommon.h | 14 +
.../RedfishFeatureUtilityInternal.h | 16 +-
.../RedfishFeatureUtilityLib.c | 3662 +++++++++++++----
.../RedfishFeatureUtilityLib.inf | 20 +-
5 files changed, 3470 insertions(+), 998 deletions(-)
create mode 100644
RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h

diff --git a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
index 50ff82c70f..1325976d8c 100644
--- a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
+++ b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
@@ -1,7 +1,7 @@
/** @file
This file defines the Redfish Feature Utility Library interface.

- (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2021-2022 Hewlett Packard Enterprise Development
LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -10,8 +10,9 @@
#ifndef REDFISH_FEATURE_UTILITY_LIB_H_
#define REDFISH_FEATURE_UTILITY_LIB_H_

-#include <Protocol/EdkIIRedfishResourceConfigProtocol.h>
-#include <Protocol/RestJsonStructure.h>
+#include <Library/RedfishLib.h>
+#include <Protocol/EdkIIRedfishPlatformConfig.h>
+#include <RedfishJsonStructure/RedfishCsCommon.h>

//
// Definition of REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
@@ -31,10 +32,10 @@ typedef struct {

/**

- Read redfish resource by given resource path.
+ Read redfish resource by given resource URI.

@param[in] Service Redfish srvice instacne to make query.
- @param[in] ResourcePath Target resource path.
+ @param[in] ResourceUri Target resource URI.
@param[out] Response HTTP response from redfish service.

@retval EFI_SUCCESS Resrouce is returned successfully.
@@ -42,12 +43,34 @@ typedef struct {

**/
EFI_STATUS
-GetResourceByPath (
+GetResourceByUri (
IN REDFISH_SERVICE *Service,
- IN CHAR8 *ResourcePath,
+ IN EFI_STRING ResourceUri,
OUT REDFISH_RESPONSE *Response
);

+/**
+
+ Check if this is the Redpath array. Usually the Redpath array represents
+ the collection member. Return
+
+ @param[in] ConfigureLang The Redpath to check
+ @param[out] ArraySignatureOpen String to the open of array
signature.
+ @param[out] ArraySignatureClose String to the close of array
signature.
+
+ @retval EFI_SUCCESS Index is found.
+ @retval EFI_NOT_FOUND The non-array configure language string
is
retured.
+ @retval EFI_INVALID_PARAMETER The format of input ConfigureLang
is
wrong.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+IsRedpathArray (
+ IN EFI_STRING ConfigureLang,
+ OUT EFI_STRING *ArraySignatureOpen,
+ OUT EFI_STRING *ArraySignatureClose
+ );
+
/**

Search HII database with given Configure Language pattern. Data is
handled
and
@@ -72,76 +95,142 @@
RedfishFeatureGetUnifiedArrayTypeConfigureLang (

/**

- Get array key by parsing the URI.
+ Clone the configure language list.

- @param[in] Uri URI with array key.
- @param[out] ArrayKey Array key in given URI string.
+ @param[in] ConfigureLangList The source
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
+ @param[out] DestConfigureLangList The destination
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.

- @retval EFI_SUCCESS Array key is found.
- @retval Others Errors occur.
+ @retval EFI_SUCCESS
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
+ @retval Others Errors occur.

**/
EFI_STATUS
-GetArraykeyFromUri (
- IN CHAR8 *Uri,
- OUT CHAR8 **ArrayKey
+CopyConfiglanguageList (
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*SourceConfigureLangList,
+ OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*DestConfigureLangList
);

/**

- Keep configure language with given key in UEFI variable.
+ Get number of node from the string. Node is seperated by '/'.

- @param[in] Schema Schema name.
- @param[in] Version Schema version.
- @param[in] Key Key string.
- @param[in] ConfigureLangIndex Index value.
+ @param[in] NodeString The node string to parse.

- @retval EFI_SUCCESS Data is saved in UEFI variable.
- @retval Others Errors occur.
+ @retval UINTN Number of nodes in the string.
+
+**/
+UINTN
+GetNumberOfRedpathNodes (
+ IN EFI_STRING NodeString
+ );
+
+/**
+
+ Get the node string by index
+
+ @param[in] NodeString The node string to parse.
+ @param[in] Index Index of the node.
+ @param[out] EndOfNodePtr Pointer to receive the poitner to
+ the last character of node string.
+
+ @retval EFI_STRING the begining of the node string.
+
+**/
+EFI_STRING
+GetRedpathNodeByIndex (
+ IN EFI_STRING NodeString,
+ IN UINTN Index,
+ OUT EFI_STRING *EndOfNodePtr OPTIONAL
+ );
+
+/**
+
+ Find array index from given configure language string.
+
+ @param[in] ConfigureLang Configure language string to parse.
+ @param[out] UnifiedConfigureLang The configure language in array.
+ @param[out] Index The array index number.
+
+ @retval EFI_SUCCESS Index is found.
+ @retval EFI_NOT_FOUND The non-array configure language string
is
retured.
+ @retval EFI_INVALID_PARAMETER The format of input ConfigureLang
is
wrong.
+ @retval Others Errors occur.

**/
EFI_STATUS
-SetConfigureLangWithkey (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN CHAR8 *Key,
- IN UINTN ConfigureLangIndex
+GetArrayIndexFromArrayTypeConfigureLang (
+ IN CHAR16 *ConfigureLang,
+ OUT CHAR16 **UnifiedConfigureLang,
+ OUT UINTN *Index
);

/**

- Find configure language with input key string.
+ Clone the configure language list.
+
+ @param[in] ConfigureLang The pointer to configuration language.

- @param[in] Schema Schema name.
- @param[in] Version Schema version.
- @param[in] Property Property name.
- @param[in] Key Key string.
+ @retval UINTN The index of collection member instance.
+ Value of 0 means no instance is found.
+**/
+UINTN
+ConfiglanguageGetInstanceIndex (
+ IN EFI_STRING ConfigureLang
+ );

- @retval CHAR16 * Corresponding configure langauge
- @retval NULL No configure language is found
+/**
+
+ Destroy the configure language list.
+
+ @param[in] ConfigureLangList The
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
+ instance to destroy.
+
+ @retval EFI_SUCCESS
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
+ @retval Others Errors occur.

**/
-CHAR16 *
-GetConfigureLangByKey (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN CHAR8 *Property,
- IN CHAR8 *Key
+EFI_STATUS
+DestroyConfiglanguageList (
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*ConfigureLangList
);

/**

- Convert HII string value to string value in JSON format.
+ Set the node instance.

- @param[in] HiiStringValue String in HII format.
+ @param[in] DestConfigLang Pointer to the node's configure
language
string.
+ The memory pointed by ConfigLang must be allocated
+ through memory allocation interface. Becasue we will
replace
+ the pointer in this function.
+ @param[in] MaxtLengthConfigLang The maximum length of ConfigLang.
+ @param[in] ConfigLangInstance Pointer to Collection member instance.

- @retval CHAR8 * String in JSON format.
- @retval NULL Errors occur.
+ @retval EFI_SUCCESS The instance is inserted to the configure
language.
+ @retval Others Errors occur.

**/
-CHAR8 *
-ConvertHiiStringValueToJsonStringValue (
- IN EFI_STRING HiiStringValue
+EFI_STATUS
+SetResourceConfigLangMemberInstance (
+ IN EFI_STRING *DestConfigLang,
+ IN UINTN MaxtLengthConfigLang,
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
*ConfigLangInstance
+ );
+
+/**
+
+ Get array key by parsing the URI.
+
+ @param[in] Uri URI with array key.
+ @param[out] ArrayKey Array key in given URI string.
+
+ @retval EFI_SUCCESS Array key is found.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+GetArraykeyFromUri (
+ IN CHAR8 *Uri,
+ OUT CHAR8 **ArrayKey
);

/**
@@ -209,125 +298,157 @@ ApplyFeatureSettingsBooleanType (

/**

- Create HTTP payload and send them to redfish service with POST method.
+ Apply property value to UEFI HII database in vague type.

- @param[in] Service Redfish service.
- @param[in] TargetPayload Target payload
- @param[in] Json Data in JSON format.
- @param[out] Location Returned location string from Redfish service.
- @param[out] Etag Returned ETAG string from Redfish service.
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] VagueValuePtr Pointer of vague values to to set.
+ @param[in] NumVagueValues Number of vague values.

- @retval EFI_SUCCESS Data is sent to redfish service successfully.
+ @retval EFI_SUCCESS New value is applied successfully.
@retval Others Errors occur.

**/
EFI_STATUS
-CreatePayloadToPostResource (
- IN REDFISH_SERVICE *Service,
- IN REDFISH_PAYLOAD *TargetPayload,
- IN CHAR8 *Json,
- OUT CHAR8 **Location,
- OUT CHAR8 **Etag
+ApplyFeatureSettingsVagueType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_EmptyProp_KeyValue *VagueValuePtr,
+ IN UINT32 NumberOfVagueValues
);

/**

- Create HTTP payload and send them to redfish service with PATCH
method.
+ Apply property value to UEFI HII database in string array type.

- @param[in] Service Redfish service.
- @param[in] TargetPayload Target payload
- @param[in] Json Data in JSON format.
- @param[out] Etag Returned ETAG string from Redfish service.
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] ArrayHead Head of array value.

- @retval EFI_SUCCESS Data is sent to redfish service successfully.
+ @retval EFI_SUCCESS New value is applied successfully.
@retval Others Errors occur.

**/
EFI_STATUS
-CreatePayloadToPatchResource (
- IN REDFISH_SERVICE *Service,
- IN REDFISH_PAYLOAD *TargetPayload,
- IN CHAR8 *Json,
- OUT CHAR8 **Etag
+ApplyFeatureSettingsStringArrayType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_char_Array *ArrayHead
);

/**

- Find Redfish Resource Config Protocol that supports given schema and
version.
+ Apply property value to UEFI HII database in numeric array type (INT64).

- @param[in] Schema Schema name.
- @param[in] Major Schema version major number.
- @param[in] Minor Schema version minor number.
- @param[in] Errata Schema version errata number.
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] ArrayHead Head of array value.

- @retval EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL * Pointer to
protocol
- @retval NULL No protocol found.
+ @retval EFI_SUCCESS New value is applied successfully.
+ @retval Others Errors occur.

**/
-EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *
-GetRedfishResourceConfigProtocol (
- IN CHAR8 *Schema,
- IN CHAR8 *Major,
- IN CHAR8 *Minor,
- IN CHAR8 *Errata
+EFI_STATUS
+ApplyFeatureSettingsNumericArrayType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_int64_Array *ArrayHead
);

/**

- Get supported schema list by given specify schema name.
+ Apply property value to UEFI HII database in boolean array type (INT64).

- @param[in] Schema Schema type name.
- @param[out] SchemaInfo Returned schema information.
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] ArrayHead Head of Redfich CS boolean array value.

- @retval EFI_SUCCESS Schema information is returned successfully.
- @retval Others Errors occur.
+ @retval EFI_SUCCESS New value is applied successfully.
+ @retval Others Errors occur.

**/
EFI_STATUS
-GetSupportedSchemaVersion (
- IN CHAR8 *Schema,
- OUT REDFISH_SCHEMA_INFO *SchemaInfo
+ApplyFeatureSettingsBooleanArrayType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_bool_Array *ArrayHead
);

/**

- Return system root path
+ Create HTTP payload and send them to redfish service with POST
method.
+
+ @param[in] Service Redfish service.
+ @param[in] TargetPayload Target payload
+ @param[in] Json Data in JSON format.
+ @param[out] Location Returned location string from Redfish service.
+ @param[out] Etag Returned ETAG string from Redfish service.

- @retval NULL Can not find system root path.
- @retval Other System root path is returned.
+ @retval EFI_SUCCESS Data is sent to redfish service successfully.
+ @retval Others Errors occur.

**/
-CHAR8 *
-RedfishGetSystemRootPath (
- VOID
+EFI_STATUS
+CreatePayloadToPostResource (
+ IN REDFISH_SERVICE *Service,
+ IN REDFISH_PAYLOAD *TargetPayload,
+ IN CHAR8 *Json,
+ OUT EFI_STRING *Location,
+ OUT CHAR8 **Etag
);

/**

- Get schema information by given protocol and service instance.
+ Create HTTP payload and send them to redfish service with PATCH
method.

- @param[in] RedfishService Pointer to Redfish service instance.
- @param[in] JsonStructProtocol Json Structure protocol instance.
- @param[in] Uri Target URI.
- @param[out] SchemaInfo Returned schema information.
+ @param[in] Service Redfish service.
+ @param[in] TargetPayload Target payload
+ @param[in] Json Data in JSON format.
+ @param[out] Etag Returned ETAG string from Redfish service.

- @retval EFI_SUCCESS Schema information is returned successfully.
- @retval Others Errors occur.
+ @retval EFI_SUCCESS Data is sent to redfish service successfully.
+ @retval Others Errors occur.

**/
EFI_STATUS
-GetRedfishSchemaInfo (
- IN REDFISH_SERVICE *RedfishService,
- IN EFI_REST_JSON_STRUCTURE_PROTOCOL *JsonStructProtocol,
- IN CHAR8 *Uri,
- OUT REDFISH_SCHEMA_INFO *SchemaInfo
+CreatePayloadToPatchResource (
+ IN REDFISH_SERVICE *Service,
+ IN REDFISH_PAYLOAD *TargetPayload,
+ IN CHAR8 *Json,
+ OUT CHAR8 **Etag
+ );
+
+/**
+
+ Save Redfish URI in database for further use.
+
+ @param[in] ConfigLang ConfigLang to save
+ @param[in] Uri Redfish Uri to save
+
+ @retval EFI_INVALID_PARAMETR SystemId is NULL or EMPTY
+ @retval EFI_SUCCESS Redfish uri is saved
+
+**/
+EFI_STATUS
+RedfisSetRedfishUri (
+ IN EFI_STRING ConfigLang,
+ IN EFI_STRING Uri
);

/**

Get the property name by given Configure Langauge.

- @param[in] ConfigureLang Configure Language string.
+ @param[in] ResourceUri URI of root of resource.
+ @param[in] ConfigureLang Configure Language string.

@retval EFI_STRING Pointer to property name.
@retval NULL There is error.
@@ -335,6 +456,7 @@ GetRedfishSchemaInfo (
**/
EFI_STRING
GetPropertyFromConfigureLang (
+ IN EFI_STRING ResourceUri,
IN EFI_STRING ConfigureLang
);

@@ -417,25 +539,6 @@ PropertyChecker (
IN BOOLEAN ProvisionMode
);

-/**
-
- Check and see if we need to do provisioning for this two properties.
-
- @param[in] PropertyBuffer1 Pointer to property instance 1.
- @param[in] PropertyBuffer2 Pointer to property instance 2.
- @param[in] ProvisionMode TRUE if we are in provision mode. FALSE
otherwise.
-
- @retval TRUE Provision is required.
- @retval FALSE Provision is not required.
-
-**/
-BOOLEAN
-PropertyChecker2Parm (
- IN VOID *PropertyBuffer1,
- IN VOID *PropertyBuffer2,
- IN BOOLEAN ProvisionMode
- );
-
/**

Keep ETAG string and URI string in database.
@@ -450,7 +553,7 @@ PropertyChecker2Parm (
EFI_STATUS
SetEtagWithUri (
IN CHAR8 *EtagStr,
- IN CHAR8 *Uri
+ IN EFI_STRING Uri
);

/**
@@ -465,7 +568,396 @@ SetEtagWithUri (
**/
CHAR8 *
GetEtagWithUri (
- IN CHAR8 *Uri
+ IN EFI_STRING Uri
+ );
+
+/**
+
+ Get @odata.id from give HTTP payload. It's call responsibility to release
returned buffer.
+
+ @param[in] Payload HTTP payload
+
+ @retval NULL Can not find @odata.id from given payload.
+ @retval Others odata.id string is returned.
+
+**/
+EFI_STRING
+GetOdataId (
+ IN REDFISH_PAYLOAD *Payload
+ );
+
+/**
+
+ Return config language from given URI and prperty name. It's call
responsibility to release returned buffer.
+
+ @param[in] Uri The URI to match
+ @param[in] PropertyName The property name of resource. This is
optional.
+
+ @retval NULL Can not find redfish uri.
+ @retval Other redfish uri is returned.
+
+**/
+EFI_STRING
+GetConfigureLang (
+ IN CHAR8 *Uri,
+ IN CHAR8 *PropertyName OPTIONAL
+ );
+
+/**
+
+ Return redfish URI by given config language. It's call responsibility to
release returned buffer.
+
+ @param[in] ConfigLang ConfigLang to search.
+
+ @retval NULL Can not find redfish uri.
+ @retval Other redfish uri is returned.
+
+**/
+EFI_STRING
+RedfishGetUri (
+ IN EFI_STRING ConfigLang
+ );
+
+/**
+
+ Return config language by given URI. It's call responsibility to release
returned buffer.
+
+ @param[in] Uri Uri to search.
+
+ @retval NULL Can not find redfish uri.
+ @retval Other redfish uri is returned.
+
+**/
+EFI_STRING
+RedfishGetConfigLanguage (
+ IN EFI_STRING Uri
+ );
+
+/**
+
+ Convert Unicode string to ASCII string. It's call responsibility to release
returned buffer.
+
+ @param[in] UnicodeStr Unicode string to convert.
+
+ @retval CHAR8 * ASCII string returned.
+ @retval NULL Errors occur.
+
+**/
+CHAR8 *
+StrUnicodeToAscii (
+ IN EFI_STRING UnicodeStr
+ );
+
+/**
+
+ Convert ASCII string to Unicode string. It's call responsibility to release
returned buffer.
+
+ @param[in] AsciiStr ASCII string to convert.
+
+ @retval EFI_STRING Unicode string returned.
+ @retval NULL Errors occur.
+
+**/
+EFI_STRING
+StrAsciiToUnicode (
+ IN CHAR8 *AsciiStr
+ );
+
+/**
+
+ Check and see if ETAG is identical to what we keep in system.
+
+ @param[in] Uri URI requested
+ @param[in] EtagInHeader ETAG string returned from HTTP request.
+ @param[in] EtagInJson ETAG string in JSON body.
+
+ @retval TRUE ETAG is identical.
+ @retval FALSE ETAG is changed.
+
+**/
+BOOLEAN
+CheckEtag (
+ IN EFI_STRING Uri,
+ IN CHAR8 *EtagInHeader,
+ IN CHAR8 *EtagInJson
+ );
+
+/**
+
+ Get the property string value in array type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] ArraySize The size of returned array.
+
+ @retval CHAR8 ** Returned string array. NULL while error happens.
+
+**/
+CHAR8 **
+GetPropertyStringArrayValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
+ );
+
+/**
+
+ Get the property numeric value in array type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] ArraySize The size of returned array.
+
+ @retval INT64 ** Returned integer array. NULL while error happens.
+
+**/
+INT64 *
+GetPropertyNumericArrayValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
+ );
+
+/**
+
+ Get the property boolean value in array type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] ArraySize The size of returned array.
+
+ @retval BOOLEAN * Returned boolean array. NULL while error
happens.
+
+**/
+BOOLEAN *
+GetPropertyBooleanArrayValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
+ );
+
+/**
+
+ Get the property value in the vague type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] NumberOfValues Return the number of vague type of
values
+
+ @retval RedfishCS_EmptyProp_KeyValue The pointer to the structure
+ of vague type of values.
+
+**/
+RedfishCS_EmptyProp_KeyValue *
+GetPropertyVagueValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINT32 *NumberOfValues
+ );
+
+/**
+
+ Free the list of empty property key values.
+
+ @param[in] EmptyPropKeyValueListHead The head of
RedfishCS_EmptyProp_KeyValue
+
+**/
+VOID
+FreeEmptyPropKeyValueList (
+ RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueListHead
+ );
+
+/**
+
+ Check and see if given property is in JSON context or not
+
+ @param[in] Property Property name string
+ @param[in] Json The JSON context to search.
+
+ @retval TRUE Property is found in JSON context
+ @retval FALSE Property is not in JSON context
+
+**/
+BOOLEAN
+MatchPropertyWithJsonContext (
+ IN EFI_STRING Property,
+ IN CHAR8 *Json
+);
+
+/**
+
+ Create string array and append to arry node in Redfish JSON convert
format.
+
+ @param[in,out] Head The head of string array.
+ @param[in] StringArray Input string array.
+ @param[in] ArraySize The size of StringArray.
+
+ @retval EFI_SUCCESS String array is created successfully.
+ @retval Others Error happens
+
+**/
+EFI_STATUS
+AddRedfishCharArray (
+ IN OUT RedfishCS_char_Array **Head,
+ IN CHAR8 **StringArray,
+ IN UINTN ArraySize
+ );
+
+/**
+
+ Create numeric array and append to arry node in Redfish JSON convert
format.
+
+ @param[in,out] Head The head of string array.
+ @param[in] NumericArray Input numeric array.
+ @param[in] ArraySize The size of StringArray.
+
+ @retval EFI_SUCCESS String array is created successfully.
+ @retval Others Error happens
+
+**/
+EFI_STATUS
+AddRedfishNumericArray (
+ IN OUT RedfishCS_int64_Array **Head,
+ IN INT64 *NumericArray,
+ IN UINTN ArraySize
+ );
+
+/**
+
+ Create boolean array and append to arry node in Redfish JSON convert
format.
+
+ @param[in,out] Head The head of string array.
+ @param[in] BooleanArray Input boolean array.
+ @param[in] ArraySize The size of BooleanArray.
+
+ @retval EFI_SUCCESS String array is created successfully.
+ @retval Others Error happens
+
+**/
+EFI_STATUS
+AddRedfishBooleanArray (
+ IN OUT RedfishCS_bool_Array **Head,
+ IN BOOLEAN *BooleanArray,
+ IN UINTN ArraySize
+ );
+/**
+
+ Check and see if value in Redfish string array are all the same as the one
+ from HII configuration.
+
+ @param[in] Head The head of string array.
+ @param[in] StringArray Input string array.
+ @param[in] ArraySize The size of StringArray.
+
+ @retval TRUE All string in Redfish array are as same as string
+ in HII configuration array.
+ FALSE These two array are not identical.
+
+**/
+BOOLEAN
+CompareRedfishStringArrayValues (
+ IN RedfishCS_char_Array *Head,
+ IN CHAR8 **StringArray,
+ IN UINTN ArraySize
+ );
+
+/**
+
+ Check and see if value in Redfish numeric array are all the same as the
one
+ from HII configuration.
+
+ @param[in] Head The head of Redfish CS numeraic array.
+ @param[in] NumericArray Input numeric array.
+ @param[in] ArraySize The size of NumericArray.
+
+ @retval TRUE All string in Redfish array are as same as integer
+ in HII configuration array.
+ FALSE These two array are not identical.
+
+**/
+BOOLEAN
+CompareRedfishNumericArrayValues (
+ IN RedfishCS_int64_Array *Head,
+ IN INT64 *NumericArray,
+ IN UINTN ArraySize
+ );
+
+/**
+
+ Check and see if value in Redfish boolean array are all the same as the
one
+ from HII configuration.
+
+ @param[in] Head The head of Redfish CS boolean array.
+ @param[in] BooleanArray Input boolean array.
+ @param[in] ArraySize The size of BooleanArray.
+
+ @retval TRUE All string in Redfish array are as same as integer
+ in HII configuration array.
+ FALSE These two array are not identical.
+
+**/
+BOOLEAN
+CompareRedfishBooleanArrayValues (
+ IN RedfishCS_bool_Array *Head,
+ IN BOOLEAN *BooleanArray,
+ IN UINTN ArraySize
+ );
+
+/**
+
+ Check and see if any difference between two vague value set.
+ This is just a simple check.
+
+ @param[in] RedfishVagueKeyValuePtr The vague key value sets on
Redfish service.
+ @param[in] RedfishVagueKeyValueNumber The numebr of vague key
value sets
+ @param[in] ConfigVagueKeyValuePtr The vague configuration on
platform.
+ @param[in] ConfigVagueKeyValueNumber The numebr of vague key
value sets
+
+ @retval TRUE All values are the same.
+ FALSE There is some difference.
+
+**/
+BOOLEAN
+CompareRedfishPropertyVagueValues (
+ IN RedfishCS_EmptyProp_KeyValue *RedfishVagueKeyValuePtr,
+ IN UINT32 RedfishVagueKeyValueNumber,
+ IN RedfishCS_EmptyProp_KeyValue *ConfigVagueKeyValuePtr,
+ IN UINT32 ConfigVagueKeyValueNumber
+ );
+
+/**
+
+ Find "ETag" and "Location" from either HTTP header or Redfish response.
+
+ @param[in] Response HTTP response
+ @param[out] Etag String buffer to return ETag
+ @param[out] Location String buffer to return Location
+
+ @retval EFI_SUCCESS Data is found and returned.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+GetEtagAndLocation (
+ IN REDFISH_RESPONSE *Response,
+ OUT CHAR8 **Etag, OPTIONAL
+ OUT EFI_STRING *Location OPTIONAL
);

#endif
diff --git
a/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h
b/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h
new file mode 100644
index 0000000000..4d0ae50fc8
--- /dev/null
+++
b/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h
@@ -0,0 +1,14 @@
+/** @file
+ Wrapper file for RedfishCsCommon.h
+
+ (C) Copyright 2021-2022 Hewlett Packard Enterprise Development
LP<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef WRAPPER_REDFISH_CS_COMMON_H_
+#define WRAPPER_REDFISH_CS_COMMON_H_
+
+#include "ConverterLib/include/RedfishCsCommon.h"
+
+#endif
diff --git
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
ernal.h
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
ernal.h
index 7d38d327ef..38d2af52b2 100644
---
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
ernal.h
+++
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
ernal.h
@@ -1,7 +1,7 @@
/** @file
Common header file for RedfishFeatureUtilityLib driver.

- (C) Copyright 2020-2021 Hewlett Packard Enterprise Development
LP<BR>
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development
LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -11,33 +11,39 @@
#define REDFISH_FEATURE_INTERNAL_H_

#include <Uefi.h>
+#include <RedfishBase.h>
+
+#include <IndustryStandard/Http11.h>

#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/JsonLib.h>
#include <Library/MemoryAllocationLib.h>
-#include <Library/PrintLib.h>
-#include <Library/PcdLib.h>
#include <Library/RedfishLib.h>
#include <Library/RedfishFeatureUtilityLib.h>
#include <Library/RedfishPlatformConfigLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HttpLib.h>

#include <Guid/VariableFormat.h>

#include <Protocol/EdkIIRedfishETagProtocol.h>
+#include <Protocol/EdkIIRedfishConfigLangMapProtocol.h>

#define INDEX_VARIABLE_SIZE 64
#define INDEX_STRING_SIZE 16
-#define IS_EMPTY_STRING(a) (a == NULL || a[0] == '\0')
#define INDEX_STRING L"{%d}"
#define SCHEMA_NAME_PREFIX "x-uefi-redfish-"
#define SCHEMA_NAME_PREFIX_OFFSET (AsciiStrLen
(SCHEMA_NAME_PREFIX))
-#define REDFISH_SYSTEM_ROOT_PATH "/v1/Systems[UUID~%g]"
+#define REDFISH_ROOT_PATH "/v1"
+#define REDFISH_ROOT_PATH_UNICODE L"/v1"
#define MAX_CONF_LANG_LEN 128
+#define MAX_REDFISH_URL_LEN 255
+#define REGULAR_EXPRESSION_ARRAY L"\\[.*\\]/.*"

#define
BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE
L"{"
#define BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE
L"}"
diff --git
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.c
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.c
index cf8696e5f0..2bd7f58f9c 100644
---
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.c
+++
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.c
@@ -1,7 +1,7 @@
/** @file
Redfish feature utility library implementation

- (C) Copyright 2020-2021 Hewlett Packard Enterprise Development
LP<BR>
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development
LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -9,7 +9,34 @@

#include "RedfishFeatureUtilityInternal.h"

-EDKII_REDFISH_ETAG_PROTOCOL *mEtagProtocol;
+EDKII_REDFISH_ETAG_PROTOCOL *mEtagProtocol = NULL;
+EDKII_REDFISH_CONFIG_LANG_MAP_PROTOCOL
*mConfigLangMapProtocol = NULL;
+
+
+EFI_STATUS
+RedfishLocateProtocol (
[Chang, Abner]
The function header is missed.
Abner

+ IN VOID **ProtocolInstance,
+ IN EFI_GUID *ProtocolGuid
+ )
+{
+ EFI_STATUS Status;
+
+ if (ProtocolInstance == NULL || ProtocolGuid == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*ProtocolInstance != NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = gBS->LocateProtocol (
+ ProtocolGuid,
+ NULL,
+ ProtocolInstance
+ );
+ return Status;
+}
+

/**

@@ -71,227 +98,168 @@ GetArraykeyFromUri (

/**

- Keep configure language with given key in UEFI variable.
+ Keep ETAG string and URI string in database.

- @param[in] Schema Schema name.
- @param[in] Version Schema version.
- @param[in] Key Key string.
- @param[in] ConfigureLangIndex Index value.
+ @param[in] EtagStr ETAG string.
+ @param[in] Uri URI string.

- @retval EFI_SUCCESS Data is saved in UEFI variable.
- @retval Others Errors occur.
+ @retval EFI_SUCCESS ETAG and URI are applied successfully.
+ @retval Others Errors occur.

**/
EFI_STATUS
-SetConfigureLangWithkey (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN CHAR8 *Key,
- IN UINTN ConfigureLangIndex
+SetEtagWithUri (
+ IN CHAR8 *EtagStr,
+ IN EFI_STRING Uri
)
{
- CHAR16 IndexString[INDEX_STRING_SIZE];
- CHAR16 VarName[INDEX_VARIABLE_SIZE];
- CHAR16 *VarData;
- EFI_STATUS Status;
- //
- // Variable content.
- //
- UnicodeSPrint (IndexString, sizeof (IndexString), INDEX_STRING,
ConfigureLangIndex);
+ EFI_STATUS Status;
+ CHAR8 *AsciiUri;

- //
- // Variable name.
- //
- UnicodeSPrint (VarName, sizeof (VarName), L"%a_%a_%a", Schema,
Version, Key);
+ if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }

- //
- // Check if it exists already.
- //
- Status = GetVariable2 (
- VarName,
- &gEfiCallerIdGuid,
- (VOID *)&VarData,
- NULL
- );
- if (!EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "%a, remove stale data: %s\n", __FUNCTION__,
VarData));
- FreePool (VarData);
- gRT->SetVariable (VarName, &gEfiCallerIdGuid,
VARIABLE_ATTRIBUTE_NV_BS, 0, NULL);
+ Status = RedfishLocateProtocol ((VOID **)&mEtagProtocol,
&gEdkIIRedfishETagProtocolGuid);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, fail to locate
gEdkIIRedfishETagProtocolGuid: %r\n", __FUNCTION__, Status));
+ return Status;
}

- return gRT->SetVariable (VarName, &gEfiCallerIdGuid,
VARIABLE_ATTRIBUTE_NV_BS, StrSize (IndexString), (VOID
*)&IndexString);
+ AsciiUri = StrUnicodeToAscii (Uri);
+ if (AsciiUri == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mEtagProtocol->Set (mEtagProtocol, AsciiUri, EtagStr);
+ mEtagProtocol->Flush (mEtagProtocol);
+
+ FreePool (AsciiUri);
+
+ return EFI_SUCCESS;
}

/**

- Find configure language with input key string.
+ Find ETAG string that refers to given URI.

- @param[in] Schema Schema name.
- @param[in] Version Schema version.
- @param[in] Property Property name.
- @param[in] Key Key string.
+ @param[in] Uri Target URI string.

- @retval CHAR16 * Corresponding configure langauge
- @retval NULL No configure language is found
+ @retval CHAR8 * ETAG string
+ @retval NULL No ETAG is found.

**/
-CHAR16 *
-GetConfigureLangByKey (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN CHAR8 *Property, OPTIONAL
- IN CHAR8 *Key
+CHAR8 *
+GetEtagWithUri (
+ IN EFI_STRING Uri
)
{
- EFI_STATUS Status;
- CHAR16 VariableName[64];
- UINTN VariableSize;
- CHAR16 *CollectionIndex;
- CHAR16 *ConfigureLang;
- UINTN ConfigureLangLen;
+ EFI_STATUS Status;
+ CHAR8 *AsciiUri;
+ CHAR8 *EtagStr;

- if (Schema == NULL || Version == NULL || Key == NULL) {
+ if (IS_EMPTY_STRING (Uri)) {
return NULL;
}

- CollectionIndex = NULL;
- ConfigureLang = NULL;
-
- UnicodeSPrint (VariableName, 64, L"%a_%a_%a", Schema, Version, Key);
-
- Status = GetVariable2 (
- VariableName,
- &gEfiCallerIdGuid,
- (VOID *)&CollectionIndex,
- &VariableSize
- );
+ Status = RedfishLocateProtocol ((VOID **)&mEtagProtocol,
&gEdkIIRedfishETagProtocolGuid);
if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, fail to locate
gEdkIIRedfishETagProtocolGuid: %r\n", __FUNCTION__, Status));
return NULL;
}

- ConfigureLangLen = AsciiStrLen (Schema) + StrLen (CollectionIndex) +
(Property == NULL ? 0 : AsciiStrLen (Property)) + 3 + 1;
- ConfigureLang = AllocatePool (sizeof (CHAR16) * ConfigureLangLen);
- ASSERT (ConfigureLang);
-
- if (Property != NULL) {
- UnicodeSPrint (ConfigureLang, sizeof (CHAR16) * ConfigureLangLen,
L"/%a/%s/%a", Schema, CollectionIndex, Property);
- } else {
- UnicodeSPrint (ConfigureLang, sizeof (CHAR16) * ConfigureLangLen,
L"/%a/%s", Schema, CollectionIndex);
+ AsciiUri = StrUnicodeToAscii (Uri);
+ if (AsciiUri == NULL) {
+ return NULL;
}

- FreePool (CollectionIndex);
-
- return ConfigureLang;
-}
-
-/**
-
- Keep ETAG string and URI string in database.
-
- @param[in] EtagStr ETAG string.
- @param[in] Uri URI string.
-
- @retval EFI_SUCCESS ETAG and URI are applied successfully.
- @retval Others Errors occur.
-
-**/
-EFI_STATUS
-SetEtagWithUri (
- IN CHAR8 *EtagStr,
- IN CHAR8 *Uri
- )
-{
- EFI_STATUS Status;
+ Status = mEtagProtocol->Get (mEtagProtocol, AsciiUri, &EtagStr);

- if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) {
- return EFI_INVALID_PARAMETER;
- }
+ FreePool (AsciiUri);

- if (mEtagProtocol == NULL) {
- Status = gBS->LocateProtocol (
- &gEdkIIRedfishETagProtocolGuid,
- NULL,
- (VOID **)&mEtagProtocol
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ if (EFI_ERROR (Status)) {
+ return NULL;
}

- mEtagProtocol->Set (mEtagProtocol, Uri, EtagStr);
- mEtagProtocol->Flush (mEtagProtocol);
-
- return EFI_SUCCESS;
+ return EtagStr;
}

/**

- Find ETAG string that refers to given URI.
+ Convert Unicode string to ASCII string. It's call responsibility to release
returned buffer.

- @param[in] Uri Target URI string.
+ @param[in] UnicodeStr Unicode string to convert.

- @retval CHAR8 * ETAG string
- @retval NULL No ETAG is found.
+ @retval CHAR8 * ASCII string returned.
+ @retval NULL Errors occur.

**/
CHAR8 *
-GetEtagWithUri (
- IN CHAR8 *Uri
+StrUnicodeToAscii (
+ IN EFI_STRING UnicodeStr
)
{
- EFI_STATUS Status;
- CHAR8 *EtagStr;
+ CHAR8 *AsciiStr;
+ UINTN AsciiStrSize;
+ EFI_STATUS Status;

- if (IS_EMPTY_STRING (Uri)) {
+ if (IS_EMPTY_STRING (UnicodeStr)) {
return NULL;
}

- if (mEtagProtocol == NULL) {
- Status = gBS->LocateProtocol (
- &gEdkIIRedfishETagProtocolGuid,
- NULL,
- (VOID **)&mEtagProtocol
- );
- if (EFI_ERROR (Status)) {
- return NULL;
- }
+ AsciiStrSize = StrLen (UnicodeStr) + 1;
+ AsciiStr = AllocatePool (AsciiStrSize);
+ if (AsciiStr == NULL) {
+ return NULL;
}

- Status = mEtagProtocol->Get (mEtagProtocol, Uri, &EtagStr);
+ Status = UnicodeStrToAsciiStrS (UnicodeStr, AsciiStr, AsciiStrSize);
if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "UnicodeStrToAsciiStrS failed: %r\n", Status));
+ FreePool (AsciiStr);
return NULL;
}

- return EtagStr;
+ return AsciiStr;
}

/**

- Convert HII string value to string value in JSON format.
+ Convert ASCII string to Unicode string. It's call responsibility to release
returned buffer.

- @param[in] HiiStringValue String in HII format.
+ @param[in] AsciiStr ASCII string to convert.

- @retval CHAR8 * String in JSON format.
+ @retval EFI_STRING Unicode string returned.
@retval NULL Errors occur.

**/
-CHAR8 *
-ConvertHiiStringValueToJsonStringValue (
- IN EFI_STRING HiiStringValue
+EFI_STRING
+StrAsciiToUnicode (
+ IN CHAR8 *AsciiStr
)
{
- CHAR8 *JsonValue;
- UINTN JsonValueSize;
+ EFI_STRING UnicodeStr;
+ UINTN UnicodeStrSize;
+ EFI_STATUS Status;

- if (IS_EMPTY_STRING (HiiStringValue)) {
+ if (IS_EMPTY_STRING (AsciiStr)) {
return NULL;
}

- JsonValueSize = StrLen (HiiStringValue) + 1;
- JsonValue = AllocatePool (JsonValueSize);
- UnicodeStrToAsciiStrS (HiiStringValue, JsonValue, JsonValueSize);
+ UnicodeStrSize = (AsciiStrLen (AsciiStr) + 1) * sizeof (CHAR16);
+ UnicodeStr = AllocatePool (UnicodeStrSize);
+ if (UnicodeStr == NULL) {
+ return NULL;
+ }
+
+ Status = AsciiStrToUnicodeStrS (AsciiStr, UnicodeStr, UnicodeStrSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "t failed: %r\n", Status));
+ FreePool (UnicodeStr);
+ return NULL;
+ }

- return JsonValue;
+ return UnicodeStr;
}

/**
@@ -480,997 +448,2979 @@ ApplyFeatureSettingsBooleanType (

/**

- Read redfish resource by given resource path.
+ Apply property value to UEFI HII database in vague type.

- @param[in] Service Redfish srvice instacne to make query.
- @param[in] ResourcePath Target resource path.
- @param[out] Response HTTP response from redfish service.
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] VagueValuePtr Pointer of vague values to to set.
+ @param[in] NumVagueValues Number of vague values.

- @retval EFI_SUCCESS Resrouce is returned successfully.
+ @retval EFI_SUCCESS New value is applied successfully.
@retval Others Errors occur.

**/
EFI_STATUS
-GetResourceByPath (
- IN REDFISH_SERVICE *Service,
- IN CHAR8 *ResourcePath,
- OUT REDFISH_RESPONSE *Response
+ApplyFeatureSettingsVagueType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_EmptyProp_KeyValue *VagueValuePtr,
+ IN UINT32 NumberOfVagueValues
)
{
- EFI_STATUS Status;
-
- if (Service == NULL || Response == NULL || IS_EMPTY_STRING
(ResourcePath)) {
+ EFI_STATUS Status;
+ UINTN StrSize;
+ CHAR8 *ConfigureLangAscii;
+ CHAR8 *ConfigureLangKeyAscii;
+ EFI_STRING ConfigureKeyLang;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EDKII_REDFISH_VALUE_TYPES PropertyDatatype;
+ RedfishCS_EmptyProp_KeyValue *CurrentVagueValuePtr;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || VagueValuePtr == NULL ||
NumberOfVagueValues == 0) {
return EFI_INVALID_PARAMETER;
}

- //
- // Get resource from redfish service.
- //
- Status = RedfishGetByService (
- Service,
- ResourcePath,
- Response
- );
+ ConfigureLangAscii = AllocatePool (StrLen (ConfigureLang) + 1);
+ if (ConfigureLangAscii == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((DEBUG_ERROR, "%a, Allocate memory for generate
ConfigureLang of vague key of %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
+ return Status;
+ }
+ Status = UnicodeStrToAsciiStrS (ConfigureLang, ConfigureLangAscii,
StrLen
(ConfigureLang) + 1);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, RedfishGetByService to %a failed: %r\n",
__FUNCTION__, ResourcePath, Status));
- if (Response->Payload != NULL) {
- RedfishDumpPayload (Response->Payload);
- RedfishFreeResponse (
- NULL,
- 0,
- NULL,
- Response->Payload
- );
- Response->Payload = NULL;
- }
-
+ DEBUG ((DEBUG_ERROR, "%a, Convert the configureLang of vague key
of
%a.%a %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLang,
Status));
return Status;
}

+ CurrentVagueValuePtr = VagueValuePtr;
+ while (CurrentVagueValuePtr != NULL) {
+ //
+ // Generate ConfigureLang with the key name
+ //
+ //ConfigureKeyLang = GetConfigureLang (ConfigureLangAscii,
CurrentVagueValuePtr->KeyNamePtr);
+ StrSize = AsciiStrLen (ConfigureLangAscii) + AsciiStrLen
(CurrentVagueValuePtr->KeyNamePtr) + 2;
+ ConfigureLangKeyAscii = AllocateZeroPool (StrSize);
+ ConfigureKeyLang = AllocateZeroPool (StrSize * sizeof (CHAR16));
+ if (ConfigureLangKeyAscii == NULL || ConfigureKeyLang == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Generate ConfigureLang of vague key
of
%a.%a %s %a failed!\n", __FUNCTION__, Schema, Version, ConfigureLang,
CurrentVagueValuePtr->KeyNamePtr));
+ goto ErrorContinue;
+ }
+ AsciiStrCatS(ConfigureLangKeyAscii, StrSize, ConfigureLangAscii);
+ AsciiStrCatS(ConfigureLangKeyAscii, StrSize, "/");
+ AsciiStrCatS(ConfigureLangKeyAscii, StrSize, CurrentVagueValuePtr-
KeyNamePtr);
+ AsciiStrToUnicodeStrS(ConfigureLangKeyAscii, ConfigureKeyLang,
StrSize);
+ FreePool (ConfigureLangKeyAscii);
+ ConfigureLangKeyAscii = NULL;
+ //
+ // Initial property data type and value.
+ //
+ if (CurrentVagueValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_String) {
+ PropertyDatatype = REDFISH_VALUE_TYPE_STRING;
+ } else if (CurrentVagueValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_Bool) {
+ PropertyDatatype = REDFISH_VALUE_TYPE_BOOLEAN;
+ } else if (CurrentVagueValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_Int64) {
+ PropertyDatatype = REDFISH_VALUE_TYPE_INTEGER;
+ } else {
+ DEBUG((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish
property
data type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+ goto ErrorContinue;
+ }
+
+ //
+ // Get the current value from HII
+ //
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureKeyLang, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureKeyLang, Status));
+ } else {
+ if (RedfishValue.Type != PropertyDatatype) {
+ DEBUG((DEBUG_ERROR, "%a, %a.%a %s mismatched data type\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang));
+ goto ErrorContinue;
+ }
+ if (PropertyDatatype == REDFISH_VALUE_TYPE_STRING) {
+ //
+ // This is a string property.
+ //
+ if (AsciiStrCmp (CurrentVagueValuePtr->Value->DataValue.CharPtr,
RedfishValue.Value.Buffer) != 0) {
+ //
+ // Apply settings from redfish
+ //
+ DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from %a to %a\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang,
RedfishValue.Value.Buffer, CurrentVagueValuePtr->Value-
DataValue.CharPtr));
+ FreePool (RedfishValue.Value.Buffer);
+ RedfishValue.Value.Buffer = CurrentVagueValuePtr->Value-
DataValue.CharPtr;
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureKeyLang, RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply %a to %a failed: %r\n",
__FUNCTION__, ConfigureKeyLang, CurrentVagueValuePtr->Value-
DataValue.CharPtr, Status));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: %a\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang,
RedfishValue.Value.Buffer, Status));
+ }
+ } else if (PropertyDatatype == REDFISH_VALUE_TYPE_BOOLEAN) {
+ //
+ // This is a boolean property.
+ //
+ if (RedfishValue.Value.Boolean != *CurrentVagueValuePtr->Value-
DataValue.BoolPtr) {
+ //
+ // Apply settings from redfish
+ //
+ DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from %a to %a\n",
+ __FUNCTION__,
+ Schema,
+ Version,
+ ConfigureKeyLang,
+ (RedfishValue.Value.Boolean ? "True" : "False"),
+ (*CurrentVagueValuePtr->Value->DataValue.BoolPtr ? "True" :
"False")));
+
+ RedfishValue.Value.Boolean = (BOOLEAN)*CurrentVagueValuePtr-
Value->DataValue.BoolPtr;
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureKeyLang, RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply %s to %a failed: %r\n",
__FUNCTION__, ConfigureKeyLang, (*CurrentVagueValuePtr->Value-
DataValue.BoolPtr ? "True" : "False"), Status));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: %a\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang,
(RedfishValue.Value.Boolean ? "True" : "False"), Status));
+ }
+ } else if (PropertyDatatype == REDFISH_VALUE_TYPE_INTEGER) {
+ //
+ // This is a integer property.
+ //
+ if (RedfishValue.Value.Integer != *CurrentVagueValuePtr->Value-
DataValue.Int64Ptr) {
+ //
+ // Apply settings from redfish
+ //
+ DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from 0x%x to 0x%x\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang,
RedfishValue.Value.Integer, *CurrentVagueValuePtr->Value-
DataValue.Int64Ptr));
+
+ RedfishValue.Value.Integer = (INT64)*CurrentVagueValuePtr-
Value-
DataValue.Int64Ptr;
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureKeyLang, RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply %s to 0x%x failed: %r\n",
__FUNCTION__, ConfigureKeyLang, *CurrentVagueValuePtr->Value-
DataValue.Int64Ptr, Status));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: 0x%x\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang,
RedfishValue.Value.Integer, Status));
+ }
+ } else {
+ DEBUG((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish
property
data type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+ goto ErrorContinue;
+ }
+ }
+
+ErrorContinue:;
+ if (ConfigureLangKeyAscii != NULL) {
+ FreePool (ConfigureLangKeyAscii);
+ ConfigureLangKeyAscii = NULL;
+ }
+ if (ConfigureKeyLang != NULL) {
+ FreePool (ConfigureKeyLang);
+ ConfigureKeyLang = NULL;
+ }
+ CurrentVagueValuePtr = CurrentVagueValuePtr->NextKeyValuePtr;
+ };
+
+ if (ConfigureLangAscii != NULL) {
+ FreePool (ConfigureLangAscii);
+ }
+ if (ConfigureLangKeyAscii != NULL) {
+ FreePool (ConfigureLangKeyAscii);
+ }
+ if (ConfigureKeyLang != NULL) {
+ FreePool (ConfigureKeyLang);
+ }
return EFI_SUCCESS;
}

/**

- Find array index from given configure language string.
-
- @param[in] ConfigureLang Configure language string to parse.
- @param[out] UnifiedConfigureLang The configure language in array.
- @param[out] Index The array index number.
+ Release the memory in RedfishValue while value type is array.

- @retval EFI_SUCCESS Index is found.
- @retval Others Errors occur.
+ @param[in] RedfishValue Pointer to Redfish value

**/
-EFI_STATUS
-GetArrayIndexFromArrayTypeConfigureLang (
- IN CHAR16 *ConfigureLang,
- OUT CHAR16 **UnifiedConfigureLang,
- OUT UINTN *Index
+VOID
+FreeArrayTypeRedfishValue (
+ EDKII_REDFISH_VALUE *RedfishValue
)
{
- CHAR16 *TmpConfigureLang;
- CHAR16 *IndexString;
- CHAR16 *TmpString;
-
- if (ConfigureLang == NULL || UnifiedConfigureLang == NULL || Index ==
NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- TmpConfigureLang = AllocateCopyPool (StrSize (ConfigureLang),
ConfigureLang);
- if (TmpConfigureLang == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
+ UINTN Index;

- //
- // looking for index signature "{""
- //
- IndexString = StrStr (TmpConfigureLang,
BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
- if (IndexString == NULL) {
- return EFI_NOT_FOUND;
+ if (RedfishValue == NULL) {
+ return;
}

- //
- // Skip "{"
- //
- TmpString = IndexString + StrLen
(BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
-
- //
- // Looking for "}"
- //
- TmpString = StrStr (TmpString,
BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE);
- if (TmpString == NULL) {
- return EFI_NOT_FOUND;
+ if (RedfishValue->Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY &&
RedfishValue->Type != REDFISH_VALUE_TYPE_STRING_ARRAY) {
+ return;
}

- //
- // Append '\0' for converting decimal string to integer.
- //
- TmpString[0] = '\0';
+ switch (RedfishValue->Type) {
+ case REDFISH_VALUE_TYPE_STRING_ARRAY:
+ for (Index = 0; Index < RedfishValue->ArrayCount; Index++) {
+ FreePool (RedfishValue->Value.StringArray[Index]);
+ }
+ FreePool (RedfishValue->Value.StringArray);
+ RedfishValue->Value.StringArray = NULL;
+ break;

- //
- // Convert decimal string to integer
- //
- *Index = StrDecimalToUintn (IndexString + StrLen
(BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE));
+ case REDFISH_VALUE_TYPE_INTEGER_ARRAY:
+ FreePool (RedfishValue->Value.IntegerArray);
+ RedfishValue->Value.IntegerArray = NULL;
+ break;

- //
- // Resotre the '}' character and remove rest of string.
- //
- TmpString[0] = L'}';
- TmpString[1] = '\0';
+ case REDFISH_VALUE_TYPE_BOOLEAN_ARRAY:
+ FreePool (RedfishValue->Value.BooleanArray);
+ RedfishValue->Value.BooleanArray = NULL;
+ break;

- *UnifiedConfigureLang = TmpConfigureLang;
+ default:
+ return;
+ }

- return EFI_SUCCESS;
+ RedfishValue->ArrayCount = 0;
}

+
/**

- Search HII database with given Configure Language pattern. Data is
handled
and
- returned in array.
+ Apply property value to UEFI HII database in string array type.

- @param[in] Schema The schema to search.
- @param[in] Version The schema version.
- @param[in] Pattern Configure Language pattern to search.
- @param[out] UnifiedConfigureLangList The data returned by HII
database.
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] ArrayHead Head of array value.

- @retval EFI_SUCCESS Data is found and returned.
+ @retval EFI_SUCCESS New value is applied successfully.
@retval Others Errors occur.

**/
EFI_STATUS
-RedfishFeatureGetUnifiedArrayTypeConfigureLang (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING Pattern, OPTIONAL
- OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*UnifiedConfigureLangList
+ApplyFeatureSettingsStringArrayType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_char_Array *ArrayHead
)
{
- EFI_STATUS Status;
- EFI_STRING *ConfigureLangList;
- UINTN Count;
- UINTN Index;
- UINTN Index2;
- UINTN ArrayIndex;
- EFI_STRING UnifiedConfigureLang;
- BOOLEAN Duplicated;
- REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
UnifiedConfigureLangPool[BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZ
E];
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ UINTN Index;
+ RedfishCS_char_Array *Buffer;

- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
UnifiedConfigureLangList == NULL) {
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || ArrayHead == NULL) {
return EFI_INVALID_PARAMETER;
}

- UnifiedConfigureLangList->Count = 0;
- UnifiedConfigureLangList->List = NULL;
- ZeroMem (UnifiedConfigureLangPool, sizeof
(UnifiedConfigureLangPool));
-
- Status = RedfishPlatformConfigGetConfigureLang (Schema, Version,
Pattern, &ConfigureLangList, &Count);
+ //
+ // Get the current value from HII
+ //
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLang,
&RedfishValue);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, RedfishFeatureGetConfigureLangRegex
failed: %r\n", __FUNCTION__, Status));
- return Status;
- }
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
+ } else {

- if (Count == 0) {
- return EFI_NOT_FOUND;
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING_ARRAY) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array
type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // If there is no change in array, do nothing
+ //
+ if (!CompareRedfishStringArrayValues (ArrayHead,
RedfishValue.Value.StringArray, RedfishValue.ArrayCount)) {
+ //
+ // Apply settings from redfish
+ //
+ DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ FreeArrayTypeRedfishValue (&RedfishValue);
+
+ //
+ // Convert array from RedfishCS_char_Array to EDKII_REDFISH_VALUE
+ //
+ RedfishValue.ArrayCount = 0;
+ Buffer = ArrayHead;
+ while (Buffer != NULL) {
+ RedfishValue.ArrayCount += 1;
+ Buffer = Buffer->Next;
+ }
+
+ //
+ // Allocate pool for new values
+ //
+ RedfishValue.Value.StringArray = AllocatePool
(RedfishValue.ArrayCount *sizeof (CHAR8 *));
+ if (RedfishValue.Value.StringArray == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Buffer = ArrayHead;
+ Index = 0;
+ while (Buffer != NULL) {
+ RedfishValue.Value.StringArray[Index] = AllocateCopyPool
(AsciiStrSize
(Buffer->ArrayValue), Buffer->ArrayValue);
+ if (RedfishValue.Value.StringArray[Index] == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Buffer = Buffer->Next;
+ Index++;
+ }
+
+ ASSERT (Index <= RedfishValue.ArrayCount);
+
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureLang, RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ }
}

- for (Index = 0; Index < Count; Index++) {
- Status = GetArrayIndexFromArrayTypeConfigureLang
(ConfigureLangList[Index], &UnifiedConfigureLang, &ArrayIndex);
- if (EFI_ERROR (Status)) {
- ASSERT (FALSE);
- continue;
+ return Status;
+}
+
+/**
+
+ Apply property value to UEFI HII database in numeric array type (INT64).
+
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] ArrayHead Head of array value.
+
+ @retval EFI_SUCCESS New value is applied successfully.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+ApplyFeatureSettingsNumericArrayType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_int64_Array *ArrayHead
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ UINTN Index;
+ RedfishCS_int64_Array *Buffer;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || ArrayHead == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the current value from HII
+ //
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLang,
&RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
+ } else {
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array
type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return EFI_DEVICE_ERROR;
}

//
- // Check if this configure language is duplicated.
+ // If there is no change in array, do nothing
//
- Duplicated = FALSE;
- for (Index2 = 0; Index2 <
BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE; Index2++) {
- if (UnifiedConfigureLangPool[Index2].ConfigureLang == NULL) {
- break;
+ if (!CompareRedfishNumericArrayValues (ArrayHead,
RedfishValue.Value.IntegerArray, RedfishValue.ArrayCount)) {
+ //
+ // Apply settings from redfish
+ //
+ DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ FreeArrayTypeRedfishValue (&RedfishValue);
+
+ //
+ // Convert array from RedfishCS_int64_Array to EDKII_REDFISH_VALUE
+ //
+ RedfishValue.ArrayCount = 0;
+ Buffer = ArrayHead;
+ while (Buffer != NULL) {
+ RedfishValue.ArrayCount += 1;
+ Buffer = Buffer->Next;
+ }
+
+ //
+ // Allocate pool for new values
+ //
+ RedfishValue.Value.IntegerArray = AllocatePool
(RedfishValue.ArrayCount * sizeof (INT64));
+ if (RedfishValue.Value.IntegerArray == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Buffer = ArrayHead;
+ Index = 0;
+ while (Buffer != NULL) {
+ RedfishValue.Value.IntegerArray[Index] = (INT64)*Buffer-
ArrayValue;
+ Buffer = Buffer->Next;
+ Index++;
+ }
+
+ ASSERT (Index <= RedfishValue.ArrayCount);
+
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureLang, RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ }
+ }
+
+ return Status;
+}
+
+/**
+
+ Apply property value to UEFI HII database in boolean array type (INT64).
+
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] ArrayHead Head of Redfich CS boolean array value.
+
+ @retval EFI_SUCCESS New value is applied successfully.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+ApplyFeatureSettingsBooleanArrayType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_bool_Array *ArrayHead
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ UINTN Index;
+ RedfishCS_bool_Array *Buffer;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || ArrayHead == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the current value from HII
+ //
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLang,
&RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
+ } else {
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN_ARRAY) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array
type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // If there is no change in array, do nothing
+ //
+ if (!CompareRedfishBooleanArrayValues (ArrayHead,
RedfishValue.Value.BooleanArray, RedfishValue.ArrayCount)) {
+ //
+ // Apply settings from redfish
+ //
+ DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ FreeArrayTypeRedfishValue (&RedfishValue);
+
+ //
+ // Convert array from RedfishCS_int64_Array to EDKII_REDFISH_VALUE
+ //
+ RedfishValue.ArrayCount = 0;
+ Buffer = ArrayHead;
+ while (Buffer != NULL) {
+ RedfishValue.ArrayCount += 1;
+ Buffer = Buffer->Next;
+ }
+
+ //
+ // Allocate pool for new values
+ //
+ RedfishValue.Value.BooleanArray = AllocatePool
(RedfishValue.ArrayCount * sizeof (BOOLEAN));
+ if (RedfishValue.Value.BooleanArray == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Buffer = ArrayHead;
+ Index = 0;
+ while (Buffer != NULL) {
+ RedfishValue.Value.BooleanArray[Index] = (BOOLEAN)*Buffer-
ArrayValue;
+ Buffer = Buffer->Next;
+ Index++;
+ }
+
+ ASSERT (Index <= RedfishValue.ArrayCount);
+
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureLang, RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ }
+ }
+
+ return Status;
+}
+
+/**
+
+ Read redfish resource by given resource URI.
+
+ @param[in] Service Redfish srvice instacne to make query.
+ @param[in] ResourceUri Target resource URI.
+ @param[out] Response HTTP response from redfish service.
+
+ @retval EFI_SUCCESS Resrouce is returned successfully.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+GetResourceByUri (
+ IN REDFISH_SERVICE *Service,
+ IN EFI_STRING ResourceUri,
+ OUT REDFISH_RESPONSE *Response
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *AsciiResourceUri;
+
+ if (Service == NULL || Response == NULL || IS_EMPTY_STRING
(ResourceUri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AsciiResourceUri = StrUnicodeToAscii (ResourceUri);
+ if (AsciiResourceUri == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get resource from redfish service.
+ //
+ Status = RedfishGetByUri (
+ Service,
+ AsciiResourceUri,
+ Response
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, RedfishGetByUri to %a failed: %r\n",
__FUNCTION__, AsciiResourceUri, Status));
+ if (Response->Payload != NULL) {
+ RedfishDumpPayload (Response->Payload);
+ RedfishFreeResponse (
+ NULL,
+ 0,
+ NULL,
+ Response->Payload
+ );
+ Response->Payload = NULL;
+ }
+ }
+
+ if (AsciiResourceUri != NULL) {
+ FreePool (AsciiResourceUri);
+ }
+
+ return Status;
+}
+
+/**
+
+ Check if this is the Redpath array. Usually the Redpath array represents
+ the collection member. Return
+
+ @param[in] ConfigureLang The Redpath to check
+ @param[out] ArraySignatureOpen String to the open of array
signature.
+ @param[out] ArraySignatureClose String to the close of array
signature.
+
+ @retval EFI_SUCCESS Index is found.
+ @retval EFI_NOT_FOUND The non-array configure language string
is
retured.
+ @retval EFI_INVALID_PARAMETER The format of input ConfigureLang
is
wrong.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+IsRedpathArray (
+ IN EFI_STRING ConfigureLang,
+ OUT EFI_STRING *ArraySignatureOpen OPTIONAL,
+ OUT EFI_STRING *ArraySignatureClose OPTIONAL
+ )
+{
+ CHAR16 *IndexString;
+
+ if (ConfigureLang == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ArraySignatureOpen != NULL) {
+ *ArraySignatureOpen = NULL;
+ }
+ if (ArraySignatureClose != NULL) {
+ *ArraySignatureClose = NULL;
+ }
+
+ //
+ // looking for index signature "{""
+ //
+ IndexString = StrStr (ConfigureLang,
BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
+ if (IndexString != NULL) {
+ if (ArraySignatureOpen != NULL) {
+ *ArraySignatureOpen = IndexString;
+ }
+ //
+ // Skip "{"
+ //
+ IndexString = IndexString + StrLen
(BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
+ //
+ // Looking for "}"
+ //
+ IndexString = StrStr (IndexString,
BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE);
+ if (IndexString == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ArraySignatureClose != NULL) {
+ *ArraySignatureClose = IndexString;
+ }
+ return EFI_SUCCESS;
+ }
+ return EFI_NOT_FOUND;
+}
+
+/**
+
+ Get number of node from the string. Node is seperated by '/'.
+
+ @param[in] NodeString The node string to parse.
+
+ @retval UINTN Number of nodes in the string.
+
+**/
+UINTN
+GetNumberOfRedpathNodes (
+ IN EFI_STRING NodeString
+ )
+{
+ UINTN Index;
+ UINTN NumberNodes;
+ UINTN StringLen;
+
+ NumberNodes = 0;
+ StringLen = StrLen (NodeString);
+ Index = 1; // ConfigLang always starts with '/'.
+ while (Index < StringLen) {
+ if (*(NodeString + Index) == L'/') {
+ NumberNodes ++;
+ }
+ Index ++;
+ };
+ NumberNodes ++;
+
+ return (NumberNodes);
+}
+
+/**
+
+ Get the node string by index
+
+ @param[in] NodeString The node string to parse.
+ @param[in] Index Zero-based index of the node.
+ @param[out] EndOfNodePtr Pointer to receive the poitner to
+ the last character of node string.
+
+ @retval EFI_STRING the begining of the node string.
+
+**/
+EFI_STRING
+GetRedpathNodeByIndex (
+ IN EFI_STRING NodeString,
+ IN UINTN Index,
+ OUT EFI_STRING *EndOfNodePtr OPTIONAL
+ )
+{
+ UINTN NumberNodes;
+ UINTN StringLen;
+ UINTN StringIndex;
+ EFI_STRING NodeStart;
+ EFI_STRING NodeEnd;
+
+ NumberNodes = 0;
+ StringLen = StrLen (NodeString);
+ StringIndex = 1; // ConfigLang always starts with '/'.
+ NodeStart = NodeString;
+ if (EndOfNodePtr != NULL) {
+ *EndOfNodePtr = NULL;
+ }
+ while (StringIndex < StringLen) {
+ if (*(NodeString + StringIndex) == L'/') {
+ NodeEnd = NodeString + StringIndex - 1;
+ if (NumberNodes == Index) {
+ if (EndOfNodePtr != NULL) {
+ *EndOfNodePtr = NodeEnd;
+ }
+ return NodeStart;
+ } else {
+ NodeStart = NodeString + StringIndex + 1;
}
+ }
+ StringIndex ++;
+ };
+ return (NULL);
+}
+
+/**
+
+ Find array index from given configure language string.
+
+ @param[in] ConfigureLang Configure language string to parse.
+ @param[out] UnifiedConfigureLang The configure language in array.
+ @param[out] Index The array index number.
+
+ @retval EFI_SUCCESS Index is found.
+ @retval EFI_NOT_FOUND The non-array configure language string
is
retured.
+ @retval EFI_INVALID_PARAMETER The format of input ConfigureLang
is
wrong.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+GetArrayIndexFromArrayTypeConfigureLang (
+ IN CHAR16 *ConfigureLang,
+ OUT CHAR16 **UnifiedConfigureLang,
+ OUT UINTN *Index
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *TmpConfigureLang;
+ CHAR16 *ArrayOpenStr;
+ CHAR16 *ArrayCloseStr;
+ INTN StringIndex;
+
+ if (ConfigureLang == NULL || UnifiedConfigureLang == NULL || Index ==
NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TmpConfigureLang = AllocateCopyPool (StrSize (ConfigureLang),
ConfigureLang);
+ if (TmpConfigureLang == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = IsRedpathArray (TmpConfigureLang, &ArrayOpenStr,
&ArrayCloseStr);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Append '\0' for converting decimal string to integer.
+ //
+ ArrayCloseStr[0] = '\0';
+
+ //
+ // Convert decimal string to integer
+ //
+ *Index = StrDecimalToUintn (ArrayOpenStr + StrLen
(BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE));
+
+ //
+ // Resotre the '}' character and remove rest of string.
+ //
+ ArrayCloseStr[0] = L'}';
+ ArrayCloseStr[1] = '\0';
+ *UnifiedConfigureLang = TmpConfigureLang;
+ } else {
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // This is not the redpath array. Search "/" for the parent root.
+ //
+ *Index = 0;
+ StringIndex = StrLen (TmpConfigureLang) - 1;
+ while (StringIndex >= 0 && *(TmpConfigureLang + StringIndex) != '/') {
+ StringIndex --;
+ };
+ if (StringIndex >= 0 ) {
+ *(TmpConfigureLang + StringIndex) = '\0';
+ *UnifiedConfigureLang = TmpConfigureLang;
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+ return Status;
+}
+
+/**
+
+ Clone the configure language list.
+
+ @param[in] ConfigureLangList The source
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
+ @param[out] DestConfigureLangList The destination
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
+
+ @retval EFI_SUCCESS
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+CopyConfiglanguageList (
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*SourceConfigureLangList,
+ OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*DestConfigureLangList
+ )
+{
+ UINTN Index;
+
+ if (SourceConfigureLangList == NULL || DestConfigureLangList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ DestConfigureLangList->Count = SourceConfigureLangList->Count;
+ DestConfigureLangList->List =
+ (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *)AllocateZeroPool
(sizeof (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) *
DestConfigureLangList->Count);
+ if (DestConfigureLangList->List == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG.\n", __FUNCTION__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ for (Index = 0; Index < SourceConfigureLangList->Count; Index++) {
+ DestConfigureLangList->List [Index].Index = SourceConfigureLangList-
List[Index].Index;
+ DestConfigureLangList->List [Index].ConfigureLang =
+ (EFI_STRING)AllocateCopyPool(StrSize(SourceConfigureLangList-
List[Index].ConfigureLang), (VOID *)SourceConfigureLangList-
List[Index].ConfigureLang);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Clone the configure language list.
+
+ @param[in] ConfigureLang The pointer to configuration language.
+
+ @retval UINTN The index of collection member instance.
+ Value of 0 means no instance is found.
+**/
+UINTN
+ConfiglanguageGetInstanceIndex (
+ IN EFI_STRING ConfigureLang
+ )
+{
+ INTN LeftBracketIndex;
+ INTN RightBracketIndex;
+ INTN Index;
+ UINT64 Instance;
+ EFI_STATUS Status;
+
+ if (ConfigureLang == NULL) {
+ return 0;
+ }
+ LeftBracketIndex = 0;
+ RightBracketIndex = 0;
+ Index = StrLen (ConfigureLang) - 1;
+ while (Index >= 0) {
+ if (*(ConfigureLang + Index) == L'{') {
+ LeftBracketIndex = Index;
+ break;
+ }
+ if (*(ConfigureLang + Index) == L'}') {
+ RightBracketIndex = Index;
+ }
+ Index --;
+ };
+ if ((RightBracketIndex - LeftBracketIndex) <= 1) {
+ return 0;
+ }
+ *(ConfigureLang + RightBracketIndex) = 0;
+ Status = StrDecimalToUint64S (ConfigureLang + LeftBracketIndex + 1,
NULL,
&Instance);
+ if (EFI_ERROR(Status)) {
+ Instance = 0;
+ }
+ //
+ // Restore right curly bracket.
+ //
+ *(ConfigureLang + RightBracketIndex) = L'}';
+ return (UINTN)Instance;
+}
+
+/**
+
+ Destroy the configure language list.
+
+ @param[in] ConfigureLangList The
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
+ instance to destroy.
+
+ @retval EFI_SUCCESS
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+DestroyConfiglanguageList (
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*ConfigureLangList
+ )
+{
+ UINTN Index;
+
+ if (ConfigureLangList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ConfigureLangList->List != NULL) {
+ for (Index = 0; Index < ConfigureLangList->Count; Index++) {
+ if (ConfigureLangList->List [Index].ConfigureLang != NULL) {
+ FreePool (ConfigureLangList->List [Index].ConfigureLang);
+ }
+ }
+ FreePool (ConfigureLangList->List);
+ ConfigureLangList->List = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Set the node instance.
+
+ @param[in] DestConfigLang Pointer to the node's configure
language
string.
+ The memory pointed by ConfigLang must be allocated
+ through memory allocation interface. Becasue we will
replace
+ the pointer in this function.
+ @param[in] MaxtLengthConfigLang The maximum length of ConfigLang.
+ @param[in] ConfigLangInstance Pointer to Collection member instance.
+
+ @retval EFI_SUCCESS The instance is inserted to the configure
language.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+SetResourceConfigLangMemberInstance (
+ IN EFI_STRING *DestConfigLang,
+ IN UINTN MaxtLengthConfigLang,
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
*ConfigLangInstance
+ )
+{
+ EFI_STRING ThisConfigLang;
+ EFI_STRING NewConfigLang;
+ CHAR16 InstanceStr [10];
+ INTN Index;
+ UINTN Length;
+ UINTN MaxStrLength;
+
+ if (DestConfigLang == NULL || ConfigLangInstance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ UnicodeSPrint ((CHAR16 *)&InstanceStr, 10, L"%d", ConfigLangInstance-
Index);
+
+ ThisConfigLang = *DestConfigLang;
+ if (ThisConfigLang [0] == 0) {
+ //
+ // Return ConfigLangInstance->ConfigureLang
+ //
+ if (ConfigLangInstance->ConfigureLang == NULL) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ StrCatS(*DestConfigLang, MaxtLengthConfigLang, ConfigLangInstance-
ConfigureLang);
+ return EFI_SUCCESS;
+ }
+ }
+
+ MaxStrLength = StrSize (ThisConfigLang) + StrSize
((EFI_STRING)&InstanceStr);
+ NewConfigLang = ThisConfigLang;
+ if (MaxtLengthConfigLang < MaxStrLength) {
+ NewConfigLang = (EFI_STRING)AllocateZeroPool(MaxStrLength);
+ if (NewConfigLang == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for
NewConfigLang.\n", __FUNCTION__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ //
+ // Search the last "{"
+ //
+ Index = StrLen (ThisConfigLang) - 1;
+ while ((ThisConfigLang[Index] != '{') && (Index >= 0)) {
+ Index --;
+ };
+ if (Index == -1) {
+ if (NewConfigLang != ThisConfigLang) {
+ FreePool(NewConfigLang);
+ }
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Copy the string to a new string.
+ //
+ Length = 0;
+ while (Index >= 0) {
+ NewConfigLang [Index] = ThisConfigLang[Index];
+ Index --;
+ Length ++;
+ };
+ UnicodeSPrint ((CHAR16 *)(NewConfigLang + Length), MaxStrLength,
L"%d", ConfigLangInstance->Index);
+ StrCatS (NewConfigLang, MaxStrLength, L"}");
+ if (NewConfigLang != ThisConfigLang) {
+ FreePool (ThisConfigLang);
+ }
+ *DestConfigLang = NewConfigLang;
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Search HII database with given Configure Language pattern. Data is
handled and
+ returned in array.
+
+ @param[in] Schema The schema to search.
+ @param[in] Version The schema version.
+ @param[in] Pattern Configure Language pattern to search.
+ @param[out] UnifiedConfigureLangList The data returned by HII
database.
+
+ @retval EFI_SUCCESS Data is found and returned.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+RedfishFeatureGetUnifiedArrayTypeConfigureLang (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING Pattern, OPTIONAL
+ OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*UnifiedConfigureLangList
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING *ConfigureLangList;
+ UINTN Count;
+ UINTN Index;
+ UINTN Index2;
+ UINTN ArrayIndex;
+ EFI_STRING UnifiedConfigureLang;
+ BOOLEAN Duplicated;
+ REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
UnifiedConfigureLangPool[BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZ
E];
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
UnifiedConfigureLangList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UnifiedConfigureLangList->Count = 0;
+ UnifiedConfigureLangList->List = NULL;
+ ZeroMem (UnifiedConfigureLangPool, sizeof
(UnifiedConfigureLangPool));
+
+ Status = RedfishPlatformConfigGetConfigureLang (Schema, Version,
Pattern, &ConfigureLangList, &Count);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, RedfishFeatureGetConfigureLangRegex
failed: %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ if (Count == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ Status = GetArrayIndexFromArrayTypeConfigureLang
(ConfigureLangList[Index], &UnifiedConfigureLang, &ArrayIndex);
+ if (EFI_ERROR (Status) && Status == EFI_INVALID_PARAMETER) {
+ ASSERT (FALSE);
+ continue;
+ }
+
+ //
+ // Check if this configure language is duplicated.
+ //
+ Duplicated = FALSE;
+ for (Index2 = 0; Index2 <
BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE; Index2++) {
+ if (UnifiedConfigureLangPool[Index2].ConfigureLang == NULL) {
+ break;
+ }
+
+ if (StrCmp (UnifiedConfigureLangPool[Index2].ConfigureLang,
UnifiedConfigureLang) == 0) {
+ Duplicated = TRUE;
+ break;
+ }
+ }
+
+ if (Duplicated) {
+ FreePool (UnifiedConfigureLang);
+ continue;
+ }
+
+ if (UnifiedConfigureLangList->Count >=
BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE) {
+ FreePool (UnifiedConfigureLang);
+ Status = EFI_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ //
+ // New configure language. Keep it in Pool
+ //
+
+ UnifiedConfigureLangPool[UnifiedConfigureLangList-
Count].ConfigureLang = UnifiedConfigureLang;
+ UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].Index =
ArrayIndex;
+ ++UnifiedConfigureLangList->Count;
+ }
+
+ FreePool (ConfigureLangList);
+
+ //
+ // Prepare the result to caller.
+ //
+ UnifiedConfigureLangList->List = AllocateCopyPool (sizeof
(REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) *
UnifiedConfigureLangList->Count, UnifiedConfigureLangPool);
+
+ return Status;
+}
+
+/**
+
+ Find "ETag" and "Location" from either HTTP header or Redfish response.
+
+ @param[in] Response HTTP response
+ @param[out] Etag String buffer to return ETag
+ @param[out] Location String buffer to return Location
+
+ @retval EFI_SUCCESS Data is found and returned.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+GetEtagAndLocation (
+ IN REDFISH_RESPONSE *Response,
+ OUT CHAR8 **Etag, OPTIONAL
+ OUT EFI_STRING *Location OPTIONAL
+ )
+{
+ EDKII_JSON_VALUE JsonValue;
+ EDKII_JSON_VALUE OdataValue;
+ CHAR8 *OdataString;
+ CHAR8 *AsciiLocation;
+ EFI_HTTP_HEADER *Header;
+ EFI_STATUS Status;
+
+ if (Response == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Etag == NULL && Location == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = EFI_SUCCESS;
+
+ if (Etag != NULL) {
+ *Etag = NULL;
+
+ if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
+ Header = HttpFindHeader (Response->HeaderCount, Response-
Headers, HTTP_HEADER_ETAG);
+ if (Header != NULL) {
+ *Etag = AllocateCopyPool (AsciiStrSize (Header->FieldValue), Header-
FieldValue);
+ ASSERT (*Etag != NULL);
+ }
+ }
+
+ //
+ // No header is returned. Search payload for location.
+ //
+ if (*Etag == NULL && Response->Payload != NULL) {
+ JsonValue = RedfishJsonInPayload (Response->Payload);
+ if (JsonValue != NULL) {
+ OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
"@odata.etag");
+ if (OdataValue != NULL) {
+ OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
+ if (OdataString != NULL) {
+ *Etag = AllocateCopyPool (AsciiStrSize (OdataString), OdataString);
+ ASSERT (*Etag != NULL);
+ }
+ }
+
+ JsonValueFree (JsonValue);
+ }
+ }
+
+ if (*Etag == NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+ if (Location != NULL) {
+ *Location = NULL;
+
+ if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
+ Header = HttpFindHeader (Response->HeaderCount, Response-
Headers, HTTP_HEADER_LOCATION);
+ if (Header != NULL) {
+ AsciiLocation = AllocateCopyPool (AsciiStrSize (Header->FieldValue),
Header->FieldValue);
+ ASSERT (AsciiLocation != NULL);
+ }
+ }
+
+ //
+ // No header is returned. Search payload for location.
+ //
+ if (*Location == NULL && Response->Payload != NULL) {
+ JsonValue = RedfishJsonInPayload (Response->Payload);
+ if (JsonValue != NULL) {
+ OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
"@odata.id");
+ if (OdataValue != NULL) {
+ OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
+ if (OdataString != NULL) {
+ AsciiLocation = AllocateCopyPool (AsciiStrSize (OdataString),
OdataString);
+ ASSERT (AsciiLocation != NULL);
+ }
+ }
+
+ JsonValueFree (JsonValue);
+ }
+ }
+
+ if (AsciiLocation != NULL) {
+ *Location = StrAsciiToUnicode (AsciiLocation);
+ FreePool (AsciiLocation);
+ } else {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+ return Status;
+}
+/**
+
+ Create HTTP payload and send them to redfish service with PATCH
method.
+
+ @param[in] Service Redfish service.
+ @param[in] TargetPayload Target payload
+ @param[in] Json Data in JSON format.
+ @param[out] Etag Returned ETAG string from Redfish service.
+
+ @retval EFI_SUCCESS Data is sent to redfish service successfully.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+CreatePayloadToPatchResource (
+ IN REDFISH_SERVICE *Service,
+ IN REDFISH_PAYLOAD *TargetPayload,
+ IN CHAR8 *Json,
+ OUT CHAR8 **Etag
+ )
+{
+ REDFISH_PAYLOAD Payload;
+ EDKII_JSON_VALUE ResourceJsonValue;
+ REDFISH_RESPONSE PostResponse;
+ EFI_STATUS Status;
+
+ if (Service == NULL || TargetPayload == NULL || IS_EMPTY_STRING (Json)
|| Etag == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ResourceJsonValue = JsonLoadString (Json, 0, NULL);
+ Payload = RedfishCreatePayload (ResourceJsonValue, Service);
+ if (Payload == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
JSON value!\n",__FUNCTION__, __LINE__));
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT_FREE_JSON_VALUE;
+ }
+
+ ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
+ Status = RedfishPatchToPayload (TargetPayload, Payload,
&PostResponse);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish
service.\n",__FUNCTION__, __LINE__));
+ goto EXIT_FREE_JSON_VALUE;
+ }
+
+ //
+ // Find ETag
+ //
+ Status = GetEtagAndLocation (&PostResponse, Etag, NULL);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ RedfishFreeResponse (
+ PostResponse.StatusCode,
+ PostResponse.HeaderCount,
+ PostResponse.Headers,
+ PostResponse.Payload
+ );
+
+EXIT_FREE_JSON_VALUE:
+ if (Payload != NULL) {
+ RedfishCleanupPayload (Payload);
+ }
+
+ JsonValueFree (ResourceJsonValue);
+
+ return Status;
+}
+
+/**
+
+ Create HTTP payload and send them to redfish service with POST
method.
+
+ @param[in] Service Redfish service.
+ @param[in] TargetPayload Target payload
+ @param[in] Json Data in JSON format.
+ @param[out] Location Returned location string from Redfish service.
+ @param[out] Etag Returned ETAG string from Redfish service.
+
+ @retval EFI_SUCCESS Data is sent to redfish service successfully.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+CreatePayloadToPostResource (
+ IN REDFISH_SERVICE *Service,
+ IN REDFISH_PAYLOAD *TargetPayload,
+ IN CHAR8 *Json,
+ OUT EFI_STRING *Location,
+ OUT CHAR8 **Etag
+ )
+{
+ REDFISH_PAYLOAD Payload;
+ EDKII_JSON_VALUE ResourceJsonValue;
+ REDFISH_RESPONSE PostResponse;
+ EFI_STATUS Status;
+
+ if (Service == NULL || TargetPayload == NULL || IS_EMPTY_STRING (Json)
|| Location == NULL || Etag == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ResourceJsonValue = JsonLoadString (Json, 0, NULL);
+ Payload = RedfishCreatePayload (ResourceJsonValue, Service);
+ if (Payload == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
JSON value!\n",__FUNCTION__, __LINE__));
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT_FREE_JSON_VALUE;
+ }
+
+ ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
+ Status = RedfishPostToPayload (TargetPayload, Payload,
&PostResponse);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to POST Attribute Registry to
Redfish service.\n",__FUNCTION__, __LINE__));
+ goto EXIT_FREE_JSON_VALUE;
+ }
+
+ //
+ // per Redfish spec. the URL of new eresource will be returned in
"Location" header.
+ //
+ Status = GetEtagAndLocation (&PostResponse, Etag, Location);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ RedfishFreeResponse (
+ PostResponse.StatusCode,
+ PostResponse.HeaderCount,
+ PostResponse.Headers,
+ PostResponse.Payload
+ );
+
+ RedfishCleanupPayload (Payload);
+
+EXIT_FREE_JSON_VALUE:
+ JsonValueFree (ResourceJsonValue);
+
+ return Status;
+}
+
+/**
+
+ Return redfish URI by given config language. It's call responsibility to
release returned buffer.
+
+ @param[in] ConfigLang ConfigLang to search.
+
+ @retval NULL Can not find redfish uri.
+ @retval Other redfish uri is returned.
+
+**/
+EFI_STRING
+RedfishGetUri (
+ IN EFI_STRING ConfigLang
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING Target;
+ EFI_STRING Found;
+ EFI_STRING TempStr;
+ EFI_STRING ResultStr;
+ EFI_STRING Head;
+ EFI_STRING CloseBracket;
+ UINTN TempStrSize;
+ UINTN RemainingLen;
+ UINTN ConfigLangLen;
+
+ Status = RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol,
&gEdkIIRedfishConfigLangMapProtocolGuid);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, fail to locate
gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__,
Status));
+ return NULL;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, Get: %s\n", __FUNCTION__,
ConfigLang));
+
+ CloseBracket = StrStr (ConfigLang, L"{");
+ if (CloseBracket == NULL) {
+ return AllocateCopyPool (StrSize (ConfigLang), ConfigLang);
+ }
+
+ //
+ // Remove leading "/v1" or "/redfish/v1" because we don't code
+ // configure language in this way.
+ //
+ Head = StrStr (ConfigLang, REDFISH_ROOT_PATH_UNICODE);
+ if (Head == NULL) {
+ Head = ConfigLang;
+ } else {
+ Head += 3;
+ }
+
+ ResultStr = AllocateZeroPool (sizeof (CHAR16) *
MAX_REDFISH_URL_LEN);
+ if (ResultStr == NULL) {
+ return NULL;
+ }
+
+ //
+ // Go though ConfigLang and replace each {} with URL
+ //
+ do {
+ ConfigLangLen = StrLen (Head);
+ Target = CloseBracket;
+
+ //
+ // Look for next ConfigLang
+ //
+ do {
+ Target += 1;
+ } while (*Target != '\0' && *Target != '}');
+
+ //
+ // Invalid format. No '}' found
+ //
+ if (*Target == '\0') {
+ DEBUG ((DEBUG_ERROR, "%a, invalid format: %s\n", __FUNCTION__,
ConfigLang));
+ return NULL;
+ }
+
+ //
+ // Copy current ConfigLang to temporary string and do a query
+ //
+ Target += 1;
+ RemainingLen = StrLen (Target);
+ TempStrSize = (ConfigLangLen - RemainingLen + 1) * sizeof (CHAR16);
+ TempStr = AllocateCopyPool (TempStrSize, Head);
+ if (TempStr == NULL) {
+ return NULL;
+ }
+ TempStr[ConfigLangLen - RemainingLen] = '\0';
+
+ Status = mConfigLangMapProtocol->Get (
+ mConfigLangMapProtocol,
+ RedfishGetTypeConfigLang,
+ TempStr,
+ &Found
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, Can not find: %s\n", __FUNCTION__,
TempStr));
+ return NULL;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, Found: %s\n", __FUNCTION__,
Found));
+
+ //
+ // Keep result in final string pool
+ //
+ StrCatS (ResultStr, MAX_REDFISH_URL_LEN, Found);
+ FreePool (TempStr);
+
+ //
+ // Prepare for next ConfigLang
+ //
+ Head = Target;
+ CloseBracket = StrStr (Head, L"{");
+ } while (CloseBracket != NULL);
+
+ //
+ // String which has no ConfigLang remaining
+ //
+ if (Head != '\0') {
+ StrCatS (ResultStr, MAX_REDFISH_URL_LEN, Head);
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, return: %s\n", __FUNCTION__,
ResultStr));
+
+ return ResultStr;
+}
+
+/**
+
+ Return config language by given URI. It's call responsibility to release
returned buffer.
+
+ @param[in] Uri Uri to search.
+
+ @retval NULL Can not find redfish uri.
+ @retval Other redfish uri is returned.
+
+**/
+EFI_STRING
+RedfishGetConfigLanguage (
+ IN EFI_STRING Uri
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING ConfigLang;
+
+ if (IS_EMPTY_STRING (Uri)) {
+ return NULL;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, search config lang for URI: %s\n",
__FUNCTION__, Uri));
+
+ Status = RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol,
&gEdkIIRedfishConfigLangMapProtocolGuid);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, fail to locate
gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__,
Status));
+ return NULL;
+ }
+
+ ConfigLang = NULL;
+ Status = mConfigLangMapProtocol->Get (
+ mConfigLangMapProtocol,
+ RedfishGetTypeUri,
+ Uri,
+ &ConfigLang
+ );
+
+
+ return ConfigLang;
+}
+
+/**
+
+ Return config language from given URI and prperty name. It's call
responsibility to release returned buffer.
+
+ @param[in] Uri The URI to match
+ @param[in] PropertyName The property name of resource. This is
optional.
+
+ @retval NULL Can not find redfish uri.
+ @retval Other redfish uri is returned.
+
+**/
+EFI_STRING
+GetConfigureLang (
+ IN CHAR8 *Uri,
+ IN CHAR8 *PropertyName OPTIONAL
+ )
+{
+ EFI_STRING ConfigLang;
+ UINTN StringSize;
+ EFI_STRING ResultStr;
+ EFI_STRING UnicodeUri;
+ EFI_STATUS Status;
+
+ if (IS_EMPTY_STRING (Uri)) {
+ return NULL;
+ }
+
+ StringSize = AsciiStrSize (Uri);
+ UnicodeUri = AllocatePool (StringSize * sizeof (CHAR16));
+ if (UnicodeUri == NULL) {
+ return NULL;
+ }
+
+ Status = AsciiStrToUnicodeStrS (Uri, UnicodeUri, StringSize);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ ConfigLang = RedfishGetConfigLanguage (UnicodeUri);
+ if (ConfigLang == NULL) {
+ return NULL;
+ }
+
+ if (IS_EMPTY_STRING (PropertyName)) {
+ return ConfigLang;
+ }
+
+ StringSize = StrSize (ConfigLang) + ((AsciiStrLen (PropertyName) + 1) *
sizeof (CHAR16));
+ ResultStr = AllocatePool (StringSize);
+ if (ResultStr == NULL) {
+ return NULL;
+ }
+
+ UnicodeSPrint (ResultStr, StringSize, L"%s/%a", ConfigLang,
PropertyName);
+
+ return ResultStr;
+}
+
+/**
+
+ Save Redfish URI in database for further use.
+
+ @param[in] ConfigLang ConfigLang to save
+ @param[in] Uri Redfish Uri to save
+
+ @retval EFI_INVALID_PARAMETR SystemId is NULL or EMPTY
+ @retval EFI_SUCCESS Redfish uri is saved
+
+**/
+EFI_STATUS
+RedfisSetRedfishUri (
+ IN EFI_STRING ConfigLang,
+ IN EFI_STRING Uri
+ )
+{
+ EFI_STATUS Status;
+
+ if (IS_EMPTY_STRING (ConfigLang) || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol,
&gEdkIIRedfishConfigLangMapProtocolGuid);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, fail to locate
gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__,
Status));
+ return Status;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, Saved: %s -> %s\n",
__FUNCTION__, ConfigLang, Uri));
+
+ return mConfigLangMapProtocol->Set (mConfigLangMapProtocol,
ConfigLang, Uri);
+}
+
+/**
+
+ Get @odata.id from give HTTP payload. It's call responsibility to release
returned buffer.
+
+ @param[in] Payload HTTP payload
+
+ @retval NULL Can not find @odata.id from given payload.
+ @retval Others odata.id string is returned.
+
+**/
+EFI_STRING
+GetOdataId (
+ IN REDFISH_PAYLOAD *Payload
+ )
+{
+ EDKII_JSON_VALUE *JsonValue;
+ EDKII_JSON_VALUE *OdataId;
+ EFI_STRING OdataIdString;
+
+ if (Payload == NULL) {
+ return NULL;
+ }
+
+ JsonValue = RedfishJsonInPayload (Payload);
+ if (!JsonValueIsObject (JsonValue)) {
+ return NULL;
+ }
+
+ OdataId = JsonObjectGetValue (JsonValueGetObject (JsonValue),
"@odata.id");
+ if (!JsonValueIsString (OdataId)) {
+ return NULL;
+ }
+
+ OdataIdString = JsonValueGetUnicodeString (OdataId);
+ if (OdataIdString == NULL) {
+ return NULL;
+ }
+
+ return AllocateCopyPool (StrSize (OdataIdString), OdataIdString);
+}
+
+
+/**
+
+ Get the property name by given Configure Langauge.
+
+ @param[in] ResourceUri URI of root of resource.
+ @param[in] ConfigureLang Configure Language string.
+
+ @retval EFI_STRING Pointer to property name.
+ @retval NULL There is error.
+
+**/
+EFI_STRING
+GetPropertyFromConfigureLang (
+ IN EFI_STRING ResourceUri,
+ IN EFI_STRING ConfigureLang
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING TempString;
+
+ if (ConfigureLang == NULL || ResourceUri == NULL) {
+ return NULL;
+ }
+
+ Status = IsRedpathArray (ConfigureLang, NULL, &TempString);
+ if (!EFI_ERROR(Status)) {
+ TempString += 2; // Advance two characters for '}' and '/'
+ return TempString;
+ }
+ if (Status != EFI_NOT_FOUND) {
+ return NULL;
+ }
+ //
+ // The ConigLang has no '{}'
+ //
+ if (GetNumberOfRedpathNodes (ConfigureLang) == 1) {
+ return NULL;
+ }
+
+ if (GetRedpathNodeByIndex (ConfigureLang, 0, &TempString) == NULL) {
+ return NULL;
+ }
+ //
+ // Advance two characters to the starting
+ // pointer of next node.
+ //
+ return TempString + 2;
+}
+
+/**
+
+ Get the property value in string type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+
+ @retval CHAR8* Pointer to the CHAR8 buffer.
+ @retval NULL There is error.
+
+**/
+CHAR8 *
+GetPropertyStringValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ CHAR8 *AsciiStringValue;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName))
{
+ return NULL;
+ }
+
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ return NULL;
+ }
+
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s",
ConfigureLang,
PropertyName);
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+ return NULL;
+ }
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return NULL;
+ }
+
+ AsciiStringValue = AllocateCopyPool (AsciiStrSize
(RedfishValue.Value.Buffer), RedfishValue.Value.Buffer);
+ ASSERT (AsciiStringValue != NULL);
+
+ return AsciiStringValue;
+}
+
+/**
+
+ Get the property value in numeric type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+
+ @retval INT64* Pointer to the INT64 value.
+ @retval NULL There is error.
+
+**/
+INT64 *
+GetPropertyNumericValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ INT64 *ResultValue;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName))
{
+ return NULL;
+ }
+
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ return NULL;
+ }
+
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s",
ConfigureLang,
PropertyName);
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+ return NULL;
+ }
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not numeric type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return NULL;
+ }
+
+ ResultValue = AllocatePool (sizeof (INT64));
+ ASSERT (ResultValue != NULL);
+ if (ResultValue == NULL) {
+ return NULL;
+ }
+
+ *ResultValue = RedfishValue.Value.Integer;
+
+ return ResultValue;
+}
+
+/**
+
+ Get the property value in Boolean type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+
+ @retval BOOLEAN Boolean value returned by this property.
+
+**/
+BOOLEAN *
+GetPropertyBooleanValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ BOOLEAN *ResultValue;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName))
{
+ return NULL;
+ }
+
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ return NULL;
+ }
+
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s",
ConfigureLang,
PropertyName);
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+ return NULL;
+ }
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not boolean type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return NULL;
+ }
+
+ ResultValue = AllocatePool (sizeof (BOOLEAN));
+ ASSERT (ResultValue != NULL);
+ if (ResultValue == NULL) {
+ return NULL;
+ }
+
+ *ResultValue = RedfishValue.Value.Boolean;
+
+ return ResultValue;
+}
+
+/**
+
+ Return the last string of configure language. Any modification to
returned
+ string will change ConfigureLanguage.
+
+ @param[in] ConfigureLanguage Configure language string
+
+ @retval EFI_STRING Attribute name is returned
+ @retval NULL Error occurs
+
+**/
+EFI_STRING
+GetAttributeNameFromConfigLanguage (
+ IN EFI_STRING ConfigureLanguage
+ )
+{
+ UINTN StringLen;
+ UINTN Index;
+
+ if (IS_EMPTY_STRING (ConfigureLanguage)) {
+ return NULL;
+ }
+
+ StringLen = StrLen (ConfigureLanguage);
+ for (Index = StringLen - 1; Index >= 0; Index--) {
+ if (ConfigureLanguage[Index] == '/') {
+ return &ConfigureLanguage[Index + 1];
+ }
+ }
+
+ return NULL;
+}
+
+/**
+
+ Get the property string value in array type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] ArraySize The size of returned array.
+
+ @retval CHAR8 ** Returned string array. NULL while error happens.
+
+**/
+CHAR8 **
+GetPropertyStringArrayValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ CHAR8 **StringArray;
+ UINTN Index;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
|| ArraySize == NULL) {
+ return NULL;
+ }
+
+ *ArraySize = 0;
+
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+ return NULL;
+ }
+
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s",
ConfigureLang,
PropertyName);
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+ return NULL;
+ }
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING_ARRAY) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array
type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return NULL;
+ }
+
+ StringArray = AllocatePool (sizeof (CHAR8 *) * RedfishValue.ArrayCount);
+ if (StringArray == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+ return NULL;
+ }
+
+ *ArraySize = RedfishValue.ArrayCount;
+ for (Index = 0; Index < RedfishValue.ArrayCount; Index++) {
+ StringArray[Index] = RedfishValue.Value.StringArray[Index];
+ }
+
+ return StringArray;
+}
+
+/**
+
+ Get the property numeric value in array type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] ArraySize The size of returned array.
+
+ @retval INT64 * Returned integer array. NULL while error happens.
+
+**/
+INT64 *
+GetPropertyNumericArrayValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ INT64 *IntegerArray;
+ UINTN Index;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
|| ArraySize == NULL) {
+ return NULL;
+ }
+
+ *ArraySize = 0;
+
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+ return NULL;
+ }
+
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s",
ConfigureLang,
PropertyName);
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+ return NULL;
+ }
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array
type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return NULL;
+ }
+
+ IntegerArray = AllocatePool (sizeof (INT64) * RedfishValue.ArrayCount);
+ if (IntegerArray == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+ return NULL;
+ }
+
+ *ArraySize = RedfishValue.ArrayCount;
+ for (Index = 0; Index < RedfishValue.ArrayCount; Index++) {
+ IntegerArray[Index] = RedfishValue.Value.IntegerArray[Index];
+ }
+
+ return IntegerArray;
+}
+
+/**
+
+ Get the property boolean value in array type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] ArraySize The size of returned array.
+
+ @retval BOOLEAN * Returned boolean array. NULL while error
happens.
+
+**/
+BOOLEAN *
+GetPropertyBooleanArrayValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ BOOLEAN *BooleanArray;
+ UINTN Index;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
|| ArraySize == NULL) {
+ return NULL;
+ }
+
+ *ArraySize = 0;
+
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+ return NULL;
+ }
+
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s",
ConfigureLang,
PropertyName);
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+ return NULL;
+ }
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN_ARRAY) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array
type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return NULL;
+ }
+
+ BooleanArray = AllocatePool (sizeof (INT64) * RedfishValue.ArrayCount);
+ if (BooleanArray == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+ return NULL;
+ }
+
+ *ArraySize = RedfishValue.ArrayCount;
+ for (Index = 0; Index < RedfishValue.ArrayCount; Index++) {
+ BooleanArray[Index] = RedfishValue.Value.BooleanArray[Index];
+ }
+
+ return BooleanArray;
+}
+
+/**
+
+ Free the list of empty property key values.
+
+ @param[in] EmptyPropKeyValueListHead The head of
RedfishCS_EmptyProp_KeyValue
+
+**/
+VOID
+FreeEmptyPropKeyValueList (
+ RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueListHead
+ )
+{
+ RedfishCS_EmptyProp_KeyValue *NextEmptyPropKeyValueList;

- if (StrCmp (UnifiedConfigureLangPool[Index2].ConfigureLang,
UnifiedConfigureLang) == 0) {
- Duplicated = TRUE;
- break;
- }
+ while (EmptyPropKeyValueListHead != NULL) {
+ NextEmptyPropKeyValueList = EmptyPropKeyValueListHead-
NextKeyValuePtr;
+ if (EmptyPropKeyValueListHead->Value->DataValue.CharPtr != NULL) {
+ FreePool(EmptyPropKeyValueListHead->Value->DataValue.CharPtr);
}
-
- if (Duplicated) {
- FreePool (UnifiedConfigureLang);
- continue;
+ if (EmptyPropKeyValueListHead->Value != NULL) {
+ FreePool(EmptyPropKeyValueListHead->Value);
}
-
- if (UnifiedConfigureLangList->Count >=
BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE) {
- FreePool (UnifiedConfigureLang);
- Status = EFI_BUFFER_TOO_SMALL;
- break;
+ if (EmptyPropKeyValueListHead->KeyNamePtr != NULL) {
+ FreePool(EmptyPropKeyValueListHead->KeyNamePtr);
}
+ FreePool (EmptyPropKeyValueListHead);
+ EmptyPropKeyValueListHead = NextEmptyPropKeyValueList;
+ };
+}

- //
- // New configure language. Keep it in Pool
- //
+/**

- UnifiedConfigureLangPool[UnifiedConfigureLangList-
Count].ConfigureLang = UnifiedConfigureLang;
- UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].Index =
ArrayIndex;
- ++UnifiedConfigureLangList->Count;
- }
+ Create a new entry of RedfishCS_EmptyProp_KeyValue

- FreePool (ConfigureLangList);
+ @param[in] KeyName The key name.
+ @param[in] RedfishValue Redfish vale of this key.

- //
- // Prepare the result to caller.
- //
- UnifiedConfigureLangList->List = AllocateCopyPool (sizeof
(REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) *
UnifiedConfigureLangList->Count, UnifiedConfigureLangPool);
+* @retval RedfishCS_EmptyProp_KeyValue Return the new
RedfishCS_EmptyProp_KeyValue.
+* NULL means no new entry is created.

- return Status;
+**/
+RedfishCS_EmptyProp_KeyValue *
+NewEmptyPropKeyValueFromRedfishValue (
+ IN EFI_STRING KeyName,
+ IN EDKII_REDFISH_VALUE *RedfishValue
+ )
+{
+ RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValue;
+ RedfishCS_Vague *VagueValue;
+ RedfishCS_char *KeyNameChar;
+ VOID *Data;
+ UINTN DataSize;
+ INT32 Bool32;
+
+ KeyNameChar = StrUnicodeToAscii(KeyName);
+ if (KeyNameChar == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Failed to convert unicode to ASCII.\n",
__FUNCTION__));
+ return NULL;
+ }
+ EmptyPropKeyValue = (RedfishCS_EmptyProp_KeyValue
*)AllocateZeroPool (sizeof (RedfishCS_EmptyProp_KeyValue));
+ if (EmptyPropKeyValue == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
EmptyPropKeyValue\n", __FUNCTION__));
+ return NULL;
+ }
+ VagueValue = (RedfishCS_Vague *)AllocateZeroPool (sizeof
(RedfishCS_Vague));
+ if (VagueValue == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
VagueValue\n", __FUNCTION__));
+ FreePool (EmptyPropKeyValue);
+ return NULL;
+ }
+
+ if (RedfishValue->Type == REDFISH_VALUE_TYPE_BOOLEAN) {
+ VagueValue->DataType = RedfishCS_Vague_DataType_Bool;
+ DataSize = sizeof (BOOLEAN);
+ //
+ // Redfish JSON to C strcuture converter uses
+ // "int" for the BOOLEAN.
+ //
+ Bool32 = (INT32)RedfishValue->Value.Boolean;
+ Data = (VOID *)&Bool32;
+ } else if (RedfishValue->Type == REDFISH_VALUE_TYPE_INTEGER) {
+ VagueValue->DataType = RedfishCS_Vague_DataType_Int64;
+ DataSize = sizeof (INT64);
+ Data = (VOID *)&RedfishValue->Value.Integer;
+ } else if (RedfishValue->Type == REDFISH_VALUE_TYPE_STRING) {
+ VagueValue->DataType = RedfishCS_Vague_DataType_String;
+ DataSize = AsciiStrSize(RedfishValue->Value.Buffer);
+ Data = (VOID *)RedfishValue->Value.Buffer;
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, wrong type of RedfishValue: %x\n",
__FUNCTION__, RedfishValue->Type));
+ FreePool (VagueValue);
+ FreePool (EmptyPropKeyValue);
+ return NULL;
+ }
+ VagueValue->DataValue.CharPtr = (RedfishCS_char
*)AllocateCopyPool(DataSize, Data);
+ EmptyPropKeyValue->Value = VagueValue;
+ EmptyPropKeyValue->KeyNamePtr = KeyNameChar;
+ return EmptyPropKeyValue;
}

/**

- Create HTTP payload and send them to redfish service with PATCH
method.
+ Get the property value in the vague type.

- @param[in] Service Redfish service.
- @param[in] TargetPayload Target payload
- @param[in] Json Data in JSON format.
- @param[out] Etag Returned ETAG string from Redfish service.
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] NumberOfValues Return the number of vague type of
values

- @retval EFI_SUCCESS Data is sent to redfish service successfully.
- @retval Others Errors occur.
+ @retval RedfishCS_EmptyProp_KeyValue The pointer to the structure
+ of vague type of values.

**/
-EFI_STATUS
-CreatePayloadToPatchResource (
- IN REDFISH_SERVICE *Service,
- IN REDFISH_PAYLOAD *TargetPayload,
- IN CHAR8 *Json,
- OUT CHAR8 **Etag
+RedfishCS_EmptyProp_KeyValue *
+GetPropertyVagueValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINT32 *NumberOfValues
)
{
- REDFISH_PAYLOAD Payload;
- EDKII_JSON_VALUE ResourceJsonValue;
- REDFISH_RESPONSE PostResponse;
- EFI_STATUS Status;
- UINTN Index;
- EDKII_JSON_VALUE JsonValue;
- EDKII_JSON_VALUE OdataIdValue;
- CHAR8 *OdataIdString;
+ EFI_STATUS Status;
+ RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueList;
+ RedfishCS_EmptyProp_KeyValue *PreEmptyPropKeyValueList;
+ RedfishCS_EmptyProp_KeyValue *FirstEmptyPropKeyValueList;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ EFI_STRING KeyName;
+ EFI_STRING *ConfigureLangList;
+ EFI_STRING SearchPattern;
+ UINTN BufferSize;
+ UINTN ConfigListCount;
+ UINTN ConfigListCountIndex;

- if (Service == NULL || TargetPayload == NULL || IS_EMPTY_STRING (Json)
|| Etag == NULL) {
- return EFI_INVALID_PARAMETER;
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName))
{
+ return NULL;
}

- ResourceJsonValue = JsonLoadString (Json, 0, NULL);
- Payload = RedfishCreatePayload (ResourceJsonValue, Service);
- if (Payload == NULL) {
- DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
JSON value!\n",__FUNCTION__, __LINE__));
- Status = EFI_DEVICE_ERROR;
- goto EXIT_FREE_JSON_VALUE;
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
ConfigureLangBuffer\n", __FUNCTION__));
+ return NULL;
}
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s",
ConfigureLang,
PropertyName);

- ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
- Status = RedfishPatchToPayload (TargetPayload, Payload,
&PostResponse);
+ //
+ // Initial search pattern
+ //
+ BufferSize = (StrLen (ConfigureLangBuffer) + StrLen (L"/.*") + 1) * sizeof
(CHAR16); // Increase one for the NULL terminator.
+ SearchPattern = AllocatePool (BufferSize);
+ if (SearchPattern == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
SearchPattern\n", __FUNCTION__));
+ FreePool (ConfigureLangBuffer);
+ return NULL;
+ }
+ BufferSize = BufferSize / sizeof (CHAR16);
+ StrCpyS (SearchPattern, BufferSize, ConfigureLangBuffer);
+ StrCatS (SearchPattern, BufferSize, L"/.*");
+ Status = RedfishPlatformConfigGetConfigureLang (Schema, Version,
SearchPattern, &ConfigureLangList, &ConfigListCount);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish
service.\n",__FUNCTION__, __LINE__));
- goto EXIT_FREE_JSON_VALUE;
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a Get configure language of vague
type values of %s failed: %r\n", __FUNCTION__, Schema, Version,
ConfigureLangBuffer, Status));
+ goto ErrorLeave;
}

-
//
- // Keep etag.
+ // Build up the list of RedfishCS_EmptyProp_KeyValue.
//
- *Etag = NULL;
- if (*PostResponse.StatusCode == HTTP_STATUS_200_OK) {
- if (PostResponse.HeaderCount != 0) {
- for (Index = 0; Index < PostResponse.HeaderCount; Index++) {
- if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName, "ETag", 4)
== 0) {
- *Etag = AllocateCopyPool (AsciiStrSize
(PostResponse.Headers[Index].FieldValue),
PostResponse.Headers[Index].FieldValue);
- }
- }
- } else if (PostResponse.Payload != NULL) {
- //
- // No header is returned. Search payload for location.
- //
- JsonValue = RedfishJsonInPayload (PostResponse.Payload);
- if (JsonValue != NULL) {
- OdataIdValue = JsonObjectGetValue (JsonValueGetObject
(JsonValue),
"@odata.etag");
- if (OdataIdValue != NULL) {
- OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
- if (OdataIdString != NULL) {
- *Etag = AllocateCopyPool (AsciiStrSize (OdataIdString),
OdataIdString);
- }
- }
- }
+ ConfigListCountIndex = 0;
+ PreEmptyPropKeyValueList = NULL;
+ FirstEmptyPropKeyValueList = NULL;
+ while (ConfigListCountIndex < ConfigListCount) {
+ Status = RedfishPlatformConfigGetValue(Schema, Version,
ConfigureLangList [ConfigListCountIndex], &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s
failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangList
[ConfigListCountIndex], Status));
+ goto ErrorLeave;
}
- }
-
- RedfishFreeResponse (
- PostResponse.StatusCode,
- PostResponse.HeaderCount,
- PostResponse.Headers,
- PostResponse.Payload
- );
+ //
+ // Get the key name.
+ //
+ KeyName = GetAttributeNameFromConfigLanguage (ConfigureLangList
[ConfigListCountIndex]);
+ //
+ // Create an entry of RedfishCS_EmptyProp_KeyValue.
+ //
+ EmptyPropKeyValueList = NewEmptyPropKeyValueFromRedfishValue
(KeyName, &RedfishValue);
+ if (EmptyPropKeyValueList == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Failed to create an entry of
EmptyPropKeyValueList\n", __FUNCTION__));
+ ConfigListCountIndex ++;
+ continue;
+ }
+ //
+ // Link the RedfishCS_EmptyProp_KeyValue list.
+ //
+ if (PreEmptyPropKeyValueList != NULL) {
+ PreEmptyPropKeyValueList->NextKeyValuePtr =
EmptyPropKeyValueList;
+ } else {
+ FirstEmptyPropKeyValueList = EmptyPropKeyValueList;
+ }
+ PreEmptyPropKeyValueList = EmptyPropKeyValueList;
+ ConfigListCountIndex ++;
+ };
+ goto LeaveFunction;

-EXIT_FREE_JSON_VALUE:
- if (Payload != NULL) {
- RedfishCleanupPayload (Payload);
+ErrorLeave:;
+ if (FirstEmptyPropKeyValueList != NULL) {
+ FreeEmptyPropKeyValueList (FirstEmptyPropKeyValueList);
}
+ FirstEmptyPropKeyValueList = NULL;

- JsonValueFree (ResourceJsonValue);
+LeaveFunction:
+ if (SearchPattern != NULL) {
+ FreePool (SearchPattern);
+ }
+ if (ConfigureLangBuffer != NULL) {
+ FreePool (ConfigureLangBuffer);
+ }
+ FreePool (ConfigureLangList);

- return Status;
+ *NumberOfValues = (UINT32)ConfigListCount;
+ return FirstEmptyPropKeyValueList;
}

/**

- Create HTTP payload and send them to redfish service with POST method.
+ Check and see if we need to do provisioning for this property.

- @param[in] Service Redfish service.
- @param[in] TargetPayload Target payload
- @param[in] Json Data in JSON format.
- @param[out] Location Returned location string from Redfish service.
- @param[out] Etag Returned ETAG string from Redfish service.
+ @param[in] PropertyBuffer Pointer to property instance.
+ @param[in] ProvisionMode TRUE if we are in provision mode. FALSE
otherwise.

- @retval EFI_SUCCESS Data is sent to redfish service successfully.
- @retval Others Errors occur.
+ @retval TRUE Provision is required.
+ @retval FALSE Provision is not required.

**/
-EFI_STATUS
-CreatePayloadToPostResource (
- IN REDFISH_SERVICE *Service,
- IN REDFISH_PAYLOAD *TargetPayload,
- IN CHAR8 *Json,
- OUT CHAR8 **Location,
- OUT CHAR8 **Etag
+BOOLEAN
+PropertyChecker (
+ IN VOID *PropertyBuffer,
+ IN BOOLEAN ProvisionMode
)
{
- REDFISH_PAYLOAD Payload;
- EDKII_JSON_VALUE ResourceJsonValue;
- REDFISH_RESPONSE PostResponse;
- EFI_STATUS Status;
- UINTN Index;
- EDKII_JSON_VALUE JsonValue;
- EDKII_JSON_VALUE OdataIdValue;
- CHAR8 *OdataIdString;
+ if (ProvisionMode) {
+ return TRUE;
+ }

- if (Service == NULL || TargetPayload == NULL || IS_EMPTY_STRING (Json)
|| Location == NULL || Etag == NULL) {
- return EFI_INVALID_PARAMETER;
+ if (!ProvisionMode && PropertyBuffer != NULL) {
+ return TRUE;
}

- ResourceJsonValue = JsonLoadString (Json, 0, NULL);
- Payload = RedfishCreatePayload (ResourceJsonValue, Service);
- if (Payload == NULL) {
- DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
JSON value!\n",__FUNCTION__, __LINE__));
- Status = EFI_DEVICE_ERROR;
- goto EXIT_FREE_JSON_VALUE;
+ return FALSE;
+}
+
+/**
+
+ Check and see if ETAG is identical to what we keep in system.
+
+ @param[in] Uri URI requested
+ @param[in] EtagInHeader ETAG string returned from HTTP request.
+ @param[in] EtagInJson ETAG string in JSON body.
+
+ @retval TRUE ETAG is identical.
+ @retval FALSE ETAG is changed.
+
+**/
+BOOLEAN
+CheckEtag (
+ IN EFI_STRING Uri,
+ IN CHAR8 *EtagInHeader,
+ IN CHAR8 *EtagInJson
+ )
+{
+ CHAR8 *EtagInDb;
+
+ if (IS_EMPTY_STRING (Uri)) {
+ return FALSE;
}

- ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
- Status = RedfishPostToPayload (TargetPayload, Payload, &PostResponse);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a:%d Failed to POST Attribute Registry to
Redfish service.\n",__FUNCTION__, __LINE__));
- goto EXIT_FREE_JSON_VALUE;
+ if (IS_EMPTY_STRING (EtagInHeader) && IS_EMPTY_STRING
(EtagInJson))
{
+ return FALSE;
}

//
- // per Redfish spec. the URL of new eresource will be returned in
"Location" header.
+ // Check ETAG to see if we need to consume it
//
- *Location = NULL;
- *Etag = NULL;
- if (*PostResponse.StatusCode == HTTP_STATUS_200_OK) {
- if (PostResponse.HeaderCount != 0) {
- for (Index = 0; Index < PostResponse.HeaderCount; Index++) {
- if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName,
"Location",
8) == 0) {
- *Location = AllocateCopyPool (AsciiStrSize
(PostResponse.Headers[Index].FieldValue),
PostResponse.Headers[Index].FieldValue);
- } else if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName,
"ETag", 4) == 0) {
- *Etag = AllocateCopyPool (AsciiStrSize
(PostResponse.Headers[Index].FieldValue),
PostResponse.Headers[Index].FieldValue);
- }
- }
- } else if (PostResponse.Payload != NULL) {
- //
- // No header is returned. Search payload for location.
- //
- JsonValue = RedfishJsonInPayload (PostResponse.Payload);
- if (JsonValue != NULL) {
- OdataIdValue = JsonObjectGetValue (JsonValueGetObject
(JsonValue),
"@odata.id");
- if (OdataIdValue != NULL) {
- OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
- if (OdataIdString != NULL) {
- *Location = AllocateCopyPool (AsciiStrSize (OdataIdString),
OdataIdString);
- }
- }
+ EtagInDb = NULL;
+ EtagInDb = GetEtagWithUri (Uri);
+ if (EtagInDb == NULL) {
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, no ETAG record cound be
found
for: %s\n", __FUNCTION__, Uri));
+ return FALSE;
+ }

- OdataIdValue = JsonObjectGetValue (JsonValueGetObject
(JsonValue),
"@odata.etag");
- if (OdataIdValue != NULL) {
- OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
- if (OdataIdString != NULL) {
- *Etag = AllocateCopyPool (AsciiStrSize (OdataIdString),
OdataIdString);
- }
- }
- }
+ if (EtagInHeader != NULL) {
+ if (AsciiStrCmp (EtagInDb, EtagInHeader) == 0) {
+ FreePool (EtagInDb);
+ return TRUE;
}
}

- //
- // This is not expected as service does not follow spec.
- //
- if (*Location == NULL) {
- Status = EFI_DEVICE_ERROR;
+ if (EtagInJson != NULL) {
+ if (AsciiStrCmp (EtagInDb, EtagInJson) == 0) {
+ FreePool (EtagInDb);
+ return TRUE;
+ }
}

- RedfishFreeResponse (
- PostResponse.StatusCode,
- PostResponse.HeaderCount,
- PostResponse.Headers,
- PostResponse.Payload
- );
-
- RedfishCleanupPayload (Payload);
-
-EXIT_FREE_JSON_VALUE:
- JsonValueFree (JsonValue);
- JsonValueFree (ResourceJsonValue);
+ FreePool (EtagInDb);

- return Status;
+ return FALSE;
}

/**
+ Check and see if given ObjectName can be found in JsonObj or not

- Find Redfish Resource Config Protocol that supports given schema and
version.
+ @param[in] JsonObj JSON object to search
+ @param[in] ObjectName Object name

- @param[in] Schema Schema name.
- @param[in] Major Schema version major number.
- @param[in] Minor Schema version minor number.
- @param[in] Errata Schema version errata number.
-
- @retval EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL * Pointer to
protocol
- @retval NULL No protocol found.
+ @retval EDKII_JSON_VALUE * Pointer to Json object is found. NULL
otherwise.

**/
-EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *
-GetRedfishResourceConfigProtocol (
- IN CHAR8 *Schema,
- IN CHAR8 *Major,
- IN CHAR8 *Minor,
- IN CHAR8 *Errata
+EDKII_JSON_VALUE *
+MatchJsonObject (
+ IN EDKII_JSON_VALUE *JsonObj,
+ IN CHAR8 *ObjectName
)
{
- EFI_STATUS Status;
- EFI_HANDLE *HandleBuffer;
- UINTN NumberOfHandles;
- UINTN Index;
- EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *Protocol;
- REDFISH_SCHEMA_INFO SchemaInfo;
- BOOLEAN Found;
+ EDKII_JSON_VALUE N;
+ CHAR8 *Key;
+ EDKII_JSON_VALUE Value;

- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Major) ||
IS_EMPTY_STRING (Minor) || IS_EMPTY_STRING (Errata)) {
+ if (JsonObj == NULL || IS_EMPTY_STRING (ObjectName)) {
return NULL;
}

- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEdkIIRedfishResourceConfigProtocolGuid,
- NULL,
- &NumberOfHandles,
- &HandleBuffer
- );
- if (EFI_ERROR (Status)) {
+ if (!JsonValueIsObject (JsonObj)) {
return NULL;
}

- Found = FALSE;
-
- for (Index = 0; Index < NumberOfHandles; Index++) {
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEdkIIRedfishResourceConfigProtocolGuid,
- (VOID **) &Protocol
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- Status = Protocol->GetInfo (Protocol, &SchemaInfo);
- if (EFI_ERROR (Status)) {
- continue;
+ EDKII_JSON_OBJECT_FOREACH_SAFE (JsonObj, N, Key, Value) {
+ if (AsciiStrCmp (Key, ObjectName) == 0) {
+ return Value;
}
-
- if (AsciiStrCmp (Schema, SchemaInfo.Schema) == 0 &&
- AsciiStrCmp (Major, SchemaInfo.Major) == 0 &&
- AsciiStrCmp (Minor, SchemaInfo.Minor) == 0 &&
- AsciiStrCmp (Errata, SchemaInfo.Errata) == 0) {
- Found = TRUE;
- break;
- }
}

- FreePool (HandleBuffer);
-
- return (Found ? Protocol : NULL);
+ return NULL;
}

/**

- Get supported schema list by given specify schema name.
+ Check and see if given property is in JSON context or not

- @param[in] Schema Schema type name.
- @param[out] SchemaInfo Returned schema information.
+ @param[in] Property Property name string
+ @param[in] Json The JSON context to search.

- @retval EFI_SUCCESS Schema information is returned successfully.
- @retval Others Errors occur.
+ @retval TRUE Property is found in JSON context
+ @retval FALSE Property is not in JSON context

**/
-EFI_STATUS
-GetSupportedSchemaVersion (
- IN CHAR8 *Schema,
- OUT REDFISH_SCHEMA_INFO *SchemaInfo
+BOOLEAN
+MatchPropertyWithJsonContext (
+ IN EFI_STRING Property,
+ IN CHAR8 *Json
)
{
- EFI_STATUS Status;
- CHAR8 *SupportSchema;
- CHAR8 *SchemaName;
- UINTN Index;
- UINTN Index2;
- BOOLEAN Found;
+ CHAR8 *AsciiProperty;
+ CHAR8 *PropertyNode;
+ UINTN Index;
+ EDKII_JSON_VALUE *JsonObj;
+ EDKII_JSON_VALUE *MatchObj;
+ EDKII_JSON_TYPE JsonType;

- if (IS_EMPTY_STRING (Schema) || SchemaInfo == NULL) {
- return EFI_INVALID_PARAMETER;
+ if (IS_EMPTY_STRING (Property) || IS_EMPTY_STRING (Json)) {
+ return FALSE;
}

- Status = RedfishPlatformConfigGetSupportedSchema (NULL,
&SupportSchema);
- if (EFI_ERROR (Status)) {
- return Status;
+ JsonObj = JsonLoadString (Json, 0, NULL);
+ if (JsonObj == NULL || !JsonValueIsObject (JsonObj)) {
+ return FALSE;
}

- DEBUG ((DEBUG_INFO, "Supported schema: %a\n", SupportSchema));
-
- Index = 0;
- Found = FALSE;
- SchemaName = SupportSchema;
- while (TRUE) {
-
- if (SupportSchema[Index] == ';' || SupportSchema[Index] == '\0') {
- if (AsciiStrnCmp (&SchemaName[SCHEMA_NAME_PREFIX_OFFSET],
Schema, AsciiStrLen (Schema)) == 0) {
- Found = TRUE;
- SupportSchema[Index] = '\0';
- break;
- }
-
- SchemaName = &SupportSchema[Index + 1];
- }
-
- if (SupportSchema[Index] == '\0') {
- break;
- }
-
- ++Index;
+ AsciiProperty = StrUnicodeToAscii (Property);
+ if (AsciiProperty == NULL) {
+ return FALSE;
}

- if (Found) {
-
- AsciiStrCpyS (SchemaInfo->Schema, REDFISH_SCHEMA_STRING_SIZE,
Schema);
-
- //
- // forward to '.'
- //
- Index = 0;
- while (SchemaName[Index] != '\0' && SchemaName[Index] != '.') {
- ++Index;
- }
- ASSERT (SchemaName[Index] != '\0');
+ Index = 0;
+ PropertyNode = AsciiProperty;
+ MatchObj = JsonObj;

- //
- // Skip '.' and 'v'
- //
- Index += 2;
+ //
+ // Walk through property and find corresponding object in JSON input
+ //
+ while (AsciiProperty[Index] != '\0') {

- //
- // forward to '_'
- //
- Index2 = Index;
- while (SchemaName[Index2] != '\0' && SchemaName[Index2] != '_') {
- ++Index2;
+ if (AsciiProperty[Index] == '/') {
+ AsciiProperty[Index] = '\0';
+ MatchObj = MatchJsonObject (MatchObj, PropertyNode);
+ if (MatchObj == NULL) {
+ PropertyNode = NULL;
+ break;
+ }
+
+ PropertyNode = &AsciiProperty[Index + 1];
}
- ASSERT (SchemaName[Index2] != '\0');

- AsciiStrnCpyS (SchemaInfo->Major, REDFISH_SCHEMA_VERSION_SIZE,
&SchemaName[Index], (Index2 - Index));
- Index = Index2;
+ Index++;
+ }

- //
- // Skip '_'
- //
- ++Index;
+ if (PropertyNode != NULL) {
+ MatchObj = MatchJsonObject (MatchObj, PropertyNode);
+ }

+ //
+ // Value check
+ //
+ if (MatchObj != NULL) {
//
- // forward to '_'
+ // If object has empty value, treat it as not matching
//
- Index2 = Index;
- while (SchemaName[Index2] != '\0' && SchemaName[Index2] != '_') {
- ++Index2;
+ JsonType = JsonGetType (MatchObj);
+ switch (JsonType) {
+ case EdkiiJsonTypeObject:
+ if (JsonValueIsNull (MatchObj)) {
+ MatchObj = NULL;
+ }
+ break;
+ case EdkiiJsonTypeArray:
+ if (JsonArrayCount (MatchObj) == 0) {
+ MatchObj = NULL;
+ }
+ break;
+ case EdkiiJsonTypeString:
+ if (IS_EMPTY_STRING (JsonValueGetString (MatchObj))) {
+ MatchObj = NULL;
+ }
+ break;
+ case EdkiiJsonTypeNull:
+ MatchObj = NULL;
+ break;
+ default:
+ break;
}
- ASSERT (SchemaName[Index2] != '\0');
-
- AsciiStrnCpyS (SchemaInfo->Minor, REDFISH_SCHEMA_VERSION_SIZE,
&SchemaName[Index], (Index2 - Index));
- Index = Index2;
-
- //
- // Skip '_'
- //
- ++Index;
-
- AsciiStrCpyS (SchemaInfo->Errata, REDFISH_SCHEMA_VERSION_SIZE,
&SchemaName[Index]);
}

- FreePool (SupportSchema);
-
- return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
-}
-
-/**
-
- Return system root path. This is dummy function now.
+ FreePool (AsciiProperty);

- @retval NULL Can not find system root path.
- @retval Other System root path is returned.
-
-**/
-CHAR8 *
-RedfishGetSystemRootPath (
- VOID
- )
-{
- return AllocateCopyPool (AsciiStrSize (REDFISH_SYSTEM_ROOT_PATH),
REDFISH_SYSTEM_ROOT_PATH);
+ return (MatchObj == NULL ? FALSE : TRUE);
}

/**

- Get schema information by given protocol and service instance.
+ Create string array and append to arry node in Redfish JSON convert
format.

- @param[in] RedfishService Pointer to Redfish service instance.
- @param[in] JsonStructProtocol Json Structure protocol instance.
- @param[in] Uri Target URI.
- @param[out] SchemaInfo Returned schema information.
+ @param[in,out] Head The head of string array.
+ @param[in] StringArray Input string array.
+ @param[in] ArraySize The size of StringArray.

- @retval EFI_SUCCESS Schema information is returned successfully.
- @retval Others Errors occur.
+ @retval EFI_SUCCESS String array is created successfully.
+ @retval Others Error happens

**/
EFI_STATUS
-GetRedfishSchemaInfo (
- IN REDFISH_SERVICE *RedfishService,
- IN EFI_REST_JSON_STRUCTURE_PROTOCOL *JsonStructProtocol,
- IN CHAR8 *Uri,
- OUT REDFISH_SCHEMA_INFO *SchemaInfo
+AddRedfishCharArray (
+ IN OUT RedfishCS_char_Array **Head,
+ IN CHAR8 **StringArray,
+ IN UINTN ArraySize
)
{
- EFI_STATUS Status;
- REDFISH_RESPONSE Response;
- REDFISH_PAYLOAD Payload;
- CHAR8 *JsonText;
- EFI_REST_JSON_STRUCTURE_HEADER *Header;
+ UINTN Index;
+ RedfishCS_char_Array *CharArrayBuffer;
+ RedfishCS_char_Array *PreArrayBuffer;

- if (RedfishService == NULL || JsonStructProtocol == NULL ||
IS_EMPTY_STRING (Uri) || SchemaInfo == NULL) {
+ if (Head == NULL || StringArray == NULL || ArraySize == 0) {
return EFI_INVALID_PARAMETER;
}

- Status = GetResourceByPath (RedfishService, Uri, &Response);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, failed to get resource from %a %r",
__FUNCTION__, Uri, Status));
- return Status;
- }
-
- Payload = Response.Payload;
- ASSERT (Payload != NULL);
+ PreArrayBuffer = NULL;
+ for (Index = 0; Index < ArraySize; Index++) {
+ CharArrayBuffer = AllocatePool (sizeof (RedfishCS_char_Array));
+ if (CharArrayBuffer == NULL) {
+ ASSERT (CharArrayBuffer != NULL);
+ continue;
+ }

- JsonText = JsonDumpString (RedfishJsonInPayload (Payload),
EDKII_JSON_COMPACT);
- ASSERT (JsonText != NULL);
+ if (Index == 0) {
+ *Head = CharArrayBuffer;
+ }

- //
- // Convert JSON text to C structure.
- //
- Status = JsonStructProtocol->ToStructure (
- JsonStructProtocol,
- NULL,
- JsonText,
- &Header
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, ToStructure() failed: %r\n",
__FUNCTION__, Status));
- return Status;
+ CharArrayBuffer->ArrayValue = StringArray[Index];
+ CharArrayBuffer->Next = NULL;
+ if (PreArrayBuffer != NULL) {
+ PreArrayBuffer->Next = CharArrayBuffer;
+ }
+ PreArrayBuffer = CharArrayBuffer;
}

- AsciiStrCpyS (SchemaInfo->Schema, REDFISH_SCHEMA_STRING_SIZE,
Header->JsonRsrcIdentifier.NameSpace.ResourceTypeName);
- AsciiStrCpyS (SchemaInfo->Major, REDFISH_SCHEMA_VERSION_SIZE,
Header->JsonRsrcIdentifier.NameSpace.MajorVersion);
- AsciiStrCpyS (SchemaInfo->Minor, REDFISH_SCHEMA_VERSION_SIZE,
Header->JsonRsrcIdentifier.NameSpace.MinorVersion);
- AsciiStrCpyS (SchemaInfo->Errata, REDFISH_SCHEMA_VERSION_SIZE,
Header->JsonRsrcIdentifier.NameSpace.ErrataVersion);
-
- //
- // Release resource.
- //
- JsonStructProtocol->DestoryStructure (JsonStructProtocol, Header);
- FreePool (JsonText);
- RedfishFreeResponse (Response.StatusCode, Response.HeaderCount,
Response.Headers, Response.Payload);
-
return EFI_SUCCESS;
}

/**

- Get the property name by given Configure Langauge.
+ Create numeric array and append to arry node in Redfish JSON convert
format.

- @param[in] ConfigureLang Configure Language string.
+ @param[in,out] Head The head of string array.
+ @param[in] NumericArray Input numeric array.
+ @param[in] ArraySize The size of NumericArray.

- @retval EFI_STRING Pointer to property name.
- @retval NULL There is error.
+ @retval EFI_SUCCESS String array is created successfully.
+ @retval Others Error happens

**/
-EFI_STRING
-GetPropertyFromConfigureLang (
- IN EFI_STRING ConfigureLang
+EFI_STATUS
+AddRedfishNumericArray (
+ IN OUT RedfishCS_int64_Array **Head,
+ IN INT64 *NumericArray,
+ IN UINTN ArraySize
)
{
- EFI_STRING Property;
- UINTN Index;
+ UINTN Index;
+ RedfishCS_int64_Array *NumericArrayBuffer;
+ RedfishCS_int64_Array *PreArrayBuffer;

- if (ConfigureLang == NULL) {
- return NULL;
+ if (Head == NULL || NumericArray == NULL || ArraySize == 0) {
+ return EFI_INVALID_PARAMETER;
}

- Index = 0;
- Property = ConfigureLang;
-
- while (ConfigureLang[Index] != '\0') {
- if (ConfigureLang[Index] == L'/') {
- Property = &ConfigureLang[Index];
+ PreArrayBuffer = NULL;
+ for (Index = 0; Index < ArraySize; Index++) {
+ NumericArrayBuffer = AllocatePool (sizeof (RedfishCS_int64_Array));
+ if (NumericArrayBuffer == NULL) {
+ ASSERT (NumericArrayBuffer != NULL);
+ continue;
}

- ++Index;
+ if (Index == 0) {
+ *Head = NumericArrayBuffer;
+ }
+ NumericArrayBuffer->ArrayValue = AllocatePool (sizeof
(RedfishCS_int64));
+ if (NumericArrayBuffer->ArrayValue == NULL) {
+ ASSERT (NumericArrayBuffer->ArrayValue != NULL);
+ continue;
+ }
+ *NumericArrayBuffer->ArrayValue = NumericArray[Index];
+ NumericArrayBuffer->Next = NULL;
+ if (PreArrayBuffer != NULL) {
+ PreArrayBuffer->Next = NumericArrayBuffer;
+ }
+ PreArrayBuffer = NumericArrayBuffer;
}

- ++Property;
-
- return Property;
+ return EFI_SUCCESS;
}

/**

- Get the property value in string type.
+ Create boolean array and append to arry node in Redfish JSON convert
format.

- @param[in] Schema Schema of this property.
- @param[in] Version Schema version.
- @param[in] PropertyName Property name.
- @param[in] ConfigureLang Configure Language of this property.
+ @param[in,out] Head The head of string array.
+ @param[in] BooleanArray Input boolean array.
+ @param[in] ArraySize The size of BooleanArray.

- @retval CHAR8* Pointer to the CHAR8 buffer.
- @retval NULL There is error.
+ @retval EFI_SUCCESS String array is created successfully.
+ @retval Others Error happens

**/
-CHAR8 *
-GetPropertyStringValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang
+EFI_STATUS
+AddRedfishBooleanArray (
+ IN OUT RedfishCS_bool_Array **Head,
+ IN BOOLEAN *BooleanArray,
+ IN UINTN ArraySize
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
- EFI_STRING ConfigureLangBuffer;
- UINTN BufferSize;
- CHAR8 *AsciiStringValue;
+ UINTN Index;
+ RedfishCS_bool_Array *BooleanArrayBuffer;
+ RedfishCS_bool_Array *PreArrayBuffer;

- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName))
{
- return NULL;
+ if (Head == NULL || BooleanArrayBuffer == NULL || ArraySize == 0) {
+ return EFI_INVALID_PARAMETER;
}

- //
- // Configure Language buffer.
- //
- BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
- ConfigureLangBuffer = AllocatePool (BufferSize);
- if (ConfigureLangBuffer == NULL) {
- return NULL;
- }
+ PreArrayBuffer = NULL;
+ for (Index = 0; Index < ArraySize; Index++) {
+ BooleanArrayBuffer = AllocatePool (sizeof (RedfishCS_bool_Array));
+ if (BooleanArrayBuffer == NULL) {
+ ASSERT (BooleanArrayBuffer != NULL);
+ continue;
+ }

- UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s",
ConfigureLang,
PropertyName);
- Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
- return NULL;
- }
+ if (Index == 0) {
+ *Head = BooleanArrayBuffer;
+ }

- if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
- return NULL;
+ BooleanArrayBuffer->ArrayValue = AllocatePool (sizeof
(RedfishCS_bool));
+ if (BooleanArrayBuffer->ArrayValue == NULL) {
+ ASSERT (BooleanArrayBuffer->ArrayValue != NULL);
+ continue;
+ }
+ *BooleanArrayBuffer->ArrayValue = BooleanArray[Index];
+ BooleanArrayBuffer->Next = NULL;
+ if (PreArrayBuffer != NULL) {
+ PreArrayBuffer->Next = BooleanArrayBuffer;
+ }
+ PreArrayBuffer = BooleanArrayBuffer;
}

- AsciiStringValue = AllocateCopyPool (AsciiStrSize
(RedfishValue.Value.Buffer), RedfishValue.Value.Buffer);
- ASSERT (AsciiStringValue != NULL);
-
- return AsciiStringValue;
+ return EFI_SUCCESS;
}

/**

- Get the property value in numeric type.
+ Check and see if value in Redfish string array are all the same as the one
+ from HII configuration.

- @param[in] Schema Schema of this property.
- @param[in] Version Schema version.
- @param[in] PropertyName Property name.
- @param[in] ConfigureLang Configure Language of this property.
+ @param[in] Head The head of string array.
+ @param[in] StringArray Input string array.
+ @param[in] ArraySize The size of StringArray.

- @retval INT64* Pointer to the INT64 value.
- @retval NULL There is error.
+ @retval TRUE All string in Redfish array are as same as string
+ in HII configuration array.
+ FALSE These two array are not identical.

**/
-INT64 *
-GetPropertyNumericValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang
+BOOLEAN
+CompareRedfishStringArrayValues (
+ IN RedfishCS_char_Array *Head,
+ IN CHAR8 **StringArray,
+ IN UINTN ArraySize
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
- EFI_STRING ConfigureLangBuffer;
- UINTN BufferSize;
- INT64 *ResultValue;
+ UINTN Index;
+ RedfishCS_char_Array *CharArrayBuffer;

- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName))
{
- return NULL;
+ if (Head == NULL || StringArray == NULL || ArraySize == 0) {
+ return FALSE;
}

- //
- // Configure Language buffer.
- //
- BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
- ConfigureLangBuffer = AllocatePool (BufferSize);
- if (ConfigureLangBuffer == NULL) {
- return NULL;
- }
+ CharArrayBuffer = Head;
+ Index = 0;
+ while (CharArrayBuffer != NULL && Index < ArraySize) {

- UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s",
ConfigureLang,
PropertyName);
- Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
- return NULL;
- }
+ if (AsciiStrCmp (StringArray[Index], CharArrayBuffer->ArrayValue) != 0)
{
+ break;
+ }

- if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not numeric type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
- return NULL;
+ Index++;
+ CharArrayBuffer = CharArrayBuffer->Next;
}

- ResultValue = AllocatePool (sizeof (INT64));
- ASSERT (ResultValue != NULL);
- if (ResultValue == NULL) {
- return NULL;
+ if (CharArrayBuffer != NULL || Index < ArraySize) {
+ return FALSE;
}

- *ResultValue = RedfishValue.Value.Integer;
-
- return ResultValue;
+ return TRUE;
}

/**

- Get the property value in Boolean type.
+ Check and see if value in Redfish numeric array are all the same as the
one
+ from HII configuration.

- @param[in] Schema Schema of this property.
- @param[in] Version Schema version.
- @param[in] PropertyName Property name.
- @param[in] ConfigureLang Configure Language of this property.
+ @param[in] Head The head of Redfish CS numeraic array.
+ @param[in] NumericArray Input numeric array.
+ @param[in] ArraySize The size of NumericArray.

- @retval BOOLEAN Boolean value returned by this property.
+ @retval TRUE All string in Redfish array are as same as integer
+ in HII configuration array.
+ FALSE These two array are not identical.

**/
-BOOLEAN *
-GetPropertyBooleanValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang
+BOOLEAN
+CompareRedfishNumericArrayValues (
+ IN RedfishCS_int64_Array *Head,
+ IN INT64 *NumericArray,
+ IN UINTN ArraySize
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
- EFI_STRING ConfigureLangBuffer;
- UINTN BufferSize;
- BOOLEAN *ResultValue;
-
- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName))
{
- return NULL;
- }
+ UINTN Index;
+ RedfishCS_int64_Array *NumericArrayBuffer;

- //
- // Configure Language buffer.
- //
- BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
- ConfigureLangBuffer = AllocatePool (BufferSize);
- if (ConfigureLangBuffer == NULL) {
- return NULL;
+ if (Head == NULL || NumericArray == NULL || ArraySize == 0) {
+ return FALSE;
}

- UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s",
ConfigureLang,
PropertyName);
- Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
- return NULL;
- }
+ NumericArrayBuffer = Head;
+ Index = 0;
+ while (NumericArrayBuffer != NULL && Index < ArraySize) {
+ if (NumericArray[Index] != *NumericArrayBuffer->ArrayValue) {
+ break;
+ }

- if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not boolean type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
- return NULL;
+ Index++;
+ NumericArrayBuffer = NumericArrayBuffer->Next;
}

- ResultValue = AllocatePool (sizeof (BOOLEAN));
- ASSERT (ResultValue != NULL);
- if (ResultValue == NULL) {
- return NULL;
+ if (NumericArrayBuffer != NULL || Index < ArraySize) {
+ return FALSE;
}

- *ResultValue = RedfishValue.Value.Boolean;
-
- return ResultValue;
+ return TRUE;
}

/**

- Check and see if we need to do provisioning for this property.
+ Check and see if value in Redfish boolean array are all the same as the
one
+ from HII configuration.

- @param[in] PropertyBuffer Pointer to property instance.
- @param[in] ProvisionMode TRUE if we are in provision mode. FALSE
otherwise.
+ @param[in] Head The head of Redfish CS boolean array.
+ @param[in] BooleanArray Input boolean array.
+ @param[in] ArraySize The size of BooleanArray.

- @retval TRUE Provision is required.
- @retval FALSE Provision is not required.
+ @retval TRUE All string in Redfish array are as same as integer
+ in HII configuration array.
+ FALSE These two array are not identical.

**/
BOOLEAN
-PropertyChecker (
- IN VOID *PropertyBuffer,
- IN BOOLEAN ProvisionMode
+CompareRedfishBooleanArrayValues (
+ IN RedfishCS_bool_Array *Head,
+ IN BOOLEAN *BooleanArray,
+ IN UINTN ArraySize
)
{
- if (ProvisionMode && PropertyBuffer == NULL) {
- return TRUE;
+ UINTN Index;
+ RedfishCS_bool_Array *BooleanArrayBuffer;
+
+ if (Head == NULL || BooleanArray == NULL || ArraySize == 0) {
+ return FALSE;
}

- if (!ProvisionMode && PropertyBuffer != NULL) {
- return TRUE;
+ BooleanArrayBuffer = Head;
+ Index = 0;
+ while (BooleanArrayBuffer != NULL && Index < ArraySize) {
+ if (BooleanArray[Index] != *BooleanArrayBuffer->ArrayValue) {
+ break;
+ }
+
+ Index++;
+ BooleanArrayBuffer = BooleanArrayBuffer->Next;
}

- return FALSE;
+ if (BooleanArrayBuffer != NULL || Index < ArraySize) {
+ return FALSE;
+ }
+
+ return TRUE;
}

/**

- Check and see if we need to do provisioning for this two properties.
+ Check and see if any difference between two vague value set.
+ This is just a simple check.

- @param[in] PropertyBuffer1 Pointer to property instance 1.
- @param[in] PropertyBuffer2 Pointer to property instance 2.
- @param[in] ProvisionMode TRUE if we are in provision mode. FALSE
otherwise.
+ @param[in] RedfishVagueKeyValuePtr The vague key value sets on
Redfish service.
+ @param[in] RedfishVagueKeyValueNumber The numebr of vague key
value sets
+ @param[in] ConfigVagueKeyValuePtr The vague configuration on
platform.
+ @param[in] ConfigVagueKeyValueNumber The numebr of vague key
value sets

- @retval TRUE Provision is required.
- @retval FALSE Provision is not required.
+ @retval TRUE All values are the same.
+ FALSE There is some difference.

**/
BOOLEAN
-PropertyChecker2Parm (
- IN VOID *PropertyBuffer1,
- IN VOID *PropertyBuffer2,
- IN BOOLEAN ProvisionMode
+CompareRedfishPropertyVagueValues (
+ IN RedfishCS_EmptyProp_KeyValue *RedfishVagueKeyValuePtr,
+ IN UINT32 RedfishVagueKeyValueNumber,
+ IN RedfishCS_EmptyProp_KeyValue *ConfigVagueKeyValuePtr,
+ IN UINT32 ConfigVagueKeyValueNumber
)
-{
- if (ProvisionMode && (PropertyBuffer1 == NULL || PropertyBuffer2 ==
NULL)) {
- return TRUE;
- }
+ {
+ RedfishCS_EmptyProp_KeyValue *ThisConfigVagueKeyValuePtr;
+ RedfishCS_EmptyProp_KeyValue *ThisRedfishVagueKeyValuePtr;

- if (!ProvisionMode && PropertyBuffer1 != NULL && PropertyBuffer2 !=
NULL) {
- return TRUE;
+ if (RedfishVagueKeyValueNumber != ConfigVagueKeyValueNumber) {
+ return FALSE;
}

- return FALSE;
+ ThisConfigVagueKeyValuePtr = ConfigVagueKeyValuePtr;
+ //
+ // Loop through all key/value on system.
+ //
+ while (ThisConfigVagueKeyValuePtr != NULL) {
+ ThisRedfishVagueKeyValuePtr = RedfishVagueKeyValuePtr;
+ //
+ // Loop through all key/value on Redfish service..
+ //
+ while (ThisRedfishVagueKeyValuePtr != NULL) {
+ if (AsciiStrCmp(ThisConfigVagueKeyValuePtr->KeyNamePtr,
ThisRedfishVagueKeyValuePtr->KeyNamePtr) == 0) {
+ //
+ // Check the type of value.
+ //
+ if (ThisConfigVagueKeyValuePtr->Value->DataType !=
ThisRedfishVagueKeyValuePtr->Value->DataType) {
+ return FALSE;
+ }
+ //
+ // Check the value.
+ //
+ if (ThisConfigVagueKeyValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_String) {
+ //
+ // Is the string identical?
+ //
+ if (AsciiStrCmp (ThisConfigVagueKeyValuePtr->Value-
DataValue.CharPtr,
+ ThisRedfishVagueKeyValuePtr->Value->DataValue.CharPtr
+ ) == 0) {
+ break;
+ } else{
+ return FALSE;
+ }
+ } else if (ThisConfigVagueKeyValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_Int64) {
+ if (*ThisConfigVagueKeyValuePtr->Value->DataValue.Int64Ptr ==
*ThisRedfishVagueKeyValuePtr->Value->DataValue.Int64Ptr) {
+ break;
+ } else {
+ return FALSE;
+ }
+ } else if (ThisConfigVagueKeyValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_Bool) {
+ if ((UINT8)*ThisConfigVagueKeyValuePtr->Value-
DataValue.BoolPtr
== (UINT8)*ThisRedfishVagueKeyValuePtr->Value->DataValue.BoolPtr) {
+ break;
+ } else {
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+ }
+ ThisRedfishVagueKeyValuePtr = ThisRedfishVagueKeyValuePtr-
NextKeyValuePtr;
+ };
+ if (ThisRedfishVagueKeyValuePtr == NULL) {
+ //
+ // No matched key name. Threat these two vague value set is different.
+ //
+ return FALSE;
+ }
+ ThisConfigVagueKeyValuePtr = ThisConfigVagueKeyValuePtr-
NextKeyValuePtr;
+ };
+ return TRUE;
}

/**
diff --git
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.inf
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.inf
index f9f283fdcc..84f338e680 100644
---
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.inf
+++
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.inf
@@ -1,6 +1,6 @@
## @file
#
-# (C) Copyright 2020-2021 Hewlett Packard Enterprise Development
LP<BR>
+# (C) Copyright 2020-2022 Hewlett Packard Enterprise Development
LP<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -27,6 +27,7 @@
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
RedfishPkg/RedfishPkg.dec
RedfishClientPkg/RedfishClientPkg.dec

@@ -35,16 +36,25 @@
BaseMemoryLib
DebugLib
MemoryAllocationLib
- PrintLib
RedfishLib
RedfishPlatformConfigLib
UefiLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
+ PrintLib
+ HttpLib

[Protocols]
- gEdkIIRedfishETagProtocolGuid ## CONSUMED ##
+ gEdkIIRedfishETagProtocolGuid ## CONSUMED ##
+ gEdkIIRedfishConfigLangMapProtocolGuid ## CONSUMED ##

[Pcd]
- gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaStringSize
- gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaVersionSize
+
+[Guids]
+
+[BuildOptions]
+ #
+ # NOTE: /wd4706 disables the following Visual Studio compiler warning in
Jansson:
+ # "C4706: assignment within conditional expression"
+ #
+ MSFT:*_*_*_CC_FLAGS = /wd4706
--
2.32.0.windows.2


Re: [edk2-staging][PATCH v3 10/15] edk2-staging/RedfishClientPkg: Update Redfish feature utility library

Chang, Abner
 

[AMD Official Use Only - General]

Please search [Chang, Abner] for the comment.

-----Original Message-----
From: Nickle Wang <nickle.wang@...>
Sent: Wednesday, July 27, 2022 9:38 AM
To: devel@edk2.groups.io
Cc: Chang, Abner <Abner.Chang@...>; Yang, Atom
<Atom.Yang@...>; Nick Ramirez <nramirez@...>
Subject: [edk2-staging][PATCH v3 10/15] edk2-staging/RedfishClientPkg:
Update Redfish feature utility library

[CAUTION: External Email]

Update Redfish feature utility library in order to support array type
of resource. Some helper functions are introduced to get Redfish data.
Also expose RedfishCsCommon.h so that feature utility library can work
with Redfish C data structure without redundant structure conversion.

Signed-off-by: Nickle Wang <nickle.wang@...>
Cc: Abner Chang <abner.chang@...>
Cc: Yang Atom <Atom.Yang@...>
Cc: Nick Ramirez <nramirez@...>
---
.../Library/RedfishFeatureUtilityLib.h | 756 +++-
.../RedfishJsonStructure/RedfishCsCommon.h | 14 +
.../RedfishFeatureUtilityInternal.h | 16 +-
.../RedfishFeatureUtilityLib.c | 3662 +++++++++++++----
.../RedfishFeatureUtilityLib.inf | 20 +-
5 files changed, 3470 insertions(+), 998 deletions(-)
create mode 100644
RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h

diff --git a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
index 50ff82c70f..1325976d8c 100644
--- a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
+++ b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
@@ -1,7 +1,7 @@
/** @file
This file defines the Redfish Feature Utility Library interface.

- (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -10,8 +10,9 @@
#ifndef REDFISH_FEATURE_UTILITY_LIB_H_
#define REDFISH_FEATURE_UTILITY_LIB_H_

-#include <Protocol/EdkIIRedfishResourceConfigProtocol.h>
-#include <Protocol/RestJsonStructure.h>
+#include <Library/RedfishLib.h>
+#include <Protocol/EdkIIRedfishPlatformConfig.h>
+#include <RedfishJsonStructure/RedfishCsCommon.h>

//
// Definition of REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
@@ -31,10 +32,10 @@ typedef struct {

/**

- Read redfish resource by given resource path.
+ Read redfish resource by given resource URI.

@param[in] Service Redfish srvice instacne to make query.
- @param[in] ResourcePath Target resource path.
+ @param[in] ResourceUri Target resource URI.
@param[out] Response HTTP response from redfish service.

@retval EFI_SUCCESS Resrouce is returned successfully.
@@ -42,12 +43,34 @@ typedef struct {

**/
EFI_STATUS
-GetResourceByPath (
+GetResourceByUri (
IN REDFISH_SERVICE *Service,
- IN CHAR8 *ResourcePath,
+ IN EFI_STRING ResourceUri,
OUT REDFISH_RESPONSE *Response
);

+/**
+
+ Check if this is the Redpath array. Usually the Redpath array represents
+ the collection member. Return
+
+ @param[in] ConfigureLang The Redpath to check
+ @param[out] ArraySignatureOpen String to the open of array signature.
+ @param[out] ArraySignatureClose String to the close of array signature.
+
+ @retval EFI_SUCCESS Index is found.
+ @retval EFI_NOT_FOUND The non-array configure language string is
retured.
+ @retval EFI_INVALID_PARAMETER The format of input ConfigureLang is
wrong.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+IsRedpathArray (
+ IN EFI_STRING ConfigureLang,
+ OUT EFI_STRING *ArraySignatureOpen,
+ OUT EFI_STRING *ArraySignatureClose
+ );
+
/**

Search HII database with given Configure Language pattern. Data is handled
and
@@ -72,76 +95,142 @@ RedfishFeatureGetUnifiedArrayTypeConfigureLang (

/**

- Get array key by parsing the URI.
+ Clone the configure language list.

- @param[in] Uri URI with array key.
- @param[out] ArrayKey Array key in given URI string.
+ @param[in] ConfigureLangList The source
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
+ @param[out] DestConfigureLangList The destination
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.

- @retval EFI_SUCCESS Array key is found.
- @retval Others Errors occur.
+ @retval EFI_SUCCESS
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
+ @retval Others Errors occur.

**/
EFI_STATUS
-GetArraykeyFromUri (
- IN CHAR8 *Uri,
- OUT CHAR8 **ArrayKey
+CopyConfiglanguageList (
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*SourceConfigureLangList,
+ OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*DestConfigureLangList
);

/**

- Keep configure language with given key in UEFI variable.
+ Get number of node from the string. Node is seperated by '/'.

- @param[in] Schema Schema name.
- @param[in] Version Schema version.
- @param[in] Key Key string.
- @param[in] ConfigureLangIndex Index value.
+ @param[in] NodeString The node string to parse.

- @retval EFI_SUCCESS Data is saved in UEFI variable.
- @retval Others Errors occur.
+ @retval UINTN Number of nodes in the string.
+
+**/
+UINTN
+GetNumberOfRedpathNodes (
+ IN EFI_STRING NodeString
+ );
+
+/**
+
+ Get the node string by index
+
+ @param[in] NodeString The node string to parse.
+ @param[in] Index Index of the node.
+ @param[out] EndOfNodePtr Pointer to receive the poitner to
+ the last character of node string.
+
+ @retval EFI_STRING the begining of the node string.
+
+**/
+EFI_STRING
+GetRedpathNodeByIndex (
+ IN EFI_STRING NodeString,
+ IN UINTN Index,
+ OUT EFI_STRING *EndOfNodePtr OPTIONAL
+ );
+
+/**
+
+ Find array index from given configure language string.
+
+ @param[in] ConfigureLang Configure language string to parse.
+ @param[out] UnifiedConfigureLang The configure language in array.
+ @param[out] Index The array index number.
+
+ @retval EFI_SUCCESS Index is found.
+ @retval EFI_NOT_FOUND The non-array configure language string is
retured.
+ @retval EFI_INVALID_PARAMETER The format of input ConfigureLang is
wrong.
+ @retval Others Errors occur.

**/
EFI_STATUS
-SetConfigureLangWithkey (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN CHAR8 *Key,
- IN UINTN ConfigureLangIndex
+GetArrayIndexFromArrayTypeConfigureLang (
+ IN CHAR16 *ConfigureLang,
+ OUT CHAR16 **UnifiedConfigureLang,
+ OUT UINTN *Index
);

/**

- Find configure language with input key string.
+ Clone the configure language list.
+
+ @param[in] ConfigureLang The pointer to configuration language.

- @param[in] Schema Schema name.
- @param[in] Version Schema version.
- @param[in] Property Property name.
- @param[in] Key Key string.
+ @retval UINTN The index of collection member instance.
+ Value of 0 means no instance is found.
+**/
+UINTN
+ConfiglanguageGetInstanceIndex (
+ IN EFI_STRING ConfigureLang
+ );

- @retval CHAR16 * Corresponding configure langauge
- @retval NULL No configure language is found
+/**
+
+ Destroy the configure language list.
+
+ @param[in] ConfigureLangList The
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
+ instance to destroy.
+
+ @retval EFI_SUCCESS
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
+ @retval Others Errors occur.

**/
-CHAR16 *
-GetConfigureLangByKey (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN CHAR8 *Property,
- IN CHAR8 *Key
+EFI_STATUS
+DestroyConfiglanguageList (
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*ConfigureLangList
);

/**

- Convert HII string value to string value in JSON format.
+ Set the node instance.

- @param[in] HiiStringValue String in HII format.
+ @param[in] DestConfigLang Pointer to the node's configure language
string.
+ The memory pointed by ConfigLang must be allocated
+ through memory allocation interface. Becasue we will
replace
+ the pointer in this function.
+ @param[in] MaxtLengthConfigLang The maximum length of ConfigLang.
+ @param[in] ConfigLangInstance Pointer to Collection member instance.

- @retval CHAR8 * String in JSON format.
- @retval NULL Errors occur.
+ @retval EFI_SUCCESS The instance is inserted to the configure
language.
+ @retval Others Errors occur.

**/
-CHAR8 *
-ConvertHiiStringValueToJsonStringValue (
- IN EFI_STRING HiiStringValue
+EFI_STATUS
+SetResourceConfigLangMemberInstance (
+ IN EFI_STRING *DestConfigLang,
+ IN UINTN MaxtLengthConfigLang,
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *ConfigLangInstance
+ );
+
+/**
+
+ Get array key by parsing the URI.
+
+ @param[in] Uri URI with array key.
+ @param[out] ArrayKey Array key in given URI string.
+
+ @retval EFI_SUCCESS Array key is found.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+GetArraykeyFromUri (
+ IN CHAR8 *Uri,
+ OUT CHAR8 **ArrayKey
);

/**
@@ -209,125 +298,157 @@ ApplyFeatureSettingsBooleanType (

/**

- Create HTTP payload and send them to redfish service with POST method.
+ Apply property value to UEFI HII database in vague type.

- @param[in] Service Redfish service.
- @param[in] TargetPayload Target payload
- @param[in] Json Data in JSON format.
- @param[out] Location Returned location string from Redfish service.
- @param[out] Etag Returned ETAG string from Redfish service.
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] VagueValuePtr Pointer of vague values to to set.
+ @param[in] NumVagueValues Number of vague values.

- @retval EFI_SUCCESS Data is sent to redfish service successfully.
+ @retval EFI_SUCCESS New value is applied successfully.
@retval Others Errors occur.

**/
EFI_STATUS
-CreatePayloadToPostResource (
- IN REDFISH_SERVICE *Service,
- IN REDFISH_PAYLOAD *TargetPayload,
- IN CHAR8 *Json,
- OUT CHAR8 **Location,
- OUT CHAR8 **Etag
+ApplyFeatureSettingsVagueType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_EmptyProp_KeyValue *VagueValuePtr,
+ IN UINT32 NumberOfVagueValues
);

/**

- Create HTTP payload and send them to redfish service with PATCH method.
+ Apply property value to UEFI HII database in string array type.

- @param[in] Service Redfish service.
- @param[in] TargetPayload Target payload
- @param[in] Json Data in JSON format.
- @param[out] Etag Returned ETAG string from Redfish service.
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] ArrayHead Head of array value.

- @retval EFI_SUCCESS Data is sent to redfish service successfully.
+ @retval EFI_SUCCESS New value is applied successfully.
@retval Others Errors occur.

**/
EFI_STATUS
-CreatePayloadToPatchResource (
- IN REDFISH_SERVICE *Service,
- IN REDFISH_PAYLOAD *TargetPayload,
- IN CHAR8 *Json,
- OUT CHAR8 **Etag
+ApplyFeatureSettingsStringArrayType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_char_Array *ArrayHead
);

/**

- Find Redfish Resource Config Protocol that supports given schema and
version.
+ Apply property value to UEFI HII database in numeric array type (INT64).

- @param[in] Schema Schema name.
- @param[in] Major Schema version major number.
- @param[in] Minor Schema version minor number.
- @param[in] Errata Schema version errata number.
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] ArrayHead Head of array value.

- @retval EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL * Pointer to
protocol
- @retval NULL No protocol found.
+ @retval EFI_SUCCESS New value is applied successfully.
+ @retval Others Errors occur.

**/
-EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *
-GetRedfishResourceConfigProtocol (
- IN CHAR8 *Schema,
- IN CHAR8 *Major,
- IN CHAR8 *Minor,
- IN CHAR8 *Errata
+EFI_STATUS
+ApplyFeatureSettingsNumericArrayType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_int64_Array *ArrayHead
);

/**

- Get supported schema list by given specify schema name.
+ Apply property value to UEFI HII database in boolean array type (INT64).

- @param[in] Schema Schema type name.
- @param[out] SchemaInfo Returned schema information.
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] ArrayHead Head of Redfich CS boolean array value.

- @retval EFI_SUCCESS Schema information is returned successfully.
- @retval Others Errors occur.
+ @retval EFI_SUCCESS New value is applied successfully.
+ @retval Others Errors occur.

**/
EFI_STATUS
-GetSupportedSchemaVersion (
- IN CHAR8 *Schema,
- OUT REDFISH_SCHEMA_INFO *SchemaInfo
+ApplyFeatureSettingsBooleanArrayType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_bool_Array *ArrayHead
);

/**

- Return system root path
+ Create HTTP payload and send them to redfish service with POST method.
+
+ @param[in] Service Redfish service.
+ @param[in] TargetPayload Target payload
+ @param[in] Json Data in JSON format.
+ @param[out] Location Returned location string from Redfish service.
+ @param[out] Etag Returned ETAG string from Redfish service.

- @retval NULL Can not find system root path.
- @retval Other System root path is returned.
+ @retval EFI_SUCCESS Data is sent to redfish service successfully.
+ @retval Others Errors occur.

**/
-CHAR8 *
-RedfishGetSystemRootPath (
- VOID
+EFI_STATUS
+CreatePayloadToPostResource (
+ IN REDFISH_SERVICE *Service,
+ IN REDFISH_PAYLOAD *TargetPayload,
+ IN CHAR8 *Json,
+ OUT EFI_STRING *Location,
+ OUT CHAR8 **Etag
);

/**

- Get schema information by given protocol and service instance.
+ Create HTTP payload and send them to redfish service with PATCH method.

- @param[in] RedfishService Pointer to Redfish service instance.
- @param[in] JsonStructProtocol Json Structure protocol instance.
- @param[in] Uri Target URI.
- @param[out] SchemaInfo Returned schema information.
+ @param[in] Service Redfish service.
+ @param[in] TargetPayload Target payload
+ @param[in] Json Data in JSON format.
+ @param[out] Etag Returned ETAG string from Redfish service.

- @retval EFI_SUCCESS Schema information is returned successfully.
- @retval Others Errors occur.
+ @retval EFI_SUCCESS Data is sent to redfish service successfully.
+ @retval Others Errors occur.

**/
EFI_STATUS
-GetRedfishSchemaInfo (
- IN REDFISH_SERVICE *RedfishService,
- IN EFI_REST_JSON_STRUCTURE_PROTOCOL *JsonStructProtocol,
- IN CHAR8 *Uri,
- OUT REDFISH_SCHEMA_INFO *SchemaInfo
+CreatePayloadToPatchResource (
+ IN REDFISH_SERVICE *Service,
+ IN REDFISH_PAYLOAD *TargetPayload,
+ IN CHAR8 *Json,
+ OUT CHAR8 **Etag
+ );
+
+/**
+
+ Save Redfish URI in database for further use.
+
+ @param[in] ConfigLang ConfigLang to save
+ @param[in] Uri Redfish Uri to save
+
+ @retval EFI_INVALID_PARAMETR SystemId is NULL or EMPTY
+ @retval EFI_SUCCESS Redfish uri is saved
+
+**/
+EFI_STATUS
+RedfisSetRedfishUri (
+ IN EFI_STRING ConfigLang,
+ IN EFI_STRING Uri
);

/**

Get the property name by given Configure Langauge.

- @param[in] ConfigureLang Configure Language string.
+ @param[in] ResourceUri URI of root of resource.
+ @param[in] ConfigureLang Configure Language string.

@retval EFI_STRING Pointer to property name.
@retval NULL There is error.
@@ -335,6 +456,7 @@ GetRedfishSchemaInfo (
**/
EFI_STRING
GetPropertyFromConfigureLang (
+ IN EFI_STRING ResourceUri,
IN EFI_STRING ConfigureLang
);

@@ -417,25 +539,6 @@ PropertyChecker (
IN BOOLEAN ProvisionMode
);

-/**
-
- Check and see if we need to do provisioning for this two properties.
-
- @param[in] PropertyBuffer1 Pointer to property instance 1.
- @param[in] PropertyBuffer2 Pointer to property instance 2.
- @param[in] ProvisionMode TRUE if we are in provision mode. FALSE
otherwise.
-
- @retval TRUE Provision is required.
- @retval FALSE Provision is not required.
-
-**/
-BOOLEAN
-PropertyChecker2Parm (
- IN VOID *PropertyBuffer1,
- IN VOID *PropertyBuffer2,
- IN BOOLEAN ProvisionMode
- );
-
/**

Keep ETAG string and URI string in database.
@@ -450,7 +553,7 @@ PropertyChecker2Parm (
EFI_STATUS
SetEtagWithUri (
IN CHAR8 *EtagStr,
- IN CHAR8 *Uri
+ IN EFI_STRING Uri
);

/**
@@ -465,7 +568,396 @@ SetEtagWithUri (
**/
CHAR8 *
GetEtagWithUri (
- IN CHAR8 *Uri
+ IN EFI_STRING Uri
+ );
+
+/**
+
+ Get @odata.id from give HTTP payload. It's call responsibility to release
returned buffer.
+
+ @param[in] Payload HTTP payload
+
+ @retval NULL Can not find @odata.id from given payload.
+ @retval Others odata.id string is returned.
+
+**/
+EFI_STRING
+GetOdataId (
+ IN REDFISH_PAYLOAD *Payload
+ );
+
+/**
+
+ Return config language from given URI and prperty name. It's call
responsibility to release returned buffer.
+
+ @param[in] Uri The URI to match
+ @param[in] PropertyName The property name of resource. This is
optional.
+
+ @retval NULL Can not find redfish uri.
+ @retval Other redfish uri is returned.
+
+**/
+EFI_STRING
+GetConfigureLang (
+ IN CHAR8 *Uri,
+ IN CHAR8 *PropertyName OPTIONAL
+ );
+
+/**
+
+ Return redfish URI by given config language. It's call responsibility to
release returned buffer.
+
+ @param[in] ConfigLang ConfigLang to search.
+
+ @retval NULL Can not find redfish uri.
+ @retval Other redfish uri is returned.
+
+**/
+EFI_STRING
+RedfishGetUri (
+ IN EFI_STRING ConfigLang
+ );
+
+/**
+
+ Return config language by given URI. It's call responsibility to release
returned buffer.
+
+ @param[in] Uri Uri to search.
+
+ @retval NULL Can not find redfish uri.
+ @retval Other redfish uri is returned.
+
+**/
+EFI_STRING
+RedfishGetConfigLanguage (
+ IN EFI_STRING Uri
+ );
+
+/**
+
+ Convert Unicode string to ASCII string. It's call responsibility to release
returned buffer.
+
+ @param[in] UnicodeStr Unicode string to convert.
+
+ @retval CHAR8 * ASCII string returned.
+ @retval NULL Errors occur.
+
+**/
+CHAR8 *
+StrUnicodeToAscii (
+ IN EFI_STRING UnicodeStr
+ );
+
+/**
+
+ Convert ASCII string to Unicode string. It's call responsibility to release
returned buffer.
+
+ @param[in] AsciiStr ASCII string to convert.
+
+ @retval EFI_STRING Unicode string returned.
+ @retval NULL Errors occur.
+
+**/
+EFI_STRING
+StrAsciiToUnicode (
+ IN CHAR8 *AsciiStr
+ );
+
+/**
+
+ Check and see if ETAG is identical to what we keep in system.
+
+ @param[in] Uri URI requested
+ @param[in] EtagInHeader ETAG string returned from HTTP request.
+ @param[in] EtagInJson ETAG string in JSON body.
+
+ @retval TRUE ETAG is identical.
+ @retval FALSE ETAG is changed.
+
+**/
+BOOLEAN
+CheckEtag (
+ IN EFI_STRING Uri,
+ IN CHAR8 *EtagInHeader,
+ IN CHAR8 *EtagInJson
+ );
+
+/**
+
+ Get the property string value in array type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] ArraySize The size of returned array.
+
+ @retval CHAR8 ** Returned string array. NULL while error happens.
+
+**/
+CHAR8 **
+GetPropertyStringArrayValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
+ );
+
+/**
+
+ Get the property numeric value in array type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] ArraySize The size of returned array.
+
+ @retval INT64 ** Returned integer array. NULL while error happens.
+
+**/
+INT64 *
+GetPropertyNumericArrayValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
+ );
+
+/**
+
+ Get the property boolean value in array type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] ArraySize The size of returned array.
+
+ @retval BOOLEAN * Returned boolean array. NULL while error
happens.
+
+**/
+BOOLEAN *
+GetPropertyBooleanArrayValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
+ );
+
+/**
+
+ Get the property value in the vague type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] NumberOfValues Return the number of vague type of
values
+
+ @retval RedfishCS_EmptyProp_KeyValue The pointer to the structure
+ of vague type of values.
+
+**/
+RedfishCS_EmptyProp_KeyValue *
+GetPropertyVagueValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINT32 *NumberOfValues
+ );
+
+/**
+
+ Free the list of empty property key values.
+
+ @param[in] EmptyPropKeyValueListHead The head of
RedfishCS_EmptyProp_KeyValue
+
+**/
+VOID
+FreeEmptyPropKeyValueList (
+ RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueListHead
+ );
+
+/**
+
+ Check and see if given property is in JSON context or not
+
+ @param[in] Property Property name string
+ @param[in] Json The JSON context to search.
+
+ @retval TRUE Property is found in JSON context
+ @retval FALSE Property is not in JSON context
+
+**/
+BOOLEAN
+MatchPropertyWithJsonContext (
+ IN EFI_STRING Property,
+ IN CHAR8 *Json
+);
+
+/**
+
+ Create string array and append to arry node in Redfish JSON convert
format.
+
+ @param[in,out] Head The head of string array.
+ @param[in] StringArray Input string array.
+ @param[in] ArraySize The size of StringArray.
+
+ @retval EFI_SUCCESS String array is created successfully.
+ @retval Others Error happens
+
+**/
+EFI_STATUS
+AddRedfishCharArray (
+ IN OUT RedfishCS_char_Array **Head,
+ IN CHAR8 **StringArray,
+ IN UINTN ArraySize
+ );
+
+/**
+
+ Create numeric array and append to arry node in Redfish JSON convert
format.
+
+ @param[in,out] Head The head of string array.
+ @param[in] NumericArray Input numeric array.
+ @param[in] ArraySize The size of StringArray.
+
+ @retval EFI_SUCCESS String array is created successfully.
+ @retval Others Error happens
+
+**/
+EFI_STATUS
+AddRedfishNumericArray (
+ IN OUT RedfishCS_int64_Array **Head,
+ IN INT64 *NumericArray,
+ IN UINTN ArraySize
+ );
+
+/**
+
+ Create boolean array and append to arry node in Redfish JSON convert
format.
+
+ @param[in,out] Head The head of string array.
+ @param[in] BooleanArray Input boolean array.
+ @param[in] ArraySize The size of BooleanArray.
+
+ @retval EFI_SUCCESS String array is created successfully.
+ @retval Others Error happens
+
+**/
+EFI_STATUS
+AddRedfishBooleanArray (
+ IN OUT RedfishCS_bool_Array **Head,
+ IN BOOLEAN *BooleanArray,
+ IN UINTN ArraySize
+ );
+/**
+
+ Check and see if value in Redfish string array are all the same as the one
+ from HII configuration.
+
+ @param[in] Head The head of string array.
+ @param[in] StringArray Input string array.
+ @param[in] ArraySize The size of StringArray.
+
+ @retval TRUE All string in Redfish array are as same as string
+ in HII configuration array.
+ FALSE These two array are not identical.
+
+**/
+BOOLEAN
+CompareRedfishStringArrayValues (
+ IN RedfishCS_char_Array *Head,
+ IN CHAR8 **StringArray,
+ IN UINTN ArraySize
+ );
+
+/**
+
+ Check and see if value in Redfish numeric array are all the same as the one
+ from HII configuration.
+
+ @param[in] Head The head of Redfish CS numeraic array.
+ @param[in] NumericArray Input numeric array.
+ @param[in] ArraySize The size of NumericArray.
+
+ @retval TRUE All string in Redfish array are as same as integer
+ in HII configuration array.
+ FALSE These two array are not identical.
+
+**/
+BOOLEAN
+CompareRedfishNumericArrayValues (
+ IN RedfishCS_int64_Array *Head,
+ IN INT64 *NumericArray,
+ IN UINTN ArraySize
+ );
+
+/**
+
+ Check and see if value in Redfish boolean array are all the same as the one
+ from HII configuration.
+
+ @param[in] Head The head of Redfish CS boolean array.
+ @param[in] BooleanArray Input boolean array.
+ @param[in] ArraySize The size of BooleanArray.
+
+ @retval TRUE All string in Redfish array are as same as integer
+ in HII configuration array.
+ FALSE These two array are not identical.
+
+**/
+BOOLEAN
+CompareRedfishBooleanArrayValues (
+ IN RedfishCS_bool_Array *Head,
+ IN BOOLEAN *BooleanArray,
+ IN UINTN ArraySize
+ );
+
+/**
+
+ Check and see if any difference between two vague value set.
+ This is just a simple check.
+
+ @param[in] RedfishVagueKeyValuePtr The vague key value sets on
Redfish service.
+ @param[in] RedfishVagueKeyValueNumber The numebr of vague key
value sets
+ @param[in] ConfigVagueKeyValuePtr The vague configuration on
platform.
+ @param[in] ConfigVagueKeyValueNumber The numebr of vague key
value sets
+
+ @retval TRUE All values are the same.
+ FALSE There is some difference.
+
+**/
+BOOLEAN
+CompareRedfishPropertyVagueValues (
+ IN RedfishCS_EmptyProp_KeyValue *RedfishVagueKeyValuePtr,
+ IN UINT32 RedfishVagueKeyValueNumber,
+ IN RedfishCS_EmptyProp_KeyValue *ConfigVagueKeyValuePtr,
+ IN UINT32 ConfigVagueKeyValueNumber
+ );
+
+/**
+
+ Find "ETag" and "Location" from either HTTP header or Redfish response.
+
+ @param[in] Response HTTP response
+ @param[out] Etag String buffer to return ETag
+ @param[out] Location String buffer to return Location
+
+ @retval EFI_SUCCESS Data is found and returned.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+GetEtagAndLocation (
+ IN REDFISH_RESPONSE *Response,
+ OUT CHAR8 **Etag, OPTIONAL
+ OUT EFI_STRING *Location OPTIONAL
);

#endif
diff --git
a/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h
b/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h
new file mode 100644
index 0000000000..4d0ae50fc8
--- /dev/null
+++ b/RedfishClientPkg/Include/RedfishJsonStructure/RedfishCsCommon.h
@@ -0,0 +1,14 @@
+/** @file
+ Wrapper file for RedfishCsCommon.h
+
+ (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef WRAPPER_REDFISH_CS_COMMON_H_
+#define WRAPPER_REDFISH_CS_COMMON_H_
+
+#include "ConverterLib/include/RedfishCsCommon.h"
+
+#endif
diff --git
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
ernal.h
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
ernal.h
index 7d38d327ef..38d2af52b2 100644
---
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
ernal.h
+++
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityInt
ernal.h
@@ -1,7 +1,7 @@
/** @file
Common header file for RedfishFeatureUtilityLib driver.

- (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -11,33 +11,39 @@
#define REDFISH_FEATURE_INTERNAL_H_

#include <Uefi.h>
+#include <RedfishBase.h>
+
+#include <IndustryStandard/Http11.h>

#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/JsonLib.h>
#include <Library/MemoryAllocationLib.h>
-#include <Library/PrintLib.h>
-#include <Library/PcdLib.h>
#include <Library/RedfishLib.h>
#include <Library/RedfishFeatureUtilityLib.h>
#include <Library/RedfishPlatformConfigLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HttpLib.h>

#include <Guid/VariableFormat.h>

#include <Protocol/EdkIIRedfishETagProtocol.h>
+#include <Protocol/EdkIIRedfishConfigLangMapProtocol.h>

#define INDEX_VARIABLE_SIZE 64
#define INDEX_STRING_SIZE 16
-#define IS_EMPTY_STRING(a) (a == NULL || a[0] == '\0')
#define INDEX_STRING L"{%d}"
#define SCHEMA_NAME_PREFIX "x-uefi-redfish-"
#define SCHEMA_NAME_PREFIX_OFFSET (AsciiStrLen
(SCHEMA_NAME_PREFIX))
-#define REDFISH_SYSTEM_ROOT_PATH "/v1/Systems[UUID~%g]"
+#define REDFISH_ROOT_PATH "/v1"
+#define REDFISH_ROOT_PATH_UNICODE L"/v1"
#define MAX_CONF_LANG_LEN 128
+#define MAX_REDFISH_URL_LEN 255
+#define REGULAR_EXPRESSION_ARRAY L"\\[.*\\]/.*"

#define BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE
L"{"
#define BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE
L"}"
diff --git
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.c
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.c
index cf8696e5f0..2bd7f58f9c 100644
---
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.c
+++
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.c
@@ -1,7 +1,7 @@
/** @file
Redfish feature utility library implementation

- (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -9,7 +9,34 @@

#include "RedfishFeatureUtilityInternal.h"

-EDKII_REDFISH_ETAG_PROTOCOL *mEtagProtocol;
+EDKII_REDFISH_ETAG_PROTOCOL *mEtagProtocol = NULL;
+EDKII_REDFISH_CONFIG_LANG_MAP_PROTOCOL
*mConfigLangMapProtocol = NULL;
+
+
+EFI_STATUS
+RedfishLocateProtocol (
[Chang, Abner]
The function header is missed.
Abner

+ IN VOID **ProtocolInstance,
+ IN EFI_GUID *ProtocolGuid
+ )
+{
+ EFI_STATUS Status;
+
+ if (ProtocolInstance == NULL || ProtocolGuid == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*ProtocolInstance != NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = gBS->LocateProtocol (
+ ProtocolGuid,
+ NULL,
+ ProtocolInstance
+ );
+ return Status;
+}
+

/**

@@ -71,227 +98,168 @@ GetArraykeyFromUri (

/**

- Keep configure language with given key in UEFI variable.
+ Keep ETAG string and URI string in database.

- @param[in] Schema Schema name.
- @param[in] Version Schema version.
- @param[in] Key Key string.
- @param[in] ConfigureLangIndex Index value.
+ @param[in] EtagStr ETAG string.
+ @param[in] Uri URI string.

- @retval EFI_SUCCESS Data is saved in UEFI variable.
- @retval Others Errors occur.
+ @retval EFI_SUCCESS ETAG and URI are applied successfully.
+ @retval Others Errors occur.

**/
EFI_STATUS
-SetConfigureLangWithkey (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN CHAR8 *Key,
- IN UINTN ConfigureLangIndex
+SetEtagWithUri (
+ IN CHAR8 *EtagStr,
+ IN EFI_STRING Uri
)
{
- CHAR16 IndexString[INDEX_STRING_SIZE];
- CHAR16 VarName[INDEX_VARIABLE_SIZE];
- CHAR16 *VarData;
- EFI_STATUS Status;
- //
- // Variable content.
- //
- UnicodeSPrint (IndexString, sizeof (IndexString), INDEX_STRING,
ConfigureLangIndex);
+ EFI_STATUS Status;
+ CHAR8 *AsciiUri;

- //
- // Variable name.
- //
- UnicodeSPrint (VarName, sizeof (VarName), L"%a_%a_%a", Schema,
Version, Key);
+ if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }

- //
- // Check if it exists already.
- //
- Status = GetVariable2 (
- VarName,
- &gEfiCallerIdGuid,
- (VOID *)&VarData,
- NULL
- );
- if (!EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "%a, remove stale data: %s\n", __FUNCTION__,
VarData));
- FreePool (VarData);
- gRT->SetVariable (VarName, &gEfiCallerIdGuid,
VARIABLE_ATTRIBUTE_NV_BS, 0, NULL);
+ Status = RedfishLocateProtocol ((VOID **)&mEtagProtocol,
&gEdkIIRedfishETagProtocolGuid);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, fail to locate
gEdkIIRedfishETagProtocolGuid: %r\n", __FUNCTION__, Status));
+ return Status;
}

- return gRT->SetVariable (VarName, &gEfiCallerIdGuid,
VARIABLE_ATTRIBUTE_NV_BS, StrSize (IndexString), (VOID *)&IndexString);
+ AsciiUri = StrUnicodeToAscii (Uri);
+ if (AsciiUri == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mEtagProtocol->Set (mEtagProtocol, AsciiUri, EtagStr);
+ mEtagProtocol->Flush (mEtagProtocol);
+
+ FreePool (AsciiUri);
+
+ return EFI_SUCCESS;
}

/**

- Find configure language with input key string.
+ Find ETAG string that refers to given URI.

- @param[in] Schema Schema name.
- @param[in] Version Schema version.
- @param[in] Property Property name.
- @param[in] Key Key string.
+ @param[in] Uri Target URI string.

- @retval CHAR16 * Corresponding configure langauge
- @retval NULL No configure language is found
+ @retval CHAR8 * ETAG string
+ @retval NULL No ETAG is found.

**/
-CHAR16 *
-GetConfigureLangByKey (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN CHAR8 *Property, OPTIONAL
- IN CHAR8 *Key
+CHAR8 *
+GetEtagWithUri (
+ IN EFI_STRING Uri
)
{
- EFI_STATUS Status;
- CHAR16 VariableName[64];
- UINTN VariableSize;
- CHAR16 *CollectionIndex;
- CHAR16 *ConfigureLang;
- UINTN ConfigureLangLen;
+ EFI_STATUS Status;
+ CHAR8 *AsciiUri;
+ CHAR8 *EtagStr;

- if (Schema == NULL || Version == NULL || Key == NULL) {
+ if (IS_EMPTY_STRING (Uri)) {
return NULL;
}

- CollectionIndex = NULL;
- ConfigureLang = NULL;
-
- UnicodeSPrint (VariableName, 64, L"%a_%a_%a", Schema, Version, Key);
-
- Status = GetVariable2 (
- VariableName,
- &gEfiCallerIdGuid,
- (VOID *)&CollectionIndex,
- &VariableSize
- );
+ Status = RedfishLocateProtocol ((VOID **)&mEtagProtocol,
&gEdkIIRedfishETagProtocolGuid);
if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, fail to locate
gEdkIIRedfishETagProtocolGuid: %r\n", __FUNCTION__, Status));
return NULL;
}

- ConfigureLangLen = AsciiStrLen (Schema) + StrLen (CollectionIndex) +
(Property == NULL ? 0 : AsciiStrLen (Property)) + 3 + 1;
- ConfigureLang = AllocatePool (sizeof (CHAR16) * ConfigureLangLen);
- ASSERT (ConfigureLang);
-
- if (Property != NULL) {
- UnicodeSPrint (ConfigureLang, sizeof (CHAR16) * ConfigureLangLen,
L"/%a/%s/%a", Schema, CollectionIndex, Property);
- } else {
- UnicodeSPrint (ConfigureLang, sizeof (CHAR16) * ConfigureLangLen,
L"/%a/%s", Schema, CollectionIndex);
+ AsciiUri = StrUnicodeToAscii (Uri);
+ if (AsciiUri == NULL) {
+ return NULL;
}

- FreePool (CollectionIndex);
-
- return ConfigureLang;
-}
-
-/**
-
- Keep ETAG string and URI string in database.
-
- @param[in] EtagStr ETAG string.
- @param[in] Uri URI string.
-
- @retval EFI_SUCCESS ETAG and URI are applied successfully.
- @retval Others Errors occur.
-
-**/
-EFI_STATUS
-SetEtagWithUri (
- IN CHAR8 *EtagStr,
- IN CHAR8 *Uri
- )
-{
- EFI_STATUS Status;
+ Status = mEtagProtocol->Get (mEtagProtocol, AsciiUri, &EtagStr);

- if (IS_EMPTY_STRING (EtagStr) || IS_EMPTY_STRING (Uri)) {
- return EFI_INVALID_PARAMETER;
- }
+ FreePool (AsciiUri);

- if (mEtagProtocol == NULL) {
- Status = gBS->LocateProtocol (
- &gEdkIIRedfishETagProtocolGuid,
- NULL,
- (VOID **)&mEtagProtocol
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ if (EFI_ERROR (Status)) {
+ return NULL;
}

- mEtagProtocol->Set (mEtagProtocol, Uri, EtagStr);
- mEtagProtocol->Flush (mEtagProtocol);
-
- return EFI_SUCCESS;
+ return EtagStr;
}

/**

- Find ETAG string that refers to given URI.
+ Convert Unicode string to ASCII string. It's call responsibility to release
returned buffer.

- @param[in] Uri Target URI string.
+ @param[in] UnicodeStr Unicode string to convert.

- @retval CHAR8 * ETAG string
- @retval NULL No ETAG is found.
+ @retval CHAR8 * ASCII string returned.
+ @retval NULL Errors occur.

**/
CHAR8 *
-GetEtagWithUri (
- IN CHAR8 *Uri
+StrUnicodeToAscii (
+ IN EFI_STRING UnicodeStr
)
{
- EFI_STATUS Status;
- CHAR8 *EtagStr;
+ CHAR8 *AsciiStr;
+ UINTN AsciiStrSize;
+ EFI_STATUS Status;

- if (IS_EMPTY_STRING (Uri)) {
+ if (IS_EMPTY_STRING (UnicodeStr)) {
return NULL;
}

- if (mEtagProtocol == NULL) {
- Status = gBS->LocateProtocol (
- &gEdkIIRedfishETagProtocolGuid,
- NULL,
- (VOID **)&mEtagProtocol
- );
- if (EFI_ERROR (Status)) {
- return NULL;
- }
+ AsciiStrSize = StrLen (UnicodeStr) + 1;
+ AsciiStr = AllocatePool (AsciiStrSize);
+ if (AsciiStr == NULL) {
+ return NULL;
}

- Status = mEtagProtocol->Get (mEtagProtocol, Uri, &EtagStr);
+ Status = UnicodeStrToAsciiStrS (UnicodeStr, AsciiStr, AsciiStrSize);
if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "UnicodeStrToAsciiStrS failed: %r\n", Status));
+ FreePool (AsciiStr);
return NULL;
}

- return EtagStr;
+ return AsciiStr;
}

/**

- Convert HII string value to string value in JSON format.
+ Convert ASCII string to Unicode string. It's call responsibility to release
returned buffer.

- @param[in] HiiStringValue String in HII format.
+ @param[in] AsciiStr ASCII string to convert.

- @retval CHAR8 * String in JSON format.
+ @retval EFI_STRING Unicode string returned.
@retval NULL Errors occur.

**/
-CHAR8 *
-ConvertHiiStringValueToJsonStringValue (
- IN EFI_STRING HiiStringValue
+EFI_STRING
+StrAsciiToUnicode (
+ IN CHAR8 *AsciiStr
)
{
- CHAR8 *JsonValue;
- UINTN JsonValueSize;
+ EFI_STRING UnicodeStr;
+ UINTN UnicodeStrSize;
+ EFI_STATUS Status;

- if (IS_EMPTY_STRING (HiiStringValue)) {
+ if (IS_EMPTY_STRING (AsciiStr)) {
return NULL;
}

- JsonValueSize = StrLen (HiiStringValue) + 1;
- JsonValue = AllocatePool (JsonValueSize);
- UnicodeStrToAsciiStrS (HiiStringValue, JsonValue, JsonValueSize);
+ UnicodeStrSize = (AsciiStrLen (AsciiStr) + 1) * sizeof (CHAR16);
+ UnicodeStr = AllocatePool (UnicodeStrSize);
+ if (UnicodeStr == NULL) {
+ return NULL;
+ }
+
+ Status = AsciiStrToUnicodeStrS (AsciiStr, UnicodeStr, UnicodeStrSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "t failed: %r\n", Status));
+ FreePool (UnicodeStr);
+ return NULL;
+ }

- return JsonValue;
+ return UnicodeStr;
}

/**
@@ -480,997 +448,2979 @@ ApplyFeatureSettingsBooleanType (

/**

- Read redfish resource by given resource path.
+ Apply property value to UEFI HII database in vague type.

- @param[in] Service Redfish srvice instacne to make query.
- @param[in] ResourcePath Target resource path.
- @param[out] Response HTTP response from redfish service.
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] VagueValuePtr Pointer of vague values to to set.
+ @param[in] NumVagueValues Number of vague values.

- @retval EFI_SUCCESS Resrouce is returned successfully.
+ @retval EFI_SUCCESS New value is applied successfully.
@retval Others Errors occur.

**/
EFI_STATUS
-GetResourceByPath (
- IN REDFISH_SERVICE *Service,
- IN CHAR8 *ResourcePath,
- OUT REDFISH_RESPONSE *Response
+ApplyFeatureSettingsVagueType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_EmptyProp_KeyValue *VagueValuePtr,
+ IN UINT32 NumberOfVagueValues
)
{
- EFI_STATUS Status;
-
- if (Service == NULL || Response == NULL || IS_EMPTY_STRING
(ResourcePath)) {
+ EFI_STATUS Status;
+ UINTN StrSize;
+ CHAR8 *ConfigureLangAscii;
+ CHAR8 *ConfigureLangKeyAscii;
+ EFI_STRING ConfigureKeyLang;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EDKII_REDFISH_VALUE_TYPES PropertyDatatype;
+ RedfishCS_EmptyProp_KeyValue *CurrentVagueValuePtr;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || VagueValuePtr == NULL ||
NumberOfVagueValues == 0) {
return EFI_INVALID_PARAMETER;
}

- //
- // Get resource from redfish service.
- //
- Status = RedfishGetByService (
- Service,
- ResourcePath,
- Response
- );
+ ConfigureLangAscii = AllocatePool (StrLen (ConfigureLang) + 1);
+ if (ConfigureLangAscii == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((DEBUG_ERROR, "%a, Allocate memory for generate
ConfigureLang of vague key of %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
+ return Status;
+ }
+ Status = UnicodeStrToAsciiStrS (ConfigureLang, ConfigureLangAscii, StrLen
(ConfigureLang) + 1);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, RedfishGetByService to %a failed: %r\n",
__FUNCTION__, ResourcePath, Status));
- if (Response->Payload != NULL) {
- RedfishDumpPayload (Response->Payload);
- RedfishFreeResponse (
- NULL,
- 0,
- NULL,
- Response->Payload
- );
- Response->Payload = NULL;
- }
-
+ DEBUG ((DEBUG_ERROR, "%a, Convert the configureLang of vague key of
%a.%a %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLang,
Status));
return Status;
}

+ CurrentVagueValuePtr = VagueValuePtr;
+ while (CurrentVagueValuePtr != NULL) {
+ //
+ // Generate ConfigureLang with the key name
+ //
+ //ConfigureKeyLang = GetConfigureLang (ConfigureLangAscii,
CurrentVagueValuePtr->KeyNamePtr);
+ StrSize = AsciiStrLen (ConfigureLangAscii) + AsciiStrLen
(CurrentVagueValuePtr->KeyNamePtr) + 2;
+ ConfigureLangKeyAscii = AllocateZeroPool (StrSize);
+ ConfigureKeyLang = AllocateZeroPool (StrSize * sizeof (CHAR16));
+ if (ConfigureLangKeyAscii == NULL || ConfigureKeyLang == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Generate ConfigureLang of vague key of
%a.%a %s %a failed!\n", __FUNCTION__, Schema, Version, ConfigureLang,
CurrentVagueValuePtr->KeyNamePtr));
+ goto ErrorContinue;
+ }
+ AsciiStrCatS(ConfigureLangKeyAscii, StrSize, ConfigureLangAscii);
+ AsciiStrCatS(ConfigureLangKeyAscii, StrSize, "/");
+ AsciiStrCatS(ConfigureLangKeyAscii, StrSize, CurrentVagueValuePtr-
KeyNamePtr);
+ AsciiStrToUnicodeStrS(ConfigureLangKeyAscii, ConfigureKeyLang, StrSize);
+ FreePool (ConfigureLangKeyAscii);
+ ConfigureLangKeyAscii = NULL;
+ //
+ // Initial property data type and value.
+ //
+ if (CurrentVagueValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_String) {
+ PropertyDatatype = REDFISH_VALUE_TYPE_STRING;
+ } else if (CurrentVagueValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_Bool) {
+ PropertyDatatype = REDFISH_VALUE_TYPE_BOOLEAN;
+ } else if (CurrentVagueValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_Int64) {
+ PropertyDatatype = REDFISH_VALUE_TYPE_INTEGER;
+ } else {
+ DEBUG((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish property
data type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+ goto ErrorContinue;
+ }
+
+ //
+ // Get the current value from HII
+ //
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureKeyLang, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureKeyLang, Status));
+ } else {
+ if (RedfishValue.Type != PropertyDatatype) {
+ DEBUG((DEBUG_ERROR, "%a, %a.%a %s mismatched data type\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang));
+ goto ErrorContinue;
+ }
+ if (PropertyDatatype == REDFISH_VALUE_TYPE_STRING) {
+ //
+ // This is a string property.
+ //
+ if (AsciiStrCmp (CurrentVagueValuePtr->Value->DataValue.CharPtr,
RedfishValue.Value.Buffer) != 0) {
+ //
+ // Apply settings from redfish
+ //
+ DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from %a to %a\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang,
RedfishValue.Value.Buffer, CurrentVagueValuePtr->Value-
DataValue.CharPtr));
+ FreePool (RedfishValue.Value.Buffer);
+ RedfishValue.Value.Buffer = CurrentVagueValuePtr->Value-
DataValue.CharPtr;
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureKeyLang, RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply %a to %a failed: %r\n",
__FUNCTION__, ConfigureKeyLang, CurrentVagueValuePtr->Value-
DataValue.CharPtr, Status));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: %a\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang,
RedfishValue.Value.Buffer, Status));
+ }
+ } else if (PropertyDatatype == REDFISH_VALUE_TYPE_BOOLEAN) {
+ //
+ // This is a boolean property.
+ //
+ if (RedfishValue.Value.Boolean != *CurrentVagueValuePtr->Value-
DataValue.BoolPtr) {
+ //
+ // Apply settings from redfish
+ //
+ DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from %a to %a\n",
+ __FUNCTION__,
+ Schema,
+ Version,
+ ConfigureKeyLang,
+ (RedfishValue.Value.Boolean ? "True" : "False"),
+ (*CurrentVagueValuePtr->Value->DataValue.BoolPtr ? "True" :
"False")));
+
+ RedfishValue.Value.Boolean = (BOOLEAN)*CurrentVagueValuePtr-
Value->DataValue.BoolPtr;
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureKeyLang, RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply %s to %a failed: %r\n",
__FUNCTION__, ConfigureKeyLang, (*CurrentVagueValuePtr->Value-
DataValue.BoolPtr ? "True" : "False"), Status));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: %a\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang,
(RedfishValue.Value.Boolean ? "True" : "False"), Status));
+ }
+ } else if (PropertyDatatype == REDFISH_VALUE_TYPE_INTEGER) {
+ //
+ // This is a integer property.
+ //
+ if (RedfishValue.Value.Integer != *CurrentVagueValuePtr->Value-
DataValue.Int64Ptr) {
+ //
+ // Apply settings from redfish
+ //
+ DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from 0x%x to 0x%x\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang,
RedfishValue.Value.Integer, *CurrentVagueValuePtr->Value-
DataValue.Int64Ptr));
+
+ RedfishValue.Value.Integer = (INT64)*CurrentVagueValuePtr->Value-
DataValue.Int64Ptr;
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureKeyLang, RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply %s to 0x%x failed: %r\n",
__FUNCTION__, ConfigureKeyLang, *CurrentVagueValuePtr->Value-
DataValue.Int64Ptr, Status));
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: 0x%x\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang,
RedfishValue.Value.Integer, Status));
+ }
+ } else {
+ DEBUG((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish property
data type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+ goto ErrorContinue;
+ }
+ }
+
+ErrorContinue:;
+ if (ConfigureLangKeyAscii != NULL) {
+ FreePool (ConfigureLangKeyAscii);
+ ConfigureLangKeyAscii = NULL;
+ }
+ if (ConfigureKeyLang != NULL) {
+ FreePool (ConfigureKeyLang);
+ ConfigureKeyLang = NULL;
+ }
+ CurrentVagueValuePtr = CurrentVagueValuePtr->NextKeyValuePtr;
+ };
+
+ if (ConfigureLangAscii != NULL) {
+ FreePool (ConfigureLangAscii);
+ }
+ if (ConfigureLangKeyAscii != NULL) {
+ FreePool (ConfigureLangKeyAscii);
+ }
+ if (ConfigureKeyLang != NULL) {
+ FreePool (ConfigureKeyLang);
+ }
return EFI_SUCCESS;
}

/**

- Find array index from given configure language string.
-
- @param[in] ConfigureLang Configure language string to parse.
- @param[out] UnifiedConfigureLang The configure language in array.
- @param[out] Index The array index number.
+ Release the memory in RedfishValue while value type is array.

- @retval EFI_SUCCESS Index is found.
- @retval Others Errors occur.
+ @param[in] RedfishValue Pointer to Redfish value

**/
-EFI_STATUS
-GetArrayIndexFromArrayTypeConfigureLang (
- IN CHAR16 *ConfigureLang,
- OUT CHAR16 **UnifiedConfigureLang,
- OUT UINTN *Index
+VOID
+FreeArrayTypeRedfishValue (
+ EDKII_REDFISH_VALUE *RedfishValue
)
{
- CHAR16 *TmpConfigureLang;
- CHAR16 *IndexString;
- CHAR16 *TmpString;
-
- if (ConfigureLang == NULL || UnifiedConfigureLang == NULL || Index ==
NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- TmpConfigureLang = AllocateCopyPool (StrSize (ConfigureLang),
ConfigureLang);
- if (TmpConfigureLang == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
+ UINTN Index;

- //
- // looking for index signature "{""
- //
- IndexString = StrStr (TmpConfigureLang,
BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
- if (IndexString == NULL) {
- return EFI_NOT_FOUND;
+ if (RedfishValue == NULL) {
+ return;
}

- //
- // Skip "{"
- //
- TmpString = IndexString + StrLen
(BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
-
- //
- // Looking for "}"
- //
- TmpString = StrStr (TmpString,
BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE);
- if (TmpString == NULL) {
- return EFI_NOT_FOUND;
+ if (RedfishValue->Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY &&
RedfishValue->Type != REDFISH_VALUE_TYPE_STRING_ARRAY) {
+ return;
}

- //
- // Append '\0' for converting decimal string to integer.
- //
- TmpString[0] = '\0';
+ switch (RedfishValue->Type) {
+ case REDFISH_VALUE_TYPE_STRING_ARRAY:
+ for (Index = 0; Index < RedfishValue->ArrayCount; Index++) {
+ FreePool (RedfishValue->Value.StringArray[Index]);
+ }
+ FreePool (RedfishValue->Value.StringArray);
+ RedfishValue->Value.StringArray = NULL;
+ break;

- //
- // Convert decimal string to integer
- //
- *Index = StrDecimalToUintn (IndexString + StrLen
(BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE));
+ case REDFISH_VALUE_TYPE_INTEGER_ARRAY:
+ FreePool (RedfishValue->Value.IntegerArray);
+ RedfishValue->Value.IntegerArray = NULL;
+ break;

- //
- // Resotre the '}' character and remove rest of string.
- //
- TmpString[0] = L'}';
- TmpString[1] = '\0';
+ case REDFISH_VALUE_TYPE_BOOLEAN_ARRAY:
+ FreePool (RedfishValue->Value.BooleanArray);
+ RedfishValue->Value.BooleanArray = NULL;
+ break;

- *UnifiedConfigureLang = TmpConfigureLang;
+ default:
+ return;
+ }

- return EFI_SUCCESS;
+ RedfishValue->ArrayCount = 0;
}

+
/**

- Search HII database with given Configure Language pattern. Data is handled
and
- returned in array.
+ Apply property value to UEFI HII database in string array type.

- @param[in] Schema The schema to search.
- @param[in] Version The schema version.
- @param[in] Pattern Configure Language pattern to search.
- @param[out] UnifiedConfigureLangList The data returned by HII database.
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] ArrayHead Head of array value.

- @retval EFI_SUCCESS Data is found and returned.
+ @retval EFI_SUCCESS New value is applied successfully.
@retval Others Errors occur.

**/
EFI_STATUS
-RedfishFeatureGetUnifiedArrayTypeConfigureLang (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING Pattern, OPTIONAL
- OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*UnifiedConfigureLangList
+ApplyFeatureSettingsStringArrayType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_char_Array *ArrayHead
)
{
- EFI_STATUS Status;
- EFI_STRING *ConfigureLangList;
- UINTN Count;
- UINTN Index;
- UINTN Index2;
- UINTN ArrayIndex;
- EFI_STRING UnifiedConfigureLang;
- BOOLEAN Duplicated;
- REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
UnifiedConfigureLangPool[BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZ
E];
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ UINTN Index;
+ RedfishCS_char_Array *Buffer;

- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
UnifiedConfigureLangList == NULL) {
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || ArrayHead == NULL) {
return EFI_INVALID_PARAMETER;
}

- UnifiedConfigureLangList->Count = 0;
- UnifiedConfigureLangList->List = NULL;
- ZeroMem (UnifiedConfigureLangPool, sizeof (UnifiedConfigureLangPool));
-
- Status = RedfishPlatformConfigGetConfigureLang (Schema, Version,
Pattern, &ConfigureLangList, &Count);
+ //
+ // Get the current value from HII
+ //
+ Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLang,
&RedfishValue);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, RedfishFeatureGetConfigureLangRegex
failed: %r\n", __FUNCTION__, Status));
- return Status;
- }
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
+ } else {

- if (Count == 0) {
- return EFI_NOT_FOUND;
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING_ARRAY) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array
type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // If there is no change in array, do nothing
+ //
+ if (!CompareRedfishStringArrayValues (ArrayHead,
RedfishValue.Value.StringArray, RedfishValue.ArrayCount)) {
+ //
+ // Apply settings from redfish
+ //
+ DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ FreeArrayTypeRedfishValue (&RedfishValue);
+
+ //
+ // Convert array from RedfishCS_char_Array to EDKII_REDFISH_VALUE
+ //
+ RedfishValue.ArrayCount = 0;
+ Buffer = ArrayHead;
+ while (Buffer != NULL) {
+ RedfishValue.ArrayCount += 1;
+ Buffer = Buffer->Next;
+ }
+
+ //
+ // Allocate pool for new values
+ //
+ RedfishValue.Value.StringArray = AllocatePool
(RedfishValue.ArrayCount *sizeof (CHAR8 *));
+ if (RedfishValue.Value.StringArray == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Buffer = ArrayHead;
+ Index = 0;
+ while (Buffer != NULL) {
+ RedfishValue.Value.StringArray[Index] = AllocateCopyPool (AsciiStrSize
(Buffer->ArrayValue), Buffer->ArrayValue);
+ if (RedfishValue.Value.StringArray[Index] == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Buffer = Buffer->Next;
+ Index++;
+ }
+
+ ASSERT (Index <= RedfishValue.ArrayCount);
+
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureLang, RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ }
}

- for (Index = 0; Index < Count; Index++) {
- Status = GetArrayIndexFromArrayTypeConfigureLang
(ConfigureLangList[Index], &UnifiedConfigureLang, &ArrayIndex);
- if (EFI_ERROR (Status)) {
- ASSERT (FALSE);
- continue;
+ return Status;
+}
+
+/**
+
+ Apply property value to UEFI HII database in numeric array type (INT64).
+
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] ArrayHead Head of array value.
+
+ @retval EFI_SUCCESS New value is applied successfully.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+ApplyFeatureSettingsNumericArrayType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_int64_Array *ArrayHead
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ UINTN Index;
+ RedfishCS_int64_Array *Buffer;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || ArrayHead == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the current value from HII
+ //
+ Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLang,
&RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
+ } else {
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return EFI_DEVICE_ERROR;
}

//
- // Check if this configure language is duplicated.
+ // If there is no change in array, do nothing
//
- Duplicated = FALSE;
- for (Index2 = 0; Index2 <
BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE; Index2++) {
- if (UnifiedConfigureLangPool[Index2].ConfigureLang == NULL) {
- break;
+ if (!CompareRedfishNumericArrayValues (ArrayHead,
RedfishValue.Value.IntegerArray, RedfishValue.ArrayCount)) {
+ //
+ // Apply settings from redfish
+ //
+ DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ FreeArrayTypeRedfishValue (&RedfishValue);
+
+ //
+ // Convert array from RedfishCS_int64_Array to EDKII_REDFISH_VALUE
+ //
+ RedfishValue.ArrayCount = 0;
+ Buffer = ArrayHead;
+ while (Buffer != NULL) {
+ RedfishValue.ArrayCount += 1;
+ Buffer = Buffer->Next;
+ }
+
+ //
+ // Allocate pool for new values
+ //
+ RedfishValue.Value.IntegerArray = AllocatePool
(RedfishValue.ArrayCount * sizeof (INT64));
+ if (RedfishValue.Value.IntegerArray == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Buffer = ArrayHead;
+ Index = 0;
+ while (Buffer != NULL) {
+ RedfishValue.Value.IntegerArray[Index] = (INT64)*Buffer->ArrayValue;
+ Buffer = Buffer->Next;
+ Index++;
+ }
+
+ ASSERT (Index <= RedfishValue.ArrayCount);
+
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureLang, RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ }
+ }
+
+ return Status;
+}
+
+/**
+
+ Apply property value to UEFI HII database in boolean array type (INT64).
+
+ @param[in] Schema Property schema.
+ @param[in] Version Property schema version.
+ @param[in] ConfigureLang Configure language refers to this property.
+ @param[in] ArrayHead Head of Redfich CS boolean array value.
+
+ @retval EFI_SUCCESS New value is applied successfully.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+ApplyFeatureSettingsBooleanArrayType (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_bool_Array *ArrayHead
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ UINTN Index;
+ RedfishCS_bool_Array *Buffer;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || ArrayHead == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the current value from HII
+ //
+ Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLang,
&RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
+ } else {
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN_ARRAY) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // If there is no change in array, do nothing
+ //
+ if (!CompareRedfishBooleanArrayValues (ArrayHead,
RedfishValue.Value.BooleanArray, RedfishValue.ArrayCount)) {
+ //
+ // Apply settings from redfish
+ //
+ DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s for array\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ FreeArrayTypeRedfishValue (&RedfishValue);
+
+ //
+ // Convert array from RedfishCS_int64_Array to EDKII_REDFISH_VALUE
+ //
+ RedfishValue.ArrayCount = 0;
+ Buffer = ArrayHead;
+ while (Buffer != NULL) {
+ RedfishValue.ArrayCount += 1;
+ Buffer = Buffer->Next;
+ }
+
+ //
+ // Allocate pool for new values
+ //
+ RedfishValue.Value.BooleanArray = AllocatePool
(RedfishValue.ArrayCount * sizeof (BOOLEAN));
+ if (RedfishValue.Value.BooleanArray == NULL) {
+ ASSERT (FALSE);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Buffer = ArrayHead;
+ Index = 0;
+ while (Buffer != NULL) {
+ RedfishValue.Value.BooleanArray[Index] = (BOOLEAN)*Buffer-
ArrayValue;
+ Buffer = Buffer->Next;
+ Index++;
+ }
+
+ ASSERT (Index <= RedfishValue.ArrayCount);
+
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureLang, RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, apply %s array failed: %r\n",
__FUNCTION__, ConfigureLang, Status));
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s array value has no change\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ }
+ }
+
+ return Status;
+}
+
+/**
+
+ Read redfish resource by given resource URI.
+
+ @param[in] Service Redfish srvice instacne to make query.
+ @param[in] ResourceUri Target resource URI.
+ @param[out] Response HTTP response from redfish service.
+
+ @retval EFI_SUCCESS Resrouce is returned successfully.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+GetResourceByUri (
+ IN REDFISH_SERVICE *Service,
+ IN EFI_STRING ResourceUri,
+ OUT REDFISH_RESPONSE *Response
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *AsciiResourceUri;
+
+ if (Service == NULL || Response == NULL || IS_EMPTY_STRING
(ResourceUri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AsciiResourceUri = StrUnicodeToAscii (ResourceUri);
+ if (AsciiResourceUri == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get resource from redfish service.
+ //
+ Status = RedfishGetByUri (
+ Service,
+ AsciiResourceUri,
+ Response
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, RedfishGetByUri to %a failed: %r\n",
__FUNCTION__, AsciiResourceUri, Status));
+ if (Response->Payload != NULL) {
+ RedfishDumpPayload (Response->Payload);
+ RedfishFreeResponse (
+ NULL,
+ 0,
+ NULL,
+ Response->Payload
+ );
+ Response->Payload = NULL;
+ }
+ }
+
+ if (AsciiResourceUri != NULL) {
+ FreePool (AsciiResourceUri);
+ }
+
+ return Status;
+}
+
+/**
+
+ Check if this is the Redpath array. Usually the Redpath array represents
+ the collection member. Return
+
+ @param[in] ConfigureLang The Redpath to check
+ @param[out] ArraySignatureOpen String to the open of array signature.
+ @param[out] ArraySignatureClose String to the close of array signature.
+
+ @retval EFI_SUCCESS Index is found.
+ @retval EFI_NOT_FOUND The non-array configure language string is
retured.
+ @retval EFI_INVALID_PARAMETER The format of input ConfigureLang is
wrong.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+IsRedpathArray (
+ IN EFI_STRING ConfigureLang,
+ OUT EFI_STRING *ArraySignatureOpen OPTIONAL,
+ OUT EFI_STRING *ArraySignatureClose OPTIONAL
+ )
+{
+ CHAR16 *IndexString;
+
+ if (ConfigureLang == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ArraySignatureOpen != NULL) {
+ *ArraySignatureOpen = NULL;
+ }
+ if (ArraySignatureClose != NULL) {
+ *ArraySignatureClose = NULL;
+ }
+
+ //
+ // looking for index signature "{""
+ //
+ IndexString = StrStr (ConfigureLang,
BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
+ if (IndexString != NULL) {
+ if (ArraySignatureOpen != NULL) {
+ *ArraySignatureOpen = IndexString;
+ }
+ //
+ // Skip "{"
+ //
+ IndexString = IndexString + StrLen
(BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE);
+ //
+ // Looking for "}"
+ //
+ IndexString = StrStr (IndexString,
BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_END_SIGNATURE);
+ if (IndexString == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ArraySignatureClose != NULL) {
+ *ArraySignatureClose = IndexString;
+ }
+ return EFI_SUCCESS;
+ }
+ return EFI_NOT_FOUND;
+}
+
+/**
+
+ Get number of node from the string. Node is seperated by '/'.
+
+ @param[in] NodeString The node string to parse.
+
+ @retval UINTN Number of nodes in the string.
+
+**/
+UINTN
+GetNumberOfRedpathNodes (
+ IN EFI_STRING NodeString
+ )
+{
+ UINTN Index;
+ UINTN NumberNodes;
+ UINTN StringLen;
+
+ NumberNodes = 0;
+ StringLen = StrLen (NodeString);
+ Index = 1; // ConfigLang always starts with '/'.
+ while (Index < StringLen) {
+ if (*(NodeString + Index) == L'/') {
+ NumberNodes ++;
+ }
+ Index ++;
+ };
+ NumberNodes ++;
+
+ return (NumberNodes);
+}
+
+/**
+
+ Get the node string by index
+
+ @param[in] NodeString The node string to parse.
+ @param[in] Index Zero-based index of the node.
+ @param[out] EndOfNodePtr Pointer to receive the poitner to
+ the last character of node string.
+
+ @retval EFI_STRING the begining of the node string.
+
+**/
+EFI_STRING
+GetRedpathNodeByIndex (
+ IN EFI_STRING NodeString,
+ IN UINTN Index,
+ OUT EFI_STRING *EndOfNodePtr OPTIONAL
+ )
+{
+ UINTN NumberNodes;
+ UINTN StringLen;
+ UINTN StringIndex;
+ EFI_STRING NodeStart;
+ EFI_STRING NodeEnd;
+
+ NumberNodes = 0;
+ StringLen = StrLen (NodeString);
+ StringIndex = 1; // ConfigLang always starts with '/'.
+ NodeStart = NodeString;
+ if (EndOfNodePtr != NULL) {
+ *EndOfNodePtr = NULL;
+ }
+ while (StringIndex < StringLen) {
+ if (*(NodeString + StringIndex) == L'/') {
+ NodeEnd = NodeString + StringIndex - 1;
+ if (NumberNodes == Index) {
+ if (EndOfNodePtr != NULL) {
+ *EndOfNodePtr = NodeEnd;
+ }
+ return NodeStart;
+ } else {
+ NodeStart = NodeString + StringIndex + 1;
}
+ }
+ StringIndex ++;
+ };
+ return (NULL);
+}
+
+/**
+
+ Find array index from given configure language string.
+
+ @param[in] ConfigureLang Configure language string to parse.
+ @param[out] UnifiedConfigureLang The configure language in array.
+ @param[out] Index The array index number.
+
+ @retval EFI_SUCCESS Index is found.
+ @retval EFI_NOT_FOUND The non-array configure language string is
retured.
+ @retval EFI_INVALID_PARAMETER The format of input ConfigureLang is
wrong.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+GetArrayIndexFromArrayTypeConfigureLang (
+ IN CHAR16 *ConfigureLang,
+ OUT CHAR16 **UnifiedConfigureLang,
+ OUT UINTN *Index
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *TmpConfigureLang;
+ CHAR16 *ArrayOpenStr;
+ CHAR16 *ArrayCloseStr;
+ INTN StringIndex;
+
+ if (ConfigureLang == NULL || UnifiedConfigureLang == NULL || Index ==
NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TmpConfigureLang = AllocateCopyPool (StrSize (ConfigureLang),
ConfigureLang);
+ if (TmpConfigureLang == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = IsRedpathArray (TmpConfigureLang, &ArrayOpenStr,
&ArrayCloseStr);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Append '\0' for converting decimal string to integer.
+ //
+ ArrayCloseStr[0] = '\0';
+
+ //
+ // Convert decimal string to integer
+ //
+ *Index = StrDecimalToUintn (ArrayOpenStr + StrLen
(BIOS_CONFIG_TO_REDFISH_REDPATH_ARRAY_START_SIGNATURE));
+
+ //
+ // Resotre the '}' character and remove rest of string.
+ //
+ ArrayCloseStr[0] = L'}';
+ ArrayCloseStr[1] = '\0';
+ *UnifiedConfigureLang = TmpConfigureLang;
+ } else {
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // This is not the redpath array. Search "/" for the parent root.
+ //
+ *Index = 0;
+ StringIndex = StrLen (TmpConfigureLang) - 1;
+ while (StringIndex >= 0 && *(TmpConfigureLang + StringIndex) != '/') {
+ StringIndex --;
+ };
+ if (StringIndex >= 0 ) {
+ *(TmpConfigureLang + StringIndex) = '\0';
+ *UnifiedConfigureLang = TmpConfigureLang;
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+ return Status;
+}
+
+/**
+
+ Clone the configure language list.
+
+ @param[in] ConfigureLangList The source
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
+ @param[out] DestConfigureLangList The destination
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST.
+
+ @retval EFI_SUCCESS
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+CopyConfiglanguageList (
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*SourceConfigureLangList,
+ OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*DestConfigureLangList
+ )
+{
+ UINTN Index;
+
+ if (SourceConfigureLangList == NULL || DestConfigureLangList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ DestConfigureLangList->Count = SourceConfigureLangList->Count;
+ DestConfigureLangList->List =
+ (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *)AllocateZeroPool
(sizeof (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) *
DestConfigureLangList->Count);
+ if (DestConfigureLangList->List == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG.\n", __FUNCTION__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ for (Index = 0; Index < SourceConfigureLangList->Count; Index++) {
+ DestConfigureLangList->List [Index].Index = SourceConfigureLangList-
List[Index].Index;
+ DestConfigureLangList->List [Index].ConfigureLang =
+ (EFI_STRING)AllocateCopyPool(StrSize(SourceConfigureLangList-
List[Index].ConfigureLang), (VOID *)SourceConfigureLangList-
List[Index].ConfigureLang);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Clone the configure language list.
+
+ @param[in] ConfigureLang The pointer to configuration language.
+
+ @retval UINTN The index of collection member instance.
+ Value of 0 means no instance is found.
+**/
+UINTN
+ConfiglanguageGetInstanceIndex (
+ IN EFI_STRING ConfigureLang
+ )
+{
+ INTN LeftBracketIndex;
+ INTN RightBracketIndex;
+ INTN Index;
+ UINT64 Instance;
+ EFI_STATUS Status;
+
+ if (ConfigureLang == NULL) {
+ return 0;
+ }
+ LeftBracketIndex = 0;
+ RightBracketIndex = 0;
+ Index = StrLen (ConfigureLang) - 1;
+ while (Index >= 0) {
+ if (*(ConfigureLang + Index) == L'{') {
+ LeftBracketIndex = Index;
+ break;
+ }
+ if (*(ConfigureLang + Index) == L'}') {
+ RightBracketIndex = Index;
+ }
+ Index --;
+ };
+ if ((RightBracketIndex - LeftBracketIndex) <= 1) {
+ return 0;
+ }
+ *(ConfigureLang + RightBracketIndex) = 0;
+ Status = StrDecimalToUint64S (ConfigureLang + LeftBracketIndex + 1, NULL,
&Instance);
+ if (EFI_ERROR(Status)) {
+ Instance = 0;
+ }
+ //
+ // Restore right curly bracket.
+ //
+ *(ConfigureLang + RightBracketIndex) = L'}';
+ return (UINTN)Instance;
+}
+
+/**
+
+ Destroy the configure language list.
+
+ @param[in] ConfigureLangList The
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
+ instance to destroy.
+
+ @retval EFI_SUCCESS
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST is copied.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+DestroyConfiglanguageList (
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*ConfigureLangList
+ )
+{
+ UINTN Index;
+
+ if (ConfigureLangList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ConfigureLangList->List != NULL) {
+ for (Index = 0; Index < ConfigureLangList->Count; Index++) {
+ if (ConfigureLangList->List [Index].ConfigureLang != NULL) {
+ FreePool (ConfigureLangList->List [Index].ConfigureLang);
+ }
+ }
+ FreePool (ConfigureLangList->List);
+ ConfigureLangList->List = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Set the node instance.
+
+ @param[in] DestConfigLang Pointer to the node's configure language
string.
+ The memory pointed by ConfigLang must be allocated
+ through memory allocation interface. Becasue we will
replace
+ the pointer in this function.
+ @param[in] MaxtLengthConfigLang The maximum length of ConfigLang.
+ @param[in] ConfigLangInstance Pointer to Collection member instance.
+
+ @retval EFI_SUCCESS The instance is inserted to the configure
language.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+SetResourceConfigLangMemberInstance (
+ IN EFI_STRING *DestConfigLang,
+ IN UINTN MaxtLengthConfigLang,
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *ConfigLangInstance
+ )
+{
+ EFI_STRING ThisConfigLang;
+ EFI_STRING NewConfigLang;
+ CHAR16 InstanceStr [10];
+ INTN Index;
+ UINTN Length;
+ UINTN MaxStrLength;
+
+ if (DestConfigLang == NULL || ConfigLangInstance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ UnicodeSPrint ((CHAR16 *)&InstanceStr, 10, L"%d", ConfigLangInstance-
Index);
+
+ ThisConfigLang = *DestConfigLang;
+ if (ThisConfigLang [0] == 0) {
+ //
+ // Return ConfigLangInstance->ConfigureLang
+ //
+ if (ConfigLangInstance->ConfigureLang == NULL) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ StrCatS(*DestConfigLang, MaxtLengthConfigLang, ConfigLangInstance-
ConfigureLang);
+ return EFI_SUCCESS;
+ }
+ }
+
+ MaxStrLength = StrSize (ThisConfigLang) + StrSize
((EFI_STRING)&InstanceStr);
+ NewConfigLang = ThisConfigLang;
+ if (MaxtLengthConfigLang < MaxStrLength) {
+ NewConfigLang = (EFI_STRING)AllocateZeroPool(MaxStrLength);
+ if (NewConfigLang == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for
NewConfigLang.\n", __FUNCTION__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ //
+ // Search the last "{"
+ //
+ Index = StrLen (ThisConfigLang) - 1;
+ while ((ThisConfigLang[Index] != '{') && (Index >= 0)) {
+ Index --;
+ };
+ if (Index == -1) {
+ if (NewConfigLang != ThisConfigLang) {
+ FreePool(NewConfigLang);
+ }
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Copy the string to a new string.
+ //
+ Length = 0;
+ while (Index >= 0) {
+ NewConfigLang [Index] = ThisConfigLang[Index];
+ Index --;
+ Length ++;
+ };
+ UnicodeSPrint ((CHAR16 *)(NewConfigLang + Length), MaxStrLength,
L"%d", ConfigLangInstance->Index);
+ StrCatS (NewConfigLang, MaxStrLength, L"}");
+ if (NewConfigLang != ThisConfigLang) {
+ FreePool (ThisConfigLang);
+ }
+ *DestConfigLang = NewConfigLang;
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Search HII database with given Configure Language pattern. Data is
handled and
+ returned in array.
+
+ @param[in] Schema The schema to search.
+ @param[in] Version The schema version.
+ @param[in] Pattern Configure Language pattern to search.
+ @param[out] UnifiedConfigureLangList The data returned by HII database.
+
+ @retval EFI_SUCCESS Data is found and returned.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+RedfishFeatureGetUnifiedArrayTypeConfigureLang (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING Pattern, OPTIONAL
+ OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*UnifiedConfigureLangList
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING *ConfigureLangList;
+ UINTN Count;
+ UINTN Index;
+ UINTN Index2;
+ UINTN ArrayIndex;
+ EFI_STRING UnifiedConfigureLang;
+ BOOLEAN Duplicated;
+ REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
UnifiedConfigureLangPool[BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZ
E];
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
UnifiedConfigureLangList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UnifiedConfigureLangList->Count = 0;
+ UnifiedConfigureLangList->List = NULL;
+ ZeroMem (UnifiedConfigureLangPool, sizeof (UnifiedConfigureLangPool));
+
+ Status = RedfishPlatformConfigGetConfigureLang (Schema, Version,
Pattern, &ConfigureLangList, &Count);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, RedfishFeatureGetConfigureLangRegex
failed: %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ if (Count == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ Status = GetArrayIndexFromArrayTypeConfigureLang
(ConfigureLangList[Index], &UnifiedConfigureLang, &ArrayIndex);
+ if (EFI_ERROR (Status) && Status == EFI_INVALID_PARAMETER) {
+ ASSERT (FALSE);
+ continue;
+ }
+
+ //
+ // Check if this configure language is duplicated.
+ //
+ Duplicated = FALSE;
+ for (Index2 = 0; Index2 <
BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE; Index2++) {
+ if (UnifiedConfigureLangPool[Index2].ConfigureLang == NULL) {
+ break;
+ }
+
+ if (StrCmp (UnifiedConfigureLangPool[Index2].ConfigureLang,
UnifiedConfigureLang) == 0) {
+ Duplicated = TRUE;
+ break;
+ }
+ }
+
+ if (Duplicated) {
+ FreePool (UnifiedConfigureLang);
+ continue;
+ }
+
+ if (UnifiedConfigureLangList->Count >=
BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE) {
+ FreePool (UnifiedConfigureLang);
+ Status = EFI_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ //
+ // New configure language. Keep it in Pool
+ //
+
+ UnifiedConfigureLangPool[UnifiedConfigureLangList-
Count].ConfigureLang = UnifiedConfigureLang;
+ UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].Index =
ArrayIndex;
+ ++UnifiedConfigureLangList->Count;
+ }
+
+ FreePool (ConfigureLangList);
+
+ //
+ // Prepare the result to caller.
+ //
+ UnifiedConfigureLangList->List = AllocateCopyPool (sizeof
(REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) *
UnifiedConfigureLangList->Count, UnifiedConfigureLangPool);
+
+ return Status;
+}
+
+/**
+
+ Find "ETag" and "Location" from either HTTP header or Redfish response.
+
+ @param[in] Response HTTP response
+ @param[out] Etag String buffer to return ETag
+ @param[out] Location String buffer to return Location
+
+ @retval EFI_SUCCESS Data is found and returned.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+GetEtagAndLocation (
+ IN REDFISH_RESPONSE *Response,
+ OUT CHAR8 **Etag, OPTIONAL
+ OUT EFI_STRING *Location OPTIONAL
+ )
+{
+ EDKII_JSON_VALUE JsonValue;
+ EDKII_JSON_VALUE OdataValue;
+ CHAR8 *OdataString;
+ CHAR8 *AsciiLocation;
+ EFI_HTTP_HEADER *Header;
+ EFI_STATUS Status;
+
+ if (Response == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Etag == NULL && Location == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = EFI_SUCCESS;
+
+ if (Etag != NULL) {
+ *Etag = NULL;
+
+ if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
+ Header = HttpFindHeader (Response->HeaderCount, Response-
Headers, HTTP_HEADER_ETAG);
+ if (Header != NULL) {
+ *Etag = AllocateCopyPool (AsciiStrSize (Header->FieldValue), Header-
FieldValue);
+ ASSERT (*Etag != NULL);
+ }
+ }
+
+ //
+ // No header is returned. Search payload for location.
+ //
+ if (*Etag == NULL && Response->Payload != NULL) {
+ JsonValue = RedfishJsonInPayload (Response->Payload);
+ if (JsonValue != NULL) {
+ OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
"@odata.etag");
+ if (OdataValue != NULL) {
+ OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
+ if (OdataString != NULL) {
+ *Etag = AllocateCopyPool (AsciiStrSize (OdataString), OdataString);
+ ASSERT (*Etag != NULL);
+ }
+ }
+
+ JsonValueFree (JsonValue);
+ }
+ }
+
+ if (*Etag == NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+ if (Location != NULL) {
+ *Location = NULL;
+
+ if (*(Response->StatusCode) == HTTP_STATUS_200_OK) {
+ Header = HttpFindHeader (Response->HeaderCount, Response-
Headers, HTTP_HEADER_LOCATION);
+ if (Header != NULL) {
+ AsciiLocation = AllocateCopyPool (AsciiStrSize (Header->FieldValue),
Header->FieldValue);
+ ASSERT (AsciiLocation != NULL);
+ }
+ }
+
+ //
+ // No header is returned. Search payload for location.
+ //
+ if (*Location == NULL && Response->Payload != NULL) {
+ JsonValue = RedfishJsonInPayload (Response->Payload);
+ if (JsonValue != NULL) {
+ OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
"@odata.id");
+ if (OdataValue != NULL) {
+ OdataString = (CHAR8 *)JsonValueGetAsciiString (OdataValue);
+ if (OdataString != NULL) {
+ AsciiLocation = AllocateCopyPool (AsciiStrSize (OdataString),
OdataString);
+ ASSERT (AsciiLocation != NULL);
+ }
+ }
+
+ JsonValueFree (JsonValue);
+ }
+ }
+
+ if (AsciiLocation != NULL) {
+ *Location = StrAsciiToUnicode (AsciiLocation);
+ FreePool (AsciiLocation);
+ } else {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+ return Status;
+}
+/**
+
+ Create HTTP payload and send them to redfish service with PATCH method.
+
+ @param[in] Service Redfish service.
+ @param[in] TargetPayload Target payload
+ @param[in] Json Data in JSON format.
+ @param[out] Etag Returned ETAG string from Redfish service.
+
+ @retval EFI_SUCCESS Data is sent to redfish service successfully.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+CreatePayloadToPatchResource (
+ IN REDFISH_SERVICE *Service,
+ IN REDFISH_PAYLOAD *TargetPayload,
+ IN CHAR8 *Json,
+ OUT CHAR8 **Etag
+ )
+{
+ REDFISH_PAYLOAD Payload;
+ EDKII_JSON_VALUE ResourceJsonValue;
+ REDFISH_RESPONSE PostResponse;
+ EFI_STATUS Status;
+
+ if (Service == NULL || TargetPayload == NULL || IS_EMPTY_STRING (Json)
|| Etag == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ResourceJsonValue = JsonLoadString (Json, 0, NULL);
+ Payload = RedfishCreatePayload (ResourceJsonValue, Service);
+ if (Payload == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
JSON value!\n",__FUNCTION__, __LINE__));
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT_FREE_JSON_VALUE;
+ }
+
+ ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
+ Status = RedfishPatchToPayload (TargetPayload, Payload, &PostResponse);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish
service.\n",__FUNCTION__, __LINE__));
+ goto EXIT_FREE_JSON_VALUE;
+ }
+
+ //
+ // Find ETag
+ //
+ Status = GetEtagAndLocation (&PostResponse, Etag, NULL);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ RedfishFreeResponse (
+ PostResponse.StatusCode,
+ PostResponse.HeaderCount,
+ PostResponse.Headers,
+ PostResponse.Payload
+ );
+
+EXIT_FREE_JSON_VALUE:
+ if (Payload != NULL) {
+ RedfishCleanupPayload (Payload);
+ }
+
+ JsonValueFree (ResourceJsonValue);
+
+ return Status;
+}
+
+/**
+
+ Create HTTP payload and send them to redfish service with POST method.
+
+ @param[in] Service Redfish service.
+ @param[in] TargetPayload Target payload
+ @param[in] Json Data in JSON format.
+ @param[out] Location Returned location string from Redfish service.
+ @param[out] Etag Returned ETAG string from Redfish service.
+
+ @retval EFI_SUCCESS Data is sent to redfish service successfully.
+ @retval Others Errors occur.
+
+**/
+EFI_STATUS
+CreatePayloadToPostResource (
+ IN REDFISH_SERVICE *Service,
+ IN REDFISH_PAYLOAD *TargetPayload,
+ IN CHAR8 *Json,
+ OUT EFI_STRING *Location,
+ OUT CHAR8 **Etag
+ )
+{
+ REDFISH_PAYLOAD Payload;
+ EDKII_JSON_VALUE ResourceJsonValue;
+ REDFISH_RESPONSE PostResponse;
+ EFI_STATUS Status;
+
+ if (Service == NULL || TargetPayload == NULL || IS_EMPTY_STRING (Json)
|| Location == NULL || Etag == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ResourceJsonValue = JsonLoadString (Json, 0, NULL);
+ Payload = RedfishCreatePayload (ResourceJsonValue, Service);
+ if (Payload == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
JSON value!\n",__FUNCTION__, __LINE__));
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT_FREE_JSON_VALUE;
+ }
+
+ ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
+ Status = RedfishPostToPayload (TargetPayload, Payload, &PostResponse);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to POST Attribute Registry to
Redfish service.\n",__FUNCTION__, __LINE__));
+ goto EXIT_FREE_JSON_VALUE;
+ }
+
+ //
+ // per Redfish spec. the URL of new eresource will be returned in
"Location" header.
+ //
+ Status = GetEtagAndLocation (&PostResponse, Etag, Location);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ RedfishFreeResponse (
+ PostResponse.StatusCode,
+ PostResponse.HeaderCount,
+ PostResponse.Headers,
+ PostResponse.Payload
+ );
+
+ RedfishCleanupPayload (Payload);
+
+EXIT_FREE_JSON_VALUE:
+ JsonValueFree (ResourceJsonValue);
+
+ return Status;
+}
+
+/**
+
+ Return redfish URI by given config language. It's call responsibility to
release returned buffer.
+
+ @param[in] ConfigLang ConfigLang to search.
+
+ @retval NULL Can not find redfish uri.
+ @retval Other redfish uri is returned.
+
+**/
+EFI_STRING
+RedfishGetUri (
+ IN EFI_STRING ConfigLang
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING Target;
+ EFI_STRING Found;
+ EFI_STRING TempStr;
+ EFI_STRING ResultStr;
+ EFI_STRING Head;
+ EFI_STRING CloseBracket;
+ UINTN TempStrSize;
+ UINTN RemainingLen;
+ UINTN ConfigLangLen;
+
+ Status = RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol,
&gEdkIIRedfishConfigLangMapProtocolGuid);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, fail to locate
gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__, Status));
+ return NULL;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, Get: %s\n", __FUNCTION__,
ConfigLang));
+
+ CloseBracket = StrStr (ConfigLang, L"{");
+ if (CloseBracket == NULL) {
+ return AllocateCopyPool (StrSize (ConfigLang), ConfigLang);
+ }
+
+ //
+ // Remove leading "/v1" or "/redfish/v1" because we don't code
+ // configure language in this way.
+ //
+ Head = StrStr (ConfigLang, REDFISH_ROOT_PATH_UNICODE);
+ if (Head == NULL) {
+ Head = ConfigLang;
+ } else {
+ Head += 3;
+ }
+
+ ResultStr = AllocateZeroPool (sizeof (CHAR16) * MAX_REDFISH_URL_LEN);
+ if (ResultStr == NULL) {
+ return NULL;
+ }
+
+ //
+ // Go though ConfigLang and replace each {} with URL
+ //
+ do {
+ ConfigLangLen = StrLen (Head);
+ Target = CloseBracket;
+
+ //
+ // Look for next ConfigLang
+ //
+ do {
+ Target += 1;
+ } while (*Target != '\0' && *Target != '}');
+
+ //
+ // Invalid format. No '}' found
+ //
+ if (*Target == '\0') {
+ DEBUG ((DEBUG_ERROR, "%a, invalid format: %s\n", __FUNCTION__,
ConfigLang));
+ return NULL;
+ }
+
+ //
+ // Copy current ConfigLang to temporary string and do a query
+ //
+ Target += 1;
+ RemainingLen = StrLen (Target);
+ TempStrSize = (ConfigLangLen - RemainingLen + 1) * sizeof (CHAR16);
+ TempStr = AllocateCopyPool (TempStrSize, Head);
+ if (TempStr == NULL) {
+ return NULL;
+ }
+ TempStr[ConfigLangLen - RemainingLen] = '\0';
+
+ Status = mConfigLangMapProtocol->Get (
+ mConfigLangMapProtocol,
+ RedfishGetTypeConfigLang,
+ TempStr,
+ &Found
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, Can not find: %s\n", __FUNCTION__,
TempStr));
+ return NULL;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, Found: %s\n", __FUNCTION__,
Found));
+
+ //
+ // Keep result in final string pool
+ //
+ StrCatS (ResultStr, MAX_REDFISH_URL_LEN, Found);
+ FreePool (TempStr);
+
+ //
+ // Prepare for next ConfigLang
+ //
+ Head = Target;
+ CloseBracket = StrStr (Head, L"{");
+ } while (CloseBracket != NULL);
+
+ //
+ // String which has no ConfigLang remaining
+ //
+ if (Head != '\0') {
+ StrCatS (ResultStr, MAX_REDFISH_URL_LEN, Head);
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, return: %s\n", __FUNCTION__,
ResultStr));
+
+ return ResultStr;
+}
+
+/**
+
+ Return config language by given URI. It's call responsibility to release
returned buffer.
+
+ @param[in] Uri Uri to search.
+
+ @retval NULL Can not find redfish uri.
+ @retval Other redfish uri is returned.
+
+**/
+EFI_STRING
+RedfishGetConfigLanguage (
+ IN EFI_STRING Uri
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING ConfigLang;
+
+ if (IS_EMPTY_STRING (Uri)) {
+ return NULL;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, search config lang for URI: %s\n",
__FUNCTION__, Uri));
+
+ Status = RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol,
&gEdkIIRedfishConfigLangMapProtocolGuid);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, fail to locate
gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__, Status));
+ return NULL;
+ }
+
+ ConfigLang = NULL;
+ Status = mConfigLangMapProtocol->Get (
+ mConfigLangMapProtocol,
+ RedfishGetTypeUri,
+ Uri,
+ &ConfigLang
+ );
+
+
+ return ConfigLang;
+}
+
+/**
+
+ Return config language from given URI and prperty name. It's call
responsibility to release returned buffer.
+
+ @param[in] Uri The URI to match
+ @param[in] PropertyName The property name of resource. This is
optional.
+
+ @retval NULL Can not find redfish uri.
+ @retval Other redfish uri is returned.
+
+**/
+EFI_STRING
+GetConfigureLang (
+ IN CHAR8 *Uri,
+ IN CHAR8 *PropertyName OPTIONAL
+ )
+{
+ EFI_STRING ConfigLang;
+ UINTN StringSize;
+ EFI_STRING ResultStr;
+ EFI_STRING UnicodeUri;
+ EFI_STATUS Status;
+
+ if (IS_EMPTY_STRING (Uri)) {
+ return NULL;
+ }
+
+ StringSize = AsciiStrSize (Uri);
+ UnicodeUri = AllocatePool (StringSize * sizeof (CHAR16));
+ if (UnicodeUri == NULL) {
+ return NULL;
+ }
+
+ Status = AsciiStrToUnicodeStrS (Uri, UnicodeUri, StringSize);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ ConfigLang = RedfishGetConfigLanguage (UnicodeUri);
+ if (ConfigLang == NULL) {
+ return NULL;
+ }
+
+ if (IS_EMPTY_STRING (PropertyName)) {
+ return ConfigLang;
+ }
+
+ StringSize = StrSize (ConfigLang) + ((AsciiStrLen (PropertyName) + 1) *
sizeof (CHAR16));
+ ResultStr = AllocatePool (StringSize);
+ if (ResultStr == NULL) {
+ return NULL;
+ }
+
+ UnicodeSPrint (ResultStr, StringSize, L"%s/%a", ConfigLang,
PropertyName);
+
+ return ResultStr;
+}
+
+/**
+
+ Save Redfish URI in database for further use.
+
+ @param[in] ConfigLang ConfigLang to save
+ @param[in] Uri Redfish Uri to save
+
+ @retval EFI_INVALID_PARAMETR SystemId is NULL or EMPTY
+ @retval EFI_SUCCESS Redfish uri is saved
+
+**/
+EFI_STATUS
+RedfisSetRedfishUri (
+ IN EFI_STRING ConfigLang,
+ IN EFI_STRING Uri
+ )
+{
+ EFI_STATUS Status;
+
+ if (IS_EMPTY_STRING (ConfigLang) || IS_EMPTY_STRING (Uri)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol,
&gEdkIIRedfishConfigLangMapProtocolGuid);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, fail to locate
gEdkIIRedfishConfigLangMapProtocolGuid: %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, Saved: %s -> %s\n",
__FUNCTION__, ConfigLang, Uri));
+
+ return mConfigLangMapProtocol->Set (mConfigLangMapProtocol,
ConfigLang, Uri);
+}
+
+/**
+
+ Get @odata.id from give HTTP payload. It's call responsibility to release
returned buffer.
+
+ @param[in] Payload HTTP payload
+
+ @retval NULL Can not find @odata.id from given payload.
+ @retval Others odata.id string is returned.
+
+**/
+EFI_STRING
+GetOdataId (
+ IN REDFISH_PAYLOAD *Payload
+ )
+{
+ EDKII_JSON_VALUE *JsonValue;
+ EDKII_JSON_VALUE *OdataId;
+ EFI_STRING OdataIdString;
+
+ if (Payload == NULL) {
+ return NULL;
+ }
+
+ JsonValue = RedfishJsonInPayload (Payload);
+ if (!JsonValueIsObject (JsonValue)) {
+ return NULL;
+ }
+
+ OdataId = JsonObjectGetValue (JsonValueGetObject (JsonValue),
"@odata.id");
+ if (!JsonValueIsString (OdataId)) {
+ return NULL;
+ }
+
+ OdataIdString = JsonValueGetUnicodeString (OdataId);
+ if (OdataIdString == NULL) {
+ return NULL;
+ }
+
+ return AllocateCopyPool (StrSize (OdataIdString), OdataIdString);
+}
+
+
+/**
+
+ Get the property name by given Configure Langauge.
+
+ @param[in] ResourceUri URI of root of resource.
+ @param[in] ConfigureLang Configure Language string.
+
+ @retval EFI_STRING Pointer to property name.
+ @retval NULL There is error.
+
+**/
+EFI_STRING
+GetPropertyFromConfigureLang (
+ IN EFI_STRING ResourceUri,
+ IN EFI_STRING ConfigureLang
+ )
+{
+ EFI_STATUS Status;
+ EFI_STRING TempString;
+
+ if (ConfigureLang == NULL || ResourceUri == NULL) {
+ return NULL;
+ }
+
+ Status = IsRedpathArray (ConfigureLang, NULL, &TempString);
+ if (!EFI_ERROR(Status)) {
+ TempString += 2; // Advance two characters for '}' and '/'
+ return TempString;
+ }
+ if (Status != EFI_NOT_FOUND) {
+ return NULL;
+ }
+ //
+ // The ConigLang has no '{}'
+ //
+ if (GetNumberOfRedpathNodes (ConfigureLang) == 1) {
+ return NULL;
+ }
+
+ if (GetRedpathNodeByIndex (ConfigureLang, 0, &TempString) == NULL) {
+ return NULL;
+ }
+ //
+ // Advance two characters to the starting
+ // pointer of next node.
+ //
+ return TempString + 2;
+}
+
+/**
+
+ Get the property value in string type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+
+ @retval CHAR8* Pointer to the CHAR8 buffer.
+ @retval NULL There is error.
+
+**/
+CHAR8 *
+GetPropertyStringValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ CHAR8 *AsciiStringValue;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
+ return NULL;
+ }
+
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ return NULL;
+ }
+
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
PropertyName);
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+ return NULL;
+ }
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return NULL;
+ }
+
+ AsciiStringValue = AllocateCopyPool (AsciiStrSize
(RedfishValue.Value.Buffer), RedfishValue.Value.Buffer);
+ ASSERT (AsciiStringValue != NULL);
+
+ return AsciiStringValue;
+}
+
+/**
+
+ Get the property value in numeric type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+
+ @retval INT64* Pointer to the INT64 value.
+ @retval NULL There is error.
+
+**/
+INT64 *
+GetPropertyNumericValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ INT64 *ResultValue;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
+ return NULL;
+ }
+
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ return NULL;
+ }
+
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
PropertyName);
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+ return NULL;
+ }
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not numeric type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return NULL;
+ }
+
+ ResultValue = AllocatePool (sizeof (INT64));
+ ASSERT (ResultValue != NULL);
+ if (ResultValue == NULL) {
+ return NULL;
+ }
+
+ *ResultValue = RedfishValue.Value.Integer;
+
+ return ResultValue;
+}
+
+/**
+
+ Get the property value in Boolean type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+
+ @retval BOOLEAN Boolean value returned by this property.
+
+**/
+BOOLEAN *
+GetPropertyBooleanValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ BOOLEAN *ResultValue;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
+ return NULL;
+ }
+
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ return NULL;
+ }
+
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
PropertyName);
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+ return NULL;
+ }
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not boolean type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return NULL;
+ }
+
+ ResultValue = AllocatePool (sizeof (BOOLEAN));
+ ASSERT (ResultValue != NULL);
+ if (ResultValue == NULL) {
+ return NULL;
+ }
+
+ *ResultValue = RedfishValue.Value.Boolean;
+
+ return ResultValue;
+}
+
+/**
+
+ Return the last string of configure language. Any modification to returned
+ string will change ConfigureLanguage.
+
+ @param[in] ConfigureLanguage Configure language string
+
+ @retval EFI_STRING Attribute name is returned
+ @retval NULL Error occurs
+
+**/
+EFI_STRING
+GetAttributeNameFromConfigLanguage (
+ IN EFI_STRING ConfigureLanguage
+ )
+{
+ UINTN StringLen;
+ UINTN Index;
+
+ if (IS_EMPTY_STRING (ConfigureLanguage)) {
+ return NULL;
+ }
+
+ StringLen = StrLen (ConfigureLanguage);
+ for (Index = StringLen - 1; Index >= 0; Index--) {
+ if (ConfigureLanguage[Index] == '/') {
+ return &ConfigureLanguage[Index + 1];
+ }
+ }
+
+ return NULL;
+}
+
+/**
+
+ Get the property string value in array type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] ArraySize The size of returned array.
+
+ @retval CHAR8 ** Returned string array. NULL while error happens.
+
+**/
+CHAR8 **
+GetPropertyStringArrayValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ CHAR8 **StringArray;
+ UINTN Index;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
|| ArraySize == NULL) {
+ return NULL;
+ }
+
+ *ArraySize = 0;
+
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+ return NULL;
+ }
+
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
PropertyName);
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+ return NULL;
+ }
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING_ARRAY) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return NULL;
+ }
+
+ StringArray = AllocatePool (sizeof (CHAR8 *) * RedfishValue.ArrayCount);
+ if (StringArray == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+ return NULL;
+ }
+
+ *ArraySize = RedfishValue.ArrayCount;
+ for (Index = 0; Index < RedfishValue.ArrayCount; Index++) {
+ StringArray[Index] = RedfishValue.Value.StringArray[Index];
+ }
+
+ return StringArray;
+}
+
+/**
+
+ Get the property numeric value in array type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] ArraySize The size of returned array.
+
+ @retval INT64 * Returned integer array. NULL while error happens.
+
+**/
+INT64 *
+GetPropertyNumericArrayValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ INT64 *IntegerArray;
+ UINTN Index;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
|| ArraySize == NULL) {
+ return NULL;
+ }
+
+ *ArraySize = 0;
+
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+ return NULL;
+ }
+
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
PropertyName);
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+ return NULL;
+ }
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return NULL;
+ }
+
+ IntegerArray = AllocatePool (sizeof (INT64) * RedfishValue.ArrayCount);
+ if (IntegerArray == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+ return NULL;
+ }
+
+ *ArraySize = RedfishValue.ArrayCount;
+ for (Index = 0; Index < RedfishValue.ArrayCount; Index++) {
+ IntegerArray[Index] = RedfishValue.Value.IntegerArray[Index];
+ }
+
+ return IntegerArray;
+}
+
+/**
+
+ Get the property boolean value in array type.
+
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] ArraySize The size of returned array.
+
+ @retval BOOLEAN * Returned boolean array. NULL while error
happens.
+
+**/
+BOOLEAN *
+GetPropertyBooleanArrayValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
+ )
+{
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ BOOLEAN *BooleanArray;
+ UINTN Index;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
|| ArraySize == NULL) {
+ return NULL;
+ }
+
+ *ArraySize = 0;
+
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+ return NULL;
+ }
+
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
PropertyName);
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
+ return NULL;
+ }
+
+ if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN_ARRAY) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ return NULL;
+ }
+
+ BooleanArray = AllocatePool (sizeof (INT64) * RedfishValue.ArrayCount);
+ if (BooleanArray == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
+ return NULL;
+ }
+
+ *ArraySize = RedfishValue.ArrayCount;
+ for (Index = 0; Index < RedfishValue.ArrayCount; Index++) {
+ BooleanArray[Index] = RedfishValue.Value.BooleanArray[Index];
+ }
+
+ return BooleanArray;
+}
+
+/**
+
+ Free the list of empty property key values.
+
+ @param[in] EmptyPropKeyValueListHead The head of
RedfishCS_EmptyProp_KeyValue
+
+**/
+VOID
+FreeEmptyPropKeyValueList (
+ RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueListHead
+ )
+{
+ RedfishCS_EmptyProp_KeyValue *NextEmptyPropKeyValueList;

- if (StrCmp (UnifiedConfigureLangPool[Index2].ConfigureLang,
UnifiedConfigureLang) == 0) {
- Duplicated = TRUE;
- break;
- }
+ while (EmptyPropKeyValueListHead != NULL) {
+ NextEmptyPropKeyValueList = EmptyPropKeyValueListHead-
NextKeyValuePtr;
+ if (EmptyPropKeyValueListHead->Value->DataValue.CharPtr != NULL) {
+ FreePool(EmptyPropKeyValueListHead->Value->DataValue.CharPtr);
}
-
- if (Duplicated) {
- FreePool (UnifiedConfigureLang);
- continue;
+ if (EmptyPropKeyValueListHead->Value != NULL) {
+ FreePool(EmptyPropKeyValueListHead->Value);
}
-
- if (UnifiedConfigureLangList->Count >=
BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZE) {
- FreePool (UnifiedConfigureLang);
- Status = EFI_BUFFER_TOO_SMALL;
- break;
+ if (EmptyPropKeyValueListHead->KeyNamePtr != NULL) {
+ FreePool(EmptyPropKeyValueListHead->KeyNamePtr);
}
+ FreePool (EmptyPropKeyValueListHead);
+ EmptyPropKeyValueListHead = NextEmptyPropKeyValueList;
+ };
+}

- //
- // New configure language. Keep it in Pool
- //
+/**

- UnifiedConfigureLangPool[UnifiedConfigureLangList-
Count].ConfigureLang = UnifiedConfigureLang;
- UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].Index =
ArrayIndex;
- ++UnifiedConfigureLangList->Count;
- }
+ Create a new entry of RedfishCS_EmptyProp_KeyValue

- FreePool (ConfigureLangList);
+ @param[in] KeyName The key name.
+ @param[in] RedfishValue Redfish vale of this key.

- //
- // Prepare the result to caller.
- //
- UnifiedConfigureLangList->List = AllocateCopyPool (sizeof
(REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) *
UnifiedConfigureLangList->Count, UnifiedConfigureLangPool);
+* @retval RedfishCS_EmptyProp_KeyValue Return the new
RedfishCS_EmptyProp_KeyValue.
+* NULL means no new entry is created.

- return Status;
+**/
+RedfishCS_EmptyProp_KeyValue *
+NewEmptyPropKeyValueFromRedfishValue (
+ IN EFI_STRING KeyName,
+ IN EDKII_REDFISH_VALUE *RedfishValue
+ )
+{
+ RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValue;
+ RedfishCS_Vague *VagueValue;
+ RedfishCS_char *KeyNameChar;
+ VOID *Data;
+ UINTN DataSize;
+ INT32 Bool32;
+
+ KeyNameChar = StrUnicodeToAscii(KeyName);
+ if (KeyNameChar == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Failed to convert unicode to ASCII.\n",
__FUNCTION__));
+ return NULL;
+ }
+ EmptyPropKeyValue = (RedfishCS_EmptyProp_KeyValue
*)AllocateZeroPool (sizeof (RedfishCS_EmptyProp_KeyValue));
+ if (EmptyPropKeyValue == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
EmptyPropKeyValue\n", __FUNCTION__));
+ return NULL;
+ }
+ VagueValue = (RedfishCS_Vague *)AllocateZeroPool (sizeof
(RedfishCS_Vague));
+ if (VagueValue == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
VagueValue\n", __FUNCTION__));
+ FreePool (EmptyPropKeyValue);
+ return NULL;
+ }
+
+ if (RedfishValue->Type == REDFISH_VALUE_TYPE_BOOLEAN) {
+ VagueValue->DataType = RedfishCS_Vague_DataType_Bool;
+ DataSize = sizeof (BOOLEAN);
+ //
+ // Redfish JSON to C strcuture converter uses
+ // "int" for the BOOLEAN.
+ //
+ Bool32 = (INT32)RedfishValue->Value.Boolean;
+ Data = (VOID *)&Bool32;
+ } else if (RedfishValue->Type == REDFISH_VALUE_TYPE_INTEGER) {
+ VagueValue->DataType = RedfishCS_Vague_DataType_Int64;
+ DataSize = sizeof (INT64);
+ Data = (VOID *)&RedfishValue->Value.Integer;
+ } else if (RedfishValue->Type == REDFISH_VALUE_TYPE_STRING) {
+ VagueValue->DataType = RedfishCS_Vague_DataType_String;
+ DataSize = AsciiStrSize(RedfishValue->Value.Buffer);
+ Data = (VOID *)RedfishValue->Value.Buffer;
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a, wrong type of RedfishValue: %x\n",
__FUNCTION__, RedfishValue->Type));
+ FreePool (VagueValue);
+ FreePool (EmptyPropKeyValue);
+ return NULL;
+ }
+ VagueValue->DataValue.CharPtr = (RedfishCS_char
*)AllocateCopyPool(DataSize, Data);
+ EmptyPropKeyValue->Value = VagueValue;
+ EmptyPropKeyValue->KeyNamePtr = KeyNameChar;
+ return EmptyPropKeyValue;
}

/**

- Create HTTP payload and send them to redfish service with PATCH method.
+ Get the property value in the vague type.

- @param[in] Service Redfish service.
- @param[in] TargetPayload Target payload
- @param[in] Json Data in JSON format.
- @param[out] Etag Returned ETAG string from Redfish service.
+ @param[in] Schema Schema of this property.
+ @param[in] Version Schema version.
+ @param[in] PropertyName Property name.
+ @param[in] ConfigureLang Configure Language of this property.
+ @param[out] NumberOfValues Return the number of vague type of
values

- @retval EFI_SUCCESS Data is sent to redfish service successfully.
- @retval Others Errors occur.
+ @retval RedfishCS_EmptyProp_KeyValue The pointer to the structure
+ of vague type of values.

**/
-EFI_STATUS
-CreatePayloadToPatchResource (
- IN REDFISH_SERVICE *Service,
- IN REDFISH_PAYLOAD *TargetPayload,
- IN CHAR8 *Json,
- OUT CHAR8 **Etag
+RedfishCS_EmptyProp_KeyValue *
+GetPropertyVagueValue (
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINT32 *NumberOfValues
)
{
- REDFISH_PAYLOAD Payload;
- EDKII_JSON_VALUE ResourceJsonValue;
- REDFISH_RESPONSE PostResponse;
- EFI_STATUS Status;
- UINTN Index;
- EDKII_JSON_VALUE JsonValue;
- EDKII_JSON_VALUE OdataIdValue;
- CHAR8 *OdataIdString;
+ EFI_STATUS Status;
+ RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueList;
+ RedfishCS_EmptyProp_KeyValue *PreEmptyPropKeyValueList;
+ RedfishCS_EmptyProp_KeyValue *FirstEmptyPropKeyValueList;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ EFI_STRING KeyName;
+ EFI_STRING *ConfigureLangList;
+ EFI_STRING SearchPattern;
+ UINTN BufferSize;
+ UINTN ConfigListCount;
+ UINTN ConfigListCountIndex;

- if (Service == NULL || TargetPayload == NULL || IS_EMPTY_STRING (Json)
|| Etag == NULL) {
- return EFI_INVALID_PARAMETER;
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
+ return NULL;
}

- ResourceJsonValue = JsonLoadString (Json, 0, NULL);
- Payload = RedfishCreatePayload (ResourceJsonValue, Service);
- if (Payload == NULL) {
- DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
JSON value!\n",__FUNCTION__, __LINE__));
- Status = EFI_DEVICE_ERROR;
- goto EXIT_FREE_JSON_VALUE;
+ //
+ // Configure Language buffer.
+ //
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ ConfigureLangBuffer = AllocatePool (BufferSize);
+ if (ConfigureLangBuffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
ConfigureLangBuffer\n", __FUNCTION__));
+ return NULL;
}
+ UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
PropertyName);

- ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
- Status = RedfishPatchToPayload (TargetPayload, Payload, &PostResponse);
+ //
+ // Initial search pattern
+ //
+ BufferSize = (StrLen (ConfigureLangBuffer) + StrLen (L"/.*") + 1) * sizeof
(CHAR16); // Increase one for the NULL terminator.
+ SearchPattern = AllocatePool (BufferSize);
+ if (SearchPattern == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
SearchPattern\n", __FUNCTION__));
+ FreePool (ConfigureLangBuffer);
+ return NULL;
+ }
+ BufferSize = BufferSize / sizeof (CHAR16);
+ StrCpyS (SearchPattern, BufferSize, ConfigureLangBuffer);
+ StrCatS (SearchPattern, BufferSize, L"/.*");
+ Status = RedfishPlatformConfigGetConfigureLang (Schema, Version,
SearchPattern, &ConfigureLangList, &ConfigListCount);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish
service.\n",__FUNCTION__, __LINE__));
- goto EXIT_FREE_JSON_VALUE;
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a Get configure language of vague
type values of %s failed: %r\n", __FUNCTION__, Schema, Version,
ConfigureLangBuffer, Status));
+ goto ErrorLeave;
}

-
//
- // Keep etag.
+ // Build up the list of RedfishCS_EmptyProp_KeyValue.
//
- *Etag = NULL;
- if (*PostResponse.StatusCode == HTTP_STATUS_200_OK) {
- if (PostResponse.HeaderCount != 0) {
- for (Index = 0; Index < PostResponse.HeaderCount; Index++) {
- if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName, "ETag", 4)
== 0) {
- *Etag = AllocateCopyPool (AsciiStrSize
(PostResponse.Headers[Index].FieldValue),
PostResponse.Headers[Index].FieldValue);
- }
- }
- } else if (PostResponse.Payload != NULL) {
- //
- // No header is returned. Search payload for location.
- //
- JsonValue = RedfishJsonInPayload (PostResponse.Payload);
- if (JsonValue != NULL) {
- OdataIdValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
"@odata.etag");
- if (OdataIdValue != NULL) {
- OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
- if (OdataIdString != NULL) {
- *Etag = AllocateCopyPool (AsciiStrSize (OdataIdString), OdataIdString);
- }
- }
- }
+ ConfigListCountIndex = 0;
+ PreEmptyPropKeyValueList = NULL;
+ FirstEmptyPropKeyValueList = NULL;
+ while (ConfigListCountIndex < ConfigListCount) {
+ Status = RedfishPlatformConfigGetValue(Schema, Version,
ConfigureLangList [ConfigListCountIndex], &RedfishValue);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangList
[ConfigListCountIndex], Status));
+ goto ErrorLeave;
}
- }
-
- RedfishFreeResponse (
- PostResponse.StatusCode,
- PostResponse.HeaderCount,
- PostResponse.Headers,
- PostResponse.Payload
- );
+ //
+ // Get the key name.
+ //
+ KeyName = GetAttributeNameFromConfigLanguage (ConfigureLangList
[ConfigListCountIndex]);
+ //
+ // Create an entry of RedfishCS_EmptyProp_KeyValue.
+ //
+ EmptyPropKeyValueList = NewEmptyPropKeyValueFromRedfishValue
(KeyName, &RedfishValue);
+ if (EmptyPropKeyValueList == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a, Failed to create an entry of
EmptyPropKeyValueList\n", __FUNCTION__));
+ ConfigListCountIndex ++;
+ continue;
+ }
+ //
+ // Link the RedfishCS_EmptyProp_KeyValue list.
+ //
+ if (PreEmptyPropKeyValueList != NULL) {
+ PreEmptyPropKeyValueList->NextKeyValuePtr =
EmptyPropKeyValueList;
+ } else {
+ FirstEmptyPropKeyValueList = EmptyPropKeyValueList;
+ }
+ PreEmptyPropKeyValueList = EmptyPropKeyValueList;
+ ConfigListCountIndex ++;
+ };
+ goto LeaveFunction;

-EXIT_FREE_JSON_VALUE:
- if (Payload != NULL) {
- RedfishCleanupPayload (Payload);
+ErrorLeave:;
+ if (FirstEmptyPropKeyValueList != NULL) {
+ FreeEmptyPropKeyValueList (FirstEmptyPropKeyValueList);
}
+ FirstEmptyPropKeyValueList = NULL;

- JsonValueFree (ResourceJsonValue);
+LeaveFunction:
+ if (SearchPattern != NULL) {
+ FreePool (SearchPattern);
+ }
+ if (ConfigureLangBuffer != NULL) {
+ FreePool (ConfigureLangBuffer);
+ }
+ FreePool (ConfigureLangList);

- return Status;
+ *NumberOfValues = (UINT32)ConfigListCount;
+ return FirstEmptyPropKeyValueList;
}

/**

- Create HTTP payload and send them to redfish service with POST method.
+ Check and see if we need to do provisioning for this property.

- @param[in] Service Redfish service.
- @param[in] TargetPayload Target payload
- @param[in] Json Data in JSON format.
- @param[out] Location Returned location string from Redfish service.
- @param[out] Etag Returned ETAG string from Redfish service.
+ @param[in] PropertyBuffer Pointer to property instance.
+ @param[in] ProvisionMode TRUE if we are in provision mode. FALSE
otherwise.

- @retval EFI_SUCCESS Data is sent to redfish service successfully.
- @retval Others Errors occur.
+ @retval TRUE Provision is required.
+ @retval FALSE Provision is not required.

**/
-EFI_STATUS
-CreatePayloadToPostResource (
- IN REDFISH_SERVICE *Service,
- IN REDFISH_PAYLOAD *TargetPayload,
- IN CHAR8 *Json,
- OUT CHAR8 **Location,
- OUT CHAR8 **Etag
+BOOLEAN
+PropertyChecker (
+ IN VOID *PropertyBuffer,
+ IN BOOLEAN ProvisionMode
)
{
- REDFISH_PAYLOAD Payload;
- EDKII_JSON_VALUE ResourceJsonValue;
- REDFISH_RESPONSE PostResponse;
- EFI_STATUS Status;
- UINTN Index;
- EDKII_JSON_VALUE JsonValue;
- EDKII_JSON_VALUE OdataIdValue;
- CHAR8 *OdataIdString;
+ if (ProvisionMode) {
+ return TRUE;
+ }

- if (Service == NULL || TargetPayload == NULL || IS_EMPTY_STRING (Json)
|| Location == NULL || Etag == NULL) {
- return EFI_INVALID_PARAMETER;
+ if (!ProvisionMode && PropertyBuffer != NULL) {
+ return TRUE;
}

- ResourceJsonValue = JsonLoadString (Json, 0, NULL);
- Payload = RedfishCreatePayload (ResourceJsonValue, Service);
- if (Payload == NULL) {
- DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
JSON value!\n",__FUNCTION__, __LINE__));
- Status = EFI_DEVICE_ERROR;
- goto EXIT_FREE_JSON_VALUE;
+ return FALSE;
+}
+
+/**
+
+ Check and see if ETAG is identical to what we keep in system.
+
+ @param[in] Uri URI requested
+ @param[in] EtagInHeader ETAG string returned from HTTP request.
+ @param[in] EtagInJson ETAG string in JSON body.
+
+ @retval TRUE ETAG is identical.
+ @retval FALSE ETAG is changed.
+
+**/
+BOOLEAN
+CheckEtag (
+ IN EFI_STRING Uri,
+ IN CHAR8 *EtagInHeader,
+ IN CHAR8 *EtagInJson
+ )
+{
+ CHAR8 *EtagInDb;
+
+ if (IS_EMPTY_STRING (Uri)) {
+ return FALSE;
}

- ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
- Status = RedfishPostToPayload (TargetPayload, Payload, &PostResponse);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a:%d Failed to POST Attribute Registry to
Redfish service.\n",__FUNCTION__, __LINE__));
- goto EXIT_FREE_JSON_VALUE;
+ if (IS_EMPTY_STRING (EtagInHeader) && IS_EMPTY_STRING (EtagInJson))
{
+ return FALSE;
}

//
- // per Redfish spec. the URL of new eresource will be returned in
"Location" header.
+ // Check ETAG to see if we need to consume it
//
- *Location = NULL;
- *Etag = NULL;
- if (*PostResponse.StatusCode == HTTP_STATUS_200_OK) {
- if (PostResponse.HeaderCount != 0) {
- for (Index = 0; Index < PostResponse.HeaderCount; Index++) {
- if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName, "Location",
8) == 0) {
- *Location = AllocateCopyPool (AsciiStrSize
(PostResponse.Headers[Index].FieldValue),
PostResponse.Headers[Index].FieldValue);
- } else if (AsciiStrnCmp (PostResponse.Headers[Index].FieldName,
"ETag", 4) == 0) {
- *Etag = AllocateCopyPool (AsciiStrSize
(PostResponse.Headers[Index].FieldValue),
PostResponse.Headers[Index].FieldValue);
- }
- }
- } else if (PostResponse.Payload != NULL) {
- //
- // No header is returned. Search payload for location.
- //
- JsonValue = RedfishJsonInPayload (PostResponse.Payload);
- if (JsonValue != NULL) {
- OdataIdValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
"@odata.id");
- if (OdataIdValue != NULL) {
- OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
- if (OdataIdString != NULL) {
- *Location = AllocateCopyPool (AsciiStrSize (OdataIdString),
OdataIdString);
- }
- }
+ EtagInDb = NULL;
+ EtagInDb = GetEtagWithUri (Uri);
+ if (EtagInDb == NULL) {
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a, no ETAG record cound be found
for: %s\n", __FUNCTION__, Uri));
+ return FALSE;
+ }

- OdataIdValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
"@odata.etag");
- if (OdataIdValue != NULL) {
- OdataIdString = (CHAR8 *)JsonValueGetAsciiString (OdataIdValue);
- if (OdataIdString != NULL) {
- *Etag = AllocateCopyPool (AsciiStrSize (OdataIdString), OdataIdString);
- }
- }
- }
+ if (EtagInHeader != NULL) {
+ if (AsciiStrCmp (EtagInDb, EtagInHeader) == 0) {
+ FreePool (EtagInDb);
+ return TRUE;
}
}

- //
- // This is not expected as service does not follow spec.
- //
- if (*Location == NULL) {
- Status = EFI_DEVICE_ERROR;
+ if (EtagInJson != NULL) {
+ if (AsciiStrCmp (EtagInDb, EtagInJson) == 0) {
+ FreePool (EtagInDb);
+ return TRUE;
+ }
}

- RedfishFreeResponse (
- PostResponse.StatusCode,
- PostResponse.HeaderCount,
- PostResponse.Headers,
- PostResponse.Payload
- );
-
- RedfishCleanupPayload (Payload);
-
-EXIT_FREE_JSON_VALUE:
- JsonValueFree (JsonValue);
- JsonValueFree (ResourceJsonValue);
+ FreePool (EtagInDb);

- return Status;
+ return FALSE;
}

/**
+ Check and see if given ObjectName can be found in JsonObj or not

- Find Redfish Resource Config Protocol that supports given schema and
version.
+ @param[in] JsonObj JSON object to search
+ @param[in] ObjectName Object name

- @param[in] Schema Schema name.
- @param[in] Major Schema version major number.
- @param[in] Minor Schema version minor number.
- @param[in] Errata Schema version errata number.
-
- @retval EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL * Pointer to
protocol
- @retval NULL No protocol found.
+ @retval EDKII_JSON_VALUE * Pointer to Json object is found. NULL
otherwise.

**/
-EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *
-GetRedfishResourceConfigProtocol (
- IN CHAR8 *Schema,
- IN CHAR8 *Major,
- IN CHAR8 *Minor,
- IN CHAR8 *Errata
+EDKII_JSON_VALUE *
+MatchJsonObject (
+ IN EDKII_JSON_VALUE *JsonObj,
+ IN CHAR8 *ObjectName
)
{
- EFI_STATUS Status;
- EFI_HANDLE *HandleBuffer;
- UINTN NumberOfHandles;
- UINTN Index;
- EDKII_REDFISH_RESOURCE_CONFIG_PROTOCOL *Protocol;
- REDFISH_SCHEMA_INFO SchemaInfo;
- BOOLEAN Found;
+ EDKII_JSON_VALUE N;
+ CHAR8 *Key;
+ EDKII_JSON_VALUE Value;

- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Major) ||
IS_EMPTY_STRING (Minor) || IS_EMPTY_STRING (Errata)) {
+ if (JsonObj == NULL || IS_EMPTY_STRING (ObjectName)) {
return NULL;
}

- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEdkIIRedfishResourceConfigProtocolGuid,
- NULL,
- &NumberOfHandles,
- &HandleBuffer
- );
- if (EFI_ERROR (Status)) {
+ if (!JsonValueIsObject (JsonObj)) {
return NULL;
}

- Found = FALSE;
-
- for (Index = 0; Index < NumberOfHandles; Index++) {
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEdkIIRedfishResourceConfigProtocolGuid,
- (VOID **) &Protocol
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- Status = Protocol->GetInfo (Protocol, &SchemaInfo);
- if (EFI_ERROR (Status)) {
- continue;
+ EDKII_JSON_OBJECT_FOREACH_SAFE (JsonObj, N, Key, Value) {
+ if (AsciiStrCmp (Key, ObjectName) == 0) {
+ return Value;
}
-
- if (AsciiStrCmp (Schema, SchemaInfo.Schema) == 0 &&
- AsciiStrCmp (Major, SchemaInfo.Major) == 0 &&
- AsciiStrCmp (Minor, SchemaInfo.Minor) == 0 &&
- AsciiStrCmp (Errata, SchemaInfo.Errata) == 0) {
- Found = TRUE;
- break;
- }
}

- FreePool (HandleBuffer);
-
- return (Found ? Protocol : NULL);
+ return NULL;
}

/**

- Get supported schema list by given specify schema name.
+ Check and see if given property is in JSON context or not

- @param[in] Schema Schema type name.
- @param[out] SchemaInfo Returned schema information.
+ @param[in] Property Property name string
+ @param[in] Json The JSON context to search.

- @retval EFI_SUCCESS Schema information is returned successfully.
- @retval Others Errors occur.
+ @retval TRUE Property is found in JSON context
+ @retval FALSE Property is not in JSON context

**/
-EFI_STATUS
-GetSupportedSchemaVersion (
- IN CHAR8 *Schema,
- OUT REDFISH_SCHEMA_INFO *SchemaInfo
+BOOLEAN
+MatchPropertyWithJsonContext (
+ IN EFI_STRING Property,
+ IN CHAR8 *Json
)
{
- EFI_STATUS Status;
- CHAR8 *SupportSchema;
- CHAR8 *SchemaName;
- UINTN Index;
- UINTN Index2;
- BOOLEAN Found;
+ CHAR8 *AsciiProperty;
+ CHAR8 *PropertyNode;
+ UINTN Index;
+ EDKII_JSON_VALUE *JsonObj;
+ EDKII_JSON_VALUE *MatchObj;
+ EDKII_JSON_TYPE JsonType;

- if (IS_EMPTY_STRING (Schema) || SchemaInfo == NULL) {
- return EFI_INVALID_PARAMETER;
+ if (IS_EMPTY_STRING (Property) || IS_EMPTY_STRING (Json)) {
+ return FALSE;
}

- Status = RedfishPlatformConfigGetSupportedSchema (NULL,
&SupportSchema);
- if (EFI_ERROR (Status)) {
- return Status;
+ JsonObj = JsonLoadString (Json, 0, NULL);
+ if (JsonObj == NULL || !JsonValueIsObject (JsonObj)) {
+ return FALSE;
}

- DEBUG ((DEBUG_INFO, "Supported schema: %a\n", SupportSchema));
-
- Index = 0;
- Found = FALSE;
- SchemaName = SupportSchema;
- while (TRUE) {
-
- if (SupportSchema[Index] == ';' || SupportSchema[Index] == '\0') {
- if (AsciiStrnCmp (&SchemaName[SCHEMA_NAME_PREFIX_OFFSET],
Schema, AsciiStrLen (Schema)) == 0) {
- Found = TRUE;
- SupportSchema[Index] = '\0';
- break;
- }
-
- SchemaName = &SupportSchema[Index + 1];
- }
-
- if (SupportSchema[Index] == '\0') {
- break;
- }
-
- ++Index;
+ AsciiProperty = StrUnicodeToAscii (Property);
+ if (AsciiProperty == NULL) {
+ return FALSE;
}

- if (Found) {
-
- AsciiStrCpyS (SchemaInfo->Schema, REDFISH_SCHEMA_STRING_SIZE,
Schema);
-
- //
- // forward to '.'
- //
- Index = 0;
- while (SchemaName[Index] != '\0' && SchemaName[Index] != '.') {
- ++Index;
- }
- ASSERT (SchemaName[Index] != '\0');
+ Index = 0;
+ PropertyNode = AsciiProperty;
+ MatchObj = JsonObj;

- //
- // Skip '.' and 'v'
- //
- Index += 2;
+ //
+ // Walk through property and find corresponding object in JSON input
+ //
+ while (AsciiProperty[Index] != '\0') {

- //
- // forward to '_'
- //
- Index2 = Index;
- while (SchemaName[Index2] != '\0' && SchemaName[Index2] != '_') {
- ++Index2;
+ if (AsciiProperty[Index] == '/') {
+ AsciiProperty[Index] = '\0';
+ MatchObj = MatchJsonObject (MatchObj, PropertyNode);
+ if (MatchObj == NULL) {
+ PropertyNode = NULL;
+ break;
+ }
+
+ PropertyNode = &AsciiProperty[Index + 1];
}
- ASSERT (SchemaName[Index2] != '\0');

- AsciiStrnCpyS (SchemaInfo->Major, REDFISH_SCHEMA_VERSION_SIZE,
&SchemaName[Index], (Index2 - Index));
- Index = Index2;
+ Index++;
+ }

- //
- // Skip '_'
- //
- ++Index;
+ if (PropertyNode != NULL) {
+ MatchObj = MatchJsonObject (MatchObj, PropertyNode);
+ }

+ //
+ // Value check
+ //
+ if (MatchObj != NULL) {
//
- // forward to '_'
+ // If object has empty value, treat it as not matching
//
- Index2 = Index;
- while (SchemaName[Index2] != '\0' && SchemaName[Index2] != '_') {
- ++Index2;
+ JsonType = JsonGetType (MatchObj);
+ switch (JsonType) {
+ case EdkiiJsonTypeObject:
+ if (JsonValueIsNull (MatchObj)) {
+ MatchObj = NULL;
+ }
+ break;
+ case EdkiiJsonTypeArray:
+ if (JsonArrayCount (MatchObj) == 0) {
+ MatchObj = NULL;
+ }
+ break;
+ case EdkiiJsonTypeString:
+ if (IS_EMPTY_STRING (JsonValueGetString (MatchObj))) {
+ MatchObj = NULL;
+ }
+ break;
+ case EdkiiJsonTypeNull:
+ MatchObj = NULL;
+ break;
+ default:
+ break;
}
- ASSERT (SchemaName[Index2] != '\0');
-
- AsciiStrnCpyS (SchemaInfo->Minor, REDFISH_SCHEMA_VERSION_SIZE,
&SchemaName[Index], (Index2 - Index));
- Index = Index2;
-
- //
- // Skip '_'
- //
- ++Index;
-
- AsciiStrCpyS (SchemaInfo->Errata, REDFISH_SCHEMA_VERSION_SIZE,
&SchemaName[Index]);
}

- FreePool (SupportSchema);
-
- return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
-}
-
-/**
-
- Return system root path. This is dummy function now.
+ FreePool (AsciiProperty);

- @retval NULL Can not find system root path.
- @retval Other System root path is returned.
-
-**/
-CHAR8 *
-RedfishGetSystemRootPath (
- VOID
- )
-{
- return AllocateCopyPool (AsciiStrSize (REDFISH_SYSTEM_ROOT_PATH),
REDFISH_SYSTEM_ROOT_PATH);
+ return (MatchObj == NULL ? FALSE : TRUE);
}

/**

- Get schema information by given protocol and service instance.
+ Create string array and append to arry node in Redfish JSON convert
format.

- @param[in] RedfishService Pointer to Redfish service instance.
- @param[in] JsonStructProtocol Json Structure protocol instance.
- @param[in] Uri Target URI.
- @param[out] SchemaInfo Returned schema information.
+ @param[in,out] Head The head of string array.
+ @param[in] StringArray Input string array.
+ @param[in] ArraySize The size of StringArray.

- @retval EFI_SUCCESS Schema information is returned successfully.
- @retval Others Errors occur.
+ @retval EFI_SUCCESS String array is created successfully.
+ @retval Others Error happens

**/
EFI_STATUS
-GetRedfishSchemaInfo (
- IN REDFISH_SERVICE *RedfishService,
- IN EFI_REST_JSON_STRUCTURE_PROTOCOL *JsonStructProtocol,
- IN CHAR8 *Uri,
- OUT REDFISH_SCHEMA_INFO *SchemaInfo
+AddRedfishCharArray (
+ IN OUT RedfishCS_char_Array **Head,
+ IN CHAR8 **StringArray,
+ IN UINTN ArraySize
)
{
- EFI_STATUS Status;
- REDFISH_RESPONSE Response;
- REDFISH_PAYLOAD Payload;
- CHAR8 *JsonText;
- EFI_REST_JSON_STRUCTURE_HEADER *Header;
+ UINTN Index;
+ RedfishCS_char_Array *CharArrayBuffer;
+ RedfishCS_char_Array *PreArrayBuffer;

- if (RedfishService == NULL || JsonStructProtocol == NULL ||
IS_EMPTY_STRING (Uri) || SchemaInfo == NULL) {
+ if (Head == NULL || StringArray == NULL || ArraySize == 0) {
return EFI_INVALID_PARAMETER;
}

- Status = GetResourceByPath (RedfishService, Uri, &Response);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, failed to get resource from %a %r",
__FUNCTION__, Uri, Status));
- return Status;
- }
-
- Payload = Response.Payload;
- ASSERT (Payload != NULL);
+ PreArrayBuffer = NULL;
+ for (Index = 0; Index < ArraySize; Index++) {
+ CharArrayBuffer = AllocatePool (sizeof (RedfishCS_char_Array));
+ if (CharArrayBuffer == NULL) {
+ ASSERT (CharArrayBuffer != NULL);
+ continue;
+ }

- JsonText = JsonDumpString (RedfishJsonInPayload (Payload),
EDKII_JSON_COMPACT);
- ASSERT (JsonText != NULL);
+ if (Index == 0) {
+ *Head = CharArrayBuffer;
+ }

- //
- // Convert JSON text to C structure.
- //
- Status = JsonStructProtocol->ToStructure (
- JsonStructProtocol,
- NULL,
- JsonText,
- &Header
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, ToStructure() failed: %r\n",
__FUNCTION__, Status));
- return Status;
+ CharArrayBuffer->ArrayValue = StringArray[Index];
+ CharArrayBuffer->Next = NULL;
+ if (PreArrayBuffer != NULL) {
+ PreArrayBuffer->Next = CharArrayBuffer;
+ }
+ PreArrayBuffer = CharArrayBuffer;
}

- AsciiStrCpyS (SchemaInfo->Schema, REDFISH_SCHEMA_STRING_SIZE,
Header->JsonRsrcIdentifier.NameSpace.ResourceTypeName);
- AsciiStrCpyS (SchemaInfo->Major, REDFISH_SCHEMA_VERSION_SIZE,
Header->JsonRsrcIdentifier.NameSpace.MajorVersion);
- AsciiStrCpyS (SchemaInfo->Minor, REDFISH_SCHEMA_VERSION_SIZE,
Header->JsonRsrcIdentifier.NameSpace.MinorVersion);
- AsciiStrCpyS (SchemaInfo->Errata, REDFISH_SCHEMA_VERSION_SIZE,
Header->JsonRsrcIdentifier.NameSpace.ErrataVersion);
-
- //
- // Release resource.
- //
- JsonStructProtocol->DestoryStructure (JsonStructProtocol, Header);
- FreePool (JsonText);
- RedfishFreeResponse (Response.StatusCode, Response.HeaderCount,
Response.Headers, Response.Payload);
-
return EFI_SUCCESS;
}

/**

- Get the property name by given Configure Langauge.
+ Create numeric array and append to arry node in Redfish JSON convert
format.

- @param[in] ConfigureLang Configure Language string.
+ @param[in,out] Head The head of string array.
+ @param[in] NumericArray Input numeric array.
+ @param[in] ArraySize The size of NumericArray.

- @retval EFI_STRING Pointer to property name.
- @retval NULL There is error.
+ @retval EFI_SUCCESS String array is created successfully.
+ @retval Others Error happens

**/
-EFI_STRING
-GetPropertyFromConfigureLang (
- IN EFI_STRING ConfigureLang
+EFI_STATUS
+AddRedfishNumericArray (
+ IN OUT RedfishCS_int64_Array **Head,
+ IN INT64 *NumericArray,
+ IN UINTN ArraySize
)
{
- EFI_STRING Property;
- UINTN Index;
+ UINTN Index;
+ RedfishCS_int64_Array *NumericArrayBuffer;
+ RedfishCS_int64_Array *PreArrayBuffer;

- if (ConfigureLang == NULL) {
- return NULL;
+ if (Head == NULL || NumericArray == NULL || ArraySize == 0) {
+ return EFI_INVALID_PARAMETER;
}

- Index = 0;
- Property = ConfigureLang;
-
- while (ConfigureLang[Index] != '\0') {
- if (ConfigureLang[Index] == L'/') {
- Property = &ConfigureLang[Index];
+ PreArrayBuffer = NULL;
+ for (Index = 0; Index < ArraySize; Index++) {
+ NumericArrayBuffer = AllocatePool (sizeof (RedfishCS_int64_Array));
+ if (NumericArrayBuffer == NULL) {
+ ASSERT (NumericArrayBuffer != NULL);
+ continue;
}

- ++Index;
+ if (Index == 0) {
+ *Head = NumericArrayBuffer;
+ }
+ NumericArrayBuffer->ArrayValue = AllocatePool (sizeof
(RedfishCS_int64));
+ if (NumericArrayBuffer->ArrayValue == NULL) {
+ ASSERT (NumericArrayBuffer->ArrayValue != NULL);
+ continue;
+ }
+ *NumericArrayBuffer->ArrayValue = NumericArray[Index];
+ NumericArrayBuffer->Next = NULL;
+ if (PreArrayBuffer != NULL) {
+ PreArrayBuffer->Next = NumericArrayBuffer;
+ }
+ PreArrayBuffer = NumericArrayBuffer;
}

- ++Property;
-
- return Property;
+ return EFI_SUCCESS;
}

/**

- Get the property value in string type.
+ Create boolean array and append to arry node in Redfish JSON convert
format.

- @param[in] Schema Schema of this property.
- @param[in] Version Schema version.
- @param[in] PropertyName Property name.
- @param[in] ConfigureLang Configure Language of this property.
+ @param[in,out] Head The head of string array.
+ @param[in] BooleanArray Input boolean array.
+ @param[in] ArraySize The size of BooleanArray.

- @retval CHAR8* Pointer to the CHAR8 buffer.
- @retval NULL There is error.
+ @retval EFI_SUCCESS String array is created successfully.
+ @retval Others Error happens

**/
-CHAR8 *
-GetPropertyStringValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang
+EFI_STATUS
+AddRedfishBooleanArray (
+ IN OUT RedfishCS_bool_Array **Head,
+ IN BOOLEAN *BooleanArray,
+ IN UINTN ArraySize
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
- EFI_STRING ConfigureLangBuffer;
- UINTN BufferSize;
- CHAR8 *AsciiStringValue;
+ UINTN Index;
+ RedfishCS_bool_Array *BooleanArrayBuffer;
+ RedfishCS_bool_Array *PreArrayBuffer;

- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
- return NULL;
+ if (Head == NULL || BooleanArrayBuffer == NULL || ArraySize == 0) {
+ return EFI_INVALID_PARAMETER;
}

- //
- // Configure Language buffer.
- //
- BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
- ConfigureLangBuffer = AllocatePool (BufferSize);
- if (ConfigureLangBuffer == NULL) {
- return NULL;
- }
+ PreArrayBuffer = NULL;
+ for (Index = 0; Index < ArraySize; Index++) {
+ BooleanArrayBuffer = AllocatePool (sizeof (RedfishCS_bool_Array));
+ if (BooleanArrayBuffer == NULL) {
+ ASSERT (BooleanArrayBuffer != NULL);
+ continue;
+ }

- UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
PropertyName);
- Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
- return NULL;
- }
+ if (Index == 0) {
+ *Head = BooleanArrayBuffer;
+ }

- if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
- return NULL;
+ BooleanArrayBuffer->ArrayValue = AllocatePool (sizeof
(RedfishCS_bool));
+ if (BooleanArrayBuffer->ArrayValue == NULL) {
+ ASSERT (BooleanArrayBuffer->ArrayValue != NULL);
+ continue;
+ }
+ *BooleanArrayBuffer->ArrayValue = BooleanArray[Index];
+ BooleanArrayBuffer->Next = NULL;
+ if (PreArrayBuffer != NULL) {
+ PreArrayBuffer->Next = BooleanArrayBuffer;
+ }
+ PreArrayBuffer = BooleanArrayBuffer;
}

- AsciiStringValue = AllocateCopyPool (AsciiStrSize
(RedfishValue.Value.Buffer), RedfishValue.Value.Buffer);
- ASSERT (AsciiStringValue != NULL);
-
- return AsciiStringValue;
+ return EFI_SUCCESS;
}

/**

- Get the property value in numeric type.
+ Check and see if value in Redfish string array are all the same as the one
+ from HII configuration.

- @param[in] Schema Schema of this property.
- @param[in] Version Schema version.
- @param[in] PropertyName Property name.
- @param[in] ConfigureLang Configure Language of this property.
+ @param[in] Head The head of string array.
+ @param[in] StringArray Input string array.
+ @param[in] ArraySize The size of StringArray.

- @retval INT64* Pointer to the INT64 value.
- @retval NULL There is error.
+ @retval TRUE All string in Redfish array are as same as string
+ in HII configuration array.
+ FALSE These two array are not identical.

**/
-INT64 *
-GetPropertyNumericValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang
+BOOLEAN
+CompareRedfishStringArrayValues (
+ IN RedfishCS_char_Array *Head,
+ IN CHAR8 **StringArray,
+ IN UINTN ArraySize
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
- EFI_STRING ConfigureLangBuffer;
- UINTN BufferSize;
- INT64 *ResultValue;
+ UINTN Index;
+ RedfishCS_char_Array *CharArrayBuffer;

- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
- return NULL;
+ if (Head == NULL || StringArray == NULL || ArraySize == 0) {
+ return FALSE;
}

- //
- // Configure Language buffer.
- //
- BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
- ConfigureLangBuffer = AllocatePool (BufferSize);
- if (ConfigureLangBuffer == NULL) {
- return NULL;
- }
+ CharArrayBuffer = Head;
+ Index = 0;
+ while (CharArrayBuffer != NULL && Index < ArraySize) {

- UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
PropertyName);
- Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
- return NULL;
- }
+ if (AsciiStrCmp (StringArray[Index], CharArrayBuffer->ArrayValue) != 0) {
+ break;
+ }

- if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not numeric type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
- return NULL;
+ Index++;
+ CharArrayBuffer = CharArrayBuffer->Next;
}

- ResultValue = AllocatePool (sizeof (INT64));
- ASSERT (ResultValue != NULL);
- if (ResultValue == NULL) {
- return NULL;
+ if (CharArrayBuffer != NULL || Index < ArraySize) {
+ return FALSE;
}

- *ResultValue = RedfishValue.Value.Integer;
-
- return ResultValue;
+ return TRUE;
}

/**

- Get the property value in Boolean type.
+ Check and see if value in Redfish numeric array are all the same as the one
+ from HII configuration.

- @param[in] Schema Schema of this property.
- @param[in] Version Schema version.
- @param[in] PropertyName Property name.
- @param[in] ConfigureLang Configure Language of this property.
+ @param[in] Head The head of Redfish CS numeraic array.
+ @param[in] NumericArray Input numeric array.
+ @param[in] ArraySize The size of NumericArray.

- @retval BOOLEAN Boolean value returned by this property.
+ @retval TRUE All string in Redfish array are as same as integer
+ in HII configuration array.
+ FALSE These two array are not identical.

**/
-BOOLEAN *
-GetPropertyBooleanValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang
+BOOLEAN
+CompareRedfishNumericArrayValues (
+ IN RedfishCS_int64_Array *Head,
+ IN INT64 *NumericArray,
+ IN UINTN ArraySize
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
- EFI_STRING ConfigureLangBuffer;
- UINTN BufferSize;
- BOOLEAN *ResultValue;
-
- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
- return NULL;
- }
+ UINTN Index;
+ RedfishCS_int64_Array *NumericArrayBuffer;

- //
- // Configure Language buffer.
- //
- BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
- ConfigureLangBuffer = AllocatePool (BufferSize);
- if (ConfigureLangBuffer == NULL) {
- return NULL;
+ if (Head == NULL || NumericArray == NULL || ArraySize == 0) {
+ return FALSE;
}

- UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
PropertyName);
- Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangBuffer, &RedfishValue);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangBuffer, Status));
- return NULL;
- }
+ NumericArrayBuffer = Head;
+ Index = 0;
+ while (NumericArrayBuffer != NULL && Index < ArraySize) {
+ if (NumericArray[Index] != *NumericArrayBuffer->ArrayValue) {
+ break;
+ }

- if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not boolean type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
- return NULL;
+ Index++;
+ NumericArrayBuffer = NumericArrayBuffer->Next;
}

- ResultValue = AllocatePool (sizeof (BOOLEAN));
- ASSERT (ResultValue != NULL);
- if (ResultValue == NULL) {
- return NULL;
+ if (NumericArrayBuffer != NULL || Index < ArraySize) {
+ return FALSE;
}

- *ResultValue = RedfishValue.Value.Boolean;
-
- return ResultValue;
+ return TRUE;
}

/**

- Check and see if we need to do provisioning for this property.
+ Check and see if value in Redfish boolean array are all the same as the one
+ from HII configuration.

- @param[in] PropertyBuffer Pointer to property instance.
- @param[in] ProvisionMode TRUE if we are in provision mode. FALSE
otherwise.
+ @param[in] Head The head of Redfish CS boolean array.
+ @param[in] BooleanArray Input boolean array.
+ @param[in] ArraySize The size of BooleanArray.

- @retval TRUE Provision is required.
- @retval FALSE Provision is not required.
+ @retval TRUE All string in Redfish array are as same as integer
+ in HII configuration array.
+ FALSE These two array are not identical.

**/
BOOLEAN
-PropertyChecker (
- IN VOID *PropertyBuffer,
- IN BOOLEAN ProvisionMode
+CompareRedfishBooleanArrayValues (
+ IN RedfishCS_bool_Array *Head,
+ IN BOOLEAN *BooleanArray,
+ IN UINTN ArraySize
)
{
- if (ProvisionMode && PropertyBuffer == NULL) {
- return TRUE;
+ UINTN Index;
+ RedfishCS_bool_Array *BooleanArrayBuffer;
+
+ if (Head == NULL || BooleanArray == NULL || ArraySize == 0) {
+ return FALSE;
}

- if (!ProvisionMode && PropertyBuffer != NULL) {
- return TRUE;
+ BooleanArrayBuffer = Head;
+ Index = 0;
+ while (BooleanArrayBuffer != NULL && Index < ArraySize) {
+ if (BooleanArray[Index] != *BooleanArrayBuffer->ArrayValue) {
+ break;
+ }
+
+ Index++;
+ BooleanArrayBuffer = BooleanArrayBuffer->Next;
}

- return FALSE;
+ if (BooleanArrayBuffer != NULL || Index < ArraySize) {
+ return FALSE;
+ }
+
+ return TRUE;
}

/**

- Check and see if we need to do provisioning for this two properties.
+ Check and see if any difference between two vague value set.
+ This is just a simple check.

- @param[in] PropertyBuffer1 Pointer to property instance 1.
- @param[in] PropertyBuffer2 Pointer to property instance 2.
- @param[in] ProvisionMode TRUE if we are in provision mode. FALSE
otherwise.
+ @param[in] RedfishVagueKeyValuePtr The vague key value sets on
Redfish service.
+ @param[in] RedfishVagueKeyValueNumber The numebr of vague key
value sets
+ @param[in] ConfigVagueKeyValuePtr The vague configuration on
platform.
+ @param[in] ConfigVagueKeyValueNumber The numebr of vague key
value sets

- @retval TRUE Provision is required.
- @retval FALSE Provision is not required.
+ @retval TRUE All values are the same.
+ FALSE There is some difference.

**/
BOOLEAN
-PropertyChecker2Parm (
- IN VOID *PropertyBuffer1,
- IN VOID *PropertyBuffer2,
- IN BOOLEAN ProvisionMode
+CompareRedfishPropertyVagueValues (
+ IN RedfishCS_EmptyProp_KeyValue *RedfishVagueKeyValuePtr,
+ IN UINT32 RedfishVagueKeyValueNumber,
+ IN RedfishCS_EmptyProp_KeyValue *ConfigVagueKeyValuePtr,
+ IN UINT32 ConfigVagueKeyValueNumber
)
-{
- if (ProvisionMode && (PropertyBuffer1 == NULL || PropertyBuffer2 ==
NULL)) {
- return TRUE;
- }
+ {
+ RedfishCS_EmptyProp_KeyValue *ThisConfigVagueKeyValuePtr;
+ RedfishCS_EmptyProp_KeyValue *ThisRedfishVagueKeyValuePtr;

- if (!ProvisionMode && PropertyBuffer1 != NULL && PropertyBuffer2 !=
NULL) {
- return TRUE;
+ if (RedfishVagueKeyValueNumber != ConfigVagueKeyValueNumber) {
+ return FALSE;
}

- return FALSE;
+ ThisConfigVagueKeyValuePtr = ConfigVagueKeyValuePtr;
+ //
+ // Loop through all key/value on system.
+ //
+ while (ThisConfigVagueKeyValuePtr != NULL) {
+ ThisRedfishVagueKeyValuePtr = RedfishVagueKeyValuePtr;
+ //
+ // Loop through all key/value on Redfish service..
+ //
+ while (ThisRedfishVagueKeyValuePtr != NULL) {
+ if (AsciiStrCmp(ThisConfigVagueKeyValuePtr->KeyNamePtr,
ThisRedfishVagueKeyValuePtr->KeyNamePtr) == 0) {
+ //
+ // Check the type of value.
+ //
+ if (ThisConfigVagueKeyValuePtr->Value->DataType !=
ThisRedfishVagueKeyValuePtr->Value->DataType) {
+ return FALSE;
+ }
+ //
+ // Check the value.
+ //
+ if (ThisConfigVagueKeyValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_String) {
+ //
+ // Is the string identical?
+ //
+ if (AsciiStrCmp (ThisConfigVagueKeyValuePtr->Value-
DataValue.CharPtr,
+ ThisRedfishVagueKeyValuePtr->Value->DataValue.CharPtr
+ ) == 0) {
+ break;
+ } else{
+ return FALSE;
+ }
+ } else if (ThisConfigVagueKeyValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_Int64) {
+ if (*ThisConfigVagueKeyValuePtr->Value->DataValue.Int64Ptr ==
*ThisRedfishVagueKeyValuePtr->Value->DataValue.Int64Ptr) {
+ break;
+ } else {
+ return FALSE;
+ }
+ } else if (ThisConfigVagueKeyValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_Bool) {
+ if ((UINT8)*ThisConfigVagueKeyValuePtr->Value->DataValue.BoolPtr
== (UINT8)*ThisRedfishVagueKeyValuePtr->Value->DataValue.BoolPtr) {
+ break;
+ } else {
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+ }
+ ThisRedfishVagueKeyValuePtr = ThisRedfishVagueKeyValuePtr-
NextKeyValuePtr;
+ };
+ if (ThisRedfishVagueKeyValuePtr == NULL) {
+ //
+ // No matched key name. Threat these two vague value set is different.
+ //
+ return FALSE;
+ }
+ ThisConfigVagueKeyValuePtr = ThisConfigVagueKeyValuePtr-
NextKeyValuePtr;
+ };
+ return TRUE;
}

/**
diff --git
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.inf
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.inf
index f9f283fdcc..84f338e680 100644
---
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.inf
+++
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.inf
@@ -1,6 +1,6 @@
## @file
#
-# (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+# (C) Copyright 2020-2022 Hewlett Packard Enterprise Development
LP<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -27,6 +27,7 @@
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
RedfishPkg/RedfishPkg.dec
RedfishClientPkg/RedfishClientPkg.dec

@@ -35,16 +36,25 @@
BaseMemoryLib
DebugLib
MemoryAllocationLib
- PrintLib
RedfishLib
RedfishPlatformConfigLib
UefiLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
+ PrintLib
+ HttpLib

[Protocols]
- gEdkIIRedfishETagProtocolGuid ## CONSUMED ##
+ gEdkIIRedfishETagProtocolGuid ## CONSUMED ##
+ gEdkIIRedfishConfigLangMapProtocolGuid ## CONSUMED ##

[Pcd]
- gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaStringSize
- gEfiRedfishClientPkgTokenSpaceGuid.PcdMaxRedfishSchemaVersionSize
+
+[Guids]
+
+[BuildOptions]
+ #
+ # NOTE: /wd4706 disables the following Visual Studio compiler warning in
Jansson:
+ # "C4706: assignment within conditional expression"
+ #
+ MSFT:*_*_*_CC_FLAGS = /wd4706
--
2.32.0.windows.2


Re: [edk2-staging][PATCH v3 09/15] edk2-staging/RedfishClientPkg: Update RedfishLib

Chang, Abner
 

[AMD Official Use Only - General]

Reviewed-by: Abner Chang <abner.chang@...>

-----Original Message-----
From: Nickle Wang <nickle.wang@...>
Sent: Wednesday, July 27, 2022 9:38 AM
To: devel@edk2.groups.io
Cc: Chang, Abner <Abner.Chang@...>; Yang, Atom
<Atom.Yang@...>; Nick Ramirez <nramirez@...>
Subject: [edk2-staging][PATCH v3 09/15] edk2-staging/RedfishClientPkg:
Update RedfishLib

[CAUTION: External Email]

RedfishLib has no capability to return HTTP header in response.
However, feature driver needs to know the information like "ETag" or
"Location" in HTTP response header per Redfish specification. Add
corresponding function to return HTTP header in response data.

Signed-off-by: Nickle Wang <nickle.wang@...>
Cc: Abner Chang <abner.chang@...>
Cc: Yang Atom <Atom.Yang@...>
Cc: Nick Ramirez <nramirez@...>
---
.../PrivateLibrary/RedfishLib/RedfishLib.c | 12 +-
.../edk2libredfish/include/redfishPayload.h | 5 +-
.../edk2libredfish/include/redfishService.h | 5 +-
.../RedfishLib/edk2libredfish/src/payload.c | 90 ++-
.../RedfishLib/edk2libredfish/src/service.c | 554 +++++++++++++++++-
5 files changed, 657 insertions(+), 9 deletions(-)

diff --git a/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c
b/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c
index 18aa4646e8..b8ca493e24 100644
--- a/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c
+++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/RedfishLib.c
@@ -3,7 +3,7 @@
(CRUD) Redfish resources and provide basic query.

Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
- (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -323,7 +323,7 @@ RedfishGetByUri (

ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));

- JsonValue = getUriFromService (RedfishService, Uri, &RedResponse-
StatusCode);
+ JsonValue = getUriFromServiceEx (RedfishService, Uri,
+ &RedResponse->Headers, &RedResponse->HeaderCount,
+ &RedResponse->StatusCode);
RedResponse->Payload = createRedfishPayload(JsonValue, RedfishService);

//
@@ -541,9 +541,11 @@ RedfishPatchToPayload (

ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));

- RedResponse->Payload = (REDFISH_PAYLOAD) patchPayload (
+ RedResponse->Payload = (REDFISH_PAYLOAD) patchPayloadEx (
Target,
Payload,
+ &RedResponse->Headers,
+ &RedResponse->HeaderCount,
&(RedResponse->StatusCode)
);

@@ -607,9 +609,11 @@ RedfishPostToPayload (

ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));

- RedResponse->Payload = (REDFISH_PAYLOAD) postPayload (
+ RedResponse->Payload = (REDFISH_PAYLOAD) postPayloadEx (
Target,
Payload,
+ &RedResponse->Headers,
+ &RedResponse->HeaderCount,
&(RedResponse->StatusCode)
);

diff --git
a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish
Payload.h
b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish
Payload.h
index 43149f3c89..be74c64297 100644
---
a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish
Payload.h
+++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/
+++ redfishPayload.h
@@ -9,7 +9,7 @@
//----------------------------------------------------------------------------

Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
- (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -29,8 +29,11 @@ redfishPayload* getPayloadByIndex(redfishPayload*
payload, size_t index, EFI_HTT
redfishPayload* getPayloadForPath(redfishPayload* payload,
redPathNode* redpath, EFI_HTTP_STATUS_CODE** StatusCode);
redfishPayload* getPayloadForPathString(redfishPayload* payload, const
char* string, EFI_HTTP_STATUS_CODE** StatusCode);
redfishPayload* patchPayload(redfishPayload* target, redfishPayload*
payload, EFI_HTTP_STATUS_CODE** StatusCode);
+redfishPayload* patchPayloadEx(redfishPayload* target, redfishPayload*
+payload, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount,
+EFI_HTTP_STATUS_CODE** StatusCode);
redfishPayload* postContentToPayload(redfishPayload* target, const char*
data, size_t dataSize, const char* contentType, EFI_HTTP_STATUS_CODE**
StatusCode);
+redfishPayload* postContentToPayloadEx(redfishPayload* target, const
+char* data, size_t dataSize, const char* contentType, EFI_HTTP_HEADER
+**Headers, UINTN *HeaderCount, EFI_HTTP_STATUS_CODE**
StatusCode);
redfishPayload* postPayload(redfishPayload* target, redfishPayload*
payload, EFI_HTTP_STATUS_CODE** StatusCode);
+redfishPayload* postPayloadEx(redfishPayload* target, redfishPayload*
+payload, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount,
+EFI_HTTP_STATUS_CODE** StatusCode);
void cleanupPayload(redfishPayload* payload);
bool isPayloadCollection (redfishPayload *Payload);
size_t getCollectionSize(redfishPayload* payload);
diff --git
a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish
Service.h
b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish
Service.h
index 0215caccfc..3d87fad85a 100644
---
a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish
Service.h
+++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/
+++ redfishService.h
@@ -9,7 +9,7 @@
//----------------------------------------------------------------------------

Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
- (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -91,8 +91,11 @@ typedef struct {
#define REDFISH_FLAG_SERVICE_NO_VERSION_DOC 0x00000001 //The
Redfish Service lacks the version document (in violation of the Redfish spec)
redfishService*
createServiceEnumerator(REDFISH_CONFIG_SERVICE_INFORMATION
*RedfishConfigServiceInfo, const char* rootUri, enumeratorAuthentication*
auth, unsigned int flags);
json_t* getUriFromService(redfishService* service, const char* uri,
EFI_HTTP_STATUS_CODE** StatusCode);
+json_t* getUriFromServiceEx(redfishService* service, const char* uri,
+EFI_HTTP_HEADER **Headers, UINTN *HeaderCount,
EFI_HTTP_STATUS_CODE
+**StatusCode);
json_t* patchUriFromService(redfishService* service, const char* uri, const
char* content, EFI_HTTP_STATUS_CODE** StatusCode);
+json_t* patchUriFromServiceEx(redfishService* service, const char* uri,
+const char* content, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount,
+EFI_HTTP_STATUS_CODE** StatusCode);
json_t* postUriFromService(redfishService* service, const char* uri, const
char* content, size_t contentLength, const char* contentType,
EFI_HTTP_STATUS_CODE** StatusCode);
+json_t* postUriFromServiceEx(redfishService* service, const char* uri,
+const char* content, size_t contentLength, const char* contentType,
+EFI_HTTP_HEADER **Headers, UINTN *HeaderCount,
EFI_HTTP_STATUS_CODE**
+StatusCode);
json_t* deleteUriFromService(redfishService* service, const char* uri,
EFI_HTTP_STATUS_CODE** StatusCode);
redfishPayload* getRedfishServiceRoot(redfishService* service, const char*
version, EFI_HTTP_STATUS_CODE** StatusCode);
redfishPayload* getPayloadByPath(redfishService* service, const char* path,
EFI_HTTP_STATUS_CODE** StatusCode); diff --git
a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c
b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c
index bd8d143c4e..8b49bec0df 100644
---
a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c
+++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payl
+++ oad.c
@@ -9,7 +9,7 @@
//----------------------------------------------------------------------------

Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
- (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -326,6 +326,40 @@ redfishPayload*
getPayloadForPathString(redfishPayload* payload, const char* str
return ret;
}

+redfishPayload* patchPayloadEx(redfishPayload* target, redfishPayload*
+payload, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount,
+EFI_HTTP_STATUS_CODE** StatusCode) {
+ json_t* json;
+ char* content;
+ char* uri;
+
+ if(!target || !payload || StatusCode == NULL) {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ json = json_object_get(target->json, "@odata.id"); if(json == NULL)
+ {
+ return NULL;
+ }
+ uri = strdup(json_string_value(json));
+
+ content = json_dumps(payload->json, 0); json_decref(json);
+
+ json = patchUriFromServiceEx(target->service, uri, content, Headers,
+ HeaderCount, StatusCode); free(uri); free(content); if(json ==
+ NULL) {
+ return NULL;
+ }
+
+ return createRedfishPayload(json, target->service); }
+
redfishPayload* patchPayload(redfishPayload* target, redfishPayload*
payload, EFI_HTTP_STATUS_CODE** StatusCode) {
json_t* json;
@@ -360,6 +394,38 @@ redfishPayload* patchPayload(redfishPayload*
target, redfishPayload* payload, EF
return createRedfishPayload(json, target->service); }

+redfishPayload* postContentToPayloadEx(redfishPayload* target, const
+char* data, size_t dataSize, const char* contentType, EFI_HTTP_HEADER
**Headers, UINTN *HeaderCount, EFI_HTTP_STATUS_CODE** StatusCode)
{
+ json_t* json;
+ char* uri;
+
+ if(!target || !data || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ json = json_object_get(target->json, "@odata.id");
+ if(json == NULL)
+ {
+ json = json_object_get(target->json, "target");
+ if(json == NULL)
+ {
+ return NULL;
+ }
+ }
+ uri = strdup(json_string_value(json));
+ json = postUriFromServiceEx(target->service, uri, data, dataSize,
contentType, Headers, HeaderCount, StatusCode);
+ free(uri);
+ if(json == NULL)
+ {
+ return NULL;
+ }
+
+ return createRedfishPayload(json, target->service); }
+
redfishPayload* postContentToPayload(redfishPayload* target, const char*
data, size_t dataSize, const char* contentType, EFI_HTTP_STATUS_CODE**
StatusCode) {
json_t* json;
@@ -392,6 +458,28 @@ redfishPayload*
postContentToPayload(redfishPayload* target, const char* data, s
return createRedfishPayload(json, target->service); }

+redfishPayload* postPayloadEx(redfishPayload* target, redfishPayload*
+payload, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount,
EFI_HTTP_STATUS_CODE** StatusCode) {
+ char* content;
+ redfishPayload* ret;
+
+ if(!target || !payload || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ if(!json_is_object(payload->json))
+ {
+ return NULL;
+ }
+ content = payloadToString(payload, false);
+ ret = postContentToPayloadEx(target, content, strlen(content), NULL,
Headers, HeaderCount, StatusCode);
+ free(content);
+ return ret;
+}
+
redfishPayload* postPayload(redfishPayload* target, redfishPayload*
payload, EFI_HTTP_STATUS_CODE** StatusCode) {
char* content;
diff --git
a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c
b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c
index 7713f89e6d..450fa78bbd 100644
--- a/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c
+++ b/RedfishClientPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/serv
+++ ice.c
@@ -9,7 +9,7 @@
//----------------------------------------------------------------------------

Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
- (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -338,6 +338,190 @@ ON_EXIT:
return ret;
}

+EFI_HTTP_HEADER *cloneHttpHeaders(EFI_HTTP_MESSAGE *message,
UINTN
+*HeaderCount) {
+ EFI_HTTP_HEADER *Buffer;
+ UINTN Index;
+
+ if (message == NULL || HeaderCount == NULL) {
+ return NULL;
+ }
+
+ *HeaderCount = message->HeaderCount;
+ Buffer = AllocatePool (sizeof (EFI_HTTP_HEADER) *
+ message->HeaderCount); if (Buffer == NULL) {
+ return NULL;
+ }
+
+ for (Index = 0; Index < message->HeaderCount; Index++) {
+ Buffer[Index].FieldName = AllocateCopyPool (AsciiStrSize (message-
Headers[Index].FieldName), message->Headers[Index].FieldName);
+ ASSERT (Buffer[Index].FieldName != NULL);
+ Buffer[Index].FieldValue = AllocateCopyPool (AsciiStrSize (message-
Headers[Index].FieldValue), message->Headers[Index].FieldValue);
+ ASSERT (Buffer[Index].FieldValue != NULL); }
+
+ return Buffer;
+}
+
+json_t* getUriFromServiceEx(redfishService* service, const char* uri,
+EFI_HTTP_HEADER **Headers, UINTN *HeaderCount,
EFI_HTTP_STATUS_CODE
+**StatusCode) {
+ char* url;
+ json_t* ret;
+ HTTP_IO_HEADER *HttpIoHeader = NULL;
+ EFI_STATUS Status;
+ EFI_HTTP_REQUEST_DATA *RequestData = NULL;
+ EFI_HTTP_MESSAGE *RequestMsg = NULL;
+ EFI_HTTP_MESSAGE ResponseMsg;
+ EFI_HTTP_HEADER *ContentEncodedHeader;
+
+ if(service == NULL || uri == NULL || Headers == NULL || HeaderCount
+ == NULL ||StatusCode == NULL) {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+ *HeaderCount = 0;
+ *Headers = NULL;
+
+ url = makeUrlForService(service, uri);
+ if(!url)
+ {
+ return NULL;
+ }
+
+ DEBUG((DEBUG_INFO, "libredfish: getUriFromServiceEx(): %a\n", url));
+
+ //
+ // Step 1: Create HTTP request message with 4 headers:
+ //
+ HttpIoHeader = HttpIoCreateHeader ((service->sessionToken ||
+ service->basicAuthStr) ? 6 : 5); if (HttpIoHeader == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ if(service->sessionToken)
+ {
+ Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service-
sessionToken);
+ ASSERT_EFI_ERROR (Status);
+ } else if (service->basicAuthStr) {
+ Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service-
basicAuthStr);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = HttpIoSetHeader (HttpIoHeader, "Host",
+ service->HostHeaderValue); ASSERT_EFI_ERROR (Status); Status =
+ HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");
+ ASSERT_EFI_ERROR (Status); Status = HttpIoSetHeader (HttpIoHeader,
+ "Accept", "application/json"); ASSERT_EFI_ERROR (Status); Status =
+ HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");
+ ASSERT_EFI_ERROR (Status); Status = HttpIoSetHeader (HttpIoHeader,
+ "Connection", "Keep-Alive"); ASSERT_EFI_ERROR (Status);
+
+ //
+ // Step 2: build the rest of HTTP request info.
+ //
+ RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA)); if
+ (RequestData == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ RequestData->Method = HttpMethodGet;
+ RequestData->Url = C8ToC16 (url);
+
+ //
+ // Step 3: fill in EFI_HTTP_MESSAGE
+ //
+ RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE)); if
+ (RequestMsg == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ RequestMsg->Data.Request = RequestData; RequestMsg->HeaderCount
=
+ HttpIoHeader->HeaderCount;
+ RequestMsg->Headers = HttpIoHeader->Headers;
+
+ ZeroMem (&ResponseMsg, sizeof (ResponseMsg));
+
+ //
+ // Step 4: call RESTEx to get response from REST service.
+ //
+ Status = service->RestEx->SendReceive (service->RestEx, RequestMsg,
+ &ResponseMsg); if (EFI_ERROR (Status)) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ //
+ // Step 5: Return the HTTP StatusCode and Body message.
+ //
+ if (ResponseMsg.Data.Response != NULL) {
+ *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
+ if (*StatusCode == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ //
+ // The caller shall take the responsibility to free the buffer.
+ //
+ **StatusCode = ResponseMsg.Data.Response->StatusCode;
+ }
+
+ if (ResponseMsg.Headers != NULL) {
+ *Headers = cloneHttpHeaders (&ResponseMsg, HeaderCount); }
+
+ if (ResponseMsg.BodyLength != 0 && ResponseMsg.Body != NULL) {
+ //
+ // Check if data is encoded.
+ //
+ ContentEncodedHeader = HttpFindHeader (ResponseMsg.HeaderCount,
ResponseMsg.Headers, HTTP_HEADER_CONTENT_ENCODING);
+ if (ContentEncodedHeader != NULL) {
+ //
+ // The content is encoded.
+ //
+ Status = DecodeResponseContent (ContentEncodedHeader->FieldValue,
&ResponseMsg.Body, &ResponseMsg.BodyLength);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to decompress the response
content %r\n.", __FUNCTION__, Status));
+ ret = NULL;
+ goto ON_EXIT;
+ }
+ }
+ ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0,
+ NULL); } else {
+ //
+ // There is no message body returned from server.
+ //
+ ret = NULL;
+ }
+
+ON_EXIT:
+ if (url != NULL) {
+ free (url);
+ }
+
+ if (HttpIoHeader != NULL) {
+ HttpIoFreeHeader (HttpIoHeader);
+ }
+
+ if (RequestData != NULL) {
+ RestConfigFreeHttpRequestData (RequestData); }
+
+ if (RequestMsg != NULL) {
+ FreePool (RequestMsg);
+ }
+
+ RestConfigFreeHttpMessage (&ResponseMsg, FALSE);
+
+ return ret;
+}
+
json_t* getUriFromService(redfishService* service, const char* uri,
EFI_HTTP_STATUS_CODE** StatusCode) {
char* url;
@@ -491,7 +675,7 @@ ON_EXIT:
return ret;
}

-json_t* patchUriFromService(redfishService* service, const char* uri, const
char* content, EFI_HTTP_STATUS_CODE** StatusCode)
+json_t* patchUriFromServiceEx(redfishService* service, const char* uri,
+const char* content, EFI_HTTP_HEADER **Headers, UINTN *HeaderCount,
+EFI_HTTP_STATUS_CODE** StatusCode)
{
char* url;
json_t* ret;
@@ -632,6 +816,10 @@ json_t* patchUriFromService(redfishService*
service, const char* uri, const char
**StatusCode = ResponseMsg.Data.Response->StatusCode;
}

+ if (ResponseMsg.Headers != NULL) {
+ *Headers = cloneHttpHeaders (&ResponseMsg, HeaderCount); }
+
if (EncodedContent != content) {
FreePool (EncodedContent);
}
@@ -668,6 +856,368 @@ ON_EXIT:
return ret;
}

+json_t* patchUriFromService(redfishService* service, const char* uri,
+const char* content, EFI_HTTP_STATUS_CODE** StatusCode) {
+ char* url;
+ json_t* ret;
+ HTTP_IO_HEADER *HttpIoHeader = NULL;
+ EFI_STATUS Status;
+ EFI_HTTP_REQUEST_DATA *RequestData = NULL;
+ EFI_HTTP_MESSAGE *RequestMsg = NULL;
+ EFI_HTTP_MESSAGE ResponseMsg;
+ CHAR8 ContentLengthStr[80];
+ CHAR8 *EncodedContent;
+ UINTN EncodedContentLen;
+
+ if(service == NULL || uri == NULL || content == NULL || StatusCode ==
+ NULL) {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ url = makeUrlForService(service, uri);
+ if(!url)
+ {
+ return NULL;
+ }
+
+ DEBUG((DEBUG_INFO, "libredfish: patchUriFromService(): %a\n", url));
+
+ //
+ // Step 1: Create HTTP request message with 4 headers:
+ //
+ HttpIoHeader = HttpIoCreateHeader ((service->sessionToken ||
+ service->basicAuthStr) ? 9 : 8); if (HttpIoHeader == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ if(service->sessionToken)
+ {
+ Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service-
sessionToken);
+ ASSERT_EFI_ERROR (Status);
+ } else if (service->basicAuthStr) {
+ Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service-
basicAuthStr);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = HttpIoSetHeader (HttpIoHeader, "Host",
+ service->HostHeaderValue); ASSERT_EFI_ERROR (Status); Status =
+ HttpIoSetHeader (HttpIoHeader, "Content-Type", "application/json");
+ ASSERT_EFI_ERROR (Status); Status = HttpIoSetHeader (HttpIoHeader,
+ "Accept", "application/json"); ASSERT_EFI_ERROR (Status); Status =
+ HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");
+ ASSERT_EFI_ERROR (Status); Status = HttpIoSetHeader (HttpIoHeader,
+ "Connection", "Keep-Alive"); ASSERT_EFI_ERROR (Status);
+
+ AsciiSPrint(
+ ContentLengthStr,
+ sizeof (ContentLengthStr),
+ "%lu",
+ (UINT64) strlen(content)
+ );
+ Status = HttpIoSetHeader (HttpIoHeader, "Content-Length",
+ ContentLengthStr); ASSERT_EFI_ERROR (Status); Status =
+ HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Step 2: build the rest of HTTP request info.
+ //
+ RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA)); if
+ (RequestData == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ RequestData->Method = HttpMethodPatch; RequestData->Url = C8ToC16
+ (url);
+
+ //
+ // Step 3: fill in EFI_HTTP_MESSAGE
+ //
+ RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE)); if
+ (RequestMsg == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ EncodedContent = (CHAR8 *)content;
+ EncodedContentLen = strlen(content);
+ //
+ // We currently only support gzip Content-Encoding.
+ //
+ Status = EncodeRequestContent ((CHAR8
*)HTTP_CONTENT_ENCODING_GZIP,
+ (CHAR8 *)content, (VOID **)&EncodedContent, &EncodedContentLen); if
(Status == EFI_INVALID_PARAMETER) {
+ DEBUG((DEBUG_ERROR, "%a: Error to encode content.\n",
__FUNCTION__));
+ ret = NULL;
+ goto ON_EXIT;
+ } else if (Status == EFI_UNSUPPORTED) {
+ DEBUG((DEBUG_INFO, "No content coding for %a! Use raw data
instead.\n", HTTP_CONTENT_ENCODING_GZIP));
+ Status = HttpIoSetHeader (HttpIoHeader, "Content-Encoding",
HTTP_CONTENT_ENCODING_IDENTITY);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ Status = HttpIoSetHeader (HttpIoHeader, "Content-Encoding",
HTTP_CONTENT_ENCODING_GZIP);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ RequestMsg->Data.Request = RequestData; RequestMsg->HeaderCount
=
+ HttpIoHeader->HeaderCount;
+ RequestMsg->Headers = HttpIoHeader->Headers;
+ RequestMsg->BodyLength = EncodedContentLen;
+ RequestMsg->Body = (VOID*) EncodedContent;
+
+ ZeroMem (&ResponseMsg, sizeof (ResponseMsg));
+
+ //
+ // Step 4: call RESTEx to get response from REST service.
+ //
+ Status = service->RestEx->SendReceive (service->RestEx, RequestMsg,
+ &ResponseMsg); if (EFI_ERROR (Status)) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ //
+ // Step 5: Return the HTTP StatusCode and Body message.
+ //
+ if (ResponseMsg.Data.Response != NULL) {
+ *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
+ if (*StatusCode == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ //
+ // The caller shall take the responsibility to free the buffer.
+ //
+ **StatusCode = ResponseMsg.Data.Response->StatusCode;
+ }
+
+ if (EncodedContent != content) {
+ FreePool (EncodedContent);
+ }
+
+
+ if (ResponseMsg.BodyLength != 0 && ResponseMsg.Body != NULL) {
+ ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0,
+ NULL); } else {
+ //
+ // There is no message body returned from server.
+ //
+ ret = NULL;
+ }
+
+ON_EXIT:
+ if (url != NULL) {
+ free (url);
+ }
+
+ if (HttpIoHeader != NULL) {
+ HttpIoFreeHeader (HttpIoHeader);
+ }
+
+ if (RequestData != NULL) {
+ RestConfigFreeHttpRequestData (RequestData); }
+
+ if (RequestMsg != NULL) {
+ FreePool (RequestMsg);
+ }
+
+ RestConfigFreeHttpMessage (&ResponseMsg, FALSE);
+
+ return ret;
+}
+
+json_t* postUriFromServiceEx(redfishService* service, const char* uri,
+const char* content, size_t contentLength, const char* contentType,
EFI_HTTP_HEADER **Headers, UINTN *HeaderCount,
EFI_HTTP_STATUS_CODE** StatusCode) {
+ char* url = NULL;
+ json_t* ret;
+ HTTP_IO_HEADER *HttpIoHeader = NULL;
+ EFI_STATUS Status;
+ EFI_HTTP_REQUEST_DATA *RequestData = NULL;
+ EFI_HTTP_MESSAGE *RequestMsg = NULL;
+ EFI_HTTP_MESSAGE ResponseMsg;
+ CHAR8 ContentLengthStr[80];
+ EFI_HTTP_HEADER *HttpHeader = NULL;
+
+ ret = NULL;
+
+ if(service == NULL || uri == NULL || content == NULL || StatusCode ==
+ NULL) {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ url = makeUrlForService(service, uri);
+ if(!url)
+ {
+ return NULL;
+ }
+
+ DEBUG((DEBUG_INFO, "libredfish: postUriFromService(): %a\n", url));
+
+ if(contentLength == 0)
+ {
+ contentLength = strlen(content);
+ }
+
+ //
+ // Step 1: Create HTTP request message with 4 headers:
+ //
+ HttpIoHeader = HttpIoCreateHeader ((service->sessionToken ||
+ service->basicAuthStr) ? 8 : 7); if (HttpIoHeader == NULL) {
+ goto ON_EXIT;
+ }
+
+ if(service->sessionToken)
+ {
+ Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service-
sessionToken);
+ ASSERT_EFI_ERROR (Status);
+ } else if (service->basicAuthStr) {
+ Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service-
basicAuthStr);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if(contentType == NULL) {
+ Status = HttpIoSetHeader (HttpIoHeader, "Content-Type",
"application/json");
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ Status = HttpIoSetHeader (HttpIoHeader, "Content-Type", (CHAR8 *)
contentType);
+ ASSERT_EFI_ERROR (Status);
+ }
+ Status = HttpIoSetHeader (HttpIoHeader, "Host",
+ service->HostHeaderValue); ASSERT_EFI_ERROR (Status); Status =
+ HttpIoSetHeader (HttpIoHeader, "Accept", "application/json");
+ ASSERT_EFI_ERROR (Status); Status = HttpIoSetHeader (HttpIoHeader,
+ "User-Agent", "libredfish"); ASSERT_EFI_ERROR (Status); Status =
+ HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");
+ ASSERT_EFI_ERROR (Status); AsciiSPrint(
+ ContentLengthStr,
+ sizeof (ContentLengthStr),
+ "%lu",
+ (UINT64) contentLength
+ );
+ Status = HttpIoSetHeader (HttpIoHeader, "Content-Length",
+ ContentLengthStr); ASSERT_EFI_ERROR (Status); Status =
+ HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Step 2: build the rest of HTTP request info.
+ //
+ RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA)); if
+ (RequestData == NULL) {
+ goto ON_EXIT;
+ }
+
+ RequestData->Method = HttpMethodPost; RequestData->Url = C8ToC16
+ (url);
+
+ //
+ // Step 3: fill in EFI_HTTP_MESSAGE
+ //
+ RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE)); if
+ (RequestMsg == NULL) {
+ goto ON_EXIT;
+ }
+
+ RequestMsg->Data.Request = RequestData; RequestMsg->HeaderCount
=
+ HttpIoHeader->HeaderCount;
+ RequestMsg->Headers = HttpIoHeader->Headers;
+ RequestMsg->BodyLength = contentLength;
+ RequestMsg->Body = (VOID*) content;
+
+ ZeroMem (&ResponseMsg, sizeof (ResponseMsg));
+
+ //
+ // Step 4: call RESTEx to get response from REST service.
+ //
+ Status = service->RestEx->SendReceive (service->RestEx, RequestMsg,
+ &ResponseMsg); if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ //
+ // Step 5: Return the HTTP StatusCode and Body message.
+ //
+ if (ResponseMsg.Data.Response != NULL) {
+ *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
+ if (*StatusCode == NULL) {
+ goto ON_EXIT;
+ }
+
+ //
+ // The caller shall take the responsibility to free the buffer.
+ //
+ **StatusCode = ResponseMsg.Data.Response->StatusCode;
+ }
+
+ if (ResponseMsg.Headers != NULL) {
+ *Headers = cloneHttpHeaders (&ResponseMsg, HeaderCount); }
+
+ if (ResponseMsg.BodyLength != 0 && ResponseMsg.Body != NULL) {
+ ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0,
+ NULL); }
+
+ //
+ // Step 6: Parsing the HttpHeader to retrive the X-Auth-Token if the HTTP
StatusCode is correct.
+ //
+ if (ResponseMsg.Data.Response->StatusCode == HTTP_STATUS_200_OK
||
+ ResponseMsg.Data.Response->StatusCode ==
HTTP_STATUS_204_NO_CONTENT) {
+ HttpHeader = HttpFindHeader (ResponseMsg.HeaderCount,
ResponseMsg.Headers, "X-Auth-Token");
+ if (HttpHeader != NULL) {
+ if(service->sessionToken)
+ {
+ free(service->sessionToken);
+ }
+ service->sessionToken = AllocateCopyPool (AsciiStrSize (HttpHeader-
FieldValue), HttpHeader->FieldValue);
+ }
+
+ /*
+ //
+ // Below opeation seems to be unnecessary.
+ // Besides, the FieldValue for the Location is the full HTTP URI
(https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2F0.0.0
.0%3A5000%2FXXX&amp;data=05%7C01%7Cabner.chang%40amd.com%7C90
03fefe404646f2d91808da6f70b041%7C3dd8961fe4884e608e11a82d994e183d
%7C0%7C0%7C637944827040099707%7CUnknown%7CTWFpbGZsb3d8eyJWIj
oiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3
000%7C%7C%7C&amp;sdata=tSmhlKBno3bHdyIGn2N5ESjfCdp%2FYUEYC%2F
Kqj9azORg%3D&amp;reserved=0), so we can't use it as the
+ // parameter of getUriFromService () directly.
+ //
+ HttpHeader = HttpFindHeader (ResponseMsg.HeaderCount,
ResponseMsg.Headers, "Location");
+ if (HttpHeader != NULL) {
+ ret = getUriFromService(service, HttpHeader->FieldValue);
+ goto ON_EXIT;
+ }
+ */
+ }
+
+ON_EXIT:
+ if (url != NULL) {
+ free (url);
+ }
+
+ if (HttpIoHeader != NULL) {
+ HttpIoFreeHeader (HttpIoHeader);
+ }
+
+ if (RequestData != NULL) {
+ RestConfigFreeHttpRequestData (RequestData); }
+
+ if (RequestMsg != NULL) {
+ FreePool (RequestMsg);
+ }
+
+ RestConfigFreeHttpMessage (&ResponseMsg, FALSE);
+
+ return ret;
+}
+
json_t* postUriFromService(redfishService* service, const char* uri, const
char* content, size_t contentLength, const char* contentType,
EFI_HTTP_STATUS_CODE** StatusCode) {
char* url = NULL;
--
2.32.0.windows.2


Re: [edk2-staging][PATCH v3 08/15] edk2-staging/RedfishClientPkg: Update Redfish feature core driver

Chang, Abner
 

[AMD Official Use Only - General]

Reviewed-by: Abner Chang <abner.chang@...>

-----Original Message-----
From: Nickle Wang <nickle.wang@...>
Sent: Wednesday, July 27, 2022 9:38 AM
To: devel@edk2.groups.io
Cc: Chang, Abner <Abner.Chang@...>; Yang, Atom
<Atom.Yang@...>; Nick Ramirez <nramirez@...>
Subject: [edk2-staging][PATCH v3 08/15] edk2-staging/RedfishClientPkg:
Update Redfish feature core driver

[CAUTION: External Email]

Update Redfish feature core driver to support Redfish resource with multiple
parents. A resource may be presented in different resource and the link in
different resource point to the same location. Also add interchange data
interface in feature core driver so feature core driver can talk to feature
drivers directly.

Signed-off-by: Nickle Wang <nickle.wang@...>
Cc: Abner Chang <abner.chang@...>
Cc: Yang Atom <Atom.Yang@...>
Cc: Nick Ramirez <nramirez@...>
---
.../Include/Protocol/EdkIIRedfishFeature.h | 20 +-
.../RedfishFeatureCoreDxe.c | 290 ++++++++++++++++--
.../RedfishFeatureCoreDxe.h | 20 +-
.../RedfishFeatureCoreDxe.inf | 5 +-
4 files changed, 278 insertions(+), 57 deletions(-)

diff --git a/RedfishClientPkg/Include/Protocol/EdkIIRedfishFeature.h
b/RedfishClientPkg/Include/Protocol/EdkIIRedfishFeature.h
index 036622128d..26814c8786 100644
--- a/RedfishClientPkg/Include/Protocol/EdkIIRedfishFeature.h
+++ b/RedfishClientPkg/Include/Protocol/EdkIIRedfishFeature.h
@@ -1,7 +1,7 @@
/** @file
This file defines the EDKII_REDFISH_FEATURE_PROTOCOL interface.

- (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -10,6 +10,8 @@
#ifndef EDKII_REDFISH_FEATURE_H_
#define EDKII_REDFISH_FEATURE_H_

+#include <Protocol/EdkIIRedfishInterchangeData.h>
+
typedef struct _EDKII_REDFISH_FEATURE_PROTOCOL
EDKII_REDFISH_FEATURE_PROTOCOL;

#define EDKII_REDFISH_FEATURE_PROTOCOL_GUID \ @@ -23,25 +25,13
@@ typedef enum {
CallbackActionMax
} FEATURE_CALLBACK_ACTION;

-typedef enum {
- InformationTypeNone = 0, ///< Invalid information.
- InformationTypeCollectionMemberUri, ///< URI to the new created
collection member.
- InformationTypeMax
-} FEATURE_RETURNED_INFORMATION_TYPE;
-
-typedef struct {
- FEATURE_RETURNED_INFORMATION_TYPE Type; -}
FEATURE_RETURNED_INFORMATION;
-
/**
The callback function provided by Redfish Feature driver.

@param[in] This Pointer to EDKII_REDFISH_FEATURE_PROTOCOL
instance.
@param[in] FeatureAction The action Redfish feature driver should
take.
@param[in] Context The context of Redfish feature driver.
- @param[in,out] InformationReturned The pointer to retrive the pointer to
- FEATURE_RETURNED_INFOMATION. The memory block
of this
- information should be freed by caller.
+ @param[in,out] ExchangeInformation The pointer to
RESOURCE_INFORMATION_EXCHANGE.

@retval EFI_SUCCESS Redfish feature driver callback is executed
successfully.
@retval Others Some errors happened.
@@ -53,7 +43,7 @@ EFI_STATUS
IN EDKII_REDFISH_FEATURE_PROTOCOL *This,
IN FEATURE_CALLBACK_ACTION FeatureAction,
IN VOID *Context,
- IN OUT FEATURE_RETURNED_INFORMATION **InformationReturned
+ IN OUT RESOURCE_INFORMATION_EXCHANGE *ExchangeInformation
);
/**
The registration function for the Redfish Feature driver.
diff --git
a/RedfishClientPkg/RedfishFeatureCoreDxe/RedfishFeatureCoreDxe.c
b/RedfishClientPkg/RedfishFeatureCoreDxe/RedfishFeatureCoreDxe.c
index 49e1cd6b60..3414f0c942 100644
--- a/RedfishClientPkg/RedfishFeatureCoreDxe/RedfishFeatureCoreDxe.c
+++ b/RedfishClientPkg/RedfishFeatureCoreDxe/RedfishFeatureCoreDxe.c
@@ -2,7 +2,7 @@
RedfishFeatureCoreDxe produces EdkIIRedfishFeatureCoreProtocol
for EDK2 Redfish Feature driver registration.

- (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -13,38 +13,188 @@
EFI_EVENT mEdkIIRedfishFeatureDriverStartupEvent;
REDFISH_FEATURE_STARTUP_CONTEXT mFeatureDriverStartupContext;
REDFISH_FEATURE_INTERNAL_DATA *ResourceUriNodeList;
+RESOURCE_INFORMATION_EXCHANGE *mInformationExchange;
+
+/**
+ Setup the information to deliver to child feature/collection driver.
+
+ @param[in] ThisList REDFISH_FEATURE_INTERNAL_DATA instance.
+ @param[in] ParentConfgLanguageUri Parent configure language URI.
+
+**/
+EFI_STATUS
+SetupExchangeInformationInfo (
+ IN REDFISH_FEATURE_INTERNAL_DATA *ThisList,
+ IN EFI_STRING ParentConfgLanguageUri
+ )
+{
+ ThisList->InformationExchange->SendInformation.ParentUri =
+(EFI_STRING)AllocateZeroPool (MaxParentUriLength * sizeof (CHAR16));
+ if (ThisList->InformationExchange->SendInformation.ParentUri == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ThisList->InformationExchange->SendInformation.PropertyName =
+(EFI_STRING)AllocateZeroPool(MaxNodeNameLength * sizeof (CHAR16));
+ if (ThisList->InformationExchange->SendInformation.PropertyName ==
NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ThisList->InformationExchange->SendInformation.FullUri =
+(EFI_STRING)AllocateZeroPool(MaxParentUriLength * sizeof (CHAR16));
+ if (ThisList->InformationExchange->SendInformation.FullUri == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Setup property name
+ //
+ StrCpyS (ThisList->InformationExchange->SendInformation.PropertyName,
+ MaxNodeNameLength, ThisList->NodeName);
+
+ //
+ // Setup parent config language URI
+ //
+ StrCpyS (ThisList->InformationExchange->SendInformation.ParentUri,
+ MaxParentUriLength, ParentConfgLanguageUri);
+
+ //
+ // Full config language URI
+ //
+ StrCpyS (ThisList->InformationExchange->SendInformation.FullUri,
+ MaxParentUriLength,
+ ThisList->InformationExchange->SendInformation.ParentUri
+ );
+ if (StrLen (ThisList->InformationExchange->SendInformation.FullUri) != 0) {
+ StrCatS (ThisList->InformationExchange->SendInformation.FullUri,
+MaxParentUriLength, L"/");
+ }
+ StrCatS (ThisList->InformationExchange->SendInformation.FullUri,
+MaxParentUriLength,
+ThisList->InformationExchange->SendInformation.PropertyName);
+ return EFI_SUCCESS;
+}
+
+/**
+ Destroy the exchange information.
+
+ @param[in] ThisList REDFISH_FEATURE_INTERNAL_DATA instance.
+
+**/
+EFI_STATUS
+DestroryExchangeInformation (
+ IN REDFISH_FEATURE_INTERNAL_DATA *ThisList
+ )
+{
+
+ if (ThisList->InformationExchange != NULL) {
+ if (ThisList->InformationExchange->SendInformation.Type ==
InformationTypeCollectionMemberUri) {
+ if (ThisList->InformationExchange->SendInformation.ParentUri != NULL)
{
+ FreePool (ThisList->InformationExchange->SendInformation.ParentUri);
+ ThisList->InformationExchange->SendInformation.ParentUri = NULL;
+ }
+ if (ThisList->InformationExchange->SendInformation.PropertyName !=
NULL) {
+ FreePool (ThisList->InformationExchange-
SendInformation.PropertyName);
+ ThisList->InformationExchange->SendInformation.PropertyName =
NULL;
+ }
+ if (ThisList->InformationExchange->SendInformation.FullUri != NULL) {
+ FreePool (ThisList->InformationExchange->SendInformation.FullUri);
+ ThisList->InformationExchange->SendInformation.FullUri = NULL;
+ }
+ }
+
+ if (ThisList->InformationExchange->ReturnedInformation.Type ==
InformationTypeCollectionMemberConfigLanguage) {
+ DestroyConfiglanguageList (&ThisList->InformationExchange-
ReturnedInformation.ConfigureLanguageList);
+ }
+
+ ThisList->InformationExchange->SendInformation.Type =
InformationTypeNone;
+ ThisList->InformationExchange->ReturnedInformation.Type =
+ InformationTypeNone;
+
+ }
+ return EFI_SUCCESS;
+}

/**
Startup child feature drivers and it's sibing feature drivers.

- @param[in] ThisFeatureDriverList This feature driver list.
- @param[in] StartupContext Start up information
+ @param[in] ThisFeatureDriverList This feature driver list.
+ @param[in] CurrentConfigLanguageUri The current parent configure
language URI.
+ @param[in] StartupContext Start up information

**/
VOID
StartUpFeatureDriver (
IN REDFISH_FEATURE_INTERNAL_DATA *ThisFeatureDriverList,
+ IN EFI_STRING CurrentConfigLanguageUri,
IN REDFISH_FEATURE_STARTUP_CONTEXT *StartupContext
)
{
EFI_STATUS Status;
+ UINTN Index;
REDFISH_FEATURE_INTERNAL_DATA *ThisList;
+ REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST ConfigLangList;
+ EFI_STRING NextParentUri;
+
+ NextParentUri = (EFI_STRING)AllocateZeroPool (MaxParentUriLength *
+ sizeof (CHAR16)); if (NextParentUri == NULL) {
+ DEBUG((DEBUG_ERROR, "%a: Fail to allocate memory for parent
configure language.\n", __FUNCTION__));
+ return;
+ }
+ if (CurrentConfigLanguageUri != NULL) {
+ StrCpyS(NextParentUri, MaxParentUriLength,
+ CurrentConfigLanguageUri); }

ThisList = ThisFeatureDriverList;
while (TRUE) {
if (ThisList->Callback != NULL) {
- Status = ThisList->Callback(
- StartupContext->This,
- StartupContext->Action,
- ThisList->Context,
- &ThisList->ReturnedInformation
- );
+ ThisList->InformationExchange = mInformationExchange;
+ Status = SetupExchangeInformationInfo (ThisList, NextParentUri);
+ if (!EFI_ERROR (Status)) {
+ Status = ThisList->Callback(
+ StartupContext->This,
+ StartupContext->Action,
+ ThisList->Context,
+ ThisList->InformationExchange
+ );
+ }
if (EFI_ERROR (Status)) {
- DEBUG((DEBUG_ERROR, "%a: Callback to EDK2 Redfish feature driver
fail.", __FUNCTION__));
+ DEBUG((DEBUG_ERROR, "%a: Callback to EDK2 Redfish feature
+ driver fail: %s.\n", __FUNCTION__,
+ ThisList->InformationExchange->SendInformation.FullUri));
}
}
- if (ThisList->ChildList != NULL) {
- StartUpFeatureDriver (ThisList->ChildList, StartupContext);
+ if (!EFI_ERROR (Status) && ThisList->Callback != NULL && ThisList-
ChildList != NULL) {
+ //
+ // Go through child list only when the parent node is managed by
feature driver.
+ //
+ if (ThisList->Flags &
REDFISH_FEATURE_INTERNAL_DATA_IS_COLLECTION) {
+ //
+ // The collection driver's callback is invoked.
InformationTypeCollectionMemberConfigLanguage
+ // should be returned in RESOURCE_INFORMATION_RETURNED.
+ //
+ if (ThisList->InformationExchange->ReturnedInformation.Type ==
InformationTypeCollectionMemberConfigLanguage) {
+ //
+ // Copy RESOURCE_INFORMATION_RETURNED then destroy the
exchange information.
+ //
+ CopyConfiglanguageList (&ThisList->InformationExchange-
ReturnedInformation.ConfigureLanguageList, &ConfigLangList);
+ DestroryExchangeInformation(ThisList);
+ //
+ // Modify the collection instance according to the returned
InformationTypeCollectionMemberConfigLanguage.
+ //
+ for (Index = 0; Index < ConfigLangList.Count; Index ++) {
+ StrCatS (NextParentUri, MaxParentUriLength, ThisList->NodeName);
+ StrCatS (NextParentUri, MaxParentUriLength,
NodeIsCollectionSymbol);
+ SetResourceConfigLangMemberInstance (&NextParentUri,
MaxParentUriLength, (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
*)&ConfigLangList.List[Index]);
+ StartUpFeatureDriver(ThisList->ChildList, NextParentUri,
StartupContext);
+ }
+ DestroyConfiglanguageList (&ConfigLangList);
+ } else {
+ DEBUG((DEBUG_ERROR, "%a: No
InformationTypeCollectionMemberConfigLanguage of %s returned.\n",
__FUNCTION__, ThisList->InformationExchange->SendInformation.FullUri));
+ DEBUG((DEBUG_ERROR, "%a: Redfish service maybe not connected or
the network has problems.\n", __FUNCTION__));
+ return;
+ }
+ } else {
+ StrCatS (NextParentUri, MaxParentUriLength, ThisList->NodeName);
+ StartUpFeatureDriver(ThisList->ChildList, NextParentUri,
StartupContext);
+ }
+ //
+ // Restore the parent configure language URI for this level.
+ //
+ if (CurrentConfigLanguageUri != NULL) {
+ StrCpyS(NextParentUri, MaxParentUriLength,
CurrentConfigLanguageUri);
+ } else{
+ NextParentUri [0] = 0;
+ }
+ } else {
+ DestroryExchangeInformation (ThisList);
}
//
// Check sibling Redfish feature driver.
@@ -57,6 +207,10 @@ StartUpFeatureDriver (
//
ThisList = ThisList->SiblingList;
};
+ if (NextParentUri != NULL) {
+ FreePool (NextParentUri);
+ }
+
}

/**
@@ -85,10 +239,30 @@ RedfishFeatureDriverStartup(
if (ResourceUriNodeList == NULL) {
return;
}
+
+ //
+ // Initial dispatcher variables.
+ //
+ mInformationExchange = (RESOURCE_INFORMATION_EXCHANGE
+ *)AllocateZeroPool (sizeof (RESOURCE_INFORMATION_EXCHANGE)); if
(mInformationExchange == NULL) {
+ DEBUG((DEBUG_ERROR, "%a: Fail to allocate memory for exchange
information.\n", __FUNCTION__));
+ return;
+ }
+
+ //
+ // Signal event before doing provisioning //
+ SignalReadyToProvisioningEvent ();
+
//
// Invoke the callback by the hierarchy level
//
- StartUpFeatureDriver (ResourceUriNodeList, StartupContext);
+ StartUpFeatureDriver (ResourceUriNodeList, NULL, StartupContext);
+
+ //
+ // Signal event after provisioning finished //
+ SignalAfterProvisioningEvent ();
}

/**
@@ -97,6 +271,8 @@ RedfishFeatureDriverStartup(
@param[in,out] PtrToNewInternalData Pointer to receive new instance of
REDFISH_FEATURE_INTERNAL_DATA.
@param[in] NodeName Name of URI node.
+ @param[in] NodeIsCollection TRUE means the node to add is the
collection node.
+ Otherwise it is a resource node.

@retval EFI_SUCCESS New entry is inserted successfully.
@retval EFI_INVALID_PARAMETER Improper given parameters.
@@ -106,7 +282,8 @@ RedfishFeatureDriverStartup(
EFI_STATUS
NewInternalInstance (
IN OUT REDFISH_FEATURE_INTERNAL_DATA **PtrToNewInternalData,
- IN EFI_STRING NodeName
+ IN EFI_STRING NodeName,
+ IN BOOLEAN NodeIsCollection
)
{
REDFISH_FEATURE_INTERNAL_DATA *NewInternalData;
@@ -126,8 +303,7 @@ NewInternalInstance (
StrnCpyS (NewInternalData->NodeName, StrSize (NodeName), (CONST
CHAR16 *)NodeName, StrLen (NodeName));
NewInternalData->SiblingList = NULL;
NewInternalData->ChildList = NULL;
- if (NodeName[0] == (UINT16)NodeIsCollectionLeftBracket &&
- NodeName [StrLen (NodeName) - 1] ==
(UINT16)NodeIsCollectionRightBracket) {
+ if (NodeIsCollection) {
NewInternalData->Flags |=
REDFISH_FEATURE_INTERNAL_DATA_IS_COLLECTION;
}
*PtrToNewInternalData = NewInternalData;
@@ -138,11 +314,15 @@ NewInternalInstance (
Insert the URI node into internal data structure

@param[in] HeadEntryToInsert The head entry to start the searching.
+ @param[in] PrevisouEntry Previsou entry.
@param[in] NodeName Name of URI node.
+ @param[in] NodeIsCollection TRUE means the node to add is the
collection node.
+ Otherwise it is a resource node.
@param[in, out] NextNodeEntry Pointer to receive the pointer of next
head
entry for inserting the follow up nodes.
The returned LIST_ENTRY is the address of
ChildList link list.
+ @param[out] MatchNodeEntry The matched node entry.
@retval EFI_SUCCESS New entry is inserted successfully.
@retval EFI_INVALID_PARAMETER Improper given parameters.
@retval EFI_OUT_OF_RESOURCES Lack of memory for the internal data
structure.
@@ -151,8 +331,11 @@ NewInternalInstance (
EFI_STATUS
InsertRedfishFeatureUriNode (
IN REDFISH_FEATURE_INTERNAL_DATA *HeadEntryToInsert,
+ IN REDFISH_FEATURE_INTERNAL_DATA **PrevisouEntry,
IN EFI_STRING NodeName,
- IN OUT REDFISH_FEATURE_INTERNAL_DATA **NextNodeEntry
+ IN BOOLEAN NodeIsCollection,
+ IN OUT REDFISH_FEATURE_INTERNAL_DATA **NextNodeEntry,
+ OUT REDFISH_FEATURE_INTERNAL_DATA **MatchNodeEntry
)
{
EFI_STATUS Status;
@@ -160,6 +343,7 @@ InsertRedfishFeatureUriNode (
REDFISH_FEATURE_INTERNAL_DATA *ThisInternalData;
REDFISH_FEATURE_INTERNAL_DATA *SiblingList;

+ *MatchNodeEntry = NULL;
if (NodeName == NULL) {
DEBUG((DEBUG_ERROR, "%a: Node name is NULL.\n", __FUNCTION__));
return EFI_INVALID_PARAMETER;
@@ -169,17 +353,18 @@ InsertRedfishFeatureUriNode (
return EFI_INVALID_PARAMETER;
}

- if (HeadEntryToInsert == NULL || HeadEntryToInsert->ChildList == NULL) {
- Status = NewInternalInstance (&NewInternalData, NodeName);
+ if (HeadEntryToInsert == NULL) {
+ Status = NewInternalInstance (&NewInternalData, NodeName,
NodeIsCollection);
if (EFI_ERROR (Status)) {
return Status;
}
- if (HeadEntryToInsert == NULL) {
+ if (HeadEntryToInsert == NULL && ResourceUriNodeList == NULL) {
ResourceUriNodeList = NewInternalData;
} else {
- HeadEntryToInsert->ChildList = NewInternalData;
+ (*PrevisouEntry)->ChildList = NewInternalData;
}
- *NextNodeEntry = NewInternalData;
+ *PrevisouEntry = NewInternalData;
+ *NextNodeEntry = NewInternalData->ChildList;
return EFI_SUCCESS;<