summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/RedfishPkg
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/RedfishPkg')
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Documents/Media/RedfishDriverStack.svg965
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/IndustryStandard/RedfishHostInterface.h169
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/BaseUcs2Utf8Lib.h61
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/JsonLib.h800
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishContentCodingLib.h78
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishCredentialLib.h91
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishHostInterfaceLib.h52
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RestExLib.h42
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Pcd/RestExServiceDevicePath.h38
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishConfigHandler.h78
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishCredential.h101
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.c421
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf31
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.c166
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.inf44
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.c983
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.inf87
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/Readme.rst35
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_config.h41
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_private_config.h19
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/load.c1111
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.c101
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf30
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.c52
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf33
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.c81
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.inf31
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/assert.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/errno.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/limits.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/math.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdarg.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stddef.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdio.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdlib.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/string.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/time.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/types.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/time.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishCrtLib.h242
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishLib.h611
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c929
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf38
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.c993
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf60
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.c201
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.h82
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish.h24
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishPayload.h39
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h101
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redpath.h42
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c732
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/redpath.c192
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c1396
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Readme.md117
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.dsc.inc21
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.fdf.inc20
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishComponents.dsc.inc22
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.c265
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.h101
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.c587
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.h159
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf60
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.c209
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.h75
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf51
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDefines.dsc.inc27
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/ComponentName.c218
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c1910
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf55
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h234
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c118
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.c243
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf50
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishLibs.dsc.inc21
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.ci.yaml105
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dec100
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dsc62
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/ComponentName.c222
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c831
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h650
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf63
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni15
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c157
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h611
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c735
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.c586
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf39
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureInternal.h33
90 files changed, 20398 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Documents/Media/RedfishDriverStack.svg b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Documents/Media/RedfishDriverStack.svg
new file mode 100644
index 00000000..76269b78
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Documents/Media/RedfishDriverStack.svg
@@ -0,0 +1,965 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by Microsoft Visio, SVG Export RedfishDriverStack.svg Page-1 -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"
+ xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="14in" height="8.5in" viewBox="0 0 1008 612"
+ xml:space="preserve" color-interpolation-filters="sRGB" class="st63">
+ <title>EDKII Redfish Driver Stack Diagrams</title>
+ <v:documentProperties v:langID="1033" v:viewMarkup="false">
+ <v:userDefs>
+ <v:ud v:nameU="msvNoAutoConnect" v:val="VT0(1):26"/>
+ </v:userDefs>
+ </v:documentProperties>
+
+ <style type="text/css">
+ <![CDATA[
+ .st1 {fill:#ffffff;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st2 {stroke:#7f7f7f;stroke-linecap:round;stroke-linejoin:round;stroke-width:4.5}
+ .st3 {fill:#a5a5a5;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st4 {fill:#000000;font-family:Calibri;font-size:1.16666em;font-weight:bold}
+ .st5 {font-size:0.714294em}
+ .st6 {fill:#0070c0;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st7 {fill:#ffffff;font-family:Calibri;font-size:1.16666em;font-weight:bold}
+ .st8 {fill:#ffffff;font-family:Calibri;font-size:1.08334em;font-weight:bold}
+ .st9 {font-size:1em}
+ .st10 {font-size:0.769226em}
+ .st11 {fill:#339966;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st12 {fill:#ffffff;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st13 {fill:#ffffff;stroke:#0070c0;stroke-linecap:round;stroke-linejoin:round;stroke-width:3}
+ .st14 {fill:#000000;font-family:Calibri;font-size:0.833336em;font-weight:bold}
+ .st15 {marker-end:url(#mrkr4-79);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st16 {fill:#000000;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:0.36964980544747}
+ .st17 {marker-end:url(#mrkr4-79);stroke:#000000;stroke-dasharray:5.7,5.7;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st18 {marker-end:url(#mrkr2-98);marker-start:url(#mrkr2-96);stroke:#fbd3d0;stroke-linecap:round;stroke-linejoin:round;stroke-width:7.5}
+ .st19 {fill:#fbd3d0;fill-opacity:1;stroke:#fbd3d0;stroke-opacity:1;stroke-width:0.74850299401198}
+ .st20 {marker-end:url(#mrkr2-112);marker-start:url(#mrkr2-110);stroke:#fbd3d0;stroke-linecap:round;stroke-linejoin:round;stroke-width:7.5}
+ .st21 {fill:#fbd3d0;fill-opacity:1;stroke:#fbd3d0;stroke-opacity:1;stroke-width:0.80645161290323}
+ .st22 {marker-end:url(#mrkr4-118);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st23 {fill:#000000;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:0.42986425339367}
+ .st24 {marker-end:url(#mrkr4-124);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st25 {fill:#ff1a1a;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st26 {fill:#ffffff;font-family:Calibri;font-size:1.00001em;font-weight:bold}
+ .st27 {fill:none;stroke:#000000;stroke-dasharray:4.5,4.5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st28 {fill:none;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st29 {fill:#000000;font-family:Calibri;font-size:1.00001em;font-weight:bold}
+ .st30 {marker-end:url(#mrkr2-151);marker-start:url(#mrkr2-149);stroke:#fbd3d0;stroke-linecap:round;stroke-linejoin:round;stroke-width:8}
+ .st31 {fill:#fbd3d0;fill-opacity:1;stroke:#fbd3d0;stroke-opacity:1;stroke-width:0.76045627376426}
+ .st32 {fill:#000000;font-family:Arial;font-size:1.33333em;font-style:italic;font-weight:bold}
+ .st33 {fill:#ffffff;stroke:#7f7f7f;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
+ .st34 {fill:#a5a5a5;font-family:Arial;font-size:0.916672em}
+ .st35 {fill:#f2dcda;stroke:#a5a5a5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st36 {fill:#a5a5a5;font-family:Calibri;font-size:1.00001em;font-weight:bold}
+ .st37 {fill:none;stroke:#a5a5a5;stroke-dasharray:4.5,4.5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st38 {fill:#000000;font-family:Arial;font-size:0.666664em}
+ .st39 {font-family:Microsoft JhengHei;font-size:1em}
+ .st40 {fill:#dbeef3;stroke:#d8d8d8;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st41 {fill:#000000;font-family:Arial;font-size:1.66667em;font-weight:bold}
+ .st42 {fill:none;stroke:#000000;stroke-dasharray:2.25,2.25;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st43 {visibility:visible}
+ .st44 {fill:none;filter:url(#filter_3.3333334922791);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:0.4}
+ .st45 {fill:none;stroke:#bfbfbf;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st46 {fill:none;stroke:#a5a5a5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st47 {fill:#ffffff;stroke:#a5a5a5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st48 {marker-end:url(#mrkr4-118);stroke:#000000;stroke-dasharray:5.7,5.7;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st49 {marker-end:url(#mrkr4-251);stroke:#a5a5a5;stroke-dasharray:5.7,5.7;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st50 {fill:#a5a5a5;fill-opacity:1;stroke:#a5a5a5;stroke-opacity:1;stroke-width:0.42986425339367}
+ .st51 {marker-end:url(#mrkr4-257);stroke:#bfbfbf;stroke-dasharray:5.7,5.7;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st52 {fill:#bfbfbf;fill-opacity:1;stroke:#bfbfbf;stroke-opacity:1;stroke-width:0.42986425339367}
+ .st53 {marker-end:url(#mrkr4-265);marker-start:url(#mrkr2-149);stroke:#fbd3d0;stroke-linecap:round;stroke-linejoin:round;stroke-width:8}
+ .st54 {marker-end:url(#mrkr2-295);marker-start:url(#mrkr2-293);stroke:#fbd3d0;stroke-linecap:round;stroke-linejoin:round;stroke-width:4.25}
+ .st55 {fill:#fbd3d0;fill-opacity:1;stroke:#fbd3d0;stroke-opacity:1;stroke-width:0.62776957163959}
+ .st56 {marker-end:url(#mrkr2-313);stroke:#d8d8d8;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st57 {fill:#d8d8d8;fill-opacity:1;stroke:#d8d8d8;stroke-opacity:1;stroke-width:0.36964980544747}
+ .st58 {marker-end:url(#mrkr4-319);stroke:#d8d8d8;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st59 {fill:#d8d8d8;fill-opacity:1;stroke:#d8d8d8;stroke-opacity:1;stroke-width:0.22935779816514}
+ .st60 {stroke:#000000;stroke-dasharray:0,9;stroke-linecap:round;stroke-linejoin:round;stroke-width:3}
+ .st61 {fill:#000000;font-family:Calibri;font-size:0.833336em}
+ .st62 {fill:#000000;font-family:Arial;font-size:0.916672em;font-weight:bold}
+ .st63 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
+ ]]>
+ </style>
+
+ <defs id="Markers">
+ <g id="lend4">
+ <path d="M 2 1 L 0 0 L 2 -1 L 2 1 " style="stroke:none"/>
+ </g>
+ <marker id="mrkr4-79" class="st16" v:arrowType="4" v:arrowSize="3" v:setback="5.22105" refX="-5.2210526315789"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-2.7052631578947,-2.7052631578947) "/>
+ </marker>
+ <g id="lend2">
+ <path d="M 1 1 L 0 0 L 1 -1 L 1 1 " style="stroke:none"/>
+ </g>
+ <marker id="mrkr2-96" class="st19" v:arrowType="2" v:arrowSize="2" v:setback="1.288" refX="1.288" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(1.336) "/>
+ </marker>
+ <marker id="mrkr2-98" class="st19" v:arrowType="2" v:arrowSize="2" v:setback="1.288" refX="-1.288" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(-1.336,-1.336) "/>
+ </marker>
+ <marker id="mrkr2-110" class="st21" v:arrowType="2" v:arrowSize="1" v:setback="1.192" refX="1.192" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(1.24) "/>
+ </marker>
+ <marker id="mrkr2-112" class="st21" v:arrowType="2" v:arrowSize="1" v:setback="1.192" refX="-1.192" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(-1.24,-1.24) "/>
+ </marker>
+ <marker id="mrkr4-118" class="st23" v:arrowType="4" v:arrowSize="2" v:setback="4.46316" refX="-4.4631578947368"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-2.3263157894737,-2.3263157894737) "/>
+ </marker>
+ <marker id="mrkr4-124" class="st23" v:arrowType="4" v:arrowSize="2" v:setback="4.65263" refX="-4.6526315789474"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-2.3263157894737,-2.3263157894737) "/>
+ </marker>
+ <marker id="mrkr2-149" class="st31" v:arrowType="2" v:arrowSize="2" v:setback="1.27" refX="1.27" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(1.315) "/>
+ </marker>
+ <marker id="mrkr2-151" class="st31" v:arrowType="2" v:arrowSize="2" v:setback="1.27" refX="-1.27" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(-1.315,-1.315) "/>
+ </marker>
+ <marker id="mrkr4-251" class="st50" v:arrowType="4" v:arrowSize="2" v:setback="4.46316" refX="-4.4631578947368"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-2.3263157894737,-2.3263157894737) "/>
+ </marker>
+ <marker id="mrkr4-257" class="st52" v:arrowType="4" v:arrowSize="2" v:setback="4.46316" refX="-4.4631578947368"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-2.3263157894737,-2.3263157894737) "/>
+ </marker>
+ <marker id="mrkr4-265" class="st31" v:arrowType="4" v:arrowSize="2" v:setback="2.585" refX="-2.585" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-1.315,-1.315) "/>
+ </marker>
+ <marker id="mrkr2-293" class="st55" v:arrowType="2" v:arrowSize="2" v:setback="1.50824" refX="1.5082352941176"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(1.5929411764706) "/>
+ </marker>
+ <marker id="mrkr2-295" class="st55" v:arrowType="2" v:arrowSize="2" v:setback="1.59294" refX="-1.5929411764706"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(-1.5929411764706,-1.5929411764706) "/>
+ </marker>
+ <marker id="mrkr2-313" class="st57" v:arrowType="2" v:arrowSize="3" v:setback="2.51579" refX="-2.5157894736842"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(-2.7052631578947,-2.7052631578947) "/>
+ </marker>
+ <marker id="mrkr4-319" class="st59" v:arrowType="4" v:arrowSize="2" v:setback="8.72" refX="-8.72" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-4.36,-4.36) "/>
+ </marker>
+ </defs>
+ <defs id="Filters">
+ <filter id="filter_3.3333334922791">
+ <feGaussianBlur stdDeviation="3.3333334922791"/>
+ </filter>
+ </defs>
+ <g v:mID="4" v:index="1" v:groupContext="backgroundPage">
+ <v:userDefs>
+ <v:ud v:nameU="msvVisioCreated" v:prompt="" v:val="VT0(0):26"/>
+ </v:userDefs>
+ <title>VBackground-1</title>
+ <v:pageProperties width="14" height="8.5" v:drawingScale="1" v:pageScale="1" v:drawingUnits="19" v:shadowOffsetX="9"
+ v:shadowOffsetY="-9"/>
+ <g id="shape1-1" v:mID="1" v:groupContext="shape">
+ <title>Solid</title>
+ <v:userDefs>
+ <v:ud v:nameU="Background" v:val="VT0(0):26"/>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ <v:ud v:nameU="msvShapeCategories" v:prompt="" v:val="VT4(DoNotContain)"/>
+ <v:ud v:nameU="msvVisioCreated" v:prompt="" v:val="VT0(0):26"/>
+ </v:userDefs>
+ <rect x="0" y="0" width="1008" height="612" class="st1"/>
+ </g>
+ </g>
+ <g v:mID="0" v:index="2" v:groupContext="foregroundPage">
+ <title>Page-1</title>
+ <v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="19" v:shadowOffsetX="9" v:shadowOffsetY="-9"/>
+ <v:layer v:name="Connector" v:index="0"/>
+ <g id="shape1-3" v:mID="1" v:groupContext="shape" transform="translate(45,-342)">
+ <title>Sheet.1</title>
+ <path d="M0 612 L751.5 612" class="st2"/>
+ </g>
+ <g id="shape2-6" v:mID="2" v:groupContext="shape" transform="translate(211.5,-279)">
+ <title>Sheet.2</title>
+ <desc>RedfishLib (libredfish)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="67.5" cy="594" width="135" height="36"/>
+ <rect x="0" y="576" width="135" height="36" class="st3"/>
+ <text x="37.36" y="591" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>RedfishLib<v:lf/><tspan
+ x="44.78" dy="1.5em" class="st5">(</tspan><tspan class="st5">libredfish</tspan><tspan class="st5">)</tspan></text> </g>
+ <g id="shape3-12" v:mID="3" v:groupContext="shape" transform="translate(616.5,-283.5)">
+ <title>Sheet.3</title>
+ <desc>JsonLib (jansson)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="594" width="153" height="36"/>
+ <rect x="0" y="576" width="153" height="36" class="st3"/>
+ <text x="55.44" y="591" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>JsonLib<v:lf/><tspan
+ x="57.6" dy="1.5em" class="st5">(</tspan><tspan class="st5">jansson</tspan><tspan class="st5">)</tspan></text> </g>
+ <g id="shape4-18" v:mID="4" v:groupContext="shape" transform="translate(211.5,-216)">
+ <title>Sheet.4</title>
+ <desc>EFI Redfish Discover (UEFI Driver Model)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="67.5" cy="594" width="135" height="36"/>
+ <rect x="0" y="576" width="135" height="36" class="st6"/>
+ <text x="9.2" y="591" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>EFI Redfish Discover<v:lf/><tspan
+ x="26.49" dy="1.5em" class="st5">(</tspan><tspan class="st5">UEFI Driver Model</tspan><tspan class="st5">)</tspan></text> </g>
+ <g id="shape5-24" v:mID="5" v:groupContext="shape" transform="translate(211.5,-153)">
+ <title>Sheet.5</title>
+ <desc>EFI REST EX (UEFI Driver Model)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="67.5" cy="594" width="135" height="36"/>
+ <rect x="0" y="576" width="135" height="36" class="st6"/>
+ <text x="34.44" y="591" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>EFI REST EX<v:lf/><tspan
+ x="26.49" dy="1.5em" class="st5">(</tspan><tspan class="st5">UEFI Driver Model</tspan><tspan class="st5">)</tspan></text> </g>
+ <g id="shape6-30" v:mID="6" v:groupContext="shape" transform="translate(409.5,-279)">
+ <title>Sheet.6</title>
+ <desc>EFI REST JSON to C Structure (DXE Driver)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="589.5" width="153" height="45"/>
+ <rect x="0" y="567" width="153" height="45" class="st6"/>
+ <text x="26.52" y="579.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>EFI REST JSON to C <v:newlineChar/><tspan
+ x="51.33" dy="1.058em" class="st9">Structure<v:lf/></tspan><tspan x="51.09" dy="1.25em" class="st10">(</tspan><tspan
+ class="st10">DXE Driver</tspan><tspan class="st10">)</tspan></text> </g>
+ <g id="shape7-37" v:mID="7" v:groupContext="shape" transform="translate(409.5,-225)">
+ <title>Sheet.7</title>
+ <desc>EDKII Redfish Credential (DXE Driver)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="594" width="153" height="36"/>
+ <rect x="0" y="576" width="153" height="36" class="st6"/>
+ <text x="11.19" y="590.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>EDKII Redfish Credential<v:lf/><tspan
+ x="51.09" dy="1.3em" class="st10">(</tspan><tspan class="st10">DXE Driver</tspan><tspan class="st10">)</tspan></text> </g>
+ <g id="shape8-43" v:mID="8" v:groupContext="shape" transform="translate(409.5,-171)">
+ <title>Sheet.8</title>
+ <desc>EDKII Platform Content Coding Library</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="594" width="153" height="36"/>
+ <rect x="0" y="576" width="153" height="36" class="st11"/>
+ <text x="13.91" y="590.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>EDKII Platform Content <tspan
+ x="37.7" dy="1em" class="st9">Coding Library</tspan></text> </g>
+ <g id="shape9-47" v:mID="9" v:groupContext="shape" transform="translate(409.5,-117)">
+ <title>Sheet.9</title>
+ <desc>EDKII Network Stacks (UEFI Driver Model)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="594" width="153" height="36"/>
+ <rect x="0" y="576" width="153" height="36" class="st6"/>
+ <text x="18.73" y="590.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>EDKII Network Stacks<v:lf/><tspan
+ x="35.49" dy="1.3em" class="st10">(</tspan><tspan class="st10">UEFI Driver Model</tspan><tspan class="st10">)</tspan></text> </g>
+ <g id="shape10-53" v:mID="10" v:groupContext="shape" transform="translate(409.5,-54)">
+ <title>Sheet.10</title>
+ <desc>EDKII Redfish Host Interface (DXE Driver)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="589.5" width="153" height="45"/>
+ <rect x="0" y="567" width="153" height="45" class="st6"/>
+ <text x="26.68" y="579.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>EDKII Redfish Host <tspan
+ x="52.19" dy="1em" class="st9">Interface<v:lf/></tspan><tspan x="51.09" dy="1.3em" class="st10">(</tspan><tspan
+ class="st10">DXE Driver</tspan><tspan class="st10">)</tspan></text> </g>
+ <g id="shape11-60" v:mID="11" v:groupContext="shape" transform="translate(211.5,-94.5)">
+ <title>Sheet.11</title>
+ <desc>SMBIOS Type 42</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="67.5" cy="598.5" width="135" height="27"/>
+ <rect x="0" y="585" width="135" height="27" class="st12"/>
+ <text x="19.92" y="602.7" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>SMBIOS Type 42</text> </g>
+ <g id="shape12-63" v:mID="12" v:groupContext="shape" transform="translate(616.5,-72)">
+ <title>Sheet.12</title>
+ <desc>RedfishPlatformConfig.efi</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="598.5" width="153" height="27"/>
+ <rect x="0" y="585" width="153" height="27" class="st13"/>
+ <text x="22.93" y="601.5" class="st14" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>RedfishPlatformConfig.efi</text> </g>
+ <g id="shape13-66" v:mID="13" v:groupContext="shape" transform="translate(616.5,-225)">
+ <title>Sheet.13</title>
+ <desc>Platform Redfish Credential Library</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="594" width="153" height="36"/>
+ <rect x="0" y="576" width="153" height="36" class="st11"/>
+ <text x="31.21" y="590.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>Platform Redfish <tspan
+ x="28.36" dy="1em" class="st9">Credential Library</tspan></text> </g>
+ <g id="shape14-70" v:mID="14" v:groupContext="shape" transform="translate(618.25,-162)">
+ <title>Sheet.14</title>
+ <desc>Platform Redfish Host Interface Library</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="594" width="153" height="36"/>
+ <rect x="0" y="576" width="153" height="36" class="st11"/>
+ <text x="17.3" y="590.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>Platform Redfish Host <tspan
+ x="31.97" dy="1em" class="st9">Interface Library</tspan></text> </g>
+ <g id="shape20-74" v:mID="20" v:groupContext="shape" transform="translate(108.912,1066.03) rotate(-150.255)">
+ <title>Sheet.20</title>
+ <path d="M0 605.85 C5.2 601.6 11.37 602.58 17.02 603.9 C34.96 608.09 47.6 615.63 63.3 610.33 L63.63 610.17"
+ class="st15"/>
+ </g>
+ <g id="shape26-80" v:mID="26" v:groupContext="shape" transform="translate(798.806,378) rotate(90)">
+ <title>Sheet.26</title>
+ <path d="M0 587.31 C27.48 618.4 91.67 620.3 119.28 595.08 L119.51 594.81" class="st15"/>
+ </g>
+ <g id="shape27-85" v:mID="27" v:groupContext="shape" transform="translate(616.5,980.172) rotate(180)">
+ <title>Sheet.27</title>
+ <path d="M0 611.17 C8.24 606.04 18.13 605.86 27 607.8 C32.73 609.05 38.03 611.18 43.74 611.86 L44.1 611.83"
+ class="st17"/>
+ </g>
+ <g id="shape34-90" v:mID="34" v:groupContext="shape" transform="translate(958.5,315) rotate(90)">
+ <title>Sheet.34</title>
+ <path d="M4.28 603.34 L4.44 603.02 C6.15 598.55 7.91 593.52 10.26 589.58 C10.52 589.15 10.79 588.72 11.06 588.3 C24.98
+ 566.86 47.13 561.26 67.61 562.5 C93.1 564.05 116.01 576.2 123.87 602.21 L123.94 602.56" class="st18"/>
+ </g>
+ <g id="shape35-99" v:mID="35" v:groupContext="shape" transform="translate(868.595,10.4444) rotate(59.7436)">
+ <title>Sheet.35</title>
+ <path d="M0 604.43 C17.43 596.28 35.82 595.77 52.17 599.33 C75.61 604.44 94.87 617.9 116.02 609.38 L116.34 609.21"
+ class="st15"/>
+ </g>
+ <g id="shape42-104" v:mID="42" v:groupContext="shape" transform="translate(511.956,-120.094) rotate(15.9454)">
+ <title>Sheet.42</title>
+ <path d="M8.92 601.65 L9.28 601.63 C11.78 602.35 14.16 603.61 16.51 604.78 C30.56 611.79 43.18 615.49 57.81 607.46 L58.11
+ 607.26" class="st20"/>
+ </g>
+ <g id="shape43-113" v:mID="43" v:groupContext="shape" transform="translate(662.85,-296.1) rotate(9.46232)">
+ <title>Sheet.43</title>
+ <path d="M0 610.4 C16.69 599.74 30.24 612.49 46.06 612.08 L46.42 612.01" class="st22"/>
+ </g>
+ <g id="shape44-119" v:mID="44" v:groupContext="shape" transform="translate(891,396) rotate(90)">
+ <title>Sheet.44</title>
+ <path d="M0 612 L18.16 612" class="st24"/>
+ </g>
+ <g id="group45-125" transform="translate(846,-319.5)" v:mID="45" v:groupContext="group">
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <title>Can</title>
+ <desc>Redfish Service</desc>
+ <g id="shape46-126" v:mID="46" v:groupContext="shape">
+ <title>Sheet.46</title>
+ <v:userDefs>
+ <v:ud v:nameU="ControlHalfHeight" v:prompt="" v:val="VT0(0.125):1"/>
+ <v:ud v:nameU="FillForegnd" v:prompt="" v:val="VT0(1):26"/>
+ <v:ud v:nameU="ControlHalfHeight" v:prompt="" v:val="VT0(0.15625):1"/>
+ <v:ud v:nameU="FillForegnd" v:prompt="" v:val="VT5(#ff1a1a)"/>
+ </v:userDefs>
+ <path d="M0 600.75 A29.25 11.25 -180 1 0 58.5 600.75 L58.5 560.25 L0 560.25 L0 600.75 Z" class="st25"/>
+ </g>
+ <g id="shape45-128" v:mID="45" v:groupContext="groupContent">
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="2"/>
+ <v:textRect cx="29.25" cy="580.5" width="58.5" height="63"/>
+ <ellipse cx="29.25" cy="560.25" rx="29.25" ry="11.25" class="st25"/>
+ <text x="10.65" y="590" class="st26" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Redfish <tspan
+ x="11.42" dy="1.2em" class="st9">Service</tspan></text> </g>
+ </g>
+ <g id="shape47-132" v:mID="47" v:groupContext="shape" transform="translate(837,-315)">
+ <title>Rounded Rectangle</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ </v:userDefs>
+ <path d="M7.65 612 L68.85 612 A7.64987 7.64987 -180 0 0 76.5 604.35 L76.5 511.65 A7.64987 7.64987 -180 0 0 68.85 504
+ L7.65 504 A7.64987 7.64987 -180 0 0 -0 511.65 L0 604.35 A7.64987 7.64987 -180 0 0 7.65 612 Z" class="st27"/>
+ </g>
+ <g id="shape48-134" v:mID="48" v:groupContext="shape" transform="translate(837,-315)">
+ <title>Rounded Rectangle.48</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.175):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.175):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.175):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.175):1"/>
+ </v:userDefs>
+ <path d="M12.6 612 L113.4 612 A12.5998 12.5998 -180 0 0 126 599.4 L126 552.6 A12.5998 12.5998 -180 0 0 113.4 540 L12.6
+ 540 A12.5998 12.5998 -180 0 0 -0 552.6 L0 599.4 A12.5998 12.5998 -180 0 0 12.6 612 Z" class="st27"/>
+ </g>
+ <g id="shape49-136" v:mID="49" v:groupContext="shape" transform="translate(846,-391.5)">
+ <title>Sheet.49</title>
+ <desc>On Network</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="29.25" cy="598.5" width="58.5" height="27"/>
+ <rect x="0" y="585" width="58.5" height="27" class="st28"/>
+ <text x="21.97" y="594.9" class="st29" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>On <tspan x="7.49"
+ dy="1.2em" class="st9">Network</tspan></text> </g>
+ <g id="shape51-140" v:mID="51" v:groupContext="shape" transform="translate(913.5,-333)">
+ <title>Sheet.51</title>
+ <desc>BMC</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="22.5" cy="598.5" width="45" height="27"/>
+ <rect x="0" y="585" width="45" height="27" class="st28"/>
+ <text x="10.72" y="602.1" class="st29" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>BMC</text> </g>
+ <g id="shape53-143" v:mID="53" v:groupContext="shape" transform="translate(300.223,21.2932) rotate(-29.9221)">
+ <title>Sheet.53</title>
+ <path d="M8.6 531.2 L8.91 531.39 C45.12 553.68 83.03 571.57 122.32 588.41 C144.61 597.96 167.35 607.17 190.07 610.52
+ C222.93 615.38 255.74 608 284.87 592.4 C310.1 578.89 332.55 559.23 354.13 533.89 L354.36 533.61"
+ class="st30"/>
+ </g>
+ <g id="shape54-152" v:mID="54" v:groupContext="shape" transform="translate(1142.22,727.062) rotate(119.385)">
+ <title>Sheet.54</title>
+ <path d="M0 601.33 C1.8 603.71 4.18 606.09 6.63 607.87 C38.72 631.29 82.4 552.5 108.8 592.25 L108.97 592.57"
+ class="st17"/>
+ </g>
+ <g id="shape55-157" v:mID="55" v:groupContext="shape" transform="translate(189,531) rotate(-90)">
+ <title>Sheet.55</title>
+ <path d="M0 580.5 C3.72 583.62 7.79 589.31 12.01 593.96 C44.21 629.47 84.97 604.53 101.41 588.39 L101.64 588.12"
+ class="st15"/>
+ </g>
+ <g id="shape56-162" v:mID="56" v:groupContext="shape" transform="translate(45,-305)">
+ <title>Sheet.56</title>
+ <desc>EDKII Redfish Foundation</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="597.2" class="st32" v:langID="1033"><v:paragraph/><v:tabList/>EDKII Redfish <tspan x="4" dy="1.2em"
+ class="st9">Foundation</tspan></text> </g>
+ <g id="shape57-166" v:mID="57" v:groupContext="shape" transform="translate(45,-351)">
+ <title>Sheet.57</title>
+ <desc>EDKII Redfish Client</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="597.2" class="st32" v:langID="1033"><v:paragraph/><v:tabList/>EDKII Redfish <tspan x="4" dy="1.2em"
+ class="st9">Client</tspan></text> </g>
+ <g id="shape58-170" v:mID="58" v:groupContext="shape" transform="translate(54,-198)">
+ <title>Rounded Rectangle.58</title>
+ <desc>SSDP over UDP</desc>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.0625):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.0625):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.0625):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.0625):1"/>
+ </v:userDefs>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="54" cy="598.5" width="108" height="27"/>
+ <path d="M4.5 612 L103.5 612 A4.49993 4.49993 -180 0 0 108 607.5 L108 589.5 A4.49993 4.49993 -180 0 0 103.5 585 L4.5
+ 585 A4.49993 4.49993 -180 0 0 0 589.5 L0 607.5 A4.49993 4.49993 -180 0 0 4.5 612 Z" class="st33"/>
+ <text x="13.65" y="601.81" class="st34" v:langID="1033"><v:paragraph v:horizAlign="1" v:bulletSize="0.166667"/><v:tabList/>SSDP over UDP</text> </g>
+ <g id="group60-173" transform="translate(76.5,-117)" v:mID="60" v:groupContext="group">
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <title>Can.60</title>
+ <desc>Redfish Service</desc>
+ <g id="shape61-174" v:mID="61" v:groupContext="shape">
+ <title>Sheet.61</title>
+ <v:userDefs>
+ <v:ud v:nameU="ControlHalfHeight" v:prompt="" v:val="VT0(0.125):1"/>
+ <v:ud v:nameU="FillForegnd" v:prompt="" v:val="VT0(1):26"/>
+ <v:ud v:nameU="ControlHalfHeight" v:prompt="" v:val="VT0(0.15625):1"/>
+ <v:ud v:nameU="FillForegnd" v:prompt="" v:val="VT5(#f2dcda)"/>
+ </v:userDefs>
+ <path d="M0 600.75 A29.25 11.25 -180 1 0 58.5 600.75 L58.5 560.25 L0 560.25 L0 600.75 Z" class="st35"/>
+ </g>
+ <g id="shape60-176" v:mID="60" v:groupContext="groupContent">
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="2"/>
+ <v:textRect cx="29.25" cy="580.5" width="58.5" height="63"/>
+ <ellipse cx="29.25" cy="560.25" rx="29.25" ry="11.25" class="st35"/>
+ <text x="10.65" y="590" class="st36" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Redfish <tspan
+ x="11.42" dy="1.2em" class="st9">Service</tspan></text> </g>
+ </g>
+ <g id="shape62-180" v:mID="62" v:groupContext="shape" transform="translate(67.5,-90)">
+ <title>Rounded Rectangle.62</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ </v:userDefs>
+ <path d="M7.65 612 L68.85 612 A7.64987 7.64987 -180 0 0 76.5 604.35 L76.5 525.15 A7.64987 7.64987 -180 0 0 68.85 517.5
+ L7.65 517.5 A7.64987 7.64987 -180 0 0 -0 525.15 L0 604.35 A7.64987 7.64987 -180 0 0 7.65 612 Z"
+ class="st37"/>
+ </g>
+ <g id="shape63-182" v:mID="63" v:groupContext="shape" transform="translate(81,-90)">
+ <title>Sheet.63</title>
+ <desc>BMC</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="22.5" cy="598.5" width="45" height="27"/>
+ <rect x="0" y="585" width="45" height="27" class="st28"/>
+ <text x="10.72" y="602.1" class="st36" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>BMC</text> </g>
+ <g id="shape64-185" v:mID="64" v:groupContext="shape" transform="translate(614.75,-135)">
+ <title>Sheet.64</title>
+ <desc>Build up Redfish Host Interface</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="597.2" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>Build up Redfish Host Interface<v:newlineChar/></text> </g>
+ <g id="shape66-188" v:mID="66" v:groupContext="shape" transform="translate(806,-85.5)">
+ <title>Sheet.66</title>
+ <desc>EFI Shell Application, which builds up Redfish Host interface...</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="589.5" width="152" height="45"/>
+ <rect x="0" y="567" width="152" height="45" class="st28"/>
+ <text x="4" y="577.1" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>EFI Shell Application, which<v:newlineChar/><tspan
+ x="4" dy="1.2em" class="st9">builds up Redfish Host interface<v:newlineChar/><v:paragraph v:spLine="-1"
+ v:bulletSize="0.166667"/></tspan><tspan x="4" dy="1.05em" class="st9">for EDK</tspan>2 emulator platform<v:newlineChar/><tspan
+ x="4" dy="1.375em" class="st9">(</tspan>EmulatorPkg<tspan class="st39" v:langID="1028">)</tspan></text> </g>
+ <g id="shape69-195" v:mID="69" v:groupContext="shape" transform="translate(612,-202.5)">
+ <title>Sheet.69</title>
+ <desc>Get Authentication</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="597.2" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>Get Authentication<v:newlineChar/></text> </g>
+ <g id="shape71-198" v:mID="71" v:groupContext="shape" transform="translate(396,-486)">
+ <title>Sheet.71</title>
+ <desc>RedfishBiosDxe</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="130.5" cy="594" width="261" height="36"/>
+ <rect x="0" y="576" width="261" height="36" class="st40"/>
+ <text x="88.66" y="597.25" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>RedfishBiosDxe</text> </g>
+ <g id="shape72-201" v:mID="72" v:groupContext="shape" transform="translate(396,-423)">
+ <title>Sheet.72</title>
+ <desc>RedfishBootInfoDxe</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="130.5" cy="594" width="261" height="36"/>
+ <rect x="0" y="576" width="261" height="36" class="st40"/>
+ <text x="76.33" y="597.25" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>RedfishBootInfoDxe</text> </g>
+ <g id="shape73-204" v:mID="73" v:groupContext="shape" transform="translate(396,-441)">
+ <title>Sheet.73</title>
+ <desc>EDKII Redfish Feature DXE Drivers</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="130.5" cy="580.5" width="261" height="63"/>
+ <rect x="0" y="549" width="261" height="63" class="st28"/>
+ <text x="25.48" y="574.5" class="st41" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>EDKII Redfish Feature <tspan
+ x="72.69" dy="1.2em" class="st9">DXE Drivers</tspan></text> </g>
+ <g id="shape75-208" v:mID="75" v:groupContext="shape" transform="translate(369,-405)">
+ <title>Rectangle</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <path d="M0 612 L315 612 L315 477 L0 477 L0 612 Z" class="st42"/>
+ </g>
+ <g id="shape76-210" v:mID="76" v:groupContext="shape" transform="translate(324,-387)">
+ <title>Rounded Rectangle.76</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.23913043478261):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.23913043478261):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.23913043478261):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.23913043478261):1"/>
+ </v:userDefs>
+ <g id="shadow76-211" v:groupContext="shadow" v:shadowOffsetX="7.2E-008" v:shadowOffsetY="0" v:shadowType="1"
+ v:shadowScale="1.02" transform="matrix(1.02,0,0,1.02,-3.96,-10.53)" class="st43">
+ <path d="M17.22 612 L378.78 612 A17.2171 17.2171 -180 0 0 396 594.78 L396 458.22 A17.2171 17.2171 -180 0 0 378.78
+ 441 L17.22 441 A17.2171 17.2171 -180 0 0 0 458.22 L0 594.78 A17.2171 17.2171 -180 0 0 17.22 612 Z"
+ class="st44"/>
+ </g>
+ <path d="M17.22 612 L378.78 612 A17.2171 17.2171 -180 0 0 396 594.78 L396 458.22 A17.2171 17.2171 -180 0 0 378.78 441
+ L17.22 441 A17.2171 17.2171 -180 0 0 0 458.22 L0 594.78 A17.2171 17.2171 -180 0 0 17.22 612 Z"
+ class="st45"/>
+ </g>
+ <g id="shape77-215" v:mID="77" v:groupContext="shape" transform="translate(166.5,-396)">
+ <title>Sheet.77</title>
+ <desc>EDKII RedfishConfigDriver (UEF Driver Model)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="67.5" cy="589.5" width="135" height="45"/>
+ <rect x="0" y="567" width="135" height="45" class="st6"/>
+ <text x="52.11" y="580" class="st7" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>EDKII <tspan
+ x="9.37" dy="1em" class="st9">RedfishConfigDriver<v:lf/></tspan><tspan x="27.82" dy="1.25em" class="st5">(</tspan><tspan
+ class="st5">UEF Driver Model</tspan><tspan class="st5">)</tspan></text> </g>
+ <g id="shape79-222" v:mID="79" v:groupContext="shape" transform="translate(807.666,295.676) rotate(97.9072)">
+ <title>Sheet.79</title>
+ <path d="M0 579.17 C20.49 576.51 31.18 592.91 46.37 602.26 C77.86 621.65 128.73 610.76 156.32 586.48 L156.58 586.22"
+ class="st15"/>
+ </g>
+ <g id="shape80-227" v:mID="80" v:groupContext="shape" transform="translate(198,-522)">
+ <title>Rounded Rectangle.80</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ </v:userDefs>
+ <path d="M4.7 612 L103.3 612 A4.69558 4.69558 -180 0 0 108 607.3 L108 589.7 A4.69558 4.69558 -180 0 0 103.3 585 L4.7
+ 585 A4.69558 4.69558 -180 0 0 0 589.7 L0 607.3 A4.69558 4.69558 -180 0 0 4.7 612 Z" class="st46"/>
+ </g>
+ <g id="shape81-229" v:mID="81" v:groupContext="shape" transform="translate(189,-513)">
+ <title>Rounded Rectangle.81</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ </v:userDefs>
+ <path d="M4.7 612 L103.3 612 A4.69558 4.69558 -180 0 0 108 607.3 L108 589.7 A4.69558 4.69558 -180 0 0 103.3 585 L4.7
+ 585 A4.69558 4.69558 -180 0 0 0 589.7 L0 607.3 A4.69558 4.69558 -180 0 0 4.7 612 Z" class="st47"/>
+ </g>
+ <g id="shape90-231" v:mID="90" v:groupContext="shape" transform="translate(-119.157,659.986) rotate(-144.162)">
+ <title>Sheet.90</title>
+ <path d="M0 603.18 C4.15 607.13 9.94 610.11 15.61 611.34 C29.37 614.32 42.44 606.94 53.45 596.49 C61.26 589.09 68.03
+ 580.16 77.42 577.8 C88.41 575.03 102.97 581.29 102.88 593.34 L102.78 593.68" class="st15"/>
+ </g>
+ <g id="shape93-236" v:mID="93" v:groupContext="shape" transform="translate(221.899,727.905) rotate(-165.964)">
+ <title>Sheet.93</title>
+ <path d="M0 606.51 C15.17 612.77 29.52 612.61 44.18 611.2 C63.42 609.36 83.21 605.38 102.5 605.92 L102.86 605.95"
+ class="st48"/>
+ </g>
+ <g id="shape99-241" v:mID="99" v:groupContext="shape" transform="translate(139.354,700.857) rotate(-157.751)">
+ <title>Sheet.99</title>
+ <path d="M0 606.51 C14.58 612.77 28.36 612.61 42.45 611.2 C60.82 609.37 79.72 605.43 98.14 605.91 L98.5 605.94"
+ class="st48"/>
+ </g>
+ <g id="shape100-246" v:mID="100" v:groupContext="shape" transform="translate(5.09146,624.711) rotate(-143.13)">
+ <title>Sheet.100</title>
+ <path d="M0 606.51 C12.27 612.77 23.86 612.61 35.72 611.2 C50.71 609.43 66.12 605.66 81.18 605.88 L81.54 605.91"
+ class="st49"/>
+ </g>
+ <g id="shape108-252" v:mID="108" v:groupContext="shape" v:layerMember="0"
+ transform="translate(-63.7494,572.249) rotate(-135)">
+ <title>Wavy connector 2</title>
+ <v:userDefs>
+ <v:ud v:nameU="Scale" v:val="VT0(1):26"/>
+ <v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <path d="M0 612 L11.04 616.08 L21.88 618.76 L32.52 620.05 L51.73 619.09 L60.91 617.82 L70.5 616.14 L80.5 614.04 L80.85
+ 613.96" class="st51"/>
+ </g>
+ <g id="shape128-258" v:mID="128" v:groupContext="shape" transform="translate(74.6891,-268.274) rotate(-20.6744)">
+ <title>Sheet.128</title>
+ <path d="M7.05 596.86 L7.3 596.6 C41.41 565.41 84.23 581.81 125.37 593.78 C147.72 600.28 169.57 605.47 191.7 609.19 C205.94
+ 611.58 220.3 613.37 234.93 610.75 L235.27 610.64" class="st53"/>
+ </g>
+ <g id="shape129-266" v:mID="129" v:groupContext="shape" transform="translate(913.572,626.328) rotate(137.291)">
+ <title>Sheet.129</title>
+ <path d="M0 570.67 C12.35 560.49 25.47 555.25 38.41 555.6 C60.3 556.19 81.63 572.81 103.52 591.21 C116.04 601.73 128.75
+ 612.82 140.98 612 C156.61 610.95 171.47 590.42 165.19 577.2 L164.94 576.93" class="st22"/>
+ </g>
+ <g id="shape130-271" v:mID="130" v:groupContext="shape" transform="translate(961.972,521.508) rotate(125.838)">
+ <title>Sheet.130</title>
+ <path d="M0 537.17 C5.61 533.31 11.98 533.39 17.86 534.13 C66.05 540.21 81.59 590.84 108.93 606.62 C129.47 618.49 156.66
+ 610.69 176.83 592.27 C191.47 578.9 202.41 559.94 201.92 545.76 L201.83 545.41" class="st22"/>
+ </g>
+ <g id="shape141-276" v:mID="141" v:groupContext="shape" transform="translate(524.018,816.193) rotate(-153.905)">
+ <title>Sheet.141</title>
+ <path d="M0 558.08 C-1.1 562.68 -4.17 567.34 -5.65 572.12 C-8.55 581.49 -5.37 591.37 -0.33 598.33 C22.05 629.26 81.08
+ 602.84 124.62 577.22 C154.8 559.45 177.54 542.06 207.45 539.15 C220.74 537.86 235.46 539.43 242.28 549.86
+ L242.41 550.2" class="st22"/>
+ </g>
+ <g id="shape142-281" v:mID="142" v:groupContext="shape" transform="translate(24.75,-556.75)">
+ <title>Sheet.142</title>
+ <rect x="0" y="604.5" width="22.5" height="7.5" class="st6"/>
+ </g>
+ <g id="shape143-283" v:mID="143" v:groupContext="shape" transform="translate(24.75,-539.5)">
+ <title>Sheet.143</title>
+ <rect x="0" y="604.5" width="22.5" height="7.5" class="st3"/>
+ </g>
+ <g id="shape144-285" v:mID="144" v:groupContext="shape" transform="translate(24.75,-521.5)">
+ <title>Sheet.144</title>
+ <rect x="0" y="604.5" width="22.5" height="7.5" class="st11"/>
+ </g>
+ <g id="shape145-287" v:mID="145" v:groupContext="shape" transform="translate(22.5,-506.5)">
+ <title>Sheet.145</title>
+ <path d="M6.41 612 L6.77 612 L20.23 612" class="st54"/>
+ </g>
+ <g id="shape147-296" v:mID="147" v:groupContext="shape" transform="translate(52.25,-551.5)">
+ <title>Sheet.147</title>
+ <desc>EDKII Open Source</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="605.6" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>EDKII Open Source</text> </g>
+ <g id="shape148-299" v:mID="148" v:groupContext="shape" transform="translate(51.75,-533.5)">
+ <title>Sheet.148</title>
+ <desc>Other Open Source</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="605.6" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>Other Open Source</text> </g>
+ <g id="shape149-302" v:mID="149" v:groupContext="shape" transform="translate(51.75,-515.5)">
+ <title>Sheet.149</title>
+ <desc>OEM EDKII Library</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="605.6" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>OEM EDKII Library</text> </g>
+ <g id="shape150-305" v:mID="150" v:groupContext="shape" transform="translate(51.75,-496.5)">
+ <title>Sheet.150</title>
+ <desc>Redfish Payload Flow</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="605.6" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>Redfish Payload Flow</text> </g>
+ <g id="shape151-308" v:mID="151" v:groupContext="shape" transform="translate(461.424,927.834) rotate(155.556)">
+ <title>Sheet.151</title>
+ <path d="M0 603.97 C7.28 610.16 18.09 613.87 26.44 611.05 C35.57 607.96 41.76 597.08 50.21 600.96 L50.5 601.17"
+ class="st56"/>
+ </g>
+ <g id="shape153-314" v:mID="153" v:groupContext="shape" transform="translate(711.673,514.612) rotate(99.4623)">
+ <title>Sheet.153</title>
+ <path d="M0 612 L7.15 612" class="st58"/>
+ </g>
+ <g id="shape154-320" v:mID="154" v:groupContext="shape" transform="translate(-161.042,-388.162) rotate(-39.2894)">
+ <title>Sheet.154</title>
+ <path d="M0 612 L21.32 612" class="st60"/>
+ </g>
+ <g id="shape155-323" v:mID="155" v:groupContext="shape" transform="translate(162,-499.5)">
+ <title>Rounded Rectangle.82</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ </v:userDefs>
+ <path d="M4.7 612 L103.3 612 A4.69558 4.69558 -180 0 0 108 607.3 L108 589.7 A4.69558 4.69558 -180 0 0 103.3 585 L4.7
+ 585 A4.69558 4.69558 -180 0 0 0 589.7 L0 607.3 A4.69558 4.69558 -180 0 0 4.7 612 Z" class="st12"/>
+ </g>
+ <g id="shape156-325" v:mID="156" v:groupContext="shape" transform="translate(153,-486)">
+ <title>Rounded Rectangle.83</title>
+ <desc>EDKII Redfish Config Handler Protocol</desc>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ </v:userDefs>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="54" cy="598.5" width="108" height="27"/>
+ <path d="M4.7 612 L103.3 612 A4.69558 4.69558 -180 0 0 108 607.3 L108 589.7 A4.69558 4.69558 -180 0 0 103.3 585 L4.7
+ 585 A4.69558 4.69558 -180 0 0 0 589.7 L0 607.3 A4.69558 4.69558 -180 0 0 4.7 612 Z" class="st12"/>
+ <text x="13.06" y="595.5" class="st61" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>EDKII Redfish Config <tspan
+ x="19.55" dy="1.2em" class="st9">Handler Protocol</tspan></text> </g>
+ <g id="shape157-329" v:mID="157" v:groupContext="shape" transform="translate(24.75,-315)">
+ <title>Sheet.157</title>
+ <desc>[1]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[1]</text> </g>
+ <g id="shape158-332" v:mID="158" v:groupContext="shape" transform="translate(24.75,-360)">
+ <title>Sheet.158</title>
+ <desc>[2]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[2]</text> </g>
+ <g id="shape159-335" v:mID="159" v:groupContext="shape" transform="translate(207,-250)">
+ <title>Sheet.159</title>
+ <desc>[3]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[3]</text> </g>
+ <g id="shape160-338" v:mID="160" v:groupContext="shape" transform="translate(207,-188)">
+ <title>Sheet.160</title>
+ <desc>[4]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[4]</text> </g>
+ <g id="shape161-341" v:mID="161" v:groupContext="shape" transform="translate(562.5,-250)">
+ <title>Sheet.161</title>
+ <desc>[5]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[5]</text> </g>
+ <g id="shape162-344" v:mID="162" v:groupContext="shape" transform="translate(562.5,-54)">
+ <title>Sheet.162</title>
+ <desc>[6]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[6]</text> </g>
+ <g id="shape163-347" v:mID="163" v:groupContext="shape" transform="translate(207,-75.5)">
+ <title>Sheet.163</title>
+ <desc>[7]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[7]</text> </g>
+ <g id="shape164-350" v:mID="164" v:groupContext="shape" transform="translate(562.5,-142)">
+ <title>Sheet.164</title>
+ <desc>[8]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[8]</text> </g>
+ <g id="shape165-353" v:mID="165" v:groupContext="shape" transform="translate(562.5,-306)">
+ <title>Sheet.165</title>
+ <desc>[9]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[9]</text> </g>
+ <g id="shape166-356" v:mID="166" v:groupContext="shape" transform="translate(612,-259)">
+ <title>Sheet.166</title>
+ <desc>[10]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[10]</text> </g>
+ <g id="shape167-359" v:mID="167" v:groupContext="shape" transform="translate(612,-196)">
+ <title>Sheet.167</title>
+ <desc>[11]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[11]</text> </g>
+ <g id="shape168-362" v:mID="168" v:groupContext="shape" transform="translate(560.25,-189)">
+ <title>Sheet.168</title>
+ <desc>[12]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[12]</text> </g>
+ <g id="shape169-365" v:mID="169" v:groupContext="shape" transform="translate(207,-313)">
+ <title>Sheet.169</title>
+ <desc>[13]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[13]</text> </g>
+ <g id="shape170-368" v:mID="170" v:groupContext="shape" transform="translate(612,-318.5)">
+ <title>Sheet.170</title>
+ <desc>[14]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[14]</text> </g>
+ <g id="shape171-371" v:mID="171" v:groupContext="shape" transform="translate(139.5,-422)">
+ <title>Sheet.171</title>
+ <desc>[15]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[15]</text> </g>
+ <g id="shape172-374" v:mID="172" v:groupContext="shape" transform="translate(135,-511)">
+ <title>Sheet.172</title>
+ <desc>[16]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[16]</text> </g>
+ <g id="shape173-377" v:mID="173" v:groupContext="shape" transform="translate(326.25,-557)">
+ <title>Sheet.173</title>
+ <desc>[17]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[17]</text> </g>
+ <g id="shape174-380" v:mID="174" v:groupContext="shape" transform="translate(54,-225)">
+ <title>Sheet.174</title>
+ <desc>[18]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[18]</text> </g>
+ <g id="shape175-383" v:mID="175" v:groupContext="shape" transform="translate(895.5,-295)">
+ <title>Sheet.175</title>
+ <desc>[19]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[19]</text> </g>
+ <g id="shape176-386" v:mID="176" v:groupContext="shape" transform="translate(612,-99)">
+ <title>Sheet.176</title>
+ <desc>[20]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[20]</text> </g>
+ </g>
+</svg>
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/IndustryStandard/RedfishHostInterface.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/IndustryStandard/RedfishHostInterface.h
new file mode 100644
index 00000000..44cb0499
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/IndustryStandard/RedfishHostInterface.h
@@ -0,0 +1,169 @@
+/** @file
+ This file defines the Redfish Interface Specific Data.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef REDFISH_HOST_INTERFACE_
+#define REDFISH_HOST_INTERFACE_
+
+#include <IndustryStandard/SmBios.h>
+
+#define REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB 0x02 // We don't support this type of interface.
+ // Use REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2 instead.
+#define REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE 0x03 // We don't support this type of interface.
+ // Use REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2 instead.
+#define REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2 0x04
+#define REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2 0x05
+
+#define REDFISH_HOST_INTERFACE_HOST_IP_ASSIGNMENT_TYPE_UNKNOWN 0x00
+#define REDFISH_HOST_INTERFACE_HOST_IP_ASSIGNMENT_TYPE_STATIC 0x01
+#define REDFISH_HOST_INTERFACE_HOST_IP_ASSIGNMENT_TYPE_DHCP 0x02
+#define REDFISH_HOST_INTERFACE_HOST_IP_ASSIGNMENT_TYPE_AUTO_CONFIGURE 0x03
+#define REDFISH_HOST_INTERFACE_HOST_IP_ASSIGNMENT_TYPE_HOST_SELECTED 0x04
+
+#define REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_UNKNOWN 0x00
+#define REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP4 0x01
+#define REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6 0x02
+
+#pragma pack(1)
+///
+/// Structure definitions of Host Interface device type 04h (USB Network Interface V2)
+///
+typedef struct {
+ UINT8 Length; ///< Length of the structure, including Device Type
+ ///< and Length fields.
+ UINT16 IdVendor; ///< The Vendor ID of the device, as read from the
+ ///< idVendor field of the USB descriptor.
+ UINT16 IdProduct; ///< The Product ID of the device, as read from the
+ ///< idProduct field of the USB descriptor.
+ UINT8 SecialNumberStr; ///< The string number for the Serial Number of the
+ ///< device. The string data is read from the
+ ///< iSerialNumber.bDescriptorType field of the USB
+ ///< descriptor, and is converted from Unicode to ASCII
+ ///< and is NULL terminated.
+ UINT8 MacAddress [6]; ///< The MAC address of the PCI/PCIe network device.
+} USB_INTERFACE_DEVICE_DESCRIPTOR_V2;
+
+//
+// Structure definitions of Host Interface device type 05h (PCI/PCIE V2)
+//
+typedef struct {
+ UINT8 Length; ///< Length of the structure, including Device Type and Length fields.
+ UINT16 VendorId; ///< The Vendor ID of the PCI/PCIe device.
+ UINT16 DeviceId; ///< The Device ID of the PCI/PCIe device.
+ UINT16 SubsystemVendorId; ///< The Subsystem Vendor ID of the PCI/PCIe device.
+ UINT16 SubsystemId; ///< The Subsystem ID of the PCI/PCIe device.
+ UINT8 MacAddress [6]; ///< The MAC address of the PCI/PCIe network device.
+ UINT16 SegmemtGroupNumber; ///< The Segment Group Number of the PCI/PCIe.
+ UINT8 BusNumber; ///< The Bus Number of the PCI/PCIe device.
+ UINT8 DeviceFunctionNumber; ///< The Device/Function Number of the PCI/PCIe.
+} PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2;
+
+///
+/// Structure definitions of Host Interface device type 80-FFh (OEM)
+///
+typedef struct {
+ UINT32 VendorIana; ///< The IANA code for the vendor (MSB first).
+ UINT8 OemDefinedData[1]; ///< OEM defined data.
+} OEM_DEVICE_DESCRIPTOR;
+
+///
+/// Define union for the Host Interface Device Descriptor
+///
+typedef union {
+ USB_INTERFACE_DEVICE_DESCRIPTOR_V2 UsbDeviceV2; ///< Device type USB V2 device discriptor.
+ PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2 PciPcieDeviceV2; ///< Device type PCI/PCIe V2 device discriptor.
+ OEM_DEVICE_DESCRIPTOR OemDevice; ///< OEM type device discriptor.
+} DEVICE_DESCRITOR; /// Device descriptor data formated based on Device Type.
+
+///
+/// Interface Specific Data starts at offset 06h of the SMBIOS Type 42 struct.
+/// This table defines the Interface Specific data for Interface Type 40h. There
+/// are 3 types of Device Descriptor3 defined , however only 1 may be used in
+/// specific Tape 42 table.
+///
+typedef struct {
+ UINT8 DeviceType; ///< The Device Type of the interface.
+ DEVICE_DESCRITOR DeviceDescriptor; ///< The Device descriptor.
+} REDFISH_INTERFACE_DATA;
+
+//
+// the protocol-specific data for the "Redfish Over IP" protocol
+//
+typedef struct {
+ EFI_GUID ServiceUuid; //same as Redfish Service UUID in Redfish Service Root resource
+
+ //
+ // Unknown=00h,
+ // Static=01h,
+ // DHCP=02h,
+ // AutoConfigure=03h,
+ // HostSelected=04h,
+ // other values reserved
+ //
+ UINT8 HostIpAssignmentType;
+
+ //
+ // Unknown=00h,
+ // Ipv4=01h,
+ // Ipv6=02h,
+ // other values reserved
+ //
+ UINT8 HostIpAddressFormat;
+
+ //
+ // Used for Static and AutoConfigure.
+ // For IPV4, use the first 4 Bytes and zero fill the remaining bytes.
+ //
+ UINT8 HostIpAddress[16];
+
+ //
+ // Used for Static and AutoConfigure.
+ // For IPV4, use the first 4 Bytes and zero fill the remaining bytes.
+ //
+ UINT8 HostIpMask[16];
+
+ //
+ // Unknown=00h,
+ // Static=01h,
+ // DHCP=02h,
+ // AutoConfigure=03h,
+ // HostSelected=04h,
+ // other values reserved
+ //
+ UINT8 RedfishServiceIpDiscoveryType;
+
+ //
+ // Unknown=00h,
+ // Ipv4=01h,
+ // Ipv6=02h,
+ // other values reserved
+ //
+ UINT8 RedfishServiceIpAddressFormat;
+
+ //
+ // Used for Static and AutoConfigure.
+ // For IPV4, use the first 4 Bytes and zero fill the remaining bytes.
+ //
+ UINT8 RedfishServiceIpAddress[16];
+
+ //
+ // Used for Static and AutoConfigure.
+ // For IPV4, use the first 4 Bytes and zero fill the remaining bytes.
+ //
+ UINT8 RedfishServiceIpMask[16];
+
+ UINT16 RedfishServiceIpPort; // Used for Static and AutoConfigure.
+ UINT32 RedfishServiceVlanId; // Used for Static and AutoConfigure.
+ UINT8 RedfishServiceHostnameLength; // length of the following hostname string
+ UINT8 RedfishServiceHostname[1]; // hostname of Redfish Service
+} REDFISH_OVER_IP_PROTOCOL_DATA;
+
+#pragma pack()
+
+#endif
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/BaseUcs2Utf8Lib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/BaseUcs2Utf8Lib.h
new file mode 100644
index 00000000..a17436bb
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/BaseUcs2Utf8Lib.h
@@ -0,0 +1,61 @@
+/** @file
+ UCS2 to UTF8 manipulation library header file.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef BASE_UCS2UTF8_LIB_H_
+#define BASE_UCS2UTF8_LIB_H_
+
+///
+/// L"\u0000"
+///
+#define UNICODE_FORMAT_LEN 6
+#define UNICODE_FORMAT_CHAR_LEN 2
+#define UNICODE_FORMAT_CHAR_SIZE 3
+
+#define UTF8_BUFFER_FOR_UCS2_MAX_SIZE 3
+
+/**
+ Convert a UCS2 string to a UTF8 encoded string.
+
+ @param[in] Ucs2Str The provided UCS2 string.
+ @param[out] Utf8StrAddr The converted UTF8 string address. Caller
+ is responsible for Free this string.
+
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES System runs out of resources.
+ @retval EFI_SUCCESS The UTF8 encoded string has been converted.
+
+**/
+EFI_STATUS
+UCS2StrToUTF8 (
+ IN CHAR16 *Ucs2Str,
+ OUT CHAR8 **Utf8StrAddr
+ );
+
+/**
+ Convert a UTF8 encoded string to a UCS2 string.
+
+ @param[in] Utf8Str The provided UTF8 encoded string.
+ @param[out] Ucs2StrAddr The converted UCS2 string address. Caller
+ is responsible for Free this string.
+
+ @retval EFI_INVALID_PARAMETER The UTF8 encoded string is not valid to
+ convert to UCS2 string.
+ One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES System runs out of resources.
+ @retval EFI_SUCCESS The UCS2 string has been converted.
+
+**/
+EFI_STATUS
+UTF8StrToUCS2 (
+ IN CHAR8 *Utf8Str,
+ OUT CHAR16 **Ucs2StrAddr
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/JsonLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/JsonLib.h
new file mode 100644
index 00000000..0b661a0a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/JsonLib.h
@@ -0,0 +1,800 @@
+/** @file
+ APIs for JSON operations.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef JSON_LIB_H_
+#define JSON_LIB_H_
+
+typedef VOID* EDKII_JSON_VALUE;
+typedef VOID* EDKII_JSON_ARRAY;
+typedef VOID* EDKII_JSON_OBJECT;
+
+///
+/// Map to json_int_t in jansson.h
+///
+typedef INT64 EDKII_JSON_INT_T; // #JSON_INTEGER_IS_LONG_LONG is set to 1
+ // in jansson_Config.h
+
+///
+/// Map to the definitions in jansson.h
+/// See below URI for the JSON encoding flags reference.
+/// https://jansson.readthedocs.io/en/2.13/apiref.html#encoding
+///
+#define EDKII_JSON_MAX_INDENT 0x1F
+#define EDKII_JSON_INDENT(n) ((n) & EDKII_JSON_MAX_INDENT)
+
+#define EDKII_JSON_COMPACT 0x20
+#define EDKII_JSON_ENSURE_ASCII 0x40
+#define EDKII_JSON_SORT_KEYS 0x80
+#define EDKII_JSON_PRESERVE_ORDER 0x100
+#define EDKII_JSON_ENCODE_ANY 0x200
+#define EDKII_JSON_ESCAPE_SLASH 0x400
+#define EDKII_JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11)
+#define EDKII_JSON_EMBED 0x10000
+
+///
+/// Map to the definitions in jansson.h
+/// See below URI for the JSON decoding flags reference.
+/// https://jansson.readthedocs.io/en/2.13/apiref.html?highlight=json_loadb#decoding
+///
+#define EDKII_JSON_REJECT_DUPLICATES 0x1
+#define EDKII_JSON_DISABLE_EOF_CHECK 0x2
+#define EDKII_JSON_DECODE_ANY 0x4
+#define EDKII_JSON_DECODE_INT_AS_REAL 0x8
+#define EDKII_JSON_ALLOW_NUL 0x10
+
+#define EDKII_JSON_ARRAY_FOREACH(Array, Index, Value) \
+ for(Index = 0; \
+ Index < JsonArrayCount(Array) && (Value = JsonArrayGetValue(Array, Index)); \
+ Index++)
+
+///
+/// Map to the json_error_t in jansson.h
+///
+#define EDKII_JSON_ERROR_TEXT_LENGTH 160
+#define EDKII_JSON_ERROR_SOURCE_LENGTH 80
+typedef struct {
+ INTN Line;
+ INTN Column;
+ INTN Position;
+ CHAR8 Source [EDKII_JSON_ERROR_SOURCE_LENGTH];
+ CHAR8 Text [EDKII_JSON_ERROR_TEXT_LENGTH];
+} EDKII_JSON_ERROR;
+
+///
+/// Map to the json_type in jansson.h
+///
+typedef enum {
+ EdkiiJsonTypeObject,
+ EdkiiJsonTypeArray,
+ EdkiiJsonTypeString,
+ EdkiiJsonTypeInteger,
+ EdkiiJsonTypeReal,
+ EdkiiJsonTypeTrue,
+ EdkiiJsonTypeFalse,
+ EdkiiJsonTypeNull
+} EDKII_JSON_TYPE;
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON array,
+ or NULL on error. Initially, the array is empty.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @retval The created JSON value which contains a JSON array or NULL if intial a JSON array
+ is failed.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitArray (
+ VOID
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON object,
+ or NULL on error. Initially, the object is empty.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @retval The created JSON value which contains a JSON object or NULL if intial a JSON object
+ is failed.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitObject (
+ VOID
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON string,
+ or NULL on error.
+
+ The input string must be NULL terminated Ascii format, non-Ascii characters will
+ be processed as an error. Unicode characters can also be represented by Ascii string
+ as the format: \u + 4 hexadecimal digits, like \u3E5A, or \u003F.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] String The Ascii string to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON string or NULL. Select a
+ Getter API for a specific encoding format.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitAsciiString (
+ IN CONST CHAR8 *String
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON string,
+ or NULL on error.
+
+ The input must be a NULL terminated UCS2 format Unicode string.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] String The Unicode string to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON string or NULL. Select a
+ Getter API for a specific encoding format.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitUnicodeString (
+ IN CHAR16 *String
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON integer,
+ or NULL on error.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] Value The integer to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON number or NULL.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitNumber (
+ IN INT64 Value
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON boolean,
+ or NULL on error.
+
+ Boolean JSON value is kept as static value, and no need to do any cleanup work.
+
+ @param[in] Value The boolean value to initialize.
+
+ @retval The created JSON value which contains a JSON boolean or NULL.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitBoolean (
+ IN BOOLEAN Value
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON NULL,
+ or NULL on error.
+
+ NULL JSON value is kept as static value, and no need to do any cleanup work.
+
+ @retval The created NULL JSON value.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitNull (
+ VOID
+ );
+
+/**
+ The function is used to decrease the reference count of a JSON value by one, and once
+ this reference count drops to zero, the value is destroyed and it can no longer be used.
+ If this destroyed value is object type or array type, reference counts for all containing
+ JSON values will be decreased by 1. Boolean JSON value and NULL JSON value won't be destroyed
+ since they are static values kept in memory.
+
+ Reference Count Strategy: BaseJsonLib uses this strategy to track whether a value is still
+ in use or not. When a value is created, it's reference count is set to 1. If a reference to a
+ value is kept for use, its reference count is incremented, and when the value is no longer
+ needed, the reference count is decremented. When the reference count drops to zero, there are
+ no references left, and the value can be destroyed.
+
+ The given JSON value maybe NULL and not causing any problem. Just output the debug message
+ to inform caller the NULL value is passed in.
+
+ @param[in] Json The JSON value to be freed. json_decref may return without any
+ changes if Json is NULL.
+
+**/
+VOID
+EFIAPI
+JsonValueFree (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to create a fresh copy of a JSON value, and all child values are deep
+ copied in a recursive fashion. It should be called when this JSON value might be modified
+ in later use, but the original still wants to be used in somewhere else.
+
+ Reference counts of the returned root JSON value and all child values will be set to 1, and
+ caller needs to cleanup the root value by calling JsonValueFree().
+
+ * Note: Since this function performs a copy from bottom to up, too many calls may cause some
+ performance issues, user should avoid unnecessary calls to this function unless it is really
+ needed.
+
+ @param[in] Json The JSON value to be cloned.
+
+ @retval Return the cloned JSON value, or NULL on error.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueClone (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON array.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON array.
+ @retval FALSE The JSON value doesn't contain a JSON array.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsArray (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON object.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON object.
+ @retval FALSE The JSON value doesn't contain a JSON object.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsObject (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON Value contains a string, Ascii or
+ Unicode format is not differentiated.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON string.
+ @retval FALSE The JSON value doesn't contain a JSON string.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsString (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON number.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value is contains JSON number.
+ @retval FALSE The JSON value doesn't contain a JSON number.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsNumber (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON boolean.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON boolean.
+ @retval FALSE The JSON value doesn't contain a JSON boolean.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsBoolean (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON NULL.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON NULL.
+ @retval FALSE The JSON value doesn't contain a JSON NULL.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsNull (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated array in an array type JSON value.
+
+ Any changes to the returned array will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated array in JSON value or NULL.
+
+**/
+EDKII_JSON_ARRAY
+EFIAPI
+JsonValueGetArray (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated object in an object type JSON value.
+
+ Any changes to the returned object will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated object in JSON value or NULL.
+
+**/
+EDKII_JSON_OBJECT
+EFIAPI
+JsonValueGetObject (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated Ascii string in a string type JSON value.
+
+ Any changes to the returned string will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Ascii string in JSON value or NULL.
+
+**/
+CONST CHAR8 *
+EFIAPI
+JsonValueGetAsciiString (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated Unicode string in a string type JSON value.
+
+ Caller can do any changes to the returned string without any impact to the original JSON
+ value, and caller needs to free the returned string using FreePool().
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Unicode string in JSON value or NULL.
+
+**/
+CHAR16*
+EFIAPI
+JsonValueGetUnicodeString (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated integer in a number type JSON value.
+
+ The input JSON value should not be NULL or contain no JSON number, otherwise it will
+ ASSERT() and return 0.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated number in JSON value.
+
+**/
+INT64
+EFIAPI
+JsonValueGetNumber (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated boolean in a boolean type JSON value.
+
+ The input JSON value should not be NULL or contain no JSON boolean, otherwise it will
+ ASSERT() and return FALSE.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated value of JSON boolean.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueGetBoolean (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated string in a string type JSON value.
+
+ Any changes to the returned string will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Ascii string in JSON value or NULL on errors.
+
+**/
+CONST CHAR8*
+EFIAPI
+JsonValueGetString (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to get the number of elements in a JSON object, or 0 if it is NULL or
+ not a JSON object.
+
+ @param[in] JsonObject The provided JSON object.
+
+ @retval Return the number of elements in this JSON object or 0.
+
+**/
+UINTN
+EFIAPI
+JsonObjectSize (
+ IN EDKII_JSON_OBJECT JsonObject
+ );
+
+/**
+ The function is used to enumerate all keys in a JSON object.
+
+ Caller should be responsible to free the returned key array reference using
+ FreePool(). But contained keys are read only and must not be modified or freed.
+
+ @param[in] JsonObj The provided JSON object for enumeration.
+ @param[out] KeyCount The count of keys in this JSON object.
+
+ @retval Return an array of the enumerated keys in this JSON object or NULL if
+ JsonObj is not an JSON object, key count is zero or on other errors.
+
+**/
+CHAR8**
+JsonObjectGetKeys (
+ IN EDKII_JSON_OBJECT JsonObj,
+ OUT UINTN *KeyCount
+ );
+
+/**
+ The function is used to get a JSON value corresponding to the input key from a JSON object.
+
+ It only returns a reference to this value and any changes on this value will impact the
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to
+ use.
+
+ Input key must be a valid NULL terminated UTF8 encoded string. NULL will be returned when
+ Key-Value is not found in this JSON object.
+
+ @param[in] JsonObj The provided JSON object.
+ @param[in] Key The key of the JSON value to be retrieved.
+
+ @retval Return the corresponding JSON value to key, or NULL on error.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonObjectGetValue (
+ IN CONST EDKII_JSON_OBJECT JsonObj,
+ IN CONST CHAR8 *Key
+ );
+
+/**
+ The function is used to set a JSON value corresponding to the input key from a JSON object,
+ and the reference count of this value will be increased by 1.
+
+ Input key must be a valid NULL terminated UTF8 encoded string. If there already is a value for
+ this key, this key will be assigned to the new JSON value. The old JSON value will be removed
+ from this object and thus its' reference count will be decreased by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonObj The provided JSON object.
+ @param[in] Key The key of the JSON value to be set.
+ @param[in] Json The JSON value to set to this JSON object mapped by key.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS The JSON value has been set to this JSON object.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonObjectSetValue (
+ IN EDKII_JSON_OBJECT JsonObj,
+ IN CONST CHAR8 *Key,
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to get the number of elements in a JSON array. Returns or 0 if JsonArray
+ is NULL or not a JSON array.
+
+ @param[in] JsonArray The provided JSON array.
+
+ @retval Return the number of elements in this JSON array or 0.
+
+**/
+UINTN
+EFIAPI
+JsonArrayCount (
+ IN EDKII_JSON_ARRAY JsonArray
+ );
+
+/**
+ The function is used to return the JSON value in the array at position index. The valid range
+ for this index is from 0 to the return value of JsonArrayCount() minus 1.
+
+ It only returns a reference to this value and any changes on this value will impact the
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to
+ use.
+
+ If this array is NULL or not a JSON array, or if index is out of range, NULL will be returned.
+
+ @param[in] JsonArray The provided JSON Array.
+
+ @retval Return the JSON value located in the Index position or
+ NULL if JsonArray is not an array or no items in the array.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonArrayGetValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN UINTN Index
+ );
+
+/**
+ The function is used to append a JSON value to the end of the JSON array, and grow the size of
+ array by 1. The reference count of this value will be increased by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonArray The provided JSON object.
+ @param[in] Json The JSON value to append.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS JSON value has been appended to the end of the JSON array.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonArrayAppendValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to remove a JSON value at position index, shifting the elements after index
+ one position towards the start of the array. The reference count of this value will be decreased
+ by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonArray The provided JSON array.
+ @param[in] Index The Index position before removement.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS The JSON array has been removed at position index.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonArrayRemoveValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN UINTN Index
+ );
+
+/**
+ Dump JSON to a buffer.
+
+ @param[in] JsonValue The provided JSON value.
+ @param[in] Flags The Index position before removement. The value
+ could be the combination of below flags.
+ - EDKII_JSON_INDENT(n)
+ - EDKII_JSON_COMPACT
+ - EDKII_JSON_ENSURE_ASCII
+ - EDKII_JSON_SORT_KEYS
+ - EDKII_JSON_PRESERVE_ORDER
+ - EDKII_JSON_ENCODE_ANY
+ - EDKII_JSON_ESCAPE_SLASH
+ - EDKII_JSON_REAL_PRECISION(n)
+ - EDKII_JSON_EMBED
+ See below URI for the JSON encoding flags reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html#encoding
+
+ @retval CHAR8 * Dump fail if NULL returned, otherwise the buffer
+ contain JSON paylaod in ASCII string. The return
+ value must be freed by the caller FreePool().
+**/
+CHAR8 *
+EFIAPI
+JsonDumpString (
+ IN EDKII_JSON_VALUE JsonValue,
+ IN UINTN Flags
+ );
+
+/**
+ Convert a string to JSON object.
+ The function is used to convert a NULL terminated CHAR8 string to a JSON
+ value. Only object and array represented strings can be converted successfully,
+ since they are the only valid root values of a JSON text for UEFI usage.
+
+ Real number and number with exponent part are not supportted by UEFI.
+
+ Caller needs to cleanup the root value by calling JsonValueFree().
+
+ @param[in] String The NULL terminated CHAR8 string to convert.
+
+ @retval Array JSON value or object JSON value, or NULL when any error occurs.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonLoadString (
+ IN CONST CHAR8* String
+ );
+
+/**
+ Load JSON from a buffer.
+
+ @param[in] Buffer Bufffer to the JSON payload
+ @param[in] BufferLen Length of the buffer
+ @param[in] Flags Flag of loading JSON buffer, the value
+ could be the combination of below flags.
+ - EDKII_JSON_REJECT_DUPLICATES
+ - EDKII_JSON_DISABLE_EOF_CHECK
+ - EDKII_JSON_DECODE_ANY
+ - EDKII_JSON_DECODE_INT_AS_REAL
+ - EDKII_JSON_ALLOW_NUL
+ See below URI for the JSON encoding flags reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html?highlight=json_loadb#decoding
+
+ @param[in,out] Error Pointer EDKII_JSON_ERROR structure
+
+ @retval EDKII_JSON_VALUE NULL means fail to load JSON payload.
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonLoadBuffer (
+ IN CONST CHAR8 *Buffer,
+ IN UINTN BufferLen,
+ IN UINTN Flags,
+ IN OUT EDKII_JSON_ERROR *Error
+ );
+
+/**
+ The reference count is used to track whether a value is still in use or not.
+ When a value is created, it's reference count is set to 1.
+ when the value is no longer needed, the reference count is decremented.
+ When the reference count drops to zero, there are no references left and the
+ value can be destroyed.
+
+ This funciton decrement the reference count of EDKII_JSON_VALUE. As soon as
+ a call to json_decref() drops the reference count to zero, the value is
+ destroyed and it can no longer be used.
+
+ @param[in] JsonValue JSON value
+**/
+VOID
+EFIAPI
+JsonDecreaseReference (
+ IN EDKII_JSON_VALUE JsonValue
+ );
+
+/**
+ The reference count is used to track whether a value is still in use or not.
+ When a value is created, it's reference count is set to 1.
+ If a reference to a value is kept (e.g. a value is stored somewhere for later use),
+ its reference count is incremented.
+
+ This function increment the reference count of json if it's not NULL.
+ Returns EDKII_JSON_VALUE.
+
+ @param[in] JsonValue JSON value
+ @retval EDKII_JSON_VALUE of itself
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonIncreaseReference (
+ IN EDKII_JSON_VALUE JsonValue
+ );
+/**
+ Returns an opaque iterator which can be used to iterate over all key-value pairs
+ in object, or NULL if object is empty
+
+ @param[in] JsonValue JSON value
+**/
+VOID *
+EFIAPI
+JsonObjectIterator (
+ IN EDKII_JSON_VALUE JsonValue
+ );
+
+/**
+ Extract the associated value from iterator.
+
+ @param[in] Iterator Iterator pointer
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonObjectIteratorValue (
+ IN VOID *Iterator
+ );
+
+/**
+ Returns an iterator pointing to the next key-value pair in object after iter,
+ or NULL if the whole object has been iterated through.
+
+ @param[in] JsonValue JSON value
+ @param[in] Iterator Iterator pointer
+ @retval Iterator pointer
+**/
+VOID *
+JsonObjectIteratorNext (
+ IN EDKII_JSON_VALUE JsonValue,
+ IN VOID *Iterator
+ );
+
+/**
+ Returns the json type of this json value
+
+ @param[in] JsonValue JSON value
+ @retval JSON type returned
+**/
+EDKII_JSON_TYPE
+EFIAPI
+JsonGetType(
+ IN EDKII_JSON_VALUE JsonValue
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishContentCodingLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishContentCodingLib.h
new file mode 100644
index 00000000..72d6799b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishContentCodingLib.h
@@ -0,0 +1,78 @@
+/** @file
+ Definitinos of RedfishContentCodingLib.
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CONTENT_CODING_LIB_H_
+#define REDFISH_CONTENT_CODING_LIB_H_
+
+/**
+ This is the function to encode the content use the
+ algorithm indicated in ContentEncodedValue. The naming of
+ ContentEncodedValue is follow HTTP spec or could be a
+ platform-specific value.
+
+ @param[in] ContentEncodedValue HTTP conent encoded value.
+ The value could be one of below
+ or any which is platform-specific.
+ - HTTP_CONTENT_ENCODING_IDENTITY "identity"
+ - HTTP_CONTENT_ENCODING_GZIP "gzip"
+ - HTTP_CONTENT_ENCODING_COMPRESS "compress"
+ - HTTP_CONTENT_ENCODING_DEFLATE "deflate"
+ - HTTP_CONTENT_ENCODING_BROTLI "br"
+ @param[in] OriginalContent Original content.
+ @param[in] OriginalContentLength The length of original content.
+ @param[out] EncodedContentPointer Pointer to receive the encoded content pointer.
+ @param[out] EncodedContentLength Length of encoded content.
+
+ @retval EFI_SUCCESS Content is encoded successfully.
+ @retval EFI_UNSUPPORTED No supported encoding funciton,
+ @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.
+
+**/
+
+EFI_STATUS
+RedfishContentEncode (
+ IN CHAR8 *ContentEncodedValue,
+ IN CHAR8 *OriginalContent,
+ IN UINTN OriginalContentLength,
+ OUT VOID **EncodedContentPointer,
+ OUT UINTN *EncodedLength
+ );
+
+/**
+ This is the function to decode the content use the
+ algorithm indicated in ContentEncodedValue. The naming of
+ ContentEncodedValue is follow HTTP spec or could be a
+ platform-specific value.
+
+ @param[in] ContentDecodedValue HTTP conent decoded value.
+ The value could be one of below
+ or any which is platform-specific.
+ - HTTP_CONTENT_ENCODING_IDENTITY "identity"
+ - HTTP_CONTENT_ENCODING_GZIP "gzip"
+ - HTTP_CONTENT_ENCODING_COMPRESS "compress"
+ - HTTP_CONTENT_ENCODING_DEFLATE "deflate"
+ - HTTP_CONTENT_ENCODING_BROTLI "br"
+ @param[in] ContentPointer Original content.
+ @param[in] ContentLength The length of original content.
+ @param[out] DecodedContentPointer Pointer to receive decoded content pointer.
+ @param[out] DecodedContentLength Length of decoded content.
+
+ @retval EFI_SUCCESS Content is decoded successfully.
+ @retval EFI_UNSUPPORTED No supported decoding funciton,
+ @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.
+
+**/
+EFI_STATUS
+RedfishContentDecode (
+ IN CHAR8 *ContentEncodedValue,
+ IN VOID *ContentPointer,
+ IN UINTN ContentLength,
+ OUT VOID **DecodedContentPointer,
+ OUT UINTN *DecodedLength
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishCredentialLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishCredentialLib.h
new file mode 100644
index 00000000..f4c788f9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishCredentialLib.h
@@ -0,0 +1,91 @@
+/** @file
+ Definitinos of RedfishHostInterfaceDxe driver.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CREDENTIAL_LIB_H_
+#define REDFISH_CREDENTIAL_LIB_H_
+
+#include <Uefi.h>
+
+/**
+ Notification of Exit Boot Service.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL.
+**/
+VOID
+EFIAPI
+LibCredentialExitBootServicesNotify (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This
+);
+
+/**
+ Notification of End of DXe.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL.
+**/
+VOID
+EFIAPI
+LibCredentialEndOfDxeNotify (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This
+);
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user Id and
+ password.
+ - For AuthMethodNone, the UserId and Password could be used for HTTP header authentication
+ as defined by RFC7235.
+ - For AuthMethodRedfishSession, the UserId and Password could be used for Redfish
+ session login as defined by Redfish API specification (DSP0266).
+
+ Callers are responsible for and freeing the returned string storage.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_ACCESS_DENIED SecureBoot is disabled after EndOfDxe.
+ @retval EFI_INVALID_PARAMETER This or AuthMethod or UserId or Password is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resources.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+
+**/
+EFI_STATUS
+EFIAPI
+LibCredentialGetAuthInfo (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+);
+
+/**
+ Notify the Redfish service provide to stop provide configuration service to this platform.
+
+ This function should be called when the platfrom is about to leave the safe environment.
+ It will notify the Redfish service provider to abort all logined session, and prohibit
+ further login with original auth info. GetAuthInfo() will return EFI_UNSUPPORTED once this
+ function is returned.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[in] ServiceStopType Reason of stopping Redfish service.
+
+ @retval EFI_SUCCESS Service has been stoped successfully.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+LibStopRedfishService (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ IN EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE ServiceStopType
+);
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishHostInterfaceLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishHostInterfaceLib.h
new file mode 100644
index 00000000..aec6de38
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishHostInterfaceLib.h
@@ -0,0 +1,52 @@
+/** @file
+ Definitinos of RedfishHostInterfaceDxe driver.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_HOST_INTERFACE_LIB_H_
+#define REDFISH_HOST_INTERFACE_LIB_H_
+
+#include <Uefi.h>
+#include <IndustryStandard/RedfishHostInterface.h>
+#include <IndustryStandard/SmBios.h>
+
+#include <Protocol/Smbios.h>
+
+/**
+ Get platform Redfish host interface device descriptor.
+
+ @param[in] DeviceType Pointer to retrieve device type.
+ @param[out] DeviceDescriptor Pointer to retrieve REDFISH_INTERFACE_DATA, caller has to free
+ this memory using FreePool().
+ @retval EFI_SUCCESS Device descriptor is returned successfully in DeviceDescriptor.
+ @retval EFI_NOT_FOUND No Redfish host interface descriptor provided on this platform.
+ @retval Others Fail to get device descriptor.
+**/
+EFI_STATUS
+RedfishPlatformHostInterfaceDeviceDescriptor (
+ IN UINT8 *DeviceType,
+ OUT REDFISH_INTERFACE_DATA **DeviceDescriptor
+);
+/**
+ Get platform Redfish host interface protocol data.
+ Caller should pass NULL in ProtocolRecord to retrive the first protocol record.
+ Then continuously pass previous ProtocolRecord for retrieving the next ProtocolRecord.
+
+ @param[in, out] ProtocolRecord Pointer to retrieve the first or the next protocol record.
+ caller has to free the new protocol record returned from
+ this function using FreePool().
+ param[in] IndexOfProtocolData The index of protocol data.
+
+ @retval EFI_SUCESS Protocol records are all returned.
+ @retval EFI_NOT_FOUND No more protocol records.
+ @retval Others Fail to get protocol records.
+**/
+EFI_STATUS
+RedfishPlatformHostInterfaceProtocolData (
+ IN OUT MC_HOST_INTERFACE_PROTOCOL_RECORD **ProtocolRecord,
+ IN UINT8 IndexOfProtocolData
+);
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RestExLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RestExLib.h
new file mode 100644
index 00000000..38858145
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RestExLib.h
@@ -0,0 +1,42 @@
+/** @file
+ This library provides help functions for REST EX Protocol.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REST_EX_LIB_H_
+#define REST_EX_LIB_H_
+
+#include <Protocol/RestEx.h>
+
+///
+/// Library class public functions
+///
+
+/**
+ This function allows the caller to create child handle for specific
+ REST server.
+
+ @param[in] Image The image handle used to open service.
+ @param[in] AccessMode Access mode of REST server.
+ @param[in] ConfigType Underlying configuration to communicate with REST server.
+ @param[in] ServiceType REST service type.
+ @param[out] ChildInstanceHandle The handle to receive the create child.
+
+ @retval EFI_SUCCESS Can't create the corresponding REST EX child instance.
+ @retval EFI_INVALID_PARAMETERS Any of input parameters is improper.
+
+**/
+EFI_STATUS
+RestExLibCreateChild (
+ IN EFI_HANDLE Image,
+ IN EFI_REST_EX_SERVICE_ACCESS_MODE AccessMode,
+ IN EFI_REST_EX_CONFIG_TYPE ConfigType,
+ IN EFI_REST_EX_SERVICE_TYPE ServiceType,
+ OUT EFI_HANDLE *ChildInstanceHandle
+);
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Pcd/RestExServiceDevicePath.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Pcd/RestExServiceDevicePath.h
new file mode 100644
index 00000000..1cfc9fd2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Pcd/RestExServiceDevicePath.h
@@ -0,0 +1,38 @@
+/** @file
+ This library defines the UEFI device path data of network device for REST
+ service to decide which should be used as the Redfish host interface.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REST_EX_SERVICE_DEVICE_PATH_H_
+#define REST_EX_SERVICE_DEVICE_PATH_H_
+
+#include <Protocol/DevicePath.h>
+
+typedef enum {
+ DEVICE_PATH_MATCH_MAC_NODE = 1,
+ DEVICE_PATH_MATCH_PCI_NODE = 2,
+ DEVICE_PATH_MATCH_MODE_MAX
+} DEVICE_PATH_MATCH_MODE;
+
+typedef struct {
+ UINT32 DevicePathMatchMode;
+ UINT32 DevicePathNum;
+ //
+ // Example:
+ // {DEVICE_PATH("PciRoot(0)/Pci(0,0)/MAC(005056C00002,0x1)")}
+ // DevicePath will be parsed as below:
+ // {0x02,0x01,0x0c,0x00,0xd0,0x41,0x03,0x0a,0x00,0x00,0x00,0x00,
+ // 0x01,0x01,0x06,0x00,0x00,0x00,
+ // 0x03,0x0b,0x25,0x00,0x00,0x50,0x56,0xc0,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+ // 0x7f,0xff,0x04,0x00}
+ //
+ EFI_DEVICE_PATH_PROTOCOL DevicePath[];
+} REST_EX_SERVICE_DEVICE_PATH_DATA;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishConfigHandler.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishConfigHandler.h
new file mode 100644
index 00000000..297bdb85
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishConfigHandler.h
@@ -0,0 +1,78 @@
+/** @file
+ This file defines the EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL interface.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EDKII_REDFISH_CONFIG_HANDLER_H_
+#define EDKII_REDFISH_CONFIG_HANDLER_H_
+
+typedef struct _EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL;
+
+#define EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL_GUID \
+ { \
+ 0xbc0fe6bb, 0x2cc9, 0x463e, { 0x90, 0x82, 0xfa, 0x11, 0x76, 0xfc, 0x67, 0xde } \
+ }
+
+typedef struct {
+ EFI_HANDLE RedfishServiceRestExHandle; ///< REST EX EFI handle associated with this Redfish service.
+ UINTN RedfishServiceVersion; ///< Redfish service version.
+ CHAR16 *RedfishServiceLocation; ///< Redfish service location.
+ CHAR16 *RedfishServiceUuid; ///< Redfish service UUID.
+ CHAR16 *RedfishServiceOs; ///< Redfish service OS.
+ CHAR16 *RedfishServiceOsVersion; ///< Redfish service OS version.
+ CHAR16 *RedfishServiceProduct; ///< Redfish service product name.
+ CHAR16 *RedfishServiceProductVer; ///< Redfish service product version.
+ BOOLEAN RedfishServiceUseHttps; ///< Redfish service uses HTTPS.
+} REDFISH_CONFIG_SERVICE_INFORMATION;
+
+/**
+ Initialize a configure handler of EDKII Redfish feature driver.
+
+ This function will be called by the EDKII Redfish config handler driver to
+ initialize the configure handler of each EDKII Redfish feature driver.
+
+ @param[in] This Pointer to EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL instance.
+ @param[in] RedfishServiceinfo Redfish service information.
+
+ @retval EFI_SUCCESS The handler has been initialized successfully.
+ @retval EFI_DEVICE_ERROR Failed to create or configure the REST EX protocol instance.
+ @retval EFI_ALREADY_STARTED This handler has already been initialized.
+ @retval Other Error happens during the initialization.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL_INIT) (
+ IN EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *This,
+ IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishServiceinfo
+ );
+
+/**
+ Stop a Redfish configure handler of EDKII Redfish feature driver.
+
+ @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.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL_STOP) (
+ IN EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *This
+ );
+
+struct _EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL {
+ EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL_INIT Init;
+ EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL_STOP Stop;
+};
+
+
+extern EFI_GUID gdkIIRedfishConfigHandlerProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishCredential.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishCredential.h
new file mode 100644
index 00000000..40a4231d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishCredential.h
@@ -0,0 +1,101 @@
+/** @file
+ This file defines the EDKII_REDFISH_CREDENTIAL_PROTOCOL interface.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EDKII_REDFISH_CREDENTIAL_H_
+#define EDKII_REDFISH_CREDENTIAL_H_
+
+typedef struct _EDKII_REDFISH_CREDENTIAL_PROTOCOL EDKII_REDFISH_CREDENTIAL_PROTOCOL;
+
+#define EDKII_REDFISH_CREDENTIAL_PROTOCOL_GUID \
+ { \
+ 0x8804377, 0xaf7a, 0x4496, { 0x8a, 0x7b, 0x17, 0x59, 0x0, 0xe9, 0xab, 0x46 } \
+ }
+
+typedef enum {
+ AuthMethodNone, ///< No authentication is required.
+ AuthMethodHttpBasic, ///< Basic authentication is required.
+ AuthMethodRedfishSession, ///< Session authentication is required.
+ AuthMethodMax
+} EDKII_REDFISH_AUTH_METHOD;
+
+typedef enum {
+ ServiceStopTypeNone = 0, ///< Stop Redfsih service without reason.
+ ServiceStopTypeSecureBootDisabled, ///< Stop Redfsih service becasue EFI
+ ///< Secure Boot is disabled.
+ ServiceStopTypeExitBootService, ///< Stop Redfsih service becasue existing
+ ///< Boot Service.
+ ServiceStopTypeMax
+} EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE;
+
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user Id and
+ password.
+ - For AuthMethodNone, the UserId and Password could be used for HTTP header authentication
+ as defined by RFC7235.
+ - For AuthMethodRedfishSession, the UserId and Password could be used for Redfish
+ session login as defined by Redfish API specification (DSP0266).
+
+ Callers are responsible for and freeing the returned string storage.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_ACCESS_DENIED SecureBoot is disabled after EndOfDxe.
+ @retval EFI_INVALID_PARAMETER This or AuthMethod or UserId or Password is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resources.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REDFISH_CREDENTIAL_PROTOCOL_GET_AUTH_INFO) (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+ );
+
+/**
+ Notify the Redfish service provide to stop provide configuration service to this platform.
+
+ This function should be called when the platfrom is about to leave the safe environment.
+ It will notify the Redfish service provider to abort all logined session, and prohibit
+ further login with original auth info. GetAuthInfo() will return EFI_UNSUPPORTED once this
+ function is returned.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[in] ServiceStopType Reason of stopping Redfish service.
+
+ @retval EFI_SUCCESS Service has been stoped successfully.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval Others Some error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REDFISH_CREDENTIAL_PROTOCOL_STOP_SERVICE) (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ IN EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE ServiceStopType
+ );
+
+struct _EDKII_REDFISH_CREDENTIAL_PROTOCOL {
+ EDKII_REDFISH_CREDENTIAL_PROTOCOL_GET_AUTH_INFO GetAuthInfo;
+ EDKII_REDFISH_CREDENTIAL_PROTOCOL_STOP_SERVICE StopService;
+};
+
+extern EFI_GUID gEdkIIRedfishCredentialProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.c
new file mode 100644
index 00000000..33afadb3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.c
@@ -0,0 +1,421 @@
+/** @file
+ UCS2 to UTF8 manipulation library.
+
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseUcs2Utf8Lib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+/**
+ Since each UCS2 character can be represented by 1-3 UTF8 encoded characters,
+ this function is used to retrieve the UTF8 encoding size for a UCS2 character.
+
+ @param[in] Utf8Buffer The buffer for UTF8 encoded data.
+
+ @retval Return the size of UTF8 encoding string or 0 if it is not for
+ UCS2 format.
+
+**/
+UINT8
+GetUTF8SizeForUCS2 (
+ IN CHAR8 *Utf8Buffer
+ )
+{
+ CHAR8 TempChar;
+ UINT8 Utf8Size;
+
+ ASSERT (Utf8Buffer != NULL);
+
+ TempChar = *Utf8Buffer;
+ if ((TempChar & 0xF0) == 0xF0) {
+
+ //
+ // This format is not for UCS2.
+ //
+ return 0;
+ }
+
+ Utf8Size = 1;
+ if ((TempChar & 0x80) == 0x80) {
+ if ((TempChar & 0xC0) == 0xC0) {
+
+ Utf8Size ++;
+ if ((TempChar & 0xE0) == 0xE0) {
+
+ Utf8Size ++;
+ }
+ }
+ }
+
+ return Utf8Size;
+}
+
+/**
+ Since each UCS2 character can be represented by the format: \uXXXX, this function
+ is used to retrieve the UCS2 character from a Unicode format.
+ Call MUST make sure there are at least 6 Bytes in the input UTF8 buffer.
+
+ @param[in] Utf8Buffer The buffer for UTF8 encoded data.
+ @param[out] Ucs2Char The converted UCS2 character.
+
+ @retval EFI_INVALID_PARAMETER Non-Ascii characters found in the hexadecimal
+ digits string, and can't be converted to a UCS2
+ character.
+ @retval EFI_SUCCESS The UCS2 character has been retrieved.
+
+**/
+EFI_STATUS
+GetUCS2CharByFormat (
+ IN CHAR8 *Utf8Buffer,
+ OUT CHAR16 *Ucs2Char
+ )
+{
+ UINT8 Num1;
+ UINT8 Num2;
+ UINT8 Index;
+ CHAR8 Ucs2CharFormat[UNICODE_FORMAT_CHAR_SIZE]; /// two Hexadecimal digits Ascii string, like "3F"
+
+ for (Index = 0; Index < 4; Index ++) {
+ if ((*(Utf8Buffer + 2 + Index) & 0x80) != 0x00) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ ZeroMem (Ucs2CharFormat, UNICODE_FORMAT_CHAR_SIZE);
+
+ //
+ // Get the First Number, Offset is 2
+ //
+ CopyMem (Ucs2CharFormat, Utf8Buffer + 2, UNICODE_FORMAT_CHAR_LEN);
+ Num1 = (UINT8) AsciiStrHexToUintn (Ucs2CharFormat);
+
+ //
+ // Get the Second Number, Offset is 4
+ //
+ CopyMem (Ucs2CharFormat, Utf8Buffer + 4, UNICODE_FORMAT_CHAR_LEN);
+ Num2 = (UINT8) AsciiStrHexToUintn (Ucs2CharFormat);
+
+ //
+ // Ucs2Char is Little-Endian
+ //
+ *((CHAR8 *) Ucs2Char) = Num2;
+ *(((CHAR8 *) Ucs2Char) + 1) = Num1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Convert a UCS2 character to UTF8 encoding string.
+
+ @param[in] Ucs2Char The provided UCS2 character.
+ @param[out] Utf8Buffer The converted UTF8 encoded data.
+
+ @retval Return the size of UTF8 encoding data for this UCS2 character.
+
+**/
+UINT8
+UCS2CharToUTF8 (
+ IN CHAR16 Ucs2Char,
+ OUT CHAR8 *Utf8Buffer
+ )
+{
+ UINT16 Ucs2Number;
+
+ ASSERT (Utf8Buffer != NULL);
+
+ Ucs2Number = (UINT16) Ucs2Char;
+ if (Ucs2Number <= 0x007F) {
+
+ //
+ // UTF8 format: 0xxxxxxx
+ //
+ *Utf8Buffer = Ucs2Char & 0x7F;
+ return 1;
+
+ } else if (Ucs2Number >= 0x0080 && Ucs2Number <= 0x07FF) {
+
+ //
+ // UTF8 format: 110xxxxx 10xxxxxx
+ //
+ *(Utf8Buffer + 1) = (Ucs2Char & 0x3F) | 0x80;
+ *Utf8Buffer = ((Ucs2Char >> 6) & 0x1F) | 0xC0;
+ return 2;
+
+ } else { /// Ucs2Number >= 0x0800 && Ucs2Number <= 0xFFFF
+
+ //
+ // UTF8 format: 1110xxxx 10xxxxxx 10xxxxxx
+ //
+ *(Utf8Buffer + 2) = (Ucs2Char & 0x3F) | 0x80;
+ *(Utf8Buffer + 1) = ((Ucs2Char >> 6) & 0x3F) | 0x80;
+ *Utf8Buffer = ((Ucs2Char >> 12) & 0x0F) | 0xE0;
+ return 3;
+ }
+}
+
+/**
+ Convert a UTF8 encoded data to a UCS2 character.
+
+ @param[in] Utf8Buffer The provided UTF8 encoded data.
+ @param[out] Ucs2Char The converted UCS2 character.
+
+ @retval EFI_INVALID_PARAMETER The UTF8 encoded string is not valid or
+ not for UCS2 character.
+ @retval EFI_SUCCESS The converted UCS2 character.
+
+**/
+EFI_STATUS
+UTF8ToUCS2Char (
+ IN CHAR8 *Utf8Buffer,
+ OUT CHAR16 *Ucs2Char
+ )
+{
+ UINT8 Utf8Size;
+ CHAR8 *Ucs2Buffer;
+ CHAR8 TempChar1;
+ CHAR8 TempChar2;
+ CHAR8 TempChar3;
+
+ ASSERT (Utf8Buffer != NULL && Ucs2Char != NULL);
+ ZeroMem (Ucs2Char, sizeof (CHAR16));
+ Ucs2Buffer = (CHAR8 *) Ucs2Char;
+
+ Utf8Size = GetUTF8SizeForUCS2 (Utf8Buffer);
+ switch (Utf8Size) {
+
+ case 1:
+
+ //
+ // UTF8 format: 0xxxxxxx
+ //
+ TempChar1 = *Utf8Buffer;
+ if ((TempChar1 & 0x80) != 0x00) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Ucs2Buffer = TempChar1;
+ *(Ucs2Buffer + 1) = 0;
+ break;
+
+ case 2:
+
+ //
+ // UTF8 format: 110xxxxx 10xxxxxx
+ //
+ TempChar1 = *Utf8Buffer;
+ if ((TempChar1 & 0xE0) != 0xC0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TempChar2 = *(Utf8Buffer + 1);
+ if ((TempChar2 & 0xC0) != 0x80) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Ucs2Buffer = (TempChar1 << 6) + (TempChar2 & 0x3F);
+ *(Ucs2Buffer + 1) = (TempChar1 >> 2) & 0x07;
+ break;
+
+ case 3:
+
+ //
+ // UTF8 format: 1110xxxx 10xxxxxx 10xxxxxx
+ //
+ TempChar1 = *Utf8Buffer;
+ if ((TempChar1 & 0xF0) != 0xE0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TempChar2 = *(Utf8Buffer + 1);
+ if ((TempChar2 & 0xC0) != 0x80) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TempChar3 = *(Utf8Buffer + 2);
+ if ((TempChar3 & 0xC0) != 0x80) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Ucs2Buffer = (TempChar2 << 6) + (TempChar3 & 0x3F);
+ *(Ucs2Buffer + 1) = (TempChar1 << 4) + ((TempChar2 >> 2) & 0x0F);
+
+ break;
+
+ default:
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Convert a UCS2 string to a UTF8 encoded string.
+
+ @param[in] Ucs2Str The provided UCS2 string.
+ @param[out] Utf8StrAddr The converted UTF8 string address. Caller
+ is responsible for Free this string.
+
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES System runs out of resources.
+ @retval EFI_SUCCESS The UTF8 encoded string has been converted.
+
+**/
+EFI_STATUS
+UCS2StrToUTF8 (
+ IN CHAR16 *Ucs2Str,
+ OUT CHAR8 **Utf8StrAddr
+ )
+{
+ UINTN Ucs2StrIndex;
+ UINTN Ucs2StrLength;
+ CHAR8 *Utf8Str;
+ UINTN Utf8StrLength;
+ UINTN Utf8StrIndex;
+ CHAR8 Utf8Buffer[UTF8_BUFFER_FOR_UCS2_MAX_SIZE];
+ UINT8 Utf8BufferSize;
+
+ if (Ucs2Str == NULL || Utf8StrAddr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ucs2StrLength = StrLen (Ucs2Str);
+ Utf8StrLength = 0;
+
+ for (Ucs2StrIndex = 0; Ucs2StrIndex < Ucs2StrLength; Ucs2StrIndex ++) {
+
+ ZeroMem (Utf8Buffer, sizeof (Utf8Buffer));
+ Utf8BufferSize = UCS2CharToUTF8 (Ucs2Str[Ucs2StrIndex], Utf8Buffer);
+ Utf8StrLength += Utf8BufferSize;
+ }
+
+ Utf8Str = AllocateZeroPool (Utf8StrLength + 1);
+ if (Utf8Str == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Utf8StrIndex = 0;
+ for (Ucs2StrIndex = 0; Ucs2StrIndex < Ucs2StrLength; Ucs2StrIndex ++) {
+
+ ZeroMem (Utf8Buffer, sizeof (Utf8Buffer));
+ Utf8BufferSize = UCS2CharToUTF8 (Ucs2Str[Ucs2StrIndex], Utf8Buffer);
+
+ CopyMem (Utf8Str + Utf8StrIndex, Utf8Buffer, Utf8BufferSize);
+ Utf8StrIndex += Utf8BufferSize;
+ }
+
+ Utf8Str[Utf8StrIndex] = '\0';
+ *Utf8StrAddr = Utf8Str;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Convert a UTF8 encoded string to a UCS2 string.
+
+ @param[in] Utf8Str The provided UTF8 encoded string.
+ @param[out] Ucs2StrAddr The converted UCS2 string address. Caller
+ is responsible for Free this string.
+
+ @retval EFI_INVALID_PARAMETER The UTF8 encoded string is not valid to
+ convert to UCS2 string.
+ One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES System runs out of resources.
+ @retval EFI_SUCCESS The UCS2 string has been converted.
+
+**/
+EFI_STATUS
+UTF8StrToUCS2 (
+ IN CHAR8 *Utf8Str,
+ OUT CHAR16 **Ucs2StrAddr
+ )
+{
+ EFI_STATUS Status;
+ UINTN Utf8StrIndex;
+ UINTN Utf8StrLength;
+ UINTN Ucs2StrIndex;
+ UINT8 Utf8BufferSize;
+ CHAR16 *Ucs2StrTemp;
+
+ if (Utf8Str == NULL || Ucs2StrAddr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // It is not an Ascii string, calculate string length.
+ //
+ Utf8StrLength = 0;
+ while (*(Utf8Str + Utf8StrLength) != '\0') {
+ Utf8StrLength ++;
+ }
+
+ //
+ // UCS2 string shall not be longer than the UTF8 string.
+ //
+ Ucs2StrTemp = AllocateZeroPool ((Utf8StrLength + 1) * sizeof (CHAR16));
+ if (Ucs2StrTemp == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Utf8StrIndex = 0;
+ Ucs2StrIndex = 0;
+ while (Utf8Str[Utf8StrIndex] != '\0') {
+
+ if (CompareMem (Utf8Str + Utf8StrIndex, "\\u", 2) == 0 &&
+ Utf8StrLength - Utf8StrIndex >= UNICODE_FORMAT_LEN) {
+
+ Status = GetUCS2CharByFormat (Utf8Str + Utf8StrIndex, Ucs2StrTemp + Ucs2StrIndex);
+ if (!EFI_ERROR (Status)) {
+
+ Utf8StrIndex += UNICODE_FORMAT_LEN;
+ Ucs2StrIndex ++;
+ } else {
+
+ StrCpyS (Ucs2StrTemp + Ucs2StrIndex, 3, L"\\u");
+
+ Ucs2StrIndex += 2;
+ Utf8StrIndex += 2;
+ }
+ } else {
+
+ Utf8BufferSize = GetUTF8SizeForUCS2 (Utf8Str + Utf8StrIndex);
+ if (Utf8BufferSize == 0 || Utf8StrLength - Utf8StrIndex < Utf8BufferSize) {
+
+ FreePool (Ucs2StrTemp);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = UTF8ToUCS2Char (Utf8Str + Utf8StrIndex, Ucs2StrTemp + Ucs2StrIndex);
+ if (EFI_ERROR (Status)) {
+
+ FreePool (Ucs2StrTemp);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ucs2StrIndex ++;
+ Utf8StrIndex += Utf8BufferSize;
+ }
+ }
+
+ *Ucs2StrAddr = AllocateZeroPool ((Ucs2StrIndex + 1) * sizeof (CHAR16));
+ if (*Ucs2StrAddr == NULL) {
+
+ FreePool (Ucs2StrTemp);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StrCpyS (*Ucs2StrAddr, Ucs2StrIndex + 1, Ucs2StrTemp);
+ *(*Ucs2StrAddr + Ucs2StrIndex) = L'\0';
+ FreePool (Ucs2StrTemp);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf
new file mode 100644
index 00000000..6b1c3151
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf
@@ -0,0 +1,31 @@
+## @file
+# UCS2 to UTF8 manipulation library.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = BaseUcs2Utf8Lib
+ FILE_GUID = 536646C3-46D0-4B12-ABC4-CDE1A33B5256
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = Ucs2Utf8Lib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ BaseUcs2Utf8Lib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.c
new file mode 100644
index 00000000..4c76166d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.c
@@ -0,0 +1,166 @@
+/** @file
+ This library provides help functions for REST EX Protocol.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/Http.h>
+#include <Protocol/RestEx.h>
+
+#define REST_EX_CONFIG_DATA_LEN_UNKNOWN 0xff
+
+/**
+ This function allows the caller to create child handle for specific
+ REST server.
+
+ @param[in] Image The image handle used to open service.
+ @param[in] AccessMode Access mode of REST server.
+ @param[in] ConfigType Underlying configuration to communicate with REST server.
+ @param[in] ServiceType REST service type.
+ @param[out] ChildInstanceHandle The handle to receive the create child.
+
+ @retval EFI_SUCCESS Can't create the corresponding REST EX child instance.
+ @retval EFI_INVALID_PARAMETERS Any of input parameters is improper.
+
+**/
+EFI_STATUS
+RestExLibCreateChild (
+ IN EFI_HANDLE Image,
+ IN EFI_REST_EX_SERVICE_ACCESS_MODE AccessMode,
+ IN EFI_REST_EX_CONFIG_TYPE ConfigType,
+ IN EFI_REST_EX_SERVICE_TYPE ServiceType,
+ OUT EFI_HANDLE *ChildInstanceHandle
+)
+{
+ EFI_STATUS Status;
+ UINTN NoBuffer;
+ EFI_HANDLE *Handle;
+ EFI_HANDLE ChildHandle;
+ EFI_REST_EX_PROTOCOL *RestEx;
+ EFI_REST_EX_SERVICE_INFO *RestExServiceInfo;
+ UINT8 LenOfConfig;
+
+ if (Image == NULL ||
+ AccessMode >= EfiRestExServiceModeMax ||
+ ConfigType >= EfiRestExConfigTypeMax ||
+ ServiceType >= EfiRestExServiceTypeMax ||
+ ChildInstanceHandle == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ChildInstanceHandle = NULL;
+ //
+ // Locate all REST EX binding service.
+ //
+ Handle = NULL;
+ NoBuffer = 0;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiRestExServiceBindingProtocolGuid,
+ NULL,
+ &NoBuffer,
+ &Handle
+ );
+ if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
+ return Status;
+ }
+ Handle = (EFI_HANDLE *)AllocateZeroPool (sizeof(EFI_HANDLE) * NoBuffer);
+ if (Handle == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiRestExServiceBindingProtocolGuid,
+ NULL,
+ &NoBuffer,
+ &Handle
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Handle);
+ return Status;
+ }
+
+ //
+ // Search for the proper REST EX instance.
+ //
+ while (NoBuffer != 0) {
+ ChildHandle = NULL;
+ Status = NetLibCreateServiceChild (
+ *(Handle + (NoBuffer - 1)),
+ Image,
+ &gEfiRestExServiceBindingProtocolGuid,
+ &ChildHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiRestExProtocolGuid,
+ (VOID **)&RestEx,
+ Image,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Get the information of REST service provided by this EFI REST EX driver
+ //
+ Status = RestEx->GetService (
+ RestEx,
+ &RestExServiceInfo
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ //
+ // Check REST EX property.
+ //
+ switch (ConfigType) {
+ case EfiRestExConfigHttp:
+ LenOfConfig = sizeof (EFI_REST_EX_HTTP_CONFIG_DATA);
+ break;
+
+ case EfiRestExConfigUnspecific:
+ LenOfConfig = REST_EX_CONFIG_DATA_LEN_UNKNOWN;
+ break;
+
+ default:
+ goto ON_ERROR;
+ }
+ if (RestExServiceInfo->EfiRestExServiceInfoV10.RestServiceAccessMode != AccessMode ||
+ RestExServiceInfo->EfiRestExServiceInfoV10.RestServiceType != ServiceType ||
+ RestExServiceInfo->EfiRestExServiceInfoV10.RestExConfigType != ConfigType ||
+ ((LenOfConfig != REST_EX_CONFIG_DATA_LEN_UNKNOWN) && (RestExServiceInfo->EfiRestExServiceInfoV10.RestExConfigDataLength != LenOfConfig))) {
+ goto ON_ERROR;
+ }
+ }
+ //
+ // This is proper REST EX instance.
+ //
+ *ChildInstanceHandle = ChildHandle;
+ FreePool (Handle);
+ return EFI_SUCCESS;
+
+ON_ERROR:;
+ NetLibDestroyServiceChild (
+ *(Handle + (NoBuffer - 1)),
+ Image,
+ &gEfiRestExServiceBindingProtocolGuid,
+ ChildHandle
+ );
+ NoBuffer --;
+ };
+ FreePool (Handle);
+ return EFI_NOT_FOUND;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.inf
new file mode 100644
index 00000000..416dc630
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Library for REST EX Protocol
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = DxeRestExLib
+ FILE_GUID = E9CBF727-8AF3-4602-9DBD-A3942869B5AE
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RestExLib | DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC RISCV64
+#
+
+[Sources.common]
+ DxeRestExLib.c
+
+[Packages]
+ NetworkPkg/NetworkPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ NetLib
+ PrintLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gEfiRestExServiceBindingProtocolGuid ## PROTOCOL ALWAYS_CONSUMED
+ gEfiRestExProtocolGuid ## PROTOCOL ALWAYS_CONSUMED
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.c
new file mode 100644
index 00000000..c05ba965
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.c
@@ -0,0 +1,983 @@
+/** @file
+ APIs for JSON operations. The fuctions provided by this library are the
+ wrapper to native open source jansson library. See below document for
+ the API reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html
+
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+#include <Library/JsonLib.h>
+#include <Library/BaseUcs2Utf8Lib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "jansson.h"
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON array,
+ or NULL on error. Initially, the array is empty.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @retval The created JSON value which contains a JSON array or NULL if intial a JSON array
+ is failed.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitArray (
+ VOID
+ )
+{
+ return (EDKII_JSON_VALUE)json_array();
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON object,
+ or NULL on error. Initially, the object is empty.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @retval The created JSON value which contains a JSON object or NULL if intial a JSON object
+ is failed.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitObject (
+ VOID
+ )
+{
+ return (EDKII_JSON_VALUE)json_object();
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON string,
+ or NULL on error.
+
+ The input string must be NULL terminated Ascii format, non-Ascii characters will
+ be processed as an error. Unicode characters can also be represented by Ascii string
+ as the format: \u + 4 hexadecimal digits, like \u3E5A, or \u003F.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] String The Ascii string to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON string or NULL. Select a
+ Getter API for a specific encoding format.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitAsciiString (
+ IN CONST CHAR8 *String
+ )
+{
+ UINTN Index;
+
+ if (String == NULL) {
+ return NULL;
+ }
+
+ Index = 0;
+ while (*(String + Index) != '\0') {
+ if (((*(String + Index)) & 0x80) != 0x00) {
+ return NULL;
+ }
+
+ Index++;
+ }
+
+ return (EDKII_JSON_VALUE)json_string (String);
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON string,
+ or NULL on error.
+
+ The input must be a NULL terminated UCS2 format Unicode string.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] String The Unicode string to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON string or NULL. Select a
+ Getter API for a specific encoding format.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitUnicodeString (
+ IN CHAR16 *String
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *Utf8Str;
+
+ if (String == NULL) {
+ return NULL;
+ }
+
+ Utf8Str = NULL;
+ Status = UCS2StrToUTF8 (String, &Utf8Str);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ return (EDKII_JSON_VALUE)json_string (Utf8Str);
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON integer,
+ or NULL on error.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] Value The integer to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON number or NULL.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitNumber (
+ IN INT64 Value
+ )
+{
+ return (EDKII_JSON_VALUE)json_integer (Value);
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON boolean,
+ or NULL on error.
+
+ Boolean JSON value is kept as static value, and no need to do any cleanup work.
+
+ @param[in] Value The boolean value to initialize.
+
+ @retval The created JSON value which contains a JSON boolean or NULL.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitBoolean (
+ IN BOOLEAN Value
+ )
+{
+ return (EDKII_JSON_VALUE)json_boolean (Value);
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON NULL,
+ or NULL on error.
+
+ NULL JSON value is kept as static value, and no need to do any cleanup work.
+
+ @retval The created NULL JSON value.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitNull (
+ VOID
+ )
+{
+ return (EDKII_JSON_VALUE)json_null();
+}
+
+/**
+ The function is used to decrease the reference count of a JSON value by one, and once
+ this reference count drops to zero, the value is destroyed and it can no longer be used.
+ If this destroyed value is object type or array type, reference counts for all containing
+ JSON values will be decreased by 1. Boolean JSON value and NULL JSON value won't be destroyed
+ since they are static values kept in memory.
+
+ Reference Count Strategy: BaseJsonLib uses this strategy to track whether a value is still
+ in use or not. When a value is created, it's reference count is set to 1. If a reference to a
+ value is kept for use, its reference count is incremented, and when the value is no longer
+ needed, the reference count is decremented. When the reference count drops to zero, there are
+ no references left, and the value can be destroyed.
+
+ The given JSON value maybe NULL and not causing any problem. Just output the debug message
+ to inform caller the NULL value is passed in.
+
+ @param[in] Json The JSON value to be freed. json_decref may return without any
+ changes if Json is NULL.
+
+**/
+VOID
+EFIAPI
+JsonValueFree (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ json_decref((json_t *)Json);
+}
+
+/**
+ The function is used to create a fresh copy of a JSON value, and all child values are deep
+ copied in a recursive fashion. It should be called when this JSON value might be modified
+ in later use, but the original still wants to be used in somewhere else.
+
+ Reference counts of the returned root JSON value and all child values will be set to 1, and
+ caller needs to cleanup the root value by calling JsonValueFree().
+
+ * Note: Since this function performs a copy from bottom to up, too many calls may cause some
+ performance issues, user should avoid unnecessary calls to this function unless it is really
+ needed.
+
+ @param[in] Json The JSON value to be cloned.
+
+ @retval Return the cloned JSON value, or NULL on error.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueClone (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return (EDKII_JSON_VALUE)json_deep_copy ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON array.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON array.
+ @retval FALSE The JSON value doesn't contain a JSON array.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsArray (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_array ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON object.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON object.
+ @retval FALSE The JSON value doesn't contain a JSON object.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsObject (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_object ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON Value contains a string, Ascii or
+ Unicode format is not differentiated.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON string.
+ @retval FALSE The JSON value doesn't contain a JSON string.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsString (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_string ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON number.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value is contains JSON number.
+ @retval FALSE The JSON value doesn't contain a JSON number.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsNumber (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_integer ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON boolean.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON boolean.
+ @retval FALSE The JSON value doesn't contain a JSON boolean.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsBoolean (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_boolean ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON NULL.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON NULL.
+ @retval FALSE The JSON value doesn't contain a JSON NULL.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsNull (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_null ((json_t *) Json);
+}
+
+/**
+ The function is used to retrieve the associated array in an array type JSON value.
+
+ Any changes to the returned array will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated array in JSON value or NULL.
+
+**/
+EDKII_JSON_ARRAY
+EFIAPI
+JsonValueGetArray (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ if (Json == NULL || !JsonValueIsArray (Json)) {
+ return NULL;
+ }
+
+ return (EDKII_JSON_ARRAY)Json;
+}
+
+/**
+ The function is used to retrieve the associated object in an object type JSON value.
+
+ Any changes to the returned object will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated object in JSON value or NULL.
+
+**/
+EDKII_JSON_OBJECT
+EFIAPI
+JsonValueGetObject (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ if (Json == NULL || !JsonValueIsObject (Json)) {
+ return NULL;
+ }
+
+ return (EDKII_JSON_OBJECT)Json;
+}
+
+/**
+ The function is used to retrieve the associated Ascii string in a string type JSON value.
+
+ Any changes to the returned string will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Ascii string in JSON value or NULL.
+
+**/
+CONST CHAR8 *
+EFIAPI
+JsonValueGetAsciiString (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ CONST CHAR8 *AsciiStr;
+ UINTN Index;
+
+ AsciiStr = json_string_value ((json_t *) Json);
+ if (AsciiStr == NULL) {
+ return NULL;
+ }
+
+ Index = 0;
+ while (*(AsciiStr + Index) != '\0') {
+ if (((*(AsciiStr + Index)) & 0x80) != 0x00) {
+ return NULL;
+ }
+
+ Index++;
+ }
+
+ return AsciiStr;
+}
+
+/**
+ The function is used to retrieve the associated Unicode string in a string type JSON value.
+
+ Caller can do any changes to the returned string without any impact to the original JSON
+ value, and caller needs to free the returned string using FreePool().
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Unicode string in JSON value or NULL.
+
+**/
+CHAR16*
+EFIAPI
+JsonValueGetUnicodeString (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ EFI_STATUS Status;
+ CONST CHAR8 *Utf8Str;
+ CHAR16 *Ucs2Str;
+
+ Utf8Str = json_string_value ((json_t *) Json);
+ if (Utf8Str == NULL) {
+ return NULL;
+ }
+
+ Status = UTF8StrToUCS2 ((CHAR8*)Utf8Str, &Ucs2Str);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ return Ucs2Str;
+}
+
+/**
+ The function is used to retrieve the associated integer in a number type JSON value.
+
+ The input JSON value should not be NULL or contain no JSON number, otherwise it will
+ ASSERT() and return 0.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated number in JSON value.
+
+**/
+INT64
+EFIAPI
+JsonValueGetNumber (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ ASSERT (Json != NULL && JsonValueIsNumber (Json));
+ if (Json == NULL || !JsonValueIsNumber (Json)) {
+ return 0;
+ }
+
+ return json_integer_value ((json_t *) Json);
+}
+
+/**
+ The function is used to retrieve the associated boolean in a boolean type JSON value.
+
+ The input JSON value should not be NULL or contain no JSON boolean, otherwise it will
+ ASSERT() and return FALSE.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated value of JSON boolean.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueGetBoolean (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ ASSERT (Json != NULL && JsonValueIsBoolean (Json));
+ if (Json == NULL || !JsonValueIsBoolean (Json)) {
+ return FALSE;
+ }
+
+ return json_is_true ((json_t *) Json);
+}
+
+/**
+ The function is used to retrieve the associated string in a string type JSON value.
+
+ Any changes to the returned string will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Ascii string in JSON value or NULL on errors.
+
+**/
+CONST CHAR8*
+EFIAPI
+JsonValueGetString (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_string_value ((const json_t *)Json);
+}
+
+/**
+ The function is used to get the number of elements in a JSON object, or 0 if it is NULL or
+ not a JSON object.
+
+ @param[in] JsonObject The provided JSON object.
+
+ @retval Return the number of elements in this JSON object or 0.
+
+**/
+UINTN
+EFIAPI
+JsonObjectSize (
+ IN EDKII_JSON_OBJECT JsonObject
+ )
+{
+ return json_object_size ((json_t *) JsonObject);
+}
+
+/**
+ The function is used to enumerate all keys in a JSON object.
+
+ Caller should be responsible to free the returned key array reference using
+ FreePool(). But contained keys are read only and must not be modified or freed.
+
+ @param[in] JsonObj The provided JSON object for enumeration.
+ @param[out] KeyCount The count of keys in this JSON object.
+
+ @retval Return an array of the enumerated keys in this JSON object or NULL if
+ JsonObj is not an JSON object, key count is zero or on other errors.
+
+**/
+CHAR8**
+JsonObjectGetKeys (
+ IN EDKII_JSON_OBJECT JsonObj,
+ OUT UINTN *KeyCount
+ )
+{
+
+ UINTN Index;
+ CONST CHAR8 **KeyArray;
+ CONST CHAR8 *Key;
+ EDKII_JSON_VALUE Value;
+
+ if (JsonObj == NULL || KeyCount == NULL) {
+ return NULL;
+ }
+
+ Index = 0;
+ json_object_foreach(JsonObj, Key, Value) {
+ Index++;
+ }
+ if (Index == 0) {
+ *KeyCount = 0;
+ return NULL;
+ }
+
+ *KeyCount = Index;
+ KeyArray = (CONST CHAR8 **) AllocateZeroPool (*KeyCount * sizeof (CHAR8 *));
+ if (KeyArray == NULL) {
+ return NULL;
+ }
+
+ Key = NULL;
+ Value = NULL;
+ Index = 0;
+ json_object_foreach((json_t *) JsonObj, Key, Value) {
+ KeyArray[Index] = Key;
+ Index++;
+ }
+
+ return (CHAR8 **)KeyArray;
+}
+
+/**
+ The function is used to get a JSON value corresponding to the input key from a JSON object.
+
+ It only returns a reference to this value and any changes on this value will impact the
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to
+ use.
+
+ Input key must be a valid NULL terminated UTF8 encoded string. NULL will be returned when
+ Key-Value is not found in this JSON object.
+
+ @param[in] JsonObj The provided JSON object.
+ @param[in] Key The key of the JSON value to be retrieved.
+
+ @retval Return the corresponding JSON value to key, or NULL on error.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonObjectGetValue (
+ IN CONST EDKII_JSON_OBJECT JsonObj,
+ IN CONST CHAR8 *Key
+ )
+{
+ return (EDKII_JSON_VALUE)json_object_get ((const json_t *)JsonObj, (const char *)Key);
+}
+
+/**
+ The function is used to set a JSON value corresponding to the input key from a JSON object,
+ and the reference count of this value will be increased by 1.
+
+ Input key must be a valid NULL terminated UTF8 encoded string. If there already is a value for
+ this key, this key will be assigned to the new JSON value. The old JSON value will be removed
+ from this object and thus its' reference count will be decreased by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonObj The provided JSON object.
+ @param[in] Key The key of the JSON value to be set.
+ @param[in] Json The JSON value to set to this JSON object mapped by key.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS The JSON value has been set to this JSON object.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonObjectSetValue (
+ IN EDKII_JSON_OBJECT JsonObj,
+ IN CONST CHAR8 *Key,
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ if (json_object_set ((json_t *) JsonObj, Key, (json_t *) Json) != 0) {
+ return EFI_ABORTED;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ The function is used to get the number of elements in a JSON array. Returns or 0 if JsonArray
+ is NULL or not a JSON array.
+
+ @param[in] JsonArray The provided JSON array.
+
+ @retval Return the number of elements in this JSON array or 0.
+
+**/
+UINTN
+EFIAPI
+JsonArrayCount (
+ IN EDKII_JSON_ARRAY JsonArray
+ )
+{
+ return json_array_size ((json_t *) JsonArray);
+}
+
+/**
+ The function is used to return the JSON value in the array at position index. The valid range
+ for this index is from 0 to the return value of JsonArrayCount() minus 1.
+
+ It only returns a reference to this value and any changes on this value will impact the
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to
+ use.
+
+ If this array is NULL or not a JSON array, or if index is out of range, NULL will be returned.
+
+ @param[in] JsonArray The provided JSON Array.
+
+ @retval Return the JSON value located in the Index position or
+ NULL if JsonArray is not an array or no items in the array.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonArrayGetValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN UINTN Index
+ )
+{
+ return (EDKII_JSON_VALUE)json_array_get ((json_t *) JsonArray, Index);
+}
+
+/**
+ The function is used to append a JSON value to the end of the JSON array, and grow the size of
+ array by 1. The reference count of this value will be increased by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonArray The provided JSON object.
+ @param[in] Json The JSON value to append.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS JSON value has been appended to the end of the JSON array.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonArrayAppendValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ if (json_array_append ((json_t *) JsonArray, (json_t *) Json) != 0) {
+ return EFI_ABORTED;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ The function is used to remove a JSON value at position index, shifting the elements after index
+ one position towards the start of the array. The reference count of this value will be decreased
+ by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonArray The provided JSON array.
+ @param[in] Index The Index position before removement.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS The JSON array has been removed at position index.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonArrayRemoveValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN UINTN Index
+ )
+{
+ if (json_array_remove ((json_t *) JsonArray, Index) != 0) {
+ return EFI_ABORTED;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ Dump JSON to a buffer.
+
+ @param[in] JsonValue The provided JSON value.
+ @param[in] Flags The Index position before removement. The value
+ could be the combination of below flags.
+ - EDKII_JSON_INDENT(n)
+ - EDKII_JSON_COMPACT
+ - EDKII_JSON_ENSURE_ASCII
+ - EDKII_JSON_SORT_KEYS
+ - EDKII_JSON_PRESERVE_ORDER
+ - EDKII_JSON_ENCODE_ANY
+ - EDKII_JSON_ESCAPE_SLASH
+ - EDKII_JSON_REAL_PRECISION(n)
+ - EDKII_JSON_EMBED
+ See below URI for the JSON encoding flags reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html#encoding
+
+ @retval CHAR8 * Dump fail if NULL returned, otherwise the buffer
+ contain JSON paylaod in ASCII string. The return
+ value must be freed by the caller using FreePool().
+**/
+CHAR8 *
+EFIAPI
+JsonDumpString (
+ IN EDKII_JSON_VALUE JsonValue,
+ IN UINTN Flags
+ )
+{
+ if (JsonValue == NULL) {
+ return NULL;
+ }
+ return json_dumps((json_t *)JsonValue, Flags);
+}
+
+/**
+ Convert a string to JSON object.
+ The function is used to convert a NULL terminated CHAR8 string to a JSON
+ value. Only object and array represented strings can be converted successfully,
+ since they are the only valid root values of a JSON text for UEFI usage.
+
+ Real number and number with exponent part are not supportted by UEFI.
+
+ Caller needs to cleanup the root value by calling JsonValueFree().
+
+ @param[in] String The NULL terminated CHAR8 string to convert.
+
+ @retval Array JSON value or object JSON value, or NULL when any error occurs.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonLoadString (
+ IN CONST CHAR8* String
+ )
+{
+ json_error_t JsonError;
+
+ return (EDKII_JSON_VALUE) json_loads ((const char *)String, 0, &JsonError);
+}
+
+/**
+ Load JSON from a buffer.
+
+ @param[in] Buffer Bufffer to the JSON payload
+ @param[in] BufferLen Length of the buffer
+ @param[in] Flags Flag of loading JSON buffer, the value
+ could be the combination of below flags.
+ - EDKII_JSON_REJECT_DUPLICATES
+ - EDKII_JSON_DISABLE_EOF_CHECK
+ - EDKII_JSON_DECODE_ANY
+ - EDKII_JSON_DECODE_INT_AS_REAL
+ - EDKII_JSON_ALLOW_NUL
+ See below URI for the JSON encoding flags reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html?highlight=json_loadb#decoding
+
+ @param[in,out] Error Pointer EDKII_JSON_ERROR structure
+
+ @retval EDKII_JSON_VALUE NULL means fail to load JSON payload.
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonLoadBuffer (
+ IN CONST CHAR8 *Buffer,
+ IN UINTN BufferLen,
+ IN UINTN Flags,
+ IN OUT EDKII_JSON_ERROR *Error
+ )
+{
+ return json_loadb(Buffer, BufferLen, Flags, (json_error_t *)Error);
+}
+
+/**
+ The reference count is used to track whether a value is still in use or not.
+ When a value is created, it's reference count is set to 1.
+ when the value is no longer needed, the reference count is decremented.
+ When the reference count drops to zero, there are no references left and the
+ value can be destroyed.
+
+ This funciton decrement the reference count of EDKII_JSON_VALUE. As soon as
+ a call to json_decref() drops the reference count to zero, the value is
+ destroyed and it can no longer be used.
+
+ @param[in] JsonValue JSON value
+**/
+VOID
+EFIAPI
+JsonDecreaseReference (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ json_decref (JsonValue);
+}
+
+/**
+ The reference count is used to track whether a value is still in use or not.
+ When a value is created, it's reference count is set to 1.
+ If a reference to a value is kept (e.g. a value is stored somewhere for later use),
+ its reference count is incremented.
+
+ This function increment the reference count of json if it's not NULL.
+ Returns EDKII_JSON_VALUE.
+
+ @param[in] JsonValue JSON value
+ @retval EDKII_JSON_VALUE of itself
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonIncreaseReference (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ return json_incref (JsonValue);
+}
+
+/**
+ Returns an opaque iterator which can be used to iterate over all key-value pairs
+ in object, or NULL if object is empty.
+
+ @param[in] JsonValue JSON value
+ @retval Iterator pointer
+**/
+VOID *
+EFIAPI
+JsonObjectIterator (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ return json_object_iter (JsonValue);
+}
+
+/**
+ Extract the associated value from iterator.
+
+ @param[in] Iterator Iterator pointer
+ @retval EDKII_JSON_VALUE
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonObjectIteratorValue (
+ IN VOID *Iterator
+ )
+{
+ return json_object_iter_value(Iterator);
+}
+
+/**
+ Returns an iterator pointing to the next key-value pair in object after iter,
+ or NULL if the whole object has been iterated through.
+
+ @param[in] JsonValue JSON value
+ @param[in] Iterator Iterator pointer
+ @retval Iterator pointer
+**/
+VOID *
+JsonObjectIteratorNext (
+ IN EDKII_JSON_VALUE JsonValue,
+ IN VOID *Iterator
+ )
+{
+ return json_object_iter_next(JsonValue, Iterator);
+}
+
+/**
+ Returns the json type of this json value.
+
+ @param[in] JsonValue JSON value
+ @retval JSON type returned
+**/
+EDKII_JSON_TYPE
+EFIAPI
+JsonGetType (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ return ((json_t *)JsonValue)->type;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.inf
new file mode 100644
index 00000000..bcc93550
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.inf
@@ -0,0 +1,87 @@
+## @file
+# Thirty party Jansson library for JSON operations.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = JsonLib
+ FILE_GUID = F5E36815-305A-4C5A-9D75-4F2149E45255
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = JsonLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ #
+ # Below are the source code of third
+ # party jansson library.
+ #
+ jansson/src/dump.c
+ jansson/src/error.c
+ jansson/src/hashtable.c
+ jansson/src/hashtable_seed.c
+ jansson/src/memory.c
+ jansson/src/pack_unpack.c
+ jansson/src/strbuffer.c
+ jansson/src/strconv.c
+ jansson/src/utf.c
+ jansson/src/value.c
+ jansson/src/version.c
+ #
+ # Below are the source of edk2 JsonLib.
+ #
+ JsonLib.c
+ jansson_config.h
+ jansson_private_config.h
+ #
+ # Below is the source code override to fix the build issue.
+ # Add code in load.c to conditionally use stdin according
+ # to HAVE_UNISTD_H macro. The PR is submitted to jansson
+ # open source community.
+ # https://github.com/akheron/jansson/pull/558
+ #
+ load.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ Ucs2Utf8Lib
+ RedfishCrtLib
+ DebugLib
+ MemoryAllocationLib
+ PrintLib
+ UefiRuntimeServicesTableLib
+ UefiLib
+
+[BuildOptions]
+ #
+ # Disables the following Visual Studio compiler warnings
+ # so we do not break the build with /WX option:
+ # C4090: 'function' : different 'const' qualifiers
+ # C4244: conversion from type1 to type2, possible loss of data
+ # C4334: 32-bit shift implicitly converted to 64-bit
+ # C4204: nonstandard extension used: non-constant aggregate initializer
+ # C4706: assignment within conditional expression
+ #
+ # Define macro HAVE_CONFIG_H to include jansson_private_config.h to build.
+ # Undefined _WIN32, WIN64, _MSC_VER macros
+ # On GCC, no error on the unused-function and unused-but-set-variable.
+ #
+ MSFT:*_*_X64_CC_FLAGS = /wd4204 /wd4244 /wd4090 /wd4334 /wd4706 /DHAVE_CONFIG_H=1 /U_WIN32 /UWIN64 /U_MSC_VER
+ MSFT:*_*_IA32_CC_FLAGS = /wd4204 /wd4244 /wd4090 /wd4706 /DHAVE_CONFIG_H=1 /U_WIN32 /UWIN64 /U_MSC_VER
+ GCC:*_*_*_CC_FLAGS = -Wno-unused-function -Wno-unused-but-set-variable
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/Readme.rst b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/Readme.rst
new file mode 100644
index 00000000..75e7cc43
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/Readme.rst
@@ -0,0 +1,35 @@
+=============================================================================
+ Introduction
+=============================================================================
+ Jansson is a C library for encoding, decoding and manipulating JSON data.
+Its main features and design principles are:
+
+ - Simple and intuitive API and data model
+ - Comprehensive documentation
+ - No dependencies on other libraries
+ - Full Unicode support (UTF-8)
+ - Extensive test suite
+
+ Jansson is licensed under the MIT license(refer to ReadMe.rst under edk2).
+It is used in production and its API is stable. It works on numerous
+platforms, including numerous Unix like systems and Windows. It's suitable
+for use on any system, including desktop, server, and small embedded systems.
+
+ In UEFI/EDKII environment, Redfish project consumes jansson to achieve JSON
+operations.
+
+* Jansson version on edk2: 2.13.1, API reference is on the below URL,
+ https://jansson.readthedocs.io/en/2.13/apiref.html
+
+* EDKII jansson library wrapper:
+ - JsonLib.h:
+ This is the denifitions of EDKII JSON APIs which are mapped to
+ jannson funcitons accordingly.
+
+*Known issue:
+ Build fail with jansson/src/load.c, add code in load.c to conditionally
+ use stdin according to HAVE_UNISTD_H macro. The PR is submitted to
+ jansson open source community.
+ https://github.com/akheron/jansson/pull/558
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_config.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_config.h
new file mode 100644
index 00000000..09cc2992
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_config.h
@@ -0,0 +1,41 @@
+/** @file This is the configuration file for building jansson library.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ **/
+
+#ifndef JANSSON_CONFIG_H_
+#define JANSSON_CONFIG_H_
+
+///
+/// We don't support inline JSON on edk2
+///
+#define JSON_INLINE
+
+///
+/// We support long long on edk2
+///
+#define JSON_INTEGER_IS_LONG_LONG 1
+
+///
+/// We don't support locale on edk2
+///
+#define JSON_HAVE_LOCALECONV 0
+
+///
+/// We don't support atomic builtins on edk2
+///
+#define JSON_HAVE_ATOMIC_BUILTINS 0
+
+///
+/// We don't support sync builtins on edk2
+///
+#define JSON_HAVE_SYNC_BUILTINS 0
+
+///
+/// Mzximum deepth is set to 2048
+///
+#define JSON_PARSER_MAX_DEPTH 2048
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_private_config.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_private_config.h
new file mode 100644
index 00000000..893a3c76
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_private_config.h
@@ -0,0 +1,19 @@
+/** @file
+ Jansson private configurations for UEFI support.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef JANSSON_PRIVATE_CONFIG_H_
+#define JANSSON_PRIVATE_CONFIG_H_
+
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TYPES_H 1
+
+#define INITIAL_HASHTABLE_ORDER 3
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/load.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/load.c
new file mode 100644
index 00000000..41d6a034
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/load.c
@@ -0,0 +1,1111 @@
+/*
+ * Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
+ *
+ * Jansson is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent AND MIT
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "jansson_private.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "jansson.h"
+#include "strbuffer.h"
+#include "utf.h"
+
+#define STREAM_STATE_OK 0
+#define STREAM_STATE_EOF -1
+#define STREAM_STATE_ERROR -2
+
+#define TOKEN_INVALID -1
+#define TOKEN_EOF 0
+#define TOKEN_STRING 256
+#define TOKEN_INTEGER 257
+#define TOKEN_REAL 258
+#define TOKEN_TRUE 259
+#define TOKEN_FALSE 260
+#define TOKEN_NULL 261
+
+/* Locale independent versions of isxxx() functions */
+#define l_isupper(c) ('A' <= (c) && (c) <= 'Z')
+#define l_islower(c) ('a' <= (c) && (c) <= 'z')
+#define l_isalpha(c) (l_isupper(c) || l_islower(c))
+#define l_isdigit(c) ('0' <= (c) && (c) <= '9')
+#define l_isxdigit(c) \
+ (l_isdigit(c) || ('A' <= (c) && (c) <= 'F') || ('a' <= (c) && (c) <= 'f'))
+
+/* Read one byte from stream, convert to unsigned char, then int, and
+ return. return EOF on end of file. This corresponds to the
+ behaviour of fgetc(). */
+typedef int (*get_func)(void *data);
+
+typedef struct {
+ get_func get;
+ void *data;
+ char buffer[5];
+ size_t buffer_pos;
+ int state;
+ int line;
+ int column, last_column;
+ size_t position;
+} stream_t;
+
+typedef struct {
+ stream_t stream;
+ strbuffer_t saved_text;
+ size_t flags;
+ size_t depth;
+ int token;
+ union {
+ struct {
+ char *val;
+ size_t len;
+ } string;
+ json_int_t integer;
+ double real;
+ } value;
+} lex_t;
+
+#define stream_to_lex(stream) container_of(stream, lex_t, stream)
+
+/*** error reporting ***/
+
+static void error_set(json_error_t *error, const lex_t *lex, enum json_error_code code,
+ const char *msg, ...) {
+ va_list ap;
+ char msg_text[JSON_ERROR_TEXT_LENGTH];
+ char msg_with_context[JSON_ERROR_TEXT_LENGTH];
+
+ int line = -1, col = -1;
+ size_t pos = 0;
+ const char *result = msg_text;
+
+ if (!error)
+ return;
+
+ va_start(ap, msg);
+ vsnprintf(msg_text, JSON_ERROR_TEXT_LENGTH, msg, ap);
+ msg_text[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
+ va_end(ap);
+
+ if (lex) {
+ const char *saved_text = strbuffer_value(&lex->saved_text);
+
+ line = lex->stream.line;
+ col = lex->stream.column;
+ pos = lex->stream.position;
+
+ if (saved_text && saved_text[0]) {
+ if (lex->saved_text.length <= 20) {
+ snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near '%s'",
+ msg_text, saved_text);
+ msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
+ result = msg_with_context;
+ }
+ } else {
+ if (code == json_error_invalid_syntax) {
+ /* More specific error code for premature end of file. */
+ code = json_error_premature_end_of_input;
+ }
+ if (lex->stream.state == STREAM_STATE_ERROR) {
+ /* No context for UTF-8 decoding errors */
+ result = msg_text;
+ } else {
+ snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near end of file",
+ msg_text);
+ msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
+ result = msg_with_context;
+ }
+ }
+ }
+
+ jsonp_error_set(error, line, col, pos, code, "%s", result);
+}
+
+/*** lexical analyzer ***/
+
+static void stream_init(stream_t *stream, get_func get, void *data) {
+ stream->get = get;
+ stream->data = data;
+ stream->buffer[0] = '\0';
+ stream->buffer_pos = 0;
+
+ stream->state = STREAM_STATE_OK;
+ stream->line = 1;
+ stream->column = 0;
+ stream->position = 0;
+}
+
+static int stream_get(stream_t *stream, json_error_t *error) {
+ int c;
+
+ if (stream->state != STREAM_STATE_OK)
+ return stream->state;
+
+ if (!stream->buffer[stream->buffer_pos]) {
+ c = stream->get(stream->data);
+ if (c == EOF) {
+ stream->state = STREAM_STATE_EOF;
+ return STREAM_STATE_EOF;
+ }
+
+ stream->buffer[0] = c;
+ stream->buffer_pos = 0;
+
+ if (0x80 <= c && c <= 0xFF) {
+ /* multi-byte UTF-8 sequence */
+ size_t i, count;
+
+ count = utf8_check_first(c);
+ if (!count)
+ goto out;
+
+ assert(count >= 2);
+
+ for (i = 1; i < count; i++)
+ stream->buffer[i] = stream->get(stream->data);
+
+ if (!utf8_check_full(stream->buffer, count, NULL))
+ goto out;
+
+ stream->buffer[count] = '\0';
+ } else
+ stream->buffer[1] = '\0';
+ }
+
+ c = stream->buffer[stream->buffer_pos++];
+
+ stream->position++;
+ if (c == '\n') {
+ stream->line++;
+ stream->last_column = stream->column;
+ stream->column = 0;
+ } else if (utf8_check_first(c)) {
+ /* track the Unicode character column, so increment only if
+ this is the first character of a UTF-8 sequence */
+ stream->column++;
+ }
+
+ return c;
+
+out:
+ stream->state = STREAM_STATE_ERROR;
+ error_set(error, stream_to_lex(stream), json_error_invalid_utf8,
+ "unable to decode byte 0x%x", c);
+ return STREAM_STATE_ERROR;
+}
+
+static void stream_unget(stream_t *stream, int c) {
+ if (c == STREAM_STATE_EOF || c == STREAM_STATE_ERROR)
+ return;
+
+ stream->position--;
+ if (c == '\n') {
+ stream->line--;
+ stream->column = stream->last_column;
+ } else if (utf8_check_first(c))
+ stream->column--;
+
+ assert(stream->buffer_pos > 0);
+ stream->buffer_pos--;
+ assert(stream->buffer[stream->buffer_pos] == c);
+}
+
+static int lex_get(lex_t *lex, json_error_t *error) {
+ return stream_get(&lex->stream, error);
+}
+
+static void lex_save(lex_t *lex, int c) { strbuffer_append_byte(&lex->saved_text, c); }
+
+static int lex_get_save(lex_t *lex, json_error_t *error) {
+ int c = stream_get(&lex->stream, error);
+ if (c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR)
+ lex_save(lex, c);
+ return c;
+}
+
+static void lex_unget(lex_t *lex, int c) { stream_unget(&lex->stream, c); }
+
+static void lex_unget_unsave(lex_t *lex, int c) {
+ if (c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR) {
+/* Since we treat warnings as errors, when assertions are turned
+ * off the "d" variable would be set but never used. Which is
+ * treated as an error by GCC.
+ */
+#ifndef NDEBUG
+ char d;
+#endif
+ stream_unget(&lex->stream, c);
+#ifndef NDEBUG
+ d =
+#endif
+ strbuffer_pop(&lex->saved_text);
+ assert(c == d);
+ }
+}
+
+static void lex_save_cached(lex_t *lex) {
+ while (lex->stream.buffer[lex->stream.buffer_pos] != '\0') {
+ lex_save(lex, lex->stream.buffer[lex->stream.buffer_pos]);
+ lex->stream.buffer_pos++;
+ lex->stream.position++;
+ }
+}
+
+static void lex_free_string(lex_t *lex) {
+ jsonp_free(lex->value.string.val);
+ lex->value.string.val = NULL;
+ lex->value.string.len = 0;
+}
+
+/* assumes that str points to 'u' plus at least 4 valid hex digits */
+static int32_t decode_unicode_escape(const char *str) {
+ int i;
+ int32_t value = 0;
+
+ assert(str[0] == 'u');
+
+ for (i = 1; i <= 4; i++) {
+ char c = str[i];
+ value <<= 4;
+ if (l_isdigit(c))
+ value += c - '0';
+ else if (l_islower(c))
+ value += c - 'a' + 10;
+ else if (l_isupper(c))
+ value += c - 'A' + 10;
+ else
+ return -1;
+ }
+
+ return value;
+}
+
+static void lex_scan_string(lex_t *lex, json_error_t *error) {
+ int c;
+ const char *p;
+ char *t;
+ int i;
+
+ lex->value.string.val = NULL;
+ lex->token = TOKEN_INVALID;
+
+ c = lex_get_save(lex, error);
+
+ while (c != '"') {
+ if (c == STREAM_STATE_ERROR)
+ goto out;
+
+ else if (c == STREAM_STATE_EOF) {
+ error_set(error, lex, json_error_premature_end_of_input,
+ "premature end of input");
+ goto out;
+ }
+
+ else if (0 <= c && c <= 0x1F) {
+ /* control character */
+ lex_unget_unsave(lex, c);
+ if (c == '\n')
+ error_set(error, lex, json_error_invalid_syntax, "unexpected newline");
+ else
+ error_set(error, lex, json_error_invalid_syntax, "control character 0x%x",
+ c);
+ goto out;
+ }
+
+ else if (c == '\\') {
+ c = lex_get_save(lex, error);
+ if (c == 'u') {
+ c = lex_get_save(lex, error);
+ for (i = 0; i < 4; i++) {
+ if (!l_isxdigit(c)) {
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid escape");
+ goto out;
+ }
+ c = lex_get_save(lex, error);
+ }
+ } else if (c == '"' || c == '\\' || c == '/' || c == 'b' || c == 'f' ||
+ c == 'n' || c == 'r' || c == 't')
+ c = lex_get_save(lex, error);
+ else {
+ error_set(error, lex, json_error_invalid_syntax, "invalid escape");
+ goto out;
+ }
+ } else
+ c = lex_get_save(lex, error);
+ }
+
+ /* the actual value is at most of the same length as the source
+ string, because:
+ - shortcut escapes (e.g. "\t") (length 2) are converted to 1 byte
+ - a single \uXXXX escape (length 6) is converted to at most 3 bytes
+ - two \uXXXX escapes (length 12) forming an UTF-16 surrogate pair
+ are converted to 4 bytes
+ */
+ t = jsonp_malloc(lex->saved_text.length + 1);
+ if (!t) {
+ /* this is not very nice, since TOKEN_INVALID is returned */
+ goto out;
+ }
+ lex->value.string.val = t;
+
+ /* + 1 to skip the " */
+ p = strbuffer_value(&lex->saved_text) + 1;
+
+ while (*p != '"') {
+ if (*p == '\\') {
+ p++;
+ if (*p == 'u') {
+ size_t length;
+ int32_t value;
+
+ value = decode_unicode_escape(p);
+ if (value < 0) {
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode escape '%.6s'", p - 1);
+ goto out;
+ }
+ p += 5;
+
+ if (0xD800 <= value && value <= 0xDBFF) {
+ /* surrogate pair */
+ if (*p == '\\' && *(p + 1) == 'u') {
+ int32_t value2 = decode_unicode_escape(++p);
+ if (value2 < 0) {
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode escape '%.6s'", p - 1);
+ goto out;
+ }
+ p += 5;
+
+ if (0xDC00 <= value2 && value2 <= 0xDFFF) {
+ /* valid second surrogate */
+ value =
+ ((value - 0xD800) << 10) + (value2 - 0xDC00) + 0x10000;
+ } else {
+ /* invalid second surrogate */
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode '\\u%04X\\u%04X'", value, value2);
+ goto out;
+ }
+ } else {
+ /* no second surrogate */
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode '\\u%04X'", value);
+ goto out;
+ }
+ } else if (0xDC00 <= value && value <= 0xDFFF) {
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode '\\u%04X'", value);
+ goto out;
+ }
+
+ if (utf8_encode(value, t, &length))
+ assert(0);
+ t += length;
+ } else {
+ switch (*p) {
+ case '"':
+ case '\\':
+ case '/':
+ *t = *p;
+ break;
+ case 'b':
+ *t = '\b';
+ break;
+ case 'f':
+ *t = '\f';
+ break;
+ case 'n':
+ *t = '\n';
+ break;
+ case 'r':
+ *t = '\r';
+ break;
+ case 't':
+ *t = '\t';
+ break;
+ default:
+ assert(0);
+ }
+ t++;
+ p++;
+ }
+ } else
+ *(t++) = *(p++);
+ }
+ *t = '\0';
+ lex->value.string.len = t - lex->value.string.val;
+ lex->token = TOKEN_STRING;
+ return;
+
+out:
+ lex_free_string(lex);
+}
+
+#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */
+#if JSON_INTEGER_IS_LONG_LONG
+#ifdef _MSC_VER /* Microsoft Visual Studio */
+#define json_strtoint _strtoi64
+#else
+#define json_strtoint strtoll
+#endif
+#else
+#define json_strtoint strtol
+#endif
+#endif
+
+static int lex_scan_number(lex_t *lex, int c, json_error_t *error) {
+ const char *saved_text;
+ char *end;
+ double doubleval;
+
+ lex->token = TOKEN_INVALID;
+
+ if (c == '-')
+ c = lex_get_save(lex, error);
+
+ if (c == '0') {
+ c = lex_get_save(lex, error);
+ if (l_isdigit(c)) {
+ lex_unget_unsave(lex, c);
+ goto out;
+ }
+ } else if (l_isdigit(c)) {
+ do
+ c = lex_get_save(lex, error);
+ while (l_isdigit(c));
+ } else {
+ lex_unget_unsave(lex, c);
+ goto out;
+ }
+
+ if (!(lex->flags & JSON_DECODE_INT_AS_REAL) && c != '.' && c != 'E' && c != 'e') {
+ json_int_t intval;
+
+ lex_unget_unsave(lex, c);
+
+ saved_text = strbuffer_value(&lex->saved_text);
+
+ errno = 0;
+ intval = json_strtoint(saved_text, &end, 10);
+ if (errno == ERANGE) {
+ if (intval < 0)
+ error_set(error, lex, json_error_numeric_overflow,
+ "too big negative integer");
+ else
+ error_set(error, lex, json_error_numeric_overflow, "too big integer");
+ goto out;
+ }
+
+ assert(end == saved_text + lex->saved_text.length);
+
+ lex->token = TOKEN_INTEGER;
+ lex->value.integer = intval;
+ return 0;
+ }
+
+ if (c == '.') {
+ c = lex_get(lex, error);
+ if (!l_isdigit(c)) {
+ lex_unget(lex, c);
+ goto out;
+ }
+ lex_save(lex, c);
+
+ do
+ c = lex_get_save(lex, error);
+ while (l_isdigit(c));
+ }
+
+ if (c == 'E' || c == 'e') {
+ c = lex_get_save(lex, error);
+ if (c == '+' || c == '-')
+ c = lex_get_save(lex, error);
+
+ if (!l_isdigit(c)) {
+ lex_unget_unsave(lex, c);
+ goto out;
+ }
+
+ do
+ c = lex_get_save(lex, error);
+ while (l_isdigit(c));
+ }
+
+ lex_unget_unsave(lex, c);
+
+ if (jsonp_strtod(&lex->saved_text, &doubleval)) {
+ error_set(error, lex, json_error_numeric_overflow, "real number overflow");
+ goto out;
+ }
+
+ lex->token = TOKEN_REAL;
+ lex->value.real = doubleval;
+ return 0;
+
+out:
+ return -1;
+}
+
+static int lex_scan(lex_t *lex, json_error_t *error) {
+ int c;
+
+ strbuffer_clear(&lex->saved_text);
+
+ if (lex->token == TOKEN_STRING)
+ lex_free_string(lex);
+
+ do
+ c = lex_get(lex, error);
+ while (c == ' ' || c == '\t' || c == '\n' || c == '\r');
+
+ if (c == STREAM_STATE_EOF) {
+ lex->token = TOKEN_EOF;
+ goto out;
+ }
+
+ if (c == STREAM_STATE_ERROR) {
+ lex->token = TOKEN_INVALID;
+ goto out;
+ }
+
+ lex_save(lex, c);
+
+ if (c == '{' || c == '}' || c == '[' || c == ']' || c == ':' || c == ',')
+ lex->token = c;
+
+ else if (c == '"')
+ lex_scan_string(lex, error);
+
+ else if (l_isdigit(c) || c == '-') {
+ if (lex_scan_number(lex, c, error))
+ goto out;
+ }
+
+ else if (l_isalpha(c)) {
+ /* eat up the whole identifier for clearer error messages */
+ const char *saved_text;
+
+ do
+ c = lex_get_save(lex, error);
+ while (l_isalpha(c));
+ lex_unget_unsave(lex, c);
+
+ saved_text = strbuffer_value(&lex->saved_text);
+
+ if (strcmp(saved_text, "true") == 0)
+ lex->token = TOKEN_TRUE;
+ else if (strcmp(saved_text, "false") == 0)
+ lex->token = TOKEN_FALSE;
+ else if (strcmp(saved_text, "null") == 0)
+ lex->token = TOKEN_NULL;
+ else
+ lex->token = TOKEN_INVALID;
+ }
+
+ else {
+ /* save the rest of the input UTF-8 sequence to get an error
+ message of valid UTF-8 */
+ lex_save_cached(lex);
+ lex->token = TOKEN_INVALID;
+ }
+
+out:
+ return lex->token;
+}
+
+static char *lex_steal_string(lex_t *lex, size_t *out_len) {
+ char *result = NULL;
+ if (lex->token == TOKEN_STRING) {
+ result = lex->value.string.val;
+ *out_len = lex->value.string.len;
+ lex->value.string.val = NULL;
+ lex->value.string.len = 0;
+ }
+ return result;
+}
+
+static int lex_init(lex_t *lex, get_func get, size_t flags, void *data) {
+ stream_init(&lex->stream, get, data);
+ if (strbuffer_init(&lex->saved_text))
+ return -1;
+
+ lex->flags = flags;
+ lex->token = TOKEN_INVALID;
+ return 0;
+}
+
+static void lex_close(lex_t *lex) {
+ if (lex->token == TOKEN_STRING)
+ lex_free_string(lex);
+ strbuffer_close(&lex->saved_text);
+}
+
+/*** parser ***/
+
+static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error);
+
+static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error) {
+ json_t *object = json_object();
+ if (!object)
+ return NULL;
+
+ lex_scan(lex, error);
+ if (lex->token == '}')
+ return object;
+
+ while (1) {
+ char *key;
+ size_t len;
+ json_t *value;
+
+ if (lex->token != TOKEN_STRING) {
+ error_set(error, lex, json_error_invalid_syntax, "string or '}' expected");
+ goto error;
+ }
+
+ key = lex_steal_string(lex, &len);
+ if (!key)
+ return NULL;
+ if (memchr(key, '\0', len)) {
+ jsonp_free(key);
+ error_set(error, lex, json_error_null_byte_in_key,
+ "NUL byte in object key not supported");
+ goto error;
+ }
+
+ if (flags & JSON_REJECT_DUPLICATES) {
+ if (json_object_get(object, key)) {
+ jsonp_free(key);
+ error_set(error, lex, json_error_duplicate_key, "duplicate object key");
+ goto error;
+ }
+ }
+
+ lex_scan(lex, error);
+ if (lex->token != ':') {
+ jsonp_free(key);
+ error_set(error, lex, json_error_invalid_syntax, "':' expected");
+ goto error;
+ }
+
+ lex_scan(lex, error);
+ value = parse_value(lex, flags, error);
+ if (!value) {
+ jsonp_free(key);
+ goto error;
+ }
+
+ if (json_object_set_new_nocheck(object, key, value)) {
+ jsonp_free(key);
+ goto error;
+ }
+
+ jsonp_free(key);
+
+ lex_scan(lex, error);
+ if (lex->token != ',')
+ break;
+
+ lex_scan(lex, error);
+ }
+
+ if (lex->token != '}') {
+ error_set(error, lex, json_error_invalid_syntax, "'}' expected");
+ goto error;
+ }
+
+ return object;
+
+error:
+ json_decref(object);
+ return NULL;
+}
+
+static json_t *parse_array(lex_t *lex, size_t flags, json_error_t *error) {
+ json_t *array = json_array();
+ if (!array)
+ return NULL;
+
+ lex_scan(lex, error);
+ if (lex->token == ']')
+ return array;
+
+ while (lex->token) {
+ json_t *elem = parse_value(lex, flags, error);
+ if (!elem)
+ goto error;
+
+ if (json_array_append_new(array, elem)) {
+ goto error;
+ }
+
+ lex_scan(lex, error);
+ if (lex->token != ',')
+ break;
+
+ lex_scan(lex, error);
+ }
+
+ if (lex->token != ']') {
+ error_set(error, lex, json_error_invalid_syntax, "']' expected");
+ goto error;
+ }
+
+ return array;
+
+error:
+ json_decref(array);
+ return NULL;
+}
+
+static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error) {
+ json_t *json;
+
+ lex->depth++;
+ if (lex->depth > JSON_PARSER_MAX_DEPTH) {
+ error_set(error, lex, json_error_stack_overflow, "maximum parsing depth reached");
+ return NULL;
+ }
+
+ switch (lex->token) {
+ case TOKEN_STRING: {
+ const char *value = lex->value.string.val;
+ size_t len = lex->value.string.len;
+
+ if (!(flags & JSON_ALLOW_NUL)) {
+ if (memchr(value, '\0', len)) {
+ error_set(error, lex, json_error_null_character,
+ "\\u0000 is not allowed without JSON_ALLOW_NUL");
+ return NULL;
+ }
+ }
+
+ json = jsonp_stringn_nocheck_own(value, len);
+ lex->value.string.val = NULL;
+ lex->value.string.len = 0;
+ break;
+ }
+
+ case TOKEN_INTEGER: {
+ json = json_integer(lex->value.integer);
+ break;
+ }
+
+ case TOKEN_REAL: {
+ json = json_real(lex->value.real);
+ break;
+ }
+
+ case TOKEN_TRUE:
+ json = json_true();
+ break;
+
+ case TOKEN_FALSE:
+ json = json_false();
+ break;
+
+ case TOKEN_NULL:
+ json = json_null();
+ break;
+
+ case '{':
+ json = parse_object(lex, flags, error);
+ break;
+
+ case '[':
+ json = parse_array(lex, flags, error);
+ break;
+
+ case TOKEN_INVALID:
+ error_set(error, lex, json_error_invalid_syntax, "invalid token");
+ return NULL;
+
+ default:
+ error_set(error, lex, json_error_invalid_syntax, "unexpected token");
+ return NULL;
+ }
+
+ if (!json)
+ return NULL;
+
+ lex->depth--;
+ return json;
+}
+
+static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error) {
+ json_t *result;
+
+ lex->depth = 0;
+
+ lex_scan(lex, error);
+ if (!(flags & JSON_DECODE_ANY)) {
+ if (lex->token != '[' && lex->token != '{') {
+ error_set(error, lex, json_error_invalid_syntax, "'[' or '{' expected");
+ return NULL;
+ }
+ }
+
+ result = parse_value(lex, flags, error);
+ if (!result)
+ return NULL;
+
+ if (!(flags & JSON_DISABLE_EOF_CHECK)) {
+ lex_scan(lex, error);
+ if (lex->token != TOKEN_EOF) {
+ error_set(error, lex, json_error_end_of_input_expected,
+ "end of file expected");
+ json_decref(result);
+ return NULL;
+ }
+ }
+
+ if (error) {
+ /* Save the position even though there was no error */
+ error->position = (int)lex->stream.position;
+ }
+
+ return result;
+}
+
+typedef struct {
+ const char *data;
+ size_t pos;
+} string_data_t;
+
+static int string_get(void *data) {
+ char c;
+ string_data_t *stream = (string_data_t *)data;
+ c = stream->data[stream->pos];
+ if (c == '\0')
+ return EOF;
+ else {
+ stream->pos++;
+ return (unsigned char)c;
+ }
+}
+
+json_t *json_loads(const char *string, size_t flags, json_error_t *error) {
+ lex_t lex;
+ json_t *result;
+ string_data_t stream_data;
+
+ jsonp_error_init(error, "<string>");
+
+ if (string == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ stream_data.data = string;
+ stream_data.pos = 0;
+
+ if (lex_init(&lex, string_get, flags, (void *)&stream_data))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
+
+typedef struct {
+ const char *data;
+ size_t len;
+ size_t pos;
+} buffer_data_t;
+
+static int buffer_get(void *data) {
+ char c;
+ buffer_data_t *stream = data;
+ if (stream->pos >= stream->len)
+ return EOF;
+
+ c = stream->data[stream->pos];
+ stream->pos++;
+ return (unsigned char)c;
+}
+
+json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error) {
+ lex_t lex;
+ json_t *result;
+ buffer_data_t stream_data;
+
+ jsonp_error_init(error, "<buffer>");
+
+ if (buffer == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ stream_data.data = buffer;
+ stream_data.pos = 0;
+ stream_data.len = buflen;
+
+ if (lex_init(&lex, buffer_get, flags, (void *)&stream_data))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
+
+json_t *json_loadf(FILE *input, size_t flags, json_error_t *error) {
+ lex_t lex;
+ const char *source;
+ json_t *result;
+#ifdef HAVE_UNISTD_H
+ if (input == stdin)
+ source = "<stdin>";
+ else
+#endif
+ source = "<stream>";
+
+ jsonp_error_init(error, source);
+
+ if (input == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ if (lex_init(&lex, (get_func)fgetc, flags, input))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
+
+static int fd_get_func(int *fd) {
+#ifdef HAVE_UNISTD_H
+ uint8_t c;
+ if (read(*fd, &c, 1) == 1)
+ return c;
+#endif
+ return EOF;
+}
+
+json_t *json_loadfd(int input, size_t flags, json_error_t *error) {
+ lex_t lex;
+ const char *source;
+ json_t *result;
+
+#ifdef HAVE_UNISTD_H
+ if (input == STDIN_FILENO)
+ source = "<stdin>";
+ else
+#endif
+ source = "<stream>";
+
+ jsonp_error_init(error, source);
+
+ if (input < 0) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ if (lex_init(&lex, (get_func)fd_get_func, flags, &input))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
+
+json_t *json_load_file(const char *path, size_t flags, json_error_t *error) {
+ json_t *result;
+ FILE *fp;
+
+ jsonp_error_init(error, path);
+
+ if (path == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ fp = fopen(path, "rb");
+ if (!fp) {
+ error_set(error, NULL, json_error_cannot_open_file, "unable to open %s: %s", path,
+ strerror(errno));
+ return NULL;
+ }
+
+ result = json_loadf(fp, flags, error);
+
+ fclose(fp);
+ return result;
+}
+
+#define MAX_BUF_LEN 1024
+
+typedef struct {
+ char data[MAX_BUF_LEN];
+ size_t len;
+ size_t pos;
+ json_load_callback_t callback;
+ void *arg;
+} callback_data_t;
+
+static int callback_get(void *data) {
+ char c;
+ callback_data_t *stream = data;
+
+ if (stream->pos >= stream->len) {
+ stream->pos = 0;
+ stream->len = stream->callback(stream->data, MAX_BUF_LEN, stream->arg);
+ if (stream->len == 0 || stream->len == (size_t)-1)
+ return EOF;
+ }
+
+ c = stream->data[stream->pos];
+ stream->pos++;
+ return (unsigned char)c;
+}
+
+json_t *json_load_callback(json_load_callback_t callback, void *arg, size_t flags,
+ json_error_t *error) {
+ lex_t lex;
+ json_t *result;
+
+ callback_data_t stream_data;
+
+ memset(&stream_data, 0, sizeof(stream_data));
+ stream_data.callback = callback;
+ stream_data.arg = arg;
+
+ jsonp_error_init(error, "<callback>");
+
+ if (callback == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ if (lex_init(&lex, (get_func)callback_get, flags, &stream_data))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.c
new file mode 100644
index 00000000..19fe2e20
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.c
@@ -0,0 +1,101 @@
+/** @file
+ NULL instace of RedfishPlatformCredentialLib
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Protocol/EdkIIRedfishCredential.h>
+/**
+ Notification of Exit Boot Service.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL.
+**/
+VOID
+EFIAPI
+LibCredentialExitBootServicesNotify (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This
+)
+{
+ return;
+}
+
+/**
+ Notification of End of DXe.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL.
+**/
+VOID
+EFIAPI
+LibCredentialEndOfDxeNotify (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This
+)
+{
+ return;
+}
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user Id and
+ password.
+ - For AuthMethodNone, the UserId and Password could be used for HTTP header authentication
+ as defined by RFC7235.
+ - For AuthMethodRedfishSession, the UserId and Password could be used for Redfish
+ session login as defined by Redfish API specification (DSP0266).
+
+ Callers are responsible for and freeing the returned string storage.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_ACCESS_DENIED SecureBoot is disabled after EndOfDxe.
+ @retval EFI_INVALID_PARAMETER This or AuthMethod or UserId or Password is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resources.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+
+**/
+EFI_STATUS
+EFIAPI
+LibCredentialGetAuthInfo (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Notify the Redfish service provide to stop provide configuration service to this platform.
+
+ This function should be called when the platfrom is about to leave the safe environment.
+ It will notify the Redfish service provider to abort all logined session, and prohibit
+ further login with original auth info. GetAuthInfo() will return EFI_UNSUPPORTED once this
+ function is returned.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[in] ServiceStopType Reason of stopping Redfish service.
+
+ @retval EFI_SUCCESS Service has been stoped successfully.
+ @retval EFI_INVALID_PARAMETER This is NULL or given the worng ServiceStopType.
+ @retval EFI_UNSUPPORTED Not support to stop Redfish service.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+LibStopRedfishService (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ IN EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE ServiceStopType
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf
new file mode 100644
index 00000000..ddad90c0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf
@@ -0,0 +1,30 @@
+## @file
+# NULL instance of RedfishPlatformCredentialLib
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001000b
+ BASE_NAME = RedfishPlatformCredentialLibNull
+ FILE_GUID = CA3BD843-0BDD-4EE0-A38A-B45CA663114F
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RedfishPlatformCredentialLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ PlatformCredentialLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.c
new file mode 100644
index 00000000..598c7f1e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.c
@@ -0,0 +1,52 @@
+/** @file
+ NULL instace of RedfishPlatformHostInterfaceLib
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/RedfishHostInterfaceLib.h>
+#include <Library/UefiLib.h>
+
+/**
+ Get platform Redfish host interface device descriptor.
+
+ @param[in] DeviceType Pointer to retrieve device type.
+ @param[out] DeviceDescriptor Pointer to retrieve REDFISH_INTERFACE_DATA, caller has to free
+ this memory using FreePool().
+
+ @retval EFI_NOT_FOUND No Redfish host interface descriptor provided on this platform.
+
+**/
+EFI_STATUS
+RedfishPlatformHostInterfaceDeviceDescriptor (
+ IN UINT8 *DeviceType,
+ OUT REDFISH_INTERFACE_DATA **DeviceDescriptor
+)
+{
+ return EFI_NOT_FOUND;
+}
+/**
+ Get platform Redfish host interface protocol data.
+ Caller should pass NULL in ProtocolRecord to retrive the first protocol record.
+ Then continuously pass previous ProtocolRecord for retrieving the next ProtocolRecord.
+
+ @param[in, out] ProtocolRecord Pointer to retrieve the first or the next protocol record.
+ caller has to free the new protocol record returned from
+ this function using FreePool().
+ @param[in] IndexOfProtocolData The index of protocol data.
+
+ @retval EFI_NOT_FOUND No more protocol records.
+
+**/
+EFI_STATUS
+RedfishPlatformHostInterfaceProtocolData (
+ IN OUT MC_HOST_INTERFACE_PROTOCOL_RECORD **ProtocolRecord,
+ IN UINT8 IndexOfProtocolData
+)
+{
+ return EFI_NOT_FOUND;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf
new file mode 100644
index 00000000..fe60ad49
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf
@@ -0,0 +1,33 @@
+## @file
+# NULL instance of RedfishPlatformHostInterfaceLib
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001000b
+ BASE_NAME = RedfishPlatformHostInterfaceLibNull
+ FILE_GUID = 851229BF-4D8B-30F3-DD0D-20AFAF99A77B
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RedfishPlatformHostInterfaceLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ PlatformHostInterfaceLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[LibraryClasses]
+ UefiLib
+ BaseLib
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.c
new file mode 100644
index 00000000..0264b365
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.c
@@ -0,0 +1,81 @@
+/** @file
+ NULL instace of RedfishContentCodingLib
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+
+/**
+ This is the function to encode the content use the
+ algorithm indicated in ContentEncodedValue. The naming of
+ ContentEncodedValue is follow HTTP spec or could be a
+ platform-specific value.
+
+ @param[in] ContentEncodedValue HTTP conent encoded value.
+ The value could be one of below
+ or any which is platform-specific.
+ - HTTP_CONTENT_ENCODING_IDENTITY "identity"
+ - HTTP_CONTENT_ENCODING_GZIP "gzip"
+ - HTTP_CONTENT_ENCODING_COMPRESS "compress"
+ - HTTP_CONTENT_ENCODING_DEFLATE "deflate"
+ - HTTP_CONTENT_ENCODING_BROTLI "br"
+ @param[in] OriginalContent Original content.
+ @param[in] OriginalContentLength The length of original content.
+ @param[out] EncodedContentPointer Pointer to receive the encoded content pointer.
+ @param[out] EncodedContentLength Length of encoded content.
+
+ @retval EFI_SUCCESS Content is encoded successfully.
+ @retval EFI_UNSUPPORTED No supported encoding funciton,
+ @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.
+
+**/
+EFI_STATUS
+RedfishContentEncode (
+ IN CHAR8 *ContentEncodedValue,
+ IN CHAR8 *OriginalContent,
+ IN UINTN OriginalContentLength,
+ OUT VOID **EncodedContentPointer,
+ OUT UINTN *EncodedContentLength
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This is the function to decode the content use the
+ algorithm indicated in ContentEncodedValue. The naming of
+ ContentEncodedValue is follow HTTP spec or could be a
+ platform-specific value.
+
+ @param[in] ContentDecodedValue HTTP conent decoded value.
+ The value could be one of below
+ or any which is platform-specific.
+ - HTTP_CONTENT_ENCODING_IDENTITY "identity"
+ - HTTP_CONTENT_ENCODING_GZIP "gzip"
+ - HTTP_CONTENT_ENCODING_COMPRESS "compress"
+ - HTTP_CONTENT_ENCODING_DEFLATE "deflate"
+ - HTTP_CONTENT_ENCODING_BROTLI "br"
+ @param[in] ContentPointer Original content.
+ @param[in] ContentLength The length of original content.
+ @param[out] DecodedContentPointer Pointer to receive decoded content pointer.
+ @param[out] DecodedContentLength Length of decoded content.
+
+ @retval EFI_SUCCESS Content is decoded successfully.
+ @retval EFI_UNSUPPORTED No supported decoding funciton,
+ @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.
+
+**/
+EFI_STATUS
+RedfishContentDecode (
+ IN CHAR8 *ContentDecodedValue,
+ IN VOID *ContentPointer,
+ IN UINTN ContentLength,
+ OUT VOID **DecodedContentPointer,
+ OUT UINTN *DecodedContentLength
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.inf
new file mode 100644
index 00000000..2a74d7fa
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.inf
@@ -0,0 +1,31 @@
+## @file
+# NULL instance of RedfishContentCodingLibNull
+# This library is used to encode/decode Redfish payload.
+#
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001000b
+ BASE_NAME = RedfishContentCodingLibNull
+ FILE_GUID = 06B10249-4D38-FF37-0CA5-13AFB6D625CC
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RedfishContentCodingLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ RedfishContentCodingLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/assert.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/assert.h
new file mode 100644
index 00000000..778f142e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/assert.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_ASSERT_H_
+#define REDFISH_CRT_ASSERT_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/errno.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/errno.h
new file mode 100644
index 00000000..98a9979d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/errno.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_ERRNO_H_
+#define REDFISH_CRT_ERRNO_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/limits.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/limits.h
new file mode 100644
index 00000000..1b97a3cc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/limits.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_LIMITS_H_
+#define REDFISH_CRT_LIMITS_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/math.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/math.h
new file mode 100644
index 00000000..503f844a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/math.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_MATH_H_
+#define REDFISH_CRT_MATH_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdarg.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdarg.h
new file mode 100644
index 00000000..e4ea626b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdarg.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_STDARG_H_
+#define REDFISH_CRT_STDARG_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stddef.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stddef.h
new file mode 100644
index 00000000..35ed2e97
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stddef.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_STDDEF_H_
+#define REDFISH_CRT_STDDEF_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdio.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdio.h
new file mode 100644
index 00000000..4ee8889b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdio.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_STDIO_H_
+#define REDFISH_CRT_STDIO_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdlib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdlib.h
new file mode 100644
index 00000000..db7a3e64
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdlib.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_STDLIB_H_
+#define REDFISH_CRT_STDLIB_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/string.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/string.h
new file mode 100644
index 00000000..af23842a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/string.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_STRING_H_
+#define REDFISH_CRT_STRING_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/time.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/time.h
new file mode 100644
index 00000000..324c6ba7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/time.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_SYS_TIME_H_
+#define REDFISH_CRT_SYS_TIME_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/types.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/types.h
new file mode 100644
index 00000000..df46193d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/types.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_SYS_TYPES_H_
+#define REDFISH_CRT_SYS_TYPES_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/time.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/time.h
new file mode 100644
index 00000000..1f7a698b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/time.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_TIME_H_
+#define REDFISH_CRT_TIME_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishCrtLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishCrtLib.h
new file mode 100644
index 00000000..9ad28dc7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishCrtLib.h
@@ -0,0 +1,242 @@
+/** @file
+ Redfish CRT wrapper functions.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_LIB_H_
+#define REDFISH_CRT_LIB_H_
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+
+#define MAX_STRING_SIZE 0x10000000
+
+// Minimum value for an object of type long long int.
+#define LLONG_MIN MIN_INT64
+
+// Maximum value for an object of type long long int.
+#define LLONG_MAX MAX_INT64
+
+// We dont support double on edk2
+#define HUGE_VAL 0
+
+#if defined(MDE_CPU_X64) || defined(MDE_CPU_AARCH64) || defined(MDE_CPU_RISCV64)
+//
+// With GCC we would normally use SIXTY_FOUR_BIT_LONG, but MSVC needs
+// SIXTY_FOUR_BIT, because 'long' is 32-bit and only 'long long' is
+// 64-bit. Since using 'long long' works fine on GCC too, just do that.
+//
+#define SIXTY_FOUR_BIT
+#elif defined(MDE_CPU_IA32) || defined(MDE_CPU_ARM) || defined(MDE_CPU_EBC)
+#define THIRTY_TWO_BIT
+#endif
+
+//
+// Map all va_xxxx elements to VA_xxx defined in MdePkg/Include/Base.h
+//
+#if !defined(__CC_ARM) // if va_list is not already defined
+#define va_list VA_LIST
+#define va_arg VA_ARG
+#define va_start VA_START
+#define va_end VA_END
+#else // __CC_ARM
+#define va_start(Marker, Parameter) __va_start(Marker, Parameter)
+#define va_arg(Marker, TYPE) __va_arg(Marker, TYPE)
+#define va_end(Marker) ((void)0)
+#endif
+
+//
+// Definitions for global constants used by CRT library routines
+//
+#define INT_MAX MAX_INT32 /* Maximum (signed) int value */
+#define LONG_MAX 0X7FFFFFFFL /* max value for a long */
+#define LONG_MIN (-LONG_MAX-1) /* min value for a long */
+#define ULONG_MAX 0xFFFFFFFF /* Maximum unsigned long value */
+#define CHAR_BIT 8 /* Number of bits in a char */
+
+// Maximum value for an object of type unsigned long long int.
+#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL // 2^64 - 1
+// Maximum value for an object of type unsigned char.
+#define UCHAR_MAX 255 // 2^8 - 1
+
+//
+// Basic types mapping
+//
+typedef UINTN size_t;
+typedef INTN ssize_t;
+typedef INT32 time_t;
+typedef UINT8 __uint8_t;
+typedef UINT8 sa_family_t;
+typedef UINT32 uid_t;
+typedef UINT32 gid_t;
+typedef INT32 int32_t;
+typedef UINT32 uint32_t;
+typedef UINT16 uint16_t;
+typedef UINT8 uint8_t;
+typedef enum {false, true} bool;
+
+//
+// File operations are not required for EFI building,
+// so FILE is mapped to VOID * to pass build
+//
+typedef VOID *FILE;
+
+/**
+ This is the Redfish version of CRT snprintf function, this function replaces "%s" to
+ "%a" before invoking AsciiSPrint(). That is becasue "%s" is unicode base on edk2
+ environment however "%s" is ascii code base on snprintf().
+ See definitions of AsciiSPrint() for the details.
+
+ @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString A Null-terminated ASCII format string.
+ @param ... Variable argument list whose contents are accessed based on the
+ format string specified by FormatString.
+
+ @return The number of ASCII characters in the produced output buffer not including the
+ Null-terminator. Zero means no string is produced or the error happens.
+
+**/
+UINTN
+EFIAPI
+RedfishAsciiSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ ...
+ );
+
+/**
+ This is the Redfish version of CRT vsnprintf function, this function replaces "%s" to
+ "%a" before invoking AsciiVSPrint(). That is because "%s" is unicode base on edk2
+ environment however "%s" is ascii code base on vsnprintf().
+ See definitions of AsciiVSPrint() for the details.
+
+ @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString A Null-terminated ASCII format string.
+ @param Marker VA_LIST marker for the variable argument list.
+
+ @return The number of ASCII characters in the produced output buffer not including the
+ Null-terminator.
+
+**/
+UINTN
+EFIAPI
+RedfishAsciiVSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ IN VA_LIST Marker
+ );
+
+//
+// Global variables
+//
+extern int errno;
+extern FILE *stderr;
+
+//
+// Function prototypes of CRT Library routines
+//
+void *malloc (size_t);
+void *realloc (void *, size_t);
+void *calloc (size_t Num, size_t Size);
+void free (void *);
+void *memset (void *, int, size_t);
+int memcmp (const void *, const void *, size_t);
+int isdigit (int);
+int isspace (int);
+int tolower (int);
+int isupper (int);
+int isxdigit (int);
+int isalnum (int);
+void *memcpy (void *, const void *, size_t);
+void *memset (void *, int, size_t);
+void *memchr (const void *, int, size_t);
+int memcmp (const void *, const void *, size_t);
+void *memmove (void *, const void *, size_t);
+int strcmp (const char *, const char *);
+int strncmp (const char *, const char *, size_t);
+char *strcpy (char *, const char *);
+size_t strlen (const char *);
+char *strcat (char *, const char *);
+char *strchr (const char *, int);
+int strcasecmp (const char *, const char *);
+int strncasecmp (const char *, const char *, size_t);
+char *strncpy (char *, size_t, const char *, size_t);
+int strncmp (const char *, const char *, size_t);
+char *strrchr (const char *, int);
+unsigned long strtoul (const char *, char **, int);
+char * strstr (const char *s1 , const char *s2);
+long strtol (const char *, char **, int);
+char *strerror (int);
+size_t strspn (const char *, const char *);
+char * strdup (const char *str);
+char * strpbrk (const char *s1, const char *s2);
+unsigned long long strtoull(const char * nptr, char ** endptr, int base);
+long long strtoll (const char * nptr, char ** endptr, int base);
+long strtol (const char * nptr, char ** endptr, int base);
+double strtod (const char * __restrict nptr, char ** __restrict endptr);
+size_t strcspn (const char *, const char *);
+int printf (const char *, ...);
+int sscanf (const char *, const char *, ...);
+FILE *fopen (const char *, const char *);
+size_t fread (void *, size_t, size_t, FILE *);
+size_t fwrite (const void *, size_t, size_t, FILE *);
+int fclose (FILE *);
+int fprintf (FILE *, const char *, ...);
+int fgetc (FILE * _File);
+uid_t getuid (void);
+uid_t geteuid (void);
+gid_t getgid (void);
+gid_t getegid (void);
+void qsort (void *, size_t, size_t, int (*)(const void *, const void *));
+char *getenv (const char *);
+#if defined(__GNUC__) && (__GNUC__ >= 2)
+void abort (void) __attribute__((__noreturn__));
+#else
+void abort (void);
+#endif
+int toupper (int);
+int Digit2Val (int);
+time_t time (time_t *);
+
+//
+// Macros that directly map functions to BaseLib, BaseMemoryLib, and DebugLib functions
+//
+#define strcmp AsciiStrCmp
+#define memcpy(dest,source,count) CopyMem(dest,source,(UINTN)(count))
+#define memset(dest,ch,count) SetMem(dest,(UINTN)(count),(UINT8)(ch))
+#define memchr(buf,ch,count) ScanMem8(buf,(UINTN)(count),(UINT8)ch)
+#define memcmp(buf1,buf2,count) (int)(CompareMem(buf1,buf2,(UINTN)(count)))
+#define memmove(dest,source,count) CopyMem(dest,source,(UINTN)(count))
+#define strlen(str) (size_t)(AsciiStrnLenS(str,MAX_STRING_SIZE))
+#define strcpy(strDest,strSource) AsciiStrCpyS(strDest,(strlen(strSource)+1),strSource)
+#define strncpy(strDest,strSource,count) AsciiStrnCpyS(strDest,(UINTN)count,strSource,(UINTN)count)
+#define strncpys(strDest, DestLen, strSource,count) AsciiStrnCpyS(strDest,DestLen,strSource,(UINTN)count)
+#define strcat(strDest,strSource) AsciiStrCatS(strDest,(strlen(strSource)+strlen(strDest)+1),strSource)
+#define strchr(str,ch) ScanMem8((VOID *)(str),AsciiStrSize(str),(UINT8)ch)
+#define strcasecmp(str1,str2) (int)AsciiStriCmp(str1,str2)
+#define strstr(s1,s2) AsciiStrStr(s1,s2)
+#define snprintf(buf,len,...) RedfishAsciiSPrint(buf,len,__VA_ARGS__)
+#define vsnprintf(buf,len,format,marker) RedfishAsciiVSPrint((buf),(len),(format),(marker))
+#define assert(expression) ASSERT(expression)
+#define offsetof(type,member) OFFSET_OF(type,member)
+
+#define EOF (-1)
+
+extern int errno;
+
+#define ERANGE 34 /* 34 Result too large */
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishLib.h
new file mode 100644
index 00000000..c3069f0d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishLib.h
@@ -0,0 +1,611 @@
+/** @file
+ This library provides a set of utility APIs that allow to create/read/update/delete
+ (CRUD) Redfish resources and provide basic query abilities by using [URI/RedPath]
+ (https://github.com/DMTF/libredfish).
+
+ The query language is based on XPath (https://www.w3.org/TR/1999/REC-xpath-19991116/).
+ This library and query language essentially treat the entire Redfish Service like it
+ was a single JSON document. In other words whenever it encounters an odata.id in JSON
+ document, it will retrieve the new JSON document (if needed). We name the path as
+ RedPath:
+
+ Expression Description
+
+ nodename Selects the JSON entity with the name "nodename".
+ If the value of nodename is an object with "@odata.id",
+ it will continue get the value from "@odata.id".
+
+ / Selects from the root node
+
+ [index] Selects the index number JSON entity from an array or
+ object. If the JSON entity is one collection (has
+ Members & Members@odata.count), means to get the index
+ member in "Members". Index number >=1, 1 means to return
+ the first instance.
+
+ [XXX] Operation on JSON entity.
+ If the JSON entity is one collection (has Members &
+ Members@odata.count), means to get all elements in
+ "Members". If the JSON entity is one array, means to
+ get all elements in array. Others will match the nodename
+ directly (e.g. JSON_OBJECT, JSON_STRING, JSON_TRUE,
+ JSON_FALSE, JSON_INTEGER).
+
+ [nodename] Selects all the elements from an JSON entity that
+ contain a property named "nodename"
+
+ [name=value] Selects all the elements from an JSON entity where
+ the property "name" is equal to "value"
+
+ [name~value] Selects all the elements from an JSON entity where
+ the string property "name" is equal to "value" using
+ case insensitive comparison.
+
+ [name<value] Selects all the elements from an JSON entity where
+ the property "name" is less than "value"
+
+ [name<=value] Selects all the elements from an JSON entity where
+ the property "name" is less than or equal to "value"
+
+ [name>value] Selects all the elements from an JSON entity where
+ the property "name" is greater than "value"
+
+ [name>=value] Selects all the elements from an JSON entity where
+ the property "name" is greater than or equal to "value"
+
+ Some examples:
+
+ /v1/Chassis[1] - Will return the first Chassis instance.
+ /v1/Chassis[SKU=1234] - Will return all Chassis instances with a SKU field equal to 1234.
+ /v1/Systems[Storage] - Will return all the System instances that have Storage field populated.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_LIB_H_
+#define REDFISH_LIB_H_
+
+#include <Library/JsonLib.h>
+
+#include <Protocol/Http.h>
+#include <Protocol/EdkIIRedfishConfigHandler.h>
+
+#define ODATA_TYPE_NAME_MAX_SIZE 128
+#define ODATA_TYPE_MAX_SIZE 128
+
+///
+/// Library class public defines
+///
+typedef VOID* REDFISH_SERVICE;
+typedef VOID* REDFISH_PAYLOAD;
+
+///
+/// Library class public structures/unions
+///
+typedef struct {
+ EFI_HTTP_STATUS_CODE *StatusCode;
+ UINTN HeaderCount;
+ EFI_HTTP_HEADER *Headers;
+ REDFISH_PAYLOAD Payload;
+} REDFISH_RESPONSE;
+
+///
+/// Odata type-name mapping structure.
+///
+typedef struct {
+ CONST CHAR8 OdataTypeName [ODATA_TYPE_NAME_MAX_SIZE];
+ CONST CHAR8 OdataType [ODATA_TYPE_MAX_SIZE];
+} REDFISH_ODATA_TYPE_MAPPING;
+
+/**
+ This function uses REST EX protocol provided in RedfishConfigServiceInfo.
+ The service enumerator will also handle the authentication flow automatically
+ if HTTP basic auth or Redfish session login is configured to use.
+
+ Callers are responsible for freeing the returned service by RedfishCleanupService().
+
+ @param[in] RedfishConfigServiceInfo Redfish service information the EFI Redfish
+ feature driver communicates with.
+
+ @return New created Redfish Service, or NULL if error happens.
+
+**/
+REDFISH_SERVICE
+EFIAPI
+RedfishCreateService (
+ IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo
+ );
+
+/**
+ Free the Service and all its related resources.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+
+**/
+VOID
+EFIAPI
+RedfishCleanupService (
+ IN REDFISH_SERVICE RedfishService
+ );
+
+/**
+ Create REDFISH_PAYLOAD instance in local with JSON represented resource value and
+ the Redfish Service.
+
+ The returned REDFISH_PAYLOAD can be used to create or update Redfish resource in
+ server side.
+
+ Callers are responsible for freeing the returned payload by RedfishCleanupPayload().
+
+ @param[in] Value JSON Value of the redfish resource.
+ @param[in] RedfishService The Service to access the Redfish resources.
+
+ @return REDFISH_PAYLOAD instance of the resource, or NULL if error happens.
+
+**/
+REDFISH_PAYLOAD
+EFIAPI
+RedfishCreatePayload (
+ IN EDKII_JSON_VALUE Value,
+ IN REDFISH_SERVICE RedfishService
+ );
+
+/**
+ Free the RedfishPayload and all its related resources.
+
+ @param[in] Payload Payload to be freed.
+
+**/
+VOID
+EFIAPI
+RedfishCleanupPayload (
+ IN REDFISH_PAYLOAD Payload
+ );
+
+/**
+ This function returns the decoded JSON value of a REDFISH_PAYLOAD.
+
+ Caller doesn't need to free the returned JSON value because it will be released
+ in corresponding RedfishCleanupPayload() function.
+
+ @param[in] Payload A REDFISH_PAYLOAD instance.
+
+ @return Decoded JSON value of the payload.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+RedfishJsonInPayload (
+ IN REDFISH_PAYLOAD Payload
+ );
+
+/**
+ Fill the input RedPath string with system UUID from SMBIOS table or use the customized
+ ID if FromSmbios == FALSE.
+
+ This is a helper function to build a RedPath string which can be used to address
+ a Redfish resource for this computer system. The input PathString must have a Systems
+ note in format of "Systems[UUID=%g]" or "Systems[UUID~%g]" to fill the UUID value.
+
+ Example:
+ Use "/v1/Systems[UUID=%g]/Bios" to build a RedPath to address the "Bios" resource
+ for this computer system.
+
+ @param[in] RedPath RedPath format to be build.
+ @param[in] FromSmbios Get system UUID from SMBIOS as computer system instance ID.
+ @param[in] IdString The computer system instance ID.
+
+ @return Full RedPath with system UUID inside, or NULL if error happens.
+
+**/
+CHAR8 *
+EFIAPI
+RedfishBuildPathWithSystemUuid (
+ IN CONST CHAR8 *RedPath,
+ IN BOOLEAN FromSmbios,
+ IN CHAR8 *IdString OPTIONAL
+ );
+
+/**
+ Get a redfish response addressed by a RedPath string, including HTTP StatusCode, Headers
+ and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+ @param[in] RedPath RedPath string to address a resource, must start
+ from the root node.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The corresponding redfish resource has
+ been returned in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER RedfishService, RedPath, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned Payload is NULL, indicates any error happen.
+ 2. If the returned StatusCode is NULL, indicates any error happen.
+ 3. If the returned StatusCode is not 2XX, indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishGetByService (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *RedPath,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Get a redfish response addressed by URI, including HTTP StatusCode, Headers
+ and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the URI resources.
+ @param[in] URI String to address a resource.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The corresponding redfish resource has
+ been returned in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER RedfishService, RedPath, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned Payload is NULL, indicates any error happen.
+ 2. If the returned StatusCode is NULL, indicates any error happen.
+ 3. If the returned StatusCode is not 2XX, indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishGetByUri (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *Uri,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Get a redfish response addressed by the input Payload and relative RedPath string,
+ including HTTP StatusCode, Headers and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] Payload A existing REDFISH_PAYLOAD instance.
+ @param[in] RedPath Relative RedPath string to address a resource inside Payload.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful:
+ 1. The HTTP StatusCode is NULL and the returned Payload in
+ RedResponse is not NULL, indicates the Redfish resource has
+ been parsed from the input payload directly.
+ 2. The HTTP StatusCode is not NULL and the value is 2XX,
+ indicates the corresponding redfish resource has been returned
+ in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER Payload, RedPath, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned Payload is NULL, indicates any error happen.
+ 2. If StatusCode is not NULL and the returned value of StatusCode
+ is not 2XX, indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishGetByPayload (
+ IN REDFISH_PAYLOAD Payload,
+ IN CONST CHAR8 *RedPath,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Use HTTP PATCH to perform updates on pre-existing Redfish resource.
+
+ This function uses the RedfishService to patch a Redfish resource addressed by
+ Uri (only the relative path is required). Changes to one or more properties within
+ the target resource are represented in the input Content, properties not specified
+ in Content won't be changed by this request. The corresponding redfish response will
+ returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
+ messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+ @param[in] Uri Relative path to address the resource.
+ @param[in] Content JSON represented properties to be update.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The Redfish resource will be returned
+ in Payload within RedResponse if server send it back in the HTTP
+ response message body.
+ @retval EFI_INVALID_PARAMETER RedfishService, Uri, Content, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishPatchToUri (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *Uri,
+ IN CONST CHAR8 *Content,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Use HTTP PATCH to perform updates on target payload. Patch to odata.id in Payload directly.
+
+ This function uses the Payload to patch the Target. Changes to one or more properties
+ within the target resource are represented in the input Payload, properties not specified
+ in Payload won't be changed by this request. The corresponding redfish response will
+ returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
+ messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] Target The target payload to be updated.
+ @param[in] Payload Palyoad with properties to be changed.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The Redfish resource will be returned
+ in Payload within RedResponse if server send it back in the HTTP
+ response message body.
+ @retval EFI_INVALID_PARAMETER Target, Payload, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishPatchToPayload (
+ IN REDFISH_PAYLOAD Target,
+ IN REDFISH_PAYLOAD Payload,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Use HTTP POST to create a new resource in target payload.
+
+ The POST request should be submitted to the Resource Collection in which the new resource
+ is to belong. The Resource Collection is addressed by Target payload. The Redfish may
+ ignore any service controlled properties. The corresponding redfish response will returned,
+ including HTTP StatusCode, Headers and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] Target Target payload of the Resource Collection.
+ @param[in] Payload The new resource to be created.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The Redfish resource will be returned
+ in Payload within RedResponse if server send it back in the HTTP
+ response message body.
+ @retval EFI_INVALID_PARAMETER Target, Payload, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishPostToPayload (
+ IN REDFISH_PAYLOAD Target,
+ IN REDFISH_PAYLOAD Payload,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Use HTTP DELETE to remove a resource.
+
+ This function uses the RedfishService to remove a Redfish resource which is addressed
+ by input Uri (only the relative path is required). The corresponding redfish response will
+ returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
+ messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+ @param[in] Uri Relative path to address the resource.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX, the Redfish resource has been removed.
+ If there is any message returned from server, it will be returned
+ in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER RedfishService, Uri, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishDeleteByUri (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *Uri,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Dump text in fractions.
+
+ @param[in] String ASCII string to dump.
+
+**/
+VOID
+RedfishDumpJsonStringFractions (
+ IN CHAR8 *String
+ );
+
+/**
+ Extract the JSON text content from REDFISH_PAYLOAD and dump to debug console.
+
+ @param[in] Payload The Redfish payload to dump.
+
+**/
+VOID
+RedfishDumpPayload (
+ IN REDFISH_PAYLOAD Payload
+ );
+/**
+ Dump text in JSON value.
+
+ @param[in] JsonValue The Redfish JSON value to dump.
+
+**/
+VOID
+RedfishDumpJson (
+ IN EDKII_JSON_VALUE JsonValue
+ );
+/**
+ This function will cleanup the HTTP header and Redfish payload resources.
+
+ @param[in] StatusCode The status code in HTTP response message.
+ @param[in] HeaderCount Number of HTTP header structures in Headers list.
+ @param[in] Headers Array containing list of HTTP headers.
+ @param[in] Payload The Redfish payload to dump.
+
+**/
+VOID
+RedfishFreeResponse (
+ IN EFI_HTTP_STATUS_CODE *StatusCode,
+ IN UINTN HeaderCount,
+ IN EFI_HTTP_HEADER *Headers,
+ IN REDFISH_PAYLOAD Payload
+ );
+
+/**
+ Check if the "@odata.type" in Payload is valid or not.
+
+ @param[in] Payload The Redfish payload to be checked.
+ @param[in] OdataTypeName OdataType will be retrived from mapping list.
+ @param[in] OdataTypeMappingList The list of OdataType.
+ @param[in] OdataTypeMappingListSize The number of mapping list
+
+ @return TRUE if the "@odata.type" in Payload is valid, otherwise FALSE.
+
+**/
+BOOLEAN
+RedfishIsValidOdataType (
+ IN REDFISH_PAYLOAD Payload,
+ IN CONST CHAR8 *OdataTypeName,
+ IN REDFISH_ODATA_TYPE_MAPPING *OdataTypeMappingList,
+ IN UINTN OdataTypeMappingListSize
+ );
+
+/**
+ Check if the payload is collection
+
+ @param[in] Payload The Redfish payload to be checked.
+
+ @return TRUE if the payload is collection.
+
+**/
+BOOLEAN
+RedfishIsPayloadCollection (
+ IN REDFISH_PAYLOAD Payload
+);
+/**
+ Get collection size.
+
+ @param[in] Payload The Redfish collection payload
+ @param[in] CollectionSize Size of this collection
+
+ @return EFI_SUCCESS Coolection size is returned in CollectionSize
+ @return EFI_INVALID_PARAMETER The payload is not a collection.
+**/
+EFI_STATUS
+RedfishGetCollectionSize(
+ IN REDFISH_PAYLOAD Payload,
+ IN UINTN *CollectionSize
+);
+/**
+ Get Redfish payload of collection member
+
+ @param[in] Payload The Redfish collection payload
+ @param[in] Index Index of collection member
+
+ @return NULL Fail to get collection member.
+ @return Non NULL Payload is returned.
+**/
+REDFISH_PAYLOAD
+RedfishGetPayloadByIndex (
+ IN REDFISH_PAYLOAD Payload,
+ IN UINTN Index
+);
+
+/**
+ Check and return Redfish resource of the given Redpath.
+
+ @param[in] RedfishService Pointer to REDFISH_SERVICE
+ @param[in] Redpath Redpath of the resource.
+ @param[in] Response Optional return the resource.
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+RedfishCheckIfRedpathExist (
+ IN REDFISH_SERVICE RedfishService,
+ IN CHAR8 *Redpath,
+ IN REDFISH_RESPONSE *Response OPTIONAL
+);
+
+/**
+ This function returns the string of Redfish service version.
+
+ @param[in] RedfishService Redfish service instance.
+ @param[out] ServiceVersionStr Redfish service string.
+
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+RedfishGetServiceVersion(
+ IN REDFISH_SERVICE RedfishService,
+ OUT CHAR8 **ServiceVersionStr
+ );
+
+/**
+ This function returns the string of Redfish service version.
+
+ @param[in] ServiceVerisonStr The string of Redfish service version.
+ @param[in] Url The URL to build Redpath with ID.
+ Start with "/", for example "/Registries"
+ @param[in] Id ID string
+ @param[out] Redpath Pointer to retrive Redpath, caller has to free
+ the memory allocated for this string.
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+RedfishBuildRedpathUseId (
+ IN CHAR8 *ServiceVerisonStr,
+ IN CHAR8 *Url,
+ IN CHAR8 *Id,
+ OUT CHAR8 **Redpath
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c
new file mode 100644
index 00000000..401c8084
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c
@@ -0,0 +1,929 @@
+/** @file
+ CRT wrapper functions for system call,the string operation functions
+ are remodeled after edk2-libc.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Library/RedfishCrtLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+int errno = 0;
+char errnum_message [] = "We don't support to map errnum to the error message on edk2 Redfish\n";
+
+// This is required to keep VC++ happy if you use floating-point
+int _fltused = 1;
+
+/**
+ Determine if a particular character is an alphanumeric character
+ @return Returns 1 if c is an alphanumeric character, otherwise returns 0.
+**/
+int isalnum (int c)
+{
+ //
+ // <alnum> ::= [0-9] | [a-z] | [A-Z]
+ //
+ return ((('0' <= (c)) && ((c) <= '9')) ||
+ (('a' <= (c)) && ((c) <= 'z')) ||
+ (('A' <= (c)) && ((c) <= 'Z')));
+}
+
+/**
+ Determine if a particular character is a digital character
+
+ @return Returns 1 if c is an digital character, otherwise returns 0.
+**/
+int isdchar (int c)
+{
+ //
+ // [0-9] | [e +-.]
+ //
+ return ((('0' <= (c)) && ((c) <= '9')) ||
+ (c == 'e') || (c == 'E') ||
+ (c == '+') || (c == '-') ||
+ (c == '.'));
+}
+
+/**
+ Determine if a particular character is a space character
+
+ @return Returns 1 if c is a space character
+**/
+int isspace (int c)
+{
+ //
+ // <space> ::= [ ]
+ //
+ return ((c) == ' ') || ((c) == '\t') || ((c) == '\r') || ((c) == '\n') || ((c) == '\v') || ((c) == '\f');
+}
+
+/**
+ Allocates memory blocks
+*/
+void *malloc (size_t size)
+{
+ return AllocatePool ((UINTN) size);
+}
+
+/**
+ De-allocates or frees a memory block
+*/
+void free (void *ptr)
+{
+ //
+ // In Standard C, free() handles a null pointer argument transparently. This
+ // is not true of FreePool() below, so protect it.
+ //
+ if (ptr != NULL) {
+ FreePool (ptr);
+ }
+}
+
+/**
+ NetBSD Compatibility Function strdup creates a duplicate copy of a string.
+
+ @return Returns the pointer to duplicated string.
+**/
+char * strdup(const char *str)
+{
+ size_t len;
+ char *copy;
+
+ len = strlen(str) + 1;
+ if ((copy = malloc(len)) == NULL)
+ return (NULL);
+ memcpy(copy, str, len);
+ return (copy);
+}
+
+/** The toupper function converts a lowercase letter to a corresponding
+ uppercase letter.
+
+ @param[in] c The character to be converted.
+
+ @return If the argument is a character for which islower is true and
+ there are one or more corresponding characters, as specified by
+ the current locale, for which isupper is true, the toupper
+ function returns one of the corresponding characters (always the
+ same one for any given locale); otherwise, the argument is
+ returned unchanged.
+**/
+int
+toupper(
+ IN int c
+ )
+{
+ if ( (c >= 'a') && (c <= 'z') ) {
+ c = c - ('a' - 'A');
+ }
+ return c;
+}
+
+/**
+ Digit to a value.
+
+ @return Returns the value of digit.
+**/
+int
+Digit2Val( int c)
+{
+ if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) { /* If c is one of [A-Za-z]... */
+ c = toupper(c) - 7; // Adjust so 'A' is ('9' + 1)
+ }
+ return c - '0'; // Value returned is between 0 and 35, inclusive.
+}
+
+
+/** The strtoll function converts the initial portion of the string pointed to
+ by nptr to long long int representation.
+
+ See the description for strtol for more information.
+
+ @return The strtoll function returns the converted value, if any. If no
+ conversion could be performed, zero is returned. If the correct
+ value is outside the range of representable values, LLONG_MIN or
+ LLONG_MAX is returned (according to the sign of the value, if any),
+ and the value of the macro ERANGE is stored in errno.
+**/
+long long
+strtoll(const char * nptr, char ** endptr, int base)
+{
+ const char *pEnd;
+ long long Result = 0;
+ long long Previous;
+ int temp;
+ BOOLEAN Negative = FALSE;
+
+ pEnd = nptr;
+
+ if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
+ *endptr = NULL;
+ }
+ return 0;
+ }
+ // Skip leading spaces.
+ while(isspace(*nptr)) ++nptr;
+
+ // Process Subject sequence: optional sign followed by digits.
+ if(*nptr == '+') {
+ Negative = FALSE;
+ ++nptr;
+ }
+ else if(*nptr == '-') {
+ Negative = TRUE;
+ ++nptr;
+ }
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
+ }
+
+ while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
+ Previous = Result;
+ Result = MultS64x64 (Result, base) + (long long int)temp;
+ if( Result <= Previous) { // Detect Overflow
+ if(Negative) {
+ Result = LLONG_MIN;
+ }
+ else {
+ Result = LLONG_MAX;
+ }
+ Negative = FALSE;
+ errno = ERANGE;
+ break;
+ }
+ pEnd = ++nptr;
+ }
+ if(Negative) {
+ Result = -Result;
+ }
+
+ // Save pointer to final sequence
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
+ }
+ return Result;
+}
+
+/** The strtol, strtoll, strtoul, and strtoull functions convert the initial
+ portion of the string pointed to by nptr to long int, long long int,
+ unsigned long int, and unsigned long long int representation, respectively.
+ First, they decompose the input string into three parts: an initial,
+ possibly empty, sequence of white-space characters (as specified by the
+ isspace function), a subject sequence resembling an integer represented in
+ some radix determined by the value of base, and a final string of one or
+ more unrecognized characters, including the terminating null character of
+ the input string. Then, they attempt to convert the subject sequence to an
+ integer, and return the result.
+
+ If the value of base is zero, the expected form of the subject sequence is
+ that of an integer constant, optionally preceded
+ by a plus or minus sign, but not including an integer suffix. If the value
+ of base is between 2 and 36 (inclusive), the expected form of the subject
+ sequence is a sequence of letters and digits representing an integer with
+ the radix specified by base, optionally preceded by a plus or minus sign,
+ but not including an integer suffix. The letters from a (or A) through z
+ (or Z) are ascribed the values 10 through 35; only letters and digits whose
+ ascribed values are less than that of base are permitted. If the value of
+ base is 16, the characters 0x or 0X may optionally precede the sequence of
+ letters and digits, following the sign if present.
+
+ The subject sequence is defined as the longest initial subsequence of the
+ input string, starting with the first non-white-space character, that is of
+ the expected form. The subject sequence contains no characters if the input
+ string is empty or consists entirely of white space, or if the first
+ non-white-space character is other than a sign or a permissible letter or digit.
+
+ If the subject sequence has the expected form and the value of base is
+ zero, the sequence of characters starting with the first digit is
+ interpreted as an integer constant. If the subject sequence has the
+ expected form and the value of base is between 2 and 36, it is used as the
+ base for conversion, ascribing to each letter its value as given above. If
+ the subject sequence begins with a minus sign, the value resulting from the
+ conversion is negated (in the return type). A pointer to the final string
+ is stored in the object pointed to by endptr, provided that endptr is
+ not a null pointer.
+
+ In other than the "C" locale, additional locale-specific subject sequence
+ forms may be accepted.
+
+ If the subject sequence is empty or does not have the expected form, no
+ conversion is performed; the value of nptr is stored in the object pointed
+ to by endptr, provided that endptr is not a null pointer.
+
+ @return The strtol, strtoll, strtoul, and strtoull functions return the
+ converted value, if any. If no conversion could be performed, zero
+ is returned. If the correct value is outside the range of
+ representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX,
+ ULONG_MAX, or ULLONG_MAX is returned (according to the return type
+ and sign of the value, if any), and the value of the macro ERANGE
+ is stored in errno.
+**/
+long
+strtol(const char * nptr, char ** endptr, int base)
+{
+ const char *pEnd;
+ long Result = 0;
+ long Previous;
+ int temp;
+ BOOLEAN Negative = FALSE;
+
+ pEnd = nptr;
+
+ if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
+ *endptr = NULL;
+ }
+ return 0;
+ }
+ // Skip leading spaces.
+ while(isspace(*nptr)) ++nptr;
+
+ // Process Subject sequence: optional sign followed by digits.
+ if(*nptr == '+') {
+ Negative = FALSE;
+ ++nptr;
+ }
+ else if(*nptr == '-') {
+ Negative = TRUE;
+ ++nptr;
+ }
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
+ }
+
+ while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
+ Previous = Result;
+ Result = (Result * base) + (long int)temp;
+ if( Result <= Previous) { // Detect Overflow
+ if(Negative) {
+ Result = LONG_MIN;
+ }
+ else {
+ Result = LONG_MAX;
+ }
+ Negative = FALSE;
+ errno = ERANGE;
+ break;
+ }
+ pEnd = ++nptr;
+ }
+ if(Negative) {
+ Result = -Result;
+ }
+
+ // Save pointer to final sequence
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
+ }
+ return Result;
+}
+
+/** The strtoull function converts the initial portion of the string pointed to
+ by nptr to unsigned long long int representation.
+
+ See the description for strtol for more information.
+
+ @return The strtoull function returns the converted value, if any. If no
+ conversion could be performed, zero is returned. If the correct
+ value is outside the range of representable values, ULLONG_MAX is
+ returned and the value of the macro ERANGE is stored in errno.
+**/
+unsigned long long
+strtoull(const char * nptr, char ** endptr, int base)
+{
+ const char *pEnd;
+ unsigned long long Result = 0;
+ unsigned long long Previous;
+ int temp;
+
+ pEnd = nptr;
+
+ if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
+ *endptr = NULL;
+ }
+ return 0;
+ }
+ // Skip leading spaces.
+ while(isspace(*nptr)) ++nptr;
+
+ // Process Subject sequence: optional + sign followed by digits.
+ if(*nptr == '+') {
+ ++nptr;
+ }
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
+ }
+
+ while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
+ Previous = Result;
+ Result = DivU64x32 (Result, base) + (unsigned long long)temp;
+ if( Result < Previous) { // If we overflowed
+ Result = ULLONG_MAX;
+ errno = ERANGE;
+ break;
+ }
+ pEnd = ++nptr;
+ }
+
+ // Save pointer to final sequence
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
+ }
+ return Result;
+}
+
+/**
+ edk2 Jansson port does not support doubles, simply return 0.
+
+ These conversion functions convert the initial portion of the string
+ pointed to by nptr to double, float, and long double representation,
+ respectively.
+
+ The strtod(), strtof(), and strtold() functions return the converted
+ value, if any.
+
+ If endptr is not NULL, a pointer to the character after the last charac-
+ ter used in the conversion is stored in the location referenced by
+ endptr.
+
+ If no conversion is performed, zero is returned and the value of nptr is
+ stored in the location referenced by endptr.
+
+ If the correct value would cause overflow, plus or minus HUGE_VAL,
+ HUGE_VALF, or HUGE_VALL is returned (according to the sign and type of
+ the return value), and ERANGE is stored in errno. If the correct value
+ would cause underflow, zero is returned and ERANGE is stored in errno.
+
+ @return Return 0.
+**/
+double
+strtod (const char * __restrict nptr, char ** __restrict endptr) {
+
+ DEBUG((DEBUG_INFO, "We don't supprot double type on edk2 yet!"));
+ ASSERT(FALSE);
+ return (double)0;
+}
+
+static UINT8 BitMask[] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
+ };
+
+#define WHICH8(c) ((unsigned char)(c) >> 3)
+#define WHICH_BIT(c) (BitMask[((c) & 0x7)])
+#define BITMAP64 ((UINT64 *)bitmap)
+
+static
+void
+BuildBitmap(unsigned char * bitmap, const char *s2, int n)
+{
+ unsigned char bit;
+ int index;
+
+ // Initialize bitmap. Bit 0 is always 1 which corresponds to '\0'
+ for (BITMAP64[0] = index = 1; index < n; index++) {
+ BITMAP64[index] = 0;
+ }
+
+ // Set bits in bitmap corresponding to the characters in s2
+ for (; *s2 != '\0'; s2++) {
+ index = WHICH8(*s2);
+ bit = WHICH_BIT(*s2);
+ bitmap[index] = bitmap[index] | bit;
+ }
+}
+
+/** The strpbrk function locates the first occurrence in the string pointed to
+ by s1 of any character from the string pointed to by s2.
+
+ @return The strpbrk function returns a pointer to the character, or a
+ null pointer if no character from s2 occurs in s1.
+**/
+char *
+strpbrk(const char *s1, const char *s2)
+{
+ UINT8 bitmap[ (((UCHAR_MAX + 1) / CHAR_BIT) + (CHAR_BIT - 1)) & ~7U];
+ UINT8 bit;
+ int index;
+
+ BuildBitmap( bitmap, s2, sizeof(bitmap) / sizeof(UINT64));
+
+ for( ; *s1 != '\0'; ++s1) {
+ index = WHICH8(*s1);
+ bit = WHICH_BIT(*s1);
+ if( (bitmap[index] & bit) != 0) {
+ return (char *)s1;
+ }
+ }
+ return NULL;
+}
+
+/** The strerror function maps the number in errnum to a message string.
+ Typically, the values for errnum come from errno, but strerror shall map
+ any value of type int to a message.
+
+ The implementation shall behave as if no library function calls the
+ strerror function.
+
+ @return The strerror function returns a pointer to the string, the
+ contents of which are locale specific. The array pointed to
+ shall not be modified by the program, but may be overwritten by
+ a subsequent call to the strerror function.
+**/
+char *
+strerror(int errnum)
+{
+ return errnum_message;
+}
+
+/**
+ Allocate and zero-initialize array.
+**/
+void *
+calloc(size_t Num, size_t Size)
+{
+ void *RetVal;
+ size_t NumSize;
+
+ NumSize = Num * Size;
+ RetVal = NULL;
+ if (NumSize != 0) {
+ RetVal = malloc(NumSize);
+ if( RetVal != NULL) {
+ (VOID)ZeroMem( RetVal, NumSize);
+ }
+ }
+ DEBUG((DEBUG_POOL, "0x%p = calloc(%d, %d)\n", RetVal, Num, Size));
+
+ return RetVal;
+}
+
+//
+// The arrays give the cumulative number of days up to the first of the
+// month number used as the index (1 -> 12) for regular and leap years.
+// The value at index 13 is for the whole year.
+//
+UINTN CumulativeDays[2][14] = {
+ {
+ 0,
+ 0,
+ 31,
+ 31 + 28,
+ 31 + 28 + 31,
+ 31 + 28 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
+ },
+ {
+ 0,
+ 0,
+ 31,
+ 31 + 29,
+ 31 + 29 + 31,
+ 31 + 29 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
+ }
+};
+
+#define IsLeap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+#define SECSPERMIN (60)
+#define SECSPERHOUR (60 * 60)
+#define SECSPERDAY (24 * SECSPERHOUR)
+
+/**
+ Get the system time as seconds elapsed since midnight, January 1, 1970.
+**/
+time_t time (time_t *timer)
+{
+ EFI_TIME Time;
+ time_t CalTime;
+ UINTN Year;
+
+ //
+ // Get the current time and date information
+ //
+ gRT->GetTime (&Time, NULL);
+
+ //
+ // Years Handling
+ // UTime should now be set to 00:00:00 on Jan 1 of the current year.
+ //
+ for (Year = 1970, CalTime = 0; Year != Time.Year; Year++) {
+ CalTime = CalTime + (time_t)(CumulativeDays[IsLeap(Year)][13] * SECSPERDAY);
+ }
+
+ //
+ // Add in number of seconds for current Month, Day, Hour, Minute, Seconds, and TimeZone adjustment
+ //
+ CalTime = CalTime +
+ (time_t)((Time.TimeZone != EFI_UNSPECIFIED_TIMEZONE) ? (Time.TimeZone * 60) : 0) +
+ (time_t)(CumulativeDays[IsLeap(Time.Year)][Time.Month] * SECSPERDAY) +
+ (time_t)(((Time.Day > 0) ? Time.Day - 1 : 0) * SECSPERDAY) +
+ (time_t)(Time.Hour * SECSPERHOUR) +
+ (time_t)(Time.Minute * 60) +
+ (time_t)Time.Second;
+
+ if (timer != NULL) {
+ *timer = CalTime;
+ }
+
+ return CalTime;
+}
+
+/**
+ Performs a quick sort
+**/
+void qsort (void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
+{
+
+ ASSERT (base != NULL);
+ ASSERT (compare != NULL);
+
+ PerformQuickSort (base, (UINTN)num, (UINTN)width, (SORT_COMPARE)compare);
+ return;
+}
+
+/**
+ Get character from stream, we don't support file operastion on edk2 JSON library.
+
+ @return Returns the character currently pointed by the internal file position indicator of the specified stream
+
+**/
+int fgetc(FILE * _File){
+ return EOF;
+}
+/**
+ Open stream file, we don't support file operastion on edk2 JSON library.
+
+ @return 0 Unsupported
+
+**/
+FILE *fopen (const char *filename, const char *mode) {
+ return NULL;
+}
+/**
+ Read stream from file, we don't support file operastion on edk2 JSON library.
+
+ @return 0 Unsupported
+
+**/
+size_t fread (void * ptr, size_t size, size_t count, FILE * stream) {
+ return 0;
+}
+/**
+ Write stream from file, we don't support file operastion on edk2 JSON library.
+
+ @return 0 Unsupported
+
+**/
+size_t fwrite (const void * ptr, size_t size, size_t count, FILE * stream) {
+ return 0;
+}
+/**
+ Close file, we don't support file operastion on edk2 JSON library.
+
+ @return 0 Unsupported
+
+**/
+int fclose (FILE * stream) {
+ return EOF;
+}
+/**
+ Write the formatted string to file, we don't support file operastion on edk2 JSON library.
+
+ @return 0 Unsupported
+
+**/
+int fprintf (FILE * stream, const char * format, ...) {
+ return -1;
+}
+/**
+ This function check if this is the formating string specifier.
+
+ @param[in] FormatString A Null-terminated ASCII format string.
+ @param[in,out] CurrentPosition The starting position at the given string to check for
+ "[flags][width][.precision][length]s" string specifier.
+ @param[in] StrLength Maximum string length.
+
+ @return BOOLEAN TRUE means this is the formating string specifier. CurrentPosition is
+ returned at the position of "s".
+ FALSE means this is not the formating string specifier.. CurrentPosition is
+ returned at the position of failed character.
+
+**/
+BOOLEAN
+CheckFormatingString (
+ IN CONST CHAR8 *FormatString,
+ IN OUT UINTN *CurrentPosition,
+ IN UINTN StrLength
+ )
+{
+ CHAR8 FormatStringParamater;
+
+ while (*(FormatString + *CurrentPosition) != 's') {
+ //
+ // Loop until reach character 's' if the formating string is
+ // compliant with "[flags][width][.precision][length]" format for
+ // the string specifier.
+ //
+ FormatStringParamater = *(FormatString + *CurrentPosition);
+ if ((FormatStringParamater != '-') &&
+ (FormatStringParamater != '+') &&
+ (FormatStringParamater != '*') &&
+ (FormatStringParamater != '.') &&
+ !(((UINTN)FormatStringParamater >= (UINTN)'0') && ((UINTN)FormatStringParamater <= (UINTN)'9'))
+ ) {
+ return FALSE;
+ }
+ (*CurrentPosition)++;
+ if (*CurrentPosition >= StrLength) {
+ return FALSE;
+ }
+ };
+ return TRUE;
+}
+
+/**
+ This function clones *FormatString however replaces "%s" with "%a" in the
+ returned string.
+
+ @param[in] A Null-terminated ASCII format string.
+
+ @return The new format string. Caller has to free the memory of this string
+ using FreePool().
+
+**/
+CHAR8 *
+ReplaceUnicodeToAsciiStrFormat (
+ IN CONST CHAR8 *FormatString
+)
+{
+ UINTN FormatStrSize;
+ UINTN FormatStrIndex;
+ UINTN FormatStrSpecifier;
+ BOOLEAN PercentageMark;
+ CHAR8 *TempFormatBuffer;
+ BOOLEAN IsFormatString;
+
+ //
+ // Error checking.
+ //
+ if (FormatString == NULL) {
+ return NULL;
+ }
+ FormatStrSize = AsciiStrSize(FormatString);
+ if (FormatStrSize == 0) {
+ return NULL;
+ }
+ TempFormatBuffer = AllocatePool(FormatStrSize); // Allocate memory for the
+ // new string.
+ if (TempFormatBuffer== NULL) {
+ return NULL;
+ }
+ //
+ // Clone *FormatString but replace "%s" wih "%a".
+ // "%%" is not considered as the format tag.
+ //
+ PercentageMark = FALSE;
+ FormatStrIndex = 0;
+ while (FormatStrIndex < FormatStrSize) {
+ if (PercentageMark == TRUE) {
+ //
+ // Previous character is "%".
+ //
+ PercentageMark = FALSE;
+ if (*(FormatString + FormatStrIndex) != '%') { // Check if this is double "%".
+ FormatStrSpecifier = FormatStrIndex;
+ //
+ // Check if this is the formating string specifier.
+ //
+ IsFormatString = CheckFormatingString (FormatString, &FormatStrSpecifier, FormatStrSize);
+ if ((FormatStrSpecifier - FormatStrIndex) != 0) {
+ CopyMem((VOID *)(TempFormatBuffer + FormatStrIndex),
+ (VOID *)(FormatString + FormatStrIndex),
+ FormatStrSpecifier - FormatStrIndex
+ );
+ }
+ FormatStrIndex = FormatStrSpecifier;
+ if (IsFormatString == TRUE) {
+ //
+ // Replace 's' with 'a' which is printed in ASCII
+ // format on edk2 environment.
+ //
+ *(TempFormatBuffer + FormatStrSpecifier) = 'a';
+ FormatStrIndex ++;
+ }
+ continue;
+ }
+ goto ContinueCheck;
+ }
+ if (*(FormatString + FormatStrIndex) == '%') {
+ //
+ // This character is "%", set the flag.
+ //
+ PercentageMark = TRUE;
+ }
+ContinueCheck:
+ //
+ // Clone character to the new string and advance FormatStrIndex
+ // to process next character.
+ //
+ *(TempFormatBuffer + FormatStrIndex) = *(FormatString + FormatStrIndex);
+ FormatStrIndex++;
+ };
+ return TempFormatBuffer;
+}
+
+/**
+ This is the Redfish version of CRT vsnprintf function, this function replaces "%s" to
+ "%a" before invoking AsciiVSPrint(). That is because "%s" is unicode base on edk2
+ environment however "%s" is ascii code base on vsnprintf().
+ See definitions of AsciiVSPrint() for the details.
+
+ @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString A Null-terminated ASCII format string.
+ @param Marker VA_LIST marker for the variable argument list.
+
+ @return The number of ASCII characters in the produced output buffer not including the
+ Null-terminator.
+
+**/
+UINTN
+EFIAPI
+RedfishAsciiVSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ IN VA_LIST Marker
+ )
+{
+ CHAR8 *TempFormatBuffer;
+ UINTN LenStrProduced;
+
+ //
+ // Looking for "%s" in the format string and replace it
+ // with "%a" for printing ASCII code characters on edk2
+ // environment.
+ //
+ TempFormatBuffer = ReplaceUnicodeToAsciiStrFormat (FormatString);
+ if (TempFormatBuffer == NULL) {
+ return 0;
+ }
+ LenStrProduced = AsciiVSPrint (StartOfBuffer, BufferSize, (CONST CHAR8 *)TempFormatBuffer, Marker);
+ FreePool (TempFormatBuffer);
+ return LenStrProduced;
+}
+
+/**
+ This is the Redfish version of CRT snprintf function, this function replaces "%s" to
+ "%a" before invoking AsciiSPrint(). That is because "%s" is unicode base on edk2
+ environment however "%s" is ascii code base on snprintf().
+ See definitions of AsciiSPrint() for the details.
+
+ @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString A Null-terminated ASCII format string.
+ @param ... Variable argument list whose contents are accessed based on the
+ format string specified by FormatString.
+
+ @return The number of ASCII characters in the produced output buffer not including the
+ Null-terminator.
+
+**/
+UINTN
+EFIAPI
+RedfishAsciiSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ ...
+ )
+{
+ VA_LIST Marker;
+ UINTN LenStrProduced;
+
+ VA_START(Marker, FormatString);
+ LenStrProduced = RedfishAsciiVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);
+ return LenStrProduced;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
new file mode 100644
index 00000000..4dc6be76
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
@@ -0,0 +1,38 @@
+## @file
+# Redfish C Runtime Library for opensource projects.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = RedfishCrtLib
+ FILE_GUID = 8263B8AC-D021-425D-B337-3EC96F5DC19B
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RedfishCrtLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ RedfishCrtLib.c
+
+[LibraryClasses]
+ BaseLib
+ BaseSortLib
+ DebugLib
+ MemoryAllocationLib
+ UefiRuntimeServicesTableLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.c
new file mode 100644
index 00000000..3a50f3dc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.c
@@ -0,0 +1,993 @@
+/** @file
+ Provides a set of utility APIs that allow to create/read/update/delete
+ (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>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishMisc.h"
+
+/**
+ This function uses REST EX protocol provided in RedfishConfigServiceInfo.
+ The service enumerator will also handle the authentication flow automatically
+ if HTTP basic auth or Redfish session login is configured to use.
+
+ Callers are responsible for freeing the returned service by RedfishCleanupService().
+
+ @param[in] RedfishConfigServiceInfo Redfish service information the EFI Redfish
+ feature driver communicates with.
+
+ @return New created Redfish Service, or NULL if error happens.
+
+**/
+REDFISH_SERVICE
+EFIAPI
+RedfishCreateService (
+ IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo
+ )
+{
+ REDFISH_SERVICE RedfishService;
+ EDKII_REDFISH_AUTH_METHOD AuthMethod;
+ CHAR8 *UserId;
+ CHAR8 *Password;
+ EFI_STATUS Status;
+
+ RedfishService = NULL;
+ UserId = NULL;
+ Password = NULL;
+
+ //
+ // Check Input Parameters.
+ //
+ if (RedfishConfigServiceInfo == NULL) {
+ return NULL;
+ }
+
+ //
+ // Get Authentication Configuration.
+ //
+ Status = RedfishGetAuthInfo (&AuthMethod, &UserId, &Password);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ //
+ // Create a redfish service node based on Redfish network host interface.
+ //
+ RedfishService = RedfishCreateLibredfishService (
+ RedfishConfigServiceInfo,
+ AuthMethod,
+ UserId,
+ Password
+ );
+
+ON_EXIT:
+ if (UserId != NULL) {
+ FreePool (UserId);
+ }
+ if (Password!= NULL) {
+ FreePool (Password);
+ }
+
+ return RedfishService;
+}
+
+/**
+ Free the Service and all its related resources.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+
+**/
+VOID
+EFIAPI
+RedfishCleanupService (
+ IN REDFISH_SERVICE RedfishService
+ )
+{
+ if (RedfishService == NULL) {
+ return;
+ }
+
+ cleanupServiceEnumerator (RedfishService);
+}
+/**
+ Create REDFISH_PAYLOAD instance in local with JSON represented resource value and
+ the Redfish Service.
+
+ The returned REDFISH_PAYLOAD can be used to create or update Redfish resource in
+ server side.
+
+ Callers are responsible for freeing the returned payload by RedfishCleanupPayload().
+
+ @param[in] Value JSON Value of the redfish resource.
+ @param[in] RedfishService The Service to access the Redfish resources.
+
+ @return REDFISH_PAYLOAD instance of the resource, or NULL if error happens.
+
+**/
+REDFISH_PAYLOAD
+EFIAPI
+RedfishCreatePayload (
+ IN EDKII_JSON_VALUE Value,
+ IN REDFISH_SERVICE RedfishService
+ )
+{
+ EDKII_JSON_VALUE CopyValue;
+
+ CopyValue = JsonValueClone (Value);
+ return createRedfishPayload (CopyValue, RedfishService);
+}
+
+/**
+ Free the RedfishPayload and all its related resources.
+
+ @param[in] Payload Payload to be freed.
+
+**/
+VOID
+EFIAPI
+RedfishCleanupPayload (
+ IN REDFISH_PAYLOAD Payload
+ )
+{
+ if (Payload == NULL) {
+ return;
+ }
+
+ cleanupPayload ((redfishPayload *) Payload);
+}
+
+/**
+ This function returns the decoded JSON value of a REDFISH_PAYLOAD.
+
+ Caller doesn't need to free the returned JSON value because it will be released
+ in corresponding RedfishCleanupPayload() function.
+
+ @param[in] Payload A REDFISH_PAYLOAD instance.
+
+ @return Decoded JSON value of the payload.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+RedfishJsonInPayload (
+ IN REDFISH_PAYLOAD Payload
+ )
+{
+ if (Payload == NULL) {
+ return NULL;
+ }
+
+ return ((redfishPayload*)Payload)->json;
+}
+
+/**
+ Fill the input RedPath string with system UUID from SMBIOS table or use the customized
+ ID if FromSmbios == FALSE.
+
+ This is a helper function to build a RedPath string which can be used to address
+ a Redfish resource for this computer system. The input PathString must have a Systems
+ note in format of "Systems[UUID=%g]" or "Systems[UUID~%g]" to fill the UUID value.
+
+ Example:
+ Use "/v1/Systems[UUID=%g]/Bios" to build a RedPath to address the "Bios" resource
+ for this computer system.
+
+ @param[in] RedPath RedPath format to be build.
+ @param[in] FromSmbios Get system UUID from SMBIOS as computer system instance ID.
+ @param[in] IdString The computer system instance ID.
+
+ @return Full RedPath with system UUID inside, or NULL if error happens.
+
+**/
+CHAR8 *
+EFIAPI
+RedfishBuildPathWithSystemUuid (
+ IN CONST CHAR8 *RedPath,
+ IN BOOLEAN FromSmbios,
+ IN CHAR8 *IdString OPTIONAL
+ )
+{
+ UINTN BufSize;
+ CHAR8* RetRedPath;
+ EFI_GUID SystemUuid;
+ EFI_STATUS Status;
+
+ if (RedPath == NULL) {
+ return NULL;
+ }
+
+ //
+ // Find system UUID from SMBIOS table.
+ //
+ if (FromSmbios) {
+ Status = NetLibGetSystemGuid(&SystemUuid);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+ // AsciiStrLen ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") = 36
+ BufSize = AsciiStrSize (RedPath) + AsciiStrLen ("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
+ } else {
+ BufSize = AsciiStrSize (RedPath) + AsciiStrLen (IdString);
+ }
+
+ RetRedPath = AllocateZeroPool (BufSize);
+ if (RetRedPath == NULL) {
+ return NULL;
+ }
+ if (FromSmbios) {
+ AsciiSPrint (RetRedPath, BufSize, RedPath, &SystemUuid);
+ } else {
+ AsciiSPrint (RetRedPath, BufSize, RedPath, IdString);
+ }
+ return RetRedPath;
+}
+/**
+ Get a redfish response addressed by a RedPath string, including HTTP StatusCode, Headers
+ and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+ @param[in] RedPath RedPath string to address a resource, must start
+ from the root node.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The corresponding redfish resource has
+ been returned in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER RedfishService, RedPath, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned Payload is NULL, indicates any error happen.
+ 2. If the returned StatusCode is NULL, indicates any error happen.
+ 3. If the returned StatusCode is not 2XX, indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishGetByService (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *RedPath,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ if (RedfishService == NULL || RedPath == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ RedResponse->Payload = (REDFISH_PAYLOAD) getPayloadByPath (RedfishService, RedPath, &(RedResponse->StatusCode));
+
+ //
+ // 1. If the returned Payload is NULL, indicates any error happen.
+ // 2. If the returned StatusCode is NULL, indicates any error happen.
+ //
+ if (RedResponse->Payload == NULL || RedResponse->StatusCode == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // 3. If the returned StatusCode is not 2XX, indicates any error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+ Get a redfish response addressed by URI, including HTTP StatusCode, Headers
+ and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the URI resources.
+ @param[in] Uri String to address a resource.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The corresponding redfish resource has
+ been returned in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER RedfishService, RedPath, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned Payload is NULL, indicates any error happen.
+ 2. If the returned StatusCode is NULL, indicates any error happen.
+ 3. If the returned StatusCode is not 2XX, indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishGetByUri (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *Uri,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ EDKII_JSON_VALUE JsonValue;
+
+ if (RedfishService == NULL || Uri == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ JsonValue = getUriFromService (RedfishService, Uri, &RedResponse->StatusCode);
+ RedResponse->Payload = createRedfishPayload(JsonValue, RedfishService);
+
+ //
+ // 1. If the returned Payload is NULL, indicates any error happen.
+ // 2. If the returned StatusCode is NULL, indicates any error happen.
+ //
+ if (RedResponse->Payload == NULL || RedResponse->StatusCode == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // 3. If the returned StatusCode is not 2XX, indicates any error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+/**
+ Get a redfish response addressed by the input Payload and relative RedPath string,
+ including HTTP StatusCode, Headers and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] Payload A existing REDFISH_PAYLOAD instance.
+ @param[in] RedPath Relative RedPath string to address a resource inside Payload.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful:
+ 1. The HTTP StatusCode is NULL and the returned Payload in
+ RedResponse is not NULL, indicates the Redfish resource has
+ been parsed from the input payload directly.
+ 2. The HTTP StatusCode is not NULL and the value is 2XX,
+ indicates the corresponding redfish resource has been returned
+ in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER Payload, RedPath, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned Payload is NULL, indicates any error happen.
+ 2. If StatusCode is not NULL and the returned value of StatusCode
+ is not 2XX, indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishGetByPayload (
+ IN REDFISH_PAYLOAD Payload,
+ IN CONST CHAR8 *RedPath,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ if (Payload == NULL || RedPath == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ RedResponse->Payload = (REDFISH_PAYLOAD) getPayloadForPathString (Payload, RedPath, &(RedResponse->StatusCode));
+
+ //
+ // 1. If the returned Payload is NULL, indicates any error happen.
+ //
+ if (RedResponse->Payload == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // 2. If StatusCode is not NULL and the returned value of StatusCode is not 2XX, indicates any
+ // error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (RedResponse->StatusCode != NULL && \
+ (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT
+ )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+ Use HTTP PATCH to perform updates on pre-existing Redfish resource.
+
+ This function uses the RedfishService to patch a Redfish resource addressed by
+ Uri (only the relative path is required). Changes to one or more properties within
+ the target resource are represented in the input Content, properties not specified
+ in Content won't be changed by this request. The corresponding redfish response will
+ returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
+ messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+ @param[in] Uri Relative path to address the resource.
+ @param[in] Content JSON represented properties to be update.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The Redfish resource will be returned
+ in Payload within RedResponse if server send it back in the HTTP
+ response message body.
+ @retval EFI_INVALID_PARAMETER RedfishService, Uri, Content, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishPatchToUri (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *Uri,
+ IN CONST CHAR8 *Content,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ EFI_STATUS Status;
+ EDKII_JSON_VALUE JsonValue;
+
+ Status = EFI_SUCCESS;
+ JsonValue = NULL;
+
+ if (RedfishService == NULL || Uri == NULL || Content == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ JsonValue = (EDKII_JSON_VALUE) patchUriFromService (
+ RedfishService,
+ Uri,
+ Content,
+ &(RedResponse->StatusCode)
+ );
+
+ //
+ // 1. If the returned StatusCode is NULL, indicates any error happen.
+ //
+ if (RedResponse->StatusCode == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ //
+ // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ON_EXIT:
+ if (JsonValue != NULL) {
+ RedResponse->Payload = createRedfishPayload (JsonValue, RedfishService);
+ if (RedResponse->Payload == NULL) {
+ //
+ // Ignore the error when create RedfishPayload, just free the JsonValue since it's not what
+ // we care about if the returned StatusCode is 2XX.
+ //
+ JsonValueFree (JsonValue);
+ }
+ }
+
+ return Status;
+}
+/**
+ Use HTTP PATCH to perform updates on target payload. Patch to odata.id in Payload directly.
+
+ This function uses the Payload to patch the Target. Changes to one or more properties
+ within the target resource are represented in the input Payload, properties not specified
+ in Payload won't be changed by this request. The corresponding redfish response will
+ returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
+ messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] Target The target payload to be updated.
+ @param[in] Payload Palyoad with properties to be changed.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The Redfish resource will be returned
+ in Payload within RedResponse if server send it back in the HTTP
+ response message body.
+ @retval EFI_INVALID_PARAMETER Target, Payload, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishPatchToPayload (
+ IN REDFISH_PAYLOAD Target,
+ IN REDFISH_PAYLOAD Payload,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ if (Target == NULL || Payload == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ RedResponse->Payload = (REDFISH_PAYLOAD) patchPayload (
+ Target,
+ Payload,
+ &(RedResponse->StatusCode)
+ );
+
+ //
+ // 1. If the returned StatusCode is NULL, indicates any error happen.
+ //
+ if (RedResponse->StatusCode == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+ Use HTTP POST to create a new resource in target payload.
+
+ The POST request should be submitted to the Resource Collection in which the new resource
+ is to belong. The Resource Collection is addressed by Target payload. The Redfish may
+ ignore any service controlled properties. The corresponding redfish response will returned,
+ including HTTP StatusCode, Headers and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] Target Target payload of the Resource Collection.
+ @param[in] Payload The new resource to be created.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The Redfish resource will be returned
+ in Payload within RedResponse if server send it back in the HTTP
+ response message body.
+ @retval EFI_INVALID_PARAMETER Target, Payload, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishPostToPayload (
+ IN REDFISH_PAYLOAD Target,
+ IN REDFISH_PAYLOAD Payload,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ if (Target == NULL || Payload == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ RedResponse->Payload = (REDFISH_PAYLOAD) postPayload (
+ Target,
+ Payload,
+ &(RedResponse->StatusCode)
+ );
+
+ //
+ // 1. If the returned StatusCode is NULL, indicates any error happen.
+ //
+ if (RedResponse->StatusCode == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+ Use HTTP DELETE to remove a resource.
+
+ This function uses the RedfishService to remove a Redfish resource which is addressed
+ by input Uri (only the relative path is required). The corresponding redfish response will
+ returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
+ messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+ @param[in] Uri Relative path to address the resource.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX, the Redfish resource has been removed.
+ If there is any message returned from server, it will be returned
+ in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER RedfishService, Uri, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishDeleteByUri (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *Uri,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ EFI_STATUS Status;
+ EDKII_JSON_VALUE JsonValue;
+
+ Status = EFI_SUCCESS;
+ JsonValue = NULL;
+
+ if (RedfishService == NULL || Uri == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ JsonValue = (EDKII_JSON_VALUE) deleteUriFromService (
+ RedfishService,
+ Uri,
+ &(RedResponse->StatusCode)
+ );
+
+ //
+ // 1. If the returned StatusCode is NULL, indicates any error happen.
+ //
+ if (RedResponse->StatusCode == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ //
+ // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ON_EXIT:
+ if (JsonValue != NULL) {
+ RedResponse->Payload = createRedfishPayload (JsonValue, RedfishService);
+ if (RedResponse->Payload == NULL) {
+ //
+ // Ignore the error when create RedfishPayload, just free the JsonValue since it's not what
+ // we care about if the returned StatusCode is 2XX.
+ //
+ JsonValueFree (JsonValue);
+ }
+ }
+
+ return Status;
+}
+/**
+ Dump text in fractions.
+
+ @param[in] String ASCII string to dump.
+
+**/
+VOID
+RedfishDumpJsonStringFractions (
+ IN CHAR8 *String
+ )
+{
+ CHAR8 *NextFraction;
+ UINTN StringFractionSize;
+ UINTN StrLen;
+ UINTN Count;
+ CHAR8 BackupChar;
+
+ StringFractionSize = 200;
+ if (String == NULL) {
+ return ;
+ }
+
+ DEBUG((DEBUG_INFO, "JSON text:\n"));
+ NextFraction = String;
+ StrLen = AsciiStrLen (String);
+ if (StrLen == 0) {
+ return;
+ }
+ for (Count = 0; Count < (StrLen / StringFractionSize); Count++) {
+ BackupChar = *(NextFraction + StringFractionSize);
+ *(NextFraction + StringFractionSize) = 0;
+ DEBUG((DEBUG_INFO, "%a", NextFraction));
+ *(NextFraction + StringFractionSize) = BackupChar;
+ NextFraction += StringFractionSize;
+ }
+ if ((StrLen % StringFractionSize) != 0) {
+ DEBUG((DEBUG_INFO, "%a\n\n", NextFraction));
+ }
+}
+/**
+ Dump text in JSON value.
+
+ @param[in] JsonValue The Redfish JSON value to dump.
+
+**/
+VOID
+RedfishDumpJson (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ CHAR8 *String;
+
+ String = JsonDumpString (JsonValue, 0);
+ if (String == NULL) {
+ return;
+ }
+ RedfishDumpJsonStringFractions (String);
+ FreePool(String);
+}
+/**
+ Extract the JSON text content from REDFISH_PAYLOAD and dump to debug console.
+
+ @param[in] Payload The Redfish payload to dump.
+
+**/
+VOID
+RedfishDumpPayload (
+ IN REDFISH_PAYLOAD Payload
+ )
+{
+ EDKII_JSON_VALUE JsonValue;
+ CHAR8 *String;
+
+ JsonValue = NULL;
+ String = NULL;
+
+ if (Payload == NULL) {
+ return;
+ }
+
+ JsonValue = RedfishJsonInPayload (Payload);
+ if (JsonValue == NULL) {
+ return;
+ }
+
+ String = JsonDumpString (JsonValue, 0);
+ if (String == NULL) {
+ return;
+ }
+
+ RedfishDumpJsonStringFractions (String);
+ FreePool(String);
+}
+/**
+ This function will cleanup the HTTP header and Redfish payload resources.
+
+ @param[in] StatusCode The status code in HTTP response message.
+ @param[in] HeaderCount Number of HTTP header structures in Headers list.
+ @param[in] Headers Array containing list of HTTP headers.
+ @param[in] Payload The Redfish payload to dump.
+
+**/
+VOID
+RedfishFreeResponse (
+ IN EFI_HTTP_STATUS_CODE *StatusCode,
+ IN UINTN HeaderCount,
+ IN EFI_HTTP_HEADER *Headers,
+ IN REDFISH_PAYLOAD Payload
+ )
+{
+ if (StatusCode != NULL) {
+ FreePool (StatusCode);
+ StatusCode = NULL;
+ }
+
+ if (HeaderCount != 0 && Headers != NULL) {
+ HttpFreeHeaderFields(Headers, HeaderCount);
+ Headers = NULL;
+ }
+
+ if (Payload != NULL) {
+ RedfishCleanupPayload (Payload);
+ Payload = NULL;
+ }
+}
+/**
+ Check if the "@odata.type" in Payload is valid or not.
+
+ @param[in] Payload The Redfish payload to be checked.
+ @param[in] OdataTypeName OdataType will be retrived from mapping list.
+ @param[in] OdataTypeMappingList The list of OdataType.
+ @param[in] OdataTypeMappingListSize The number of mapping list
+
+ @return TRUE if the "@odata.type" in Payload is valid, otherwise FALSE.
+
+**/
+BOOLEAN
+RedfishIsValidOdataType (
+ IN REDFISH_PAYLOAD Payload,
+ IN CONST CHAR8 *OdataTypeName,
+ IN REDFISH_ODATA_TYPE_MAPPING *OdataTypeMappingList,
+ IN UINTN OdataTypeMappingListSize
+ )
+{
+ UINTN Index;
+ EDKII_JSON_VALUE OdataType;
+ EDKII_JSON_VALUE JsonValue;
+
+ if (Payload == NULL || OdataTypeName == NULL) {
+ return FALSE;
+ }
+
+ JsonValue = RedfishJsonInPayload (Payload);
+ if (!JsonValueIsObject (JsonValue)) {
+ return FALSE;
+ }
+
+ OdataType = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.type");
+ if (!JsonValueIsString (OdataType) || JsonValueGetAsciiString (OdataType) == NULL) {
+ return FALSE;
+ }
+
+ for (Index = 0; Index < OdataTypeMappingListSize; Index ++) {
+ if (AsciiStrCmp (OdataTypeMappingList[Index].OdataTypeName, OdataTypeName) == 0 &&
+ AsciiStrCmp (OdataTypeMappingList[Index].OdataType, JsonValueGetAsciiString (OdataType)) == 0) {
+ return TRUE;
+ }
+ }
+ DEBUG ((DEBUG_INFO, "%a: This Odata type is not in the list.\n", __FUNCTION__));
+ return FALSE;
+}
+/**
+ Check if the payload is collection
+
+ @param[in] Payload The Redfish payload to be checked.
+
+ @return TRUE if the payload is collection.
+
+**/
+BOOLEAN
+RedfishIsPayloadCollection (
+ IN REDFISH_PAYLOAD Payload
+)
+{
+ return isPayloadCollection (Payload);
+}
+/**
+ Get collection size.
+
+ @param[in] Payload The Redfish collection payload
+ @param[in] CollectionSize Size of this collection
+
+ @return EFI_SUCCESS Coolection size is returned in CollectionSize
+ @return EFI_INVALID_PARAMETER The payload is not a collection.
+**/
+EFI_STATUS
+RedfishGetCollectionSize(
+ IN REDFISH_PAYLOAD Payload,
+ IN UINTN *CollectionSize
+ )
+{
+ if (Payload == NULL || CollectionSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (!RedfishIsPayloadCollection(Payload)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *CollectionSize = (UINTN)getCollectionSize(Payload);
+ return EFI_SUCCESS;
+}
+/**
+ Get Redfish payload of collection member
+
+ @param[in] Payload The Redfish collection payload
+ @param[in] Index Index of collection member
+
+ @return NULL Fail to get collection member.
+ @return Non NULL Payload is returned.
+**/
+REDFISH_PAYLOAD
+RedfishGetPayloadByIndex (
+ IN REDFISH_PAYLOAD Payload,
+ IN UINTN Index
+)
+{
+ REDFISH_RESPONSE RedfishResponse;
+ REDFISH_PAYLOAD PayloadReturn;
+
+ PayloadReturn = (VOID *)getPayloadByIndex (Payload, Index, &RedfishResponse.StatusCode);
+ if(PayloadReturn == NULL ||
+ (*(RedfishResponse.StatusCode) < HTTP_STATUS_200_OK && *(RedfishResponse.StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT)){
+ return NULL;
+ }
+ return PayloadReturn;
+}
+/**
+ Check and return Redfish resource of the given Redpath.
+
+ @param[in] RedfishService Pointer to REDFISH_SERVICE
+ @param[in] Redpath Redpath of the resource.
+ @param[in] Response Optional return the resource.
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+RedfishCheckIfRedpathExist (
+ IN REDFISH_SERVICE RedfishService,
+ IN CHAR8 *Redpath,
+ IN REDFISH_RESPONSE *Response OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ REDFISH_RESPONSE TempResponse;
+
+ if (Redpath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Status = RedfishGetByService (RedfishService, Redpath, &TempResponse);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Response == NULL) {
+ RedfishFreeResponse(
+ TempResponse.StatusCode,
+ TempResponse.HeaderCount,
+ TempResponse.Headers,
+ TempResponse.Payload
+ );
+ } else {
+ CopyMem ((VOID *)Response, (VOID *)&TempResponse, sizeof (REDFISH_RESPONSE));
+ }
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
new file mode 100644
index 00000000..6afabd6d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
@@ -0,0 +1,60 @@
+## @file
+# RedfishLib Library implementation.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = DxeRedfishLib
+ FILE_GUID = 9C2CA9CF-4F79-11E8-A7D1-8CDCD426C973
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RedfishLib| DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ edk2libredfish/src/redpath.c
+ edk2libredfish/src/service.c
+ edk2libredfish/src/payload.c
+ edk2libredfish/include/redfish.h
+ edk2libredfish/include/redfishPayload.h
+ edk2libredfish/include/redfishService.h
+ edk2libredfish/include/redpath.h
+ RedfishLib.c
+ RedfishMisc.h
+ RedfishMisc.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ HttpLib
+ MemoryAllocationLib
+ NetLib
+ RedfishContentCodingLib
+ RedfishCrtLib
+ UefiBootServicesTableLib
+ UefiLib
+
+[Protocols]
+ gEfiRestExServiceBindingProtocolGuid ## Consumed
+ gEfiRestExProtocolGuid ## Consumed
+ gEdkIIRedfishCredentialProtocolGuid ## Consumed
+
+[BuildOptions]
+ MSFT:*_*_*_CC_FLAGS = /U_WIN32 /UWIN64 /U_MSC_VER
+ GCC:*_*_*_CC_FLAGS = -Wno-unused-function -Wno-unused-but-set-variable
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.c
new file mode 100644
index 00000000..32481153
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.c
@@ -0,0 +1,201 @@
+/** @file
+ Internal Functions for RedfishLib.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishMisc.h"
+
+EDKII_REDFISH_CREDENTIAL_PROTOCOL *mCredentialProtocol = NULL;
+
+/**
+ This function returns the string of Redfish service version.
+
+ @param[in] RedfishService Redfish service instance.
+ @param[out] ServiceVersionStr Redfish service string.
+
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+RedfishGetServiceVersion (
+ IN REDFISH_SERVICE RedfishService,
+ OUT CHAR8 **ServiceVersionStr
+ )
+{
+ redfishService *Redfish;
+ CHAR8 **KeysArray;
+ UINTN KeysNum;
+
+ if (RedfishService == NULL || ServiceVersionStr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Redfish = (redfishService *)RedfishService;
+ if (Redfish->versions == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ KeysArray = JsonObjectGetKeys (Redfish->versions, &KeysNum);
+ if (KeysNum == 0 || KeysArray == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ *ServiceVersionStr = *KeysArray;
+ return EFI_SUCCESS;
+}
+
+/**
+ Creates a REDFISH_SERVICE which can be later used to access the Redfish resources.
+
+ This function will configure REST EX child according to parameters described in
+ Redfish network host interface in SMBIOS type 42 record. The service enumerator will also
+ handle the authentication flow automatically if HTTP basic auth or Redfish session
+ login is configured to use.
+
+ @param[in] RedfishConfigServiceInfo Redfish service information the EFI Redfish
+ feature driver communicates with.
+ @param[in] AuthMethod None, HTTP basic auth, or Redfish session login.
+ @param[in] UserId User Name used for authentication.
+ @param[in] Password Password used for authentication.
+
+ @return New created Redfish service, or NULL if error happens.
+
+**/
+REDFISH_SERVICE
+RedfishCreateLibredfishService (
+ IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo,
+ IN EDKII_REDFISH_AUTH_METHOD AuthMethod,
+ IN CHAR8 *UserId,
+ IN CHAR8 *Password
+ )
+{
+
+ UINTN Flags;
+ enumeratorAuthentication Auth;
+ redfishService* Redfish;
+
+ Redfish = NULL;
+
+ ZeroMem (&Auth, sizeof (Auth));
+ if (AuthMethod == AuthMethodHttpBasic) {
+ Auth.authType = REDFISH_AUTH_BASIC;
+ } else if (AuthMethod == AuthMethodRedfishSession) {
+ Auth.authType = REDFISH_AUTH_SESSION;
+ }
+ Auth.authCodes.userPass.username = UserId;
+ Auth.authCodes.userPass.password = Password;
+
+ Flags = REDFISH_FLAG_SERVICE_NO_VERSION_DOC;
+
+ if (AuthMethod != AuthMethodNone) {
+ Redfish = createServiceEnumerator(RedfishConfigServiceInfo, NULL, &Auth, (unsigned int ) Flags);
+ } else {
+ Redfish = createServiceEnumerator(RedfishConfigServiceInfo, NULL, NULL, (unsigned int) Flags);
+ }
+
+ //
+ // Zero the Password after use.
+ //
+ if (Password != NULL) {
+ ZeroMem (Password, AsciiStrLen(Password));
+ }
+
+ return (REDFISH_SERVICE) Redfish;
+}
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user
+ Id and password.
+ For AuthMethodNone, UserId and Password will point to NULL which means authentication
+ is not required to access the Redfish service.
+ For AuthMethodHttpBasic, the UserId and Password could be used for
+ HTTP header authentication as defined by RFC7235. For AuthMethodRedfishSession,
+ the UserId and Password could be used for Redfish session login as defined by
+ Redfish API specification (DSP0266).
+
+ Callers are responsible for freeing the returned string storage pointed by UserId
+ and Password.
+
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_INVALID_PARAMETER AuthMethod or UserId or Password is NULL.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+**/
+EFI_STATUS
+RedfishGetAuthInfo (
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+ )
+{
+ EFI_STATUS Status;
+
+ if (AuthMethod == NULL || UserId == NULL || Password == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Locate Redfish Credential Protocol.
+ //
+ if (mCredentialProtocol == NULL) {
+ Status = gBS->LocateProtocol (&gEdkIIRedfishCredentialProtocolGuid, NULL, (VOID **)&mCredentialProtocol);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ ASSERT (mCredentialProtocol != NULL);
+
+ Status = mCredentialProtocol->GetAuthInfo (mCredentialProtocol, AuthMethod, UserId, Password);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "RedfishGetAuthInfo: failed to retrieve Redfish credential - %r\n", Status));
+ return Status;
+ }
+
+ return Status;
+}
+/**
+ This function returns the string of Redfish service version.
+
+ @param[in] ServiceVerisonStr The string of Redfish service version.
+ @param[in] Url The URL to build Redpath with ID.
+ Start with "/", for example "/Registries"
+ @param[in] Id ID string
+ @param[out] Redpath Pointer to retrive Redpath, caller has to free
+ the memory allocated for this string.
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+RedfishBuildRedpathUseId (
+ IN CHAR8 *ServiceVerisonStr,
+ IN CHAR8 *Url,
+ IN CHAR8 *Id,
+ OUT CHAR8 **Redpath
+ )
+{
+ UINTN RedpathSize;
+
+ if (Redpath == NULL || ServiceVerisonStr == NULL || Url == NULL || Id == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RedpathSize = AsciiStrLen ("/") +
+ AsciiStrLen (ServiceVerisonStr) +
+ AsciiStrLen (Url) +
+ AsciiStrLen ("[Id=]") +
+ AsciiStrLen (Id) + 1;
+ *Redpath = AllocatePool(RedpathSize);
+ if (*Redpath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ AsciiSPrint (*Redpath, RedpathSize, "/%a%a[Id=%a]", ServiceVerisonStr, Url, Id);
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.h
new file mode 100644
index 00000000..19710398
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.h
@@ -0,0 +1,82 @@
+/** @file
+ Internal Functions for RedfishLib.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef DXE_REDFISH_MISC_LIB_H_
+#define DXE_REDFISH_MISC_LIB_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/RedfishLib.h>
+#include <Library/UefiLib.h>
+#include <Protocol/EdkIIRedfishCredential.h>
+#include <redfish.h>
+
+#define ARRAY_SIZE(Array) (sizeof (Array) / sizeof ((Array)[0]))
+
+/**
+ Creates a REDFISH_SERVICE which can be later used to access the Redfish resources.
+
+ This function will configure REST EX child according to parameters described in
+ Redfish network host interface in SMBIOS type 42 record. The service enumerator will also
+ handle the authentication flow automatically if HTTP basic auth or Redfish session
+ login is configured to use.
+
+ @param[in] RedfishConfigServiceInfo Redfish service information the EFI Redfish
+ feature driver communicates with.
+ @param[in] AuthMethod None, HTTP basic auth, or Redfish session login.
+ @param[in] UserId User Name used for authentication.
+ @param[in] Password Password used for authentication.
+
+ @return New created Redfish service, or NULL if error happens.
+
+**/
+REDFISH_SERVICE
+RedfishCreateLibredfishService (
+ IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo,
+ IN EDKII_REDFISH_AUTH_METHOD AuthMethod,
+ IN CHAR8 *UserId,
+ IN CHAR8 *Password
+ );
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user
+ Id and password.
+ For AuthMethodNone, UserId and Password will point to NULL which means authentication
+ is not required to access the Redfish service.
+ For AuthMethodHttpBasic, the UserId and Password could be used for
+ HTTP header authentication as defined by RFC7235. For AuthMethodRedfishSession,
+ the UserId and Password could be used for Redfish session login as defined by
+ Redfish API specification (DSP0266).
+
+ Callers are responsible for freeing the returned string storage pointed by UserId
+ and Password.
+
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_INVALID_PARAMETER AuthMethod or UserId or Password is NULL.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+**/
+EFI_STATUS
+RedfishGetAuthInfo (
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish.h
new file mode 100644
index 00000000..5804379b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish.h
@@ -0,0 +1,24 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef LIBREDFISH_REDFISH_H_
+#define LIBREDFISH_REDFISH_H_
+
+#include <redfishService.h>
+#include <redfishPayload.h>
+#include <redpath.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishPayload.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishPayload.h
new file mode 100644
index 00000000..778aff55
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishPayload.h
@@ -0,0 +1,39 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef LIBREDFISH_REDFISH_PAYLOAD_H_
+#define LIBREDFISH_REDFISH_PAYLOAD_H_
+
+#include <PrivateInclude/Library/RedfishCrtLib.h>
+
+#include <jansson.h>
+#include <redfishService.h>
+#include <redpath.h>
+
+redfishPayload* createRedfishPayload(json_t* value, redfishService* service);
+redfishPayload* getPayloadByNodeName(redfishPayload* payload, const char* nodeName, EFI_HTTP_STATUS_CODE** StatusCode);
+redfishPayload* getPayloadByIndex(redfishPayload* payload, size_t index, EFI_HTTP_STATUS_CODE** StatusCode);
+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* postContentToPayload(redfishPayload* target, const char* data, size_t dataSize, const char* contentType, EFI_HTTP_STATUS_CODE** StatusCode);
+redfishPayload* postPayload(redfishPayload* target, redfishPayload* payload, EFI_HTTP_STATUS_CODE** StatusCode);
+void cleanupPayload(redfishPayload* payload);
+bool isPayloadCollection (redfishPayload *Payload);
+size_t getCollectionSize(redfishPayload* payload);
+redfishPayload* getPayloadByIndex (redfishPayload* payload, size_t index, EFI_HTTP_STATUS_CODE** StatusCode);
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h
new file mode 100644
index 00000000..13a6db5b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h
@@ -0,0 +1,101 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef LIBREDFISH_REDFISH_SERVICE_H_
+#define LIBREDFISH_REDFISH_SERVICE_H_
+
+#include <IndustryStandard/Http11.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HttpLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/RedfishContentCodingLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <PrivateInclude/Library/RedfishCrtLib.h>
+
+#include <Protocol/EdkIIRedfishConfigHandler.h>
+#include <Protocol/RestEx.h>
+
+#include <jansson.h>
+
+typedef struct {
+ char* host;
+ json_t* versions;
+ unsigned int flags;
+ char* sessionToken;
+ char* basicAuthStr;
+ //
+ // point to the <HOST> part in above "host" field, which will be put into
+ // the "Host" header of HTTP request message.
+ //
+ char* HostHeaderValue;
+ EFI_REST_EX_PROTOCOL *RestEx;
+} redfishService;
+
+typedef struct {
+ json_t* json;
+ redfishService* service;
+} redfishPayload;
+
+#define REDFISH_AUTH_BASIC 0
+#define REDFISH_AUTH_BEARER_TOKEN 1
+#define REDFISH_AUTH_SESSION 2
+
+#define REDFISH_HTTP_RESPONSE_TIMEOUT 5000 /// 5 seconds in uints of millisecond.
+
+///
+/// Library class public defines
+///
+#define HTTP_FLAG L"http://"
+#define HTTPS_FLAG L"https://"
+
+///
+/// The redfish first URL should be "/redfish/v1/", while we use "/redfish/v1" here without "/"
+/// in the end is to avoid the 301 Perment redirect response from Redfish profile simulator.
+///
+#define REDFISH_FIRST_URL L"/redfish/v1"
+
+typedef struct {
+ unsigned int authType;
+ union {
+ struct {
+ char* username;
+ char* password;
+ } userPass;
+ struct {
+ char* token;
+ } authToken;
+ } authCodes;
+} enumeratorAuthentication;
+
+//Values for flags
+#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* patchUriFromService(redfishService* service, const char* uri, const char* content, 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* 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);
+void cleanupServiceEnumerator(redfishService* service);
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redpath.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redpath.h
new file mode 100644
index 00000000..f9e9c182
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redpath.h
@@ -0,0 +1,42 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef LIBREDFISH_REDPATH_H_
+#define LIBREDFISH_REDPATH_H_
+
+#include <PrivateInclude/Library/RedfishCrtLib.h>
+
+#include <jansson.h>
+
+typedef struct _redPathNode
+{
+ bool isRoot;
+ bool isIndex;
+
+ char* version;
+ char* nodeName;
+ size_t index;
+ char* op;
+ char* propName;
+ char* value;
+
+ struct _redPathNode* next;
+} redPathNode;
+
+redPathNode* parseRedPath(const char* path);
+void cleanupRedPath(redPathNode* node);
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c
new file mode 100644
index 00000000..f9f2294e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c
@@ -0,0 +1,732 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <redfishPayload.h>
+
+static redfishPayload* getOpResult(redfishPayload* payload, const char* propName, const char* op, const char* value, EFI_HTTP_STATUS_CODE** StatusCode);
+static redfishPayload* collectionEvalOp(redfishPayload* payload, const char* propName, const char* op, const char* value, EFI_HTTP_STATUS_CODE** StatusCode);
+static redfishPayload* arrayEvalOp(redfishPayload* payload, const char* propName, const char* op, const char* value, EFI_HTTP_STATUS_CODE** StatusCode);
+static redfishPayload* createCollection(redfishService* service, size_t count, redfishPayload** payloads);
+static json_t* json_object_get_by_index(json_t* json, size_t index);
+
+bool isPayloadCollection(redfishPayload* payload)
+{
+ json_t* members;
+ json_t* count;
+
+ if(!payload || !json_is_object(payload->json))
+ {
+ return false;
+ }
+ members = json_object_get(payload->json, "Members");
+ count = json_object_get(payload->json, "Members@odata.count");
+ return ((members != NULL) && (count != NULL));
+}
+
+size_t getCollectionSize(redfishPayload* payload)
+{
+ json_t* members;
+ json_t* count;
+
+ if(!payload || !json_is_object(payload->json))
+ {
+ return 0;
+ }
+ members = json_object_get(payload->json, "Members");
+ count = json_object_get(payload->json, "Members@odata.count");
+ if(!members || !count)
+ {
+ return 0;
+ }
+ return (size_t)json_integer_value(count);
+}
+
+bool isPayloadArray(redfishPayload* payload)
+{
+ if(!payload || !json_is_array(payload->json))
+ {
+ return false;
+ }
+ return true;
+}
+
+char* payloadToString(redfishPayload* payload, bool prettyPrint)
+{
+ size_t flags = 0;
+ if(!payload)
+ {
+ return NULL;
+ }
+ if(prettyPrint)
+ {
+ flags = JSON_INDENT(2);
+ }
+ return json_dumps(payload->json, flags);
+}
+
+redfishPayload* createRedfishPayload(json_t* value, redfishService* service)
+{
+ redfishPayload* payload;
+ payload = (redfishPayload*)malloc(sizeof(redfishPayload));
+ if(payload != NULL)
+ {
+ payload->json = value;
+ payload->service = service;
+ }
+ return payload;
+}
+
+redfishPayload* getPayloadByNodeName(redfishPayload* payload, const char* nodeName, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ json_t* value;
+ json_t* odataId;
+ const char* uri;
+
+ if(!payload || !nodeName || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ value = json_object_get(payload->json, nodeName);
+ if(value == NULL)
+ {
+ return NULL;
+ }
+ json_incref(value);
+ if(json_object_size(value) == 1)
+ {
+ odataId = json_object_get(value, "@odata.id");
+ if(odataId != NULL)
+ {
+ json_incref(odataId);
+ uri = json_string_value(odataId);
+ json_decref(value);
+ value = getUriFromService(payload->service, uri, StatusCode);
+ json_decref(odataId);
+ if(value == NULL || *StatusCode == NULL)
+ {
+ return NULL;
+ }
+ }
+ }
+ if (*StatusCode == NULL || (**StatusCode >= HTTP_STATUS_200_OK && **StatusCode <= HTTP_STATUS_206_PARTIAL_CONTENT)) {
+ if(json_is_string(value))
+ {
+ odataId = json_object();
+ json_object_set(odataId, nodeName, value);
+ json_decref(value);
+ value = odataId;
+ }
+ }
+
+ return createRedfishPayload(value, payload->service);
+}
+
+redfishPayload* getPayloadByIndex(redfishPayload* payload, size_t index, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ json_t* value = NULL;
+ json_t* odataId;
+ const char* uri;
+ BOOLEAN FromServerFlag = FALSE;
+
+ if(!payload || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ if(isPayloadCollection(payload))
+ {
+ redfishPayload* members = getPayloadByNodeName(payload, "Members", StatusCode);
+ if ((*StatusCode == NULL && members == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return members;
+ }
+
+ if (*StatusCode != NULL) {
+ //
+ // The Payload (members) are retrived from server.
+ //
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+ FromServerFlag = TRUE;
+ }
+
+ redfishPayload* ret = getPayloadByIndex(members, index, StatusCode);
+ if (*StatusCode == NULL && ret != NULL && FromServerFlag) {
+ //
+ // In such a case, the Redfish resource is parsed from the input payload (members) directly.
+ // Since the members are retrived from server, we still return HTTP_STATUS_200_OK.
+ //
+ *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
+ if (*StatusCode == NULL) {
+ ret = NULL;
+ } else {
+ **StatusCode = HTTP_STATUS_200_OK;
+ }
+ }
+
+ cleanupPayload(members);
+ return ret;
+ }
+
+ if(json_is_array(payload->json))
+ {
+ //
+ // The valid range for index is from 0 to the return value of json_array_size() minus 1
+ //
+ value = json_array_get(payload->json, index);
+ }
+ else if(json_is_object(payload->json))
+ {
+ value = json_object_get_by_index(payload->json, index);
+ }
+
+ if(value == NULL)
+ {
+ return NULL;
+ }
+
+ json_incref(value);
+ if(json_object_size(value) == 1)
+ {
+ odataId = json_object_get(value, "@odata.id");
+ if(odataId != NULL)
+ {
+ uri = json_string_value(odataId);
+ json_decref(value);
+ value = getUriFromService(payload->service, uri, StatusCode);
+ if(value == NULL)
+ {
+ return NULL;
+ }
+ }
+ }
+ return createRedfishPayload(value, payload->service);
+}
+
+redfishPayload* getPayloadForPath(redfishPayload* payload, redPathNode* redpath, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ redfishPayload* ret = NULL;
+ redfishPayload* tmp;
+
+ if(!payload || !redpath || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+ BOOLEAN FromServerFlag = FALSE;
+
+ if(redpath->nodeName)
+ {
+ ret = getPayloadByNodeName(payload, redpath->nodeName, StatusCode);
+ if ((*StatusCode == NULL && ret == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ //
+ // Any error happen, return directly.
+ //
+ return ret;
+ }
+ }
+ else if(redpath->isIndex)
+ {
+ ASSERT (redpath->index >= 1);
+ ret = getPayloadByIndex(payload, redpath->index - 1, StatusCode);
+ if ((*StatusCode == NULL && ret == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ //
+ // Any error happen, return directly.
+ //
+ return ret;
+ }
+ }
+ else if(redpath->op)
+ {
+ ret = getOpResult(payload, redpath->propName, redpath->op, redpath->value, StatusCode);
+ if ((*StatusCode == NULL && ret == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ //
+ // Any error happen, return directly.
+ //
+ return ret;
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+
+ if(redpath->next == NULL || ret == NULL)
+ {
+ return ret;
+ }
+ else
+ {
+ if (*StatusCode != NULL) {
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+ FromServerFlag = TRUE;
+ }
+
+ tmp = getPayloadForPath(ret, redpath->next, StatusCode);
+ if (*StatusCode == NULL && tmp != NULL && FromServerFlag) {
+ //
+ // In such a case, the Redfish resource is parsed from the input payload (ret) directly.
+ // Since the ret are retrived from server, we still return HTTP_STATUS_200_OK.
+ //
+ *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
+ if (*StatusCode == NULL) {
+ tmp = NULL;
+ } else {
+ **StatusCode = HTTP_STATUS_200_OK;
+ }
+ }
+
+ cleanupPayload(ret);
+ return tmp;
+ }
+}
+
+redfishPayload* getPayloadForPathString(redfishPayload* payload, const char* string, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ redPathNode* redpath;
+ redfishPayload* ret;
+
+ if(!string || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ redpath = parseRedPath(string);
+ if(redpath == NULL)
+ {
+ return NULL;
+ }
+ ret = getPayloadForPath(payload, redpath, StatusCode);
+ cleanupRedPath(redpath);
+ return ret;
+}
+
+redfishPayload* patchPayload(redfishPayload* target, redfishPayload* payload, 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 = patchUriFromService(target->service, uri, content, StatusCode);
+ free(uri);
+ free(content);
+ 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;
+ 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 = postUriFromService(target->service, uri, data, dataSize, contentType, StatusCode);
+ free(uri);
+ if(json == NULL)
+ {
+ return NULL;
+ }
+
+ return createRedfishPayload(json, target->service);
+}
+
+redfishPayload* postPayload(redfishPayload* target, redfishPayload* payload, 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 = postContentToPayload(target, content, strlen(content), NULL, StatusCode);
+ free(content);
+ return ret;
+}
+
+void cleanupPayload(redfishPayload* payload)
+{
+ if(!payload)
+ {
+ return;
+ }
+ json_decref(payload->json);
+ //Don't free payload->service, let the caller handle cleaning up the service
+ free(payload);
+}
+
+static redfishPayload* getOpResult(redfishPayload* payload, const char* propName, const char* op, const char* value, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ const char* propStr;
+ json_t* stringProp;
+ bool ret = false;
+ redfishPayload* prop;
+ long long intVal, intPropVal;
+ json_type jsonType;
+
+ if(isPayloadCollection(payload))
+ {
+ return collectionEvalOp(payload, propName, op, value, StatusCode);
+ }
+ if(isPayloadArray(payload))
+ {
+ return arrayEvalOp(payload, propName, op, value, StatusCode);
+ }
+
+ prop = getPayloadByNodeName(payload, propName, StatusCode);
+ if ((*StatusCode == NULL && prop == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return prop;
+ }
+ stringProp = prop->json;
+ jsonType = prop->json->type;
+ switch(jsonType)
+ {
+ case JSON_OBJECT:
+ stringProp = json_object_get(prop->json, propName);
+ case JSON_STRING:
+ if(strcmp(op, "=") == 0)
+ {
+ propStr = json_string_value(stringProp);
+ if(propStr == NULL)
+ {
+ cleanupPayload(prop);
+ return NULL;
+ }
+ ret = (strcmp(propStr, value) == 0);
+ } else if(strcmp(op, "~") == 0)
+ {
+ propStr = json_string_value(stringProp);
+ if(propStr == NULL)
+ {
+ cleanupPayload(prop);
+ return NULL;
+ }
+ ret = (strcasecmp(propStr, value) == 0);
+ }
+ break;
+ case JSON_TRUE:
+ if(strcmp(op, "=") == 0)
+ {
+ ret = (strcmp(value, "true") == 0);
+ }
+ break;
+ case JSON_FALSE:
+ if(strcmp(op, "=") == 0)
+ {
+ ret = (strcmp(value, "false") == 0);
+ }
+ break;
+ case JSON_INTEGER:
+ intPropVal = json_integer_value(prop->json);
+ intVal = strtoll(value, NULL, 0);
+ if(strcmp(op, "=") == 0)
+ {
+ ret = (intPropVal == intVal);
+ }
+ else if(strcmp(op, "<") == 0)
+ {
+ ret = (intPropVal < intVal);
+ }
+ else if(strcmp(op, ">") == 0)
+ {
+ ret = (intPropVal > intVal);
+ }
+ else if(strcmp(op, "<=") == 0)
+ {
+ ret = (intPropVal <= intVal);
+ }
+ else if(strcmp(op, ">=") == 0)
+ {
+ ret = (intPropVal >= intVal);
+ }
+ break;
+ default:
+ break;
+ }
+ cleanupPayload(prop);
+ if(ret)
+ {
+ return payload;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+static redfishPayload* collectionEvalOp(redfishPayload* payload, const char* propName, const char* op, const char* value, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ redfishPayload* ret;
+ redfishPayload* tmp;
+ redfishPayload* members;
+ redfishPayload** valid;
+ size_t validMax;
+ size_t validCount = 0;
+ size_t i;
+
+ validMax = getCollectionSize(payload);
+ if(validMax == 0)
+ {
+ return NULL;
+ }
+
+ valid = (redfishPayload**)calloc(validMax, sizeof(redfishPayload*));
+ if(valid == NULL)
+ {
+ return NULL;
+ }
+ /*Technically getPayloadByIndex would do this, but this optimizes things*/
+ members = getPayloadByNodeName(payload, "Members", StatusCode);
+ if ((*StatusCode == NULL && members == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return members;
+ }
+
+ for(i = 0; i < validMax; i++)
+ {
+ if (*StatusCode != NULL) {
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+ }
+
+ tmp = getPayloadByIndex(members, i, StatusCode);
+ if ((*StatusCode == NULL && tmp == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return tmp;
+ }
+
+ if (*StatusCode != NULL) {
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+ }
+
+ valid[validCount] = getOpResult(tmp, propName, op, value, StatusCode);
+ /*
+ if ((*StatusCode == NULL && valid[validCount] == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return valid[validCount];
+ }
+ */
+ if(valid[validCount] != NULL)
+ {
+ validCount++;
+ }
+ else
+ {
+ cleanupPayload(tmp);
+ }
+ }
+ cleanupPayload(members);
+ if(validCount == 0)
+ {
+ free(valid);
+ return NULL;
+ }
+ if(validCount == 1)
+ {
+ ret = valid[0];
+ free(valid);
+ return ret;
+ }
+ else
+ {
+ ret = createCollection(payload->service, validCount, valid);
+ free(valid);
+ return ret;
+ }
+}
+
+static redfishPayload* arrayEvalOp(redfishPayload* payload, const char* propName, const char* op, const char* value, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ redfishPayload* ret;
+ redfishPayload* tmp;
+ redfishPayload** valid;
+ size_t validMax;
+ size_t validCount = 0;
+ size_t i;
+
+ validMax = json_array_size(payload->json);
+ if(validMax == 0)
+ {
+ return NULL;
+ }
+
+ valid = (redfishPayload**)calloc(validMax, sizeof(redfishPayload*));
+ if(valid == NULL)
+ {
+ return NULL;
+ }
+ for(i = 0; i < validMax; i++)
+ {
+ if (*StatusCode != NULL) {
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+ }
+
+ tmp = getPayloadByIndex(payload, i, StatusCode);
+ if ((*StatusCode == NULL && tmp == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return tmp;
+ }
+
+ if (*StatusCode != NULL) {
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+ }
+
+ valid[validCount] = getOpResult(tmp, propName, op, value, StatusCode);
+ /*
+ if ((*StatusCode == NULL && valid[validCount] == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return valid[validCount];
+ }
+ */
+
+ if(valid[validCount] != NULL)
+ {
+ validCount++;
+ }
+ else
+ {
+ cleanupPayload(tmp);
+ }
+ }
+ if(validCount == 0)
+ {
+ free(valid);
+ return NULL;
+ }
+ if(validCount == 1)
+ {
+ ret = valid[0];
+ free(valid);
+ return ret;
+ }
+ else
+ {
+ ret = createCollection(payload->service, validCount, valid);
+ free(valid);
+ return ret;
+ }
+}
+
+static redfishPayload* createCollection(redfishService* service, size_t count, redfishPayload** payloads)
+{
+ redfishPayload* ret;
+ json_t* collectionJson = json_object();
+ json_t* jcount = json_integer((json_int_t)count);
+ json_t* members = json_array();
+ size_t i;
+
+ if(!collectionJson)
+ {
+ return NULL;
+ }
+ if(!members)
+ {
+ json_decref(collectionJson);
+ return NULL;
+ }
+ json_object_set(collectionJson, "Members@odata.count", jcount);
+ json_decref(jcount);
+ for(i = 0; i < count; i++)
+ {
+ json_array_append(members, payloads[i]->json);
+ cleanupPayload(payloads[i]);
+ }
+ json_object_set(collectionJson, "Members", members);
+ json_decref(members);
+
+ ret = createRedfishPayload(collectionJson, service);
+ return ret;
+}
+
+static json_t* json_object_get_by_index(json_t* json, size_t index)
+{
+ void* iter;
+ size_t i;
+
+ iter = json_object_iter(json);
+ for(i = 0; i < index; i++)
+ {
+ iter = json_object_iter_next(json, iter);
+ if(iter == NULL) break;
+ }
+ if(iter == NULL)
+ {
+ return NULL;
+ }
+ return json_object_iter_value(iter);
+}
+/* vim: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/redpath.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/redpath.c
new file mode 100644
index 00000000..28291426
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/redpath.c
@@ -0,0 +1,192 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <redpath.h>
+
+static char* getVersion(const char* path, char** end);
+static void parseNode(const char* path, redPathNode* node, redPathNode** end);
+
+static char* getStringTill(const char* string, const char* terminator, char** retEnd);
+
+redPathNode* parseRedPath(const char* path)
+{
+ redPathNode* node;
+ redPathNode* endNode;
+ char* curPath;
+ char* end;
+
+ if(!path || strlen(path) == 0)
+ {
+ return NULL;
+ }
+
+ node = (redPathNode*)calloc(1, sizeof(redPathNode));
+ if(!node)
+ {
+ return NULL;
+ }
+ if(path[0] == '/')
+ {
+ node->isRoot = true;
+ if(path[1] == 'v')
+ {
+ node->version = getVersion(path+1, &curPath);
+ if(curPath == NULL)
+ {
+ return node;
+ }
+ if(curPath[0] == '/')
+ {
+ curPath++;
+ }
+ node->next = parseRedPath(curPath);
+ }
+ else
+ {
+ node->next = parseRedPath(path+1);
+ }
+ return node;
+ }
+ node->isRoot = false;
+ curPath = getStringTill(path, "/", &end);
+ endNode = node;
+ parseNode(curPath, node, &endNode);
+ free(curPath);
+ if(end != NULL)
+ {
+ endNode->next = parseRedPath(end+1);
+ }
+ return node;
+}
+
+void cleanupRedPath(redPathNode* node)
+{
+ if(!node)
+ {
+ return;
+ }
+ cleanupRedPath(node->next);
+ node->next = NULL;
+ if(node->version)
+ {
+ free(node->version);
+ }
+ if(node->nodeName)
+ {
+ free(node->nodeName);
+ }
+ if(node->op)
+ {
+ free(node->op);
+ }
+ if(node->propName)
+ {
+ free(node->propName);
+ }
+ if(node->value)
+ {
+ free(node->value);
+ }
+ free(node);
+}
+
+static char* getVersion(const char* path, char** end)
+{
+ return getStringTill(path, "/", end);
+}
+
+static void parseNode(const char* path, redPathNode* node, redPathNode** end)
+{
+ char* indexStart;
+ char* index;
+ char* indexEnd;
+ char* nodeName = getStringTill(path, "[", &indexStart);
+ size_t tmpIndex;
+ char* opChars;
+
+ node->nodeName = nodeName;
+ if(indexStart == NULL)
+ {
+ *end = node;
+ return;
+ }
+ node->next = (redPathNode*)calloc(1, sizeof(redPathNode));
+ if(!node->next)
+ {
+ return;
+ }
+ //Skip past [
+ indexStart++;
+ *end = node->next;
+ index = getStringTill(indexStart, "]", NULL);
+ tmpIndex = (size_t)strtoull(index, &indexEnd, 0);
+ if(indexEnd != index)
+ {
+ free(index);
+ node->next->index = tmpIndex;
+ node->next->isIndex = true;
+ return;
+ }
+ opChars = strpbrk(index, "<>=~");
+ if(opChars == NULL)
+ {
+ //TODO handle last() and position()
+ node->next->op = strdup("exists");
+ node->next->propName = index;
+ return;
+ }
+ node->next->propName = (char*)malloc((opChars - index)+1);
+ memcpy(node->next->propName, index, (opChars - index));
+ node->next->propName[(opChars - index)] = 0;
+
+ tmpIndex = 1;
+ while(1)
+ {
+ if(opChars[tmpIndex] == '=' || opChars[tmpIndex] == '<' || opChars[tmpIndex] == '>' || opChars[tmpIndex] == '~')
+ {
+ tmpIndex++;
+ continue;
+ }
+ break;
+ }
+
+ node->next->op = (char*)malloc(tmpIndex+1);
+ memcpy(node->next->op, opChars, tmpIndex);
+ node->next->op[tmpIndex] = 0;
+
+ node->next->value = strdup(opChars+tmpIndex);
+ free(index);
+}
+
+static char* getStringTill(const char* string, const char* terminator, char** retEnd)
+{
+ char* ret;
+ char* end;
+ end = strstr((char*)string, terminator);
+ if(retEnd)
+ {
+ *retEnd = end;
+ }
+ if(end == NULL)
+ {
+ //No terminator
+ return strdup(string);
+ }
+ ret = (char*)malloc((end-string)+1);
+ memcpy(ret, string, (end-string));
+ ret[(end-string)] = 0;
+ return ret;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c
new file mode 100644
index 00000000..7139a2e2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c
@@ -0,0 +1,1396 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <redfishService.h>
+#include <redfishPayload.h>
+#include <redpath.h>
+
+static int initRest(redfishService* service, void * restProtocol);
+static redfishService* createServiceEnumeratorNoAuth(const char* host, const char* rootUri, bool enumerate, unsigned int flags, void * restProtocol);
+static redfishService* createServiceEnumeratorBasicAuth(const char* host, const char* rootUri, const char* username, const char* password, unsigned int flags, void * restProtocol);
+static redfishService* createServiceEnumeratorSessionAuth(const char* host, const char* rootUri, const char* username, const char* password, unsigned int flags, void * restProtocol);
+static char* makeUrlForService(redfishService* service, const char* uri);
+static json_t* getVersions(redfishService* service, const char* rootUri);
+static void addStringToJsonObject(json_t* object, const char* key, const char* value);
+
+CHAR16*
+C8ToC16 (CHAR8 *AsciiStr)
+{
+ CHAR16 *Str;
+ UINTN BufLen;
+
+ BufLen = (AsciiStrLen (AsciiStr) + 1) * 2;
+ Str = AllocatePool (BufLen);
+ ASSERT (Str != NULL);
+
+ AsciiStrToUnicodeStrS (AsciiStr, Str, AsciiStrLen (AsciiStr) + 1);
+
+ return Str;
+}
+
+VOID
+RestConfigFreeHttpRequestData (
+ IN EFI_HTTP_REQUEST_DATA *RequestData
+ )
+{
+ if (RequestData == NULL) {
+ return ;
+ }
+
+ if (RequestData->Url != NULL) {
+ FreePool (RequestData->Url);
+ }
+
+ FreePool (RequestData);
+}
+
+VOID
+RestConfigFreeHttpMessage (
+ IN EFI_HTTP_MESSAGE *Message,
+ IN BOOLEAN IsRequest
+ )
+{
+ if (Message == NULL) {
+ return ;
+ }
+
+ if (IsRequest) {
+ RestConfigFreeHttpRequestData (Message->Data.Request);
+ Message->Data.Request = NULL;
+ } else {
+ if (Message->Data.Response != NULL) {
+ FreePool (Message->Data.Response);
+ Message->Data.Response = NULL;
+ }
+ }
+
+ if (Message->Headers != NULL) {
+ FreePool (Message->Headers);
+ Message->Headers = NULL;
+ }
+ if (Message->Body != NULL) {
+ FreePool (Message->Body);
+ Message->Body = NULL;
+ }
+}
+
+/**
+ Converts the Unicode string to ASCII string to a new allocated buffer.
+
+ @param[in] String Unicode string to be converted.
+
+ @return Buffer points to ASCII string, or NULL if error happens.
+
+**/
+
+CHAR8 *
+UnicodeStrDupToAsciiStr (
+ CONST CHAR16 *String
+ )
+{
+ CHAR8 *AsciiStr;
+ UINTN BufLen;
+ EFI_STATUS Status;
+
+ BufLen = StrLen (String) + 1;
+ AsciiStr = AllocatePool (BufLen);
+ if (AsciiStr == NULL) {
+ return NULL;
+ }
+
+ Status = UnicodeStrToAsciiStrS (String, AsciiStr, BufLen);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ return AsciiStr;
+}
+/**
+ This function encodes the content.
+
+ @param[in] ContentEncodedValue HTTP conent encoded value.
+ @param[in] OriginalContent Original content.
+ @param[out] EncodedContent Pointer to receive encoded content.
+ @param[out] EncodedContentLength Length of encoded content.
+
+ @retval EFI_SUCCESS Content encoded successfully.
+ @retval EFI_UNSUPPORTED No source encoding funciton,
+ @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.
+
+**/
+EFI_STATUS
+EncodeRequestContent (
+ IN CHAR8 *ContentEncodedValue,
+ IN CHAR8 *OriginalContent,
+ OUT VOID **EncodedContent,
+ OUT UINTN *EncodedContentLength
+)
+{
+ EFI_STATUS Status;
+ VOID *EncodedPointer;
+ UINTN EncodedLength;
+
+ if (OriginalContent == NULL || EncodedContent == NULL || EncodedContentLength == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Status = RedfishContentEncode (
+ ContentEncodedValue,
+ OriginalContent,
+ AsciiStrLen (OriginalContent),
+ &EncodedPointer,
+ &EncodedLength
+ );
+ if (Status == EFI_SUCCESS) {
+ *EncodedContent = EncodedPointer;
+ *EncodedContentLength = EncodedLength;
+ return EFI_SUCCESS;
+ }
+ return Status;
+}
+
+/**
+ This function decodes the content. The Memory block pointed by
+ ContentPointer would be freed and replaced with the cooked Redfish
+ payload.
+
+ @param[in] ContentEncodedValue HTTP conent encoded value.
+ @param[in, out] ContentPointer Pointer to encoded content.
+ Pointer of decoded content when out.
+ @param[in, out] ContentLength Pointer to the length of encoded content.
+ Length of decoded content when out.
+
+ @retval EFI_SUCCESS Functinos found.
+ @retval EFI_UNSUPPORTED No functions found.
+ @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.
+
+**/
+EFI_STATUS
+DecodeResponseContent (
+ IN CHAR8 *ContentEncodedValue,
+ IN OUT VOID **ContentPointer,
+ IN OUT UINTN *ContentLength
+)
+{
+ EFI_STATUS Status;
+ VOID *DecodedPointer;
+ UINTN DecodedLength;
+
+ if (ContentEncodedValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Status = RedfishContentDecode (
+ ContentEncodedValue,
+ *ContentPointer,
+ *ContentLength,
+ &DecodedPointer,
+ &DecodedLength
+ );
+ if (Status == EFI_SUCCESS) {
+ FreePool (*ContentPointer);
+ *ContentPointer = DecodedPointer;
+ *ContentLength = DecodedLength;
+ }
+ return Status;
+}
+
+/**
+ Create a HTTP URL string for specific Redfish resource.
+
+ This function build a URL string from the Redfish Host interface record and caller specified
+ relative path of the resource.
+
+ Callers are responsible for freeing the returned string storage pointed by HttpUrl.
+
+ @param[in] RedfishData Redfish network host interface record.
+ @param[in] RelativePath Relative path of a resource.
+ @param[out] HttpUrl The pointer to store the returned URL string.
+
+ @retval EFI_SUCCESS Build the URL string successfully.
+ @retval EFI_INVALID_PARAMETER RedfishData or HttpUrl is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resources.
+
+**/
+EFI_STATUS
+RedfishBuildUrl (
+ IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo,
+ IN CHAR16 *RelativePath, OPTIONAL
+ OUT CHAR16 **HttpUrl
+ )
+{
+ CHAR16 *Url;
+ CHAR16 *UrlHead;
+ UINTN UrlLength;
+ UINTN PathLen;
+
+ if ((RedfishConfigServiceInfo == NULL) || (HttpUrl == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // RFC2616: http_URL = "http(s):" "//" host [ ":" port ] [ abs_path [ "?" query ]]
+ //
+ if (RelativePath == NULL) {
+ PathLen = 0;
+ } else {
+ PathLen = StrLen (RelativePath);
+ }
+ UrlLength = StrLen (HTTPS_FLAG) + StrLen (REDFISH_FIRST_URL) + 1 + StrLen(RedfishConfigServiceInfo->RedfishServiceLocation) + PathLen;
+ Url = AllocateZeroPool (UrlLength * sizeof (CHAR16));
+ if (Url == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UrlHead = Url;
+ //
+ // Copy "http://" or "https://" according RedfishServiceIpPort.
+ //
+ if (!RedfishConfigServiceInfo->RedfishServiceUseHttps) {
+ StrCpyS (Url, StrLen (HTTPS_FLAG) + 1, HTTP_FLAG);
+ Url = Url + StrLen (HTTP_FLAG);
+ } else {
+ StrCpyS (Url, StrLen (HTTPS_FLAG) + 1, HTTPS_FLAG);
+ Url = Url + StrLen (HTTPS_FLAG);
+ }
+
+ StrCpyS (Url, StrLen (RedfishConfigServiceInfo->RedfishServiceLocation) + 1, RedfishConfigServiceInfo->RedfishServiceLocation);
+ Url = Url + StrLen (RedfishConfigServiceInfo->RedfishServiceLocation);
+
+ //
+ // Copy abs_path
+ //
+ if (RelativePath != NULL && PathLen != 0 ) {
+ StrnCpyS (Url, UrlLength, RelativePath, PathLen);
+ }
+ *HttpUrl = UrlHead;
+ return EFI_SUCCESS;
+}
+
+redfishService* createServiceEnumerator(REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo, const char* rootUri, enumeratorAuthentication* auth, unsigned int flags)
+{
+ EFI_STATUS Status;
+ CHAR16 *HttpUrl;
+ CHAR8 *AsciiHost;
+ EFI_REST_EX_PROTOCOL *RestEx;
+ redfishService *ret;
+
+ HttpUrl = NULL;
+ AsciiHost = NULL;
+ RestEx = NULL;
+ ret = NULL;
+
+ if (RedfishConfigServiceInfo->RedfishServiceRestExHandle == NULL) {
+ goto ON_EXIT;
+ }
+ Status = RedfishBuildUrl(RedfishConfigServiceInfo, NULL, &HttpUrl);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ ASSERT (HttpUrl != NULL);
+
+ AsciiHost = UnicodeStrDupToAsciiStr (HttpUrl);
+ if (AsciiHost == NULL) {
+ goto ON_EXIT;
+ }
+
+ Status = gBS->HandleProtocol (
+ RedfishConfigServiceInfo->RedfishServiceRestExHandle,
+ &gEfiRestExProtocolGuid,
+ (VOID **)&RestEx
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ if(auth == NULL) {
+ ret = createServiceEnumeratorNoAuth(AsciiHost, rootUri, true, flags, RestEx);
+ } else if(auth->authType == REDFISH_AUTH_BASIC) {
+ ret = createServiceEnumeratorBasicAuth(AsciiHost, rootUri, auth->authCodes.userPass.username, auth->authCodes.userPass.password, flags, RestEx);
+ } else if(auth->authType == REDFISH_AUTH_SESSION) {
+ ret = createServiceEnumeratorSessionAuth(AsciiHost, rootUri, auth->authCodes.userPass.username, auth->authCodes.userPass.password, flags, RestEx);
+ } else {
+ goto ON_EXIT;
+ }
+
+ ret->RestEx = RestEx;
+ON_EXIT:
+ if (HttpUrl != NULL) {
+ FreePool (HttpUrl);
+ }
+
+ if (AsciiHost != NULL) {
+ FreePool (AsciiHost);
+ }
+
+ return ret;
+}
+
+json_t* getUriFromService(redfishService* service, const char* uri, 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 || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ url = makeUrlForService(service, uri);
+ if(!url)
+ {
+ return NULL;
+ }
+
+ DEBUG((DEBUG_INFO, "libredfish: getUriFromService(): %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.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* 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* postUriFromService(redfishService* service, const char* uri, const char* content, size_t contentLength, const char* contentType, 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.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 (Http://0.0.0.0:5000/XXX), 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* deleteUriFromService(redfishService* service, const char* uri, 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;
+
+ ret = NULL;
+
+ if(service == NULL || uri == NULL || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ url = makeUrlForService(service, uri);
+ if(!url)
+ {
+ return NULL;
+ }
+
+ DEBUG((DEBUG_INFO, "libredfish: deleteUriFromService(): %a\n", url));
+
+ //
+ // Step 1: Create HTTP request message with 4 headers:
+ //
+ HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service->basicAuthStr) ? 5 : 4);
+ 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, "User-Agent", "libredfish");
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");
+ 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 = HttpMethodDelete;
+ 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.BodyLength != 0 && ResponseMsg.Body != NULL) {
+ ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, 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;
+}
+
+redfishPayload* getRedfishServiceRoot(redfishService* service, const char* version, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ json_t* value;
+ json_t* versionNode;
+ const char* verUrl;
+
+ if(version == NULL)
+ {
+ versionNode = json_object_get(service->versions, "v1");
+ }
+ else
+ {
+ versionNode = json_object_get(service->versions, version);
+ }
+ if(versionNode == NULL)
+ {
+ return NULL;
+ }
+ verUrl = json_string_value(versionNode);
+ if(verUrl == NULL)
+ {
+ return NULL;
+ }
+ value = getUriFromService(service, verUrl, StatusCode);
+ if(value == NULL)
+ {
+ if((service->flags & REDFISH_FLAG_SERVICE_NO_VERSION_DOC) == 0)
+ {
+ json_decref(versionNode);
+ }
+ return NULL;
+ }
+ return createRedfishPayload(value, service);
+}
+
+redfishPayload* getPayloadByPath(redfishService* service, const char* path, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ redPathNode* redpath;
+ redfishPayload* root;
+ redfishPayload* ret;
+
+ if(!service || !path || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ redpath = parseRedPath(path);
+ if(!redpath)
+ {
+ return NULL;
+ }
+ if(!redpath->isRoot)
+ {
+ cleanupRedPath(redpath);
+ return NULL;
+ }
+ root = getRedfishServiceRoot(service, redpath->version, StatusCode);
+ if (*StatusCode == NULL || **StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ cleanupRedPath(redpath);
+ return root;
+ }
+
+ if(redpath->next == NULL)
+ {
+ cleanupRedPath(redpath);
+ return root;
+ }
+
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+
+ ret = getPayloadForPath(root, redpath->next, StatusCode);
+ if (*StatusCode == NULL && ret != NULL) {
+ //
+ // In such a case, the Redfish resource is parsed from the input payload (root) directly.
+ // So, we still return HTTP_STATUS_200_OK.
+ //
+ *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
+ if (*StatusCode == NULL) {
+ ret = NULL;
+ } else {
+ **StatusCode = HTTP_STATUS_200_OK;
+ }
+ }
+ cleanupPayload(root);
+ cleanupRedPath(redpath);
+ return ret;
+}
+
+void cleanupServiceEnumerator(redfishService* service)
+{
+ if(!service)
+ {
+ return;
+ }
+ free(service->host);
+ json_decref(service->versions);
+ if(service->sessionToken != NULL)
+ {
+ ZeroMem (service->sessionToken, (UINTN)strlen(service->sessionToken));
+ FreePool(service->sessionToken);
+ }
+ if (service->basicAuthStr != NULL) {
+ ZeroMem (service->basicAuthStr, (UINTN)strlen(service->basicAuthStr));
+ FreePool (service->basicAuthStr);
+ }
+ free(service);
+}
+
+static int initRest(redfishService* service, void * restProtocol)
+{
+ service->RestEx = restProtocol;
+ return 0;
+}
+
+static redfishService* createServiceEnumeratorNoAuth(const char* host, const char* rootUri, bool enumerate, unsigned int flags, void * restProtocol)
+{
+ redfishService* ret;
+ char *HostStart;
+
+ ret = (redfishService*)calloc(1, sizeof(redfishService));
+ ZeroMem (ret, sizeof(redfishService));
+ if(initRest(ret, restProtocol) != 0)
+ {
+ free(ret);
+ return NULL;
+ }
+ ret->host = AllocateCopyPool(AsciiStrSize(host), host);
+ ret->flags = flags;
+ if(enumerate)
+ {
+ ret->versions = getVersions(ret, rootUri);
+ }
+ HostStart = strstr (ret->host, "//");
+ if (HostStart != NULL && (*(HostStart + 2) != '\0')) {
+ ret->HostHeaderValue = HostStart + 2;
+ }
+
+ return ret;
+}
+
+EFI_STATUS
+createBasicAuthStr (
+ IN redfishService* service,
+ IN CONST CHAR8 *UserId,
+ IN CONST CHAR8 *Password
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *RawAuthValue;
+ UINTN RawAuthBufSize;
+ CHAR8 *EnAuthValue;
+ UINTN EnAuthValueSize;
+ CHAR8 *BasicWithEnAuthValue;
+ UINTN BasicBufSize;
+
+ EnAuthValue = NULL;
+ EnAuthValueSize = 0;
+
+ RawAuthBufSize = AsciiStrLen (UserId) + AsciiStrLen (Password) + 2;
+ RawAuthValue = AllocatePool (RawAuthBufSize);
+ if (RawAuthValue == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Build raw AuthValue (UserId:Password).
+ //
+ AsciiSPrint (
+ RawAuthValue,
+ RawAuthBufSize,
+ "%a:%a",
+ UserId,
+ Password
+ );
+
+ //
+ // Encoding RawAuthValue into Base64 format.
+ //
+ Status = Base64Encode (
+ (CONST UINT8 *) RawAuthValue,
+ AsciiStrLen (RawAuthValue),
+ EnAuthValue,
+ &EnAuthValueSize
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ EnAuthValue = (CHAR8 *) AllocateZeroPool (EnAuthValueSize);
+ if (EnAuthValue == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ return Status;
+ }
+
+ Status = Base64Encode (
+ (CONST UINT8 *) RawAuthValue,
+ AsciiStrLen (RawAuthValue),
+ EnAuthValue,
+ &EnAuthValueSize
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ BasicBufSize = AsciiStrLen ("Basic ") + AsciiStrLen(EnAuthValue) + 2;
+ BasicWithEnAuthValue = AllocatePool (BasicBufSize);
+ if (BasicWithEnAuthValue == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ //
+ // Build encoded EnAuthValue with Basic (Basic EnAuthValue).
+ //
+ AsciiSPrint (
+ BasicWithEnAuthValue,
+ BasicBufSize,
+ "%a %a",
+ "Basic",
+ EnAuthValue
+ );
+
+ service->basicAuthStr = BasicWithEnAuthValue;
+
+Exit:
+ if (RawAuthValue != NULL) {
+ ZeroMem (RawAuthValue, RawAuthBufSize);
+ FreePool (RawAuthValue);
+ }
+
+ if (EnAuthValue != NULL) {
+ ZeroMem (EnAuthValue, EnAuthValueSize);
+ FreePool (EnAuthValue);
+ }
+
+ return Status;
+}
+
+static redfishService* createServiceEnumeratorBasicAuth(const char* host, const char* rootUri, const char* username, const char* password, unsigned int flags, void * restProtocol)
+{
+ redfishService* ret;
+ EFI_STATUS Status;
+
+ ret = createServiceEnumeratorNoAuth(host, rootUri, false, flags, restProtocol);
+
+ // add basic auth str
+ Status = createBasicAuthStr (ret, username, password);
+ if (EFI_ERROR(Status)) {
+ cleanupServiceEnumerator (ret);
+ return NULL;
+ }
+
+ ret->versions = getVersions(ret, rootUri);
+ return ret;
+}
+
+static redfishService* createServiceEnumeratorSessionAuth(const char* host, const char* rootUri, const char* username, const char* password, unsigned int flags, void * restProtocol)
+{
+ redfishService* ret;
+ redfishPayload* payload;
+ redfishPayload* links;
+ json_t* sessionPayload;
+ json_t* session;
+ json_t* odataId;
+ const char* uri;
+ json_t* post;
+ char* content;
+ EFI_HTTP_STATUS_CODE *StatusCode;
+
+ content = NULL;
+ StatusCode = NULL;
+
+ ret = createServiceEnumeratorNoAuth(host, rootUri, true, flags, restProtocol);
+ if(ret == NULL)
+ {
+ return NULL;
+ }
+ payload = getRedfishServiceRoot(ret, NULL, &StatusCode);
+ if(StatusCode == NULL || *StatusCode < HTTP_STATUS_200_OK || *StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT)
+ {
+ if (StatusCode != NULL) {
+ FreePool (StatusCode);
+ }
+
+ if (payload != NULL) {
+ cleanupPayload(payload);
+ }
+ cleanupServiceEnumerator(ret);
+ return NULL;
+ }
+
+ if (StatusCode != NULL) {
+ FreePool (StatusCode);
+ StatusCode = NULL;
+ }
+
+ links = getPayloadByNodeName(payload, "Links", &StatusCode);
+ cleanupPayload(payload);
+ if(links == NULL)
+ {
+ cleanupServiceEnumerator(ret);
+ return NULL;
+ }
+ session = json_object_get(links->json, "Sessions");
+ if(session == NULL)
+ {
+ cleanupPayload(links);
+ cleanupServiceEnumerator(ret);
+ return NULL;
+ }
+ odataId = json_object_get(session, "@odata.id");
+ if(odataId == NULL)
+ {
+ cleanupPayload(links);
+ cleanupServiceEnumerator(ret);
+ return NULL;
+ }
+ uri = json_string_value(odataId);
+ post = json_object();
+ addStringToJsonObject(post, "UserName", username);
+ addStringToJsonObject(post, "Password", password);
+ content = json_dumps(post, 0);
+ json_decref(post);
+ sessionPayload = postUriFromService(ret, uri, content, 0, NULL, &StatusCode);
+
+ if (content != NULL) {
+ ZeroMem (content, (UINTN)strlen(content));
+ free(content);
+ }
+
+ if(sessionPayload == NULL || StatusCode == NULL || *StatusCode < HTTP_STATUS_200_OK || *StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT)
+ {
+ //Failed to create session!
+
+ cleanupPayload(links);
+ cleanupServiceEnumerator(ret);
+
+ if (StatusCode != NULL) {
+ FreePool (StatusCode);
+ }
+
+ if (sessionPayload != NULL) {
+ json_decref(sessionPayload);
+ }
+
+ return NULL;
+ }
+ json_decref(sessionPayload);
+ cleanupPayload(links);
+ FreePool (StatusCode);
+ return ret;
+}
+
+static char* makeUrlForService(redfishService* service, const char* uri)
+{
+ char* url;
+ if(service->host == NULL)
+ {
+ return NULL;
+ }
+ url = (char*)malloc(strlen(service->host)+strlen(uri)+1);
+ strcpy(url, service->host);
+ strcat(url, uri);
+ return url;
+}
+
+static json_t* getVersions(redfishService* service, const char* rootUri)
+{
+ json_t* ret = NULL;
+ EFI_HTTP_STATUS_CODE* StatusCode = NULL;
+
+ if(service->flags & REDFISH_FLAG_SERVICE_NO_VERSION_DOC)
+ {
+ service->versions = json_object();
+ if(service->versions == NULL)
+ {
+ return NULL;
+ }
+ addStringToJsonObject(service->versions, "v1", "/redfish/v1");
+ return service->versions;
+ }
+ if(rootUri != NULL)
+ {
+ ret = getUriFromService(service, rootUri, &StatusCode);
+ }
+ else
+ {
+ ret = getUriFromService(service, "/redfish", &StatusCode);
+ }
+
+ if (ret == NULL || StatusCode == NULL || *StatusCode < HTTP_STATUS_200_OK || *StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ if (ret != NULL) {
+ json_decref(ret);
+ }
+ ret = NULL;
+ }
+
+ if (StatusCode != NULL) {
+ FreePool (StatusCode);
+ }
+
+ return ret;
+}
+
+static void addStringToJsonObject(json_t* object, const char* key, const char* value)
+{
+ json_t* jValue = json_string(value);
+
+ json_object_set(object, key, jValue);
+
+ json_decref(jValue);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Readme.md b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Readme.md
new file mode 100644
index 00000000..4503ed3f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Readme.md
@@ -0,0 +1,117 @@
+# UEFI Redfish EDK2 Implementation
+
+## Introduction
+UEFI Redfish EDK2 solution is an efficient and secure solution for the end-users to remote configure (in Out-of-band) UEFI platform configurations by leveraging the Redfish RESTful API. It's simple for end-users to access the configurations of UEFI firmware which have the equivalent properties defined in Redfish schema.
+
+Below are the block diagrams of UEFI Redfish EDK2 Implementation. ***[EDK2 Redfish Foundation[1]](#[0])*** in the lower part of the figure refers to the EDK2 Redfish Foundation, which provides the fundamental EDK2 drivers to communicate with Redfish service ***([[19]](#[0]) in the above figure)***. The Redfish service could be implemented in BMC to manage the system, or on the network for managing multiple systems.
+
+***[EDK2 Redfish Client[2]](#[0])*** in the upper part of the figure refers to the EDK2 Redfish client, which is the EDK2 Redfish application used to configure platform configurations by consuming the Redfish properties. The EDK2 Redfish client can also provision the UEFI platform-owned Redfish properties, consume and update Redfish properties as well. The ***[EDK2 Redfish Feature DXE Drivers [17]](#[0])*** is the next project after EDK2 Redfish Foundation. Each EDK2 Redfish Feature DXE Driver is designed to communicate with the particular Redfish data model defined in the Redfish schema *(e.g. Edk2RedfishBiosDxe driver manipulates the properties defined in Redfish BIOS data model)*.
+
+## <a name="[0]">EDK2 Redfish Implementation Diagrams</a>
+![UEFI Redfish Implementation](https://github.com/tianocore/edk2/blob/master/RedfishPkg/Documents/Media/RedfishDriverStack.svg?raw=true)
+
+## EFI EDK2 Redfish Driver Stack
+Below are the EDK2 drivers implemented on EDK2,
+
+### EDK2 Redfish Host Interface DXE Driver ***[[6]](#[0])***
+
+The abstract EDK2 DXE driver to create SMBIOS type 42 record through EFI SMBIOS protocol according to the device descriptor and protocol type data (defined in SMBIOS type 42h ***[[7]](#[0])***) provided by platform level Redfish host interface library. On EDK2 open source implementation (**EmulatorPkg**), SMBIOS type 42 data is retrieved from EFI variables created by RedfishPlatformConfig.efi ***[[20]](#[0])*** under EFI shell. OEM may provide its own PlatformHostInterfaceLib ***[[11]](#[0])*** instance for the platform-specific implementation.
+
+### EDK2 Refish Credential DXE Driver ***[[5]](#[0])***
+
+The abstract DXE driver which incorporates with RedfishPlatformCredentialLib ***[[10]](#[0])*** to acquire the credential of Redfish service. On edk2 EmulatorPkg implementation, the credential is hardcoded using the fixed Account/Password in order to connect to Redfish service established by [Redfish Profile Simulator](https://github.com/DMTF/Redfish-Profile-Simulator). OEM may provide its own RedfishPlatformCredentialLib instance for the platform-specific implementation.
+
+### EFI REST EX UEFI Driver for Redfish service ***[[4]](#[0])***
+
+This is the network-based driver instance of EFI_REST_EX protocol [(UEFI spec 2.8, section 29.7.2)](http://uefi.org/specifications) for communicating with Redfish service using the HTTP protocol. OEM may have its own EFI REST EX UEFI Driver instance on which the underlying transport to Redfish service could be proprietary.
+
+### EFI Redfish Discover UEFI Driver ***[[3]](#[0])***
+
+EFI Redfish Discover Protocol implementation (UEFI spec 2.8, section 31.1). Only support Redfish service discovery through Redfish Host Interface. The Redfish service discovery using SSDP over UDP ***[[18]](#[0])*** is not implemented at the moment.
+
+### EFI REST JSON Structure DXE Driver ***[[9]](#[0])***
+
+EFI REST JSON Structure DXE implementation (UEFI spec 2.8, section 29.7.3). This could be used by EDK2 Redfish Feature DXE Drivers ***[[17]](#[0])***. The EDK2 Redfish feature drivers manipulate platform-owned Redfish properties in C structure format and convert them into the payload in JSON format through this protocol. This driver leverages the effort of [Redfish Schema to C Generator](https://github.com/DMTF/Redfish-Schema-C-Struct-Generator) to have the "C Structure" <-> "JSON" conversion.
+
+### EDK2 Redfish Config Handler UEFI Driver ***[[15]](#[0])***
+
+This is the centralized manager of EDK2 Redfish feature drivers, it initiates EDK2 Redfish feature drivers by invoking init() function of EDK2 Redfish Config Handler Protocol ***[[16]](#[0])*** installed by each EDK2 Redfish feature driver. EDK2 Redfish Config Handler driver is an UEFI driver which has the dependency with EFI REST EX protocol and utilizes EFI Redfish Discover protocol to discover Redfish service that manages this system.
+
+### EDK2 Content Coding Library ***[[12]](#[0])***
+The library is incorporated with RedfishLib ***[[13]](#[0])*** to encode and decode Redfish JSON payload. This is the platform library to support HTTP Content-Encoding/Accept-Encoding headers. EumlatorPkg use the NULL instance of this library because [Redfish Profile Simulator](https://github.com/DMTF/Redfish-Profile-Simulator) supports neither HTTP Content-Encoding header on the payload returned to Redfish client nor HTTP Accept-Encoding header.
+
+## Other Open Source Projects
+ The following libraries are the wrappers of other open source projects used in RedfishPkg
+
+ * **RedfishPkg\PrivateLibrary\RedfishLib** ***[[13]](#[0])***
+ This is the wrapper of open source project ***[libredfish](https://github.com/DMTF/libredfish)***,
+ which is the library to initialize the connection to Redfish service with the proper credential and execute Create/Read/Update/Delete (CRUD) HTTP methods on Redfish properties.
+
+ * **RedfishPkg\Library\JsonLib** ***[[14]](#[0])***
+ This is the wrapper of open source project ***[Jansson](https://digip.org/jansson)***, which is the library that provides APIs to manipulate JSON payload.
+
+## Platform Components for EDK2 EmulatorPkg:
+ * **RedfishPlatformCredentialLib**
+ the EDK2 Emulator platform implementation of acquiring credential to build up the communication between UEFI firmware and Redfish service. ***[[10]](#[0])***
+
+ * **RedfishPlatformHostInterfaceLib**
+ EDK2 Emulator platform implementation which provides the information of building up SMBIOS type 42h record. ***[[11]](#[0])***
+
+## Miscellaneous:
+
+ * **EFI Shell Application**
+ RedfishPlatformConfig.exe is an EFI Shell application used to set up the Redfish service information for the EDK2 Emulator platform. The information such as IP address, subnet, and port.
+ ```C
+ For example, run shell command "RedfishPlatformConfig.efi -s 192.168.10.101 255.255.255.0 192.168.10.123 255.255.255.0", which means
+ the source IP address is 192.168.10.101, and the Redfish Server IP address is 192.168.10.123.
+ ```
+
+ * **Redfish Profile Simulator**
+ Refer to [Redfish Profile Simulator](https://github.com/DMTF/Redfish-Profile-Simulator) to set up the Redfish service.
+ We are also in the progress to contribute bug fixes and enhancements to the mainstream Redfish Profile Simulator in order to incorporate with EDK2 Redfish solution.
+
+## Connect to Redfish Service on EDK2 Emulator Platform
+ 1. Install the WinpCap and copy [SnpNt32Io.dll](https://github.com/tianocore/edk2-NetNt32Io) to the building directory of the Emulator platform. This is the emulated network interface for EDK2 Emulator Platform.
+ ```C
+ e.g. %WORKSPACE%/Build/EmulatorX64/DEBUG_VS2015x86/X64
+ ```
+
+ 2. Enable below macros in EmulatorPkg.dsc
+ ```C
+ NETWORK_HTTP_ENABLE = TRUE
+ SECURE_BOOT_ENABLE = TRUE
+ REDFISH_ENABLE = TRUE
+ ```
+
+ 3. Allow HTTP connection
+ Enable below macro to allow HTTP connection on EDK2 network stack for connecting to [Redfish Profile Simulator](https://github.com/DMTF/Redfish-Profile-Simulator) becasue Redfish Profile Simulator doesn't support HTTPS.
+ ```C
+ NETWORK_ALLOW_HTTP_CONNECTIONS = TRUE
+ ```
+
+ 4. Assign the correct MAC Address
+ Assign the correct MAC address of the network interface card emulated by WinpCap.
+ - Rebuild EmulatorPkg and boot to EFI shell once SnpNt32Io.dll is copied to the building directory and the macros mentioned in #2 are all set to TURE.
+ - Execute the EFI shell command "ifconfig -l" under EFI shell and look for MAC address information, then assign the MAC address to below PCD.
+ ```c
+ gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceDevicePath.DevicePath|{DEVICE_PATH("MAC(000000000000,0x1)")}
+ ```
+
+ 5. Configure the Redfish service on the EDK2 Emulator platform
+
+ Execute RedfishPlatformConfig.efi under EFI shell to configure the Redfish service information. The EFI variables are created for storing Redfish service information and is consumed by RedfishPlatformHostInterfaceLib under EmulatorPkg.
+
+## Related Materials
+1. [DSP0270](https://www.dmtf.org/sites/default/files/standards/documents/DSP0270_1.3.0.pdf) - Redfish Host Interface Specification, 1.3.0
+2. [DSP0266](https://www.dmtf.org/sites/default/files/standards/documents/DSP0266_1.12.0.pdf) - Redfish Specification, 1.12.0
+3. Redfish Schemas - https://redfish.dmtf.org/schemas/v1/
+4. UEFI Specification - http://uefi.org/specifications
+
+## The Contributors
+Thanks to the below predecessors who contributed to the UEFI EDK2 Redfish Prove of Concept code.\
+Fu, Siyuan <siyuan.fu@intel.com>\
+Ye, Ting <ting.ye@intel.com>\
+Wang, Fan <fan.wang@intel.com>\
+Wu, Jiaxin <jiaxin.wu@intel.com>\
+Yao, Jiewen <jiewen.yao@intel.com>\
+Shia, Cinnamon <cinnamon.shia@hpe.com>
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.dsc.inc b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.dsc.inc
new file mode 100644
index 00000000..da8a4a9b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.dsc.inc
@@ -0,0 +1,21 @@
+## @file
+# Redfish DSC include file for Platform DSC
+#
+# This file includes all required information to enable Redfish features.
+# It can be included to a platform DSC file by using "!include RedfishPkg/Redfish.dsc.inc".
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ !include RedfishPkg/RedfishDefines.dsc.inc
+
+[LibraryClasses]
+ !include RedfishPkg/RedfishLibs.dsc.inc
+
+[Components]
+ !include RedfishPkg/RedfishComponents.dsc.inc
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.fdf.inc b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.fdf.inc
new file mode 100644
index 00000000..21754f00
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.fdf.inc
@@ -0,0 +1,20 @@
+## @file
+# Redfish FDF include file for [FV*] section of all Architectures.
+#
+# This file can be included to the [FV*] section(s) of a platform FDF file
+# by using "!include RedfishPkg/RedfisLibs.fdf.inc" to specify the module instances
+# to be built in the firmware volume.
+#
+# (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+!if $(REDFISH_ENABLE) == TRUE
+ INF RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf
+ INF RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf
+ INF RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
+ INF RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf
+ INF RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf
+ INF RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf
+!endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishComponents.dsc.inc b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishComponents.dsc.inc
new file mode 100644
index 00000000..81b5e6b8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishComponents.dsc.inc
@@ -0,0 +1,22 @@
+## @file
+# Redfish DSC include file for [Components*] section of all Architectures.
+#
+# This file can be included to the [Components*] section(s) of a platform DSC file
+# by using "!include RedfishPkg/RedfishComponents.dsc.inc" to specify the INF files
+# of EDKII Redfish drivers according to the value of flags described in
+# "RedfishDefines.dsc.inc".
+#
+# (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+!if $(REDFISH_ENABLE) == TRUE
+ RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf
+ RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf
+ RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
+ RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf
+ RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf
+ RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf
+!endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.c
new file mode 100644
index 00000000..ca10a84d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.c
@@ -0,0 +1,265 @@
+/** @file
+ The common code of EDKII Redfish Configuration Handler driver.
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishConfigHandlerCommon.h"
+
+REDFISH_CONFIG_DRIVER_DATA gRedfishConfigData; // Only one Redfish service supproted
+ // on platform for the BIOS
+ // Redfish configuration.
+EFI_EVENT gEndOfDxeEvent = NULL;
+EFI_EVENT gExitBootServiceEvent = NULL;
+EDKII_REDFISH_CREDENTIAL_PROTOCOL *gCredential = NULL;
+
+/**
+ Callback function executed when the EndOfDxe event group is signaled.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[out] Context Pointer to the Context buffer.
+
+**/
+VOID
+EFIAPI
+RedfishConfigOnEndOfDxe (
+ IN EFI_EVENT Event,
+ OUT VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gCredential->StopService (gCredential, ServiceStopTypeSecureBootDisabled);
+ if (EFI_ERROR(Status) && Status != EFI_UNSUPPORTED) {
+ DEBUG ((DEBUG_ERROR, "Redfish credential protocol faied to stop service on EndOfDxe: %r", Status));
+ }
+
+ //
+ // Close event, so it will not be invoked again.
+ //
+ gBS->CloseEvent (gEndOfDxeEvent);
+ gEndOfDxeEvent = NULL;
+}
+
+/**
+ Callback function executed when the ExitBootService event group is signaled.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[out] Context Pointer to the Context buffer
+
+**/
+VOID
+EFIAPI
+RedfishConfigOnExitBootService (
+ IN EFI_EVENT Event,
+ OUT VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gCredential->StopService (gCredential, ServiceStopTypeExitBootService);
+ if (EFI_ERROR(Status) && Status != EFI_UNSUPPORTED) {
+ DEBUG ((DEBUG_ERROR, "Redfish credential protocol faied to stop service on ExitBootService: %r", Status));
+ }
+}
+
+/**
+ Unloads an image.
+
+ @param[in] ImageHandle Handle that identifies the image to be unloaded.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+
+**/
+EFI_STATUS
+RedfishConfigDriverCommonUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ if (gEndOfDxeEvent != NULL) {
+ gBS->CloseEvent (gEndOfDxeEvent);
+ gEndOfDxeEvent = NULL;
+ }
+
+ if (gExitBootServiceEvent != NULL) {
+ gBS->CloseEvent (gExitBootServiceEvent);
+ gExitBootServiceEvent = NULL;
+ }
+
+ if (gRedfishConfigData.Event != NULL) {
+ gBS->CloseEvent (gRedfishConfigData.Event);
+ gRedfishConfigData.Event = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This is the common code for Redfish configuration UEFI and DXE driver
+ initialization.
+
+ @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 Others An unexpected error occurred.
+**/
+EFI_STATUS
+RedfishConfigCommonInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ //
+ // Locate Redfish Credential Protocol to get credential for
+ // accessing to Redfish service.
+ //
+ Status = gBS->LocateProtocol (&gEdkIIRedfishCredentialProtocolGuid, NULL, (VOID **) &gCredential);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "%a: No Redfish Credential Protocol is installed on system.", __FUNCTION__));
+ return Status;
+ }
+ //
+ // Create EndOfDxe Event.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RedfishConfigOnEndOfDxe,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &gEndOfDxeEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Fail to register End Of DXE event.", __FUNCTION__));
+ return Status;
+ }
+ //
+ // Create Exit Boot Service event.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RedfishConfigOnExitBootService,
+ NULL,
+ &gEfiEventExitBootServicesGuid,
+ &gExitBootServiceEvent
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (gEndOfDxeEvent);
+ gEndOfDxeEvent = NULL;
+ DEBUG ((DEBUG_ERROR, "%a: Fail to register Exit Boot Service event.", __FUNCTION__));
+ return Status;
+ }
+ return EFI_SUCCESS;
+}
+/**
+ This is the common code to stop EDK2 Redfish feature driver.
+
+ @retval EFI_SUCCESS All EDK2 Redfish feature drivers are
+ stopped.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+RedfishConfigCommonStop (
+ VOID
+)
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ UINTN Index;
+ EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *ConfigHandler;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
+ return Status;
+ }
+
+ Status = EFI_SUCCESS;
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ (VOID**) &ConfigHandler
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = ConfigHandler->Stop (ConfigHandler);
+ if (EFI_ERROR (Status) && Status != EFI_UNSUPPORTED) {
+ DEBUG ((DEBUG_ERROR, "ERROR: Failed to stop Redfish config handler %p.\n", ConfigHandler));
+ break;
+ }
+ }
+ return Status;
+}
+/**
+ Callback function executed when a Redfish Config Handler Protocol is installed
+ by EDK2 Redfish Feature Drivers.
+
+**/
+VOID
+RedfishConfigHandlerInitialization (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *ConfigHandler;
+ UINTN Index;
+ UINT32 Id;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer [Index],
+ &gEfiCallerIdGuid,
+ (VOID **) &Id
+ );
+ if (!EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = gBS->HandleProtocol (
+ HandleBuffer [Index],
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ (VOID**) &ConfigHandler
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = ConfigHandler->Init (ConfigHandler, &gRedfishConfigData.RedfishServiceInfo);
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ DEBUG ((DEBUG_ERROR, "ERROR: Failed to init Redfish config handler %p.\n", ConfigHandler));
+ }
+ //
+ // Install caller ID to indicate Redfish Configure Handler is initialized.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &HandleBuffer [Index],
+ &gEfiCallerIdGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *)&gRedfishConfigData.CallerId
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.h
new file mode 100644
index 00000000..32a3cace
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.h
@@ -0,0 +1,101 @@
+/** @file
+ Common Header file for Redfish Configuration Handler UEFI driver
+ and DXE driver.
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_CONFIG_HANDLER_COMMON_H_
+#define EFI_REDFISH_CONFIG_HANDLER_COMMON_H_
+
+#include <Uefi.h>
+
+//
+// Libraries
+//
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+
+//
+// Consumed Protocols
+//
+#include <Protocol/EdkIIRedfishCredential.h>
+#include <Protocol/EdkIIRedfishConfigHandler.h>
+
+//
+// Driver Version
+//
+#define REDFISH_CONFIG_VERSION 0x00000001
+
+///
+/// Internal structure used by Redfish Config DXE driver.
+///
+typedef struct {
+ UINT32 CallerId; ///< Caller ID used to indicate Redfish Config Handler
+ ///< has been initiated
+ EFI_HANDLE Image; ///< Image handle of Redfish Config Driver
+ EFI_EVENT Event; ///< Event for the notification of EFI_REDFISH_CONFIG_HANDLER_PROTOCOL
+ REDFISH_CONFIG_SERVICE_INFORMATION RedfishServiceInfo; /// Redfish Service information discovered
+} REDFISH_CONFIG_DRIVER_DATA;
+
+/**
+ Common code of unloading image for both UEFI/DXE Redfish Configuration drivers.
+
+ @param[in] ImageHandle Handle that identifies the image to be unloaded.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+
+**/
+EFI_STATUS
+RedfishConfigDriverCommonUnload (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ This is the common code for Redfish configuration UEFI and DXE driver
+ initialization.
+
+ @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 Others An unexpected error occurred.
+**/
+EFI_STATUS
+RedfishConfigCommonInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ This is the common code to stop EDK2 Redfish feature driver.
+
+ @retval EFI_SUCCESS All EDK2 Redfish feature drivers are
+ stopped.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+RedfishConfigCommonStop (
+ VOID
+);
+
+/**
+ Callback function executed when a Redfish Config Handler Protocol is installed
+ by EDK2 Redfish Feature Drivers.
+
+**/
+VOID
+RedfishConfigHandlerInitialization (
+ VOID
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.c
new file mode 100644
index 00000000..c988140a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.c
@@ -0,0 +1,587 @@
+/** @file
+ The UEFI driver model driver which is responsible for locating the
+ Redfish service through Redfish host interface and executing EDKII
+ Redfish feature drivers.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishConfigHandlerDriver.h"
+
+EFI_EVENT gEfiRedfishDiscoverProtocolEvent = NULL;
+
+//
+// Variables for using RFI Redfish Discover Protocol
+//
+VOID *gEfiRedfishDiscoverRegistration;
+EFI_HANDLE gEfiRedfishDiscoverControllerHandle = NULL;
+EFI_REDFISH_DISCOVER_PROTOCOL *gEfiRedfishDiscoverProtocol = NULL;
+BOOLEAN gRedfishDiscoverActivated = FALSE;
+BOOLEAN gRedfishServiceDiscovered = FALSE;
+//
+// Network interfaces discovered by EFI Redfish Discover Protocol.
+//
+UINTN gNumberOfNetworkInterfaces;
+EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *gNetworkInterfaceInstances = NULL;
+EFI_REDFISH_DISCOVERED_TOKEN *gRedfishDiscoveredToken = NULL;
+
+///
+/// Driver Binding Protocol instance
+///
+EFI_DRIVER_BINDING_PROTOCOL gRedfishConfigDriverBinding = {
+ RedfishConfigDriverBindingSupported,
+ RedfishConfigDriverBindingStart,
+ RedfishConfigDriverBindingStop,
+ REDFISH_CONFIG_VERSION,
+ NULL,
+ NULL
+};
+
+/**
+ Stop acquiring Redfish service.
+
+**/
+VOID
+RedfishConfigStopRedfishDiscovery (
+ VOID
+)
+{
+ if (gRedfishDiscoverActivated) {
+ //
+ // No more EFI Discover Protocol.
+ //
+ if (gEfiRedfishDiscoverProtocolEvent != NULL) {
+ gBS->CloseEvent (gEfiRedfishDiscoverProtocolEvent);
+ }
+ //
+ // Stop Redfish service discovery.
+ //
+ gEfiRedfishDiscoverProtocol->AbortAcquireRedfishService (
+ gEfiRedfishDiscoverProtocol,
+ gNetworkInterfaceInstances
+ );
+ gEfiRedfishDiscoverControllerHandle = NULL;
+ gEfiRedfishDiscoverProtocol = NULL;
+ gRedfishDiscoverActivated = FALSE;
+ gRedfishServiceDiscovered = FALSE;
+ }
+}
+
+/**
+ Callback function executed when a Redfish Config Handler Protocol is installed.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the REDFISH_CONFIG_DRIVER_DATA buffer.
+
+**/
+VOID
+EFIAPI
+RedfishConfigHandlerInstalledCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ if (!gRedfishDiscoverActivated) {
+ //
+ // No Redfish service is discovered yet.
+ //
+ return;
+ }
+
+ RedfishConfigHandlerInitialization ();
+}
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_REST_EX_PROTOCOL *RestEx;
+ EFI_STATUS Status;
+ EFI_HANDLE ChildHandle;
+
+ ChildHandle = NULL;
+
+ //
+ // Check if REST EX is ready. This just makes sure
+ // the network stack is brought up.
+ //
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ This->ImageHandle,
+ &gEfiRestExServiceBindingProtocolGuid,
+ &ChildHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Test if REST EX protocol is ready.
+ //
+ Status = gBS->OpenProtocol(
+ ChildHandle,
+ &gEfiRestExProtocolGuid,
+ (VOID**) &RestEx,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ }
+ NetLibDestroyServiceChild (
+ ControllerHandle,
+ This->ImageHandle,
+ &gEfiRestExServiceBindingProtocolGuid,
+ ChildHandle
+ );
+ return Status;
+}
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The driver is started.
+ @retval EFI_ALREADY_STARTED The driver was already started.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ VOID *ConfigHandlerRegistration;
+
+ if (gRedfishConfigData.Event != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ gRedfishConfigData.Event = EfiCreateProtocolNotifyEvent (
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ TPL_CALLBACK,
+ RedfishConfigHandlerInstalledCallback,
+ (VOID *)&gRedfishConfigData,
+ &ConfigHandlerRegistration
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+
+ if (ControllerHandle == gEfiRedfishDiscoverControllerHandle) {
+ RedfishConfigStopRedfishDiscovery ();
+ }
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ gRedfishConfigData.Image,
+ gRedfishConfigData.Image
+ );
+
+ Status = RedfishConfigCommonStop ();
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (gRedfishConfigData.Event != NULL) {
+ gBS->CloseEvent (gRedfishConfigData.Event);
+ gRedfishConfigData.Event = NULL;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Callback function when Redfish service is discovered.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[out] Context Pointer to the Context buffer
+
+**/
+VOID
+EFIAPI
+RedfishServiceDiscoveredCallback (
+ IN EFI_EVENT Event,
+ OUT VOID *Context
+ )
+{
+ EFI_REDFISH_DISCOVERED_TOKEN *RedfishDiscoveredToken;
+ EFI_REDFISH_DISCOVERED_INSTANCE *RedfishInstance;
+
+ if (gRedfishServiceDiscovered) {
+ //
+ // Only support one Redfish service on platform.
+ //
+ return;
+ }
+
+ RedfishDiscoveredToken = (EFI_REDFISH_DISCOVERED_TOKEN *)Context;
+ RedfishInstance = RedfishDiscoveredToken->DiscoverList.RedfishInstances;
+ //
+ // Only pick up the first found Redfish service.
+ //
+ if (RedfishInstance->Status == EFI_SUCCESS) {
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceRestExHandle = RedfishInstance->Information.RedfishRestExHandle;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceVersion = RedfishInstance->Information.RedfishVersion;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceLocation = RedfishInstance->Information.Location;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceUuid = RedfishInstance->Information.Uuid;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceOs = RedfishInstance->Information.Os;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceOsVersion = RedfishInstance->Information.OsVersion;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceProduct = RedfishInstance->Information.Product;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceProductVer = RedfishInstance->Information.ProductVer;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceUseHttps = RedfishInstance->Information.UseHttps;
+ gRedfishServiceDiscovered = TRUE;
+ }
+
+ //
+ // Invoke RedfishConfigHandlerInstalledCallback to execute
+ // the initialization of Redfish Configure Handler instance.
+ //
+ RedfishConfigHandlerInstalledCallback (gRedfishConfigData.Event, &gRedfishConfigData);
+}
+
+/**
+ Callback function executed when the EFI_REDFISH_DISCOVER_PROTOCOL
+ protocol interface is installed.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[out] Context Pointer to the Context buffer
+
+**/
+VOID
+EFIAPI
+RedfishDiscoverProtocolInstalled (
+ IN EFI_EVENT Event,
+ OUT VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_HANDLE HandleBuffer;
+ UINTN NetworkInterfaceIndex;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *ThisNetworkInterface;
+ EFI_REDFISH_DISCOVERED_TOKEN *ThisRedfishDiscoveredToken;
+
+ DEBUG((DEBUG_INFO, "%a: New network interface is installed on system by EFI Redfish discover driver.\n", __FUNCTION__));
+
+ BufferSize = sizeof (EFI_HANDLE);
+ Status = gBS->LocateHandle (
+ ByRegisterNotify,
+ NULL,
+ gEfiRedfishDiscoverRegistration,
+ &BufferSize,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: Can't locate handle with EFI_REDFISH_DISCOVER_PROTOCOL installed.\n", __FUNCTION__));
+ }
+ gRedfishDiscoverActivated = TRUE;
+ if (gEfiRedfishDiscoverProtocol == NULL) {
+ gEfiRedfishDiscoverControllerHandle = HandleBuffer;
+ //
+ // First time to open EFI_REDFISH_DISCOVER_PROTOCOL.
+ //
+ Status = gBS->OpenProtocol(
+ gEfiRedfishDiscoverControllerHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ (VOID **)&gEfiRedfishDiscoverProtocol,
+ gRedfishConfigData.Image,
+ gRedfishConfigData.Image,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ gEfiRedfishDiscoverProtocol = NULL;
+ gRedfishDiscoverActivated = FALSE;
+ DEBUG((DEBUG_ERROR, "%a: Can't locate EFI_REDFISH_DISCOVER_PROTOCOL.\n", __FUNCTION__));
+ return;
+ }
+ }
+ //
+ // Check the new found network interface.
+ //
+ if (gNetworkInterfaceInstances != NULL) {
+ FreePool (gNetworkInterfaceInstances);
+ }
+ Status = gEfiRedfishDiscoverProtocol->GetNetworkInterfaceList(
+ gEfiRedfishDiscoverProtocol,
+ gRedfishConfigData.Image,
+ &gNumberOfNetworkInterfaces,
+ &gNetworkInterfaceInstances
+ );
+ if (EFI_ERROR (Status) || gNumberOfNetworkInterfaces == 0) {
+ DEBUG((DEBUG_ERROR, "%a: No network interfaces found on the handle.\n", __FUNCTION__));
+ return;
+ }
+
+ gRedfishDiscoveredToken = AllocateZeroPool (gNumberOfNetworkInterfaces * sizeof (EFI_REDFISH_DISCOVERED_TOKEN));
+ if (gRedfishDiscoveredToken == NULL) {
+ DEBUG((DEBUG_ERROR, "%a: Not enough memory for EFI_REDFISH_DISCOVERED_TOKEN.\n", __FUNCTION__));
+ return;
+ }
+
+ ThisNetworkInterface = gNetworkInterfaceInstances;
+ ThisRedfishDiscoveredToken = gRedfishDiscoveredToken;
+ //
+ // Loop to discover Redfish service on each network interface.
+ //
+ for (NetworkInterfaceIndex = 0; NetworkInterfaceIndex < gNumberOfNetworkInterfaces; NetworkInterfaceIndex ++) {
+ //
+ // Initial this Redfish Discovered Token
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RedfishServiceDiscoveredCallback,
+ (VOID *)ThisRedfishDiscoveredToken,
+ &ThisRedfishDiscoveredToken->Event
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: Failed to create event for Redfish discovered token.\n", __FUNCTION__));
+ goto ErrorReturn;
+ }
+ ThisRedfishDiscoveredToken->Signature = REDFISH_DISCOVER_TOKEN_SIGNATURE;
+ ThisRedfishDiscoveredToken->DiscoverList.NumberOfServiceFound = 0;
+ ThisRedfishDiscoveredToken->DiscoverList.RedfishInstances = NULL;
+ //
+ // Acquire for Redfish service which is reported by
+ // Redfish Host Interface.
+ //
+ Status = gEfiRedfishDiscoverProtocol->AcquireRedfishService(
+ gEfiRedfishDiscoverProtocol,
+ gRedfishConfigData.Image,
+ ThisNetworkInterface,
+ EFI_REDFISH_DISCOVER_HOST_INTERFACE,
+ ThisRedfishDiscoveredToken
+ );
+ ThisNetworkInterface ++;
+ ThisRedfishDiscoveredToken ++;
+ }
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: Acquire Redfish service fail.\n", __FUNCTION__));
+ goto ErrorReturn;
+ }
+ return;
+
+ErrorReturn:
+ if (gRedfishDiscoveredToken != NULL) {
+ FreePool(gRedfishDiscoveredToken);
+ }
+}
+
+/**
+ Unloads an image.
+
+ @param[in] ImageHandle Handle that identifies the image to be unloaded.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigHandlerDriverUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_REDFISH_DISCOVERED_TOKEN *ThisRedfishDiscoveredToken;
+ UINTN NumberOfNetworkInterfacesIndex;
+
+ RedfishConfigDriverCommonUnload (ImageHandle);
+
+ RedfishConfigStopRedfishDiscovery ();
+ if (gRedfishDiscoveredToken != NULL) {
+ ThisRedfishDiscoveredToken = gRedfishDiscoveredToken;
+ for (NumberOfNetworkInterfacesIndex = 0; NumberOfNetworkInterfacesIndex < gNumberOfNetworkInterfaces; NumberOfNetworkInterfacesIndex ++) {
+ if (ThisRedfishDiscoveredToken->Event != NULL) {
+ gBS->CloseEvent (ThisRedfishDiscoveredToken->Event);
+ }
+ FreePool (ThisRedfishDiscoveredToken);
+ ThisRedfishDiscoveredToken ++;
+ }
+ gRedfishDiscoveredToken = NULL;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ 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.
+
+ @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 Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigHandlerDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem ((VOID *)&gRedfishConfigData, sizeof (REDFISH_CONFIG_DRIVER_DATA));
+ gRedfishConfigData.Image = ImageHandle;
+ //
+ // Register event for EFI_REDFISH_DISCOVER_PROTOCOL protocol install
+ // notification.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RedfishDiscoverProtocolInstalled,
+ NULL,
+ &gEfiRedfishDiscoverProtocolGuid,
+ &gEfiRedfishDiscoverProtocolEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Fail to create event for the installation of EFI_REDFISH_DISCOVER_PROTOCOL.", __FUNCTION__));
+ return Status;
+ }
+ Status = gBS->RegisterProtocolNotify (
+ &gEfiRedfishDiscoverProtocolGuid,
+ gEfiRedfishDiscoverProtocolEvent,
+ &gEfiRedfishDiscoverRegistration
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Fail to register event for the installation of EFI_REDFISH_DISCOVER_PROTOCOL.", __FUNCTION__));
+ return Status;
+ }
+
+ Status = RedfishConfigCommonInit (ImageHandle, SystemTable);
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (gEfiRedfishDiscoverProtocolEvent);
+ gEfiRedfishDiscoverProtocolEvent = NULL;
+ return Status;
+ }
+
+ //
+ // Install UEFI Driver Model protocol(s).
+ //
+ Status = EfiLibInstallDriverBinding (
+ ImageHandle,
+ SystemTable,
+ &gRedfishConfigDriverBinding,
+ ImageHandle
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (gEndOfDxeEvent);
+ gEndOfDxeEvent = NULL;
+ gBS->CloseEvent (gExitBootServiceEvent);
+ gExitBootServiceEvent = NULL;
+ gBS->CloseEvent (gEfiRedfishDiscoverProtocolEvent);
+ gEfiRedfishDiscoverProtocolEvent = NULL;
+ DEBUG ((DEBUG_ERROR, "%a: Fail to install EFI Binding Protocol of EFI Redfish Config driver.", __FUNCTION__));
+ return Status;
+ }
+ return Status;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.h
new file mode 100644
index 00000000..d0ee0ade
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.h
@@ -0,0 +1,159 @@
+/** @file
+ Header file of Redfish Configuration Handler UEFI driver.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_CONFIG_HANDLER_DRIVER_H_
+#define EFI_REDFISH_CONFIG_HANDLER_DRIVER_H_
+
+#include "RedfishConfigHandlerCommon.h"
+
+//
+// UEFI Driver Model Protocols
+//
+
+#include <Protocol/DriverBinding.h>
+#include <Protocol/RedfishDiscover.h>
+#include <Protocol/RestEx.h>
+
+//
+// Protocol instances
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gRedfishConfigDriverBinding;
+
+extern REDFISH_CONFIG_DRIVER_DATA gRedfishConfigData;
+extern EDKII_REDFISH_CREDENTIAL_PROTOCOL *gCredential;
+extern EFI_EVENT gEndOfDxeEvent;
+extern EFI_EVENT gExitBootServiceEvent;
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The driver is started.
+ @retval EFI_ALREADY_STARTED The driver was already started.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf
new file mode 100644
index 00000000..782e8e62
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf
@@ -0,0 +1,60 @@
+## @file
+# INF file for the UEFI driver model Redfish Configuration Handler
+# Driver.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001000b
+ BASE_NAME = RedfishConfigHandlerDriver
+ FILE_GUID = 6e881000-5749-11e8-9bf0-8cdcd426c973
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishConfigHandlerDriverEntryPoint
+ UNLOAD_IMAGE = RedfishConfigHandlerDriverUnload
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[Sources]
+ RedfishConfigHandlerDriver.h
+ RedfishConfigHandlerDriver.c
+ RedfishConfigHandlerCommon.h
+ RedfishConfigHandlerCommon.c
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ UefiLib
+ MemoryAllocationLib
+ NetLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEfiRedfishDiscoverProtocolGuid ## CONSUMES
+ gEfiRestExServiceBindingProtocolGuid
+ gEfiRestExProtocolGuid ## CONSUMES
+ gEdkIIRedfishCredentialProtocolGuid ## CONSUMES
+ gEdkIIRedfishConfigHandlerProtocolGuid ## CONSUMES
+
+[Guids]
+ gEfiEventExitBootServicesGuid ## CONSUMES ## Event
+ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
+
+[Depex]
+ TRUE
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.c
new file mode 100644
index 00000000..5039522f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.c
@@ -0,0 +1,209 @@
+/** @file
+ RedfishCrentialDxe produces the EdkIIRedfishCredentialProtocol for the consumer
+ to get the Redfish credential Info and to restrict Redfish access from UEFI side.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <RedfishCredentialDxe.h>
+
+EDKII_REDFISH_CREDENTIAL_PROTOCOL mRedfishCredentialProtocol = {
+ RedfishCredentialGetAuthInfo,
+ RedfishCredentialStopService
+};
+
+/**
+ Callback function executed when the ExitBootServices event group is signaled.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[out] Context Pointer to the buffer pass in.
+**/
+VOID
+EFIAPI
+RedfishCredentialExitBootServicesEventNotify (
+ IN EFI_EVENT Event,
+ OUT VOID *Context
+ )
+{
+ LibCredentialExitBootServicesNotify ((EDKII_REDFISH_CREDENTIAL_PROTOCOL *)Context);
+}
+
+/**
+ Callback function executed when the EndOfDxe event group is signaled.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[out] Context Pointer to the buffer pass in.
+**/
+VOID
+EFIAPI
+RedfishCredentialEndOfDxeEventNotify (
+ IN EFI_EVENT Event,
+ OUT VOID *Context
+ )
+{
+ LibCredentialEndOfDxeNotify ((EDKII_REDFISH_CREDENTIAL_PROTOCOL *)Context);
+
+ //
+ // Close event, so it will not be invoked again.
+ //
+ gBS->CloseEvent (Event);
+}
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user Id and
+ password.
+ - For AuthMethodNone, the UserId and Password could be used for HTTP header authentication
+ as defined by RFC7235.
+ - For AuthMethodRedfishSession, the UserId and Password could be used for Redfish
+ session login as defined by Redfish API specification (DSP0266).
+
+ Callers are responsible for and freeing the returned string storage.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_ACCESS_DENIED SecureBoot is disabled after EndOfDxe.
+ @retval EFI_INVALID_PARAMETER This or AuthMethod or UserId or Password is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resources.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCredentialGetAuthInfo (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+ )
+{
+ if (This == NULL || AuthMethod == NULL || UserId == NULL || Password == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return LibCredentialGetAuthInfo (This, AuthMethod, UserId,Password);
+}
+
+/**
+ Notify the Redfish service provide to stop provide configuration service to this platform.
+
+ This function should be called when the platfrom is about to leave the safe environment.
+ It will notify the Redfish service provider to abort all logined session, and prohibit
+ further login with original auth info. GetAuthInfo() will return EFI_UNSUPPORTED once this
+ function is returned.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[in] ServiceStopType Reason of stopping Redfish service.
+
+ @retval EFI_SUCCESS Service has been stoped successfully.
+ @retval EFI_INVALID_PARAMETER This is NULL or given the worng ServiceStopType.
+ @retval EFI_UNSUPPORTED Not support to stop Redfish service.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCredentialStopService (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ IN EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE ServiceStopType
+ )
+{
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return LibStopRedfishService (This, ServiceStopType);
+}
+
+/**
+ Main entry for this driver.
+
+ @param ImageHandle Image handle this driver.
+ @param SystemTable Pointer to SystemTable.
+
+ @retval EFI_SUCESS This function always complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCredentialDxeDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_EVENT EndOfDxeEvent;
+ EFI_EVENT ExitBootServiceEvent;
+
+ Handle = NULL;
+
+ //
+ // Install the RedfishCredentialProtocol onto Handle.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEdkIIRedfishCredentialProtocolGuid,
+ &mRedfishCredentialProtocol,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // After EndOfDxe, if SecureBoot is disabled, Redfish Credential Protocol should return
+ // error code to caller to avoid the 3rd code to bypass Redfish Credential Protocol and
+ // retrieve userid/pwd directly. So, here, we create EndOfDxe Event to check SecureBoot
+ // status.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RedfishCredentialEndOfDxeEventNotify,
+ (VOID *)&mRedfishCredentialProtocol,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // After ExitBootServices, Redfish Credential Protocol should stop the service.
+ // So, here, we create ExitBootService Event to stop service.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RedfishCredentialExitBootServicesEventNotify,
+ (VOID *)&mRedfishCredentialProtocol,
+ &gEfiEventExitBootServicesGuid,
+ &ExitBootServiceEvent
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (EndOfDxeEvent);
+ goto ON_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Handle,
+ &gEdkIIRedfishCredentialProtocolGuid,
+ &mRedfishCredentialProtocol,
+ NULL
+ );
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.h
new file mode 100644
index 00000000..aee5c67f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.h
@@ -0,0 +1,75 @@
+/** @file
+ Definition of Redfish Credential DXE driver.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef EDKII_REDFISH_CREDENTIAL_DXE_H_
+#define EDKII_REDFISH_CREDENTIAL_DXE_H_
+
+#include <Protocol/EdkIIRedfishCredential.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+#include <Library/RedfishCredentialLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user Id and
+ password.
+ - For AuthMethodNone, the UserId and Password could be used for HTTP header authentication
+ as defined by RFC7235.
+ - For AuthMethodRedfishSession, the UserId and Password could be used for Redfish
+ session login as defined by Redfish API specification (DSP0266).
+
+ Callers are responsible for and freeing the returned string storage.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_ACCESS_DENIED SecureBoot is disabled after EndOfDxe.
+ @retval EFI_INVALID_PARAMETER This or AuthMethod or UserId or Password is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resources.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCredentialGetAuthInfo (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+ );
+
+/**
+ Notify the Redfish service provide to stop provide configuration service to this platform.
+
+ This function should be called when the platfrom is about to leave the safe environment.
+ It will notify the Redfish service provider to abort all logined session, and prohibit
+ further login with original auth info. GetAuthInfo() will return EFI_UNSUPPORTED once this
+ function is returned.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Service has been stoped successfully.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCredentialStopService (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ IN EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE ServiceStopType
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf
new file mode 100644
index 00000000..479e1eb8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf
@@ -0,0 +1,51 @@
+## @file
+# RedfishCredentialDxe is required to produce the
+# EdkII RedfishCredentialProtocol for the consumer to get the Redfish
+# credential Info and to restrict Redfish access from UEFI side.
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001000b
+ BASE_NAME = RedfishCredentialDxe
+ FILE_GUID = 458CE95A-4942-09A9-5D21-A6B16D5DAD7F
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishCredentialDxeDriverEntryPoint
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ RedfishCredentialDxe.c
+ RedfishCredentialDxe.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ PrintLib
+ RedfishPlatformCredentialLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ UefiLib
+
+[Protocols]
+ gEdkIIRedfishCredentialProtocolGuid ## BY_START
+
+
+[Guids]
+ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
+ gEfiEventExitBootServicesGuid ## CONSUMES ## Event
+
+[Depex]
+ TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDefines.dsc.inc b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDefines.dsc.inc
new file mode 100644
index 00000000..29a826b7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDefines.dsc.inc
@@ -0,0 +1,27 @@
+## @file
+# RedfishPkg DSC include file for [Defines] section of all Architectures.
+#
+# This file can be included to the [Defines] section of a platform DSC file by
+# using "!include RedfishPkg/RedfishDefines.dsc.inc" to set value of
+# flags.
+#
+# These flags can be defined before the !include line, or changed on the command
+# line to enable or disable related feature support.
+# -D FLAG=VALUE
+#
+# The default value of these flags are:
+# DEFINE REDFISH_ENABLE = TRUE
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+!ifndef REDFISH_ENABLE
+ #
+ # This flag is to enable or disable the whole Redfish support.
+ #
+ DEFINE REDFISH_ENABLE = TRUE
+!endif
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/ComponentName.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/ComponentName.c
new file mode 100644
index 00000000..932d668b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/ComponentName.c
@@ -0,0 +1,218 @@
+/** @file
+ Implementation of EFI_COMPONENT_NAME_PROTOCOL and EFI_COMPONENT_NAME2_PROTOCOL protocol.
+ for EFI Refish Discover Protocol
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishDiscoverInternal.h"
+
+//
+// EFI Component Name Functions
+//
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+
+///
+/// Component Name Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME_PROTOCOL gRedfishDiscoverComponentName = {
+ RedfishDiscoverComponentNameGetDriverName,
+ RedfishDiscoverComponentNameGetControllerName,
+ "eng"
+};
+
+///
+/// Component Name 2 Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL gRedfishDiscoverComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) RedfishDiscoverComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) RedfishDiscoverComponentNameGetControllerName,
+ "en"
+};
+
+///
+/// Table of driver names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mRedfishDiscoverDriverNameTable[] = {
+ { "eng;en", (CHAR16 *)L"Redfish Discover UEFI Driver" },
+ { NULL, NULL }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gRedfishDiscoverControllerNameTable = NULL;
+
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mRedfishDiscoverDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gRedfishDiscoverComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c
new file mode 100644
index 00000000..5e390ca8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c
@@ -0,0 +1,1910 @@
+/** @file
+
+ The implementation of EFI Redfidh Discover Protocol.
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishDiscoverInternal.h"
+
+LIST_ENTRY mRedfishDiscoverList;
+LIST_ENTRY mRedfishInstanceList;
+EFI_SMBIOS_PROTOCOL *mSmbios = NULL;
+
+UINTN mNumNetworkInterface = 0;
+UINTN mNumRestExInstance = 0;
+LIST_ENTRY mEfiRedfishDiscoverNetworkInterface;
+LIST_ENTRY mEfiRedfishDiscoverRestExInstance;
+
+EFI_GUID mRedfishDiscoverTcp4InstanceGuid = EFI_REDFISH_DISCOVER_TCP4_INSTANCE_GUID;
+EFI_GUID mRedfishDiscoverTcp6InstanceGuid = EFI_REDFISH_DISCOVER_TCP6_INSTANCE_GUID;
+EFI_GUID mRedfishDiscoverRestExInstanceGuid = EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_GUID;
+
+EFI_HANDLE EfiRedfishDiscoverProtocolHandle = NULL;
+
+EFI_STATUS
+EFIAPI
+Tcp4GetSubnetInfo (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
+);
+
+EFI_STATUS
+EFIAPI
+Tcp6GetSubnetInfo (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
+);
+
+static REDFISH_DISCOVER_REQUIRED_PROTOCOL gRequiredProtocol[] = {
+ {
+ ProtocolTypeTcp4,
+ L"TCP4 Service Binding Protocol",
+ &gEfiTcp4ProtocolGuid,
+ &gEfiTcp4ServiceBindingProtocolGuid,
+ &mRedfishDiscoverTcp4InstanceGuid,
+ Tcp4GetSubnetInfo
+ },
+ {
+ ProtocolTypeTcp6,
+ L"TCP6 Service Binding Protocol",
+ &gEfiTcp6ProtocolGuid,
+ &gEfiTcp6ServiceBindingProtocolGuid,
+ &mRedfishDiscoverTcp6InstanceGuid,
+ Tcp6GetSubnetInfo
+ },
+ {
+ ProtocolTypeRestEx,
+ L"REST EX Service Binding Protocol",
+ &gEfiRestExProtocolGuid,
+ &gEfiRestExServiceBindingProtocolGuid,
+ &mRedfishDiscoverRestExInstanceGuid,
+ NULL
+ }
+};
+
+/**
+ This function creates REST EX instance for the found Resfish service.
+ by known owner handle.
+
+ @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
+ @param[in] Token Client token.
+
+ @retval NULL Instance not found.
+ @retval EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE The instance owned by this owner.
+
+**/
+EFI_STATUS
+CreateRestExInstance (
+ IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance,
+ IN EFI_REDFISH_DISCOVERED_TOKEN *Token
+ )
+{
+ EFI_STATUS Status;
+
+ Status = RestExLibCreateChild (
+ Instance->Owner,
+ FixedPcdGetBool (PcdRedfishDiscoverAccessModeInBand)? EfiRestExServiceInBandAccess: EfiRestExServiceOutOfBandAccess,
+ EfiRestExConfigHttp,
+ EfiRestExServiceRedfish,
+ &Token->DiscoverList.RedfishInstances->Information.RedfishRestExHandle
+ );
+ return Status;
+}
+
+/**
+ This function gets EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
+ by known owner handle.
+
+ @param[in] ImageHandle Image handle owns EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
+ @param[in] TargetNetworkInterface Target network interface used by this EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
+ @param[in] DiscoverFlags EFI_REDFISH_DISCOVER_FLAG
+
+ @retval NULL Instance not found.
+ @retval EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE The instance owned by this owner.
+
+**/
+EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *
+GetInstanceByOwner (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *TargetNetworkInterface,
+ IN EFI_REDFISH_DISCOVER_FLAG DiscoverFlags
+ )
+{
+ EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *ThisInstance;
+
+ if (IsListEmpty (&mRedfishDiscoverList)) {
+ return NULL;
+ }
+ ThisInstance =
+ (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetFirstNode (&mRedfishDiscoverList);
+ while (TRUE) {
+ if ((ThisInstance->Owner == ImageHandle) &&
+ (ThisInstance->DiscoverFlags == DiscoverFlags) &&
+ (ThisInstance->NetworkInterface == TargetNetworkInterface)) {
+ return ThisInstance;
+ }
+ if (IsNodeAtEnd (&mRedfishDiscoverList, &ThisInstance->Entry)) {
+ break;
+ }
+ ThisInstance =
+ (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetNextNode (&mRedfishDiscoverList, &ThisInstance->Entry);
+ };
+ return NULL;
+}
+
+/**
+ This function gets the subnet information of this TCP4 instance.
+
+ @param[in] ImageHandle EFI handle with this image.
+ @param[in] Instance Instance of Network interface.
+ @retval EFI_STATUS Get subnet information successfully.
+ @retval Otherwise Fail to get subnet information.
+**/
+EFI_STATUS
+EFIAPI
+Tcp4GetSubnetInfo (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
+)
+{
+ EFI_STATUS Status;
+ EFI_TCP4_PROTOCOL *Tcp4;
+ EFI_TCP4_CONFIG_DATA Tcp4CfgData;
+ EFI_TCP4_OPTION Tcp4Option;
+ EFI_IP4_MODE_DATA IpModedata;
+ UINT8 SubnetMaskIndex;
+ UINT8 BitMask;
+ UINT8 PrefixLength;
+ BOOLEAN GotPrefixLength;
+
+ if (Instance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Tcp4 = (EFI_TCP4_PROTOCOL *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface;
+
+ ZeroMem ((VOID *)&Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));
+ ZeroMem ((VOID *)&Tcp4Option, sizeof (EFI_TCP4_OPTION));
+ // Give a local host IP address just for getting subnet information.
+ Tcp4CfgData.AccessPoint.UseDefaultAddress = TRUE;
+ Tcp4CfgData.AccessPoint.RemoteAddress.Addr [0] = 127;
+ Tcp4CfgData.AccessPoint.RemoteAddress.Addr [1] = 0;
+ Tcp4CfgData.AccessPoint.RemoteAddress.Addr [2] = 0;
+ Tcp4CfgData.AccessPoint.RemoteAddress.Addr [3] = 1;
+ Tcp4CfgData.AccessPoint.RemotePort = 80;
+ Tcp4CfgData.AccessPoint.ActiveFlag = TRUE;
+
+ Tcp4CfgData.ControlOption = &Tcp4Option;
+ Tcp4Option.ReceiveBufferSize = 65535;
+ Tcp4Option.SendBufferSize = 65535;
+ Tcp4Option.MaxSynBackLog = 5;
+ Tcp4Option.ConnectionTimeout = 60;
+ Tcp4Option.DataRetries = 12;
+ Tcp4Option.FinTimeout = 2;
+ Tcp4Option.KeepAliveProbes = 6;
+ Tcp4Option.KeepAliveTime = 7200;
+ Tcp4Option.KeepAliveInterval = 30;
+ Tcp4Option.EnableNagle = TRUE;
+ Status = Tcp4->Configure (Tcp4, &Tcp4CfgData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Can't get subnet information\n", __FUNCTION__));
+ return Status;
+ }
+ Status = Tcp4->GetModeData (Tcp4, NULL, NULL, &IpModedata, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Can't get IP mode data information\n", __FUNCTION__));
+ return Status;
+ }
+ IP4_COPY_ADDRESS (&Instance->SubnetMask, &IpModedata.ConfigData.SubnetMask);
+ Instance->SubnetAddr.v4.Addr [0] = IpModedata.ConfigData.StationAddress.Addr [0] & Instance->SubnetMask.v4.Addr [0];
+ Instance->SubnetAddr.v4.Addr [1] = IpModedata.ConfigData.StationAddress.Addr [1] & Instance->SubnetMask.v4.Addr [1];
+ Instance->SubnetAddr.v4.Addr [2] = IpModedata.ConfigData.StationAddress.Addr [2] & Instance->SubnetMask.v4.Addr [2];
+ Instance->SubnetAddr.v4.Addr [3] = IpModedata.ConfigData.StationAddress.Addr [3] & Instance->SubnetMask.v4.Addr [3];
+ //
+ // Calculate the subnet mask prefix.
+ //
+ GotPrefixLength = FALSE;
+ PrefixLength = 0;
+ SubnetMaskIndex = 0;
+ while (GotPrefixLength == FALSE && SubnetMaskIndex < 4) {
+ BitMask = 0x80;
+ while (BitMask != 0) {
+ if ((Instance->SubnetMask.v4.Addr [SubnetMaskIndex] & BitMask) != 0) {
+ PrefixLength ++;
+ } else {
+ GotPrefixLength = TRUE;
+ break;
+ }
+ BitMask = BitMask >> 1;
+ };
+ SubnetMaskIndex ++;
+ };
+ Instance->SubnetPrefixLength = PrefixLength;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function gets the subnet information of this TCP6 instance.
+
+ @param[in] ImageHandle EFI handle with this image.
+ @param[in] Instance Instance of Network interface.
+ @retval EFI_STATUS Get subnet information successfully.
+ @retval Otherwise Fail to get subnet information.
+**/
+EFI_STATUS
+EFIAPI
+Tcp6GetSubnetInfo (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
+)
+{
+ EFI_STATUS Status;
+ EFI_TCP6_PROTOCOL *Tcp6;
+ EFI_IP6_MODE_DATA IpModedata;
+
+ if (Instance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Tcp6 = (EFI_TCP6_PROTOCOL *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface;
+
+ Status = Tcp6->GetModeData (Tcp6, NULL, NULL, &IpModedata, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Can't get IP mode data information\n"));
+ return Status;
+ }
+ if (IpModedata.AddressCount == 0) {
+ DEBUG ((DEBUG_INFO, "%a: No IPv6 address configured.\n"));
+ }
+ if (Instance->SubnetAddrInfoIPv6 != NULL) {
+ FreePool (Instance->SubnetAddrInfoIPv6);
+ }
+ Instance->SubnetAddrInfoIPv6 = AllocateZeroPool (IpModedata.AddressCount * sizeof (EFI_IP6_ADDRESS_INFO));
+ if (Instance->SubnetAddrInfoIPv6 == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory fir IPv6 subnet address information\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Instance->SubnetAddrInfoIPv6Number = IpModedata.AddressCount;
+ CopyMem (
+ (VOID *)Instance->SubnetAddrInfoIPv6,
+ (VOID *)&IpModedata.AddressList,
+ IpModedata.AddressCount * sizeof (EFI_IP6_ADDRESS_INFO)
+ );
+ FreePool (IpModedata.AddressList);
+ return EFI_SUCCESS;
+}
+
+/**
+ This function searches EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
+ instance with the given EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
+
+ @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
+ NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs.
+
+ @retval Non-NULL EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL is returned.
+ @retval NULL Non of EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance is returned.
+**/
+EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *
+GetTargetNetworkInterfaceInternal (
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface
+ )
+{
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
+
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetworkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) == 0) {
+ return ThisNetworkInterface;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ return NULL;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ };
+ return NULL;
+}
+
+/**
+ This function validate if target network interface is ready for discovering
+ Redfish service.
+
+ @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
+ NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs.
+ @param[in] Flags EFI_REDFISH_DISCOVER_FLAG
+
+ @retval EFI_SUCCESS Target network interface is ready to use.
+ @retval EFI_UNSUPPORTED Target network interface is not ready to use.
+**/
+EFI_STATUS
+ValidateTargetNetworkInterface (
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface,
+ IN EFI_REDFISH_DISCOVER_FLAG Flags
+ )
+{
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
+
+ if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface) && TargetNetworkInterface == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ if (TargetNetworkInterface == NULL) {
+ return EFI_SUCCESS; // Return EFI_SUCCESS if no network interface is specified.
+ }
+
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode(&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetworkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) == 0) {
+ break;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ return EFI_UNSUPPORTED;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ };
+ if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) {
+ // Validate if UDP4/6 is supported on the given network interface.
+ // SSDP is not supported.
+
+ return EFI_SUCCESS;
+ }
+ if (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle == NULL) {
+ return EFI_UNSUPPORTED; // The required protocol on this network interface is not found.
+ }
+ return EFI_SUCCESS;
+}
+/**
+ This function returns number of network interface instance.
+
+ @retval UINTN Number of network interface instances.
+**/
+UINTN
+NumberOfNetworkInterface (VOID)
+{
+ UINTN Num;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
+
+ if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {
+ return 0;
+ }
+
+ Num = 1;
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ break;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ Num ++;
+ };
+ return Num;
+}
+
+/**
+ This function checks the IP version supported on this
+ netwoek interface.
+
+ @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
+
+ @retval TRUE Is IPv6, otherwise IPv4.
+
+**/
+BOOLEAN
+CheckIsIpVersion6 (
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface
+)
+{
+ if (ThisNetworkInterface->NetworkProtocolType == ProtocolTypeTcp6) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ This function discover Redfish service through SMBIOS host interface.
+
+ @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
+
+ @retval EFI_SUCCESS Redfish service is discovered through SMBIOS Host interface.
+ @retval Others Fail to discover Redfish service throught SMBIOS host interface
+
+**/
+EFI_STATUS
+DiscoverRedfishHostInterface (IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance)
+{
+ EFI_STATUS Status;
+ REDFISH_OVER_IP_PROTOCOL_DATA *Data;
+ REDFISH_INTERFACE_DATA *DeviceDescriptor;
+ CHAR8 UuidStr[sizeof"00000000-0000-0000-0000-000000000000" + 1];
+ CHAR16 Ipv6Str [sizeof"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1];
+ CHAR8 RedfishServiceLocateStr [sizeof"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1];
+ UINTN StrSize;
+ UINTN MacCompareStstus;
+ BOOLEAN IsHttps;
+
+ Data = NULL;
+ DeviceDescriptor = NULL;
+
+ if (mSmbios == NULL) {
+ Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID **)&mSmbios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ Status = RedfishGetHostInterfaceProtocolData (mSmbios, &DeviceDescriptor, &Data); // Search for SMBIOS type 42h
+ if (!EFI_ERROR (Status) && Data != NULL && DeviceDescriptor != NULL) {
+ //
+ // Chceck if we can reach out Redfish service using this network interface.
+ // Check with MAC address using Device Descroptor Data Device Type 04 and Type 05.
+ // Those two types of Redfish host interface device has MAC information.
+ //
+ if (DeviceDescriptor->DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) {
+ MacCompareStstus = CompareMem(&Instance->NetworkInterface->MacAddress, &DeviceDescriptor->DeviceDescriptor.PciPcieDeviceV2.MacAddress, 6);
+ } else if (DeviceDescriptor->DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2){
+ MacCompareStstus = CompareMem(&Instance->NetworkInterface->MacAddress, &DeviceDescriptor->DeviceDescriptor.UsbDeviceV2.MacAddress, 6);
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ if (MacCompareStstus != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Data->RedfishServiceIpAddressFormat == 1) {
+ IP4_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v4, (VOID *)Data->RedfishServiceIpAddress);
+ } else {
+ IP6_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v6, (VOID *)Data->RedfishServiceIpAddress);
+ }
+
+ if (Instance->HostIntfValidation) {
+ DEBUG ((DEBUG_ERROR,"%a:Send UPnP unicast SSDP to validate this Redfish Host Interface is not supported.\n", __FUNCTION__));
+ Status = EFI_UNSUPPORTED;
+ } else {
+ //
+ // Add this istance to list without detial information of Redfish
+ // service.
+ //
+ IsHttps = FALSE;
+ if (Data->RedfishServiceIpPort == 443) {
+ IsHttps = TRUE;
+ }
+ StrSize = sizeof(UuidStr);
+ AsciiSPrint(UuidStr, StrSize, "%g", &Data->ServiceUuid);
+ //
+ // Generate Redfish service location string.
+ //
+ if (Data->RedfishServiceIpAddressFormat == REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6) {
+ NetLibIp6ToStr((IPv6_ADDRESS *)&Data->RedfishServiceIpAddress, Ipv6Str, sizeof (Ipv6Str));
+ if (Data->RedfishServiceIpPort == 0 || IsHttps == TRUE) {
+ AsciiSPrintUnicodeFormat (
+ RedfishServiceLocateStr,
+ sizeof (RedfishServiceLocateStr),
+ L"%s",
+ Ipv6Str
+ );
+ } else {
+ AsciiSPrintUnicodeFormat(
+ RedfishServiceLocateStr,
+ sizeof (RedfishServiceLocateStr),
+ L"[%s]:%d",
+ Ipv6Str,
+ Data->RedfishServiceIpPort
+ );
+ }
+ } else {
+ if (Data->RedfishServiceIpPort == 0 || IsHttps == TRUE) {
+ AsciiSPrint(
+ RedfishServiceLocateStr,
+ sizeof (RedfishServiceLocateStr),
+ "%d.%d.%d.%d",
+ Data->RedfishServiceIpAddress [0],
+ Data->RedfishServiceIpAddress [1],
+ Data->RedfishServiceIpAddress [2],
+ Data->RedfishServiceIpAddress [3]
+ );
+ } else {
+ AsciiSPrint(
+ RedfishServiceLocateStr,
+ sizeof (RedfishServiceLocateStr),
+ "%d.%d.%d.%d:%d",
+ Data->RedfishServiceIpAddress [0],
+ Data->RedfishServiceIpAddress [1],
+ Data->RedfishServiceIpAddress [2],
+ Data->RedfishServiceIpAddress [3],
+ Data->RedfishServiceIpPort
+ );
+ }
+ }
+ Status = AddAndSignalNewRedfishService (
+ Instance,
+ NULL,
+ RedfishServiceLocateStr,
+ UuidStr,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ IsHttps
+ );
+ }
+ }
+ return Status;
+}
+
+/**
+ The function adds a new found Redfish service to internal list and
+ notify client.
+
+ @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
+ @param[in] RedfishVersion Redfish version.
+ @param[in] RedfishLocation Redfish location.
+ @param[in] Uuid Service UUID string.
+ @param[in] Os OS string.
+ @param[in] OsVer OS version string.
+ @param[in] Product Product string.
+ @param[in] ProductVer Product verison string.
+ @param[in] UseHttps Redfish service requires secured connection.
+ @retval EFI_SUCCESS Redfish service is added to list successfully.
+
+**/
+EFI_STATUS
+AddAndSignalNewRedfishService (
+ IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance,
+ IN UINTN *RedfishVersion OPTIONAL,
+ IN CHAR8 *RedfishLocation OPTIONAL,
+ IN CHAR8 *Uuid OPTIONAL,
+ IN CHAR8 *Os OPTIONAL,
+ IN CHAR8 *OsVer OPTIONAL,
+ IN CHAR8 *Product OPTIONAL,
+ IN CHAR8 *ProductVer OPTIONAL,
+ IN BOOLEAN UseHttps
+ )
+{
+ BOOLEAN NewFound;
+ BOOLEAN InfoRefresh;
+ BOOLEAN RestExOpened;
+ BOOLEAN DeleteRestEx;
+ EFI_STATUS Status;
+ EFI_REDFISH_DISCOVERED_INTERNAL_LIST *DiscoveredList;
+ EFI_REDFISH_DISCOVERED_INSTANCE *DiscoveredInstance;
+ CHAR16 *Char16Uuid;
+ EFI_REST_EX_PROTOCOL *RestEx;
+ EFI_REST_EX_HTTP_CONFIG_DATA *RestExHttpConfigData;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NetworkInterface;
+
+ NewFound = TRUE;
+ InfoRefresh = FALSE;
+ Char16Uuid = NULL;
+ RestExOpened = FALSE;
+ DeleteRestEx = FALSE;
+
+ DEBUG ((DEBUG_INFO,"%a:Add this instance to Redfish instance list.\n", __FUNCTION__));
+
+ if (Uuid != NULL) {
+ Char16Uuid = (CHAR16 *)AllocateZeroPool(AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, Char16Uuid, AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16));
+ }
+ DiscoveredList = NULL;
+ DiscoveredInstance = NULL;
+ RestExHttpConfigData = NULL;
+
+ NetworkInterface = Instance->NetworkInterface;
+ if (!IsListEmpty (&mRedfishInstanceList)) {
+ //
+ // Is this a duplicate redfish service.
+ //
+ DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetFirstNode (&mRedfishInstanceList);
+ NewFound = FALSE;
+ do {
+ if (Char16Uuid == NULL || DiscoveredList->Instance->Information.Uuid == NULL) {
+ //
+ // Check if this Redfish instance already found using IP addrress.
+ //
+ if (!CheckIsIpVersion6(NetworkInterface)) {
+ if (CompareMem ((VOID *)&Instance->TargetIpAddress.v4,
+ (VOID *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v4,
+ sizeof (EFI_IPv4_ADDRESS)
+ ) == 0)
+ {
+ DiscoveredInstance = DiscoveredList->Instance;
+ if (DiscoveredList->Instance->Information.Uuid == NULL &&
+ Char16Uuid != NULL) {
+ InfoRefresh = TRUE;
+ DiscoveredInstance = DiscoveredList->Instance;
+ DEBUG((DEBUG_INFO,"*** This Redfish Service information refresh ***\n"));
+ }
+ break;
+ }
+ } else {
+ if (CompareMem ((VOID *)&Instance->TargetIpAddress.v6,
+ (VOID *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v6,
+ sizeof (EFI_IPv6_ADDRESS)
+ ) == 0)
+ {
+ DiscoveredInstance = DiscoveredList->Instance;
+ break;
+ }
+ }
+ } else {
+ //
+ // Check if this Redfish instance already found using UUID.
+ //
+ if (StrCmp((const CHAR16 *)Char16Uuid, (const CHAR16 *)DiscoveredList->Instance->Information.Uuid) == 0) {
+ DiscoveredInstance = DiscoveredList->Instance;
+ break;
+ }
+ }
+ if (IsNodeAtEnd (&mRedfishInstanceList, &DiscoveredList->NextInstance)) {
+ NewFound = TRUE;
+ break;
+ }
+ DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetNextNode (&mRedfishInstanceList, &DiscoveredList->NextInstance);
+ } while (TRUE);
+ }
+ if (NewFound || InfoRefresh) {
+ if (!InfoRefresh) {
+ DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_LIST));
+ if (DiscoveredList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ InitializeListHead (&DiscoveredList->NextInstance);
+ DiscoveredInstance = (EFI_REDFISH_DISCOVERED_INSTANCE *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INSTANCE));
+ if (DiscoveredInstance == NULL) {
+ FreePool ((VOID *)DiscoveredList);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ DEBUG ((DEBUG_INFO,"*** Redfish Service Information ***\n"));
+
+ DiscoveredInstance->Information.UseHttps = UseHttps;
+ if (RedfishVersion != NULL) {
+ DiscoveredInstance->Information.RedfishVersion = *RedfishVersion;
+ DEBUG ((DEBUG_INFO,"Redfish service version: %d.\n", DiscoveredInstance->Information.RedfishVersion));
+ }
+ if (RedfishLocation != NULL) {
+ DiscoveredInstance->Information.Location = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)RedfishLocation) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)RedfishLocation, DiscoveredInstance->Information.Location, AsciiStrSize((const CHAR8 *)RedfishLocation) * sizeof(CHAR16));
+ DEBUG ((DEBUG_INFO,"Redfish service location: %s.\n", DiscoveredInstance->Information.Location));
+ }
+ if (Uuid != NULL) {
+ DiscoveredInstance->Information.Uuid = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, DiscoveredInstance->Information.Uuid, AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16));
+ DEBUG ((DEBUG_INFO,"Service UUID: %s.\n", DiscoveredInstance->Information.Uuid));
+ }
+ if (Os != NULL) {
+ DiscoveredInstance->Information.Os = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)Os) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)Os, DiscoveredInstance->Information.Os, AsciiStrSize((const CHAR8 *)Os) * sizeof(CHAR16));
+ DEBUG ((DEBUG_INFO,"Redfish service OS: %s, Version:%s.\n", DiscoveredInstance->Information.Os, DiscoveredInstance->Information.OsVersion));
+ }
+ if (OsVer != NULL) {
+ DiscoveredInstance->Information.OsVersion = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)OsVer) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)OsVer, DiscoveredInstance->Information.OsVersion, AsciiStrSize((const CHAR8 *)OsVer) * sizeof(CHAR16));
+ }
+ if (Product != NULL && ProductVer != NULL) {
+ DiscoveredInstance->Information.Product = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)Product) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)Product, DiscoveredInstance->Information.Product, AsciiStrSize((const CHAR8 *)Product) * sizeof(CHAR16));
+ DiscoveredInstance->Information.ProductVer = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)ProductVer) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)ProductVer, DiscoveredInstance->Information.ProductVer, AsciiStrSize((const CHAR8 *)ProductVer) * sizeof(CHAR16));
+ DEBUG ((DEBUG_INFO,"Redfish service product: %s, Version:%s.\n", DiscoveredInstance->Information.Product, DiscoveredInstance->Information.ProductVer));
+ }
+
+ if (RedfishLocation == NULL) {
+ // This is the Redfish reported from SMBIOS 42h
+ // without validation.
+
+ IP4_COPY_ADDRESS((VOID *)&DiscoveredInstance->Information.RedfishHostIpAddress.v4, (VOID *)&Instance->TargetIpAddress.v4);
+ }
+ if (!InfoRefresh) {
+ DiscoveredList->Instance = DiscoveredInstance;
+ InsertTailList(&mRedfishInstanceList, &DiscoveredList->NextInstance);
+ }
+ DiscoveredInstance->Status = EFI_SUCCESS;
+ } else {
+ if (DiscoveredList != NULL) {
+ DEBUG((DEBUG_INFO,"*** This Redfish Service was already found ***\n"));
+ if (DiscoveredInstance->Information.Uuid != NULL) {
+ DEBUG((DEBUG_INFO,"Service UUID: %s.\n", DiscoveredInstance->Information.Uuid));
+ } else {
+ DEBUG((DEBUG_INFO,"Service UUID: unknown.\n"));
+ }
+ }
+ }
+ if (Char16Uuid != NULL) {
+ FreePool((VOID *)Char16Uuid);
+ }
+
+ Status = EFI_SUCCESS;
+ if (NewFound || InfoRefresh) {
+ //
+ // Build up EFI_REDFISH_DISCOVERED_LIST in token.
+ //
+ Instance->DiscoverToken->DiscoverList.NumberOfServiceFound = 1;
+ Instance->DiscoverToken->DiscoverList.RedfishInstances = DiscoveredInstance;
+ DiscoveredInstance->Status = EFI_SUCCESS;
+ if (!InfoRefresh) {
+ Status = CreateRestExInstance (Instance, Instance->DiscoverToken); // Create REST EX child.
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:Can't create REST EX child instance.\n",__FUNCTION__));
+ goto ON_EXIT;
+ }
+ Status = gBS->OpenProtocol ( // Configure local host information.
+ Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
+ &gEfiRestExProtocolGuid,
+ (VOID **)&RestEx,
+ Instance->NetworkInterface->OpenDriverAgentHandle,
+ Instance->NetworkInterface->OpenDriverControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ DeleteRestEx = TRUE;
+ goto ERROR_EXIT;
+ }
+ RestExOpened = TRUE;
+ RestExHttpConfigData = AllocateZeroPool (sizeof (EFI_REST_EX_HTTP_CONFIG_DATA));
+ if (RestExHttpConfigData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DeleteRestEx = TRUE;
+ goto EXIT_FREE_CONFIG_DATA;
+ }
+ RestExHttpConfigData->SendReceiveTimeout = 5000;
+ RestExHttpConfigData->HttpConfigData.HttpVersion = HttpVersion11;
+ RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6 = CheckIsIpVersion6(NetworkInterface);
+ if (RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6) {
+ RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node = AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT));
+ if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT_FREE_CONFIG_DATA;
+ }
+ } else {
+ RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node = AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT));
+ if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT_FREE_CONFIG_DATA;
+ }
+ RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node->UseDefaultAddress = TRUE;
+ }
+ Status = RestEx->Configure (
+ RestEx,
+ (EFI_REST_EX_CONFIG_DATA)(UINT8 *)RestExHttpConfigData
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,"%a:REST EX configured..\n", __FUNCTION__));
+ DeleteRestEx = TRUE;
+ goto EXIT_FREE_ALL;
+ }
+ //
+ // Signal client, close REST EX before signaling client.
+ //
+ if (RestExOpened) {
+ gBS->CloseProtocol(
+ Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
+ &gEfiRestExProtocolGuid,
+ Instance->NetworkInterface->OpenDriverAgentHandle,
+ Instance->NetworkInterface->OpenDriverControllerHandle
+ );
+ RestExOpened = FALSE;
+ }
+ }
+ Status = gBS->SignalEvent(Instance->DiscoverToken->Event);
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,"%a:No event to signal!\n", __FUNCTION__));
+ }
+ }
+
+EXIT_FREE_ALL:;
+ if (RestExHttpConfigData != NULL && RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node != NULL) {
+ FreePool (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node);
+ }
+
+EXIT_FREE_CONFIG_DATA:;
+ if (RestExHttpConfigData != NULL) {
+ FreePool((VOID *)RestExHttpConfigData);
+ }
+ if (RestExOpened) {
+ gBS->CloseProtocol(
+ Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
+ &gEfiRestExProtocolGuid,
+ Instance->NetworkInterface->OpenDriverAgentHandle,
+ Instance->NetworkInterface->OpenDriverControllerHandle
+ );
+ }
+ERROR_EXIT:;
+ if (DeleteRestEx && RestExOpened) {
+ gBS->CloseProtocol(
+ Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
+ &gEfiRestExProtocolGuid,
+ Instance->NetworkInterface->OpenDriverAgentHandle,
+ Instance->NetworkInterface->OpenDriverControllerHandle
+ );
+ }
+ON_EXIT:;
+ return Status;
+}
+
+/**
+ This function gets the subnet information of this network interface instance.
+ can discover Redfish service on it.
+
+ @param[in] Instance EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance.
+ @param[in] ImageHandle EFI Image handle request the network interface list.
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+NetworkInterfaceGetSubnetInfo (
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance,
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ProtocolType;
+ UINT32 IPv6InfoIndex;
+ EFI_IP6_ADDRESS_INFO *ThisSubnetAddrInfoIPv6;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NewNetworkInterface;
+
+ if (Instance->GotSubnetInfo) {
+ return EFI_SUCCESS;
+ }
+
+ ProtocolType = Instance->NetworkProtocolType;
+ if (gRequiredProtocol [ProtocolType].GetSubnetInfo != NULL && Instance->GotSubnetInfo == FALSE) {
+ Status = gRequiredProtocol [ProtocolType].GetSubnetInfo (
+ ImageHandle,
+ Instance
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,"%a:Faile to get Subnet infomation.\n", __FUNCTION__));
+ return Status;
+ } else {
+ DEBUG ((DEBUG_INFO,"%a:MAC address: %s\n", __FUNCTION__, Instance->StrMacAddr));
+ if (CheckIsIpVersion6 (Instance)) {
+ if (Instance->SubnetAddrInfoIPv6Number == 0) {
+ DEBUG ((DEBUG_ERROR,"%a: There is no Subnet infomation for IPv6 network interface.\n", __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+ ThisSubnetAddrInfoIPv6 = Instance->SubnetAddrInfoIPv6; // First IPv6 address information.
+ IP6_COPY_ADDRESS (&Instance->SubnetAddr.v6, &ThisSubnetAddrInfoIPv6->Address);
+ Instance->SubnetPrefixLength = ThisSubnetAddrInfoIPv6->PrefixLength;
+ DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix length: %d.\n",
+ ThisSubnetAddrInfoIPv6->Address.Addr [7] + (UINT16)ThisSubnetAddrInfoIPv6->Address.Addr [6] * 256,
+ ThisSubnetAddrInfoIPv6->PrefixLength)
+ );
+ //
+ // If this is IPv6, then we may have to propagate network interface for IPv6 network scopes
+ // according to the Ipv6 address information.
+ //
+ ThisSubnetAddrInfoIPv6 ++;
+ for (IPv6InfoIndex = 0; IPv6InfoIndex < Instance->SubnetAddrInfoIPv6Number - 1; IPv6InfoIndex++) {
+ //
+ // Build up addtional EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instances.
+ //
+ NewNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL));
+ if (NewNetworkInterface != NULL) {
+ CopyMem ((VOID *)NewNetworkInterface, (VOID *)Instance, sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); // Clone information of first instance.
+ IP6_COPY_ADDRESS (&NewNetworkInterface->SubnetAddr.v6, &ThisSubnetAddrInfoIPv6->Address);
+ NewNetworkInterface->SubnetPrefixLength = ThisSubnetAddrInfoIPv6->PrefixLength;
+ NewNetworkInterface->GotSubnetInfo = TRUE;
+ InsertTailList (&mEfiRedfishDiscoverNetworkInterface, &NewNetworkInterface->Entry);
+ ThisSubnetAddrInfoIPv6 ++;
+ mNumNetworkInterface ++;
+ DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix length: %d.\n",
+ ThisSubnetAddrInfoIPv6->Address.Addr [7] + (UINT16)ThisSubnetAddrInfoIPv6->Address.Addr [6] * 256,
+ ThisSubnetAddrInfoIPv6->PrefixLength)
+ );
+ } else {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ } else {
+ DEBUG ((DEBUG_INFO," IPv4 Subnet:%d.%d.%d.%d Subnet mask: %d.%d.%d.%d.\n",
+ Instance->SubnetAddr.v4.Addr [0],
+ Instance->SubnetAddr.v4.Addr [1],
+ Instance->SubnetAddr.v4.Addr [2],
+ Instance->SubnetAddr.v4.Addr [3],
+ Instance->SubnetMask.v4.Addr [0],
+ Instance->SubnetMask.v4.Addr [1],
+ Instance->SubnetMask.v4.Addr [2],
+ Instance->SubnetMask.v4.Addr [3]
+ ));
+ }
+ }
+ }
+ Instance->GotSubnetInfo = TRUE; // Only try to get Subnet Info once.
+ return EFI_SUCCESS;
+}
+
+/**
+ This function gets the network interface list which Redfish discover protocol
+ can discover Redfish service on it.
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] ImageHandle EFI Image handle request the network interface list,
+ @param[out] NumberOfNetworkIntfs Number of network interfaces can do Redfish service discovery.
+ @param[out] NetworkIntfInstances Network interface instances. It's an array of instance. The number of entries
+ in array is indicated by NumberOfNetworkIntfs.
+ Caller has to release the memory
+ allocated by Redfish discover protocol.
+
+ @retval EFI_SUCCESS The information of network interface is returned in NumberOfNetworkIntfs and
+ NetworkIntfInstances.
+ @retval Others Fail to return the information of network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishServiceGetNetworkInterface (
+ IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
+ IN EFI_HANDLE ImageHandle,
+ OUT UINTN *NumberOfNetworkIntfs,
+ OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE **NetworkIntfInstances
+)
+{
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterfaceIntn;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *ThisNetworkInterface;
+
+ if (NetworkIntfInstances == NULL || NumberOfNetworkIntfs == NULL || ImageHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *NumberOfNetworkIntfs = 0;
+ *NetworkIntfInstances = NULL;
+
+ if (IsListEmpty ((const LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterface)) {
+ return EFI_NOT_FOUND;
+ }
+
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE) * mNumNetworkInterface);
+ if (ThisNetworkInterface == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ *NetworkIntfInstances = ThisNetworkInterface;
+ ThisNetworkInterfaceIntn = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ ThisNetworkInterface->IsIpv6 = FALSE;
+ if (CheckIsIpVersion6 (ThisNetworkInterfaceIntn)) {
+ ThisNetworkInterface->IsIpv6 = TRUE;
+ }
+ CopyMem((VOID *)&ThisNetworkInterface->MacAddress, &ThisNetworkInterfaceIntn->MacAddress, ThisNetworkInterfaceIntn->HwAddressSize);
+ NetworkInterfaceGetSubnetInfo(ThisNetworkInterfaceIntn, ImageHandle); // Get subnet info.
+ if (!ThisNetworkInterface->IsIpv6) {
+ IP4_COPY_ADDRESS(&ThisNetworkInterface->SubnetId.v4, &ThisNetworkInterfaceIntn->SubnetAddr.v4); // IPv4 subnet information.
+ } else {
+ IP6_COPY_ADDRESS (&ThisNetworkInterface->SubnetId.v6, &ThisNetworkInterfaceIntn->SubnetAddr.v6); // IPv6 subnet information in IPv6 address information.
+ }
+ ThisNetworkInterface->SubnetPrefixLength = ThisNetworkInterfaceIntn->SubnetPrefixLength;
+ ThisNetworkInterface->VlanId = ThisNetworkInterfaceIntn->VlanId;
+ (*NumberOfNetworkIntfs) ++;
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfaceIntn->Entry)) {
+ break;
+ }
+ ThisNetworkInterfaceIntn = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfaceIntn->Entry);
+ ThisNetworkInterface ++;
+ };
+ return EFI_SUCCESS;
+}
+/**
+ This function acquires Redfish services by discovering static Redfish setting
+ according to Redfish Host Interface or through SSDP. Returns a list of EFI
+ handles in EFI_REDFISH_DISCOVERED_LIST. Each of EFI handle has cooresponding
+ EFI REST EX instance installed on it. Each REST EX isntance is a child instance which
+ created through EFI REST EX serivce protoocl for communicating with specific
+ Redfish service.
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] ImageHandle EFI image owns these Redfish service instances.
+ @param[in] TargetNetworkInterface Target network interface to do the discovery.
+ NULL means discover Redfish service on all network interfaces on platform.
+ @param[in] Flags Redfish service discover flags.
+ @param[in] Token EFI_REDFISH_DISCOVERED_TOKEN instance.
+ The memory of EFI_REDFISH_DISCOVERED_LIST and the strings in
+ EFI_REDFISH_DISCOVERED_INFORMATION are all allocated by Acquire()
+ and must be freed when caller invoke Release().
+
+ @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
+ @retval EFI_INVALID_PARAMETERS ImageHandle == NULL, Flags == 0, Token == NULL, Token->Timeout > 5,
+ or Token->Event == NULL.
+ @retval Others Fail acquire Redfish services.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishServiceAcquireService (
+ IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface,
+ IN EFI_REDFISH_DISCOVER_FLAG Flags,
+ IN EFI_REDFISH_DISCOVERED_TOKEN *Token
+ )
+{
+ EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance;
+ EFI_STATUS Status1;
+ EFI_STATUS Status2;
+ BOOLEAN NewInstance;
+ UINTN NumNetworkInterfaces;
+ UINTN NetworkInterfacesIndex;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *TargetNetworkInterfaceInternal;
+
+ DEBUG ((DEBUG_INFO,"%a:Entry.\n", __FUNCTION__));
+
+ //
+ // Validate parameters.
+ //
+ if (ImageHandle == NULL || Token == NULL || ((Flags & ~EFI_REDFISH_DISCOVER_VALIDATION) == 0)) {
+ DEBUG ((DEBUG_ERROR,"%a:Invalid parameters.\n", __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Validate target network interface.
+ //
+ if (EFI_ERROR (ValidateTargetNetworkInterface (TargetNetworkInterface, Flags))) {
+ return EFI_UNSUPPORTED;
+ }
+ if (TargetNetworkInterface != NULL) {
+ TargetNetworkInterfaceInternal = GetTargetNetworkInterfaceInternal (TargetNetworkInterface);
+ NumNetworkInterfaces = 1;
+ } else {
+ TargetNetworkInterfaceInternal = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ NumNetworkInterfaces = NumberOfNetworkInterface ();
+ if (NumNetworkInterfaces == 0) {
+ DEBUG ((DEBUG_ERROR,"%a:No network interface on platform.\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+ }
+ for (NetworkInterfacesIndex = 0; NetworkInterfacesIndex < NumNetworkInterfaces; NetworkInterfacesIndex ++) {
+ Status1 = EFI_SUCCESS;
+ Status2 = EFI_SUCCESS;
+ NewInstance = FALSE;
+ Instance = GetInstanceByOwner (ImageHandle, TargetNetworkInterfaceInternal, Flags & ~EFI_REDFISH_DISCOVER_VALIDATION); // Check if we can re-use previous instance.
+ if (Instance == NULL) {
+ DEBUG ((DEBUG_INFO,"%a:Create new EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.\n", __FUNCTION__));
+ Instance = (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE));
+ if (Instance == NULL) {
+ DEBUG ((DEBUG_ERROR,"%a:Memory allocation fail.\n", __FUNCTION__));
+ }
+ InitializeListHead (&Instance->Entry);
+ Instance->Owner = ImageHandle;
+ Instance->DiscoverFlags = Flags & ~EFI_REDFISH_DISCOVER_VALIDATION;
+ Instance->NetworkInterface = TargetNetworkInterfaceInternal;
+ //
+ // Get subnet information in case subnet information is not set because
+ // RedfishServiceGetNetworkInterfaces hasn't been called yet.
+ //
+ NetworkInterfaceGetSubnetInfo (TargetNetworkInterfaceInternal, ImageHandle);
+ NewInstance = TRUE;
+ }
+ if (TargetNetworkInterfaceInternal->StrMacAddr != NULL) {
+ DEBUG((DEBUG_INFO,"%a:Acquire Redfish service on network interface MAC address:%s.\n", __FUNCTION__, TargetNetworkInterfaceInternal->StrMacAddr));
+ } else {
+ DEBUG((DEBUG_INFO,"%a:WARNING: No MAC address on this network interface.\n", __FUNCTION__));
+ }
+
+ Instance->DiscoverToken = Token; // Always use the latest Token passed by caller.
+ if ((Flags & EFI_REDFISH_DISCOVER_HOST_INTERFACE) != 0) {
+ DEBUG ((DEBUG_INFO,"%a:Redfish HOST interface discovery.\n", __FUNCTION__));
+ Instance->HostIntfValidation = FALSE;
+ if ((Flags & EFI_REDFISH_DISCOVER_VALIDATION) != 0) {
+ Instance->HostIntfValidation = TRUE;
+ }
+ Status1 = DiscoverRedfishHostInterface (Instance); // Discover Redfish service through Redfish Host Interface.
+ }
+ if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) {
+ DEBUG ((DEBUG_ERROR,"%a:Redfish service discovery through SSDP is not supported\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ } else {
+ if (EFI_ERROR (Status1) && EFI_ERROR (Status2)) {
+ FreePool ((VOID *)Instance);
+ DEBUG ((DEBUG_ERROR,"%a:Something wrong on Redfish service discovery Status1=%x, Status2=%x.\n", __FUNCTION__, Status1, Status2));
+ } else {
+ if (NewInstance) {
+ InsertTailList(&mRedfishDiscoverList, &Instance->Entry);
+ }
+ }
+ }
+ if (TargetNetworkInterface == NULL) {
+ //
+ // Discover Redfish services on all of network interfaces.
+ //
+ TargetNetworkInterfaceInternal = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &TargetNetworkInterfaceInternal->Entry);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function aborts Redfish service discovery on the given network interface.
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] TargetNetworkInterface Target network interface to do the discovery.
+
+ @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
+ @retval Others Fail to abort Redfish service discovery.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishServiceAbortAcquire (
+ IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface OPTIONAL
+)
+{
+ // This function is used to abort Redfish service discovery through SSDP
+ // on the network interface. SSDP is optionally supprted by EFI_REDFISH_DISCOVER_PROTOCOL,
+ // we dont have implementation for SSDP now.
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function releases Redfish services found by RedfishServiceAcquire().
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] InstanceList The Redfish service to release.
+
+ @retval EFI_SUCCESS REST EX instances of discovered Redfish are released.
+ @retval Others Fail to remove the entry
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishServiceReleaseService (
+ IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
+ IN EFI_REDFISH_DISCOVERED_LIST *InstanceList
+ )
+{
+ UINTN NumService;
+ BOOLEAN AnyFailRelease;
+ EFI_REDFISH_DISCOVERED_INSTANCE *ThisRedfishInstance;
+ EFI_REDFISH_DISCOVERED_INTERNAL_LIST *DiscoveredRedfishInstance;
+
+ if (IsListEmpty (&mRedfishInstanceList)) {
+ DEBUG ((DEBUG_ERROR,"%a:No any discovered Redfish service.\n", __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+ AnyFailRelease = FALSE;
+ ThisRedfishInstance = InstanceList->RedfishInstances;
+ for (NumService = 0; NumService < InstanceList->NumberOfServiceFound; NumService ++) {
+ DiscoveredRedfishInstance = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetFirstNode(&mRedfishInstanceList);
+ do {
+ if (DiscoveredRedfishInstance->Instance == ThisRedfishInstance) {
+ RemoveEntryList (&DiscoveredRedfishInstance->NextInstance);
+ if (ThisRedfishInstance->Information.Location != NULL) {
+ FreePool (ThisRedfishInstance->Information.Location);
+ }
+ if (ThisRedfishInstance->Information.Uuid != NULL) {
+ FreePool (ThisRedfishInstance->Information.Uuid);
+ }
+ if (ThisRedfishInstance->Information.Os != NULL) {
+ FreePool (ThisRedfishInstance->Information.Os);
+ }
+ if (ThisRedfishInstance->Information.OsVersion != NULL) {
+ FreePool (ThisRedfishInstance->Information.OsVersion);
+ }
+ if (ThisRedfishInstance->Information.Product != NULL) {
+ FreePool (ThisRedfishInstance->Information.Product);
+ }
+ if (ThisRedfishInstance->Information.ProductVer != NULL) {
+ FreePool (ThisRedfishInstance->Information.ProductVer);
+ }
+ FreePool((VOID *)ThisRedfishInstance);
+ goto ReleaseNext;
+ }
+
+ if (IsNodeAtEnd(&mRedfishInstanceList, &DiscoveredRedfishInstance->NextInstance)) {
+ break;
+ }
+ DiscoveredRedfishInstance = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetNextNode(&mRedfishInstanceList, &DiscoveredRedfishInstance->NextInstance);
+ } while (TRUE);
+ AnyFailRelease = TRUE;
+ReleaseNext:;
+ //
+ // Release next discovered Redfish Service.
+ //
+ ThisRedfishInstance = (EFI_REDFISH_DISCOVERED_INSTANCE *)((UINT8 *)ThisRedfishInstance + sizeof (EFI_REDFISH_DISCOVERED_INSTANCE));
+ }
+ if (AnyFailRelease) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+EFI_REDFISH_DISCOVER_PROTOCOL mRedfishDiscover = {
+ RedfishServiceGetNetworkInterface,
+ RedfishServiceAcquireService,
+ RedfishServiceAbortAcquire,
+ RedfishServiceReleaseService
+};
+
+/**
+ This function create an EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL for the
+ given network interface.
+
+
+ @param[in] ControllerHandle MAC address of this network interface.
+ @param[in] NetworkProtocolType Network protocol type.
+ @param[out] IsNewInstance BOOLEAN means new instance or not.
+ @param[out] NetworkInterface Pointer to to EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL.
+
+ @retval EFI_STATUS
+**/
+EFI_STATUS
+CreateRedfishDiscoverNetworkInterface (
+ IN EFI_HANDLE ControllerHandle,
+ IN UINT32 NetworkProtocolType,
+ OUT BOOLEAN *IsNewInstance,
+ OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL **NetworkInterface
+ )
+{
+ EFI_MAC_ADDRESS MacAddress;
+ UINTN HwAddressSize;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NewNetworkInterface;
+
+ NetLibGetMacAddress (ControllerHandle, &MacAddress, &HwAddressSize);
+ NewNetworkInterface = NULL;
+ *IsNewInstance = TRUE;
+ if (!IsListEmpty ((const LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterface)) {
+ //
+ // Check if this instance already exist.
+ //
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ if (ThisNetworkInterface != NULL) {
+ while (TRUE) {
+ if ((CompareMem ((CONST VOID *)&ThisNetworkInterface->MacAddress.Addr, (CONST VOID *)&MacAddress.Addr, HwAddressSize) == 0) &&
+ (ThisNetworkInterface->NetworkProtocolType == NetworkProtocolType)){
+ NewNetworkInterface = ThisNetworkInterface;
+ *IsNewInstance = FALSE;
+ break;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ NewNetworkInterface = NULL;
+ break;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ };
+ }
+ }
+ if (NewNetworkInterface == NULL) {
+ //
+ // Create a new instance.
+ //
+ NewNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL));
+ if (NewNetworkInterface == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ NewNetworkInterface->HwAddressSize = HwAddressSize;
+ CopyMem (&NewNetworkInterface->MacAddress.Addr, &MacAddress.Addr, NewNetworkInterface->HwAddressSize);
+ NetLibGetMacString (ControllerHandle, NULL, &NewNetworkInterface->StrMacAddr);
+ NewNetworkInterface->VlanId = NetLibGetVlanId (ControllerHandle);
+ }
+ *NetworkInterface = NewNetworkInterface;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function destory network interface
+
+
+ @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance.
+
+ @retval EFI_STATUS
+**/
+EFI_STATUS
+DestroyRedfishNetwrokInterface (
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->UninstallProtocolInterface(
+ ThisNetworkInterface->OpenDriverControllerHandle,
+ gRequiredProtocol [ThisNetworkInterface->NetworkProtocolType].DiscoveredProtocolGuid,
+ &ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId
+ );
+ RemoveEntryList (&ThisNetworkInterface->Entry);
+ mNumNetworkInterface --;
+ FreePool (ThisNetworkInterface);
+ return Status;
+}
+
+/**
+ Tests to see if the required protocols are provided on the given
+ controller handle.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @retval EFI_SUCCESS One of required protocol is found.
+ @retval EFI_UNSUPPORTED None of required protocol is found.
+**/
+EFI_STATUS
+TestForRequiredProtocols (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle
+ )
+{
+ UINT32 Id;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ for (Index = 0; Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index ++) {
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ gRequiredProtocol [Index].DiscoveredProtocolGuid,
+ (VOID **) &Id,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: %s is found on this controller handle.\n", __FUNCTION__, gRequiredProtocol [Index].ProtocolName));
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Build up network interface and create corresponding service through the given
+ controller handle.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @retval EFI_SUCCESS One of required protocol is found.
+ @retval EFI_UNSUPPORTED None of required protocol is found.
+ @retval EFI_UNSUPPORTED Failed to build up network interface.
+**/
+EFI_STATUS
+BuildupNetworkInterface (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle
+ )
+{
+ UINT32 Id;
+ UINT32 Index;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NetworkInterface;
+ BOOLEAN IsNew;
+ EFI_STATUS Status;
+ VOID *TempInterface;
+ VOID **Interface;
+ UINT32 *ProtocolDiscoverIdPtr;
+ EFI_HANDLE OpenDriverAgentHandle;
+ EFI_HANDLE OpenDriverControllerHandle;
+ EFI_HANDLE *HandleOfProtocolInterfacePtr;
+ EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *RestExInstance;
+ EFI_TPL OldTpl;
+ BOOLEAN NewNetworkInterfaceInstalled;
+
+ NewNetworkInterfaceInstalled = FALSE;
+ Index = 0;
+ do {
+ Status = gBS->OpenProtocol ( // Already in list?
+ ControllerHandle,
+ gRequiredProtocol [Index].DiscoveredProtocolGuid,
+ (VOID **) &Id,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Index ++;
+ if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
+ break;
+ }
+ continue;
+ }
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid,
+ &TempInterface,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ Index ++;
+ if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
+ break;
+ }
+ continue;
+ }
+ if (gRequiredProtocol [Index].ProtocolType != ProtocolTypeRestEx) {
+ OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL);
+ Status = CreateRedfishDiscoverNetworkInterface(ControllerHandle, gRequiredProtocol [Index].ProtocolType, &IsNew, &NetworkInterface);
+ if (EFI_ERROR (Status)) {
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+ }
+ NetworkInterface->NetworkProtocolType = gRequiredProtocol [Index].ProtocolType;
+ NetworkInterface->OpenDriverAgentHandle = This->DriverBindingHandle;
+ NetworkInterface->OpenDriverControllerHandle = ControllerHandle;
+ NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolGuid = \
+ *gRequiredProtocol [Index].RequiredProtocolGuid;
+ NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolServiceGuid = \
+ *gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid;
+ ProtocolDiscoverIdPtr = &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId;
+ OpenDriverAgentHandle = NetworkInterface->OpenDriverAgentHandle;
+ OpenDriverControllerHandle = NetworkInterface->OpenDriverControllerHandle;
+ HandleOfProtocolInterfacePtr = &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle;
+ Interface = &NetworkInterface->NetworkInterfaceProtocolInfo.NetworkProtocolInterface;
+ NewNetworkInterfaceInstalled = TRUE;
+ if (IsNew) {
+ InsertTailList (&mEfiRedfishDiscoverNetworkInterface, &NetworkInterface->Entry);
+ mNumNetworkInterface ++;
+ }
+ gBS->RestoreTPL (OldTpl);
+ } else {
+ // Record REST_EX instance. REST_EX is created when clinet asks for Redfish service discovery.
+ // Redfish Service Discover protocol will match REST EX to the corresponding EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
+ // when discovery.
+
+ RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL));
+ if (RestExInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ RestExInstance->OpenDriverAgentHandle = This->DriverBindingHandle;
+ RestExInstance->OpenDriverControllerHandle = ControllerHandle;
+ RestExInstance->RestExControllerHandle = ControllerHandle;
+ InitializeListHead (&RestExInstance->Entry);
+ InsertTailList (&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry);
+ mNumRestExInstance ++;
+ ProtocolDiscoverIdPtr = &RestExInstance->RestExId;
+ OpenDriverAgentHandle = RestExInstance->OpenDriverAgentHandle;
+ OpenDriverControllerHandle = RestExInstance->OpenDriverControllerHandle;
+ HandleOfProtocolInterfacePtr = &RestExInstance->RestExChildHandle;
+ Interface = (VOID **)&RestExInstance->RestExProtocolInterface;
+ }
+ Status = gBS->InstallProtocolInterface (
+ &ControllerHandle,
+ gRequiredProtocol [Index].DiscoveredProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ ProtocolDiscoverIdPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Index ++;
+ if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
+ break;
+ }
+ continue;
+ }
+ //
+ // Create service binding child and open it BY_DRIVER.
+ //
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ This->ImageHandle,
+ gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid,
+ HandleOfProtocolInterfacePtr
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ *HandleOfProtocolInterfacePtr,
+ gRequiredProtocol [Index].RequiredProtocolGuid,
+ Interface,
+ OpenDriverAgentHandle,
+ OpenDriverControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR (Status)) {
+ if (EfiRedfishDiscoverProtocolHandle == NULL &&
+ (gRequiredProtocol [Index].ProtocolType == ProtocolTypeRestEx) &&
+ !IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)
+ ) {
+ // Install the fisrt Redfish Discover Protocol when EFI REST EX protcol is discovered.
+ // This ensures EFI REST EX is ready while EFI_REDFISH_DISCOVER_PROTOCOL consumer acquires
+ // Redfish serivce over network interface.
+
+ Status = gBS->InstallProtocolInterface (
+ &EfiRedfishDiscoverProtocolHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *)&mRedfishDiscover
+ );
+ } else if (EfiRedfishDiscoverProtocolHandle != NULL && NewNetworkInterfaceInstalled) {
+ Status = gBS->ReinstallProtocolInterface (
+ EfiRedfishDiscoverProtocolHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ (VOID *)&mRedfishDiscover,
+ (VOID *)&mRedfishDiscover
+ );
+ NewNetworkInterfaceInstalled = FALSE;
+ }
+ }
+ return Status;
+ } else {
+ Index ++;
+ if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
+ break;
+ }
+ continue;
+ }
+ } while (Index < (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL)));
+ return EFI_UNSUPPORTED;
+}
+/**
+ Close the protocol opened for Redfish discovery. This function also destories
+ the network services.
+
+ @param[in] ThisBindingProtocol A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] ThisRequiredProtocol Pointer to the instance of REDFISH_DISCOVER_REQUIRED_PROTOCOL.
+ @param[in] DriverAgentHandle Driver agent handle which used to open protocol earlier.
+ @param[in] DriverControllerHandle Driver controller handle which used to open protocol earlier.
+
+ @retval EFI_SUCCESS Prorocol is closed successfully.
+ @retval Others Prorocol is closed unsuccessfully.
+
+**/
+EFI_STATUS
+CloseProtocolService (
+ IN EFI_DRIVER_BINDING_PROTOCOL *ThisBindingProtocol,
+ IN EFI_HANDLE ControllerHandle,
+ IN REDFISH_DISCOVER_REQUIRED_PROTOCOL *ThisRequiredProtocol,
+ IN EFI_HANDLE DriverAgentHandle,
+ IN EFI_HANDLE DriverControllerHandle
+)
+{
+ EFI_STATUS Status;
+
+ Status = gBS->CloseProtocol (
+ ControllerHandle,
+ ThisRequiredProtocol->RequiredProtocolGuid,
+ DriverAgentHandle,
+ DriverControllerHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ NetLibDestroyServiceChild(
+ ControllerHandle,
+ ThisBindingProtocol->ImageHandle,
+ ThisRequiredProtocol->RequiredServiceBindingProtocolGuid,
+ ControllerHandle
+ );
+ }
+ return Status;
+}
+/**
+ Stop the services on network interface.
+
+ @param[in] ThisBindingProtocol A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @retval EFI_SUCCESS One of required protocol is found.
+ @retval Others Faile to stop the services on network interface.
+**/
+EFI_STATUS
+StopServiceOnNetworkInterface (
+ IN EFI_DRIVER_BINDING_PROTOCOL *ThisBindingProtocol,
+ IN EFI_HANDLE ControllerHandle
+ )
+{
+ UINT32 Index;
+ EFI_STATUS Status;
+ VOID *Interface;
+ EFI_TPL OldTpl;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
+ EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *RestExInstance;
+
+ for (Index = 0; Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index ++) {
+ Status = gBS->HandleProtocol (
+ ControllerHandle,
+ gRequiredProtocol [Index].RequiredProtocolGuid,
+ (VOID **)&Interface
+ );
+ if (!EFI_ERROR (Status)) {
+ if (gRequiredProtocol [Index].ProtocolType != ProtocolTypeRestEx) {
+ if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {
+ return EFI_NOT_FOUND;
+ }
+ OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL);
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ if (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle == ControllerHandle) {
+
+ Status = CloseProtocolService ( // Close protocol and destroy service.
+ ThisBindingProtocol,
+ ControllerHandle,
+ &gRequiredProtocol [Index],
+ ThisNetworkInterface->OpenDriverAgentHandle,
+ ThisNetworkInterface->OpenDriverControllerHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = DestroyRedfishNetwrokInterface (ThisNetworkInterface);
+ }
+ gBS->RestoreTPL (OldTpl);
+ // Reinstall Redfish Discover protocol to notify network
+ // interface change.
+
+ Status = gBS->ReinstallProtocolInterface (
+ EfiRedfishDiscoverProtocolHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ (VOID *)&mRedfishDiscover,
+ (VOID *)&mRedfishDiscover
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: Reinstall gEfiRedfishDiscoverProtocolGuid fail.", __FUNCTION__));
+ }
+ return Status;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ break;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ };
+ gBS->RestoreTPL (OldTpl);
+ } else {
+ if (IsListEmpty (&mEfiRedfishDiscoverRestExInstance)) {
+ return EFI_NOT_FOUND;
+ }
+ OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL);
+ RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverRestExInstance);
+ while (TRUE) {
+ if (RestExInstance->RestExChildHandle == ControllerHandle) {
+ Status = CloseProtocolService ( // Close REST_EX protocol.
+ ThisBindingProtocol,
+ ControllerHandle,
+ &gRequiredProtocol [Index],
+ RestExInstance->OpenDriverAgentHandle,
+ RestExInstance->OpenDriverControllerHandle
+ );
+ RemoveEntryList (&RestExInstance->Entry);
+ FreePool ((VOID *)RestExInstance);
+ mNumRestExInstance --;
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry)) {
+ break;
+ }
+ RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry);
+ };
+ gBS->RestoreTPL (OldTpl);
+ }
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ return TestForRequiredProtocols (This, ControllerHandle);
+}
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ return BuildupNetworkInterface (This, ControllerHandle);
+}
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ return StopServiceOnNetworkInterface (This, ControllerHandle);
+}
+
+EFI_DRIVER_BINDING_PROTOCOL gRedfishDiscoverDriverBinding = {
+ RedfishDiscoverDriverBindingSupported,
+ RedfishDiscoverDriverBindingStart,
+ RedfishDiscoverDriverBindingStop,
+ REDFISH_DISCOVER_VERSION,
+ NULL,
+ NULL
+};
+
+/**
+ This is the declaration of an EFI image entry point.
+
+ @param ImageHandle The firmware allocated handle for the UEFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ InitializeListHead (&mRedfishDiscoverList);
+ InitializeListHead (&mRedfishInstanceList);
+ InitializeListHead (&mEfiRedfishDiscoverNetworkInterface);
+ InitializeListHead (&mEfiRedfishDiscoverRestExInstance);
+ //
+ // Install binding protoocl to obtain UDP and REST EX protocol.
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gRedfishDiscoverDriverBinding,
+ ImageHandle,
+ &gRedfishDiscoverComponentName,
+ &gRedfishDiscoverComponentName2
+ );
+ return Status;
+}
+
+/**
+ This is the unload handle for Redfish discover module.
+
+ Disconnect the driver specified by ImageHandle from all the devices in the handle database.
+ Uninstall all the protocols installed in the driver entry point.
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
+
+ Status = EFI_SUCCESS;
+ // Destroy all network interfaces found by EFI Redfish Discover driver and
+ // stop services created for Redfish Discover.
+
+ while (!IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ StopServiceOnNetworkInterface (&gRedfishDiscoverDriverBinding, ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle);
+ };
+ // Disconnect EFI Redfish discover driver controller to notify the
+ // clinet which uses .EFI Redfish discover protocol.
+
+ if (EfiRedfishDiscoverProtocolHandle != NULL) {
+ //
+ // Notify user EFI_REDFISH_DISCOVER_PROTOCOL is unloaded.
+ //
+ gBS->DisconnectController (EfiRedfishDiscoverProtocolHandle, NULL, NULL);
+ Status = gBS->UninstallProtocolInterface(
+ EfiRedfishDiscoverProtocolHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ (VOID *)&mRedfishDiscover
+ );
+ }
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf
new file mode 100644
index 00000000..1f303fcb
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf
@@ -0,0 +1,55 @@
+## @file
+# Implementation of EFI_REDFISH_DISCOVER_PROTOCOL interfaces.
+#
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = RedfishDiscoverDxe
+ FILE_GUID = 28A76FE5-43D7-48A3-9714-C1B7BDD6DFB6
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishDiscoverEntryPoint
+ UNLOAD_IMAGE = RedfishDiscoverUnload
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[Sources]
+ ComponentName.c
+ RedfishDiscoverDxe.c
+ RedfishSmbiosHostInterface.c
+ RedfishDiscoverInternal.h
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ PrintLib
+ RestExLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEfiRestExServiceBindingProtocolGuid ## Consuming
+ gEfiRestExProtocolGuid ## Consuming
+ gEfiTcp4ServiceBindingProtocolGuid ## Consuming
+ gEfiTcp4ProtocolGuid ## Consuming
+ gEfiTcp6ServiceBindingProtocolGuid ## Consuming
+ gEfiTcp6ProtocolGuid ## Consuming
+ gEfiRedfishDiscoverProtocolGuid ## Prodcuing
+ gEfiSmbiosProtocolGuid ## Consuming
+ gEfiDriverBindingProtocolGuid ## Consuming
+
+[Pcd]
+ gEfiRedfishPkgTokenSpaceGuid.PcdRedfishDiscoverAccessModeInBand ## CONSUMES
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h
new file mode 100644
index 00000000..5407ee87
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h
@@ -0,0 +1,234 @@
+/** @file
+ This file defines the EFI Redfish Discover Protocol interface.
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_DISCOVER_INTERNAL_H_
+#define EFI_REDFISH_DISCOVER_INTERNAL_H_
+
+#include <Uefi.h>
+
+#include <Protocol/ComponentName.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/RedfishDiscover.h>
+#include <Protocol/Smbios.h>
+#include <Protocol/Tcp4.h>
+#include <Protocol/Tcp6.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/PrintLib.h>
+#include <Library/RestExLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+#include <IndustryStandard/RedfishHostInterface.h>
+
+#define REDFISH_DISCOVER_VERSION 0x00010000
+#define EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL TPL_NOTIFY
+
+//
+//GUID definitions
+//
+
+#define EFI_REDFISH_DISCOVER_TCP4_INSTANCE_GUID \
+ { \
+ 0xfbab97a4, 0x4c6a, 0xf8e8, { 0xf2, 0x25, 0x42, 0x8a, 0x80, 0x3f, 0xb6, 0xaa } \
+ }
+
+#define EFI_REDFISH_DISCOVER_TCP6_INSTANCE_GUID \
+ { \
+ 0xbe513b6d, 0x41c1, 0x96Ed, { 0x8d, 0xaf, 0x3e, 0x89, 0xc5, 0xf5, 0x02, 0x25 } \
+ }
+
+#define EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_GUID \
+ { \
+ 0xc44a6076, 0xd42a, 0x4d54, { 0x85, 0x6d, 0x98, 0x8a, 0x85, 0x8f, 0xa1, 0x11 } \
+ }
+
+extern EFI_COMPONENT_NAME_PROTOCOL gRedfishDiscoverComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gRedfishDiscoverComponentName2;
+extern EFI_UNICODE_STRING_TABLE *gRedfishDiscoverControllerNameTable;
+
+//
+// Enumeration of network protocols
+// required for the Redfish service discovery.
+//
+typedef enum {
+ ProtocolTypeTcp4 = 0, ///< Network protocol TCPv4.
+ ProtocolTypeTcp6, ///< Network protocol TCCv6.
+ ProtocolTypeRestEx, ///< REST EX over network protocol.
+ MaxProtocolType
+} NETWORK_INTERFACE_PROTOCOL_TYPE;
+
+//
+// Network protocol information installed on
+// the network interface.
+//
+typedef struct {
+ EFI_GUID ProtocolGuid; ///< Network protocol GUID.
+ EFI_GUID ProtocolServiceGuid; ///< Network protocol service GUID.
+ UINT32 ProtocolDiscoverId; ///< The identifier installed on network protocol handle.
+ EFI_HANDLE ProtocolControllerHandle; ///< The controller handle on network protocol.
+ VOID *NetworkProtocolInterface; ///< The protocol interface of network protocol.
+} REDFISH_DISCOVER_NETWORK_INTERFACE_PROTOCOL;
+
+//
+// Internal structure used to maintain network
+// interface properties.
+//
+typedef struct {
+ LIST_ENTRY Entry; ///< Link list entry.
+ EFI_HANDLE OpenDriverAgentHandle; ///< The agent to open network protocol.
+ EFI_HANDLE OpenDriverControllerHandle; ///< The controller handle to open network protocol.
+ UINTN HwAddressSize; ///< The size of network interface hardware address.
+ EFI_MAC_ADDRESS MacAddress; ///< MAC address of network interface.
+ CHAR16 *StrMacAddr; ///< String to MAC address of network interface.
+ BOOLEAN GotSubnetInfo; ///< Indicates sub net information is retrieved.
+ EFI_IP_ADDRESS SubnetAddr; ///< Subnet ID.
+ EFI_IP_ADDRESS SubnetMask; ///< Subnet mask (IPv4 only)
+ UINT8 SubnetPrefixLength; ///< Subnet prefix.
+ UINT16 VlanId; ///< VLAN ID
+ UINT32 SubnetAddrInfoIPv6Number; ///< IPv6 address info number.
+ EFI_IP6_ADDRESS_INFO *SubnetAddrInfoIPv6; ///< IPv6 address info.
+ //
+ // Network interface protocol and REST EX infor.
+ //
+ UINT32 NetworkProtocolType; ///< Network protocol type. Refer to
+ ///< NETWORK_INTERFACE_PROTOCOL_TYPE.
+ REDFISH_DISCOVER_NETWORK_INTERFACE_PROTOCOL NetworkInterfaceProtocolInfo; ///< Network interface protocol information.
+ EFI_HANDLE RestExHandle; ///< REST EX handle associated with this network interface.
+} EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL;
+
+//
+// Internal structure used to maintain REST EX properties.
+//
+typedef struct {
+ LIST_ENTRY Entry; ///< Link list entry.
+ EFI_HANDLE OpenDriverAgentHandle; ///< The agent to open network protocol.
+ EFI_HANDLE OpenDriverControllerHandle; ///< The controller handle to open network protocol.
+ EFI_HANDLE RestExChildHandle; ///< The child handle created throught REST EX Service Protocol.
+ EFI_HANDLE RestExControllerHandle; ///< The controller handle which provide REST EX protocol.
+ EFI_REST_EX_PROTOCOL *RestExProtocolInterface; ///< Pointer to EFI_REST_EX_PROTOCOL.
+ UINT32 RestExId; ///< The identifier installed on REST EX controller handle.
+} EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL;
+
+/**
+ This function to get subnet information.
+
+ @param[in] ImageHandle EFI handle with this image.
+ @param[in] Instance Instance of Network interface.
+ @retval EFI_STATUS Get subnet information successfully.
+ @retval Otherwise Fail to get subnet information.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REDFISH_DISCOVER_GET_SUBNET_INFO)(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
+);
+
+//
+// The require network protocol matrix.
+//
+typedef struct {
+ UINT32 ProtocolType; ///< Network protocol type,
+ ///< Refer to NETWORK_INTERFACE_PROTOCOL_TYPE.
+ CHAR16 *ProtocolName; ///< Protocol name.
+ EFI_GUID *RequiredProtocolGuid; ///< Network protocol interface GUID.
+ EFI_GUID *RequiredServiceBindingProtocolGuid; ///< Network protocol service GUID.
+ EFI_GUID *DiscoveredProtocolGuid; ///< Protocol interface GUID use to install identifier.
+ EFI_REDFISH_DISCOVER_GET_SUBNET_INFO GetSubnetInfo; ///< Function of getting subnet information.
+} REDFISH_DISCOVER_REQUIRED_PROTOCOL;
+
+//
+// Link list of Redfish discover instance.
+//
+typedef struct {
+ LIST_ENTRY NextInstance; ///< Next list.
+ EFI_REDFISH_DISCOVERED_INSTANCE *Instance; ///< Pointer to EFI_REDFISH_DISCOVERED_INSTANCE.
+} EFI_REDFISH_DISCOVERED_INTERNAL_LIST;
+
+//
+// Internal structure of Redfish discover instance.
+//
+typedef struct {
+ LIST_ENTRY Entry; ///< Link list entry.
+ EFI_HANDLE Owner; ///< The owner owns this Redfish service discovery.
+ ///< It's the EFI image handle of driver uses
+ ///< EFI Redfish Discover Protocol.
+ EFI_REDFISH_DISCOVER_FLAG DiscoverFlags; ///< EFI_REDFISH_DISCOVER_FLAG
+ EFI_REDFISH_DISCOVERED_TOKEN *DiscoverToken; ///< Token used to signal when Redfish service is discovered.
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NetworkInterface; ///< EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
+ ///< instance used to discover Redfish service.
+ //
+ // Below for Host insterface discovery.
+ //
+ BOOLEAN HostIntfValidation; ///< Indicates whether to validate Redfish Host interface.
+ EFI_IP_ADDRESS TargetIpAddress; ///< Target IP address reported in Redfish Host interface.
+} EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE;
+
+/**
+ The function adds a new foudn Redfish service to internal list and
+ notify clinet.
+
+ It simply frees the packet.
+
+ @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
+ @param[in] RedfishVersion Redfish version.
+ @param[in] RedfishLocation Redfish location.
+ @param[in] Uuid Service UUID string.
+ @param[in] Os OS string.
+ @param[in] OsVer OS version string.
+ @param[in] Product Product string.
+ @param[in] ProductVer Product verison string.
+ @param[in] UseHttps Redfish service requires secured connection.
+ @retval EFI_SUCCESS Redfish service is added to list successfully.
+
+**/
+EFI_STATUS
+AddAndSignalNewRedfishService (
+ IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance,
+ IN UINTN *RedfishVersion OPTIONAL,
+ IN CHAR8 *RedfishLocation OPTIONAL,
+ IN CHAR8 *Uuid OPTIONAL,
+ IN CHAR8 *Os OPTIONAL,
+ IN CHAR8 *OsVer OPTIONAL,
+ IN CHAR8 *Product OPTIONAL,
+ IN CHAR8 *ProductVer OPTIONAL,
+ IN BOOLEAN UseHttps
+ );
+
+/**
+ The function gets information reported in Redfish Host Interface.
+
+ It simply frees the packet.
+
+ @param[in] Smbios SMBIOS protocol.
+ @param[out] DeviceDescriptor Pointer to REDFISH_INTERFACE_DATA.
+ @param[out] ProtocolData Pointer to REDFISH_OVER_IP_PROTOCOL_DATA.
+
+ @retval EFI_SUCCESS Get host interface succesfully.
+ @retval Otherwise Fail to tet host interface.
+
+**/
+EFI_STATUS
+RedfishGetHostInterfaceProtocolData (
+ IN EFI_SMBIOS_PROTOCOL *Smbios,
+ OUT REDFISH_INTERFACE_DATA **DeviceDescriptor,
+ OUT REDFISH_OVER_IP_PROTOCOL_DATA **ProtocolData
+ );
+
+extern EFI_GUID gRedfishDiscoverTcp4Instance;
+extern EFI_GUID gRedfishDiscoverTcp6Instance;
+extern EFI_GUID gRedfishDiscoverRestEXInstance;
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c
new file mode 100644
index 00000000..78d1447a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c
@@ -0,0 +1,118 @@
+/** @file
+ RedfishSmbiosHostInterface.c
+
+ Discover Redfish SMBIOS Host Interface.
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishDiscoverInternal.h"
+
+SMBIOS_TABLE_TYPE42 *mType42Record;
+
+/**
+ The function gets information reported in Redfish Host Interface.
+
+ It simply frees the packet.
+
+ @param[in] Smbios SMBIOS protocol.
+ @param[out] DeviceDescriptor Pointer to REDFISH_INTERFACE_DATA.
+ @param[out] ProtocolData Pointer to REDFISH_OVER_IP_PROTOCOL_DATA.
+
+ @retval EFI_SUCCESS Get host interface succesfully.
+ @retval Otherwise Fail to tet host interface.
+
+**/
+EFI_STATUS
+RedfishGetHostInterfaceProtocolData (
+ IN EFI_SMBIOS_PROTOCOL *Smbios,
+ OUT REDFISH_INTERFACE_DATA **DeviceDescriptor,
+ OUT REDFISH_OVER_IP_PROTOCOL_DATA **ProtocolData
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ EFI_SMBIOS_TABLE_HEADER *Record;
+ UINT16 Offset;
+ UINT8 *RecordTmp;
+ UINT8 ProtocolLength;
+ UINT8 SpecificDataLen;
+
+ if ((Smbios == NULL) || (ProtocolData == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
+ while (!EFI_ERROR (Status) && SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED) {
+ if (Record->Type == SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE) {
+ //
+ // Check Interface Type, should be Network Host Interface = 40h
+ //
+ mType42Record = (SMBIOS_TABLE_TYPE42 *) Record;
+ if (mType42Record->InterfaceType == MCHostInterfaceTypeNetworkHostInterface) {
+ ASSERT (Record->Length >= 9);
+ Offset = 5;
+ RecordTmp = (UINT8 *) Record + Offset;
+ //
+ // Get interface specific data length.
+ //
+ SpecificDataLen = *RecordTmp;
+ Offset += 1;
+ RecordTmp = (UINT8 *) Record + Offset;
+
+ //
+ // Check Device Type, only PCI/PCIe Network Interface v2 is supported now.
+ //
+ if (*RecordTmp == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) {
+ ASSERT (SpecificDataLen == sizeof (PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2) + 1);
+ *DeviceDescriptor = (REDFISH_INTERFACE_DATA *)RecordTmp;
+ Offset = Offset + SpecificDataLen;
+ RecordTmp = (UINT8 *) Record + Offset;
+ //
+ // Check Protocol count. if > 1, only use the first protocol.
+ //
+ ASSERT (*RecordTmp == 1);
+ Offset += 1;
+ RecordTmp = (UINT8 *) Record + Offset;
+ //
+ // Check protocol identifier.
+ //
+ if (*RecordTmp == MCHostInterfaceProtocolTypeRedfishOverIP) {
+ Offset += 1;
+ RecordTmp = (UINT8 *) Record + Offset;
+ ProtocolLength = *RecordTmp;
+
+ Offset += 1;
+ RecordTmp = (UINT8 *) Record + Offset;
+
+ //
+ // This SMBIOS record is invalid, if the length of protocol specific data for
+ // Redfish Over IP protocol is wrong.
+ //
+ if ((*(RecordTmp + 90) + sizeof (REDFISH_OVER_IP_PROTOCOL_DATA) - 1) != ProtocolLength) {
+ return EFI_SECURITY_VIOLATION;
+ }
+
+ Offset += ProtocolLength;
+ //
+ // This SMBIOS record is invalid, if the length is smaller than the offset.
+ //
+ if (Offset > mType42Record->Hdr.Length) {
+ return EFI_SECURITY_VIOLATION;
+ }
+ *ProtocolData = (REDFISH_OVER_IP_PROTOCOL_DATA *)RecordTmp;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+ Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
+ }
+
+ *ProtocolData = NULL;
+ return EFI_NOT_FOUND;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.c
new file mode 100644
index 00000000..d4ba24e4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.c
@@ -0,0 +1,243 @@
+/** @file
+ RedfishHostInterfaceDxe builds up SMBIOS Type 42h host interface
+ record for Redfish service host interface using EFI MBIOS Protocol.
+ RedfishHostInterfacePlatformLib is the platform-level library which
+ provides the content of Redfish host interface type 42h record.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/RedfishHostInterfaceLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+/**
+ Create SMBIOS type 42 record for Redfish host interface.
+
+ @retval EFI_SUCESS SMBIOS type 42 record is created.
+ @retval Others Fail to create SMBIOS 42 record.
+
+**/
+EFI_STATUS
+RedfishCreateSmbiosTable42 (
+ VOID
+ )
+{
+ REDFISH_INTERFACE_DATA *DeviceDescriptor;
+ UINT8 DeviceDataLength;
+ UINT8 DeviceType;
+ EFI_STATUS Status;
+ MC_HOST_INTERFACE_PROTOCOL_RECORD *ProtocolRecord;
+ VOID *ProtocolRecords;
+ VOID *NewProtocolRecords;
+ UINT8 ProtocolCount;
+ UINT8 CurrentProtocolsDataLength;
+ UINT8 NewProtocolsDataLength;
+ UINT8 ProtocolDataSize;
+ SMBIOS_TABLE_TYPE42 *Type42Record;
+ EFI_SMBIOS_PROTOCOL *Smbios;
+ EFI_SMBIOS_HANDLE MemArrayMappedAddrSmbiosHandle;
+
+ //
+ // Get platform Redfish host interface device type descriptor data.
+ //
+ Status = RedfishPlatformHostInterfaceDeviceDescriptor (&DeviceType, &DeviceDescriptor);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_ERROR, "%a: No Redfish host interface descriptor is provided on this platform.", __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+ DEBUG((DEBUG_ERROR, "%a: Fail to get device descriptor, %r.", __FUNCTION__, Status));
+ return Status;
+ }
+ if (DeviceType != REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2 &&
+ DeviceType != REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2
+ ) {
+ DEBUG ((DEBUG_ERROR, "%a: Only support either protocol type 04h or 05h as Redfish host interface.", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+ if (DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) {
+ DeviceDataLength = DeviceDescriptor->DeviceDescriptor.PciPcieDeviceV2.Length;
+ } else {
+ DeviceDataLength = DeviceDescriptor->DeviceDescriptor.UsbDeviceV2.Length;
+ }
+ //
+ // Loop to get platform Redfish host interface protocol type data.
+ //
+ ProtocolRecord = NULL;
+ ProtocolRecords = NULL;
+ NewProtocolRecords = NULL;
+ Type42Record = NULL;
+ ProtocolCount = 0;
+ CurrentProtocolsDataLength = 0;
+ NewProtocolsDataLength = 0;
+ while (TRUE) {
+ Status = RedfishPlatformHostInterfaceProtocolData (&ProtocolRecord, ProtocolCount);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Fail to get Redfish host interafce protocol type data.", __FUNCTION__));
+ if (ProtocolRecords != NULL) {
+ FreePool (ProtocolRecords);
+ }
+ if (ProtocolRecord != NULL) {
+ FreePool (ProtocolRecord);
+ }
+ return Status;
+ }
+ ProtocolDataSize = sizeof (MC_HOST_INTERFACE_PROTOCOL_RECORD) - sizeof(ProtocolRecord->ProtocolTypeData) + ProtocolRecord->ProtocolTypeDataLen;
+ NewProtocolsDataLength += ProtocolDataSize;
+ if (ProtocolRecords == NULL) {
+ ProtocolRecords = AllocateZeroPool (NewProtocolsDataLength);
+ if (ProtocolRecords == NULL) {
+ FreePool (ProtocolRecord);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem ((VOID *)ProtocolRecords, (VOID *)ProtocolRecord, ProtocolDataSize);
+ NewProtocolRecords = ProtocolRecords;
+ } else {
+ NewProtocolRecords = ReallocatePool(CurrentProtocolsDataLength, NewProtocolsDataLength, (VOID *)ProtocolRecords);
+ if (NewProtocolRecords == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for Redfish host interface protocol data."));
+ FreePool (ProtocolRecords);
+ FreePool (ProtocolRecord);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (
+ (VOID *)((UINT8 *)NewProtocolRecords + CurrentProtocolsDataLength),
+ (VOID *)ProtocolRecord,
+ ProtocolDataSize
+ );
+ }
+ FreePool (ProtocolRecord);
+ CurrentProtocolsDataLength = NewProtocolsDataLength;
+ ProtocolCount ++;
+ };
+ if (ProtocolCount == 0) {
+ goto ON_EXIT;
+ }
+ //
+ // Construct SMBIOS Type 42h for Redfish host inteface.
+ //
+ // SMBIOS type 42 Record for Redfish Interface
+ // 00h Type BYTE 42 Management Controller Host Interface structure indicator
+ // 01h Length BYTE Varies Length of the structure, a minimum of 09h
+ // 02h Handle WORD Varies
+ // 04h Interface Type BYTE Varies Management Controller Interface Type.
+ // 05h Interface Specific Data Length (n)
+ // 06h Interface Specific data
+ // 06h+n number of protocols defined for the host interface (typically 1)
+ // 07h+n Include a Protocol Record for each protocol supported.
+ //
+ Type42Record = (SMBIOS_TABLE_TYPE42 *) AllocateZeroPool (
+ sizeof (SMBIOS_TABLE_TYPE42) - 4
+ + DeviceDataLength
+ + 1 /// For Protocol Record Count
+ + CurrentProtocolsDataLength
+ + 2 /// Double NULL terminator/
+ );
+ if (Type42Record == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ Type42Record->Hdr.Type = EFI_SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE;
+ Type42Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE42) - 4
+ + DeviceDataLength
+ + 1
+ + CurrentProtocolsDataLength;
+ Type42Record->Hdr.Handle = 0;
+ Type42Record->InterfaceType = MCHostInterfaceTypeNetworkHostInterface; // Network Host Interface
+
+ //
+ // Fill in InterfaceTypeSpecificDataLength field
+ //
+ Type42Record->InterfaceTypeSpecificDataLength = DeviceDataLength;
+
+ //
+ // Fill in InterfaceTypeSpecificData field
+ //
+ CopyMem (Type42Record->InterfaceTypeSpecificData, DeviceDescriptor, DeviceDataLength);
+ FreePool (DeviceDescriptor);
+ DeviceDescriptor = NULL;
+
+ //
+ // Fill in InterfaceTypeSpecificData Protocol Count field
+ //
+ *(Type42Record->InterfaceTypeSpecificData + DeviceDataLength) = ProtocolCount;
+
+ //
+ // Fill in Redfish Protocol Data
+ //
+ CopyMem (
+ Type42Record->InterfaceTypeSpecificData + DeviceDataLength + 1,
+ NewProtocolRecords,
+ CurrentProtocolsDataLength
+ );
+
+ //
+ // 5. Add Redfish interface data record to SMBIOS table 42
+ //
+ Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->Add (
+ Smbios,
+ NULL,
+ &MemArrayMappedAddrSmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER*) Type42Record
+ );
+ DEBUG ((DEBUG_INFO, "RedfishPlatformDxe: Smbios->Add() - %r\n", Status));
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ Status = EFI_SUCCESS;
+
+ON_EXIT:
+ if (DeviceDescriptor != NULL) {
+ FreePool (DeviceDescriptor);
+ }
+ if (NewProtocolRecords != NULL) {
+ FreePool (NewProtocolRecords);
+ }
+ if (Type42Record != NULL) {
+ FreePool (Type42Record);
+ }
+ return Status;
+}
+
+/**
+ Main entry for this driver.
+
+ @param ImageHandle Image handle this driver.
+ @param SystemTable Pointer to SystemTable.
+
+ @retval EFI_SUCESS This function always complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishHostInterfaceDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // Create SMBIOS type 42 record.
+ //
+ return RedfishCreateSmbiosTable42 ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf
new file mode 100644
index 00000000..a0d12e80
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf
@@ -0,0 +1,50 @@
+## @file
+# RedfishHostInterfaceDxe builds up SMBIOS Type 42h host interface
+# record for Redfish service host interface using SMBIOS Protocol.
+# RedfishHostInterfacePlatformLib is the platform-level library which
+# provides the content of Redfish host interface type 42h record.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001000b
+ BASE_NAME = RedfishHostInterfaceDxe
+ FILE_GUID = 592626DA-4A1E-8B39-28BA-FEAD92C4A0A4
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishHostInterfaceDxeEntryPoint
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ RedfishHostInterfaceDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ PrintLib
+ RedfishPlatformHostInterfaceLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gEfiSmbiosProtocolGuid ## TO_START
+
+[Depex]
+ gEfiSmbiosProtocolGuid
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishLibs.dsc.inc b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishLibs.dsc.inc
new file mode 100644
index 00000000..0bcc32c3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishLibs.dsc.inc
@@ -0,0 +1,21 @@
+## @file
+# Redfish DSC include file for [LibraryClasses*] section of all Architectures.
+#
+# This file can be included to the [LibraryClasses*] section(s) of a platform DSC file
+# by using "!include RedfishPkg/RedfisLibs.dsc.inc" to specify the library instances
+# of EDKII network library classes.
+#
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+!if $(REDFISH_ENABLE) == TRUE
+ RestExLib|RedfishPkg/Library/DxeRestExLib/DxeRestExLib.inf
+ Ucs2Utf8Lib|RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf
+ BaseSortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
+ RedfishCrtLib|RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
+ JsonLib|RedfishPkg/Library/JsonLib/JsonLib.inf
+ RedfishLib|RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
+!endif
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.ci.yaml
new file mode 100644
index 00000000..bd3877a0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.ci.yaml
@@ -0,0 +1,105 @@
+## @file
+# CI configuration for NetworkPkg
+#
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+{
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ "EccCheck": {
+ ## Exception sample looks like below:
+ ## "ExceptionList": [
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+ ## Below are files incorporated with open source which are
+ ## not edk2 coding standard compliant.
+ ##
+ ## EDK2 CRT library which is not edk2 coding
+ ## standard compliant.
+ ## C runtime library for RedfishPkg modules
+ "PrivateInclude/Crt/sys",
+ "PrivateInclude/Crt/assert.h",
+ "PrivateInclude/Crt/errno.h",
+ "PrivateInclude/Crt/limits.h",
+ "PrivateInclude/Crt/math.h",
+ "PrivateInclude/Crt/stdarg.h",
+ "PrivateInclude/Crt/stddef.h",
+ "PrivateInclude/Crt/stdio.h",
+ "PrivateInclude/Crt/stdlib.h",
+ "PrivateInclude/Crt/string.h",
+ "PrivateInclude/Crt/time.h",
+ "PrivateInclude/Library/RedfishCrtLib.h",
+ "PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c",
+ ##
+ ## For jansson library open source
+ ## load.c is overrided from open source.
+ "Library/JsonLib/load.c",
+ "Library/JsonLib/jansson_config.h",
+ "Library/JsonLib/jansson_private_config.h",
+ ##
+ ## For libredfish open source
+ ## The files under edk2libredfish are cloned
+ ## from DMTF open source
+ "PrivateLibrary/RedfishLib/edk2libredfish/include/redfish.h",
+ "PrivateLibrary/RedfishLib/edk2libredfish/include/redfishPayload.h",
+ "PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h",
+ "PrivateLibrary/RedfishLib/edk2libredfish/include/redpath.h",
+ "PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c",
+ "PrivateLibrary/RedfishLib/edk2libredfish/src/redpath.c",
+ "PrivateLibrary/RedfishLib/edk2libredfish/src/service.c"
+ ]
+ },
+ "CompilerPlugin": {
+ "DscPath": "RedfishPkg.dsc"
+ },
+ "CharEncodingCheck": {
+ "IgnoreFiles": []
+ },
+ "DependencyCheck": {
+ "AcceptableDependencies": [
+ "MdePkg/MdePkg.dec",
+ "MdeModulePkg/MdeModulePkg.dec",
+ "NetworkPkg/NetworkPkg.dec",
+ "RedfishPkg/RedfishPkg.dec"
+ ],
+ # For host based unit tests
+ "AcceptableDependencies-HOST_APPLICATION":[],
+ # For UEFI shell based apps
+ "AcceptableDependencies-UEFI_APPLICATION":[
+ "ShellPkg/ShellPkg.dec"
+ ],
+ "IgnoreInf": []
+ },
+ "DscCompleteCheck": {
+ "DscPath": "RedfishPkg.dsc",
+ "IgnoreInf": []
+ },
+ "GuidCheck": {
+ "IgnoreGuidName": [],
+ "IgnoreGuidValue": [],
+ "IgnoreFoldersAndFiles": []
+ },
+ "LibraryClassCheck": {
+ "IgnoreHeaderFile": []
+ },
+
+ ## options defined ci/Plugin/SpellCheck
+ "SpellCheck": {
+ "AuditOnly": True, # Fails test but run in AuditOnly mode to collect log
+ "IgnoreFiles": [], # use gitignore syntax to ignore errors in matching files
+ "ExtendWords": [], # words to extend to the dictionary for this package
+ "IgnoreStandardPaths": [], # Standard Plugin defined paths that should be ignore
+ "AdditionalIncludePaths": [] # Additional paths to spell check (wildcards supported)
+ },
+
+ "Defines": {
+ "BLD_*_CONTINUOUS_INTEGRATION": "TRUE",
+ "BLD_*_REDFISH_ENABLE": "TRUE"
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dec b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dec
new file mode 100644
index 00000000..972ea1b9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dec
@@ -0,0 +1,100 @@
+## @file
+# Redfish Package
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ DEC_SPECIFICATION = 0x0001001b
+ PACKAGE_NAME = RedfishPkg
+ PACKAGE_GUID = c432b76e-5232-11e7-9010-005056c00008
+ PACKAGE_VERSION = 1.0
+
+[Includes]
+ Include
+
+[Includes.Common.Private]
+ PrivateInclude # Private header files for C RTL.
+ PrivateInclude/Crt # Private header files for C RTL.
+ Library/JsonLib # Private header files for jansson
+ # configuration files.
+ # - jansson_config.h
+ # - jansson_private_config.h
+ # jansson.h refers to above two configuration
+ # files for building platform jansson library.
+ Library/JsonLib/jansson/src # For referring to jannson.h
+
+[LibraryClasses]
+ ## @libraryclass Platform Redfish Host Interface Library
+ # Platform implementation-specific Redfish Host Interface.
+ RedfishPlatformHostInterfaceLib|Include/Library/RedfishHostInterfaceLib.h
+
+ ## @libraryclass This library provides UCS2 to UTF8 manipulation
+ # functions.
+ #
+ Ucs2Utf8Lib|Include/Library/BaseUcs2Utf8Lib.h
+
+ ## @libraryclass Platform Redfish Credential Library
+ # Platform implementation-specific Redfish Credential Interface.
+ RedfishPlatformCredentialLib|Include/Library/RedfishCredentialLib.h
+
+ ## @libraryclass The helper routines to access REST EX service.
+ # This library is only intended to be used by UEFI network stack modules.
+ RestExLib|Include/Library/RestExLib.h
+
+ ## @libraryclass Provides the library functions based on third party
+ # jansson library to manipulate JSON data structure.
+ #
+ JsonLib|Include/Library/JsonLib.h
+
+ ## @libraryclass Provides the library functions to encode/decode
+ # Redfish packet.
+ #
+ RedfishContentCodingLib|Include/Library/RedfishContentCodingLib.h
+
+[LibraryClasses.Common.Private]
+ ## @libraryclass Provides the private C runtime library functions.
+ # CRT library is currently used by edk2 JsonLib (open source
+ # jansson project) and edk2 RedfishLib (libredfish open source
+ # project).
+ RedfishCrtLib|PrivateInclude/Library/RedfishCrtLib.h
+
+ ## @libraryclass Redfish Helper Library
+ # Library provides Redfish helper functions.
+ RedfishLib|PrivateInclude/Library/RedfishLib.h
+
+[Protocols]
+ ## Include/Protocol/EdkIIRedfishCredential.h
+ gEdkIIRedfishCredentialProtocolGuid = { 0x8804377, 0xaf7a, 0x4496, { 0x8a, 0x7b, 0x17, 0x59, 0x0, 0xe9, 0xab, 0x46 } }
+
+ ## Include/Protocol/Edk2RedfishConfigHandler.h
+ gEdkIIRedfishConfigHandlerProtocolGuid = { 0xbc0fe6bb, 0x2cc9, 0x463e, { 0x90, 0x82, 0xfa, 0x11, 0x76, 0xfc, 0x67, 0xde } }
+
+[Guids]
+ gEfiRedfishPkgTokenSpaceGuid = { 0x4fdbccb7, 0xe829, 0x4b4c, { 0x88, 0x87, 0xb2, 0x3f, 0xd7, 0x25, 0x4b, 0x85 }}
+
+[PcdsFixedAtBuild, PcdsPatchableInModule]
+ #
+ # This PCD is the UEFI device path which is used as the Redfish host interface.
+ #
+ gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceDevicePath|{0x0}|REST_EX_SERVICE_DEVICE_PATH_DATA|0x00001000 {
+ <HeaderFiles>
+ Pcd/RestExServiceDevicePath.h
+ <Packages>
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+ }
+ #
+ # This PCD indicates the EFI REST EX access mode to Redfish service.
+ # Default is set to out of band access.
+ #
+ gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceAccessModeInBand|FALSE|BOOLEAN|0x00001001
+ #
+ # This PCD indicates the access mode EFI Discover protocol uses to look for the proper EFI REST EX
+ # protocol instance.
+ #
+ gEfiRedfishPkgTokenSpaceGuid.PcdRedfishDiscoverAccessModeInBand|FALSE|BOOLEAN|0x00001002
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dsc b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dsc
new file mode 100644
index 00000000..b0d36e7f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dsc
@@ -0,0 +1,62 @@
+## @file
+# Redfish Package
+#
+# Copyright (c) 2019 - 2021, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2021 Hewlett-Packard Enterprise Development LP.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ PLATFORM_NAME = RedfishPkg
+ PLATFORM_GUID = c4352870-5232-11e7-9522-005056c00008
+ PLATFORM_VERSION = 1.0
+ DSC_SPECIFICATION = 0x0001001c
+ OUTPUT_DIRECTORY = Build/RedfishPkg
+ SUPPORTED_ARCHITECTURES = IA32|X64|ARM|AARCH64|RISCV64
+ BUILD_TARGETS = DEBUG|RELEASE|NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+
+!include MdePkg/MdeLibs.dsc.inc
+
+[LibraryClasses]
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ RedfishPlatformHostInterfaceLib|RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf
+ HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf
+ HttpIoLib|NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf
+ NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
+ DpcLib|NetworkPkg/Library/DxeDpcLib/DxeDpcLib.inf
+ RedfishPlatformCredentialLib|RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf
+ RedfishContentCodingLib|RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.inf
+
+[LibraryClasses.ARM, LibraryClasses.AARCH64]
+ #
+ # This library provides the instrinsic functions generated by a given compiler.
+ #
+ NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
+ NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
+ ArmSoftFloatLib|ArmPkg/Library/ArmSoftFloatLib/ArmSoftFloatLib.inf
+
+[Components]
+ RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf
+ RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf
+ RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.inf
+ RedfishPkg/Library/DxeRestExLib/DxeRestExLib.inf
+ RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf
+ RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
+ RedfishPkg/Library/JsonLib/JsonLib.inf
+ RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
+
+ !include RedfishPkg/Redfish.dsc.inc
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/ComponentName.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/ComponentName.c
new file mode 100644
index 00000000..1147d070
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/ComponentName.c
@@ -0,0 +1,222 @@
+/** @file
+ Implementation of EFI_COMPONENT_NAME_PROTOCOL and EFI_COMPONENT_NAME2_PROTOCOL
+ protocol.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+
+#include <Library/UefiLib.h>
+
+#include <Protocol/ComponentName.h>
+#include <Protocol/ComponentName2.h>
+
+//
+// EFI Component Name Functions
+//
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+///
+/// Component Name Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME_PROTOCOL gRedfishRestExComponentName = {
+ RedfishRestExComponentNameGetDriverName,
+ RedfishRestExComponentNameGetControllerName,
+ "eng"
+};
+
+///
+/// Component Name 2 Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL gRedfishRestExComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) RedfishRestExComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) RedfishRestExComponentNameGetControllerName,
+ "en"
+};
+
+///
+/// Table of driver names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mRedfishRestExDriverNameTable[] = {
+ { "eng;en", (CHAR16 *)L"Redfish RestEx Network Service Driver" },
+ { NULL, NULL }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gRedfishRestExControllerNameTable = NULL;
+
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mRedfishRestExDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gRedfishRestExComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c
new file mode 100644
index 00000000..1ecf444c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c
@@ -0,0 +1,831 @@
+/** @file
+ The driver binding and service binding protocol for Redfish RestExDxe driver.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include "RedfishRestExDriver.h"
+
+EFI_DRIVER_BINDING_PROTOCOL gRedfishRestExDriverBinding = {
+ RedfishRestExDriverBindingSupported,
+ RedfishRestExDriverBindingStart,
+ RedfishRestExDriverBindingStop,
+ REDFISH_RESTEX_DRIVER_VERSION,
+ NULL,
+ NULL
+};
+
+EFI_SERVICE_BINDING_PROTOCOL mRedfishRestExServiceBinding = {
+ RedfishRestExServiceBindingCreateChild,
+ RedfishRestExServiceBindingDestroyChild
+};
+
+/**
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.
+
+ @param[in] Entry The entry to be removed.
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
+
+ @retval EFI_SUCCESS The entry has been removed successfully.
+ @retval Others Fail to remove the entry.
+
+**/
+EFI_STATUS
+EFIAPI
+RestExDestroyChildEntryInHandleBuffer (
+ IN LIST_ENTRY *Entry,
+ IN VOID *Context
+ )
+{
+ RESTEX_INSTANCE *Instance;
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ UINTN NumberOfChildren;
+ EFI_HANDLE *ChildHandleBuffer;
+
+ if (Entry == NULL || Context == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = NET_LIST_USER_STRUCT_S (Entry, RESTEX_INSTANCE, Link, RESTEX_INSTANCE_SIGNATURE);
+ ServiceBinding = ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;
+ NumberOfChildren = ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;
+ ChildHandleBuffer = ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;
+
+ if (!NetIsInHandleBuffer (Instance->ChildHandle, NumberOfChildren, ChildHandleBuffer)) {
+ return EFI_SUCCESS;
+ }
+
+ return ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHandle);
+}
+
+/**
+ Destroy the RestEx instance and recycle the resources.
+
+ @param[in] Instance The pointer to the RestEx instance.
+
+**/
+VOID
+RestExDestroyInstance (
+ IN RESTEX_INSTANCE *Instance
+ )
+{
+ HttpIoDestroyIo (&(Instance->HttpIo));
+
+ FreePool (Instance);
+}
+
+/**
+ Create the RestEx instance and initialize it.
+
+ @param[in] Service The pointer to the RestEx service.
+ @param[out] Instance The pointer to the RestEx instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
+ @retval EFI_SUCCESS The RestEx instance is created.
+
+**/
+EFI_STATUS
+RestExCreateInstance (
+ IN RESTEX_SERVICE *Service,
+ OUT RESTEX_INSTANCE **Instance
+ )
+{
+ RESTEX_INSTANCE *RestExIns;
+ EFI_STATUS Status;
+
+ *Instance = NULL;
+ Status = EFI_SUCCESS;
+
+ RestExIns = AllocateZeroPool (sizeof (RESTEX_INSTANCE));
+ if (RestExIns == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RestExIns->Signature = RESTEX_INSTANCE_SIGNATURE;
+ InitializeListHead (&RestExIns->Link);
+ RestExIns->InDestroy = FALSE;
+ RestExIns->Service = Service;
+
+ CopyMem (&RestExIns->RestEx, &mRedfishRestExProtocol, sizeof (RestExIns->RestEx));
+
+ //
+ // Create a HTTP_IO to access the HTTP service.
+ //
+ Status = HttpIoCreateIo (
+ RestExIns->Service->ImageHandle,
+ RestExIns->Service->ControllerHandle,
+ IP_VERSION_4,
+ NULL,
+ NULL,
+ NULL,
+ &(RestExIns->HttpIo)
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (RestExIns);
+ return Status;
+ }
+
+ *Instance = RestExIns;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Release all the resource used the RestEx service binding instance.
+
+ @param[in] RestExSb The RestEx service binding instance.
+
+**/
+VOID
+RestExDestroyService (
+ IN RESTEX_SERVICE *RestExSb
+ )
+{
+ if (RestExSb->HttpChildHandle != NULL) {
+ gBS->CloseProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ RestExSb->ImageHandle,
+ RestExSb->ControllerHandle
+ );
+
+ NetLibDestroyServiceChild (
+ RestExSb->ControllerHandle,
+ RestExSb->ImageHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ RestExSb->HttpChildHandle
+ );
+
+ RestExSb->HttpChildHandle = NULL;
+ }
+
+ gBS->UninstallProtocolInterface (
+ RestExSb->ControllerHandle,
+ &gEfiCallerIdGuid,
+ &RestExSb->Id
+ );
+
+ FreePool (RestExSb);
+}
+
+/**
+ Check the NIC controller handle represents an in-band or out-of-band Redfish host
+ interface device. If not in-band, treat it as out-of-band interface device.
+
+ @param[in] Controller The NIC controller handle needs to be checked.
+
+ @return EFI_REST_EX_SERVICE_ACCESS_MODE of the device.
+
+**/
+EFI_REST_EX_SERVICE_ACCESS_MODE
+RestExServiceAccessMode (
+ IN EFI_HANDLE Controller
+ )
+{
+ //
+ // This is EFI REST EX driver instance to connect
+ // to Redfish service using HTTP in out of band.
+ //
+ if (FixedPcdGetBool (PcdRedfishRestExServiceAccessModeInBand)) {
+ return EfiRestExServiceInBandAccess;
+ } else {
+ return EfiRestExServiceOutOfBandAccess;
+ }
+}
+
+/**
+ Create then initialize a RestEx service binding instance.
+
+ @param[in] Controller The controller to install the RestEx service
+ binding on.
+ @param[in] Image The driver binding image of the RestEx driver.
+ @param[out] Service The variable to receive the created service
+ binding instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.
+ @retval EFI_SUCCESS The service instance is created for the controller.
+
+**/
+EFI_STATUS
+RestExCreateService (
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Image,
+ OUT RESTEX_SERVICE **Service
+ )
+{
+ EFI_STATUS Status;
+ RESTEX_SERVICE *RestExSb;
+
+ Status = EFI_SUCCESS;
+ RestExSb = NULL;
+
+ *Service = NULL;
+
+ RestExSb = AllocateZeroPool (sizeof (RESTEX_SERVICE));
+ if (RestExSb == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RestExSb->Signature = RESTEX_SERVICE_SIGNATURE;
+
+ RestExSb->ServiceBinding = mRedfishRestExServiceBinding;
+
+ RestExSb->RestExChildrenNum = 0;
+ InitializeListHead (&RestExSb->RestExChildrenList);
+
+ RestExSb->ControllerHandle = Controller;
+ RestExSb->ImageHandle = Image;
+
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.Length = sizeof (EFI_REST_EX_SERVICE_INFO);
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.RestServiceInfoVer.Major = 1;
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.RestServiceInfoVer.Minor = 0;
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestServiceType = EfiRestExServiceRedfish;
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestServiceAccessMode = RestExServiceAccessMode (Controller);
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestExConfigType = EfiRestExConfigHttp;
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestExConfigDataLength = sizeof (EFI_REST_EX_HTTP_CONFIG_DATA);
+
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiCallerIdGuid,
+ EFI_NATIVE_INTERFACE,
+ &RestExSb->Id
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (RestExSb);
+ RestExSb = NULL;
+ }
+
+ *Service = RestExSb;
+ 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.
+
+ @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 Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Install the RestEx Driver Binding Protocol.
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gRedfishRestExDriverBinding,
+ ImageHandle,
+ &gRedfishRestExComponentName,
+ &gRedfishRestExComponentName2
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return Status;
+}
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+
+ //
+ // Test for the HttpServiceBinding Protocol.
+ //
+ return gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+
+}
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ RESTEX_SERVICE *RestExSb;
+ EFI_STATUS Status;
+ UINT32 *Id;
+ VOID *Interface;
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiCallerIdGuid,
+ (VOID **) &Id,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ Status = RestExCreateService (ControllerHandle, This->DriverBindingHandle, &RestExSb);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ASSERT (RestExSb != NULL);
+
+ //
+ // Create a Http child instance, but do not configure it.
+ // This will establish the parent-child relationship.
+ //
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ This->DriverBindingHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ &RestExSb->HttpChildHandle
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ Status = gBS->OpenProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ &Interface,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Install the RestEx ServiceBinding Protocol onto ControllerHandle.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ControllerHandle,
+ &gEfiRestExServiceBindingProtocolGuid,
+ &RestExSb->ServiceBinding,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ RestExDestroyService (RestExSb);
+
+ return Status;
+}
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ RESTEX_SERVICE *RestExSb;
+ EFI_HANDLE NicHandle;
+ EFI_STATUS Status;
+ LIST_ENTRY *List;
+ RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
+
+ //
+ // RestEx driver opens HTTP child, So, Controller is a HTTP
+ // child handle. Locate the Nic handle first. Then get the
+ // RestEx private data back.
+ //
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGuid);
+ if (NicHandle == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = gBS->OpenProtocol (
+ NicHandle,
+ &gEfiRestExServiceBindingProtocolGuid,
+ (VOID **) &ServiceBinding,
+ This->DriverBindingHandle,
+ NicHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ RestExSb = RESTEX_SERVICE_FROM_THIS (ServiceBinding);
+
+ if (!IsListEmpty (&RestExSb->RestExChildrenList)) {
+ //
+ // Destroy the RestEx child instance in ChildHandleBuffer.
+ //
+ List = &RestExSb->RestExChildrenList;
+ Context.ServiceBinding = ServiceBinding;
+ Context.NumberOfChildren = NumberOfChildren;
+ Context.ChildHandleBuffer = ChildHandleBuffer;
+ Status = NetDestroyLinkList (
+ List,
+ RestExDestroyChildEntryInHandleBuffer,
+ &Context,
+ NULL
+ );
+ }
+
+ if (NumberOfChildren == 0 && IsListEmpty (&RestExSb->RestExChildrenList)) {
+ gBS->UninstallProtocolInterface (
+ NicHandle,
+ &gEfiRestExServiceBindingProtocolGuid,
+ ServiceBinding
+ );
+
+ RestExDestroyService (RestExSb);
+
+ if (gRedfishRestExControllerNameTable != NULL) {
+ FreeUnicodeStringTable (gRedfishRestExControllerNameTable);
+ gRedfishRestExControllerNameTable = NULL;
+ }
+
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCES The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
+ the child
+ @retval other The child handle was not created
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ )
+{
+ RESTEX_SERVICE *RestExSb;
+ RESTEX_INSTANCE *Instance;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+ VOID *Http;
+
+ if ((This == NULL) || (ChildHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RestExSb = RESTEX_SERVICE_FROM_THIS (This);
+
+ Status = RestExCreateInstance (RestExSb, &Instance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ASSERT (Instance != NULL);
+
+ //
+ // Install the RestEx protocol onto ChildHandle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ ChildHandle,
+ &gEfiRestExProtocolGuid,
+ &Instance->RestEx,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ Instance->ChildHandle = *ChildHandle;
+
+ //
+ // Open the Http protocol BY_CHILD.
+ //
+ Status = gBS->OpenProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ (VOID **) &Http,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ Instance->ChildHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ Instance->ChildHandle,
+ &gEfiRestExProtocolGuid,
+ &Instance->RestEx,
+ NULL
+ );
+
+ goto ON_ERROR;
+ }
+
+ //
+ // Open the Http protocol by child.
+ //
+ Status = gBS->OpenProtocol (
+ Instance->HttpIo.Handle,
+ &gEfiHttpProtocolGuid,
+ (VOID **) &Http,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ Instance->ChildHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Close the Http protocol.
+ //
+ gBS->CloseProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ ChildHandle
+ );
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Instance->ChildHandle,
+ &gEfiRestExProtocolGuid,
+ &Instance->RestEx,
+ NULL
+ );
+
+ goto ON_ERROR;
+ }
+
+ //
+ // Add it to the parent's child list.
+ //
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ InsertTailList (&RestExSb->RestExChildrenList, &Instance->Link);
+ RestExSb->RestExChildrenNum++;
+
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+
+ RestExDestroyInstance (Instance);
+ return Status;
+}
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Handle of the child to destroy
+
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ )
+{
+ RESTEX_SERVICE *RestExSb;
+ RESTEX_INSTANCE *Instance;
+
+ EFI_REST_EX_PROTOCOL *RestEx;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ if ((This == NULL) || (ChildHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Retrieve the private context data structures
+ //
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiRestExProtocolGuid,
+ (VOID **) &RestEx,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Instance = RESTEX_INSTANCE_FROM_THIS (RestEx);
+ RestExSb = RESTEX_SERVICE_FROM_THIS (This);
+
+ if (Instance->Service != RestExSb) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Instance->InDestroy) {
+ return EFI_SUCCESS;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance->InDestroy = TRUE;
+
+ //
+ // Close the Http protocol.
+ //
+ gBS->CloseProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ ChildHandle
+ );
+
+ gBS->CloseProtocol (
+ Instance->HttpIo.Handle,
+ &gEfiHttpProtocolGuid,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ ChildHandle
+ );
+
+
+ gBS->RestoreTPL (OldTpl);
+
+ //
+ // Uninstall the RestEx protocol first to enable a top down destruction.
+ //
+ Status = gBS->UninstallProtocolInterface (
+ ChildHandle,
+ &gEfiRestExProtocolGuid,
+ RestEx
+ );
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ if (EFI_ERROR (Status)) {
+ Instance->InDestroy = FALSE;
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+ }
+
+ RemoveEntryList (&Instance->Link);
+ RestExSb->RestExChildrenNum--;
+
+ gBS->RestoreTPL (OldTpl);
+
+ RestExDestroyInstance (Instance);
+ return EFI_SUCCESS;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h
new file mode 100644
index 00000000..0b9ba701
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h
@@ -0,0 +1,650 @@
+/** @file
+ RedfishRestExDxe support functions definitions.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_RESTEX_DRIVER_H_
+#define EFI_REDFISH_RESTEX_DRIVER_H_
+
+///
+/// Libraries classes
+///
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HttpIoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+///
+/// UEFI Driver Model Protocols
+///
+#include <Protocol/DriverBinding.h>
+#include <Protocol/RestEx.h>
+#include <Protocol/ServiceBinding.h>
+
+///
+/// Protocol instances
+///
+extern EFI_COMPONENT_NAME_PROTOCOL gRedfishRestExComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gRedfishRestExComponentName2;
+extern EFI_UNICODE_STRING_TABLE *gRedfishRestExControllerNameTable;
+
+extern EFI_DRIVER_BINDING_PROTOCOL gRedfishRestExDriverBinding;
+extern EFI_SERVICE_BINDING_PROTOCOL mRedfishRestExServiceBinding;
+extern EFI_REST_EX_PROTOCOL mRedfishRestExProtocol;
+///
+/// RestEx service block
+///
+typedef struct _RESTEX_SERVICE RESTEX_SERVICE;
+
+///
+/// RestEx instance block
+///
+typedef struct _RESTEX_INSTANCE RESTEX_INSTANCE;
+
+///
+/// Driver Version
+///
+#define REDFISH_RESTEX_DRIVER_VERSION 0x0100
+
+#define RESTEX_SERVICE_SIGNATURE SIGNATURE_32 ('R', 'E', 'S', 'S')
+#define RESTEX_INSTANCE_SIGNATURE SIGNATURE_32 ('R', 'E', 'I', 'S')
+
+#define RESTEX_SERVICE_FROM_THIS(a) \
+ CR (a, RESTEX_SERVICE, ServiceBinding, RESTEX_SERVICE_SIGNATURE)
+
+#define RESTEX_INSTANCE_FROM_THIS(a) \
+ CR (a, RESTEX_INSTANCE, RestEx, RESTEX_INSTANCE_SIGNATURE)
+
+
+#define RESTEX_STATE_UNCONFIGED 0
+#define RESTEX_STATE_CONFIGED 1
+
+struct _RESTEX_SERVICE {
+ UINT32 Signature;
+ EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
+
+ UINT16 RestExChildrenNum;
+ LIST_ENTRY RestExChildrenList;
+
+ EFI_HANDLE ControllerHandle;
+ EFI_HANDLE ImageHandle;
+
+ //
+ // Use to establish the parent-child relationship.
+ //
+ EFI_HANDLE HttpChildHandle;
+
+ UINT32 Id;
+
+ EFI_REST_EX_SERVICE_INFO RestExServiceInfo;
+};
+
+#define RESTEX_INSTANCE_FLAGS_TLS_RETRY 0x00000001
+#define RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY 0x00000002
+
+struct _RESTEX_INSTANCE {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+
+ EFI_REST_EX_PROTOCOL RestEx;
+
+ INTN State;
+ BOOLEAN InDestroy;
+
+ RESTEX_SERVICE *Service;
+ EFI_HANDLE ChildHandle;
+
+ EFI_REST_EX_CONFIG_DATA ConfigData;
+
+ //
+ // HTTP_IO to access the HTTP service
+ //
+ HTTP_IO HttpIo;
+
+ UINT32 Flags;
+};
+
+typedef struct {
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ UINTN NumberOfChildren;
+ EFI_HANDLE *ChildHandleBuffer;
+} RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT;
+
+/**
+ Provides a simple HTTP-like interface to send and receive resources from a REST service.
+
+ The SendReceive() function sends an HTTP request to this REST service, and returns a
+ response when the data is retrieved from the service. RequestMessage contains the HTTP
+ request to the REST resource identified by RequestMessage.Request.Url. The
+ ResponseMessage is the returned HTTP response for that request, including any HTTP
+ status.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[out] ResponseMessage Pointer to the HTTP response data obtained for this requested.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage are NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ OUT EFI_HTTP_MESSAGE *ResponseMessage
+ );
+
+/**
+ Obtain the current time from this REST service instance.
+
+ The GetServiceTime() function is an optional interface to obtain the current time from
+ this REST service instance. If this REST service does not support to retrieve the time,
+ this function returns EFI_UNSUPPORTED. This function must returns EFI_UNSUPPORTED if
+ EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from GetService() is
+ EFI_REST_EX_SERVICE_UNSPECIFIC.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] Time A pointer to storage to receive a snapshot of the current time of
+ the REST service.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This or Time are NULL.
+ @retval EFI_UNSUPPORTED The RESTful service does not support returning the time.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must
+ be executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetServiceTime (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_TIME *Time
+ );
+
+/**
+ This function returns the information of REST service provided by this EFI REST EX driver instance.
+
+ The information such as the type of REST service and the access mode of REST EX driver instance
+ (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO structure. For the vendor-specific
+ REST service, vendor-specific REST service information is returned in VendorSpecifcData.
+ REST EX driver designer is well know what REST service this REST EX driver instance intends to
+ communicate with. The designer also well know this driver instance is used to talk to BMC through
+ specific platform mechanism or talk to REST server through UEFI HTTP protocol. REST EX driver is
+ responsible to fill up the correct information in EFI_REST_EX_SERVICE_INFO. EFI_REST_EX_SERVICE_INFO
+ is referred by EFI REST clients to pickup the proper EFI REST EX driver instance to get and set resource.
+ GetService() is a basic and mandatory function which must be able to use even Configure() is not invoked
+ in previously.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] RestExServiceInfo Pointer to receive a pointer to EFI_REST_EX_SERVICE_INFO structure. The
+ format of EFI_REST_EX_SERVICE_INFO is version controlled for the future
+ extension. The version of EFI_REST_EX_SERVICE_INFO structure is returned
+ in the header within this structure. EFI REST client refers to the correct
+ format of structure according to the version number. The pointer to
+ EFI_REST_EX_SERVICE_INFO is a memory block allocated by EFI REST EX driver
+ instance. That is caller's responsibility to free this memory when this
+ structure is no longer needed. Refer to Related Definitions below for the
+ definitions of EFI_REST_EX_SERVICE_INFO structure.
+
+ @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in RestExServiceInfo. This function
+ is not supported in this REST EX Protocol driver instance.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo
+ );
+
+/**
+ This function returns operational configuration of current EFI REST EX child instance.
+
+ This function returns the current configuration of EFI REST EX child instance. The format of
+ operational configuration depends on the implementation of EFI REST EX driver instance. For
+ example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol as the undying protocol
+ to communicate with REST service. In this case, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService(). EFI_HTTP_CONFIG_DATA is used as EFI REST
+ EX configuration format and returned to EFI REST client. User has to type cast RestExConfigData
+ to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver instances, the type of configuration
+ is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In this case, the format of
+ returning data could be non industrial. Instead, the format of configuration data is system/platform
+ specific definition such as BMC mechanism used in EFI REST EX driver instance. EFI REST client and
+ EFI REST EX driver instance have to refer to the specific system /platform spec which is out of UEFI scope.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[out] RestExConfigData Pointer to receive a pointer to EFI_REST_EX_CONFIG_DATA.
+ The memory allocated for configuration data should be freed
+ by caller. See Related Definitions for the details.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in successfully.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be
+ executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetModeData (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData
+ );
+
+/**
+ This function is used to configure EFI REST EX child instance.
+
+ This function is used to configure the setting of underlying protocol of REST EX child
+ instance. The type of configuration is according to the implementation of EFI REST EX
+ driver instance. For example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol
+ as the undying protocol to communicate with REST service. The type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same format with EFI_HTTP_CONFIG_DATA.
+ Akin to HTTP configuration, REST EX child instance can be configure to use different HTTP
+ local access point for the data transmission. Multiple REST clients may use different
+ configuration of HTTP to distinguish themselves, such as to use the different TCP port.
+ For those non HTTP-aware REST EX driver instance, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the non industrial standard.
+ Instead, the format of configuration data is system/platform specific definition such as BMC.
+ In this case, EFI REST client and EFI REST EX driver instance have to refer to the specific
+ system/platform spec which is out of the UEFI scope. Besides GetService()function, no other
+ EFI REST EX functions can be executed by this instance until Configure()is executed and returns
+ successfully. All other functions must returns EFI_NOT_READY if this instance is not configured
+ yet. Set RestExConfigData to NULL means to put EFI REST EX child instance into the unconfigured
+ state.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA. See Related Definitions in
+ GetModeData() protocol interface.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in successfully.
+ @retval EFI_DEVICE_ERROR Configuration for this REST EX child instance is failed with the given
+ EFI_REST_EX_CONFIG_DATA.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExConfigure (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_REST_EX_CONFIG_DATA RestExConfigData
+ );
+
+/**
+ This function sends REST request to REST service and signal caller's event asynchronously when
+ the final response is received by REST EX Protocol driver instance.
+
+ The essential design of this function is to handle asynchronous send/receive implicitly according
+ to REST service asynchronous request mechanism. Caller will get the notification once the response
+ is returned from REST service.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous asynchronous request associated with the
+ corresponding RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol instance uses to notify REST client
+ the status of response of asynchronous REST request. See related definition
+ of EFI_REST_EX_TOKEN.
+ @param[in] TimeOutInMilliSeconds The pointer to the timeout in milliseconds which REST EX Protocol driver
+ instance refers as the duration to drop asynchronous REST request. NULL
+ pointer means no timeout for this REST request. REST EX Protocol driver
+ signals caller's event with EFI_STATUS set to EFI_TIMEOUT in RestExToken
+ if REST EX Protocol can't get the response from REST service within
+ TimeOutInMilliSeconds.
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_TIMEOUT Asynchronous REST request is not established and timeout is expired.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExAyncSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken,
+ IN UINTN *TimeOutInMilliSeconds OPTIONAL
+ );
+
+/**
+ This function sends REST request to a REST Event service and signals caller's event
+ token asynchronously when the URI resource change event is received by REST EX
+ Protocol driver instance.
+
+ The essential design of this function is to monitor event implicitly according to
+ REST service event service mechanism. Caller will get the notification if certain
+ resource is changed.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous event service associated with the corresponding
+ RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol driver instance uses to notify REST client
+ the URI resource which monitored by REST client has been changed. See the related
+ definition of EFI_REST_EX_TOKEN in EFI_REST_EX_PROTOCOL.AsyncSendReceive().
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled or event subscription has been
+ delete from service.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExEventService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken
+ );
+/**
+ Create a new TLS session becuase the previous on is closed.
+ status.
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI Errors Other errors.
+
+**/
+EFI_STATUS
+ResetHttpTslSession (
+ IN RESTEX_INSTANCE *Instance
+);
+
+
+/**
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.
+
+ @param[in] Entry The entry to be removed.
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
+
+ @retval EFI_SUCCESS The entry has been removed successfully.
+ @retval Others Fail to remove the entry.
+
+**/
+EFI_STATUS
+EFIAPI
+RestExDestroyChildEntryInHandleBuffer (
+ IN LIST_ENTRY *Entry,
+ IN VOID *Context
+ );
+
+/**
+ Destroy the RestEx instance and recycle the resources.
+
+ @param[in] Instance The pointer to the RestEx instance.
+
+**/
+VOID
+RestExDestroyInstance (
+ IN RESTEX_INSTANCE *Instance
+ );
+
+/**
+ Create the RestEx instance and initialize it.
+
+ @param[in] Service The pointer to the RestEx service.
+ @param[out] Instance The pointer to the RestEx instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
+ @retval EFI_SUCCESS The RestEx instance is created.
+
+**/
+EFI_STATUS
+RestExCreateInstance (
+ IN RESTEX_SERVICE *Service,
+ OUT RESTEX_INSTANCE **Instance
+ );
+
+
+/**
+ Release all the resource used the RestEx service binding instance.
+
+ @param RestExSb The RestEx service binding instance.
+
+**/
+VOID
+RestExDestroyService (
+ IN RESTEX_SERVICE *RestExSb
+ );
+
+/**
+ Create then initialize a RestEx service binding instance.
+
+ @param[in] Controller The controller to install the RestEx service
+ binding on.
+ @param[in] Image The driver binding image of the RestEx driver.
+ @param[out] Service The variable to receive the created service
+ binding instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.
+ @retval EFI_SUCCESS The service instance is created for the controller.
+
+**/
+EFI_STATUS
+RestExCreateService (
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Image,
+ OUT RESTEX_SERVICE **Service
+ );
+
+/**
+ 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.
+
+ @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 Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ );
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCES The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
+ the child
+ @retval other The child handle was not created
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ );
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Handle of the child to destroy
+
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
new file mode 100644
index 00000000..de5411bf
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
@@ -0,0 +1,63 @@
+## @file
+# Implementation of Redfish EFI_REST_EX_PROTOCOL interfaces.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = RedfishRestExDxe
+ FILE_GUID = B64702DA-E6B5-43c8-8CE8-D253071E9D6C
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishRestExDriverEntryPoint
+ UNLOAD_IMAGE = NetLibDefaultUnload
+ MODULE_UNI_FILE = RedfishRestExDxe.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[Sources]
+ ComponentName.c
+ RedfishRestExDriver.c
+ RedfishRestExDriver.h
+ RedfishRestExImpl.c
+ RedfishRestExProtocol.c
+ RedfishRestExInternal.h
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ DpcLib
+ HttpLib
+ HttpIoLib
+ PrintLib
+ MemoryAllocationLib
+ NetLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gEfiRestExServiceBindingProtocolGuid ## BY_START
+ gEfiRestExProtocolGuid ## BY_START
+ gEfiHttpServiceBindingProtocolGuid ## TO_START
+ gEfiHttpProtocolGuid ## TO_START
+ gEfiDevicePathProtocolGuid ## TO_START
+
+[Pcd]
+ gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceAccessModeInBand ## CONSUMES
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ RedfishRestExDxeExtra.uni
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni
new file mode 100644
index 00000000..afa0c142
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Redfish UEFI RESTEX DXE Driver.
+//
+// This driver provides Redfish UEFI RESTEX protocols.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+// (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "UEFI Redfish RESTEX service"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This driver provides Redfish EFI RESTEX Protocol and Redfish EFI RESREX Service Binding Protocol."
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni
new file mode 100644
index 00000000..a8ecf8ae
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni
@@ -0,0 +1,15 @@
+// /** @file
+// RestExDxe Localized Strings and Content
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+// (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Redfish UEFI RESTEX DXE"
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c
new file mode 100644
index 00000000..e09a7117
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c
@@ -0,0 +1,157 @@
+/** @file
+ RestExDxe support functions implementation.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include "RedfishRestExInternal.h"
+
+/**
+ Create a new TLS session becuase the previous on is closed.
+ status.
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_ERROR Other errors.
+
+**/
+EFI_STATUS
+ResetHttpTslSession (
+ IN RESTEX_INSTANCE *Instance
+)
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "%a: TCP connection is finished. Could be TSL session closure, reset HTTP instance for the new TLS session.\n", __FUNCTION__));
+
+ Status = Instance->HttpIo.Http->Configure (Instance->HttpIo.Http, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Error to reset HTTP instance.\n", __FUNCTION__));
+ return Status;
+ }
+ Status = Instance->HttpIo.Http->Configure(Instance->HttpIo.Http, &((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Error to re-initiate HTTP instance.\n", __FUNCTION__));
+ }
+ return Status;
+}
+/**
+ This function check
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] HttpIoReceiveStatus This is the status return from HttpIoRecvResponse
+
+ @retval EFI_SUCCESS The payload receive from Redfish service in sucessfully.
+ @retval EFI_NOT_READY May need to resend the HTTP request.
+ @retval EFI_DEVICE_ERROR Something wrong and can't be resolved.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+RedfishCheckHttpReceiveStatus (
+ IN RESTEX_INSTANCE *Instance,
+ IN EFI_STATUS HttpIoReceiveStatus
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+
+ if (!EFI_ERROR (HttpIoReceiveStatus)){
+ ReturnStatus = EFI_SUCCESS;
+ } else if (EFI_ERROR (HttpIoReceiveStatus) && HttpIoReceiveStatus != EFI_CONNECTION_FIN) {
+ if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY) == 0) {
+ DEBUG ((DEBUG_ERROR, "%a: TCP error, reset HTTP session.\n", __FUNCTION__));
+ Instance->Flags |= RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY;
+ gBS->Stall (500);
+ Status = ResetHttpTslSession (Instance);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n", __FUNCTION__));
+ ReturnStatus = EFI_DEVICE_ERROR;
+ } else {
+ return EFI_NOT_READY;
+ }
+ } else {
+ ReturnStatus = EFI_DEVICE_ERROR;
+ }
+ } else {
+ if (HttpIoReceiveStatus == EFI_CONNECTION_FIN) {
+ if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TLS_RETRY) != 0) {
+ DEBUG ((DEBUG_ERROR, "%a: REST_EX Send and receive fail even with a new TLS session.\n", __FUNCTION__));
+ ReturnStatus = EFI_DEVICE_ERROR;
+ }
+ Instance->Flags |= RESTEX_INSTANCE_FLAGS_TLS_RETRY;
+ Status = ResetHttpTslSession (Instance);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n", __FUNCTION__));
+ ReturnStatus = EFI_DEVICE_ERROR;
+ }
+ return EFI_NOT_READY;
+ }
+ }
+ //
+ // Clean TLS new session retry and error try flags.
+ //
+ Instance->Flags &= ~ (RESTEX_INSTANCE_FLAGS_TLS_RETRY | RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY);
+ return ReturnStatus;
+}
+
+/**
+ This function send the HTTP request without body to see
+ if the write to URL is permitted by Redfish service. This function
+ checks if the HTTP request has Content-length in HTTP header. If yes,
+ set HTTP body to NULL and then send to service. Check the HTTP status
+ for the firther actions.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[in] PreservedRequestHeaders The pointer to save the request headers
+ @param[in] ItsWrite This is write method to URL.
+
+ @retval EFI_INVALID_PARAMETER Improper given parameters.
+ @retval EFI_SUCCESS This HTTP request is free to send to Redfish service.
+ @retval EFI_OUT_OF_RESOURCES NOt enough memory to process.
+ @retval EFI_ACCESS_DENIED Not allowed to write to this URL.
+
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+RedfishHttpAddExpectation (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ IN EFI_HTTP_HEADER **PreservedRequestHeaders,
+ IN BOOLEAN *ItsWrite
+ )
+{
+ EFI_HTTP_HEADER *NewHeaders;
+
+ if (This == NULL || RequestMessage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ItsWrite = FALSE;
+ if (PreservedRequestHeaders != NULL) {
+ *PreservedRequestHeaders = RequestMessage->Headers;
+ }
+
+ if ((RequestMessage->Data.Request->Method != HttpMethodPut) && (RequestMessage->Data.Request->Method != HttpMethodPost) &&
+ (RequestMessage->Data.Request->Method != HttpMethodPatch)) {
+ return EFI_SUCCESS;
+ }
+ *ItsWrite = TRUE;
+
+ NewHeaders = AllocateZeroPool((RequestMessage->HeaderCount + 1) * sizeof(EFI_HTTP_HEADER));
+ CopyMem ((VOID*)NewHeaders, (VOID *)RequestMessage->Headers, RequestMessage->HeaderCount * sizeof (EFI_HTTP_HEADER));
+ HttpSetFieldNameAndValue (NewHeaders + RequestMessage->HeaderCount, HTTP_HEADER_EXPECT, HTTP_EXPECT_100_CONTINUE);
+ RequestMessage->HeaderCount ++;
+ RequestMessage->Headers = NewHeaders;
+ return EFI_SUCCESS;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h
new file mode 100644
index 00000000..5a397ade
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h
@@ -0,0 +1,611 @@
+/** @file
+ RedfishRestExDxe support functions definitions.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2019-2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_RESTEX_INTERNAL_H_
+#define EFI_REDFISH_RESTEX_INTERNAL_H_
+
+///
+/// Libraries classes
+///
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HttpIoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+///
+/// UEFI Driver Model Protocols
+///
+#include <Protocol/DriverBinding.h>
+#include <Protocol/RestEx.h>
+#include <Protocol/ServiceBinding.h>
+
+#include "RedfishRestExDriver.h"
+
+/**
+ This function check
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] HttpReceiveEfiStatus This is the status return from HttpIoRecvResponse
+
+ @retval EFI_SUCCESS The payload receive from Redfish service in sucessfully.
+ @retval EFI_NOT_READY May need to resend the HTTP request.
+ @retval EFI_DEVICE_ERROR Something wrong and can't be resolved.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+RedfishCheckHttpReceiveStatus (
+ IN RESTEX_INSTANCE *Instance,
+ IN EFI_STATUS HttpIoReceiveStatus
+ );
+
+/**
+ This function send the HTTP request without body to see
+ if the write to URL is permitted by Redfish service. This function
+ checks if the HTTP request has Content-length in HTTP header. If yes,
+ set HTTP body to NULL and then send to service. Check the HTTP status
+ for the firther actions.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[in] PreservedRequestHeaders The pointer to save the request headers
+ @param[in] ItsWrite This is write method to URL.
+
+ @retval EFI_INVALID_PARAMETER Improper given parameters.
+ @retval EFI_SUCCESS This HTTP request is free to send to Redfish service.
+ @retval EFI_OUT_OF_RESOURCES NOt enough memory to process.
+ @retval EFI_ACCESS_DENIED Not allowed to write to this URL.
+
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+RedfishHttpAddExpectation (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ IN EFI_HTTP_HEADER **PreservedRequestHeaders,
+ IN BOOLEAN *ItsWrite
+ );
+
+/**
+ Provides a simple HTTP-like interface to send and receive resources from a REST service.
+
+ The SendReceive() function sends an HTTP request to this REST service, and returns a
+ response when the data is retrieved from the service. RequestMessage contains the HTTP
+ request to the REST resource identified by RequestMessage.Request.Url. The
+ ResponseMessage is the returned HTTP response for that request, including any HTTP
+ status.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[out] ResponseMessage Pointer to the HTTP response data obtained for this requested.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage are NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ OUT EFI_HTTP_MESSAGE *ResponseMessage
+ );
+
+/**
+ Obtain the current time from this REST service instance.
+
+ The GetServiceTime() function is an optional interface to obtain the current time from
+ this REST service instance. If this REST service does not support to retrieve the time,
+ this function returns EFI_UNSUPPORTED. This function must returns EFI_UNSUPPORTED if
+ EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from GetService() is
+ EFI_REST_EX_SERVICE_UNSPECIFIC.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] Time A pointer to storage to receive a snapshot of the current time of
+ the REST service.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This or Time are NULL.
+ @retval EFI_UNSUPPORTED The RESTful service does not support returning the time.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must
+ be executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetServiceTime (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_TIME *Time
+ );
+
+/**
+ This function returns the information of REST service provided by this EFI REST EX driver instance.
+
+ The information such as the type of REST service and the access mode of REST EX driver instance
+ (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO structure. For the vendor-specific
+ REST service, vendor-specific REST service information is returned in VendorSpecifcData.
+ REST EX driver designer is well know what REST service this REST EX driver instance intends to
+ communicate with. The designer also well know this driver instance is used to talk to BMC through
+ specific platform mechanism or talk to REST server through UEFI HTTP protocol. REST EX driver is
+ responsible to fill up the correct information in EFI_REST_EX_SERVICE_INFO. EFI_REST_EX_SERVICE_INFO
+ is referred by EFI REST clients to pickup the proper EFI REST EX driver instance to get and set resource.
+ GetService() is a basic and mandatory function which must be able to use even Configure() is not invoked
+ in previously.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] RestExServiceInfo Pointer to receive a pointer to EFI_REST_EX_SERVICE_INFO structure. The
+ format of EFI_REST_EX_SERVICE_INFO is version controlled for the future
+ extension. The version of EFI_REST_EX_SERVICE_INFO structure is returned
+ in the header within this structure. EFI REST client refers to the correct
+ format of structure according to the version number. The pointer to
+ EFI_REST_EX_SERVICE_INFO is a memory block allocated by EFI REST EX driver
+ instance. That is caller's responsibility to free this memory when this
+ structure is no longer needed. Refer to Related Definitions below for the
+ definitions of EFI_REST_EX_SERVICE_INFO structure.
+
+ @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in RestExServiceInfo. This function
+ is not supported in this REST EX Protocol driver instance.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo
+ );
+
+/**
+ This function returns operational configuration of current EFI REST EX child instance.
+
+ This function returns the current configuration of EFI REST EX child instance. The format of
+ operational configuration depends on the implementation of EFI REST EX driver instance. For
+ example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol as the undying protocol
+ to communicate with REST service. In this case, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService(). EFI_HTTP_CONFIG_DATA is used as EFI REST
+ EX configuration format and returned to EFI REST client. User has to type cast RestExConfigData
+ to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver instances, the type of configuration
+ is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In this case, the format of
+ returning data could be non industrial. Instead, the format of configuration data is system/platform
+ specific definition such as BMC mechanism used in EFI REST EX driver instance. EFI REST client and
+ EFI REST EX driver instance have to refer to the specific system /platform spec which is out of UEFI scope.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[out] RestExConfigData Pointer to receive a pointer to EFI_REST_EX_CONFIG_DATA.
+ The memory allocated for configuration data should be freed
+ by caller. See Related Definitions for the details.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in successfully.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be
+ executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetModeData (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData
+ );
+
+/**
+ This function is used to configure EFI REST EX child instance.
+
+ This function is used to configure the setting of underlying protocol of REST EX child
+ instance. The type of configuration is according to the implementation of EFI REST EX
+ driver instance. For example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol
+ as the undying protocol to communicate with REST service. The type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same format with EFI_HTTP_CONFIG_DATA.
+ Akin to HTTP configuration, REST EX child instance can be configure to use different HTTP
+ local access point for the data transmission. Multiple REST clients may use different
+ configuration of HTTP to distinguish themselves, such as to use the different TCP port.
+ For those non HTTP-aware REST EX driver instance, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the non industrial standard.
+ Instead, the format of configuration data is system/platform specific definition such as BMC.
+ In this case, EFI REST client and EFI REST EX driver instance have to refer to the specific
+ system/platform spec which is out of the UEFI scope. Besides GetService()function, no other
+ EFI REST EX functions can be executed by this instance until Configure()is executed and returns
+ successfully. All other functions must returns EFI_NOT_READY if this instance is not configured
+ yet. Set RestExConfigData to NULL means to put EFI REST EX child instance into the unconfigured
+ state.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA. See Related Definitions in
+ GetModeData() protocol interface.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in successfully.
+ @retval EFI_DEVICE_ERROR Configuration for this REST EX child instance is failed with the given
+ EFI_REST_EX_CONFIG_DATA.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExConfigure (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_REST_EX_CONFIG_DATA RestExConfigData
+ );
+
+/**
+ This function sends REST request to REST service and signal caller's event asynchronously when
+ the final response is received by REST EX Protocol driver instance.
+
+ The essential design of this function is to handle asynchronous send/receive implicitly according
+ to REST service asynchronous request mechanism. Caller will get the notification once the response
+ is returned from REST service.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous asynchronous request associated with the
+ corresponding RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol instance uses to notify REST client
+ the status of response of asynchronous REST request. See related definition
+ of EFI_REST_EX_TOKEN.
+ @param[in] TimeOutInMilliSeconds The pointer to the timeout in milliseconds which REST EX Protocol driver
+ instance refers as the duration to drop asynchronous REST request. NULL
+ pointer means no timeout for this REST request. REST EX Protocol driver
+ signals caller's event with EFI_STATUS set to EFI_TIMEOUT in RestExToken
+ if REST EX Protocol can't get the response from REST service within
+ TimeOutInMilliSeconds.
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_TIMEOUT Asynchronous REST request is not established and timeout is expired.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExAyncSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken,
+ IN UINTN *TimeOutInMilliSeconds OPTIONAL
+ );
+
+/**
+ This function sends REST request to a REST Event service and signals caller's event
+ token asynchronously when the URI resource change event is received by REST EX
+ Protocol driver instance.
+
+ The essential design of this function is to monitor event implicitly according to
+ REST service event service mechanism. Caller will get the notification if certain
+ resource is changed.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous event service associated with the corresponding
+ RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol driver instance uses to notify REST client
+ the URI resource which monitored by REST client has been changed. See the related
+ definition of EFI_REST_EX_TOKEN in EFI_REST_EX_PROTOCOL.AsyncSendReceive().
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled or event subscription has been
+ delete from service.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExEventService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken
+ );
+/**
+ Create a new TLS session becuase the previous on is closed.
+ status.
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI Errors Other errors.
+
+**/
+EFI_STATUS
+ResetHttpTslSession (
+ IN RESTEX_INSTANCE *Instance
+);
+
+
+/**
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.
+
+ @param[in] Entry The entry to be removed.
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
+
+ @retval EFI_SUCCESS The entry has been removed successfully.
+ @retval Others Fail to remove the entry.
+
+**/
+EFI_STATUS
+EFIAPI
+RestExDestroyChildEntryInHandleBuffer (
+ IN LIST_ENTRY *Entry,
+ IN VOID *Context
+ );
+
+/**
+ Destroy the RestEx instance and recycle the resources.
+
+ @param[in] Instance The pointer to the RestEx instance.
+
+**/
+VOID
+RestExDestroyInstance (
+ IN RESTEX_INSTANCE *Instance
+ );
+
+/**
+ Create the RestEx instance and initialize it.
+
+ @param[in] Service The pointer to the RestEx service.
+ @param[out] Instance The pointer to the RestEx instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
+ @retval EFI_SUCCESS The RestEx instance is created.
+
+**/
+EFI_STATUS
+RestExCreateInstance (
+ IN RESTEX_SERVICE *Service,
+ OUT RESTEX_INSTANCE **Instance
+ );
+
+
+/**
+ Release all the resource used the RestEx service binding instance.
+
+ @param[in] RestExSb The RestEx service binding instance.
+
+**/
+VOID
+RestExDestroyService (
+ IN RESTEX_SERVICE *RestExSb
+ );
+
+/**
+ Create then initialize a RestEx service binding instance.
+
+ @param[in] Controller The controller to install the RestEx service
+ binding on.
+ @param[in] Image The driver binding image of the RestEx driver.
+ @param[out] Service The variable to receive the created service
+ binding instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.
+ @retval EFI_SUCCESS The service instance is created for the controller.
+
+**/
+EFI_STATUS
+RestExCreateService (
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Image,
+ OUT RESTEX_SERVICE **Service
+ );
+
+/**
+ 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.
+
+ @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 Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ );
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCES The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
+ the child
+ @retval other The child handle was not created
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ );
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Handle of the child to destroy
+
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c
new file mode 100644
index 00000000..418fac29
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c
@@ -0,0 +1,735 @@
+/** @file
+ Implementation of Redfish EFI_REST_EX_PROTOCOL interfaces.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include "RedfishRestExInternal.h"
+
+EFI_REST_EX_PROTOCOL mRedfishRestExProtocol = {
+ RedfishRestExSendReceive,
+ RedfishRestExGetServiceTime,
+ RedfishRestExGetService,
+ RedfishRestExGetModeData,
+ RedfishRestExConfigure,
+ RedfishRestExAyncSendReceive,
+ RedfishRestExEventService
+};
+
+/**
+ Provides a simple HTTP-like interface to send and receive resources from a REST service.
+
+ The SendReceive() function sends an HTTP request to this REST service, and returns a
+ response when the data is retrieved from the service. RequestMessage contains the HTTP
+ request to the REST resource identified by RequestMessage.Request.Url. The
+ ResponseMessage is the returned HTTP response for that request, including any HTTP
+ status.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[out] ResponseMessage Pointer to the HTTP response data obtained for this requested.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage are NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_ACCESS_DENIED HTTP method is not allowed on this URL.
+ @retval EFI_BAD_BUFFER_SIZE The payload is to large to be handled on server side.
+ @retval EFI_UNSUPPORTED Unsupported HTTP response.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ OUT EFI_HTTP_MESSAGE *ResponseMessage
+ )
+{
+ EFI_STATUS Status;
+ RESTEX_INSTANCE *Instance;
+ HTTP_IO_RESPONSE_DATA *ResponseData;
+ UINTN TotalReceivedSize;
+ UINTN Index;
+ LIST_ENTRY *ChunkListLink;
+ HTTP_IO_CHUNKS *ThisChunk;
+ BOOLEAN CopyChunkData;
+ BOOLEAN MediaPresent;
+ EFI_HTTP_HEADER *PreservedRequestHeaders;
+ BOOLEAN ItsWrite;
+ BOOLEAN IsGetChunkedTransfer;
+ HTTP_IO_SEND_CHUNK_PROCESS SendChunkProcess;
+ HTTP_IO_SEND_NON_CHUNK_PROCESS SendNonChunkProcess;
+ EFI_HTTP_MESSAGE ChunkTransferRequestMessage;
+
+ Status = EFI_SUCCESS;
+ ResponseData = NULL;
+ IsGetChunkedTransfer = FALSE;
+ SendChunkProcess = HttpIoSendChunkNone;
+ SendNonChunkProcess = HttpIoSendNonChunkNone;
+
+ //
+ // Validate the parameters
+ //
+ if ((This == NULL) || (RequestMessage == NULL) || ResponseMessage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = RESTEX_INSTANCE_FROM_THIS (This);
+
+ //
+ // Check Media Status.
+ //
+ MediaPresent = TRUE;
+ NetLibDetectMedia (Instance->Service->ControllerHandle, &MediaPresent);
+ if (!MediaPresent) {
+ DEBUG ((DEBUG_INFO, "RedfishRestExSendReceive(): No MediaPresent.\n"));
+ return EFI_NO_MEDIA;
+ }
+
+ DEBUG ((DEBUG_INFO, "\nRedfishRestExSendReceive():\n"));
+ DEBUG ((DEBUG_INFO, "*** Perform HTTP Request Method - %d, URL: %s\n", RequestMessage->Data.Request->Method, RequestMessage->Data.Request->Url));
+
+ //
+ // Add header "Expect" to server, only for URL write.
+ //
+ Status = RedfishHttpAddExpectation (This, RequestMessage, &PreservedRequestHeaders, &ItsWrite);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (ItsWrite == TRUE) {
+ if (RequestMessage->BodyLength > HTTP_IO_MAX_SEND_PAYLOAD) {
+ //
+ // Send chunked transfer.
+ //
+ SendChunkProcess ++;
+ CopyMem ((VOID *)&ChunkTransferRequestMessage, (VOID *)RequestMessage, sizeof (EFI_HTTP_MESSAGE));
+ } else {
+ SendNonChunkProcess ++;
+ }
+ }
+ReSendRequest:;
+ //
+ // Send out the request to REST service.
+ //
+ if (ItsWrite == TRUE) {
+ //
+ // This is write to URI
+ //
+ if (SendChunkProcess > HttpIoSendChunkNone) {
+ //
+ // This is chunk transfer for writing large payload.
+ // Send request header first and then handle the
+ // following request message body using chunk transfer.
+ //
+ do {
+ Status = HttpIoSendChunkedTransfer(
+ &(Instance->HttpIo),
+ &SendChunkProcess,
+ &ChunkTransferRequestMessage
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ } while (SendChunkProcess == HttpIoSendChunkContent || SendChunkProcess == HttpIoSendChunkEndChunk);
+ } else {
+ //
+ // This is the non-chunk transfer, send request header first and then
+ // handle the following request message body using chunk transfer.
+ //
+ Status = HttpIoSendRequest(
+ &(Instance->HttpIo),
+ (SendNonChunkProcess == HttpIoSendNonChunkContent)? NULL: RequestMessage->Data.Request,
+ (SendNonChunkProcess == HttpIoSendNonChunkContent)? 0: RequestMessage->HeaderCount,
+ (SendNonChunkProcess == HttpIoSendNonChunkContent)? NULL: RequestMessage->Headers,
+ (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent)? 0: RequestMessage->BodyLength,
+ (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent)? NULL: RequestMessage->Body
+ );
+ }
+ } else {
+ //
+ // This is read from URI.
+ //
+ Status = HttpIoSendRequest(
+ &(Instance->HttpIo),
+ RequestMessage->Data.Request,
+ RequestMessage->HeaderCount,
+ RequestMessage->Headers,
+ RequestMessage->BodyLength,
+ RequestMessage->Body
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ //
+ // ResponseMessage->Data.Response is to indicate whether to receive the HTTP header or not.
+ // ResponseMessage->BodyLength/ResponseMessage->Body are to indicate whether to receive the response body or not.
+ // Clean the previous buffers and all of them will be allocated later according to the actual situation.
+ //
+ if (ResponseMessage->Data.Response != NULL) {
+ FreePool(ResponseMessage->Data.Response);
+ ResponseMessage->Data.Response = NULL;
+ }
+
+ ResponseMessage->BodyLength = 0;
+ if (ResponseMessage->Body != NULL) {
+ FreePool(ResponseMessage->Body);
+ ResponseMessage->Body = NULL;
+ }
+
+ //
+ // Use zero BodyLength to only receive the response headers.
+ //
+ ResponseData = AllocateZeroPool (sizeof(HTTP_IO_RESPONSE_DATA));
+ if (ResponseData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ DEBUG ((DEBUG_INFO, "Receiving HTTP response and headers...\n"));
+ Status = RedfishCheckHttpReceiveStatus (
+ Instance,
+ HttpIoRecvResponse (
+ &(Instance->HttpIo),
+ TRUE,
+ ResponseData
+ )
+ );
+ if (Status == EFI_NOT_READY) {
+ goto ReSendRequest;
+ } else if (Status == EFI_DEVICE_ERROR) {
+ goto ON_EXIT;
+ }
+ //
+ // Restore the headers if it ever changed in RedfishHttpAddExpectation().
+ //
+ if (RequestMessage->Headers != PreservedRequestHeaders) {
+ FreePool (RequestMessage->Headers);
+ RequestMessage->Headers = PreservedRequestHeaders; // Restore headers before we adding "Expect".
+ RequestMessage->HeaderCount --; // Minus one header count for "Expect".
+ }
+
+ DEBUG ((DEBUG_INFO, "HTTP Response StatusCode - %d:", ResponseData->Response.StatusCode));
+ if (ResponseData->Response.StatusCode == HTTP_STATUS_200_OK) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_200_OK\n"));
+
+ if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
+ DEBUG ((DEBUG_INFO, "This is chunk transfer, start to send all chunks.", ResponseData->Response.StatusCode));
+ SendChunkProcess ++;
+ goto ReSendRequest;
+ }
+ } else if (ResponseData->Response.StatusCode == HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE\n"));
+
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto ON_EXIT;
+ } else if (ResponseData->Response.StatusCode == HTTP_STATUS_405_METHOD_NOT_ALLOWED){
+ DEBUG ((DEBUG_ERROR, "HTTP_STATUS_405_METHOD_NOT_ALLOWED\n"));
+
+ Status = EFI_ACCESS_DENIED;
+ goto ON_EXIT;
+ } else if (ResponseData->Response.StatusCode == HTTP_STATUS_400_BAD_REQUEST) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_400_BAD_REQUEST\n"));
+ if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
+ DEBUG ((DEBUG_INFO, "Bad request may caused by zero length chunk. Try to send all chunks...\n"));
+ SendChunkProcess ++;
+ goto ReSendRequest;
+ }
+ } else if (ResponseData->Response.StatusCode == HTTP_STATUS_100_CONTINUE) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE\n"));
+ if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
+ //
+ // We get HTTP_STATUS_100_CONTINUE to send the body using chunk transfer.
+ //
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE for chunk transfer...\n"));
+ SendChunkProcess ++;
+ goto ReSendRequest;
+ }
+ if (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE for non chunk transfer...\n"));
+ SendNonChunkProcess ++;
+ goto ReSendRequest;
+ }
+ //
+ // It's the REST protocol's responsibility to handle the interim HTTP response (e.g. 100 Continue Informational),
+ // and return the final response content to the caller.
+ //
+ if (ResponseData->Headers != NULL && ResponseData->HeaderCount != 0) {
+ FreePool (ResponseData->Headers);
+ }
+ ZeroMem (ResponseData, sizeof(HTTP_IO_RESPONSE_DATA));
+ Status = HttpIoRecvResponse (
+ &(Instance->HttpIo),
+ TRUE,
+ ResponseData
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "This HTTP Status is not handled!\n"));
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Ready to return the StatusCode, Header info and BodyLength.
+ //
+ ResponseMessage->Data.Response = AllocateZeroPool (sizeof (EFI_HTTP_RESPONSE_DATA));
+ if (ResponseMessage->Data.Response == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ ResponseMessage->Data.Response->StatusCode = ResponseData->Response.StatusCode;
+ ResponseMessage->HeaderCount = ResponseData->HeaderCount;
+ ResponseMessage->Headers = ResponseData->Headers;
+
+ //
+ // Get response message body.
+ //
+ if (ResponseMessage->HeaderCount > 0) {
+ Status = HttpIoGetContentLength (ResponseMessage->HeaderCount, ResponseMessage->Headers, &ResponseMessage->BodyLength);
+ if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
+ goto ON_EXIT;
+ }
+
+ if (Status == EFI_NOT_FOUND) {
+ ASSERT (ResponseMessage->BodyLength == 0);
+ }
+
+ if (ResponseMessage->BodyLength == 0) {
+ //
+ // Check if Chunked Transfer Coding.
+ //
+ Status = HttpIoGetChunkedTransferContent (
+ &(Instance->HttpIo),
+ ResponseMessage->HeaderCount,
+ ResponseMessage->Headers,
+ &ChunkListLink,
+ &ResponseMessage->BodyLength
+ );
+ if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
+ goto ON_EXIT;
+ }
+ if (Status == EFI_SUCCESS &&
+ ChunkListLink != NULL &&
+ !IsListEmpty(ChunkListLink) &&
+ ResponseMessage->BodyLength != 0) {
+ IsGetChunkedTransfer = TRUE;
+ //
+ // Copy data to Message body.
+ //
+ CopyChunkData = TRUE;
+ ResponseMessage->Body = AllocateZeroPool (ResponseMessage->BodyLength);
+ if (ResponseMessage->Body == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ CopyChunkData = FALSE;
+ }
+ Index = 0;
+ while (!IsListEmpty(ChunkListLink)) {
+ ThisChunk = (HTTP_IO_CHUNKS *)GetFirstNode (ChunkListLink);
+ if (CopyChunkData) {
+ CopyMem(((UINT8 *)ResponseMessage->Body + Index), (UINT8 *)ThisChunk->Data, ThisChunk->Length);
+ Index += ThisChunk->Length;
+ }
+ RemoveEntryList (&ThisChunk->NextChunk);
+ FreePool ((VOID *)ThisChunk->Data);
+ FreePool ((VOID *)ThisChunk);
+ };
+ FreePool ((VOID *)ChunkListLink);
+ }
+ }
+ Status = EFI_SUCCESS;
+ }
+
+ //
+ // Ready to return the Body from REST service if have any.
+ //
+ if (ResponseMessage->BodyLength > 0 && !IsGetChunkedTransfer) {
+ ResponseData->HeaderCount = 0;
+ ResponseData->Headers = NULL;
+
+ ResponseMessage->Body = AllocateZeroPool (ResponseMessage->BodyLength);
+ if (ResponseMessage->Body == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ //
+ // Only receive the Body.
+ //
+ TotalReceivedSize = 0;
+ while (TotalReceivedSize < ResponseMessage->BodyLength) {
+ ResponseData->BodyLength = ResponseMessage->BodyLength - TotalReceivedSize;
+ ResponseData->Body = (CHAR8 *) ResponseMessage->Body + TotalReceivedSize;
+ Status = HttpIoRecvResponse (
+ &(Instance->HttpIo),
+ FALSE,
+ ResponseData
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ TotalReceivedSize += ResponseData->BodyLength;
+ }
+ DEBUG ((DEBUG_INFO, "Total of lengh of Response :%d\n", TotalReceivedSize));
+ }
+ DEBUG ((DEBUG_INFO, "RedfishRestExSendReceive()- EFI_STATUS: %r\n", Status));
+
+ON_EXIT:
+
+ if (ResponseData != NULL) {
+ FreePool (ResponseData);
+ }
+
+ if (EFI_ERROR (Status)) {
+ if (ResponseMessage->Data.Response != NULL) {
+ FreePool (ResponseMessage->Data.Response);
+ ResponseMessage->Data.Response = NULL;
+ }
+
+ if (ResponseMessage->Body != NULL) {
+ FreePool (ResponseMessage->Body);
+ ResponseMessage->Body = NULL;
+ }
+ }
+ return Status;
+}
+
+/**
+ Obtain the current time from this REST service instance.
+
+ The GetServiceTime() function is an optional interface to obtain the current time from
+ this REST service instance. If this REST service does not support to retrieve the time,
+ this function returns EFI_UNSUPPORTED. This function must returns EFI_UNSUPPORTED if
+ EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from GetService() is
+ EFI_REST_EX_SERVICE_UNSPECIFIC.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] Time A pointer to storage to receive a snapshot of the current time of
+ the REST service.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This or Time are NULL.
+ @retval EFI_UNSUPPORTED The RESTful service does not support returning the time.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must
+ be executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetServiceTime (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_TIME *Time
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function returns the information of REST service provided by this EFI REST EX driver instance.
+
+ The information such as the type of REST service and the access mode of REST EX driver instance
+ (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO structure. For the vendor-specific
+ REST service, vendor-specific REST service information is returned in VendorSpecifcData.
+ REST EX driver designer is well know what REST service this REST EX driver instance intends to
+ communicate with. The designer also well know this driver instance is used to talk to BMC through
+ specific platform mechanism or talk to REST server through UEFI HTTP protocol. REST EX driver is
+ responsible to fill up the correct information in EFI_REST_EX_SERVICE_INFO. EFI_REST_EX_SERVICE_INFO
+ is referred by EFI REST clients to pickup the proper EFI REST EX driver instance to get and set resource.
+ GetService() is a basic and mandatory function which must be able to use even Configure() is not invoked
+ in previously.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] RestExServiceInfo Pointer to receive a pointer to EFI_REST_EX_SERVICE_INFO structure. The
+ format of EFI_REST_EX_SERVICE_INFO is version controlled for the future
+ extension. The version of EFI_REST_EX_SERVICE_INFO structure is returned
+ in the header within this structure. EFI REST client refers to the correct
+ format of structure according to the version number. The pointer to
+ EFI_REST_EX_SERVICE_INFO is a memory block allocated by EFI REST EX driver
+ instance. That is caller's responsibility to free this memory when this
+ structure is no longer needed. Refer to Related Definitions below for the
+ definitions of EFI_REST_EX_SERVICE_INFO structure.
+
+ @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in RestExServiceInfo. This function
+ is not supported in this REST EX Protocol driver instance.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo
+ )
+{
+ EFI_TPL OldTpl;
+ RESTEX_INSTANCE *Instance;
+ EFI_REST_EX_SERVICE_INFO *ServiceInfo;
+
+ ServiceInfo = NULL;
+
+ if (This == NULL || RestExServiceInfo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance = RESTEX_INSTANCE_FROM_THIS (This);
+
+ ServiceInfo = AllocateZeroPool (sizeof (EFI_REST_EX_SERVICE_INFO));
+ if (ServiceInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (ServiceInfo, &(Instance->Service->RestExServiceInfo), sizeof (EFI_REST_EX_SERVICE_INFO));
+
+ *RestExServiceInfo = ServiceInfo;
+
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function returns operational configuration of current EFI REST EX child instance.
+
+ This function returns the current configuration of EFI REST EX child instance. The format of
+ operational configuration depends on the implementation of EFI REST EX driver instance. For
+ example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol as the undying protocol
+ to communicate with REST service. In this case, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService(). EFI_HTTP_CONFIG_DATA is used as EFI REST
+ EX configuration format and returned to EFI REST client. User has to type cast RestExConfigData
+ to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver instances, the type of configuration
+ is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In this case, the format of
+ returning data could be non industrial. Instead, the format of configuration data is system/platform
+ specific definition such as BMC mechanism used in EFI REST EX driver instance. EFI REST client and
+ EFI REST EX driver instance have to refer to the specific system /platform spec which is out of UEFI scope.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[out] RestExConfigData Pointer to receive a pointer to EFI_REST_EX_CONFIG_DATA.
+ The memory allocated for configuration data should be freed
+ by caller. See Related Definitions for the details.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in successfully.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be
+ executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetModeData (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function is used to configure EFI REST EX child instance.
+
+ This function is used to configure the setting of underlying protocol of REST EX child
+ instance. The type of configuration is according to the implementation of EFI REST EX
+ driver instance. For example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol
+ as the undying protocol to communicate with REST service. The type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same format with EFI_HTTP_CONFIG_DATA.
+ Akin to HTTP configuration, REST EX child instance can be configure to use different HTTP
+ local access point for the data transmission. Multiple REST clients may use different
+ configuration of HTTP to distinguish themselves, such as to use the different TCP port.
+ For those non HTTP-aware REST EX driver instance, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the non industrial standard.
+ Instead, the format of configuration data is system/platform specific definition such as BMC.
+ In this case, EFI REST client and EFI REST EX driver instance have to refer to the specific
+ system/platform spec which is out of the UEFI scope. Besides GetService()function, no other
+ EFI REST EX functions can be executed by this instance until Configure()is executed and returns
+ successfully. All other functions must returns EFI_NOT_READY if this instance is not configured
+ yet. Set RestExConfigData to NULL means to put EFI REST EX child instance into the unconfigured
+ state.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA. See Related Definitions in
+ GetModeData() protocol interface.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in successfully.
+ @retval EFI_DEVICE_ERROR Configuration for this REST EX child instance is failed with the given
+ EFI_REST_EX_CONFIG_DATA.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExConfigure (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_REST_EX_CONFIG_DATA RestExConfigData
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+ RESTEX_INSTANCE *Instance;
+
+ EFI_HTTP_CONFIG_DATA *HttpConfigData;
+
+ Status = EFI_SUCCESS;
+ HttpConfigData = NULL;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance = RESTEX_INSTANCE_FROM_THIS (This);
+
+ if (RestExConfigData == NULL) {
+ //
+ // Set RestExConfigData to NULL means to put EFI REST EX child instance into the unconfigured state.
+ //
+ HttpIoDestroyIo (&(Instance->HttpIo));
+
+ if (Instance->ConfigData != NULL) {
+ if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node != NULL) {
+ FreePool(((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node);
+ }
+ FreePool(Instance->ConfigData);
+ Instance->ConfigData = NULL;
+ }
+
+ Instance->State = RESTEX_STATE_UNCONFIGED;
+ } else {
+ HttpConfigData = &((EFI_REST_EX_HTTP_CONFIG_DATA *)RestExConfigData)->HttpConfigData;
+ Status = Instance->HttpIo.Http->Configure (Instance->HttpIo.Http, HttpConfigData);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ Instance->HttpIo.Timeout = ((EFI_REST_EX_HTTP_CONFIG_DATA *)RestExConfigData)->SendReceiveTimeout;
+
+ Instance->ConfigData = AllocateZeroPool (sizeof (EFI_REST_EX_HTTP_CONFIG_DATA));
+ if (Instance->ConfigData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ CopyMem (Instance->ConfigData, RestExConfigData, sizeof (EFI_REST_EX_HTTP_CONFIG_DATA));
+ if (HttpConfigData->LocalAddressIsIPv6 == TRUE) {
+ ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv6Node = AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT));
+ if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv6Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ CopyMem (
+ ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv6Node,
+ HttpConfigData->AccessPoint.IPv6Node,
+ sizeof (EFI_HTTPv6_ACCESS_POINT)
+ );
+ } else {
+ ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node = AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT));
+ if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ CopyMem (
+ ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node,
+ HttpConfigData->AccessPoint.IPv4Node,
+ sizeof (EFI_HTTPv4_ACCESS_POINT)
+ );
+ }
+ Instance->State = RESTEX_STATE_CONFIGED;
+ }
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ This function sends REST request to REST service and signal caller's event asynchronously when
+ the final response is received by REST EX Protocol driver instance.
+
+ The essential design of this function is to handle asynchronous send/receive implicitly according
+ to REST service asynchronous request mechanism. Caller will get the notification once the response
+ is returned from REST service.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous asynchronous request associated with the
+ corresponding RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol instance uses to notify REST client
+ the status of response of asynchronous REST request. See related definition
+ of EFI_REST_EX_TOKEN.
+ @param[in] TimeOutInMilliSeconds The pointer to the timeout in milliseconds which REST EX Protocol driver
+ instance refers as the duration to drop asynchronous REST request. NULL
+ pointer means no timeout for this REST request. REST EX Protocol driver
+ signals caller's event with EFI_STATUS set to EFI_TIMEOUT in RestExToken
+ if REST EX Protocol can't get the response from REST service within
+ TimeOutInMilliSeconds.
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_TIMEOUT Asynchronous REST request is not established and timeout is expired.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExAyncSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken,
+ IN UINTN *TimeOutInMilliSeconds OPTIONAL
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function sends REST request to a REST Event service and signals caller's event
+ token asynchronously when the URI resource change event is received by REST EX
+ Protocol driver instance.
+
+ The essential design of this function is to monitor event implicitly according to
+ REST service event service mechanism. Caller will get the notification if certain
+ resource is changed.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous event service associated with the corresponding
+ RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol driver instance uses to notify REST client
+ the URI resource which monitored by REST client has been changed. See the related
+ definition of EFI_REST_EX_TOKEN in EFI_REST_EX_PROTOCOL.AsyncSendReceive().
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled or event subscription has been
+ delete from service.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExEventService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.c
new file mode 100644
index 00000000..527739d8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.c
@@ -0,0 +1,586 @@
+/** @file
+
+ The implementation of EFI REST Resource JSON to C structure convertor
+ Protocol.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Protocol/RestJsonStructure.h>
+#include "RestJsonStructureInternal.h"
+
+LIST_ENTRY mRestJsonStructureList;
+EFI_HANDLE mProtocolHandle;
+
+/**
+ This function registers Restful resource interpreter for the
+ specific schema.
+
+ @param[in] This This is the EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] JsonStructureSupported The type and version of REST JSON resource which this converter
+ supports.
+ @param[in] ToStructure The function to convert REST JSON resource to structure.
+ @param[in] ToJson The function to convert REST JSON structure to JSON in text format.
+ @param[in] DestroyStructure Destroy REST JSON structure returned in ToStructure() function.
+
+ @retval EFI_SUCCESS Register successfully.
+ @retval Others Fail to register.
+
+**/
+EFI_STATUS
+EFIAPI
+RestJsonStructureRegister (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN EFI_REST_JSON_STRUCTURE_SUPPORTED *JsonStructureSupported,
+ IN EFI_REST_JSON_STRUCTURE_TO_STRUCTURE ToStructure,
+ IN EFI_REST_JSON_STRUCTURE_TO_JSON ToJson,
+ IN EFI_REST_JSON_STRUCTURE_DESTORY_STRUCTURE DestroyStructure
+)
+{
+ UINTN NumberOfNS;
+ UINTN Index;
+ LIST_ENTRY *ThisList;
+ REST_JSON_STRUCTURE_INSTANCE *Instance;
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *CloneSupportedInterpId;
+ EFI_REST_JSON_STRUCTURE_SUPPORTED *ThisSupportedInterp;
+
+ if (This == NULL ||
+ ToStructure == NULL ||
+ ToJson == NULL ||
+ DestroyStructure == NULL ||
+ JsonStructureSupported == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check how many name space interpreter can interpret.
+ //
+ ThisList = &JsonStructureSupported->NextSupportedRsrcInterp;
+ NumberOfNS = 1;
+ while (TRUE) {
+ if (ThisList->ForwardLink == &JsonStructureSupported->NextSupportedRsrcInterp) {
+ break;
+ } else {
+ ThisList = ThisList->ForwardLink;
+ NumberOfNS ++;
+ }
+ };
+
+ Instance =
+ (REST_JSON_STRUCTURE_INSTANCE *)AllocateZeroPool (sizeof (REST_JSON_STRUCTURE_INSTANCE) + NumberOfNS * sizeof (EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER));
+ if (Instance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ InitializeListHead (&Instance->NextRestJsonStructureInstance);
+ Instance->NumberOfNameSpaceToConvert = NumberOfNS;
+ Instance->SupportedRsrcIndentifier = (EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *)((REST_JSON_STRUCTURE_INSTANCE *)Instance + 1);
+ //
+ // Copy supported resource identifer interpreter.
+ //
+ CloneSupportedInterpId = Instance->SupportedRsrcIndentifier;
+ ThisSupportedInterp = JsonStructureSupported;
+ for (Index = 0; Index < NumberOfNS; Index ++) {
+ CopyMem ((VOID *)CloneSupportedInterpId, (VOID *)&ThisSupportedInterp->RestResourceInterp, sizeof (EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER));
+ ThisSupportedInterp = (EFI_REST_JSON_STRUCTURE_SUPPORTED *)ThisSupportedInterp->NextSupportedRsrcInterp.ForwardLink;
+ CloneSupportedInterpId ++;
+ }
+ Instance->JsonToStructure = ToStructure;
+ Instance->StructureToJson = ToJson;
+ Instance->DestroyStructure = DestroyStructure;
+ InsertTailList (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
+ return EFI_SUCCESS;
+}
+
+/**
+ This function check if this interpreter instance support the given namesapce.
+
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] InterpreterInstance REST_JSON_STRUCTURE_INSTANCE
+ @param[in] RsrcTypeIdentifier Resource type identifier.
+ @param[in] ResourceRaw Given Restful resource.
+ @param[out] RestJSonHeader Property interpreted from given ResourceRaw.
+
+ @retval EFI_SUCCESS
+ @retval Others.
+
+**/
+EFI_STATUS
+InterpreterInstanceToStruct (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN REST_JSON_STRUCTURE_INSTANCE *InterpreterInstance,
+ IN EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *RsrcTypeIdentifier OPTIONAL,
+ IN CHAR8 *ResourceRaw,
+ OUT EFI_REST_JSON_STRUCTURE_HEADER **RestJSonHeader
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *ThisSupportedRsrcTypeId;
+
+ if (This == NULL ||
+ InterpreterInstance == NULL ||
+ ResourceRaw == NULL ||
+ RestJSonHeader == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (RsrcTypeIdentifier == NULL) {
+ //
+ // No resource type identifier, send to intepreter anyway.
+ // Interpreter may recognize this resource.
+ //
+ Status = InterpreterInstance->JsonToStructure (
+ This,
+ NULL,
+ ResourceRaw,
+ RestJSonHeader
+ );
+ } else {
+ //
+ // Check if the namesapce and version is supported by this interpreter.
+ //
+ ThisSupportedRsrcTypeId = InterpreterInstance->SupportedRsrcIndentifier;
+ for (Index = 0; Index < InterpreterInstance->NumberOfNameSpaceToConvert; Index ++){
+ if (AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.ResourceTypeName,
+ ThisSupportedRsrcTypeId->NameSpace.ResourceTypeName) == 0){
+ if ((RsrcTypeIdentifier->NameSpace.MajorVersion == NULL) &&
+ (RsrcTypeIdentifier->NameSpace.MinorVersion == NULL) &&
+ (RsrcTypeIdentifier->NameSpace.ErrataVersion == NULL)
+ ) {
+ //
+ // Don't check version of this resource type identifier.
+ //
+ Status = InterpreterInstance->JsonToStructure (
+ This,
+ RsrcTypeIdentifier,
+ ResourceRaw,
+ RestJSonHeader
+ );
+ break;
+ } else {
+ //
+ // Check version.
+ //
+ if ((AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.MajorVersion,
+ ThisSupportedRsrcTypeId->NameSpace.MajorVersion) == 0) &&
+ (AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.MinorVersion,
+ ThisSupportedRsrcTypeId->NameSpace.MinorVersion) == 0) &&
+ (AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.ErrataVersion,
+ ThisSupportedRsrcTypeId->NameSpace.ErrataVersion) == 0)) {
+ Status = InterpreterInstance->JsonToStructure (
+ This,
+ RsrcTypeIdentifier,
+ ResourceRaw,
+ RestJSonHeader
+ );
+ break;
+ }
+ }
+ }
+ ThisSupportedRsrcTypeId ++;
+ }
+ }
+ return Status;
+}
+/**
+ This function converts JSON C structure to JSON property.
+
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] InterpreterInstance REST_JSON_STRUCTURE_INSTANCE
+ @param[in] RestJSonHeader Resource type identifier.
+ @param[out] ResourceRaw Output in JSON text format.
+
+ @retval EFI_SUCCESS
+ @retval Others.
+
+**/
+EFI_STATUS
+InterpreterEfiStructToInstance (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN REST_JSON_STRUCTURE_INSTANCE *InterpreterInstance,
+ IN EFI_REST_JSON_STRUCTURE_HEADER *RestJSonHeader,
+ OUT CHAR8 **ResourceRaw
+)
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *ThisSupportedRsrcTypeId;
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *RsrcTypeIdentifier;
+
+ if (This == NULL ||
+ InterpreterInstance == NULL ||
+ RestJSonHeader == NULL ||
+ ResourceRaw == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ RsrcTypeIdentifier = &RestJSonHeader->JsonRsrcIdentifier;
+ if (RsrcTypeIdentifier == NULL ||
+ RsrcTypeIdentifier->NameSpace.ResourceTypeName == NULL ||
+ RsrcTypeIdentifier->NameSpace.MajorVersion == NULL ||
+ RsrcTypeIdentifier->NameSpace.MinorVersion == NULL ||
+ RsrcTypeIdentifier->NameSpace.ErrataVersion == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if the namesapce and version is supported by this interpreter.
+ //
+ Status = EFI_UNSUPPORTED;
+ ThisSupportedRsrcTypeId = InterpreterInstance->SupportedRsrcIndentifier;
+ for (Index = 0; Index < InterpreterInstance->NumberOfNameSpaceToConvert; Index ++){
+ if (AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.ResourceTypeName,
+ ThisSupportedRsrcTypeId->NameSpace.ResourceTypeName) == 0){
+ //
+ // Check version.
+ //
+ if ((AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.MajorVersion,
+ ThisSupportedRsrcTypeId->NameSpace.MajorVersion) == 0) &&
+ (AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.MinorVersion,
+ ThisSupportedRsrcTypeId->NameSpace.MinorVersion) == 0) &&
+ (AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.ErrataVersion,
+ ThisSupportedRsrcTypeId->NameSpace.ErrataVersion) == 0)) {
+ Status = InterpreterInstance->StructureToJson (
+ This,
+ RestJSonHeader,
+ ResourceRaw
+ );
+ break;
+ }
+ }
+ ThisSupportedRsrcTypeId ++;
+ }
+ return Status;
+}
+
+/**
+ This function destory REST property structure.
+
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] InterpreterInstance REST_JSON_STRUCTURE_INSTANCE
+ @param[in] RestJSonHeader Property interpreted from given ResourceRaw.
+
+ @retval EFI_SUCCESS
+ @retval Others.
+
+**/
+EFI_STATUS
+InterpreterInstanceDestoryJsonStruct (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN REST_JSON_STRUCTURE_INSTANCE *InterpreterInstance,
+ IN EFI_REST_JSON_STRUCTURE_HEADER *RestJSonHeader
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *ThisSupportedRsrcTypeId;
+
+ if (This == NULL ||
+ InterpreterInstance == NULL ||
+ RestJSonHeader == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ //
+ // Check if the namesapce and version is supported by this interpreter.
+ //
+ ThisSupportedRsrcTypeId = InterpreterInstance->SupportedRsrcIndentifier;
+ for (Index = 0; Index < InterpreterInstance->NumberOfNameSpaceToConvert; Index ++){
+ if (AsciiStrCmp (
+ RestJSonHeader->JsonRsrcIdentifier.NameSpace.ResourceTypeName,
+ ThisSupportedRsrcTypeId->NameSpace.ResourceTypeName) == 0) {
+ if ((RestJSonHeader->JsonRsrcIdentifier.NameSpace.MajorVersion == NULL) &&
+ (RestJSonHeader->JsonRsrcIdentifier.NameSpace.MinorVersion == NULL) &&
+ (RestJSonHeader->JsonRsrcIdentifier.NameSpace.ErrataVersion == NULL)
+ ) {
+ //
+ // Don't check version of this resource type identifier.
+ //
+ Status = InterpreterInstance->DestroyStructure (
+ This,
+ RestJSonHeader
+ );
+ break;
+ } else {
+ //
+ // Check version.
+ //
+ if ((AsciiStrCmp (
+ RestJSonHeader->JsonRsrcIdentifier.NameSpace.MajorVersion,
+ ThisSupportedRsrcTypeId->NameSpace.MajorVersion) == 0) &&
+ (AsciiStrCmp (
+ RestJSonHeader->JsonRsrcIdentifier.NameSpace.MinorVersion,
+ ThisSupportedRsrcTypeId->NameSpace.MinorVersion) == 0) &&
+ (AsciiStrCmp (
+ RestJSonHeader->JsonRsrcIdentifier.NameSpace.ErrataVersion,
+ ThisSupportedRsrcTypeId->NameSpace.ErrataVersion) == 0)) {
+ Status = InterpreterInstance->DestroyStructure (
+ This,
+ RestJSonHeader
+ );
+ break;
+ }
+ }
+ }
+ ThisSupportedRsrcTypeId ++;
+ }
+ return Status;
+}
+
+/**
+ This function translates the given JSON text to JSON C Structure.
+
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] RsrcTypeIdentifier Resource type identifier.
+ @param[in] ResourceJsonText Given Restful resource.
+ @param[out] JsonStructure Property interpreted from given ResourceRaw.
+
+ @retval EFI_SUCCESS
+ @retval Others.
+
+**/
+EFI_STATUS
+EFIAPI
+RestJsonStructureToStruct (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *RsrcTypeIdentifier OPTIONAL,
+ IN CHAR8 *ResourceJsonText,
+ OUT EFI_REST_JSON_STRUCTURE_HEADER **JsonStructure
+)
+{
+ EFI_STATUS Status;
+ REST_JSON_STRUCTURE_INSTANCE *Instance;
+
+ if (This == NULL ||
+ ResourceJsonText == NULL ||
+ JsonStructure == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsListEmpty (&mRestJsonStructureList)) {
+ return EFI_UNSUPPORTED;
+ }
+ Status = EFI_SUCCESS;
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);
+ while (TRUE) {
+ Status = InterpreterInstanceToStruct (
+ This,
+ Instance,
+ RsrcTypeIdentifier,
+ ResourceJsonText,
+ JsonStructure
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ if (IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
+ };
+ return Status;
+}
+
+/**
+ This function destory REST property EFI structure which returned in
+ JsonToStructure().
+
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] RestJSonHeader Property to destory.
+
+ @retval EFI_SUCCESS
+ @retval Others
+
+**/
+EFI_STATUS
+EFIAPI
+RestJsonStructureDestroyStruct (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN EFI_REST_JSON_STRUCTURE_HEADER *RestJSonHeader
+)
+{
+ EFI_STATUS Status;
+ REST_JSON_STRUCTURE_INSTANCE *Instance;
+
+ if (This == NULL || RestJSonHeader == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsListEmpty (&mRestJsonStructureList)) {
+ return EFI_UNSUPPORTED;
+ }
+ Status = EFI_SUCCESS;
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);
+ while (TRUE) {
+ Status = InterpreterInstanceDestoryJsonStruct (
+ This,
+ Instance,
+ RestJSonHeader
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ if (IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
+ };
+ return Status;
+}
+
+/**
+ This function translates the given JSON C Structure to JSON text.
+
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] RestJSonHeader Given Restful resource.
+ @param[out] ResourceRaw Resource in RESTfuls service oriented.
+
+ @retval EFI_SUCCESS
+ @retval Others Fail to remove the entry
+
+**/
+EFI_STATUS
+EFIAPI
+RestJsonStructureToJson (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN EFI_REST_JSON_STRUCTURE_HEADER *RestJSonHeader,
+ OUT CHAR8 **ResourceRaw
+)
+{
+ EFI_STATUS Status;
+ REST_JSON_STRUCTURE_INSTANCE *Instance;
+
+ if (This == NULL || RestJSonHeader == NULL || ResourceRaw == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsListEmpty (&mRestJsonStructureList)) {
+ return EFI_UNSUPPORTED;
+ }
+ Status = EFI_SUCCESS;
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);
+ while (TRUE) {
+ Status = InterpreterEfiStructToInstance (
+ This,
+ Instance,
+ RestJSonHeader,
+ ResourceRaw
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ if (IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
+ };
+ return Status;
+}
+
+EFI_REST_JSON_STRUCTURE_PROTOCOL mRestJsonStructureProtocol = {
+ RestJsonStructureRegister,
+ RestJsonStructureToStruct,
+ RestJsonStructureToJson,
+ RestJsonStructureDestroyStruct
+};
+
+/**
+ This is the declaration of an EFI image entry point.
+
+ @param ImageHandle The firmware allocated handle for the UEFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RestJsonStructureEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ InitializeListHead (&mRestJsonStructureList);
+ //
+ // Install the Restful Resource Interpreter Protocol.
+ //
+ mProtocolHandle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &mProtocolHandle,
+ &gEfiRestJsonStructureProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *)&mRestJsonStructureProtocol
+ );
+ return Status;
+}
+
+/**
+ This is the unload handle for Redfish discover module.
+
+ Disconnect the driver specified by ImageHandle from all the devices in the handle database.
+ Uninstall all the protocols installed in the driver entry point.
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+RestJsonStructureUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ REST_JSON_STRUCTURE_INSTANCE *Instance;
+ REST_JSON_STRUCTURE_INSTANCE *NextInstance;
+
+ Status = gBS->UninstallProtocolInterface (
+ mProtocolHandle,
+ &gEfiRestJsonStructureProtocolGuid,
+ (VOID *)&mRestJsonStructureProtocol
+ );
+
+ if (IsListEmpty (&mRestJsonStructureList)) {
+ return Status;
+ }
+ //
+ // Free memory of REST_JSON_STRUCTURE_INSTANCE instance.
+ //
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);
+ do {
+ NextInstance = NULL;
+ if (!IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {
+ NextInstance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
+ }
+ FreePool ((VOID *)Instance);
+ Instance = NextInstance;
+ } while (Instance != NULL);
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf
new file mode 100644
index 00000000..1d6a2bfc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf
@@ -0,0 +1,39 @@
+## @file
+# Implementation of EFI REST JSON Structure Protocol.
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = RestJsonStructureDxe
+ FILE_GUID = 83FAAFBF-FC4B-469F-892A-798E66A6F50A
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RestJsonStructureEntryPoint
+ UNLOAD_IMAGE = RestJsonStructureUnload
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[Sources]
+ RestJsonStructureDxe.c
+ RestJsonStructureInternal.h
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gEfiRestJsonStructureProtocolGuid ## Producing
+
+[Depex]
+ TRUE
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureInternal.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureInternal.h
new file mode 100644
index 00000000..e1394cfd
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureInternal.h
@@ -0,0 +1,33 @@
+/** @file
+ The internal definitions of EFI REST Resource JSON to C structure convertor
+ Protocol.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REST_JSON_STRUCTURE_INTERNAL_H_
+#define EFI_REST_JSON_STRUCTURE_INTERNAL_H_
+
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+///
+/// Internal structure to maintain the information of JSON to
+/// C structure convertor.
+///
+typedef struct _REST_JSON_STRUCTURE_INSTANCE {
+ LIST_ENTRY NextRestJsonStructureInstance; ///< Next convertor instance
+ UINTN NumberOfNameSpaceToConvert; ///< Number of resource type this convertor supports.
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *SupportedRsrcIndentifier; ///< The resource type linklist
+ EFI_REST_JSON_STRUCTURE_TO_STRUCTURE JsonToStructure; ///< JSON to C structure function
+ EFI_REST_JSON_STRUCTURE_TO_JSON StructureToJson; ///< C structure to JSON function
+ EFI_REST_JSON_STRUCTURE_DESTORY_STRUCTURE DestroyStructure; ///< Destory C struture function.
+} REST_JSON_STRUCTURE_INSTANCE;
+#endif