* [edk2-devel] [PATCH v2 0/2] UefiPayloadPkg supports Fit @ 2023-09-15 8:58 brucex.wang 2023-09-15 8:58 ` [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang 2023-09-15 8:58 ` [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support brucex.wang 0 siblings, 2 replies; 10+ messages in thread From: brucex.wang @ 2023-09-15 8:58 UTC (permalink / raw) To: devel; +Cc: brucex.wang From: "Brucex.Wang" <brucex.wang@intel.com> v2: Add fit support and fix some spelling issues. Brucex.Wang (2): MdePkg/BaseFdtLib: Add Fdt function. UefiPayloadPkg: Add FIT support MdePkg/Include/Library/FdtLib.h | 34 + MdePkg/Library/BaseFdtLib/FdtLib.c | 40 ++ .../Include/Guid/UniversalPayloadBase.h | 21 + UefiPayloadPkg/PayloadLoaderPeim/FitLib.h | 60 ++ .../PayloadLoaderPeim/FitLib/FitLib.c | 127 ++++ .../PayloadLoaderPeim/FitPayloadLoaderPeim.c | 150 ++++ .../FitPayloadLoaderPeim.inf | 59 ++ UefiPayloadPkg/Readme.md | 191 +++++ UefiPayloadPkg/Tools/MkFitImage.py | 272 ++++++++ .../FitUniversalPayloadEntry.c | 654 ++++++++++++++++++ .../FitUniversalPayloadEntry.inf | 98 +++ UefiPayloadPkg/UefiPayloadPkg.dec | 3 + UefiPayloadPkg/UefiPayloadPkg.dsc | 27 +- UefiPayloadPkg/UniversalPayloadBuild.py | 328 ++++++--- 14 files changed, 1968 insertions(+), 96 deletions(-) create mode 100644 UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf create mode 100644 UefiPayloadPkg/Readme.md create mode 100644 UefiPayloadPkg/Tools/MkFitImage.py create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf -- 2.39.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108716): https://edk2.groups.io/g/devel/message/108716 Mute This Topic: https://groups.io/mt/101378802/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply [flat|nested] 10+ messages in thread
* [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function. 2023-09-15 8:58 [edk2-devel] [PATCH v2 0/2] UefiPayloadPkg supports Fit brucex.wang @ 2023-09-15 8:58 ` brucex.wang 2023-09-15 9:02 ` Guo, Gua ` (2 more replies) 2023-09-15 8:58 ` [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support brucex.wang 1 sibling, 3 replies; 10+ messages in thread From: brucex.wang @ 2023-09-15 8:58 UTC (permalink / raw) To: devel; +Cc: brucex.wang, Benny Lin, Gua Guo, Chasel Chiu, James Lu From: "Brucex.Wang" <brucex.wang@intel.com> Add FdtGetName() and FdtNodeDepth() function. Cc: Benny Lin <benny.lin@intel.com> Cc: Gua Guo <gua.guo@intel.com> Cc: Chasel Chiu <chasel.chiu@intel.com> Cc: James Lu <james.lu@intel.com> Signed-off-by: BruceX Wang <brucex.wang@intel.com> --- MdePkg/Include/Library/FdtLib.h | 34 +++++++++++++++++++++++++ MdePkg/Library/BaseFdtLib/FdtLib.c | 40 ++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/MdePkg/Include/Library/FdtLib.h b/MdePkg/Include/Library/FdtLib.h index cf5ceba9e9..2bd926b5b4 100644 --- a/MdePkg/Include/Library/FdtLib.h +++ b/MdePkg/Include/Library/FdtLib.h @@ -398,4 +398,38 @@ FdtSetProp ( IN UINT32 Length ); +/** + Returns the name of a given node. + + @param[in] Fdt The pointer to FDT blob. + @param[in] NodeOffse Offset of node to check. + @param[in] Length The pointer to an integer variable (will be overwritten) or NULL. + + @return The pointer to the node's name. + +**/ +CONST CHAR8 * +EFIAPI +FdtGetName ( + IN VOID *Fdt, + IN INT32 NodeOffset, + IN UINT32 *Length + ); + +/** + FdtNodeDepth() finds the depth of a given node. The root node + has depth 0, its immediate subnodes depth 1 and so forth. + + @param[in] Fdt The pointer to FDT blob. + @param[in] NodeOffset Offset of node to check. + + @return Depth of the node at NodeOffset. + **/ +INT32 +EFIAPI +FdtNodeDepth ( + IN CONST VOID *Fdt, + IN INT32 NodeOffset + ); + #endif /* FDT_LIB_H_ */ diff --git a/MdePkg/Library/BaseFdtLib/FdtLib.c b/MdePkg/Library/BaseFdtLib/FdtLib.c index 090b0b3fd4..1ef99ea882 100644 --- a/MdePkg/Library/BaseFdtLib/FdtLib.c +++ b/MdePkg/Library/BaseFdtLib/FdtLib.c @@ -402,3 +402,43 @@ FdtSetProp ( { return fdt_setprop (Fdt, NodeOffset, Name, Value, (int)Length); } + +/** + Returns the name of a given node. + + @param[in] Fdt The pointer to FDT blob. + @param[in] NodeOffset Offset of node to check. + @param[in] Length The pointer to an integer variable (will be overwritten) or NULL. + + @return The pointer to the node's name. + +**/ +CONST CHAR8 * +EFIAPI +FdtGetName ( + IN VOID *Fdt, + IN INT32 NodeOffset, + IN UINT32 *Length + ) +{ + return fdt_get_name (Fdt, NodeOffset, (int *)Length); +} + +/** + FdtNodeDepth() finds the depth of a given node. The root node + has depth 0, its immediate subnodes depth 1 and so forth. + + @param[in] Fdt The pointer to FDT blob. + @param[in] NodeOffset Offset of node to check. + + @returns Depth of the node at NodeOffset. +**/ +INT32 +EFIAPI +FdtNodeDepth ( + IN CONST VOID *Fdt, + IN INT32 NodeOffset + ) +{ + return fdt_node_depth (Fdt, NodeOffset); +} -- 2.39.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108717): https://edk2.groups.io/g/devel/message/108717 Mute This Topic: https://groups.io/mt/101378804/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function. 2023-09-15 8:58 ` [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang @ 2023-09-15 9:02 ` Guo, Gua 2023-09-15 9:06 ` Lu, James 2023-09-15 9:09 ` Benny Lin 2 siblings, 0 replies; 10+ messages in thread From: Guo, Gua @ 2023-09-15 9:02 UTC (permalink / raw) To: Wang, BruceX, devel@edk2.groups.io; +Cc: Lin, Benny, Chiu, Chasel, Lu, James Reviewed-by: Gua Guo <gua.guo@intel.com> -----Original Message----- From: Wang, BruceX <brucex.wang@intel.com> Sent: Friday, September 15, 2023 4:58 PM To: devel@edk2.groups.io Cc: Wang, BruceX <brucex.wang@intel.com>; Lin, Benny <benny.lin@intel.com>; Guo, Gua <gua.guo@intel.com>; Chiu, Chasel <chasel.chiu@intel.com>; Lu, James <james.lu@intel.com> Subject: [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function. From: "Brucex.Wang" <brucex.wang@intel.com> Add FdtGetName() and FdtNodeDepth() function. Cc: Benny Lin <benny.lin@intel.com> Cc: Gua Guo <gua.guo@intel.com> Cc: Chasel Chiu <chasel.chiu@intel.com> Cc: James Lu <james.lu@intel.com> Signed-off-by: BruceX Wang <brucex.wang@intel.com> --- MdePkg/Include/Library/FdtLib.h | 34 +++++++++++++++++++++++++ MdePkg/Library/BaseFdtLib/FdtLib.c | 40 ++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/MdePkg/Include/Library/FdtLib.h b/MdePkg/Include/Library/FdtLib.h index cf5ceba9e9..2bd926b5b4 100644 --- a/MdePkg/Include/Library/FdtLib.h +++ b/MdePkg/Include/Library/FdtLib.h @@ -398,4 +398,38 @@ FdtSetProp ( IN UINT32 Length ); +/**+ Returns the name of a given node.++ @param[in] Fdt The pointer to FDT blob.+ @param[in] NodeOffse Offset of node to check.+ @param[in] Length The pointer to an integer variable (will be overwritten) or NULL.++ @return The pointer to the node's name.++**/+CONST CHAR8 *+EFIAPI+FdtGetName (+ IN VOID *Fdt,+ IN INT32 NodeOffset,+ IN UINT32 *Length+ );++/**+ FdtNodeDepth() finds the depth of a given node. The root node+ has depth 0, its immediate subnodes depth 1 and so forth.++ @param[in] Fdt The pointer to FDT blob.+ @param[in] NodeOffset Offset of node to check.++ @return Depth of the node at NodeOffset.+ **/+INT32+EFIAPI+FdtNodeDepth (+ IN CONST VOID *Fdt,+ IN INT32 NodeOffset+ );+ #endif /* FDT_LIB_H_ */diff --git a/MdePkg/Library/BaseFdtLib/FdtLib.c b/MdePkg/Library/BaseFdtLib/FdtLib.c index 090b0b3fd4..1ef99ea882 100644 --- a/MdePkg/Library/BaseFdtLib/FdtLib.c +++ b/MdePkg/Library/BaseFdtLib/FdtLib.c @@ -402,3 +402,43 @@ FdtSetProp ( { return fdt_setprop (Fdt, NodeOffset, Name, Value, (int)Length); }++/**+ Returns the name of a given node.++ @param[in] Fdt The pointer to FDT blob.+ @param[in] NodeOffset Offset of node to check.+ @param[in] Length The pointer to an integer variable (will be overwritten) or NULL.++ @return The pointer to the node's name.++**/+CONST CHAR8 *+EFIAPI+FdtGetName (+ IN VOID *Fdt,+ IN INT32 NodeOffset,+ IN UINT32 *Length+ )+{+ return fdt_get_name (Fdt, NodeOffset, (int *)Length);+}++/**+ FdtNodeDepth() finds the depth of a given node. The root node+ has depth 0, its immediate subnodes depth 1 and so forth.++ @param[in] Fdt The pointer to FDT blob.+ @param[in] NodeOffset Offset of node to check.++ @returns Depth of the node at NodeOffset.+**/+INT32+EFIAPI+FdtNodeDepth (+ IN CONST VOID *Fdt,+ IN INT32 NodeOffset+ )+{+ return fdt_node_depth (Fdt, NodeOffset);+}-- 2.39.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108700): https://edk2.groups.io/g/devel/message/108700 Mute This Topic: https://groups.io/mt/101375949/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function. 2023-09-15 8:58 ` [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang 2023-09-15 9:02 ` Guo, Gua @ 2023-09-15 9:06 ` Lu, James 2023-09-15 9:09 ` Benny Lin 2 siblings, 0 replies; 10+ messages in thread From: Lu, James @ 2023-09-15 9:06 UTC (permalink / raw) To: Wang, BruceX, devel@edk2.groups.io; +Cc: Lin, Benny, Guo, Gua, Chiu, Chasel Reviewed-by: James Lu <james.lu@intel.com> Thanks, James -----Original Message----- From: Wang, BruceX <brucex.wang@intel.com> Sent: Friday, September 15, 2023 4:58 PM To: devel@edk2.groups.io Cc: Wang, BruceX <brucex.wang@intel.com>; Lin, Benny <benny.lin@intel.com>; Guo, Gua <gua.guo@intel.com>; Chiu, Chasel <chasel.chiu@intel.com>; Lu, James <james.lu@intel.com> Subject: [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function. From: "Brucex.Wang" <brucex.wang@intel.com> Add FdtGetName() and FdtNodeDepth() function. Cc: Benny Lin <benny.lin@intel.com> Cc: Gua Guo <gua.guo@intel.com> Cc: Chasel Chiu <chasel.chiu@intel.com> Cc: James Lu <james.lu@intel.com> Signed-off-by: BruceX Wang <brucex.wang@intel.com> --- MdePkg/Include/Library/FdtLib.h | 34 +++++++++++++++++++++++++ MdePkg/Library/BaseFdtLib/FdtLib.c | 40 ++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/MdePkg/Include/Library/FdtLib.h b/MdePkg/Include/Library/FdtLib.h index cf5ceba9e9..2bd926b5b4 100644 --- a/MdePkg/Include/Library/FdtLib.h +++ b/MdePkg/Include/Library/FdtLib.h @@ -398,4 +398,38 @@ FdtSetProp ( IN UINT32 Length ); +/**+ Returns the name of a given node.++ @param[in] Fdt The pointer to FDT blob.+ @param[in] NodeOffse Offset of node to check.+ @param[in] Length The pointer to an integer variable (will be overwritten) or NULL.++ @return The pointer to the node's name.++**/+CONST CHAR8 *+EFIAPI+FdtGetName (+ IN VOID *Fdt,+ IN INT32 NodeOffset,+ IN UINT32 *Length+ );++/**+ FdtNodeDepth() finds the depth of a given node. The root node+ has depth 0, its immediate subnodes depth 1 and so forth.++ @param[in] Fdt The pointer to FDT blob.+ @param[in] NodeOffset Offset of node to check.++ @return Depth of the node at NodeOffset.+ **/+INT32+EFIAPI+FdtNodeDepth (+ IN CONST VOID *Fdt,+ IN INT32 NodeOffset+ );+ #endif /* FDT_LIB_H_ */diff --git a/MdePkg/Library/BaseFdtLib/FdtLib.c b/MdePkg/Library/BaseFdtLib/FdtLib.c index 090b0b3fd4..1ef99ea882 100644 --- a/MdePkg/Library/BaseFdtLib/FdtLib.c +++ b/MdePkg/Library/BaseFdtLib/FdtLib.c @@ -402,3 +402,43 @@ FdtSetProp ( { return fdt_setprop (Fdt, NodeOffset, Name, Value, (int)Length); }++/**+ Returns the name of a given node.++ @param[in] Fdt The pointer to FDT blob.+ @param[in] NodeOffset Offset of node to check.+ @param[in] Length The pointer to an integer variable (will be overwritten) or NULL.++ @return The pointer to the node's name.++**/+CONST CHAR8 *+EFIAPI+FdtGetName (+ IN VOID *Fdt,+ IN INT32 NodeOffset,+ IN UINT32 *Length+ )+{+ return fdt_get_name (Fdt, NodeOffset, (int *)Length);+}++/**+ FdtNodeDepth() finds the depth of a given node. The root node+ has depth 0, its immediate subnodes depth 1 and so forth.++ @param[in] Fdt The pointer to FDT blob.+ @param[in] NodeOffset Offset of node to check.++ @returns Depth of the node at NodeOffset.+**/+INT32+EFIAPI+FdtNodeDepth (+ IN CONST VOID *Fdt,+ IN INT32 NodeOffset+ )+{+ return fdt_node_depth (Fdt, NodeOffset);+}-- 2.39.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108702): https://edk2.groups.io/g/devel/message/108702 Mute This Topic: https://groups.io/mt/101375949/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function. 2023-09-15 8:58 ` [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang 2023-09-15 9:02 ` Guo, Gua 2023-09-15 9:06 ` Lu, James @ 2023-09-15 9:09 ` Benny Lin 2 siblings, 0 replies; 10+ messages in thread From: Benny Lin @ 2023-09-15 9:09 UTC (permalink / raw) To: Wang, BruceX, devel@edk2.groups.io; +Cc: Guo, Gua, Chiu, Chasel, Lu, James Reviewed-by: Benny Lin <benny.lin@intel.com> -----Original Message----- From: Wang, BruceX <brucex.wang@intel.com> Sent: Friday, September 15, 2023 4:58 PM To: devel@edk2.groups.io Cc: Wang, BruceX <brucex.wang@intel.com>; Lin, Benny <benny.lin@intel.com>; Guo, Gua <gua.guo@intel.com>; Chiu, Chasel <chasel.chiu@intel.com>; Lu, James <james.lu@intel.com> Subject: [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function. From: "Brucex.Wang" <brucex.wang@intel.com> Add FdtGetName() and FdtNodeDepth() function. Cc: Benny Lin <benny.lin@intel.com> Cc: Gua Guo <gua.guo@intel.com> Cc: Chasel Chiu <chasel.chiu@intel.com> Cc: James Lu <james.lu@intel.com> Signed-off-by: BruceX Wang <brucex.wang@intel.com> --- MdePkg/Include/Library/FdtLib.h | 34 +++++++++++++++++++++++++ MdePkg/Library/BaseFdtLib/FdtLib.c | 40 ++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/MdePkg/Include/Library/FdtLib.h b/MdePkg/Include/Library/FdtLib.h index cf5ceba9e9..2bd926b5b4 100644 --- a/MdePkg/Include/Library/FdtLib.h +++ b/MdePkg/Include/Library/FdtLib.h @@ -398,4 +398,38 @@ FdtSetProp ( IN UINT32 Length ); +/**+ Returns the name of a given node.++ @param[in] Fdt The pointer to FDT blob.+ @param[in] NodeOffse Offset of node to check.+ @param[in] Length The pointer to an integer variable (will be overwritten) or NULL.++ @return The pointer to the node's name.++**/+CONST CHAR8 *+EFIAPI+FdtGetName (+ IN VOID *Fdt,+ IN INT32 NodeOffset,+ IN UINT32 *Length+ );++/**+ FdtNodeDepth() finds the depth of a given node. The root node+ has depth 0, its immediate subnodes depth 1 and so forth.++ @param[in] Fdt The pointer to FDT blob.+ @param[in] NodeOffset Offset of node to check.++ @return Depth of the node at NodeOffset.+ **/+INT32+EFIAPI+FdtNodeDepth (+ IN CONST VOID *Fdt,+ IN INT32 NodeOffset+ );+ #endif /* FDT_LIB_H_ */diff --git a/MdePkg/Library/BaseFdtLib/FdtLib.c b/MdePkg/Library/BaseFdtLib/FdtLib.c index 090b0b3fd4..1ef99ea882 100644 --- a/MdePkg/Library/BaseFdtLib/FdtLib.c +++ b/MdePkg/Library/BaseFdtLib/FdtLib.c @@ -402,3 +402,43 @@ FdtSetProp ( { return fdt_setprop (Fdt, NodeOffset, Name, Value, (int)Length); }++/**+ Returns the name of a given node.++ @param[in] Fdt The pointer to FDT blob.+ @param[in] NodeOffset Offset of node to check.+ @param[in] Length The pointer to an integer variable (will be overwritten) or NULL.++ @return The pointer to the node's name.++**/+CONST CHAR8 *+EFIAPI+FdtGetName (+ IN VOID *Fdt,+ IN INT32 NodeOffset,+ IN UINT32 *Length+ )+{+ return fdt_get_name (Fdt, NodeOffset, (int *)Length);+}++/**+ FdtNodeDepth() finds the depth of a given node. The root node+ has depth 0, its immediate subnodes depth 1 and so forth.++ @param[in] Fdt The pointer to FDT blob.+ @param[in] NodeOffset Offset of node to check.++ @returns Depth of the node at NodeOffset.+**/+INT32+EFIAPI+FdtNodeDepth (+ IN CONST VOID *Fdt,+ IN INT32 NodeOffset+ )+{+ return fdt_node_depth (Fdt, NodeOffset);+}-- 2.39.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108703): https://edk2.groups.io/g/devel/message/108703 Mute This Topic: https://groups.io/mt/101375949/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support 2023-09-15 8:58 [edk2-devel] [PATCH v2 0/2] UefiPayloadPkg supports Fit brucex.wang 2023-09-15 8:58 ` [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang @ 2023-09-15 8:58 ` brucex.wang 2023-09-15 9:02 ` Guo, Gua 2023-09-15 9:06 ` Lu, James 1 sibling, 2 replies; 10+ messages in thread From: brucex.wang @ 2023-09-15 8:58 UTC (permalink / raw) To: devel; +Cc: brucex.wang, Guo Dong, Sean Rhodes, James Lu, Gua Guo From: "Brucex.Wang" <brucex.wang@intel.com> Provide Fit format for UniversalPayload, developer can use argument "--Fit" to build UniversalPayload.fit Cc: Guo Dong <guo.dong@intel.com> Cc: Sean Rhodes <sean@starlabs.systems> Cc: James Lu <james.lu@intel.com> Cc: Gua Guo <gua.guo@intel.com> Signed-off-by: BruceX Wang <brucex.wang@intel.com> --- .../Include/Guid/UniversalPayloadBase.h | 21 + UefiPayloadPkg/PayloadLoaderPeim/FitLib.h | 60 ++ .../PayloadLoaderPeim/FitLib/FitLib.c | 127 ++++ .../PayloadLoaderPeim/FitPayloadLoaderPeim.c | 150 ++++ .../FitPayloadLoaderPeim.inf | 59 ++ UefiPayloadPkg/Readme.md | 191 +++++ UefiPayloadPkg/Tools/MkFitImage.py | 272 ++++++++ .../FitUniversalPayloadEntry.c | 654 ++++++++++++++++++ .../FitUniversalPayloadEntry.inf | 98 +++ UefiPayloadPkg/UefiPayloadPkg.dec | 3 + UefiPayloadPkg/UefiPayloadPkg.dsc | 27 +- UefiPayloadPkg/UniversalPayloadBuild.py | 328 ++++++--- 12 files changed, 1894 insertions(+), 96 deletions(-) create mode 100644 UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf create mode 100644 UefiPayloadPkg/Readme.md create mode 100644 UefiPayloadPkg/Tools/MkFitImage.py create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf diff --git a/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h new file mode 100644 index 0000000000..31c9ec0bfb --- /dev/null +++ b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h @@ -0,0 +1,21 @@ +/** @file + Universal Payload general definitions. + +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Revision Reference: + - Universal Payload Specification 0.75 (https://universalpayload.github.io/documentation/) +**/ + +#ifndef UNIVERSAL_PAYLOAD_BASE_H_ +#define UNIVERSAL_PAYLOAD_BASE_H_ + +extern GUID gUniversalPayloadBaseGuid; + +typedef struct { + UNIVERSAL_PAYLOAD_GENERIC_HEADER Header; + EFI_PHYSICAL_ADDRESS Entry; +} UNIVERSAL_PAYLOAD_BASE; + +#endif // UNIVERSAL_PAYLOAD_BASE_H_ diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h new file mode 100644 index 0000000000..0514d675a6 --- /dev/null +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h @@ -0,0 +1,60 @@ +/** @file + FIT Load Image Support +Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef FIT_LIB_H_ +#define FIT_LIB_H_ + +#include <PiPei.h> +#include <Library/DebugLib.h> +#include <Library/FdtLib.h> + +typedef struct { + UINT64 RelocateType; + UINT64 Offset; +} FIT_RELOCATE_ITEM; + +typedef struct { + EFI_PHYSICAL_ADDRESS ImageBase; + EFI_PHYSICAL_ADDRESS PayloadBaseAddress; + UINT64 PayloadSize; + UINTN PayloadEntryOffset; + UINTN PayloadEntrySize; + EFI_PHYSICAL_ADDRESS PayloadEntryPoint; + UINTN RelocateTableOffset; + UINTN RelocateTableCount; + EFI_PHYSICAL_ADDRESS PayloadLoadAddress; +} FIT_IMAGE_CONTEXT; + +typedef struct { + UINT8 *Name; + UINT32 Offset; +} PROPERTY_DATA; + +#define IMAGE_BASE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, ImageBase) +#define PAYLOAD_BASE_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadBaseAddress) +#define PAYLOAD_BASE_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadSize) +#define PAYLOAD_ENTRY_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryOffset) +#define PAYLOAD_ENTRY_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntrySize) +#define PAYLOAD_ENTRY_POINT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryPoint) +#define RELOCATE_TABLE_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableOffset) +#define RELOCATE_TABLE_COUNT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableCount) +#define PAYLOAD_LOAD_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadLoadAddress) + +/** + Parse the FIT image info. + @param[in] ImageBase Memory address of an image. + @param[out] Context The FIT image context pointer. + @retval EFI_UNSUPPORTED Unsupported binary type. + @retval EFI_SUCCESS FIT binary is loaded successfully. +**/ +EFI_STATUS +EFIAPI +ParseFitImage ( + IN VOID *ImageBase, + OUT FIT_IMAGE_CONTEXT *Context + ); + +#endif diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c new file mode 100644 index 0000000000..9d1d8a4f61 --- /dev/null +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c @@ -0,0 +1,127 @@ +/** @file + FIT Load Image Support +Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "FitLib.h" + +PROPERTY_DATA PropertyData32List[] = { + { "data-offset", PAYLOAD_ENTRY_OFFSET_OFFSET }, + { "data-size", PAYLOAD_ENTRY_SIZE_OFFSET }, + { "reloc-start", RELOCATE_TABLE_OFFSET_OFFSET } +}; + +PROPERTY_DATA PropertyData64List[] = { + { "entry-start", PAYLOAD_ENTRY_POINT_OFFSET }, + { "load", PAYLOAD_LOAD_ADDR_OFFSET } +}; + +/** + Parse the target firmware image info in FIT. + @param[in] Fdt Memory address of a fdt. + @param[in] Firmware Target name of an image. + @param[out] Context The FIT image context pointer. + @retval EFI_NOT_FOUND FIT node dose not find. + @retval EFI_SUCCESS FIT binary is loaded successfully. +**/ +EFI_STATUS +EFIAPI +FitParseFirmwarePropertyData ( + IN VOID *Fdt, + IN CHAR8 *Firmware, + OUT FIT_IMAGE_CONTEXT *Context + ) +{ + CONST FDT_PROPERTY *PropertyPtr; + INT32 ImageNode; + INT32 TianoNode; + INT32 TempLen; + UINT32 *Data32; + UINT64 *Data64; + UINT32 *ContextOffset32; + UINT64 *ContextOffset64; + INT32 Index; + + ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images")); + if (ImageNode <= 0) { + return EFI_NOT_FOUND; + } + + TianoNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, Firmware, (INT32)AsciiStrLen (Firmware)); + if (TianoNode <= 0) { + return EFI_NOT_FOUND; + } + + for (Index = 0; Index < sizeof (PropertyData32List) / sizeof (PROPERTY_DATA); Index++) { + PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData32List[Index].Name, &TempLen); + Data32 = (UINT32 *)(PropertyPtr->Data); + ContextOffset32 = (UINT32 *)((UINTN)Context + PropertyData32List[Index].Offset); + *ContextOffset32 = Fdt32ToCpu (*Data32); + } + + for (Index = 0; Index < sizeof (PropertyData64List)/sizeof (PROPERTY_DATA); Index++) { + PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData64List[Index].Name, &TempLen); + Data64 = (UINT64 *)(PropertyPtr->Data); + ContextOffset64 = (UINT64 *)((UINTN)Context + PropertyData64List[Index].Offset); + *ContextOffset64 = Fdt64ToCpu (*Data64); + } + + return EFI_SUCCESS; +} + +/** + Parse the FIT image info. + @param[in] ImageBase Memory address of an image. + @param[out] Context The FIT image context pointer. + @retval EFI_UNSUPPORTED Unsupported binary type. + @retval EFI_SUCCESS FIT binary is loaded successfully. +**/ +EFI_STATUS +EFIAPI +ParseFitImage ( + IN VOID *ImageBase, + OUT FIT_IMAGE_CONTEXT *Context + ) +{ + VOID *Fdt; + INT32 ConfigNode; + INT32 Config1Node; + CONST FDT_PROPERTY *PropertyPtr; + INT32 TempLen; + UINT32 *Data32; + UINT64 Value; + EFI_STATUS Status; + UINTN UplSize; + CHAR8 *Firmware; + + Status = FdtCheckHeader (ImageBase); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Fdt = ImageBase; + PropertyPtr = FdtGetProperty (Fdt, 0, "size", &TempLen); + Data32 = (UINT32 *)(PropertyPtr->Data); + UplSize = Value = Fdt32ToCpu (*Data32); + ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations")); + if (ConfigNode <= 0) { + return EFI_NOT_FOUND; + } + + Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1")); + if (Config1Node <= 0) { + return EFI_NOT_FOUND; + } + + PropertyPtr = FdtGetProperty (Fdt, Config1Node, "firmware", &TempLen); + Firmware = (CHAR8 *)(PropertyPtr->Data); + + FitParseFirmwarePropertyData (Fdt, Firmware, Context); + + Context->ImageBase = (EFI_PHYSICAL_ADDRESS)ImageBase; + Context->PayloadSize = UplSize; + Context->RelocateTableCount = (Context->PayloadEntrySize - (Context->RelocateTableOffset - Context->PayloadEntryOffset)) / sizeof (FIT_RELOCATE_ITEM); + + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c new file mode 100644 index 0000000000..3c5dacbb65 --- /dev/null +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c @@ -0,0 +1,150 @@ +/** @file + ELF Load Image Support +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include <PiPei.h> +#include <UniversalPayload/UniversalPayload.h> +#include <Guid/UniversalPayloadBase.h> +#include <UniversalPayload/ExtraData.h> + +#include <Ppi/LoadFile.h> + +#include <Library/DebugLib.h> +#include <Library/HobLib.h> +#include <Library/PeiServicesLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/BaseMemoryLib.h> + +#include "FitLib.h" + +/** + The wrapper function of PeiLoadImageLoadImage(). + @param This - Pointer to EFI_PEI_LOAD_FILE_PPI. + @param FileHandle - Pointer to the FFS file header of the image. + @param ImageAddressArg - Pointer to PE/TE image. + @param ImageSizeArg - Size of PE/TE image. + @param EntryPoint - Pointer to entry point of specified image file for output. + @param AuthenticationState - Pointer to attestation authentication state of image. + @return Status of PeiLoadImageLoadImage(). +**/ +EFI_STATUS +EFIAPI +PeiLoadFileLoadPayload ( + IN CONST EFI_PEI_LOAD_FILE_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL, + OUT UINT64 *ImageSizeArg OPTIONAL, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +{ + EFI_STATUS Status; + FIT_IMAGE_CONTEXT Context; + UINTN Instance; + VOID *Binary; + FIT_RELOCATE_ITEM *RelocateTable; + UNIVERSAL_PAYLOAD_BASE *PayloadBase; + UINTN Length; + UINTN Delta; + UINTN Index; + + Instance = 0; + do { + Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++, FileHandle, &Binary, AuthenticationState); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (&Context, sizeof (Context)); + Status = ParseFitImage (Binary, &Context); + } while (EFI_ERROR (Status)); + + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + DEBUG (( + DEBUG_INFO, + "Before Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n", + Context.PayloadBaseAddress, + Context.PayloadSize, + Context.PayloadEntryPoint + )); + Context.PayloadBaseAddress = (EFI_PHYSICAL_ADDRESS)AllocatePages (EFI_SIZE_TO_PAGES (Context.PayloadSize)); + + RelocateTable = (FIT_RELOCATE_ITEM *)(UINTN)(Context.PayloadBaseAddress + Context.RelocateTableOffset); + CopyMem ((VOID *)Context.PayloadBaseAddress, Binary, Context.PayloadSize); + + if (Context.PayloadBaseAddress > Context.PayloadLoadAddress) { + Delta = Context.PayloadBaseAddress - Context.PayloadLoadAddress; + Context.PayloadEntryPoint += Delta; + for (Index = 0; Index < Context.RelocateTableCount; Index++) { + if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) { + *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) + Delta; + } + } + } else { + Delta = Context.PayloadLoadAddress - Context.PayloadBaseAddress; + Context.PayloadEntryPoint -= Delta; + for (Index = 0; Index < Context.RelocateTableCount; Index++) { + if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) { + *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) - Delta; + } + } + } + + DEBUG (( + DEBUG_INFO, + "After Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n", + Context.PayloadBaseAddress, + Context.PayloadSize, + Context.PayloadEntryPoint + )); + + Length = sizeof (UNIVERSAL_PAYLOAD_BASE); + PayloadBase = BuildGuidHob ( + &gUniversalPayloadBaseGuid, + Length + ); + PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)Context.ImageBase; + + *ImageAddressArg = Context.PayloadBaseAddress; + *ImageSizeArg = Context.PayloadSize; + *EntryPoint = Context.PayloadEntryPoint; + + return EFI_SUCCESS; +} + +EFI_PEI_LOAD_FILE_PPI mPeiLoadFilePpi = { + PeiLoadFileLoadPayload +}; + +EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiLoadFilePpiGuid, + &mPeiLoadFilePpi +}; + +/** + Install Pei Load File PPI. + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + @retval EFI_SUCESS The entry point executes successfully. + @retval Others Some error occurs during the execution of this function. +**/ +EFI_STATUS +EFIAPI +InitializeFitPayloadLoaderPeim ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + + Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList); + + return Status; +} diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf new file mode 100644 index 0000000000..acb0e09f68 --- /dev/null +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf @@ -0,0 +1,59 @@ +## @file +# Produce LoadFile PPI for payload loading. +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FitPayloadLoaderPeim + FILE_GUID = 55AC82C8-FC17-4C56-BCDA-990BB0A73E41 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializeFitPayloadLoaderPeim + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + FitPayloadLoaderPeim.c + FitLib.h + FitLib/FitLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + PcAtChipsetPkg/PcAtChipsetPkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + PcdLib + MemoryAllocationLib + BaseMemoryLib + PeiServicesLib + HobLib + BaseLib + PeimEntryPoint + DebugLib + FdtLib + +[Ppis] + gEfiPeiLoadFilePpiGuid ## PRODUCES + +[Pcd] + gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister + gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister + +[Guids] + gUniversalPayloadExtraDataGuid ## PRODUCES + gUniversalPayloadBaseGuid ## PRODUCES + +[Depex] + TRUE diff --git a/UefiPayloadPkg/Readme.md b/UefiPayloadPkg/Readme.md new file mode 100644 index 0000000000..616a5dd467 --- /dev/null +++ b/UefiPayloadPkg/Readme.md @@ -0,0 +1,191 @@ +# UefiPayloadPkg +Provide UEFI Universal Payload for different bootloader to generate EFI environment + +# Spec + +UniversalPayload URL: https://universalscalablefirmware.github.io/documentation/2_universal_payload.html + +ELF Format URL: https://refspecs.linuxfoundation.org/elf/elf.pdf + +FIT Format URL: https://universalpayload.github.io/spec/chapter2-payload-image-format.html + +# Uefi UniversalPayload Format + | Binary Format | HandOffPayload - HOB | + |---------------|----------------------| + | ELF | V (Default) | + | FIT | V | + +# Binary Format + - ELF + ``` + + +-----------------------+ + | | UniversalPayloadEntry | <----------- UefiPayloadPkg\UefiPayloadEntry\UniversalPayloadEntry.c:_ModuleEntryPoint (HOB) + | +-----------------------+ + | | .upld_info | patch it directly + ELF Format | +-----------------------+ + | | .upld.uefi_fv | patch it directly + | +-----------------------+ + | | .upld.bds_fv | patch it directly + | +-----------------------+ + | | .upld.<afpx>_fv | patch it directly + + +-----------------------+ + ``` + + - FIT + ``` + + +-----------------------+ + FIT Data | | FIT Header | <----------- Generate by pylibfdt + + +-----------------------+ + PECOFF Format | | UniversalPayloadEntry | <----------- UefiPayloadPkg\UefiPayloadEntry\FitUniversalPayloadEntry.c:_ModuleEntryPoint (HOB) + + +-----------------------+ + Relocate Data | | reloc-start | + + +-----------------------+ + | | uefi_fv | patch it directly + | +-----------------------+ + Multi Binary | | bds_fv | patch it directly + | +-----------------------+ + | | afp_xxx_fv | patch it directly + | +-----------------------+ + | | afp_xxx_fv | patch it directly + + +-----------------------+ + ``` + +# Environment + - ELF + ``` + Download and install https://github.com/llvm/llvm-project/releases/tag/llvmorg-10.0.1 + ``` + - FIT + - Windows + ```powershell + Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) + choco install dtc-msys2 + pip3 install pefile + pip3 install swig + pip3 install pylibfdt + ``` + - Ubuntu + ```bash + sudo apt install -y u-boot-tools + pip3 install pefile + pip3 install swig + pip3 install pylibfdt + ``` +# How to build UEFI UniversalPayload + - Windows + - edksetup Rebuild + - Linux + - make -C BaseTools + - source edksetup.sh + + - UniversalPayload.elf + - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG> + - llvm-objdump -h Build/UefiPayloadPkgX64/UniversalPayload.elf + + - UniversalPayload.fit + - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG> --Fit + - fdtdump Build/UefiPayloadPkgX64/UniversalPayload.fit + +# Edk2boot + UefiUniversalPayload +ELF Edk2boot use below way to support compress and sign. + +- ELF Behavior - Edk2boot + UefiUniversalPayload.elf + ``` + Boot Flow + +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+ + | Platform Init | Universal Loader Interface | OS | + +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+ + HOBs + SEC -> PEI -> DXE -> DXE IPL -> UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c ------------------------------------------------------------------------------------> Load UniversalPayload.elf -> Operation System + + + | Platform Initialize - Edk2 | UniversalPayload - Edk2 | + +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+ + + Binary Format + + +-------------------+ + | BIOS.rom | + +-------------------+ + | Other Firmware | + +-------------------+ + | ... | FMMT UniversalPayloadBuild.py + +-------------------+<----------------+-----------------------+ GenFfs +-----------------------+ Rsa2048Sha256 Sign +-----------------------+ LzmaCompress +----------------------+ GenSec +--------------------------------+ + | | | EDK2 FFS Header |<-----------| Rsa2048Sha256 Hash |<--------------------| UniversalPayload.lzma |<--------------| EDK2 SEC Header |<--------| UniversalPayload.elf | + | RAW Data | +-----------------------+ +-----------------------+ +-----------------------+ +----------------------+ +--------------------------------+ + | | | Rsa2048Sha256 Hash | | UniversalPayload.lzma | | UniversalPayload.elf | | upld_info | + | | +-----------------------+ +-----------------------+ +----------------------+ +--------------------------------+ + | | | UniversalPayload.lzma | | upld_info | | upld.uefi_fv | + +-------------------+<----------------+-----------------------+ +----------------------+ +--------------------------------+ + | ... | | upld.uefi_fv | | upld.bds_fv | + +-------------------+ +----------------------+ +--------------------------------+ + | Other Firmware | | upld.bds_fv | | upld.AFP1 | + +-------------------+ +----------------------+ +--------------------------------+ + | upld.AFP1 | | upld.AFP2 | + +----------------------+ +--------------------------------+ + | upld.AFP2 | | ... | + +----------------------+ +--------------------------------+ + | ... | | upld.AFPn | + +----------------------+ +--------------------------------+ + | upld.AFPn | + +----------------------+ + ``` + +FIT Edk2boot use below way to support compress and sign +- FIT Behavior - Edk2boot + UefiUniversalPayload.fit + ``` + Boot Flow + +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+ + | Platform Init | Universal Loader Interface | OS | + +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+ + HOBs + SEC -> PEI -> DXE -> DXE IPL -> *UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c ----------------------------------------------> Load UniversalPayload.fit -> Operation System + + Binary Format + + | Platform Initialize - Edk2 | UniversalPayload - Edk2 (UniversalPayloadBuild.py --Fit) | + +---------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+ + + +-------------------+ + | BIOS.rom | + +-------------------+ + | Other Firmware | + +-------------------+ + | ... | FMMT UniversalPayloadBuild.py --Fit tianocore -> data-offset + +-------------------+<----------------+--------------------------------+ GenFfs +--------------------------------+ GenSec +--------------------------------+ tianocore -> reloc-start +--------------------------+ + | | | EDK2 FFS Header |<--------| EDK2 SEC Header |<--------| FIT Header |<-------------------------| UniversalPayload.pecoff | + | | +--------------------------------+ +--------------------------------+ | description = "Uefi Payload"; | +--------------------------+ + | | | EDK2 SEC Header | | FIT Header | | ... | + | RAW Data | +--------------------------------+ | | | images { | uefi-fv -> data-offset +--------------------------+ + | | | FIT Header | | | | tianocore {...}; |<-------------------------| uefi_fv | + | | | | +--------------------------------+ | uefi-fv {...}; | bds-fv -> data-offset +--------------------------+ + | | | | | tianocore -> data | | bds-fv {...}; |<-------------------------| bds_fv | + | | +--------------------------------+ +--------------------------------+ | afp1-fv {...}; | AFP1 -> data-offset +--------------------------+ + | | | tianocore -> data | | tianocore -> reloc-start | | ... |<-------------------------| AFP1 | + | | +--------------------------------+ +--------------------------------+ | afpn-fv {...}; | AFP2 -> data-offset +--------------------------+ + | | | tianocore -> reloc-start | | uefi-fv -> data | | } |<-------------------------| AFP2 | + | | +--------------------------------+ +--------------------------------+ | configurations { | ... +--------------------------+ + | | | uefi-fv -> data | | bds-fv -> data | | conf-1 {...} |<-------------------------| ... | + | | +--------------------------------+ +--------------------------------+ | } | AFPn -> data-offset +--------------------------+ + | | | bds-fv -> data | | AFP1-fv -> data | | |<-------------------------| AFPn | + | | +--------------------------------+ +--------------------------------+ | | +--------------------------+ + | | | AFP1-fv -> data | | AFP2-fv -> data | | | + | | +--------------------------------+ +--------------------------------+ +--------------------------------+ + | | | AFP2-fv -> data | | ... | | tianocore -> data | + | | +--------------------------------+ +--------------------------------+ +--------------------------------+ + | | | ... | | AFPn-fv -> data | | tianocore -> reloc-start | + | | +--------------------------------+ +--------------------------------+ +--------------------------------+ + | | | AFPn-fv -> data | | uefi-fv -> data | + +-------------------+<----------------+--------------------------------+ +--------------------------------+ + | ... | | bds-fv -> data | + +-------------------+ +--------------------------------+ + | Other Firmware | | AFP1-fv -> data | + +-------------------+ +--------------------------------+ + | AFP2-fv -> data | + +--------------------------------+ + | ... | + +--------------------------------+ + | AFPn-fv -> data | + +--------------------------------+ + + ``` diff --git a/UefiPayloadPkg/Tools/MkFitImage.py b/UefiPayloadPkg/Tools/MkFitImage.py new file mode 100644 index 0000000000..82ab933d6d --- /dev/null +++ b/UefiPayloadPkg/Tools/MkFitImage.py @@ -0,0 +1,272 @@ +## @file +# This file is a script to build fit image. +# It generate a dtb header and combine a binary file after this header. +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +from os.path import exists +import libfdt +from ctypes import * +import time + +class FIT_IMAGE_INFO_HEADER: + """Class for user setting data to use MakeFitImage() + """ + _pack_ = 1 + _fields_ = [ + ('Compatible', str), + ('UplVersion', int), + ('Description', str), + ('Type', str), + ('Arch', str), + ('Compression', str), + ('Revision', int), + ('BuildType', str), + ('Capabilities', str), + ('Producer', str), + ('ImageId', str), + ('DataOffset', int), + ('DataSize', int), + ('RelocStart', int), + ('LoadAddr', int), + ('Entry', int), + ('Binary', str), + ('TargetPath', str), + ('UefifvPath', str), + ('BdsfvPath', str), + ('NetworkfvPath', str), + ('Project', str), + ] + + def __init__(self): + self.Compatible = 'universal-payload' + self.UplVersion = 0x0100 + self.TargetPath = 'mkimage.fit' + +def CreatFdt(Fdt): + FdtEmptyTree = libfdt.fdt_create_empty_tree(Fdt, len(Fdt)) + if FdtEmptyTree != 0: + print('\n- Failed - Create Fdt failed!') + return False + return True + +def BuildConfNode(Fdt, ParentNode, MultiImage): + ConfNode1 = libfdt.fdt_add_subnode(Fdt, ParentNode, 'conf-1') + + libfdt.fdt_setprop(Fdt, ConfNode1, 'require-fit', b'', 0) + libfdt.fdt_setprop(Fdt, ConfNode1, 'firmware', bytes('tianocore', 'utf-8'), len('tianocore') + 1) + +def BuildFvImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize, Description): + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize) + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset) + libfdt.fdt_setprop(Fdt, ParentNode, 'compression', bytes('none', 'utf-8'), len('none') + 1) + libfdt.fdt_setprop(Fdt, ParentNode, 'project ', bytes('tianocore', 'utf-8'), len('tianocore') + 1) + libfdt.fdt_setprop(Fdt, ParentNode, 'arch', bytes('x86_64', 'utf-8'), len('x86_64') + 1) + libfdt.fdt_setprop(Fdt, ParentNode, 'type', bytes('flat-binary', 'utf-8'), len('flat-binary') + 1) + libfdt.fdt_setprop(Fdt, ParentNode, 'description', bytes(Description, 'utf-8'), len(Description) + 1) + +def BuildTianoImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize, Description): + # + # Set 'load' and 'data-offset' to reserve the memory first. + # They would be set again when Fdt completes or this function parses target binary file. + # + if InfoHeader.LoadAddr is not None: + libfdt.fdt_setprop_u64(Fdt, ParentNode, 'load', InfoHeader.LoadAddr) + if InfoHeader.Entry is not None: + libfdt.fdt_setprop_u64(Fdt, ParentNode, 'entry-start', InfoHeader.Entry) + if InfoHeader.RelocStart is not None: + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'reloc-start', InfoHeader.RelocStart) + if InfoHeader.DataSize is not None: + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize) + if InfoHeader.DataOffset is not None: + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset) + if InfoHeader.Producer is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'producer ', bytes(InfoHeader.Producer, 'utf-8'), len(InfoHeader.Producer) + 1) + if InfoHeader.Capabilities is not None: + CapStrs = ','.join(InfoHeader.Capabilities) + libfdt.fdt_setprop(Fdt, ParentNode, 'capabilities ', bytes(CapStrs, 'utf-8'), len(CapStrs) + 1) + if InfoHeader.Type is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'type ', bytes(InfoHeader.Type, 'utf-8'), len(InfoHeader.Type) + 1) + if InfoHeader.Arch is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'arch ', bytes(InfoHeader.Arch, 'utf-8'), len(InfoHeader.Arch) + 1) + if InfoHeader.Project is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'project ', bytes(InfoHeader.Project, 'utf-8'), len(InfoHeader.Project) + 1) + if InfoHeader.Description is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'description', bytes(Description, 'utf-8'), len(Description) + 1) + +# +# The subnode would be inserted from bottom to top of structure block. +# +def BuildFitImage(Fdt, InfoHeader): + MultiImage = [ + ["tianocore", InfoHeader.Binary, BuildTianoImageNode , InfoHeader.Description, None, 0 ], + ["uefi-fv", InfoHeader.UefifvPath, BuildFvImageNode, "UEFI Firmware Volume", None, 0 ], + ["bds-fv", InfoHeader.BdsfvPath, BuildFvImageNode , "BDS Firmware Volume", None, 0 ], + ["network-fv", InfoHeader.NetworkfvPath, BuildFvImageNode , "Network Firmware Volume", None, 0 ], + ] + + # + # Set basic information + # + libfdt.fdt_setprop_u32(Fdt, 0, 'build-revision ', InfoHeader.Revision) + libfdt.fdt_setprop_u32(Fdt, 0, 'spec-version', InfoHeader.UplVersion) + + # + # Build configurations node + # + ConfNode = libfdt.fdt_add_subnode(Fdt, 0, 'configurations') + BuildConfNode(Fdt, ConfNode, MultiImage) + + # Build image + DataOffset = InfoHeader.DataOffset + for Index in range (0, len (MultiImage)): + _, Path, _, _, _, _ = MultiImage[Index] + if exists(Path) == 1: + TempBinary = open(Path, 'rb') + BinaryData = TempBinary.read() + TempBinary.close() + MultiImage[Index][-2] = BinaryData + MultiImage[Index][-1] = DataOffset + DataOffset += len (BinaryData) + libfdt.fdt_setprop_u32(Fdt, 0, 'size', DataOffset) + posix_time = int(time.time()) + libfdt.fdt_setprop_u32(Fdt, 0, 'timestamp', posix_time) + DescriptionFit = 'Uefi OS Loader' + libfdt.fdt_setprop(Fdt, 0, 'description', bytes(DescriptionFit, 'utf-8'), len(DescriptionFit) + 1) + + ImageNode = libfdt.fdt_add_subnode(Fdt, 0, 'images') + for Item in reversed (MultiImage): + Name, Path, BuildFvNode, Description, BinaryData, DataOffset = Item + FvNode = libfdt.fdt_add_subnode(Fdt, ImageNode, Name) + BuildFvNode (Fdt, InfoHeader, FvNode, DataOffset, len(BinaryData), Description) + + # + # Create new image file and combine all binary. + # + DtbFile = open(InfoHeader.TargetPath, "wb") + DtbFile.truncate() + DtbFile.write(Fdt) + for Item in MultiImage: + _, _, _, _, BinaryData, _ = Item + DtbFile.write(BinaryData) + DtbFile.close() + + return True + +def MakeFitImage(InfoHeader): + # + # Allocate fdt byte array. + # + Fdt = bytearray(InfoHeader.DataOffset) + + # + # Create fdt empty tree. + # + if CreatFdt(Fdt) is False: + return False + + # + # Parse args to build fit image. + # + return BuildFitImage(Fdt, InfoHeader) + +def ReplaceFv (UplBinary, SectionFvFile, SectionName): + try: + # + # Get Original Multi Fv + # + with open (UplBinary, "rb") as File: + Dtb = File.read () + Fit = libfdt.Fdt (Dtb) + NewFitHeader = bytearray(Dtb[0:Fit.totalsize()]) + FitSize = len(Dtb) + + LoadablesList = [] + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images') + FvNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, 'uefi-fv') + NodeDepth = libfdt.fdt_node_depth (NewFitHeader, ImagesNode) + node_name = libfdt.fdt_get_name(NewFitHeader, FvNode) + FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode, NodeDepth) + + while node_name[0][-2:] == 'fv': + LoadablesList.append (node_name[0]) + node_name = libfdt.fdt_get_name(NewFitHeader, FvNode[0]) + FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode[0], NodeDepth) + # + # Get current Fit Binary FV data + # + MultiFvList = [] + for Item in LoadablesList: + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, Item) + ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big') + ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big') + MultiFvList.append ([Item, Dtb[ImageOffset:ImageOffset + ImageSize]]) + + IsFvExist = False + for Index in range (0, len (MultiFvList)): + if MultiFvList[Index][0] == SectionName: + with open (SectionFvFile, 'rb') as File: + MultiFvList[Index][1] = File.read () + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, SectionName) + ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big') + ReplaceOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big') + OffsetDelta = len(MultiFvList[Index][1]) - ImageSize + FitSize += OffsetDelta + IsFvExist = True + libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, 'data-size', len(MultiFvList[Index][1])) + + # + # Update new fit header + # + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images') + if (IsFvExist == False): + with open (SectionFvFile, 'rb') as File: + SectionFvFileBinary = File.read () + MultiFvList.append ([SectionName, SectionFvFileBinary]) + FvNode = libfdt.fdt_add_subnode(NewFitHeader, ImagesNode, SectionName) + BuildFvImageNode (NewFitHeader, None, FvNode, FitSize, len(SectionFvFileBinary), SectionName + " Firmware Volume") + FitSize += len(SectionFvFileBinary) + else: + for Index in range (0, len (MultiFvList)): + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, MultiFvList[Index][0]) + ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big') + if ImageOffset > ReplaceOffset: + libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, 'data-offset', ImageOffset + OffsetDelta) + + ConfNodes = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'configurations') + libfdt.fdt_setprop(NewFitHeader, ConfNodes, 'default ', bytes('conf-1', 'utf-8'), len('conf-1') + 1) + ConfNode = libfdt.fdt_subnode_offset(NewFitHeader, ConfNodes, 'conf-1') + + libfdt.fdt_setprop_u32(NewFitHeader, 0, 'size', FitSize) + + # + # Generate new fit image + # + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images') + TianoNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, 'tianocore') + TianoOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, TianoNode, 'data-offset')[0], 'big') + TianoSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, TianoNode, 'data-size')[0], 'big') + TianoBinary = Dtb[TianoOffset:TianoOffset + TianoSize] + + print("\nGenerate new fit image:") + NewUplBinary = bytearray(FitSize) + print("Update fit header\t to 0x0\t\t ~ " + str(hex(len(NewFitHeader)))) + NewUplBinary[:len(NewFitHeader)] = NewFitHeader + print("Update tiano image\t to " + str(hex(len(NewFitHeader))) + "\t ~ " + str(hex(len(NewFitHeader) + len(TianoBinary)))) + NewUplBinary[len(NewFitHeader):len(NewFitHeader) + len(TianoBinary)] = TianoBinary + for Index in range (0, len (MultiFvList)): + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, MultiFvList[Index][0]) + ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big') + ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big') + NewUplBinary[ImageOffset:ImageOffset + ImageSize] = MultiFvList[Index][1] + print("Update " + MultiFvList[Index][0] + "\t\t to " + str(hex(ImageOffset)) + "\t ~ " + str(hex(ImageOffset + ImageSize))) + + with open (UplBinary, "wb") as File: + File.write (NewUplBinary) + + return 0 + except Exception as Ex: + print(Ex) + return 1 diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c new file mode 100644 index 0000000000..a53d988627 --- /dev/null +++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c @@ -0,0 +1,654 @@ +/** @file + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "UefiPayloadEntry.h" +#include <Library/FdtLib.h> +#include <Guid/UniversalPayloadBase.h> + +#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \ + EFI_RESOURCE_ATTRIBUTE_TESTED | \ + EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_PERSISTENT ) + +#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \ + EFI_RESOURCE_ATTRIBUTE_TESTED ) + +extern VOID *mHobList; + +CHAR8 *mLineBuffer = NULL; + +/** + Print all HOBs info from the HOB list. + @return The pointer to the HOB list. +**/ +VOID +PrintHob ( + IN CONST VOID *HobStart + ); + +/** + Find the first substring. + @param String Point to the string where to find the substring. + @param CharSet Point to the string to be found. +**/ +UINTN +EFIAPI +AsciiStrSpn ( + IN CHAR8 *String, + IN CHAR8 *CharSet + ) +{ + UINTN Count; + CHAR8 *Str1; + CHAR8 *Str2; + + Count = 0; + + for (Str1 = String; *Str1 != L'\0'; Str1++) { + for (Str2 = CharSet; *Str2 != L'\0'; Str2++) { + if (*Str1 == *Str2) { + break; + } + } + + if (*Str2 == L'\0') { + return Count; + } + + Count++; + } + + return Count; +} + +/** + Searches a string for the first occurrence of a character contained in a + specified buffer. + @param String Point to the string where to find the substring. + @param CharSet Point to the string to be found. +**/ +CHAR8 * +EFIAPI +AsciiStrBrk ( + IN CHAR8 *String, + IN CHAR8 *CharSet + ) +{ + CHAR8 *Str1; + CHAR8 *Str2; + + for (Str1 = String; *Str1 != L'\0'; Str1++) { + for (Str2 = CharSet; *Str2 != L'\0'; Str2++) { + if (*Str1 == *Str2) { + return (CHAR8 *)Str1; + } + } + } + + return NULL; +} + +/** + Find the next token after one or more specified characters. + @param String Point to the string where to find the substring. + @param CharSet Point to the string to be found. +**/ +CHAR8 * +EFIAPI +AsciiStrTokenLine ( + IN CHAR8 *String OPTIONAL, + IN CHAR8 *CharSet + ) +{ + CHAR8 *Begin; + CHAR8 *End; + + Begin = (String == NULL) ? mLineBuffer : String; + if (Begin == NULL) { + return NULL; + } + + Begin += AsciiStrSpn (Begin, CharSet); + if (*Begin == L'\0') { + mLineBuffer = NULL; + return NULL; + } + + End = AsciiStrBrk (Begin, CharSet); + if ((End != NULL) && (*End != L'\0')) { + *End = L'\0'; + End++; + } + + mLineBuffer = End; + return Begin; +} + +/** + Some bootloader may pass a pcd database, and UPL also contain a PCD database. + Dxe PCD driver has the assumption that the two PCD database can be catenated and + the local token number should be successive. + This function will fix up the UPL PCD database to meet that assumption. + @param[in] DxeFv The FV where to find the Universal PCD database. + @retval EFI_SUCCESS If it completed successfully. + @retval other Failed to fix up. +**/ +EFI_STATUS +FixUpPcdDatabase ( + IN EFI_FIRMWARE_VOLUME_HEADER *DxeFv + ) +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER *FileHeader; + VOID *PcdRawData; + PEI_PCD_DATABASE *PeiDatabase; + PEI_PCD_DATABASE *UplDatabase; + EFI_HOB_GUID_TYPE *GuidHob; + DYNAMICEX_MAPPING *ExMapTable; + UINTN Index; + + GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); + if (GuidHob == NULL) { + // + // No fix-up is needed. + // + return EFI_SUCCESS; + } + + PeiDatabase = (PEI_PCD_DATABASE *)GET_GUID_HOB_DATA (GuidHob); + DEBUG ((DEBUG_INFO, "Find the Pei PCD data base, the total local token number is %d\n", PeiDatabase->LocalTokenCount)); + + Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DRIVER, PcdGetPtr (PcdPcdDriverFile), &FileHeader); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + UplDatabase = (PEI_PCD_DATABASE *)PcdRawData; + ExMapTable = (DYNAMICEX_MAPPING *)(UINTN)((UINTN)PcdRawData + UplDatabase->ExMapTableOffset); + + for (Index = 0; Index < UplDatabase->ExTokenCount; Index++) { + ExMapTable[Index].TokenNumber += PeiDatabase->LocalTokenCount; + } + + DEBUG ((DEBUG_INFO, "Fix up UPL PCD database successfully\n")); + return EFI_SUCCESS; +} + +/** + Add HOB into HOB list + @param[in] Hob The HOB to be added into the HOB list. +**/ +VOID +AddNewHob ( + IN EFI_PEI_HOB_POINTERS *Hob + ) +{ + EFI_PEI_HOB_POINTERS NewHob; + + if (Hob->Raw == NULL) { + return; + } + + NewHob.Header = CreateHob (Hob->Header->HobType, Hob->Header->HobLength); + + if (NewHob.Header != NULL) { + CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - sizeof (EFI_HOB_GENERIC_HEADER)); + } +} + +/** + Found the Resource Descriptor HOB that contains a range (Base, Top) + @param[in] HobList Hob start address + @param[in] Base Memory start address + @param[in] Top Memory end address. + @retval The pointer to the Resource Descriptor HOB. +**/ +EFI_HOB_RESOURCE_DESCRIPTOR * +FindResourceDescriptorByRange ( + IN VOID *HobList, + IN EFI_PHYSICAL_ADDRESS Base, + IN EFI_PHYSICAL_ADDRESS Top + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + + for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + // + // Skip all HOBs except Resource Descriptor HOBs + // + if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + continue; + } + + // + // Skip Resource Descriptor HOBs that do not describe tested system memory + // + ResourceHob = Hob.ResourceDescriptor; + if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) { + continue; + } + + if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) { + continue; + } + + // + // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop + // + if (Base < ResourceHob->PhysicalStart) { + continue; + } + + if (Top > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) { + continue; + } + + return ResourceHob; + } + + return NULL; +} + +/** + Find the highest below 4G memory resource descriptor, except the input Resource Descriptor. + @param[in] HobList Hob start address + @param[in] MinimalNeededSize Minimal needed size. + @param[in] ExceptResourceHob Ignore this Resource Descriptor. + @retval The pointer to the Resource Descriptor HOB. +**/ +EFI_HOB_RESOURCE_DESCRIPTOR * +FindAnotherHighestBelow4GResourceDescriptor ( + IN VOID *HobList, + IN UINTN MinimalNeededSize, + IN EFI_HOB_RESOURCE_DESCRIPTOR *ExceptResourceHob + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + EFI_HOB_RESOURCE_DESCRIPTOR *ReturnResourceHob; + + ReturnResourceHob = NULL; + + for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + // + // Skip all HOBs except Resource Descriptor HOBs + // + if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + continue; + } + + // + // Skip Resource Descriptor HOBs that do not describe tested system memory + // + ResourceHob = Hob.ResourceDescriptor; + if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) { + continue; + } + + if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) { + continue; + } + + // + // Skip if the Resource Descriptor HOB equals to ExceptResourceHob + // + if (ResourceHob == ExceptResourceHob) { + continue; + } + + // + // Skip Resource Descriptor HOBs that are beyond 4G + // + if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > BASE_4GB) { + continue; + } + + // + // Skip Resource Descriptor HOBs that are too small + // + if (ResourceHob->ResourceLength < MinimalNeededSize) { + continue; + } + + // + // Return the topest Resource Descriptor + // + if (ReturnResourceHob == NULL) { + ReturnResourceHob = ResourceHob; + } else { + if (ReturnResourceHob->PhysicalStart < ResourceHob->PhysicalStart) { + ReturnResourceHob = ResourceHob; + } + } + } + + return ReturnResourceHob; +} + +/** + Check the HOB and decide if it is need inside Payload + Payload maintainer may make decision which HOB is need or needn't + Then add the check logic in the function. + @param[in] Hob The HOB to check + @retval TRUE If HOB is need inside Payload + @retval FALSE If HOB is needn't inside Payload +**/ +BOOLEAN +IsHobNeed ( + EFI_PEI_HOB_POINTERS Hob + ) +{ + if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) { + return FALSE; + } + + if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) { + if (CompareGuid (&Hob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) { + return FALSE; + } + } + + // Arrive here mean the HOB is need + return TRUE; +} + +/** + It will build Fv HOBs based on information from bootloaders. + @param[out] DxeFv The pointer to the DXE FV in memory. + @retval EFI_SUCCESS If it completed successfully. + @retval EFI_NOT_FOUND If it failed to find node in fit image. + @retval Others If it failed to build required HOBs. +**/ +EFI_STATUS +BuildFitLoadablesFvHob ( + OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv + ) +{ + EFI_STATUS Status; + VOID *Fdt; + UINT8 *GuidHob; + UNIVERSAL_PAYLOAD_BASE *PayloadBase; + INT32 ConfigNode; + INT32 Config1Node; + INT32 ImageNode; + INT32 FvNode; + INT32 Depth; + CONST FDT_PROPERTY *PropertyPtr; + INT32 TempLen; + CONST CHAR8 *Fvname; + UINT32 DataOffset; + UINT32 DataSize; + UINT32 *Data32; + + GuidHob = GetFirstGuidHob (&gUniversalPayloadBaseGuid); + if (GuidHob != NULL) { + PayloadBase = (UNIVERSAL_PAYLOAD_BASE *)GET_GUID_HOB_DATA (GuidHob); + Fdt = (VOID *)(UINTN)PayloadBase->Entry; + DEBUG ((DEBUG_INFO, "PayloadBase Entry = 0x%08x\n", PayloadBase->Entry)); + } + + Status = FdtCheckHeader (Fdt); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations")); + if (ConfigNode <= 0) { + return EFI_NOT_FOUND; + } + + Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1")); + if (Config1Node <= 0) { + return EFI_NOT_FOUND; + } + + ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images")); + if (ImageNode <= 0) { + return EFI_NOT_FOUND; + } + + FvNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, "tianocore", (INT32)AsciiStrLen ("tianocore")); + Depth = FdtNodeDepth (Fdt, FvNode); + FvNode = FdtNextNode (Fdt, FvNode, &Depth); + Fvname = FdtGetName (Fdt, FvNode, &TempLen); + while ((AsciiStrCmp ((Fvname + AsciiStrLen (Fvname) - 2), "fv") == 0)) { + if (FvNode <= 0) { + return EFI_NOT_FOUND; + } + + PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-offset", &TempLen); + Data32 = (UINT32 *)(PropertyPtr->Data); + DataOffset = SwapBytes32 (*Data32); + + PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-size", &TempLen); + Data32 = (UINT32 *)(PropertyPtr->Data); + DataSize = SwapBytes32 (*Data32); + + if (AsciiStrCmp (Fvname, "uefi-fv") == 0) { + *DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)PayloadBase->Entry + (UINTN)DataOffset); + ASSERT ((*DxeFv)->FvLength == DataSize); + } else { + BuildFvHob (((UINTN)PayloadBase->Entry + (UINTN)DataOffset), DataSize); + } + + DEBUG (( + DEBUG_INFO, + "UPL Multiple fv[%a], Base=0x%08x, size=0x%08x\n", + Fvname, + ((UINTN)PayloadBase->Entry + (UINTN)DataOffset), + DataSize, + DataOffset + )); + Depth = FdtNodeDepth (Fdt, FvNode); + FvNode = FdtNextNode (Fdt, FvNode, &Depth); + Fvname = FdtGetName (Fdt, FvNode, &TempLen); + } + + return EFI_SUCCESS; +} + +/** + It will build HOBs based on information from bootloaders. + @param[in] BootloaderParameter The starting memory address of bootloader parameter block. + @param[out] DxeFv The pointer to the DXE FV in memory. + @retval EFI_SUCCESS If it completed successfully. + @retval Others If it failed to build required HOBs. +**/ +EFI_STATUS +BuildHobs ( + IN UINTN BootloaderParameter, + OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv + ) +{ + EFI_PEI_HOB_POINTERS Hob; + UINTN MinimalNeededSize; + EFI_PHYSICAL_ADDRESS FreeMemoryBottom; + EFI_PHYSICAL_ADDRESS FreeMemoryTop; + EFI_PHYSICAL_ADDRESS MemoryBottom; + EFI_PHYSICAL_ADDRESS MemoryTop; + EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + UINT8 *GuidHob; + EFI_HOB_FIRMWARE_VOLUME *FvHob; + UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable; + ACPI_BOARD_INFO *AcpiBoardInfo; + EFI_HOB_HANDOFF_INFO_TABLE *HobInfo; + + Hob.Raw = (UINT8 *)BootloaderParameter; + MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize); + + ASSERT (Hob.Raw != NULL); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop == Hob.HandoffInformationTable->EfiFreeMemoryTop); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryTop == Hob.HandoffInformationTable->EfiMemoryTop); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom == Hob.HandoffInformationTable->EfiFreeMemoryBottom); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryBottom == Hob.HandoffInformationTable->EfiMemoryBottom); + + // + // Try to find Resource Descriptor HOB that contains Hob range EfiMemoryBottom..EfiMemoryTop + // + PhitResourceHob = FindResourceDescriptorByRange (Hob.Raw, Hob.HandoffInformationTable->EfiMemoryBottom, Hob.HandoffInformationTable->EfiMemoryTop); + if (PhitResourceHob == NULL) { + // + // Boot loader's Phit Hob is not in an available Resource Descriptor, find another Resource Descriptor for new Phit Hob + // + ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, NULL); + if (ResourceHob == NULL) { + return EFI_NOT_FOUND; + } + + MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize; + FreeMemoryBottom = MemoryBottom; + FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength; + MemoryTop = FreeMemoryTop; + } else if (PhitResourceHob->PhysicalStart + PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop >= MinimalNeededSize) { + // + // New availiable Memory range in new hob is right above memory top in old hob. + // + MemoryBottom = Hob.HandoffInformationTable->EfiFreeMemoryTop; + FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop; + FreeMemoryTop = FreeMemoryBottom + MinimalNeededSize; + MemoryTop = FreeMemoryTop; + } else if (Hob.HandoffInformationTable->EfiMemoryBottom - PhitResourceHob->PhysicalStart >= MinimalNeededSize) { + // + // New availiable Memory range in new hob is right below memory bottom in old hob. + // + MemoryBottom = Hob.HandoffInformationTable->EfiMemoryBottom - MinimalNeededSize; + FreeMemoryBottom = MemoryBottom; + FreeMemoryTop = Hob.HandoffInformationTable->EfiMemoryBottom; + MemoryTop = Hob.HandoffInformationTable->EfiMemoryTop; + } else { + // + // In the Resource Descriptor HOB contains boot loader Hob, there is no enough free memory size for payload hob + // Find another Resource Descriptor Hob + // + ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, PhitResourceHob); + if (ResourceHob == NULL) { + return EFI_NOT_FOUND; + } + + MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize; + FreeMemoryBottom = MemoryBottom; + FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength; + MemoryTop = FreeMemoryTop; + } + + HobInfo = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID *)(UINTN)FreeMemoryTop); + HobInfo->BootMode = Hob.HandoffInformationTable->BootMode; + // + // From now on, mHobList will point to the new Hob range. + // + + // + // Create an empty FvHob for the DXE FV that contains DXE core. + // + BuildFvHob ((EFI_PHYSICAL_ADDRESS)0, 0); + // + // Since payload created new Hob, move all hobs except PHIT from boot loader hob list. + // + while (!END_OF_HOB_LIST (Hob)) { + if (IsHobNeed (Hob)) { + // Add this hob to payload HOB + AddNewHob (&Hob); + } + + Hob.Raw = GET_NEXT_HOB (Hob); + } + + BuildFitLoadablesFvHob (DxeFv); + + // + // Create guid hob for acpi board information + // + GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid); + if (GuidHob != NULL) { + AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA (GuidHob); + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid); + if (GuidHob == NULL) { + AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp); + ASSERT (AcpiBoardInfo != NULL); + } + } + + // + // Update DXE FV information to first fv hob in the hob list, which + // is the empty FvHob created before. + // + FvHob = GetFirstHob (EFI_HOB_TYPE_FV); + FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)*DxeFv; + FvHob->Length = (*DxeFv)->FvLength; + return EFI_SUCCESS; +} + +/** + Entry point to the C language phase of UEFI payload. + @param[in] BootloaderParameter The starting address of bootloader parameter block. + @retval It will not return if SUCCESS, and return error when passing bootloader parameter. +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN UINTN BootloaderParameter + ) +{ + EFI_STATUS Status; + PHYSICAL_ADDRESS DxeCoreEntryPoint; + EFI_PEI_HOB_POINTERS Hob; + EFI_FIRMWARE_VOLUME_HEADER *DxeFv; + + mHobList = (VOID *)BootloaderParameter; + DxeFv = NULL; + // Call constructor for all libraries + ProcessLibraryConstructorList (); + + DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n")); + DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN))); + + DEBUG_CODE ( + // + // Dump the Hobs from boot loader + // + PrintHob (mHobList); + ); + + // Initialize floating point operating environment to be compliant with UEFI spec. + InitializeFloatingPointUnits (); + + // Build HOB based on information from Bootloader + Status = BuildHobs (BootloaderParameter, &DxeFv); + ASSERT_EFI_ERROR (Status); + + FixUpPcdDatabase (DxeFv); + Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint); + ASSERT_EFI_ERROR (Status); + + // + // Mask off all legacy 8259 interrupt sources + // + IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF); + IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF); + + Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob (EFI_HOB_TYPE_HANDOFF); + HandOffToDxeCore (DxeCoreEntryPoint, Hob); + + // Should not get here + CpuDeadLoop (); + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf new file mode 100644 index 0000000000..a7d1a8c9e5 --- /dev/null +++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf @@ -0,0 +1,98 @@ +## @file +# This is the first module for UEFI payload. +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FitUniversalPayloadEntry + FILE_GUID = CED5A8A9-B6EA-4D5A-8689-577EE88566CF + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + FitUniversalPayloadEntry.c + LoadDxeCore.c + MemoryAllocation.c + PrintHob.c + AcpiTable.c + +[Sources.Ia32] + X64/VirtualMemory.h + X64/VirtualMemory.c + Ia32/DxeLoadFunc.c + Ia32/IdtVectorAsm.nasm + +[Sources.X64] + X64/VirtualMemory.h + X64/VirtualMemory.c + X64/DxeLoadFunc.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + BaseLib + SerialPortLib + IoLib + HobLib + PeCoffLib + CpuLib + FdtLib + +[Guids] + gEfiMemoryTypeInformationGuid + gEfiFirmwareFileSystem2Guid + gEfiGraphicsInfoHobGuid + gEfiGraphicsDeviceInfoHobGuid + gUefiAcpiBoardInfoGuid + gEfiSmbiosTableGuid + gUefiSerialPortInfoGuid + gUniversalPayloadExtraDataGuid + gUniversalPayloadBaseGuid + gPcdDataBaseHobGuid + gUniversalPayloadSmbiosTableGuid + gEfiHobMemoryAllocBspStoreGuid + gUniversalPayloadAcpiTableGuid + gUniversalPayloadPciRootBridgeInfoGuid + gUniversalPayloadSmbios3TableGuid + +[FeaturePcd.IA32] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES + +[FeaturePcd.X64] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ## CONSUMES + + +[Pcd.IA32,Pcd.X64] + gUefiPayloadPkgTokenSpaceGuid.PcdPcdDriverFile + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ## CONSUMES + + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize + gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize + + gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## SOMETIMES_CONSUMES diff --git a/UefiPayloadPkg/UefiPayloadPkg.dec b/UefiPayloadPkg/UefiPayloadPkg.dec index e2e4a79db3..2f1fd82487 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dec +++ b/UefiPayloadPkg/UefiPayloadPkg.dec @@ -24,6 +24,9 @@ # gUefiPayloadPkgTokenSpaceGuid = {0x1d127ea, 0xf6f1, 0x4ef6, {0x94, 0x15, 0x8a, 0x0, 0x0, 0x93, 0xf8, 0x9d}} + ## Include/Guid/UniversalPayloadBase.h + gUniversalPayloadBaseGuid = { 0x03d4c61d, 0x2713, 0x4ec5, {0xa1, 0xcc, 0x88, 0x3b, 0xe9, 0xdc, 0x18, 0xe5 } } + # # Gop Temp # diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc index 47812048dd..af9308ef8e 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dsc +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -30,7 +30,6 @@ DEFINE PS2_KEYBOARD_ENABLE = FALSE DEFINE RAM_DISK_ENABLE = FALSE DEFINE SIO_BUS_ENABLE = FALSE - DEFINE UNIVERSAL_PAYLOAD = FALSE DEFINE SECURITY_STUB_ENABLE = TRUE DEFINE SMM_SUPPORT = FALSE DEFINE PLATFORM_BOOT_TIMEOUT = 3 @@ -44,6 +43,14 @@ DEFINE BOOTSPLASH_IMAGE = FALSE DEFINE NVME_ENABLE = TRUE DEFINE CAPSULE_SUPPORT = FALSE + # + # Setup Universal Payload + # + # ELF: Build UniversalPayload file as UniversalPayload.elf + # FIT: Build UniversalPayload file as UniversalPayload.fit + # + DEFINE UNIVERSAL_PAYLOAD = FALSE + DEFINE UNIVERSAL_PAYLOAD_FORMAT = ELF # # NULL: NullMemoryTestDxe @@ -311,7 +318,7 @@ VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf - + FdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf [LibraryClasses.common] !if $(BOOTSPLASH_IMAGE) SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf @@ -600,14 +607,26 @@ !if "IA32" in "$(ARCH)" [Components.IA32] !if $(UNIVERSAL_PAYLOAD) == TRUE - UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf + !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF" + UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf + !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT" + UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf + !else + UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf + !endif !else UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf !endif !else [Components.X64] !if $(UNIVERSAL_PAYLOAD) == TRUE - UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf + !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF" + UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf + !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT" + UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf + !else + UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf + !endif !else UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf !endif diff --git a/UefiPayloadPkg/UniversalPayloadBuild.py b/UefiPayloadPkg/UniversalPayloadBuild.py index 47f37b3377..9a83fc9e44 100644 --- a/UefiPayloadPkg/UniversalPayloadBuild.py +++ b/UefiPayloadPkg/UniversalPayloadBuild.py @@ -10,10 +10,22 @@ import subprocess import os import shutil import sys +import pathlib from ctypes import * -from Tools.ElfFv import ReplaceFv + sys.dont_write_bytecode = True +class bcolors: + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKCYAN = '\033[96m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + class UPLD_INFO_HEADER(LittleEndianStructure): _pack_ = 1 _fields_ = [ @@ -36,40 +48,114 @@ class UPLD_INFO_HEADER(LittleEndianStructure): self.ImageId = b'UEFI' self.ProducerId = b'INTEL' -def BuildUniversalPayload(Args): - def RunCommand(cmd): - print(cmd) - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE']) - while True: - line = p.stdout.readline() - if not line: - break - print(line.strip().decode(errors='ignore')) - - p.communicate() - if p.returncode != 0: - print("- Failed - error happened when run command: %s"%cmd) - raise Exception("ERROR: when run command: %s"%cmd) +def ValidateSpecRevision (Argument): + try: + (MajorStr, MinorStr) = Argument.split('.') + except: + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + # + # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version. + # + if len(MinorStr) > 0 and len(MinorStr) < 3: + try: + Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4) + except: + raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument)) + else: + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + + if len(MajorStr) > 0 and len(MajorStr) < 3: + try: + Major = int(MajorStr, 16) + except: + raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument)) + else: + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + + return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0) + +def Validate32BitInteger (Argument): + try: + Value = int (Argument, 0) + except: + raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument)) + if Value < 0: + raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument)) + if Value > 0xffffffff: + raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument)) + return Value +def ValidateAddFv (Argument): + Value = Argument.split ("=") + if len (Value) != 2: + raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) + if Value[0][-3:] != "_fv": + raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) + if Value[1][-3:].lower () != ".fv": + raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) + if os.path.exists (Value[1]) == False: + raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1])) + return Value + +def RunCommand(cmd): + print(cmd) + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE']) + while True: + line = p.stdout.readline() + if not line: + break + print(line.strip().decode(errors='ignore')) + + p.communicate() + if p.returncode != 0: + print("- Failed - error happened when run command: %s"%cmd) + raise Exception("ERROR: when run command: %s"%cmd) + +def BuildUniversalPayload(Args): BuildTarget = Args.Target ToolChain = Args.ToolChain Quiet = "--quiet" if Args.Quiet else "" - ElfToolChain = 'CLANGDWARF' - BuildDir = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64")) - BuildModule = "" - BuildArch = "" + if Args.Fit == True: + PayloadEntryToolChain = ToolChain + Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=FIT") + UpldEntryFile = "FitUniversalPayloadEntry" + else: + PayloadEntryToolChain = 'CLANGDWARF' + Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=ELF") + UpldEntryFile = "UniversalPayloadEntry" + + BuildDir = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64")) if Args.Arch == 'X64': BuildArch = "X64" - EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll")) + FitArch = "x86_64" + ObjCopyFlag = "elf64-x86-64" + EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile))) else: BuildArch = "IA32 -a X64" - EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll")) + FitArch = "x86" + ObjCopyFlag = "elf32-i386" + EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile))) + EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/{}.inf".format (UpldEntryFile)) DscPath = os.path.normpath("UefiPayloadPkg/UefiPayloadPkg.dsc") + DxeFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) + BdsFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) + NetworkFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv")) + PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt") ModuleReportPath = os.path.join(BuildDir, "UefiUniversalPayloadEntry.txt") UpldInfoFile = os.path.join(BuildDir, "UniversalPayloadInfo.bin") + if "CLANG_BIN" in os.environ: + LlvmObjcopyPath = os.path.join(os.environ["CLANG_BIN"], "llvm-objcopy") + else: + LlvmObjcopyPath = "llvm-objcopy" + try: + RunCommand('"%s" --version'%LlvmObjcopyPath) + except: + print("- Failed - Please check if LLVM is installed or if CLANG_BIN is set correctly") + sys.exit(1) + Pcds = "" if (Args.pcd != None): for PcdItem in Args.pcd: @@ -84,7 +170,6 @@ def BuildUniversalPayload(Args): # Building DXE core and DXE drivers as DXEFV. # if Args.BuildEntryOnly == False: - PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt") BuildPayload = "build -p {} -b {} -a X64 -t {} -y {} {}".format (DscPath, BuildTarget, ToolChain, PayloadReportPath, Quiet) BuildPayload += Pcds BuildPayload += Defines @@ -93,94 +178,138 @@ def BuildUniversalPayload(Args): # Building Universal Payload entry. # if Args.PreBuildUplBinary is None: - EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf") - BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, ElfToolChain, ModuleReportPath, Quiet) + BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, PayloadEntryToolChain, ModuleReportPath, Quiet) BuildModule += Pcds BuildModule += Defines RunCommand(BuildModule) if Args.PreBuildUplBinary is not None: - EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf") + if Args.Fit == False: + EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf") + else: + EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.fit") shutil.copy (os.path.abspath(Args.PreBuildUplBinary), EntryOutputDir) # - # Buid Universal Payload Information Section ".upld_info" + # Build Universal Payload Information Section ".upld_info" # - upld_info_hdr = UPLD_INFO_HEADER() - upld_info_hdr.SpecRevision = Args.SpecRevision - upld_info_hdr.Revision = Args.Revision - upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16] - upld_info_hdr.ImageId = Args.ImageId.encode()[:16] - upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0 - fp = open(UpldInfoFile, 'wb') - fp.write(bytearray(upld_info_hdr)) - fp.close() + if Args.Fit == False: + upld_info_hdr = UPLD_INFO_HEADER() + upld_info_hdr.SpecRevision = Args.SpecRevision + upld_info_hdr.Revision = Args.Revision + upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16] + upld_info_hdr.ImageId = Args.ImageId.encode()[:16] + upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0 + fp = open(UpldInfoFile, 'wb') + fp.write(bytearray(upld_info_hdr)) + fp.close() + + if Args.BuildEntryOnly == False: + import Tools.ElfFv as ElfFv + ElfFv.ReplaceFv (EntryOutputDir, UpldInfoFile, '.upld_info', Alignment = 4) + if Args.Fit == False: + shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf')) + else: + shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.fit')) MultiFvList = [] if Args.BuildEntryOnly == False: MultiFvList = [ - ['uefi_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ], - ['bds_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ], - ['network_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv")) ], + ['uefi_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ], + ['bds_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ], + ['network_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))], ] - AddSectionName = '.upld_info' - ReplaceFv (EntryOutputDir, UpldInfoFile, AddSectionName, Alignment = 4) - if Args.PreBuildUplBinary is None: - shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf')) - return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf') + if Args.Fit == True: + import Tools.MkFitImage as MkFitImage + import pefile + fit_image_info_header = MkFitImage.FIT_IMAGE_INFO_HEADER() + fit_image_info_header.Description = 'Uefi Universal Payload' + fit_image_info_header.UplVersion = Args.SpecRevision + fit_image_info_header.Type = 'flat-binary' + fit_image_info_header.Arch = FitArch + fit_image_info_header.Compression = 'none' + fit_image_info_header.Revision = Args.Revision + fit_image_info_header.BuildType = Args.Target.lower() + fit_image_info_header.Capabilities = None + fit_image_info_header.Producer = Args.ProducerId.lower() + fit_image_info_header.ImageId = Args.ImageId.lower() + fit_image_info_header.Binary = os.path.join(BuildDir, 'UniversalPayload.fit') + fit_image_info_header.TargetPath = os.path.join(BuildDir, 'UniversalPayload.fit') + fit_image_info_header.UefifvPath = DxeFvOutputDir + fit_image_info_header.BdsfvPath = BdsFvOutputDir + fit_image_info_header.NetworkfvPath = NetworkFvOutputDir + fit_image_info_header.DataOffset = 0x1000 + fit_image_info_header.LoadAddr = Args.LoadAddress + fit_image_info_header.Project = 'tianocore' + + TargetRebaseFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".pecoff") + TargetRebaseEntryFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".entry") + -def main(): - def ValidateSpecRevision (Argument): - try: - (MajorStr, MinorStr) = Argument.split('.') - except: - raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) # - # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version. + # Rebase PECOFF to load address # - if len(MinorStr) > 0 and len(MinorStr) < 3: - try: - Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4) - except: - raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument)) - else: - raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + RunCommand ( + "GenFw -e SEC -o {} {}".format ( + TargetRebaseFile, + fit_image_info_header.Binary + )) + RunCommand ( + "GenFw --rebase 0x{:02X} -o {} {} ".format ( + fit_image_info_header.LoadAddr + fit_image_info_header.DataOffset, + TargetRebaseFile, + TargetRebaseFile, + )) - if len(MajorStr) > 0 and len(MajorStr) < 3: - try: - Major = int(MajorStr, 16) - except: - raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument)) - else: - raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + # + # Open PECOFF relocation table binary. + # + RelocBinary = b'' + PeCoff = pefile.PE (TargetRebaseFile) + for reloc in PeCoff.DIRECTORY_ENTRY_BASERELOC: + for entry in reloc.entries: + if (entry.type == 0): + continue + Type = entry.type + Offset = entry.rva + fit_image_info_header.DataOffset + RelocBinary += Type.to_bytes (8, 'little') + Offset.to_bytes (8, 'little') + RelocBinary += b'\x00' * (0x1000 - (len(RelocBinary) % 0x1000)) - return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0) + # + # Output UniversalPayload.entry + # + TempBinary = open (TargetRebaseFile, 'rb') + TianoBinary = TempBinary.read () + TempBinary.close () - def Validate32BitInteger (Argument): - try: - Value = int (Argument, 0) - except: - raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument)) - if Value < 0: - raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument)) - if Value > 0xffffffff: - raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument)) - return Value - - def ValidateAddFv (Argument): - Value = Argument.split ("=") - if len (Value) != 2: - raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) - if Value[0][-3:] != "_fv": - raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) - if Value[1][-3:].lower () != ".fv": - raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) - if os.path.exists (Value[1]) == False: - raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1])) - return Value + TianoEntryBinary = TianoBinary + RelocBinary + TianoEntryBinary += (b'\x00' * (0x1000 - (len(TianoBinary) % 0x1000))) + TianoEntryBinarySize = len (TianoEntryBinary) + + TempBinary = open(TargetRebaseEntryFile, "wb") + TempBinary.truncate() + TempBinary.write(TianoEntryBinary) + TempBinary.close() + + # + # Calculate entry and update relocation table start address and data-size. + # + fit_image_info_header.Entry = PeCoff.OPTIONAL_HEADER.ImageBase + PeCoff.OPTIONAL_HEADER.AddressOfEntryPoint + fit_image_info_header.RelocStart = fit_image_info_header.DataOffset + len(TianoBinary) + fit_image_info_header.DataSize = TianoEntryBinarySize + fit_image_info_header.Binary = TargetRebaseEntryFile + + if MkFitImage.MakeFitImage(fit_image_info_header) is True: + print('\nSuccessfully build Fit Image') + else: + sys.exit(1) + return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.fit') + else: + return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf') +def main(): parser = argparse.ArgumentParser(description='For building Universal Payload') parser.add_argument('-t', '--ToolChain') parser.add_argument('-b', '--Target', default='DEBUG') @@ -192,13 +321,16 @@ def main(): parser.add_argument("-s", "--SpecRevision", type=ValidateSpecRevision, default ='0.7', help='Indicates compliance with a revision of this specification in the BCD format.') parser.add_argument("-r", "--Revision", type=Validate32BitInteger, default ='0x0000010105', help='Revision of the Payload binary. Major.Minor.Revision.Build') parser.add_argument("-o", "--ProducerId", default ='INTEL', help='A null-terminated OEM-supplied string that identifies the payload producer (16 bytes maximal).') + parser.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file') + parser.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file') parser.add_argument("-sk", "--SkipBuild", action='store_true', help='Skip UniversalPayload build') parser.add_argument("-af", "--AddFv", type=ValidateAddFv, action='append', help='Add or replace specific FV into payload, Ex: uefi_fv=XXX.fv') - command_group = parser.add_mutually_exclusive_group() - command_group.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file') - command_group.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file') + parser.add_argument("-f", "--Fit", action='store_true', help='Build UniversalPayload file as UniversalPayload.fit', default=False) + parser.add_argument('-l', "--LoadAddress", type=int, help='Specify payload load address', default =0x000800000) + args = parser.parse_args() + MultiFvList = [] UniversalPayloadBinary = args.PreBuildUplBinary if (args.SkipBuild == False): @@ -208,12 +340,24 @@ def main(): for (SectionName, SectionFvFile) in args.AddFv: MultiFvList.append ([SectionName, SectionFvFile]) + def ReplaceFv (UplBinary, SectionFvFile, SectionName): + print (bcolors.OKGREEN + "Patch {}={} into {}".format (SectionName, SectionFvFile, UplBinary) + bcolors.ENDC) + if (args.Fit == False): + import Tools.ElfFv as ElfFv + return ElfFv.ReplaceFv (UplBinary, SectionFvFile, '.upld.{}'.format (SectionName)) + else: + import Tools.MkFitImage as MkFitImage + return MkFitImage.ReplaceFv (UplBinary, SectionFvFile, SectionName) + if (UniversalPayloadBinary != None): for (SectionName, SectionFvFile) in MultiFvList: if os.path.exists (SectionFvFile) == False: continue - print ("Patch {}={} into {}".format (SectionName, SectionFvFile, UniversalPayloadBinary)) - ReplaceFv (UniversalPayloadBinary, SectionFvFile, '.upld.{}'.format (SectionName)) + + status = ReplaceFv (UniversalPayloadBinary, SectionFvFile, SectionName.replace ("_", "-")) + if status != 0: + print (bcolors.FAIL + "[Fail] Patch {}={}".format (SectionName, SectionFvFile) + bcolors.ENDC) + return status print ("\nSuccessfully build Universal Payload") -- 2.39.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108718): https://edk2.groups.io/g/devel/message/108718 Mute This Topic: https://groups.io/mt/101378805/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support 2023-09-15 8:58 ` [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support brucex.wang @ 2023-09-15 9:02 ` Guo, Gua 2023-09-15 10:26 ` Sheng Lean Tan 2023-09-15 9:06 ` Lu, James 1 sibling, 1 reply; 10+ messages in thread From: Guo, Gua @ 2023-09-15 9:02 UTC (permalink / raw) To: Wang, BruceX, devel@edk2.groups.io; +Cc: Dong, Guo, Rhodes, Sean, Lu, James Reviewed-by: Gua Guo <gua.guo@intel.com> -----Original Message----- From: Wang, BruceX <brucex.wang@intel.com> Sent: Friday, September 15, 2023 4:58 PM To: devel@edk2.groups.io Cc: Wang, BruceX <brucex.wang@intel.com>; Dong, Guo <guo.dong@intel.com>; Rhodes, Sean <sean@starlabs.systems>; Lu, James <james.lu@intel.com>; Guo, Gua <gua.guo@intel.com> Subject: [PATCH v2 2/2] UefiPayloadPkg: Add FIT support From: "Brucex.Wang" <brucex.wang@intel.com> Provide Fit format for UniversalPayload, developer can use argument "--Fit" to build UniversalPayload.fit Cc: Guo Dong <guo.dong@intel.com> Cc: Sean Rhodes <sean@starlabs.systems> Cc: James Lu <james.lu@intel.com> Cc: Gua Guo <gua.guo@intel.com> Signed-off-by: BruceX Wang <brucex.wang@intel.com> --- .../Include/Guid/UniversalPayloadBase.h | 21 + UefiPayloadPkg/PayloadLoaderPeim/FitLib.h | 60 ++ .../PayloadLoaderPeim/FitLib/FitLib.c | 127 ++++ .../PayloadLoaderPeim/FitPayloadLoaderPeim.c | 150 ++++ .../FitPayloadLoaderPeim.inf | 59 ++ UefiPayloadPkg/Readme.md | 191 +++++ UefiPayloadPkg/Tools/MkFitImage.py | 272 ++++++++ .../FitUniversalPayloadEntry.c | 654 ++++++++++++++++++ .../FitUniversalPayloadEntry.inf | 98 +++ UefiPayloadPkg/UefiPayloadPkg.dec | 3 + UefiPayloadPkg/UefiPayloadPkg.dsc | 27 +- UefiPayloadPkg/UniversalPayloadBuild.py | 328 ++++++--- 12 files changed, 1894 insertions(+), 96 deletions(-) create mode 100644 UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf create mode 100644 UefiPayloadPkg/Readme.md create mode 100644 UefiPayloadPkg/Tools/MkFitImage.py create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf diff --git a/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h new file mode 100644 index 0000000000..31c9ec0bfb --- /dev/null +++ b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h @@ -0,0 +1,21 @@ +/** @file + Universal Payload general definitions. + +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Revision Reference: + - Universal Payload Specification 0.75 (https://universalpayload.github.io/documentation/) +**/ + +#ifndef UNIVERSAL_PAYLOAD_BASE_H_ +#define UNIVERSAL_PAYLOAD_BASE_H_ + +extern GUID gUniversalPayloadBaseGuid; + +typedef struct { + UNIVERSAL_PAYLOAD_GENERIC_HEADER Header; + EFI_PHYSICAL_ADDRESS Entry; +} UNIVERSAL_PAYLOAD_BASE; + +#endif // UNIVERSAL_PAYLOAD_BASE_H_ diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h new file mode 100644 index 0000000000..0514d675a6 --- /dev/null +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h @@ -0,0 +1,60 @@ +/** @file + FIT Load Image Support +Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef FIT_LIB_H_ +#define FIT_LIB_H_ + +#include <PiPei.h> +#include <Library/DebugLib.h> +#include <Library/FdtLib.h> + +typedef struct { + UINT64 RelocateType; + UINT64 Offset; +} FIT_RELOCATE_ITEM; + +typedef struct { + EFI_PHYSICAL_ADDRESS ImageBase; + EFI_PHYSICAL_ADDRESS PayloadBaseAddress; + UINT64 PayloadSize; + UINTN PayloadEntryOffset; + UINTN PayloadEntrySize; + EFI_PHYSICAL_ADDRESS PayloadEntryPoint; + UINTN RelocateTableOffset; + UINTN RelocateTableCount; + EFI_PHYSICAL_ADDRESS PayloadLoadAddress; +} FIT_IMAGE_CONTEXT; + +typedef struct { + UINT8 *Name; + UINT32 Offset; +} PROPERTY_DATA; + +#define IMAGE_BASE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, ImageBase) +#define PAYLOAD_BASE_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadBaseAddress) +#define PAYLOAD_BASE_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadSize) +#define PAYLOAD_ENTRY_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryOffset) +#define PAYLOAD_ENTRY_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntrySize) +#define PAYLOAD_ENTRY_POINT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryPoint) +#define RELOCATE_TABLE_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableOffset) +#define RELOCATE_TABLE_COUNT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableCount) +#define PAYLOAD_LOAD_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadLoadAddress) + +/** + Parse the FIT image info. + @param[in] ImageBase Memory address of an image. + @param[out] Context The FIT image context pointer. + @retval EFI_UNSUPPORTED Unsupported binary type. + @retval EFI_SUCCESS FIT binary is loaded successfully. +**/ +EFI_STATUS +EFIAPI +ParseFitImage ( + IN VOID *ImageBase, + OUT FIT_IMAGE_CONTEXT *Context + ); + +#endif diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c new file mode 100644 index 0000000000..9d1d8a4f61 --- /dev/null +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c @@ -0,0 +1,127 @@ +/** @file + FIT Load Image Support +Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "FitLib.h" + +PROPERTY_DATA PropertyData32List[] = { + { "data-offset", PAYLOAD_ENTRY_OFFSET_OFFSET }, + { "data-size", PAYLOAD_ENTRY_SIZE_OFFSET }, + { "reloc-start", RELOCATE_TABLE_OFFSET_OFFSET } +}; + +PROPERTY_DATA PropertyData64List[] = { + { "entry-start", PAYLOAD_ENTRY_POINT_OFFSET }, + { "load", PAYLOAD_LOAD_ADDR_OFFSET } +}; + +/** + Parse the target firmware image info in FIT. + @param[in] Fdt Memory address of a fdt. + @param[in] Firmware Target name of an image. + @param[out] Context The FIT image context pointer. + @retval EFI_NOT_FOUND FIT node dose not find. + @retval EFI_SUCCESS FIT binary is loaded successfully. +**/ +EFI_STATUS +EFIAPI +FitParseFirmwarePropertyData ( + IN VOID *Fdt, + IN CHAR8 *Firmware, + OUT FIT_IMAGE_CONTEXT *Context + ) +{ + CONST FDT_PROPERTY *PropertyPtr; + INT32 ImageNode; + INT32 TianoNode; + INT32 TempLen; + UINT32 *Data32; + UINT64 *Data64; + UINT32 *ContextOffset32; + UINT64 *ContextOffset64; + INT32 Index; + + ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images")); + if (ImageNode <= 0) { + return EFI_NOT_FOUND; + } + + TianoNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, Firmware, (INT32)AsciiStrLen (Firmware)); + if (TianoNode <= 0) { + return EFI_NOT_FOUND; + } + + for (Index = 0; Index < sizeof (PropertyData32List) / sizeof (PROPERTY_DATA); Index++) { + PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData32List[Index].Name, &TempLen); + Data32 = (UINT32 *)(PropertyPtr->Data); + ContextOffset32 = (UINT32 *)((UINTN)Context + PropertyData32List[Index].Offset); + *ContextOffset32 = Fdt32ToCpu (*Data32); + } + + for (Index = 0; Index < sizeof (PropertyData64List)/sizeof (PROPERTY_DATA); Index++) { + PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData64List[Index].Name, &TempLen); + Data64 = (UINT64 *)(PropertyPtr->Data); + ContextOffset64 = (UINT64 *)((UINTN)Context + PropertyData64List[Index].Offset); + *ContextOffset64 = Fdt64ToCpu (*Data64); + } + + return EFI_SUCCESS; +} + +/** + Parse the FIT image info. + @param[in] ImageBase Memory address of an image. + @param[out] Context The FIT image context pointer. + @retval EFI_UNSUPPORTED Unsupported binary type. + @retval EFI_SUCCESS FIT binary is loaded successfully. +**/ +EFI_STATUS +EFIAPI +ParseFitImage ( + IN VOID *ImageBase, + OUT FIT_IMAGE_CONTEXT *Context + ) +{ + VOID *Fdt; + INT32 ConfigNode; + INT32 Config1Node; + CONST FDT_PROPERTY *PropertyPtr; + INT32 TempLen; + UINT32 *Data32; + UINT64 Value; + EFI_STATUS Status; + UINTN UplSize; + CHAR8 *Firmware; + + Status = FdtCheckHeader (ImageBase); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Fdt = ImageBase; + PropertyPtr = FdtGetProperty (Fdt, 0, "size", &TempLen); + Data32 = (UINT32 *)(PropertyPtr->Data); + UplSize = Value = Fdt32ToCpu (*Data32); + ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations")); + if (ConfigNode <= 0) { + return EFI_NOT_FOUND; + } + + Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1")); + if (Config1Node <= 0) { + return EFI_NOT_FOUND; + } + + PropertyPtr = FdtGetProperty (Fdt, Config1Node, "firmware", &TempLen); + Firmware = (CHAR8 *)(PropertyPtr->Data); + + FitParseFirmwarePropertyData (Fdt, Firmware, Context); + + Context->ImageBase = (EFI_PHYSICAL_ADDRESS)ImageBase; + Context->PayloadSize = UplSize; + Context->RelocateTableCount = (Context->PayloadEntrySize - (Context->RelocateTableOffset - Context->PayloadEntryOffset)) / sizeof (FIT_RELOCATE_ITEM); + + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c new file mode 100644 index 0000000000..3c5dacbb65 --- /dev/null +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c @@ -0,0 +1,150 @@ +/** @file + ELF Load Image Support +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include <PiPei.h> +#include <UniversalPayload/UniversalPayload.h> +#include <Guid/UniversalPayloadBase.h> +#include <UniversalPayload/ExtraData.h> + +#include <Ppi/LoadFile.h> + +#include <Library/DebugLib.h> +#include <Library/HobLib.h> +#include <Library/PeiServicesLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/BaseMemoryLib.h> + +#include "FitLib.h" + +/** + The wrapper function of PeiLoadImageLoadImage(). + @param This - Pointer to EFI_PEI_LOAD_FILE_PPI. + @param FileHandle - Pointer to the FFS file header of the image. + @param ImageAddressArg - Pointer to PE/TE image. + @param ImageSizeArg - Size of PE/TE image. + @param EntryPoint - Pointer to entry point of specified image file for output. + @param AuthenticationState - Pointer to attestation authentication state of image. + @return Status of PeiLoadImageLoadImage(). +**/ +EFI_STATUS +EFIAPI +PeiLoadFileLoadPayload ( + IN CONST EFI_PEI_LOAD_FILE_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL, + OUT UINT64 *ImageSizeArg OPTIONAL, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +{ + EFI_STATUS Status; + FIT_IMAGE_CONTEXT Context; + UINTN Instance; + VOID *Binary; + FIT_RELOCATE_ITEM *RelocateTable; + UNIVERSAL_PAYLOAD_BASE *PayloadBase; + UINTN Length; + UINTN Delta; + UINTN Index; + + Instance = 0; + do { + Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++, FileHandle, &Binary, AuthenticationState); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (&Context, sizeof (Context)); + Status = ParseFitImage (Binary, &Context); + } while (EFI_ERROR (Status)); + + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + DEBUG (( + DEBUG_INFO, + "Before Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n", + Context.PayloadBaseAddress, + Context.PayloadSize, + Context.PayloadEntryPoint + )); + Context.PayloadBaseAddress = (EFI_PHYSICAL_ADDRESS)AllocatePages (EFI_SIZE_TO_PAGES (Context.PayloadSize)); + + RelocateTable = (FIT_RELOCATE_ITEM *)(UINTN)(Context.PayloadBaseAddress + Context.RelocateTableOffset); + CopyMem ((VOID *)Context.PayloadBaseAddress, Binary, Context.PayloadSize); + + if (Context.PayloadBaseAddress > Context.PayloadLoadAddress) { + Delta = Context.PayloadBaseAddress - Context.PayloadLoadAddress; + Context.PayloadEntryPoint += Delta; + for (Index = 0; Index < Context.RelocateTableCount; Index++) { + if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) { + *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) + Delta; + } + } + } else { + Delta = Context.PayloadLoadAddress - Context.PayloadBaseAddress; + Context.PayloadEntryPoint -= Delta; + for (Index = 0; Index < Context.RelocateTableCount; Index++) { + if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) { + *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) - Delta; + } + } + } + + DEBUG (( + DEBUG_INFO, + "After Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n", + Context.PayloadBaseAddress, + Context.PayloadSize, + Context.PayloadEntryPoint + )); + + Length = sizeof (UNIVERSAL_PAYLOAD_BASE); + PayloadBase = BuildGuidHob ( + &gUniversalPayloadBaseGuid, + Length + ); + PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)Context.ImageBase; + + *ImageAddressArg = Context.PayloadBaseAddress; + *ImageSizeArg = Context.PayloadSize; + *EntryPoint = Context.PayloadEntryPoint; + + return EFI_SUCCESS; +} + +EFI_PEI_LOAD_FILE_PPI mPeiLoadFilePpi = { + PeiLoadFileLoadPayload +}; + +EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiLoadFilePpiGuid, + &mPeiLoadFilePpi +}; + +/** + Install Pei Load File PPI. + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + @retval EFI_SUCESS The entry point executes successfully. + @retval Others Some error occurs during the execution of this function. +**/ +EFI_STATUS +EFIAPI +InitializeFitPayloadLoaderPeim ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + + Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList); + + return Status; +} diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf new file mode 100644 index 0000000000..acb0e09f68 --- /dev/null +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf @@ -0,0 +1,59 @@ +## @file +# Produce LoadFile PPI for payload loading. +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FitPayloadLoaderPeim + FILE_GUID = 55AC82C8-FC17-4C56-BCDA-990BB0A73E41 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializeFitPayloadLoaderPeim + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + FitPayloadLoaderPeim.c + FitLib.h + FitLib/FitLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + PcAtChipsetPkg/PcAtChipsetPkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + PcdLib + MemoryAllocationLib + BaseMemoryLib + PeiServicesLib + HobLib + BaseLib + PeimEntryPoint + DebugLib + FdtLib + +[Ppis] + gEfiPeiLoadFilePpiGuid ## PRODUCES + +[Pcd] + gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister + gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister + +[Guids] + gUniversalPayloadExtraDataGuid ## PRODUCES + gUniversalPayloadBaseGuid ## PRODUCES + +[Depex] + TRUE diff --git a/UefiPayloadPkg/Readme.md b/UefiPayloadPkg/Readme.md new file mode 100644 index 0000000000..616a5dd467 --- /dev/null +++ b/UefiPayloadPkg/Readme.md @@ -0,0 +1,191 @@ +# UefiPayloadPkg +Provide UEFI Universal Payload for different bootloader to generate EFI environment + +# Spec + +UniversalPayload URL: https://universalscalablefirmware.github.io/documentation/2_universal_payload.html + +ELF Format URL: https://refspecs.linuxfoundation.org/elf/elf.pdf + +FIT Format URL: https://universalpayload.github.io/spec/chapter2-payload-image-format.html + +# Uefi UniversalPayload Format + | Binary Format | HandOffPayload - HOB | + |---------------|----------------------| + | ELF | V (Default) | + | FIT | V | + +# Binary Format + - ELF + ``` + + +-----------------------+ + | | UniversalPayloadEntry | <----------- UefiPayloadPkg\UefiPayloadEntry\UniversalPayloadEntry.c:_ModuleEntryPoint (HOB) + | +-----------------------+ + | | .upld_info | patch it directly + ELF Format | +-----------------------+ + | | .upld.uefi_fv | patch it directly + | +-----------------------+ + | | .upld.bds_fv | patch it directly + | +-----------------------+ + | | .upld.<afpx>_fv | patch it directly + + +-----------------------+ + ``` + + - FIT + ``` + + +-----------------------+ + FIT Data | | FIT Header | <----------- Generate by pylibfdt + + +-----------------------+ + PECOFF Format | | UniversalPayloadEntry | <----------- UefiPayloadPkg\UefiPayloadEntry\FitUniversalPayloadEntry.c:_ModuleEntryPoint (HOB) + + +-----------------------+ + Relocate Data | | reloc-start | + + +-----------------------+ + | | uefi_fv | patch it directly + | +-----------------------+ + Multi Binary | | bds_fv | patch it directly + | +-----------------------+ + | | afp_xxx_fv | patch it directly + | +-----------------------+ + | | afp_xxx_fv | patch it directly + + +-----------------------+ + ``` + +# Environment + - ELF + ``` + Download and install https://github.com/llvm/llvm-project/releases/tag/llvmorg-10.0.1 + ``` + - FIT + - Windows + ```powershell + Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) + choco install dtc-msys2 + pip3 install pefile + pip3 install swig + pip3 install pylibfdt + ``` + - Ubuntu + ```bash + sudo apt install -y u-boot-tools + pip3 install pefile + pip3 install swig + pip3 install pylibfdt + ``` +# How to build UEFI UniversalPayload + - Windows + - edksetup Rebuild + - Linux + - make -C BaseTools + - source edksetup.sh + + - UniversalPayload.elf + - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG> + - llvm-objdump -h Build/UefiPayloadPkgX64/UniversalPayload.elf + + - UniversalPayload.fit + - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG> --Fit + - fdtdump Build/UefiPayloadPkgX64/UniversalPayload.fit + +# Edk2boot + UefiUniversalPayload +ELF Edk2boot use below way to support compress and sign. + +- ELF Behavior - Edk2boot + UefiUniversalPayload.elf + ``` + Boot Flow + +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+ + | Platform Init | Universal Loader Interface | OS | + +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+ + HOBs + SEC -> PEI -> DXE -> DXE IPL -> UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c ------------------------------------------------------------------------------------> Load UniversalPayload.elf -> Operation System + + + | Platform Initialize - Edk2 | UniversalPayload - Edk2 | + +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+ + + Binary Format + + +-------------------+ + | BIOS.rom | + +-------------------+ + | Other Firmware | + +-------------------+ + | ... | FMMT UniversalPayloadBuild.py + +-------------------+<----------------+-----------------------+ GenFfs +-----------------------+ Rsa2048Sha256 Sign +-----------------------+ LzmaCompress +----------------------+ GenSec +--------------------------------+ + | | | EDK2 FFS Header |<-----------| Rsa2048Sha256 Hash |<--------------------| UniversalPayload.lzma |<--------------| EDK2 SEC Header |<--------| UniversalPayload.elf | + | RAW Data | +-----------------------+ +-----------------------+ +-----------------------+ +----------------------+ +--------------------------------+ + | | | Rsa2048Sha256 Hash | | UniversalPayload.lzma | | UniversalPayload.elf | | upld_info | + | | +-----------------------+ +-----------------------+ +----------------------+ +--------------------------------+ + | | | UniversalPayload.lzma | | upld_info | | upld.uefi_fv | + +-------------------+<----------------+-----------------------+ +----------------------+ +--------------------------------+ + | ... | | upld.uefi_fv | | upld.bds_fv | + +-------------------+ +----------------------+ +--------------------------------+ + | Other Firmware | | upld.bds_fv | | upld.AFP1 | + +-------------------+ +----------------------+ +--------------------------------+ + | upld.AFP1 | | upld.AFP2 | + +----------------------+ +--------------------------------+ + | upld.AFP2 | | ... | + +----------------------+ +--------------------------------+ + | ... | | upld.AFPn | + +----------------------+ +--------------------------------+ + | upld.AFPn | + +----------------------+ + ``` + +FIT Edk2boot use below way to support compress and sign +- FIT Behavior - Edk2boot + UefiUniversalPayload.fit + ``` + Boot Flow + +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+ + | Platform Init | Universal Loader Interface | OS | + +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+ + HOBs + SEC -> PEI -> DXE -> DXE IPL -> *UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c ----------------------------------------------> Load UniversalPayload.fit -> Operation System + + Binary Format + + | Platform Initialize - Edk2 | UniversalPayload - Edk2 (UniversalPayloadBuild.py --Fit) | + +---------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+ + + +-------------------+ + | BIOS.rom | + +-------------------+ + | Other Firmware | + +-------------------+ + | ... | FMMT UniversalPayloadBuild.py --Fit tianocore -> data-offset + +-------------------+<----------------+--------------------------------+ GenFfs +--------------------------------+ GenSec +--------------------------------+ tianocore -> reloc-start +--------------------------+ + | | | EDK2 FFS Header |<--------| EDK2 SEC Header |<--------| FIT Header |<-------------------------| UniversalPayload.pecoff | + | | +--------------------------------+ +--------------------------------+ | description = "Uefi Payload"; | +--------------------------+ + | | | EDK2 SEC Header | | FIT Header | | ... | + | RAW Data | +--------------------------------+ | | | images { | uefi-fv -> data-offset +--------------------------+ + | | | FIT Header | | | | tianocore {...}; |<-------------------------| uefi_fv | + | | | | +--------------------------------+ | uefi-fv {...}; | bds-fv -> data-offset +--------------------------+ + | | | | | tianocore -> data | | bds-fv {...}; |<-------------------------| bds_fv | + | | +--------------------------------+ +--------------------------------+ | afp1-fv {...}; | AFP1 -> data-offset +--------------------------+ + | | | tianocore -> data | | tianocore -> reloc-start | | ... |<-------------------------| AFP1 | + | | +--------------------------------+ +--------------------------------+ | afpn-fv {...}; | AFP2 -> data-offset +--------------------------+ + | | | tianocore -> reloc-start | | uefi-fv -> data | | } |<-------------------------| AFP2 | + | | +--------------------------------+ +--------------------------------+ | configurations { | ... +--------------------------+ + | | | uefi-fv -> data | | bds-fv -> data | | conf-1 {...} |<-------------------------| ... | + | | +--------------------------------+ +--------------------------------+ | } | AFPn -> data-offset +--------------------------+ + | | | bds-fv -> data | | AFP1-fv -> data | | |<-------------------------| AFPn | + | | +--------------------------------+ +--------------------------------+ | | +--------------------------+ + | | | AFP1-fv -> data | | AFP2-fv -> data | | | + | | +--------------------------------+ +--------------------------------+ +--------------------------------+ + | | | AFP2-fv -> data | | ... | | tianocore -> data | + | | +--------------------------------+ +--------------------------------+ +--------------------------------+ + | | | ... | | AFPn-fv -> data | | tianocore -> reloc-start | + | | +--------------------------------+ +--------------------------------+ +--------------------------------+ + | | | AFPn-fv -> data | | uefi-fv -> data | + +-------------------+<----------------+--------------------------------+ +--------------------------------+ + | ... | | bds-fv -> data | + +-------------------+ +--------------------------------+ + | Other Firmware | | AFP1-fv -> data | + +-------------------+ +--------------------------------+ + | AFP2-fv -> data | + +--------------------------------+ + | ... | + +--------------------------------+ + | AFPn-fv -> data | + +--------------------------------+ + + ``` diff --git a/UefiPayloadPkg/Tools/MkFitImage.py b/UefiPayloadPkg/Tools/MkFitImage.py new file mode 100644 index 0000000000..82ab933d6d --- /dev/null +++ b/UefiPayloadPkg/Tools/MkFitImage.py @@ -0,0 +1,272 @@ +## @file +# This file is a script to build fit image. +# It generate a dtb header and combine a binary file after this header. +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +from os.path import exists +import libfdt +from ctypes import * +import time + +class FIT_IMAGE_INFO_HEADER: + """Class for user setting data to use MakeFitImage() + """ + _pack_ = 1 + _fields_ = [ + ('Compatible', str), + ('UplVersion', int), + ('Description', str), + ('Type', str), + ('Arch', str), + ('Compression', str), + ('Revision', int), + ('BuildType', str), + ('Capabilities', str), + ('Producer', str), + ('ImageId', str), + ('DataOffset', int), + ('DataSize', int), + ('RelocStart', int), + ('LoadAddr', int), + ('Entry', int), + ('Binary', str), + ('TargetPath', str), + ('UefifvPath', str), + ('BdsfvPath', str), + ('NetworkfvPath', str), + ('Project', str), + ] + + def __init__(self): + self.Compatible = 'universal-payload' + self.UplVersion = 0x0100 + self.TargetPath = 'mkimage.fit' + +def CreatFdt(Fdt): + FdtEmptyTree = libfdt.fdt_create_empty_tree(Fdt, len(Fdt)) + if FdtEmptyTree != 0: + print('\n- Failed - Create Fdt failed!') + return False + return True + +def BuildConfNode(Fdt, ParentNode, MultiImage): + ConfNode1 = libfdt.fdt_add_subnode(Fdt, ParentNode, 'conf-1') + + libfdt.fdt_setprop(Fdt, ConfNode1, 'require-fit', b'', 0) + libfdt.fdt_setprop(Fdt, ConfNode1, 'firmware', bytes('tianocore', 'utf-8'), len('tianocore') + 1) + +def BuildFvImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize, Description): + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize) + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset) + libfdt.fdt_setprop(Fdt, ParentNode, 'compression', bytes('none', 'utf-8'), len('none') + 1) + libfdt.fdt_setprop(Fdt, ParentNode, 'project ', bytes('tianocore', 'utf-8'), len('tianocore') + 1) + libfdt.fdt_setprop(Fdt, ParentNode, 'arch', bytes('x86_64', 'utf-8'), len('x86_64') + 1) + libfdt.fdt_setprop(Fdt, ParentNode, 'type', bytes('flat-binary', 'utf-8'), len('flat-binary') + 1) + libfdt.fdt_setprop(Fdt, ParentNode, 'description', bytes(Description, 'utf-8'), len(Description) + 1) + +def BuildTianoImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize, Description): + # + # Set 'load' and 'data-offset' to reserve the memory first. + # They would be set again when Fdt completes or this function parses target binary file. + # + if InfoHeader.LoadAddr is not None: + libfdt.fdt_setprop_u64(Fdt, ParentNode, 'load', InfoHeader.LoadAddr) + if InfoHeader.Entry is not None: + libfdt.fdt_setprop_u64(Fdt, ParentNode, 'entry-start', InfoHeader.Entry) + if InfoHeader.RelocStart is not None: + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'reloc-start', InfoHeader.RelocStart) + if InfoHeader.DataSize is not None: + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize) + if InfoHeader.DataOffset is not None: + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset) + if InfoHeader.Producer is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'producer ', bytes(InfoHeader.Producer, 'utf-8'), len(InfoHeader.Producer) + 1) + if InfoHeader.Capabilities is not None: + CapStrs = ','.join(InfoHeader.Capabilities) + libfdt.fdt_setprop(Fdt, ParentNode, 'capabilities ', bytes(CapStrs, 'utf-8'), len(CapStrs) + 1) + if InfoHeader.Type is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'type ', bytes(InfoHeader.Type, 'utf-8'), len(InfoHeader.Type) + 1) + if InfoHeader.Arch is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'arch ', bytes(InfoHeader.Arch, 'utf-8'), len(InfoHeader.Arch) + 1) + if InfoHeader.Project is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'project ', bytes(InfoHeader.Project, 'utf-8'), len(InfoHeader.Project) + 1) + if InfoHeader.Description is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'description', bytes(Description, 'utf-8'), len(Description) + 1) + +# +# The subnode would be inserted from bottom to top of structure block. +# +def BuildFitImage(Fdt, InfoHeader): + MultiImage = [ + ["tianocore", InfoHeader.Binary, BuildTianoImageNode , InfoHeader.Description, None, 0 ], + ["uefi-fv", InfoHeader.UefifvPath, BuildFvImageNode, "UEFI Firmware Volume", None, 0 ], + ["bds-fv", InfoHeader.BdsfvPath, BuildFvImageNode , "BDS Firmware Volume", None, 0 ], + ["network-fv", InfoHeader.NetworkfvPath, BuildFvImageNode , "Network Firmware Volume", None, 0 ], + ] + + # + # Set basic information + # + libfdt.fdt_setprop_u32(Fdt, 0, 'build-revision ', InfoHeader.Revision) + libfdt.fdt_setprop_u32(Fdt, 0, 'spec-version', InfoHeader.UplVersion) + + # + # Build configurations node + # + ConfNode = libfdt.fdt_add_subnode(Fdt, 0, 'configurations') + BuildConfNode(Fdt, ConfNode, MultiImage) + + # Build image + DataOffset = InfoHeader.DataOffset + for Index in range (0, len (MultiImage)): + _, Path, _, _, _, _ = MultiImage[Index] + if exists(Path) == 1: + TempBinary = open(Path, 'rb') + BinaryData = TempBinary.read() + TempBinary.close() + MultiImage[Index][-2] = BinaryData + MultiImage[Index][-1] = DataOffset + DataOffset += len (BinaryData) + libfdt.fdt_setprop_u32(Fdt, 0, 'size', DataOffset) + posix_time = int(time.time()) + libfdt.fdt_setprop_u32(Fdt, 0, 'timestamp', posix_time) + DescriptionFit = 'Uefi OS Loader' + libfdt.fdt_setprop(Fdt, 0, 'description', bytes(DescriptionFit, 'utf-8'), len(DescriptionFit) + 1) + + ImageNode = libfdt.fdt_add_subnode(Fdt, 0, 'images') + for Item in reversed (MultiImage): + Name, Path, BuildFvNode, Description, BinaryData, DataOffset = Item + FvNode = libfdt.fdt_add_subnode(Fdt, ImageNode, Name) + BuildFvNode (Fdt, InfoHeader, FvNode, DataOffset, len(BinaryData), Description) + + # + # Create new image file and combine all binary. + # + DtbFile = open(InfoHeader.TargetPath, "wb") + DtbFile.truncate() + DtbFile.write(Fdt) + for Item in MultiImage: + _, _, _, _, BinaryData, _ = Item + DtbFile.write(BinaryData) + DtbFile.close() + + return True + +def MakeFitImage(InfoHeader): + # + # Allocate fdt byte array. + # + Fdt = bytearray(InfoHeader.DataOffset) + + # + # Create fdt empty tree. + # + if CreatFdt(Fdt) is False: + return False + + # + # Parse args to build fit image. + # + return BuildFitImage(Fdt, InfoHeader) + +def ReplaceFv (UplBinary, SectionFvFile, SectionName): + try: + # + # Get Original Multi Fv + # + with open (UplBinary, "rb") as File: + Dtb = File.read () + Fit = libfdt.Fdt (Dtb) + NewFitHeader = bytearray(Dtb[0:Fit.totalsize()]) + FitSize = len(Dtb) + + LoadablesList = [] + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images') + FvNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, 'uefi-fv') + NodeDepth = libfdt.fdt_node_depth (NewFitHeader, ImagesNode) + node_name = libfdt.fdt_get_name(NewFitHeader, FvNode) + FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode, NodeDepth) + + while node_name[0][-2:] == 'fv': + LoadablesList.append (node_name[0]) + node_name = libfdt.fdt_get_name(NewFitHeader, FvNode[0]) + FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode[0], NodeDepth) + # + # Get current Fit Binary FV data + # + MultiFvList = [] + for Item in LoadablesList: + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, Item) + ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big') + ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big') + MultiFvList.append ([Item, Dtb[ImageOffset:ImageOffset + ImageSize]]) + + IsFvExist = False + for Index in range (0, len (MultiFvList)): + if MultiFvList[Index][0] == SectionName: + with open (SectionFvFile, 'rb') as File: + MultiFvList[Index][1] = File.read () + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, SectionName) + ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big') + ReplaceOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big') + OffsetDelta = len(MultiFvList[Index][1]) - ImageSize + FitSize += OffsetDelta + IsFvExist = True + libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, 'data-size', len(MultiFvList[Index][1])) + + # + # Update new fit header + # + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images') + if (IsFvExist == False): + with open (SectionFvFile, 'rb') as File: + SectionFvFileBinary = File.read () + MultiFvList.append ([SectionName, SectionFvFileBinary]) + FvNode = libfdt.fdt_add_subnode(NewFitHeader, ImagesNode, SectionName) + BuildFvImageNode (NewFitHeader, None, FvNode, FitSize, len(SectionFvFileBinary), SectionName + " Firmware Volume") + FitSize += len(SectionFvFileBinary) + else: + for Index in range (0, len (MultiFvList)): + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, MultiFvList[Index][0]) + ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big') + if ImageOffset > ReplaceOffset: + libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, 'data-offset', ImageOffset + OffsetDelta) + + ConfNodes = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'configurations') + libfdt.fdt_setprop(NewFitHeader, ConfNodes, 'default ', bytes('conf-1', 'utf-8'), len('conf-1') + 1) + ConfNode = libfdt.fdt_subnode_offset(NewFitHeader, ConfNodes, 'conf-1') + + libfdt.fdt_setprop_u32(NewFitHeader, 0, 'size', FitSize) + + # + # Generate new fit image + # + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images') + TianoNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, 'tianocore') + TianoOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, TianoNode, 'data-offset')[0], 'big') + TianoSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, TianoNode, 'data-size')[0], 'big') + TianoBinary = Dtb[TianoOffset:TianoOffset + TianoSize] + + print("\nGenerate new fit image:") + NewUplBinary = bytearray(FitSize) + print("Update fit header\t to 0x0\t\t ~ " + str(hex(len(NewFitHeader)))) + NewUplBinary[:len(NewFitHeader)] = NewFitHeader + print("Update tiano image\t to " + str(hex(len(NewFitHeader))) + "\t ~ " + str(hex(len(NewFitHeader) + len(TianoBinary)))) + NewUplBinary[len(NewFitHeader):len(NewFitHeader) + len(TianoBinary)] = TianoBinary + for Index in range (0, len (MultiFvList)): + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, MultiFvList[Index][0]) + ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big') + ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big') + NewUplBinary[ImageOffset:ImageOffset + ImageSize] = MultiFvList[Index][1] + print("Update " + MultiFvList[Index][0] + "\t\t to " + str(hex(ImageOffset)) + "\t ~ " + str(hex(ImageOffset + ImageSize))) + + with open (UplBinary, "wb") as File: + File.write (NewUplBinary) + + return 0 + except Exception as Ex: + print(Ex) + return 1 diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c new file mode 100644 index 0000000000..a53d988627 --- /dev/null +++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c @@ -0,0 +1,654 @@ +/** @file + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "UefiPayloadEntry.h" +#include <Library/FdtLib.h> +#include <Guid/UniversalPayloadBase.h> + +#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \ + EFI_RESOURCE_ATTRIBUTE_TESTED | \ + EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_PERSISTENT ) + +#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \ + EFI_RESOURCE_ATTRIBUTE_TESTED ) + +extern VOID *mHobList; + +CHAR8 *mLineBuffer = NULL; + +/** + Print all HOBs info from the HOB list. + @return The pointer to the HOB list. +**/ +VOID +PrintHob ( + IN CONST VOID *HobStart + ); + +/** + Find the first substring. + @param String Point to the string where to find the substring. + @param CharSet Point to the string to be found. +**/ +UINTN +EFIAPI +AsciiStrSpn ( + IN CHAR8 *String, + IN CHAR8 *CharSet + ) +{ + UINTN Count; + CHAR8 *Str1; + CHAR8 *Str2; + + Count = 0; + + for (Str1 = String; *Str1 != L'\0'; Str1++) { + for (Str2 = CharSet; *Str2 != L'\0'; Str2++) { + if (*Str1 == *Str2) { + break; + } + } + + if (*Str2 == L'\0') { + return Count; + } + + Count++; + } + + return Count; +} + +/** + Searches a string for the first occurrence of a character contained in a + specified buffer. + @param String Point to the string where to find the substring. + @param CharSet Point to the string to be found. +**/ +CHAR8 * +EFIAPI +AsciiStrBrk ( + IN CHAR8 *String, + IN CHAR8 *CharSet + ) +{ + CHAR8 *Str1; + CHAR8 *Str2; + + for (Str1 = String; *Str1 != L'\0'; Str1++) { + for (Str2 = CharSet; *Str2 != L'\0'; Str2++) { + if (*Str1 == *Str2) { + return (CHAR8 *)Str1; + } + } + } + + return NULL; +} + +/** + Find the next token after one or more specified characters. + @param String Point to the string where to find the substring. + @param CharSet Point to the string to be found. +**/ +CHAR8 * +EFIAPI +AsciiStrTokenLine ( + IN CHAR8 *String OPTIONAL, + IN CHAR8 *CharSet + ) +{ + CHAR8 *Begin; + CHAR8 *End; + + Begin = (String == NULL) ? mLineBuffer : String; + if (Begin == NULL) { + return NULL; + } + + Begin += AsciiStrSpn (Begin, CharSet); + if (*Begin == L'\0') { + mLineBuffer = NULL; + return NULL; + } + + End = AsciiStrBrk (Begin, CharSet); + if ((End != NULL) && (*End != L'\0')) { + *End = L'\0'; + End++; + } + + mLineBuffer = End; + return Begin; +} + +/** + Some bootloader may pass a pcd database, and UPL also contain a PCD database. + Dxe PCD driver has the assumption that the two PCD database can be catenated and + the local token number should be successive. + This function will fix up the UPL PCD database to meet that assumption. + @param[in] DxeFv The FV where to find the Universal PCD database. + @retval EFI_SUCCESS If it completed successfully. + @retval other Failed to fix up. +**/ +EFI_STATUS +FixUpPcdDatabase ( + IN EFI_FIRMWARE_VOLUME_HEADER *DxeFv + ) +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER *FileHeader; + VOID *PcdRawData; + PEI_PCD_DATABASE *PeiDatabase; + PEI_PCD_DATABASE *UplDatabase; + EFI_HOB_GUID_TYPE *GuidHob; + DYNAMICEX_MAPPING *ExMapTable; + UINTN Index; + + GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); + if (GuidHob == NULL) { + // + // No fix-up is needed. + // + return EFI_SUCCESS; + } + + PeiDatabase = (PEI_PCD_DATABASE *)GET_GUID_HOB_DATA (GuidHob); + DEBUG ((DEBUG_INFO, "Find the Pei PCD data base, the total local token number is %d\n", PeiDatabase->LocalTokenCount)); + + Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DRIVER, PcdGetPtr (PcdPcdDriverFile), &FileHeader); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + UplDatabase = (PEI_PCD_DATABASE *)PcdRawData; + ExMapTable = (DYNAMICEX_MAPPING *)(UINTN)((UINTN)PcdRawData + UplDatabase->ExMapTableOffset); + + for (Index = 0; Index < UplDatabase->ExTokenCount; Index++) { + ExMapTable[Index].TokenNumber += PeiDatabase->LocalTokenCount; + } + + DEBUG ((DEBUG_INFO, "Fix up UPL PCD database successfully\n")); + return EFI_SUCCESS; +} + +/** + Add HOB into HOB list + @param[in] Hob The HOB to be added into the HOB list. +**/ +VOID +AddNewHob ( + IN EFI_PEI_HOB_POINTERS *Hob + ) +{ + EFI_PEI_HOB_POINTERS NewHob; + + if (Hob->Raw == NULL) { + return; + } + + NewHob.Header = CreateHob (Hob->Header->HobType, Hob->Header->HobLength); + + if (NewHob.Header != NULL) { + CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - sizeof (EFI_HOB_GENERIC_HEADER)); + } +} + +/** + Found the Resource Descriptor HOB that contains a range (Base, Top) + @param[in] HobList Hob start address + @param[in] Base Memory start address + @param[in] Top Memory end address. + @retval The pointer to the Resource Descriptor HOB. +**/ +EFI_HOB_RESOURCE_DESCRIPTOR * +FindResourceDescriptorByRange ( + IN VOID *HobList, + IN EFI_PHYSICAL_ADDRESS Base, + IN EFI_PHYSICAL_ADDRESS Top + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + + for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + // + // Skip all HOBs except Resource Descriptor HOBs + // + if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + continue; + } + + // + // Skip Resource Descriptor HOBs that do not describe tested system memory + // + ResourceHob = Hob.ResourceDescriptor; + if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) { + continue; + } + + if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) { + continue; + } + + // + // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop + // + if (Base < ResourceHob->PhysicalStart) { + continue; + } + + if (Top > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) { + continue; + } + + return ResourceHob; + } + + return NULL; +} + +/** + Find the highest below 4G memory resource descriptor, except the input Resource Descriptor. + @param[in] HobList Hob start address + @param[in] MinimalNeededSize Minimal needed size. + @param[in] ExceptResourceHob Ignore this Resource Descriptor. + @retval The pointer to the Resource Descriptor HOB. +**/ +EFI_HOB_RESOURCE_DESCRIPTOR * +FindAnotherHighestBelow4GResourceDescriptor ( + IN VOID *HobList, + IN UINTN MinimalNeededSize, + IN EFI_HOB_RESOURCE_DESCRIPTOR *ExceptResourceHob + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + EFI_HOB_RESOURCE_DESCRIPTOR *ReturnResourceHob; + + ReturnResourceHob = NULL; + + for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + // + // Skip all HOBs except Resource Descriptor HOBs + // + if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + continue; + } + + // + // Skip Resource Descriptor HOBs that do not describe tested system memory + // + ResourceHob = Hob.ResourceDescriptor; + if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) { + continue; + } + + if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) { + continue; + } + + // + // Skip if the Resource Descriptor HOB equals to ExceptResourceHob + // + if (ResourceHob == ExceptResourceHob) { + continue; + } + + // + // Skip Resource Descriptor HOBs that are beyond 4G + // + if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > BASE_4GB) { + continue; + } + + // + // Skip Resource Descriptor HOBs that are too small + // + if (ResourceHob->ResourceLength < MinimalNeededSize) { + continue; + } + + // + // Return the topest Resource Descriptor + // + if (ReturnResourceHob == NULL) { + ReturnResourceHob = ResourceHob; + } else { + if (ReturnResourceHob->PhysicalStart < ResourceHob->PhysicalStart) { + ReturnResourceHob = ResourceHob; + } + } + } + + return ReturnResourceHob; +} + +/** + Check the HOB and decide if it is need inside Payload + Payload maintainer may make decision which HOB is need or needn't + Then add the check logic in the function. + @param[in] Hob The HOB to check + @retval TRUE If HOB is need inside Payload + @retval FALSE If HOB is needn't inside Payload +**/ +BOOLEAN +IsHobNeed ( + EFI_PEI_HOB_POINTERS Hob + ) +{ + if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) { + return FALSE; + } + + if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) { + if (CompareGuid (&Hob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) { + return FALSE; + } + } + + // Arrive here mean the HOB is need + return TRUE; +} + +/** + It will build Fv HOBs based on information from bootloaders. + @param[out] DxeFv The pointer to the DXE FV in memory. + @retval EFI_SUCCESS If it completed successfully. + @retval EFI_NOT_FOUND If it failed to find node in fit image. + @retval Others If it failed to build required HOBs. +**/ +EFI_STATUS +BuildFitLoadablesFvHob ( + OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv + ) +{ + EFI_STATUS Status; + VOID *Fdt; + UINT8 *GuidHob; + UNIVERSAL_PAYLOAD_BASE *PayloadBase; + INT32 ConfigNode; + INT32 Config1Node; + INT32 ImageNode; + INT32 FvNode; + INT32 Depth; + CONST FDT_PROPERTY *PropertyPtr; + INT32 TempLen; + CONST CHAR8 *Fvname; + UINT32 DataOffset; + UINT32 DataSize; + UINT32 *Data32; + + GuidHob = GetFirstGuidHob (&gUniversalPayloadBaseGuid); + if (GuidHob != NULL) { + PayloadBase = (UNIVERSAL_PAYLOAD_BASE *)GET_GUID_HOB_DATA (GuidHob); + Fdt = (VOID *)(UINTN)PayloadBase->Entry; + DEBUG ((DEBUG_INFO, "PayloadBase Entry = 0x%08x\n", PayloadBase->Entry)); + } + + Status = FdtCheckHeader (Fdt); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations")); + if (ConfigNode <= 0) { + return EFI_NOT_FOUND; + } + + Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1")); + if (Config1Node <= 0) { + return EFI_NOT_FOUND; + } + + ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images")); + if (ImageNode <= 0) { + return EFI_NOT_FOUND; + } + + FvNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, "tianocore", (INT32)AsciiStrLen ("tianocore")); + Depth = FdtNodeDepth (Fdt, FvNode); + FvNode = FdtNextNode (Fdt, FvNode, &Depth); + Fvname = FdtGetName (Fdt, FvNode, &TempLen); + while ((AsciiStrCmp ((Fvname + AsciiStrLen (Fvname) - 2), "fv") == 0)) { + if (FvNode <= 0) { + return EFI_NOT_FOUND; + } + + PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-offset", &TempLen); + Data32 = (UINT32 *)(PropertyPtr->Data); + DataOffset = SwapBytes32 (*Data32); + + PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-size", &TempLen); + Data32 = (UINT32 *)(PropertyPtr->Data); + DataSize = SwapBytes32 (*Data32); + + if (AsciiStrCmp (Fvname, "uefi-fv") == 0) { + *DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)PayloadBase->Entry + (UINTN)DataOffset); + ASSERT ((*DxeFv)->FvLength == DataSize); + } else { + BuildFvHob (((UINTN)PayloadBase->Entry + (UINTN)DataOffset), DataSize); + } + + DEBUG (( + DEBUG_INFO, + "UPL Multiple fv[%a], Base=0x%08x, size=0x%08x\n", + Fvname, + ((UINTN)PayloadBase->Entry + (UINTN)DataOffset), + DataSize, + DataOffset + )); + Depth = FdtNodeDepth (Fdt, FvNode); + FvNode = FdtNextNode (Fdt, FvNode, &Depth); + Fvname = FdtGetName (Fdt, FvNode, &TempLen); + } + + return EFI_SUCCESS; +} + +/** + It will build HOBs based on information from bootloaders. + @param[in] BootloaderParameter The starting memory address of bootloader parameter block. + @param[out] DxeFv The pointer to the DXE FV in memory. + @retval EFI_SUCCESS If it completed successfully. + @retval Others If it failed to build required HOBs. +**/ +EFI_STATUS +BuildHobs ( + IN UINTN BootloaderParameter, + OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv + ) +{ + EFI_PEI_HOB_POINTERS Hob; + UINTN MinimalNeededSize; + EFI_PHYSICAL_ADDRESS FreeMemoryBottom; + EFI_PHYSICAL_ADDRESS FreeMemoryTop; + EFI_PHYSICAL_ADDRESS MemoryBottom; + EFI_PHYSICAL_ADDRESS MemoryTop; + EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + UINT8 *GuidHob; + EFI_HOB_FIRMWARE_VOLUME *FvHob; + UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable; + ACPI_BOARD_INFO *AcpiBoardInfo; + EFI_HOB_HANDOFF_INFO_TABLE *HobInfo; + + Hob.Raw = (UINT8 *)BootloaderParameter; + MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize); + + ASSERT (Hob.Raw != NULL); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop == Hob.HandoffInformationTable->EfiFreeMemoryTop); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryTop == Hob.HandoffInformationTable->EfiMemoryTop); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom == Hob.HandoffInformationTable->EfiFreeMemoryBottom); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryBottom == Hob.HandoffInformationTable->EfiMemoryBottom); + + // + // Try to find Resource Descriptor HOB that contains Hob range EfiMemoryBottom..EfiMemoryTop + // + PhitResourceHob = FindResourceDescriptorByRange (Hob.Raw, Hob.HandoffInformationTable->EfiMemoryBottom, Hob.HandoffInformationTable->EfiMemoryTop); + if (PhitResourceHob == NULL) { + // + // Boot loader's Phit Hob is not in an available Resource Descriptor, find another Resource Descriptor for new Phit Hob + // + ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, NULL); + if (ResourceHob == NULL) { + return EFI_NOT_FOUND; + } + + MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize; + FreeMemoryBottom = MemoryBottom; + FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength; + MemoryTop = FreeMemoryTop; + } else if (PhitResourceHob->PhysicalStart + PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop >= MinimalNeededSize) { + // + // New availiable Memory range in new hob is right above memory top in old hob. + // + MemoryBottom = Hob.HandoffInformationTable->EfiFreeMemoryTop; + FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop; + FreeMemoryTop = FreeMemoryBottom + MinimalNeededSize; + MemoryTop = FreeMemoryTop; + } else if (Hob.HandoffInformationTable->EfiMemoryBottom - PhitResourceHob->PhysicalStart >= MinimalNeededSize) { + // + // New availiable Memory range in new hob is right below memory bottom in old hob. + // + MemoryBottom = Hob.HandoffInformationTable->EfiMemoryBottom - MinimalNeededSize; + FreeMemoryBottom = MemoryBottom; + FreeMemoryTop = Hob.HandoffInformationTable->EfiMemoryBottom; + MemoryTop = Hob.HandoffInformationTable->EfiMemoryTop; + } else { + // + // In the Resource Descriptor HOB contains boot loader Hob, there is no enough free memory size for payload hob + // Find another Resource Descriptor Hob + // + ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, PhitResourceHob); + if (ResourceHob == NULL) { + return EFI_NOT_FOUND; + } + + MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize; + FreeMemoryBottom = MemoryBottom; + FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength; + MemoryTop = FreeMemoryTop; + } + + HobInfo = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID *)(UINTN)FreeMemoryTop); + HobInfo->BootMode = Hob.HandoffInformationTable->BootMode; + // + // From now on, mHobList will point to the new Hob range. + // + + // + // Create an empty FvHob for the DXE FV that contains DXE core. + // + BuildFvHob ((EFI_PHYSICAL_ADDRESS)0, 0); + // + // Since payload created new Hob, move all hobs except PHIT from boot loader hob list. + // + while (!END_OF_HOB_LIST (Hob)) { + if (IsHobNeed (Hob)) { + // Add this hob to payload HOB + AddNewHob (&Hob); + } + + Hob.Raw = GET_NEXT_HOB (Hob); + } + + BuildFitLoadablesFvHob (DxeFv); + + // + // Create guid hob for acpi board information + // + GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid); + if (GuidHob != NULL) { + AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA (GuidHob); + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid); + if (GuidHob == NULL) { + AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp); + ASSERT (AcpiBoardInfo != NULL); + } + } + + // + // Update DXE FV information to first fv hob in the hob list, which + // is the empty FvHob created before. + // + FvHob = GetFirstHob (EFI_HOB_TYPE_FV); + FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)*DxeFv; + FvHob->Length = (*DxeFv)->FvLength; + return EFI_SUCCESS; +} + +/** + Entry point to the C language phase of UEFI payload. + @param[in] BootloaderParameter The starting address of bootloader parameter block. + @retval It will not return if SUCCESS, and return error when passing bootloader parameter. +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN UINTN BootloaderParameter + ) +{ + EFI_STATUS Status; + PHYSICAL_ADDRESS DxeCoreEntryPoint; + EFI_PEI_HOB_POINTERS Hob; + EFI_FIRMWARE_VOLUME_HEADER *DxeFv; + + mHobList = (VOID *)BootloaderParameter; + DxeFv = NULL; + // Call constructor for all libraries + ProcessLibraryConstructorList (); + + DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n")); + DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN))); + + DEBUG_CODE ( + // + // Dump the Hobs from boot loader + // + PrintHob (mHobList); + ); + + // Initialize floating point operating environment to be compliant with UEFI spec. + InitializeFloatingPointUnits (); + + // Build HOB based on information from Bootloader + Status = BuildHobs (BootloaderParameter, &DxeFv); + ASSERT_EFI_ERROR (Status); + + FixUpPcdDatabase (DxeFv); + Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint); + ASSERT_EFI_ERROR (Status); + + // + // Mask off all legacy 8259 interrupt sources + // + IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF); + IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF); + + Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob (EFI_HOB_TYPE_HANDOFF); + HandOffToDxeCore (DxeCoreEntryPoint, Hob); + + // Should not get here + CpuDeadLoop (); + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf new file mode 100644 index 0000000000..a7d1a8c9e5 --- /dev/null +++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf @@ -0,0 +1,98 @@ +## @file +# This is the first module for UEFI payload. +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FitUniversalPayloadEntry + FILE_GUID = CED5A8A9-B6EA-4D5A-8689-577EE88566CF + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + FitUniversalPayloadEntry.c + LoadDxeCore.c + MemoryAllocation.c + PrintHob.c + AcpiTable.c + +[Sources.Ia32] + X64/VirtualMemory.h + X64/VirtualMemory.c + Ia32/DxeLoadFunc.c + Ia32/IdtVectorAsm.nasm + +[Sources.X64] + X64/VirtualMemory.h + X64/VirtualMemory.c + X64/DxeLoadFunc.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + BaseLib + SerialPortLib + IoLib + HobLib + PeCoffLib + CpuLib + FdtLib + +[Guids] + gEfiMemoryTypeInformationGuid + gEfiFirmwareFileSystem2Guid + gEfiGraphicsInfoHobGuid + gEfiGraphicsDeviceInfoHobGuid + gUefiAcpiBoardInfoGuid + gEfiSmbiosTableGuid + gUefiSerialPortInfoGuid + gUniversalPayloadExtraDataGuid + gUniversalPayloadBaseGuid + gPcdDataBaseHobGuid + gUniversalPayloadSmbiosTableGuid + gEfiHobMemoryAllocBspStoreGuid + gUniversalPayloadAcpiTableGuid + gUniversalPayloadPciRootBridgeInfoGuid + gUniversalPayloadSmbios3TableGuid + +[FeaturePcd.IA32] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES + +[FeaturePcd.X64] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ## CONSUMES + + +[Pcd.IA32,Pcd.X64] + gUefiPayloadPkgTokenSpaceGuid.PcdPcdDriverFile + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ## CONSUMES + + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize + gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize + + gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## SOMETIMES_CONSUMES diff --git a/UefiPayloadPkg/UefiPayloadPkg.dec b/UefiPayloadPkg/UefiPayloadPkg.dec index e2e4a79db3..2f1fd82487 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dec +++ b/UefiPayloadPkg/UefiPayloadPkg.dec @@ -24,6 +24,9 @@ # gUefiPayloadPkgTokenSpaceGuid = {0x1d127ea, 0xf6f1, 0x4ef6, {0x94, 0x15, 0x8a, 0x0, 0x0, 0x93, 0xf8, 0x9d}} + ## Include/Guid/UniversalPayloadBase.h + gUniversalPayloadBaseGuid = { 0x03d4c61d, 0x2713, 0x4ec5, {0xa1, 0xcc, 0x88, 0x3b, 0xe9, 0xdc, 0x18, 0xe5 } } + # # Gop Temp # diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc index 47812048dd..af9308ef8e 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dsc +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -30,7 +30,6 @@ DEFINE PS2_KEYBOARD_ENABLE = FALSE DEFINE RAM_DISK_ENABLE = FALSE DEFINE SIO_BUS_ENABLE = FALSE - DEFINE UNIVERSAL_PAYLOAD = FALSE DEFINE SECURITY_STUB_ENABLE = TRUE DEFINE SMM_SUPPORT = FALSE DEFINE PLATFORM_BOOT_TIMEOUT = 3 @@ -44,6 +43,14 @@ DEFINE BOOTSPLASH_IMAGE = FALSE DEFINE NVME_ENABLE = TRUE DEFINE CAPSULE_SUPPORT = FALSE + # + # Setup Universal Payload + # + # ELF: Build UniversalPayload file as UniversalPayload.elf + # FIT: Build UniversalPayload file as UniversalPayload.fit + # + DEFINE UNIVERSAL_PAYLOAD = FALSE + DEFINE UNIVERSAL_PAYLOAD_FORMAT = ELF # # NULL: NullMemoryTestDxe @@ -311,7 +318,7 @@ VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf - + FdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf [LibraryClasses.common] !if $(BOOTSPLASH_IMAGE) SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf @@ -600,14 +607,26 @@ !if "IA32" in "$(ARCH)" [Components.IA32] !if $(UNIVERSAL_PAYLOAD) == TRUE - UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf + !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF" + UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf + !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT" + UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf + !else + UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf + !endif !else UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf !endif !else [Components.X64] !if $(UNIVERSAL_PAYLOAD) == TRUE - UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf + !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF" + UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf + !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT" + UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf + !else + UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf + !endif !else UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf !endif diff --git a/UefiPayloadPkg/UniversalPayloadBuild.py b/UefiPayloadPkg/UniversalPayloadBuild.py index 47f37b3377..9a83fc9e44 100644 --- a/UefiPayloadPkg/UniversalPayloadBuild.py +++ b/UefiPayloadPkg/UniversalPayloadBuild.py @@ -10,10 +10,22 @@ import subprocess import os import shutil import sys +import pathlib from ctypes import * -from Tools.ElfFv import ReplaceFv + sys.dont_write_bytecode = True +class bcolors: + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKCYAN = '\033[96m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + class UPLD_INFO_HEADER(LittleEndianStructure): _pack_ = 1 _fields_ = [ @@ -36,40 +48,114 @@ class UPLD_INFO_HEADER(LittleEndianStructure): self.ImageId = b'UEFI' self.ProducerId = b'INTEL' -def BuildUniversalPayload(Args): - def RunCommand(cmd): - print(cmd) - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE']) - while True: - line = p.stdout.readline() - if not line: - break - print(line.strip().decode(errors='ignore')) - - p.communicate() - if p.returncode != 0: - print("- Failed - error happened when run command: %s"%cmd) - raise Exception("ERROR: when run command: %s"%cmd) +def ValidateSpecRevision (Argument): + try: + (MajorStr, MinorStr) = Argument.split('.') + except: + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + # + # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version. + # + if len(MinorStr) > 0 and len(MinorStr) < 3: + try: + Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4) + except: + raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument)) + else: + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + + if len(MajorStr) > 0 and len(MajorStr) < 3: + try: + Major = int(MajorStr, 16) + except: + raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument)) + else: + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + + return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0) + +def Validate32BitInteger (Argument): + try: + Value = int (Argument, 0) + except: + raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument)) + if Value < 0: + raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument)) + if Value > 0xffffffff: + raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument)) + return Value +def ValidateAddFv (Argument): + Value = Argument.split ("=") + if len (Value) != 2: + raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) + if Value[0][-3:] != "_fv": + raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) + if Value[1][-3:].lower () != ".fv": + raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) + if os.path.exists (Value[1]) == False: + raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1])) + return Value + +def RunCommand(cmd): + print(cmd) + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE']) + while True: + line = p.stdout.readline() + if not line: + break + print(line.strip().decode(errors='ignore')) + + p.communicate() + if p.returncode != 0: + print("- Failed - error happened when run command: %s"%cmd) + raise Exception("ERROR: when run command: %s"%cmd) + +def BuildUniversalPayload(Args): BuildTarget = Args.Target ToolChain = Args.ToolChain Quiet = "--quiet" if Args.Quiet else "" - ElfToolChain = 'CLANGDWARF' - BuildDir = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64")) - BuildModule = "" - BuildArch = "" + if Args.Fit == True: + PayloadEntryToolChain = ToolChain + Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=FIT") + UpldEntryFile = "FitUniversalPayloadEntry" + else: + PayloadEntryToolChain = 'CLANGDWARF' + Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=ELF") + UpldEntryFile = "UniversalPayloadEntry" + + BuildDir = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64")) if Args.Arch == 'X64': BuildArch = "X64" - EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll")) + FitArch = "x86_64" + ObjCopyFlag = "elf64-x86-64" + EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile))) else: BuildArch = "IA32 -a X64" - EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll")) + FitArch = "x86" + ObjCopyFlag = "elf32-i386" + EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile))) + EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/{}.inf".format (UpldEntryFile)) DscPath = os.path.normpath("UefiPayloadPkg/UefiPayloadPkg.dsc") + DxeFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) + BdsFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) + NetworkFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv")) + PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt") ModuleReportPath = os.path.join(BuildDir, "UefiUniversalPayloadEntry.txt") UpldInfoFile = os.path.join(BuildDir, "UniversalPayloadInfo.bin") + if "CLANG_BIN" in os.environ: + LlvmObjcopyPath = os.path.join(os.environ["CLANG_BIN"], "llvm-objcopy") + else: + LlvmObjcopyPath = "llvm-objcopy" + try: + RunCommand('"%s" --version'%LlvmObjcopyPath) + except: + print("- Failed - Please check if LLVM is installed or if CLANG_BIN is set correctly") + sys.exit(1) + Pcds = "" if (Args.pcd != None): for PcdItem in Args.pcd: @@ -84,7 +170,6 @@ def BuildUniversalPayload(Args): # Building DXE core and DXE drivers as DXEFV. # if Args.BuildEntryOnly == False: - PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt") BuildPayload = "build -p {} -b {} -a X64 -t {} -y {} {}".format (DscPath, BuildTarget, ToolChain, PayloadReportPath, Quiet) BuildPayload += Pcds BuildPayload += Defines @@ -93,94 +178,138 @@ def BuildUniversalPayload(Args): # Building Universal Payload entry. # if Args.PreBuildUplBinary is None: - EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf") - BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, ElfToolChain, ModuleReportPath, Quiet) + BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, PayloadEntryToolChain, ModuleReportPath, Quiet) BuildModule += Pcds BuildModule += Defines RunCommand(BuildModule) if Args.PreBuildUplBinary is not None: - EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf") + if Args.Fit == False: + EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf") + else: + EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.fit") shutil.copy (os.path.abspath(Args.PreBuildUplBinary), EntryOutputDir) # - # Buid Universal Payload Information Section ".upld_info" + # Build Universal Payload Information Section ".upld_info" # - upld_info_hdr = UPLD_INFO_HEADER() - upld_info_hdr.SpecRevision = Args.SpecRevision - upld_info_hdr.Revision = Args.Revision - upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16] - upld_info_hdr.ImageId = Args.ImageId.encode()[:16] - upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0 - fp = open(UpldInfoFile, 'wb') - fp.write(bytearray(upld_info_hdr)) - fp.close() + if Args.Fit == False: + upld_info_hdr = UPLD_INFO_HEADER() + upld_info_hdr.SpecRevision = Args.SpecRevision + upld_info_hdr.Revision = Args.Revision + upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16] + upld_info_hdr.ImageId = Args.ImageId.encode()[:16] + upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0 + fp = open(UpldInfoFile, 'wb') + fp.write(bytearray(upld_info_hdr)) + fp.close() + + if Args.BuildEntryOnly == False: + import Tools.ElfFv as ElfFv + ElfFv.ReplaceFv (EntryOutputDir, UpldInfoFile, '.upld_info', Alignment = 4) + if Args.Fit == False: + shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf')) + else: + shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.fit')) MultiFvList = [] if Args.BuildEntryOnly == False: MultiFvList = [ - ['uefi_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ], - ['bds_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ], - ['network_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv")) ], + ['uefi_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ], + ['bds_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ], + ['network_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))], ] - AddSectionName = '.upld_info' - ReplaceFv (EntryOutputDir, UpldInfoFile, AddSectionName, Alignment = 4) - if Args.PreBuildUplBinary is None: - shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf')) - return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf') + if Args.Fit == True: + import Tools.MkFitImage as MkFitImage + import pefile + fit_image_info_header = MkFitImage.FIT_IMAGE_INFO_HEADER() + fit_image_info_header.Description = 'Uefi Universal Payload' + fit_image_info_header.UplVersion = Args.SpecRevision + fit_image_info_header.Type = 'flat-binary' + fit_image_info_header.Arch = FitArch + fit_image_info_header.Compression = 'none' + fit_image_info_header.Revision = Args.Revision + fit_image_info_header.BuildType = Args.Target.lower() + fit_image_info_header.Capabilities = None + fit_image_info_header.Producer = Args.ProducerId.lower() + fit_image_info_header.ImageId = Args.ImageId.lower() + fit_image_info_header.Binary = os.path.join(BuildDir, 'UniversalPayload.fit') + fit_image_info_header.TargetPath = os.path.join(BuildDir, 'UniversalPayload.fit') + fit_image_info_header.UefifvPath = DxeFvOutputDir + fit_image_info_header.BdsfvPath = BdsFvOutputDir + fit_image_info_header.NetworkfvPath = NetworkFvOutputDir + fit_image_info_header.DataOffset = 0x1000 + fit_image_info_header.LoadAddr = Args.LoadAddress + fit_image_info_header.Project = 'tianocore' + + TargetRebaseFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".pecoff") + TargetRebaseEntryFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".entry") + -def main(): - def ValidateSpecRevision (Argument): - try: - (MajorStr, MinorStr) = Argument.split('.') - except: - raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) # - # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version. + # Rebase PECOFF to load address # - if len(MinorStr) > 0 and len(MinorStr) < 3: - try: - Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4) - except: - raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument)) - else: - raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + RunCommand ( + "GenFw -e SEC -o {} {}".format ( + TargetRebaseFile, + fit_image_info_header.Binary + )) + RunCommand ( + "GenFw --rebase 0x{:02X} -o {} {} ".format ( + fit_image_info_header.LoadAddr + fit_image_info_header.DataOffset, + TargetRebaseFile, + TargetRebaseFile, + )) - if len(MajorStr) > 0 and len(MajorStr) < 3: - try: - Major = int(MajorStr, 16) - except: - raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument)) - else: - raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + # + # Open PECOFF relocation table binary. + # + RelocBinary = b'' + PeCoff = pefile.PE (TargetRebaseFile) + for reloc in PeCoff.DIRECTORY_ENTRY_BASERELOC: + for entry in reloc.entries: + if (entry.type == 0): + continue + Type = entry.type + Offset = entry.rva + fit_image_info_header.DataOffset + RelocBinary += Type.to_bytes (8, 'little') + Offset.to_bytes (8, 'little') + RelocBinary += b'\x00' * (0x1000 - (len(RelocBinary) % 0x1000)) - return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0) + # + # Output UniversalPayload.entry + # + TempBinary = open (TargetRebaseFile, 'rb') + TianoBinary = TempBinary.read () + TempBinary.close () - def Validate32BitInteger (Argument): - try: - Value = int (Argument, 0) - except: - raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument)) - if Value < 0: - raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument)) - if Value > 0xffffffff: - raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument)) - return Value - - def ValidateAddFv (Argument): - Value = Argument.split ("=") - if len (Value) != 2: - raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) - if Value[0][-3:] != "_fv": - raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) - if Value[1][-3:].lower () != ".fv": - raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) - if os.path.exists (Value[1]) == False: - raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1])) - return Value + TianoEntryBinary = TianoBinary + RelocBinary + TianoEntryBinary += (b'\x00' * (0x1000 - (len(TianoBinary) % 0x1000))) + TianoEntryBinarySize = len (TianoEntryBinary) + + TempBinary = open(TargetRebaseEntryFile, "wb") + TempBinary.truncate() + TempBinary.write(TianoEntryBinary) + TempBinary.close() + + # + # Calculate entry and update relocation table start address and data-size. + # + fit_image_info_header.Entry = PeCoff.OPTIONAL_HEADER.ImageBase + PeCoff.OPTIONAL_HEADER.AddressOfEntryPoint + fit_image_info_header.RelocStart = fit_image_info_header.DataOffset + len(TianoBinary) + fit_image_info_header.DataSize = TianoEntryBinarySize + fit_image_info_header.Binary = TargetRebaseEntryFile + + if MkFitImage.MakeFitImage(fit_image_info_header) is True: + print('\nSuccessfully build Fit Image') + else: + sys.exit(1) + return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.fit') + else: + return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf') +def main(): parser = argparse.ArgumentParser(description='For building Universal Payload') parser.add_argument('-t', '--ToolChain') parser.add_argument('-b', '--Target', default='DEBUG') @@ -192,13 +321,16 @@ def main(): parser.add_argument("-s", "--SpecRevision", type=ValidateSpecRevision, default ='0.7', help='Indicates compliance with a revision of this specification in the BCD format.') parser.add_argument("-r", "--Revision", type=Validate32BitInteger, default ='0x0000010105', help='Revision of the Payload binary. Major.Minor.Revision.Build') parser.add_argument("-o", "--ProducerId", default ='INTEL', help='A null-terminated OEM-supplied string that identifies the payload producer (16 bytes maximal).') + parser.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file') + parser.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file') parser.add_argument("-sk", "--SkipBuild", action='store_true', help='Skip UniversalPayload build') parser.add_argument("-af", "--AddFv", type=ValidateAddFv, action='append', help='Add or replace specific FV into payload, Ex: uefi_fv=XXX.fv') - command_group = parser.add_mutually_exclusive_group() - command_group.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file') - command_group.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file') + parser.add_argument("-f", "--Fit", action='store_true', help='Build UniversalPayload file as UniversalPayload.fit', default=False) + parser.add_argument('-l', "--LoadAddress", type=int, help='Specify payload load address', default =0x000800000) + args = parser.parse_args() + MultiFvList = [] UniversalPayloadBinary = args.PreBuildUplBinary if (args.SkipBuild == False): @@ -208,12 +340,24 @@ def main(): for (SectionName, SectionFvFile) in args.AddFv: MultiFvList.append ([SectionName, SectionFvFile]) + def ReplaceFv (UplBinary, SectionFvFile, SectionName): + print (bcolors.OKGREEN + "Patch {}={} into {}".format (SectionName, SectionFvFile, UplBinary) + bcolors.ENDC) + if (args.Fit == False): + import Tools.ElfFv as ElfFv + return ElfFv.ReplaceFv (UplBinary, SectionFvFile, '.upld.{}'.format (SectionName)) + else: + import Tools.MkFitImage as MkFitImage + return MkFitImage.ReplaceFv (UplBinary, SectionFvFile, SectionName) + if (UniversalPayloadBinary != None): for (SectionName, SectionFvFile) in MultiFvList: if os.path.exists (SectionFvFile) == False: continue - print ("Patch {}={} into {}".format (SectionName, SectionFvFile, UniversalPayloadBinary)) - ReplaceFv (UniversalPayloadBinary, SectionFvFile, '.upld.{}'.format (SectionName)) + + status = ReplaceFv (UniversalPayloadBinary, SectionFvFile, SectionName.replace ("_", "-")) + if status != 0: + print (bcolors.FAIL + "[Fail] Patch {}={}".format (SectionName, SectionFvFile) + bcolors.ENDC) + return status print ("\nSuccessfully build Universal Payload") -- 2.39.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108699): https://edk2.groups.io/g/devel/message/108699 Mute This Topic: https://groups.io/mt/101375948/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support 2023-09-15 9:02 ` Guo, Gua @ 2023-09-15 10:26 ` Sheng Lean Tan 2023-09-15 10:32 ` Sheng Lean Tan 0 siblings, 1 reply; 10+ messages in thread From: Sheng Lean Tan @ 2023-09-15 10:26 UTC (permalink / raw) To: devel, gua.guo; +Cc: Wang, BruceX, Dong, Guo, Rhodes, Sean, Lu, James [-- Attachment #1: Type: text/plain, Size: 102196 bytes --] Hi, It looks good to me, but could you help to update these 2 parts: 1. the copyright year should be 2023 instead of 2021? 2. the correct UPL spec website should be universalpayload.github.io/spec Thanks, Sheng On Fri, 15 Sept 2023 at 11:02, Guo, Gua <gua.guo@intel.com> wrote: > Reviewed-by: Gua Guo <gua.guo@intel.com> > > -----Original Message----- > From: Wang, BruceX <brucex.wang@intel.com> > Sent: Friday, September 15, 2023 4:58 PM > To: devel@edk2.groups.io > Cc: Wang, BruceX <brucex.wang@intel.com>; Dong, Guo <guo.dong@intel.com>; > Rhodes, Sean <sean@starlabs.systems>; Lu, James <james.lu@intel.com>; > Guo, Gua <gua.guo@intel.com> > Subject: [PATCH v2 2/2] UefiPayloadPkg: Add FIT support > > From: "Brucex.Wang" <brucex.wang@intel.com> > > Provide Fit format for UniversalPayload, developer can use argument > "--Fit" to build UniversalPayload.fit > > Cc: Guo Dong <guo.dong@intel.com> > Cc: Sean Rhodes <sean@starlabs.systems> > Cc: James Lu <james.lu@intel.com> > Cc: Gua Guo <gua.guo@intel.com> > > Signed-off-by: BruceX Wang <brucex.wang@intel.com> > --- > .../Include/Guid/UniversalPayloadBase.h | 21 + > UefiPayloadPkg/PayloadLoaderPeim/FitLib.h | 60 ++ > .../PayloadLoaderPeim/FitLib/FitLib.c | 127 ++++ > .../PayloadLoaderPeim/FitPayloadLoaderPeim.c | 150 ++++ > .../FitPayloadLoaderPeim.inf | 59 ++ > UefiPayloadPkg/Readme.md | 191 +++++ > UefiPayloadPkg/Tools/MkFitImage.py | 272 ++++++++ > .../FitUniversalPayloadEntry.c | 654 ++++++++++++++++++ > .../FitUniversalPayloadEntry.inf | 98 +++ > UefiPayloadPkg/UefiPayloadPkg.dec | 3 + > UefiPayloadPkg/UefiPayloadPkg.dsc | 27 +- > UefiPayloadPkg/UniversalPayloadBuild.py | 328 ++++++--- > 12 files changed, 1894 insertions(+), 96 deletions(-) > create mode 100644 UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h > create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h > create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c > create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c > create mode 100644 > UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf > create mode 100644 UefiPayloadPkg/Readme.md > create mode 100644 UefiPayloadPkg/Tools/MkFitImage.py > create mode 100644 > UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c > create mode 100644 > UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf > > diff --git a/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h > b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h > new file mode 100644 > index 0000000000..31c9ec0bfb > --- /dev/null > +++ b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h > @@ -0,0 +1,21 @@ > +/** @file > > + Universal Payload general definitions. > > + > > +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > +SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > + @par Revision Reference: > > + - Universal Payload Specification 0.75 ( > https://universalpayload.github.io/documentation/) > > +**/ > > + > > +#ifndef UNIVERSAL_PAYLOAD_BASE_H_ > > +#define UNIVERSAL_PAYLOAD_BASE_H_ > > + > > +extern GUID gUniversalPayloadBaseGuid; > > + > > +typedef struct { > > + UNIVERSAL_PAYLOAD_GENERIC_HEADER Header; > > + EFI_PHYSICAL_ADDRESS Entry; > > +} UNIVERSAL_PAYLOAD_BASE; > > + > > +#endif // UNIVERSAL_PAYLOAD_BASE_H_ > > diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h > b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h > new file mode 100644 > index 0000000000..0514d675a6 > --- /dev/null > +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h > @@ -0,0 +1,60 @@ > +/** @file > > + FIT Load Image Support > > +Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> > > +SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#ifndef FIT_LIB_H_ > > +#define FIT_LIB_H_ > > + > > +#include <PiPei.h> > > +#include <Library/DebugLib.h> > > +#include <Library/FdtLib.h> > > + > > +typedef struct { > > + UINT64 RelocateType; > > + UINT64 Offset; > > +} FIT_RELOCATE_ITEM; > > + > > +typedef struct { > > + EFI_PHYSICAL_ADDRESS ImageBase; > > + EFI_PHYSICAL_ADDRESS PayloadBaseAddress; > > + UINT64 PayloadSize; > > + UINTN PayloadEntryOffset; > > + UINTN PayloadEntrySize; > > + EFI_PHYSICAL_ADDRESS PayloadEntryPoint; > > + UINTN RelocateTableOffset; > > + UINTN RelocateTableCount; > > + EFI_PHYSICAL_ADDRESS PayloadLoadAddress; > > +} FIT_IMAGE_CONTEXT; > > + > > +typedef struct { > > + UINT8 *Name; > > + UINT32 Offset; > > +} PROPERTY_DATA; > > + > > +#define IMAGE_BASE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, > ImageBase) > > +#define PAYLOAD_BASE_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, > PayloadBaseAddress) > > +#define PAYLOAD_BASE_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, > PayloadSize) > > +#define PAYLOAD_ENTRY_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, > PayloadEntryOffset) > > +#define PAYLOAD_ENTRY_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, > PayloadEntrySize) > > +#define PAYLOAD_ENTRY_POINT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, > PayloadEntryPoint) > > +#define RELOCATE_TABLE_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, > RelocateTableOffset) > > +#define RELOCATE_TABLE_COUNT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, > RelocateTableCount) > > +#define PAYLOAD_LOAD_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, > PayloadLoadAddress) > > + > > +/** > > + Parse the FIT image info. > > + @param[in] ImageBase Memory address of an image. > > + @param[out] Context The FIT image context pointer. > > + @retval EFI_UNSUPPORTED Unsupported binary type. > > + @retval EFI_SUCCESS FIT binary is loaded successfully. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +ParseFitImage ( > > + IN VOID *ImageBase, > > + OUT FIT_IMAGE_CONTEXT *Context > > + ); > > + > > +#endif > > diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c > b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c > new file mode 100644 > index 0000000000..9d1d8a4f61 > --- /dev/null > +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c > @@ -0,0 +1,127 @@ > +/** @file > > + FIT Load Image Support > > +Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> > > +SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#include "FitLib.h" > > + > > +PROPERTY_DATA PropertyData32List[] = { > > + { "data-offset", PAYLOAD_ENTRY_OFFSET_OFFSET }, > > + { "data-size", PAYLOAD_ENTRY_SIZE_OFFSET }, > > + { "reloc-start", RELOCATE_TABLE_OFFSET_OFFSET } > > +}; > > + > > +PROPERTY_DATA PropertyData64List[] = { > > + { "entry-start", PAYLOAD_ENTRY_POINT_OFFSET }, > > + { "load", PAYLOAD_LOAD_ADDR_OFFSET } > > +}; > > + > > +/** > > + Parse the target firmware image info in FIT. > > + @param[in] Fdt Memory address of a fdt. > > + @param[in] Firmware Target name of an image. > > + @param[out] Context The FIT image context pointer. > > + @retval EFI_NOT_FOUND FIT node dose not find. > > + @retval EFI_SUCCESS FIT binary is loaded successfully. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +FitParseFirmwarePropertyData ( > > + IN VOID *Fdt, > > + IN CHAR8 *Firmware, > > + OUT FIT_IMAGE_CONTEXT *Context > > + ) > > +{ > > + CONST FDT_PROPERTY *PropertyPtr; > > + INT32 ImageNode; > > + INT32 TianoNode; > > + INT32 TempLen; > > + UINT32 *Data32; > > + UINT64 *Data64; > > + UINT32 *ContextOffset32; > > + UINT64 *ContextOffset64; > > + INT32 Index; > > + > > + ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", > (INT32)AsciiStrLen ("images")); > > + if (ImageNode <= 0) { > > + return EFI_NOT_FOUND; > > + } > > + > > + TianoNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, Firmware, > (INT32)AsciiStrLen (Firmware)); > > + if (TianoNode <= 0) { > > + return EFI_NOT_FOUND; > > + } > > + > > + for (Index = 0; Index < sizeof (PropertyData32List) / sizeof > (PROPERTY_DATA); Index++) { > > + PropertyPtr = FdtGetProperty (Fdt, TianoNode, > PropertyData32List[Index].Name, &TempLen); > > + Data32 = (UINT32 *)(PropertyPtr->Data); > > + ContextOffset32 = (UINT32 *)((UINTN)Context + > PropertyData32List[Index].Offset); > > + *ContextOffset32 = Fdt32ToCpu (*Data32); > > + } > > + > > + for (Index = 0; Index < sizeof (PropertyData64List)/sizeof > (PROPERTY_DATA); Index++) { > > + PropertyPtr = FdtGetProperty (Fdt, TianoNode, > PropertyData64List[Index].Name, &TempLen); > > + Data64 = (UINT64 *)(PropertyPtr->Data); > > + ContextOffset64 = (UINT64 *)((UINTN)Context + > PropertyData64List[Index].Offset); > > + *ContextOffset64 = Fdt64ToCpu (*Data64); > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Parse the FIT image info. > > + @param[in] ImageBase Memory address of an image. > > + @param[out] Context The FIT image context pointer. > > + @retval EFI_UNSUPPORTED Unsupported binary type. > > + @retval EFI_SUCCESS FIT binary is loaded successfully. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +ParseFitImage ( > > + IN VOID *ImageBase, > > + OUT FIT_IMAGE_CONTEXT *Context > > + ) > > +{ > > + VOID *Fdt; > > + INT32 ConfigNode; > > + INT32 Config1Node; > > + CONST FDT_PROPERTY *PropertyPtr; > > + INT32 TempLen; > > + UINT32 *Data32; > > + UINT64 Value; > > + EFI_STATUS Status; > > + UINTN UplSize; > > + CHAR8 *Firmware; > > + > > + Status = FdtCheckHeader (ImageBase); > > + if (EFI_ERROR (Status)) { > > + return EFI_UNSUPPORTED; > > + } > > + > > + Fdt = ImageBase; > > + PropertyPtr = FdtGetProperty (Fdt, 0, "size", &TempLen); > > + Data32 = (UINT32 *)(PropertyPtr->Data); > > + UplSize = Value = Fdt32ToCpu (*Data32); > > + ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", > (INT32)AsciiStrLen ("configurations")); > > + if (ConfigNode <= 0) { > > + return EFI_NOT_FOUND; > > + } > > + > > + Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", > (INT32)AsciiStrLen ("conf-1")); > > + if (Config1Node <= 0) { > > + return EFI_NOT_FOUND; > > + } > > + > > + PropertyPtr = FdtGetProperty (Fdt, Config1Node, "firmware", &TempLen); > > + Firmware = (CHAR8 *)(PropertyPtr->Data); > > + > > + FitParseFirmwarePropertyData (Fdt, Firmware, Context); > > + > > + Context->ImageBase = (EFI_PHYSICAL_ADDRESS)ImageBase; > > + Context->PayloadSize = UplSize; > > + Context->RelocateTableCount = (Context->PayloadEntrySize - > (Context->RelocateTableOffset - Context->PayloadEntryOffset)) / sizeof > (FIT_RELOCATE_ITEM); > > + > > + return EFI_SUCCESS; > > +} > > diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c > b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c > new file mode 100644 > index 0000000000..3c5dacbb65 > --- /dev/null > +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c > @@ -0,0 +1,150 @@ > +/** @file > > + ELF Load Image Support > > +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > +SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#include <PiPei.h> > > +#include <UniversalPayload/UniversalPayload.h> > > +#include <Guid/UniversalPayloadBase.h> > > +#include <UniversalPayload/ExtraData.h> > > + > > +#include <Ppi/LoadFile.h> > > + > > +#include <Library/DebugLib.h> > > +#include <Library/HobLib.h> > > +#include <Library/PeiServicesLib.h> > > +#include <Library/MemoryAllocationLib.h> > > +#include <Library/BaseMemoryLib.h> > > + > > +#include "FitLib.h" > > + > > +/** > > + The wrapper function of PeiLoadImageLoadImage(). > > + @param This - Pointer to EFI_PEI_LOAD_FILE_PPI. > > + @param FileHandle - Pointer to the FFS file header of the image. > > + @param ImageAddressArg - Pointer to PE/TE image. > > + @param ImageSizeArg - Size of PE/TE image. > > + @param EntryPoint - Pointer to entry point of specified image file > for output. > > + @param AuthenticationState - Pointer to attestation authentication > state of image. > > + @return Status of PeiLoadImageLoadImage(). > > +**/ > > +EFI_STATUS > > +EFIAPI > > +PeiLoadFileLoadPayload ( > > + IN CONST EFI_PEI_LOAD_FILE_PPI *This, > > + IN EFI_PEI_FILE_HANDLE FileHandle, > > + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL, > > + OUT UINT64 *ImageSizeArg OPTIONAL, > > + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, > > + OUT UINT32 *AuthenticationState > > + ) > > +{ > > + EFI_STATUS Status; > > + FIT_IMAGE_CONTEXT Context; > > + UINTN Instance; > > + VOID *Binary; > > + FIT_RELOCATE_ITEM *RelocateTable; > > + UNIVERSAL_PAYLOAD_BASE *PayloadBase; > > + UINTN Length; > > + UINTN Delta; > > + UINTN Index; > > + > > + Instance = 0; > > + do { > > + Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++, > FileHandle, &Binary, AuthenticationState); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + ZeroMem (&Context, sizeof (Context)); > > + Status = ParseFitImage (Binary, &Context); > > + } while (EFI_ERROR (Status)); > > + > > + if (EFI_ERROR (Status)) { > > + ASSERT_EFI_ERROR (Status); > > + return Status; > > + } > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "Before Rebase Payload File Base: 0x%08x, File Size: 0x%08X, > EntryPoint: 0x%08x\n", > > + Context.PayloadBaseAddress, > > + Context.PayloadSize, > > + Context.PayloadEntryPoint > > + )); > > + Context.PayloadBaseAddress = (EFI_PHYSICAL_ADDRESS)AllocatePages > (EFI_SIZE_TO_PAGES (Context.PayloadSize)); > > + > > + RelocateTable = (FIT_RELOCATE_ITEM *)(UINTN)(Context.PayloadBaseAddress > + Context.RelocateTableOffset); > > + CopyMem ((VOID *)Context.PayloadBaseAddress, Binary, > Context.PayloadSize); > > + > > + if (Context.PayloadBaseAddress > Context.PayloadLoadAddress) { > > + Delta = Context.PayloadBaseAddress - > Context.PayloadLoadAddress; > > + Context.PayloadEntryPoint += Delta; > > + for (Index = 0; Index < Context.RelocateTableCount; Index++) { > > + if ((RelocateTable[Index].RelocateType == 10) || > (RelocateTable[Index].RelocateType == 3)) { > > + *((UINT64 *)(Context.PayloadBaseAddress + > RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + > RelocateTable[Index].Offset)) + Delta; > > + } > > + } > > + } else { > > + Delta = Context.PayloadLoadAddress - > Context.PayloadBaseAddress; > > + Context.PayloadEntryPoint -= Delta; > > + for (Index = 0; Index < Context.RelocateTableCount; Index++) { > > + if ((RelocateTable[Index].RelocateType == 10) || > (RelocateTable[Index].RelocateType == 3)) { > > + *((UINT64 *)(Context.PayloadBaseAddress + > RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + > RelocateTable[Index].Offset)) - Delta; > > + } > > + } > > + } > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "After Rebase Payload File Base: 0x%08x, File Size: 0x%08X, > EntryPoint: 0x%08x\n", > > + Context.PayloadBaseAddress, > > + Context.PayloadSize, > > + Context.PayloadEntryPoint > > + )); > > + > > + Length = sizeof (UNIVERSAL_PAYLOAD_BASE); > > + PayloadBase = BuildGuidHob ( > > + &gUniversalPayloadBaseGuid, > > + Length > > + ); > > + PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)Context.ImageBase; > > + > > + *ImageAddressArg = Context.PayloadBaseAddress; > > + *ImageSizeArg = Context.PayloadSize; > > + *EntryPoint = Context.PayloadEntryPoint; > > + > > + return EFI_SUCCESS; > > +} > > + > > +EFI_PEI_LOAD_FILE_PPI mPeiLoadFilePpi = { > > + PeiLoadFileLoadPayload > > +}; > > + > > +EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = { > > + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), > > + &gEfiPeiLoadFilePpiGuid, > > + &mPeiLoadFilePpi > > +}; > > + > > +/** > > + Install Pei Load File PPI. > > + @param FileHandle Handle of the file being invoked. > > + @param PeiServices Describes the list of possible PEI Services. > > + @retval EFI_SUCESS The entry point executes successfully. > > + @retval Others Some error occurs during the execution of this > function. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +InitializeFitPayloadLoaderPeim ( > > + IN EFI_PEI_FILE_HANDLE FileHandle, > > + IN CONST EFI_PEI_SERVICES **PeiServices > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList); > > + > > + return Status; > > +} > > diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf > b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf > new file mode 100644 > index 0000000000..acb0e09f68 > --- /dev/null > +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf > @@ -0,0 +1,59 @@ > +## @file > > +# Produce LoadFile PPI for payload loading. > > +# > > +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > +# > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > +[Defines] > > + INF_VERSION = 0x00010005 > > + BASE_NAME = FitPayloadLoaderPeim > > + FILE_GUID = 55AC82C8-FC17-4C56-BCDA-990BB0A73E41 > > + MODULE_TYPE = PEIM > > + VERSION_STRING = 1.0 > > + > > + ENTRY_POINT = InitializeFitPayloadLoaderPeim > > + > > +# > > +# The following information is for reference only and not required by the > build tools. > > +# > > +# VALID_ARCHITECTURES = IA32 X64 > > +# > > + > > +[Sources] > > + FitPayloadLoaderPeim.c > > + FitLib.h > > + FitLib/FitLib.c > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + MdeModulePkg/MdeModulePkg.dec > > + PcAtChipsetPkg/PcAtChipsetPkg.dec > > + UefiPayloadPkg/UefiPayloadPkg.dec > > + > > +[LibraryClasses] > > + PcdLib > > + MemoryAllocationLib > > + BaseMemoryLib > > + PeiServicesLib > > + HobLib > > + BaseLib > > + PeimEntryPoint > > + DebugLib > > + FdtLib > > + > > +[Ppis] > > + gEfiPeiLoadFilePpiGuid ## PRODUCES > > + > > +[Pcd] > > + gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister > > + gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister > > + > > +[Guids] > > + gUniversalPayloadExtraDataGuid ## PRODUCES > > + gUniversalPayloadBaseGuid ## PRODUCES > > + > > +[Depex] > > + TRUE > > diff --git a/UefiPayloadPkg/Readme.md b/UefiPayloadPkg/Readme.md > new file mode 100644 > index 0000000000..616a5dd467 > --- /dev/null > +++ b/UefiPayloadPkg/Readme.md > @@ -0,0 +1,191 @@ > +# UefiPayloadPkg > > +Provide UEFI Universal Payload for different bootloader to generate EFI > environment > > + > > +# Spec > > + > > +UniversalPayload URL: > https://universalscalablefirmware.github.io/documentation/2_universal_payload.html > > + > > +ELF Format URL: https://refspecs.linuxfoundation.org/elf/elf.pdf > > + > > +FIT Format URL: > https://universalpayload.github.io/spec/chapter2-payload-image-format.html > > + > > +# Uefi UniversalPayload Format > > + | Binary Format | HandOffPayload - HOB | > > + |---------------|----------------------| > > + | ELF | V (Default) | > > + | FIT | V | > > + > > +# Binary Format > > + - ELF > > + ``` > > + + +-----------------------+ > > + | | UniversalPayloadEntry | <----------- > UefiPayloadPkg\UefiPayloadEntry\UniversalPayloadEntry.c:_ModuleEntryPoint > (HOB) > > + | +-----------------------+ > > + | | .upld_info | patch it directly > > + ELF Format | +-----------------------+ > > + | | .upld.uefi_fv | patch it directly > > + | +-----------------------+ > > + | | .upld.bds_fv | patch it directly > > + | +-----------------------+ > > + | | .upld.<afpx>_fv | patch it directly > > + + +-----------------------+ > > + ``` > > + > > + - FIT > > + ``` > > + + +-----------------------+ > > + FIT Data | | FIT Header | <----------- Generate by > pylibfdt > > + + +-----------------------+ > > + PECOFF Format | | UniversalPayloadEntry | <----------- > UefiPayloadPkg\UefiPayloadEntry\FitUniversalPayloadEntry.c:_ModuleEntryPoint > (HOB) > > + + +-----------------------+ > > + Relocate Data | | reloc-start | > > + + +-----------------------+ > > + | | uefi_fv | patch it directly > > + | +-----------------------+ > > + Multi Binary | | bds_fv | patch it directly > > + | +-----------------------+ > > + | | afp_xxx_fv | patch it directly > > + | +-----------------------+ > > + | | afp_xxx_fv | patch it directly > > + + +-----------------------+ > > + ``` > > + > > +# Environment > > + - ELF > > + ``` > > + Download and install > https://github.com/llvm/llvm-project/releases/tag/llvmorg-10.0.1 > > + ``` > > + - FIT > > + - Windows > > + ```powershell > > + Set-ExecutionPolicy Bypass -Scope Process -Force; > [System.Net.ServicePointManager]::SecurityProtocol = > [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex > ((New-Object System.Net.WebClient).DownloadString(' > https://chocolatey.org/install.ps1')) > > + choco install dtc-msys2 > > + pip3 install pefile > > + pip3 install swig > > + pip3 install pylibfdt > > + ``` > > + - Ubuntu > > + ```bash > > + sudo apt install -y u-boot-tools > > + pip3 install pefile > > + pip3 install swig > > + pip3 install pylibfdt > > + ``` > > +# How to build UEFI UniversalPayload > > + - Windows > > + - edksetup Rebuild > > + - Linux > > + - make -C BaseTools > > + - source edksetup.sh > > + > > + - UniversalPayload.elf > > + - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG> > > + - llvm-objdump -h Build/UefiPayloadPkgX64/UniversalPayload.elf > > + > > + - UniversalPayload.fit > > + - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG> > --Fit > > + - fdtdump Build/UefiPayloadPkgX64/UniversalPayload.fit > > + > > +# Edk2boot + UefiUniversalPayload > > +ELF Edk2boot use below way to support compress and sign. > > + > > +- ELF Behavior - Edk2boot + UefiUniversalPayload.elf > > + ``` > > + Boot Flow > > + > +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+ > > + | Platform Init > | Universal Loader Interface > | OS | > > + > +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+ > > + > > HOBs > > + SEC -> PEI -> DXE -> DXE IPL -> > UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c > ------------------------------------------------------------------------------------> > Load UniversalPayload.elf -> Operation System > > + > > + > > + | Platform Initialize - Edk2 > > | UniversalPayload - Edk2 > | > > + > +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+ > > + > > + Binary Format > > + > > + +-------------------+ > > + | BIOS.rom | > > + +-------------------+ > > + | Other Firmware | > > + +-------------------+ > > + | ... | FMMT > > UniversalPayloadBuild.py > > + +-------------------+<----------------+-----------------------+ > GenFfs +-----------------------+ Rsa2048Sha256 Sign > +-----------------------+ LzmaCompress +----------------------+ GenSec > +--------------------------------+ > > + | | | EDK2 FFS Header > |<-----------| Rsa2048Sha256 Hash |<--------------------| > UniversalPayload.lzma |<--------------| EDK2 SEC Header |<--------| > UniversalPayload.elf | > > + | RAW Data | +-----------------------+ > +-----------------------+ > +-----------------------+ +----------------------+ > +--------------------------------+ > > + | | | Rsa2048Sha256 Hash | > | UniversalPayload.lzma | > | UniversalPayload.elf | | upld_info > | > > + | | +-----------------------+ > +-----------------------+ > +----------------------+ > +--------------------------------+ > > + | | | UniversalPayload.lzma | > > | upld_info | | upld.uefi_fv > | > > + +-------------------+<----------------+-----------------------+ > > +----------------------+ > +--------------------------------+ > > + | ... | > > | upld.uefi_fv | | upld.bds_fv > | > > + +-------------------+ > > +----------------------+ > +--------------------------------+ > > + | Other Firmware | > > | upld.bds_fv | | upld.AFP1 > | > > + +-------------------+ > > +----------------------+ > +--------------------------------+ > > + > > | upld.AFP1 | | upld.AFP2 > | > > + > > +----------------------+ > +--------------------------------+ > > + > > | upld.AFP2 | | ... > | > > + > > +----------------------+ > +--------------------------------+ > > + > > | ... | | upld.AFPn > | > > + > > +----------------------+ > +--------------------------------+ > > + > > | upld.AFPn | > > + > > +----------------------+ > > + ``` > > + > > +FIT Edk2boot use below way to support compress and sign > > +- FIT Behavior - Edk2boot + UefiUniversalPayload.fit > > + ``` > > + Boot Flow > > + > +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+ > > + | Platform Init > | Universal Loader Interface > | OS | > > + > +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+ > > + > HOBs > > + SEC -> PEI -> DXE -> DXE IPL -> > *UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c > ----------------------------------------------> Load UniversalPayload.fit > -> Operation System > > + > > + Binary Format > > + > > + | Platform Initialize - Edk2 > | UniversalPayload - > Edk2 (UniversalPayloadBuild.py --Fit) | > > + > +---------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+ > > + > > + +-------------------+ > > + | BIOS.rom | > > + +-------------------+ > > + | Other Firmware | > > + +-------------------+ > > + | ... | FMMT > > UniversalPayloadBuild.py --Fit tianocore -> data-offset > > + > +-------------------+<----------------+--------------------------------+ > GenFfs +--------------------------------+ GenSec > +--------------------------------+ tianocore -> reloc-start > +--------------------------+ > > + | | | EDK2 FFS Header > |<--------| EDK2 SEC Header |<--------| FIT Header > |<-------------------------| UniversalPayload.pecoff | > > + | | > +--------------------------------+ > +--------------------------------+ | description = "Uefi > Payload"; | +--------------------------+ > > + | | | EDK2 SEC Header > | | FIT Header | | ... > | > > + | RAW Data | > +--------------------------------+ | > | | images { | uefi-fv -> data-offset > +--------------------------+ > > + | | | FIT Header > | | | | tianocore {...}; > |<-------------------------| uefi_fv | > > + | | | > | +--------------------------------+ | uefi-fv {...}; > | bds-fv -> data-offset +--------------------------+ > > + | | | > | | tianocore -> data | | bds-fv {...}; > |<-------------------------| bds_fv | > > + | | > +--------------------------------+ > +--------------------------------+ | afp1-fv {...}; > | AFP1 -> data-offset +--------------------------+ > > + | | | tianocore -> data > | | tianocore -> reloc-start | | ... > |<-------------------------| AFP1 | > > + | | > +--------------------------------+ > +--------------------------------+ | afpn-fv {...}; > | AFP2 -> data-offset +--------------------------+ > > + | | | tianocore -> reloc-start > | | uefi-fv -> data | | } > |<-------------------------| AFP2 | > > + | | > +--------------------------------+ > +--------------------------------+ | configurations { > | ... +--------------------------+ > > + | | | uefi-fv -> data > | | bds-fv -> data | | conf-1 {...} > |<-------------------------| ... | > > + | | > +--------------------------------+ > +--------------------------------+ | } > | AFPn -> data-offset +--------------------------+ > > + | | | bds-fv -> data > | | AFP1-fv -> data | | > |<-------------------------| AFPn | > > + | | > +--------------------------------+ > +--------------------------------+ | > | +--------------------------+ > > + | | | AFP1-fv -> data > | | AFP2-fv -> data | | > | > > + | | > +--------------------------------+ > +--------------------------------+ > +--------------------------------+ > > + | | | AFP2-fv -> data > | | ... | | tianocore -> data > | > > + | | > +--------------------------------+ > +--------------------------------+ > +--------------------------------+ > > + | | | ... > | | AFPn-fv -> data | | tianocore -> > reloc-start | > > + | | > +--------------------------------+ > +--------------------------------+ > +--------------------------------+ > > + | | | AFPn-fv -> data > | | uefi-fv -> data > | > > + > +-------------------+<----------------+--------------------------------+ > > +--------------------------------+ > > + | ... | > | bds-fv -> data > | > > + +-------------------+ > > +--------------------------------+ > > + | Other Firmware | > | AFP1-fv -> data > | > > + +-------------------+ > > +--------------------------------+ > > + > | AFP2-fv -> data > | > > + > > +--------------------------------+ > > + > | ... > | > > + > > +--------------------------------+ > > + > | AFPn-fv -> data > | > > + > > +--------------------------------+ > > + > > + ``` > > diff --git a/UefiPayloadPkg/Tools/MkFitImage.py > b/UefiPayloadPkg/Tools/MkFitImage.py > new file mode 100644 > index 0000000000..82ab933d6d > --- /dev/null > +++ b/UefiPayloadPkg/Tools/MkFitImage.py > @@ -0,0 +1,272 @@ > +## @file > > +# This file is a script to build fit image. > > +# It generate a dtb header and combine a binary file after this header. > > +# > > +# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +## > > + > > +from os.path import exists > > +import libfdt > > +from ctypes import * > > +import time > > + > > +class FIT_IMAGE_INFO_HEADER: > > + """Class for user setting data to use MakeFitImage() > > + """ > > + _pack_ = 1 > > + _fields_ = [ > > + ('Compatible', str), > > + ('UplVersion', int), > > + ('Description', str), > > + ('Type', str), > > + ('Arch', str), > > + ('Compression', str), > > + ('Revision', int), > > + ('BuildType', str), > > + ('Capabilities', str), > > + ('Producer', str), > > + ('ImageId', str), > > + ('DataOffset', int), > > + ('DataSize', int), > > + ('RelocStart', int), > > + ('LoadAddr', int), > > + ('Entry', int), > > + ('Binary', str), > > + ('TargetPath', str), > > + ('UefifvPath', str), > > + ('BdsfvPath', str), > > + ('NetworkfvPath', str), > > + ('Project', str), > > + ] > > + > > + def __init__(self): > > + self.Compatible = 'universal-payload' > > + self.UplVersion = 0x0100 > > + self.TargetPath = 'mkimage.fit' > > + > > +def CreatFdt(Fdt): > > + FdtEmptyTree = libfdt.fdt_create_empty_tree(Fdt, len(Fdt)) > > + if FdtEmptyTree != 0: > > + print('\n- Failed - Create Fdt failed!') > > + return False > > + return True > > + > > +def BuildConfNode(Fdt, ParentNode, MultiImage): > > + ConfNode1 = libfdt.fdt_add_subnode(Fdt, ParentNode, 'conf-1') > > + > > + libfdt.fdt_setprop(Fdt, ConfNode1, 'require-fit', b'', 0) > > + libfdt.fdt_setprop(Fdt, ConfNode1, 'firmware', bytes('tianocore', > 'utf-8'), len('tianocore') + 1) > > + > > +def BuildFvImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize, > Description): > > + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize) > > + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset) > > + libfdt.fdt_setprop(Fdt, ParentNode, 'compression', bytes('none', > 'utf-8'), len('none') + 1) > > + libfdt.fdt_setprop(Fdt, ParentNode, 'project ', > bytes('tianocore', 'utf-8'), len('tianocore') + 1) > > + libfdt.fdt_setprop(Fdt, ParentNode, 'arch', bytes('x86_64', > 'utf-8'), len('x86_64') + 1) > > + libfdt.fdt_setprop(Fdt, ParentNode, 'type', > bytes('flat-binary', 'utf-8'), len('flat-binary') + 1) > > + libfdt.fdt_setprop(Fdt, ParentNode, 'description', > bytes(Description, 'utf-8'), len(Description) + 1) > > + > > +def BuildTianoImageNode(Fdt, InfoHeader, ParentNode, DataOffset, > DataSize, Description): > > + # > > + # Set 'load' and 'data-offset' to reserve the memory first. > > + # They would be set again when Fdt completes or this function parses > target binary file. > > + # > > + if InfoHeader.LoadAddr is not None: > > + libfdt.fdt_setprop_u64(Fdt, ParentNode, 'load', > InfoHeader.LoadAddr) > > + if InfoHeader.Entry is not None: > > + libfdt.fdt_setprop_u64(Fdt, ParentNode, 'entry-start', > InfoHeader.Entry) > > + if InfoHeader.RelocStart is not None: > > + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'reloc-start', > InfoHeader.RelocStart) > > + if InfoHeader.DataSize is not None: > > + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize) > > + if InfoHeader.DataOffset is not None: > > + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset) > > + if InfoHeader.Producer is not None: > > + libfdt.fdt_setprop(Fdt, ParentNode, 'producer ', > bytes(InfoHeader.Producer, 'utf-8'), len(InfoHeader.Producer) + 1) > > + if InfoHeader.Capabilities is not None: > > + CapStrs = ','.join(InfoHeader.Capabilities) > > + libfdt.fdt_setprop(Fdt, ParentNode, 'capabilities ', > bytes(CapStrs, 'utf-8'), len(CapStrs) + 1) > > + if InfoHeader.Type is not None: > > + libfdt.fdt_setprop(Fdt, ParentNode, 'type ', > bytes(InfoHeader.Type, 'utf-8'), len(InfoHeader.Type) + 1) > > + if InfoHeader.Arch is not None: > > + libfdt.fdt_setprop(Fdt, ParentNode, 'arch ', > bytes(InfoHeader.Arch, 'utf-8'), len(InfoHeader.Arch) + 1) > > + if InfoHeader.Project is not None: > > + libfdt.fdt_setprop(Fdt, ParentNode, 'project ', > bytes(InfoHeader.Project, 'utf-8'), len(InfoHeader.Project) + 1) > > + if InfoHeader.Description is not None: > > + libfdt.fdt_setprop(Fdt, ParentNode, 'description', > bytes(Description, 'utf-8'), len(Description) + 1) > > + > > +# > > +# The subnode would be inserted from bottom to top of structure block. > > +# > > +def BuildFitImage(Fdt, InfoHeader): > > + MultiImage = [ > > + ["tianocore", InfoHeader.Binary, BuildTianoImageNode , > InfoHeader.Description, None, 0 ], > > + ["uefi-fv", InfoHeader.UefifvPath, BuildFvImageNode, > "UEFI Firmware Volume", None, 0 ], > > + ["bds-fv", InfoHeader.BdsfvPath, BuildFvImageNode , > "BDS Firmware Volume", None, 0 ], > > + ["network-fv", InfoHeader.NetworkfvPath, BuildFvImageNode , > "Network Firmware Volume", None, 0 ], > > + ] > > + > > + # > > + # Set basic information > > + # > > + libfdt.fdt_setprop_u32(Fdt, 0, 'build-revision ', InfoHeader.Revision) > > + libfdt.fdt_setprop_u32(Fdt, 0, 'spec-version', InfoHeader.UplVersion) > > + > > + # > > + # Build configurations node > > + # > > + ConfNode = libfdt.fdt_add_subnode(Fdt, 0, 'configurations') > > + BuildConfNode(Fdt, ConfNode, MultiImage) > > + > > + # Build image > > + DataOffset = InfoHeader.DataOffset > > + for Index in range (0, len (MultiImage)): > > + _, Path, _, _, _, _ = MultiImage[Index] > > + if exists(Path) == 1: > > + TempBinary = open(Path, 'rb') > > + BinaryData = TempBinary.read() > > + TempBinary.close() > > + MultiImage[Index][-2] = BinaryData > > + MultiImage[Index][-1] = DataOffset > > + DataOffset += len (BinaryData) > > + libfdt.fdt_setprop_u32(Fdt, 0, 'size', DataOffset) > > + posix_time = int(time.time()) > > + libfdt.fdt_setprop_u32(Fdt, 0, 'timestamp', posix_time) > > + DescriptionFit = 'Uefi OS Loader' > > + libfdt.fdt_setprop(Fdt, 0, 'description', bytes(DescriptionFit, > 'utf-8'), len(DescriptionFit) + 1) > > + > > + ImageNode = libfdt.fdt_add_subnode(Fdt, 0, 'images') > > + for Item in reversed (MultiImage): > > + Name, Path, BuildFvNode, Description, BinaryData, DataOffset = > Item > > + FvNode = libfdt.fdt_add_subnode(Fdt, ImageNode, Name) > > + BuildFvNode (Fdt, InfoHeader, FvNode, DataOffset, > len(BinaryData), Description) > > + > > + # > > + # Create new image file and combine all binary. > > + # > > + DtbFile = open(InfoHeader.TargetPath, "wb") > > + DtbFile.truncate() > > + DtbFile.write(Fdt) > > + for Item in MultiImage: > > + _, _, _, _, BinaryData, _ = Item > > + DtbFile.write(BinaryData) > > + DtbFile.close() > > + > > + return True > > + > > +def MakeFitImage(InfoHeader): > > + # > > + # Allocate fdt byte array. > > + # > > + Fdt = bytearray(InfoHeader.DataOffset) > > + > > + # > > + # Create fdt empty tree. > > + # > > + if CreatFdt(Fdt) is False: > > + return False > > + > > + # > > + # Parse args to build fit image. > > + # > > + return BuildFitImage(Fdt, InfoHeader) > > + > > +def ReplaceFv (UplBinary, SectionFvFile, SectionName): > > + try: > > + # > > + # Get Original Multi Fv > > + # > > + with open (UplBinary, "rb") as File: > > + Dtb = File.read () > > + Fit = libfdt.Fdt (Dtb) > > + NewFitHeader = bytearray(Dtb[0:Fit.totalsize()]) > > + FitSize = len(Dtb) > > + > > + LoadablesList = [] > > + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, > 'images') > > + FvNode = libfdt.fdt_subnode_offset(NewFitHeader, > ImagesNode, 'uefi-fv') > > + NodeDepth = libfdt.fdt_node_depth (NewFitHeader, ImagesNode) > > + node_name = libfdt.fdt_get_name(NewFitHeader, FvNode) > > + FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode, > NodeDepth) > > + > > + while node_name[0][-2:] == 'fv': > > + LoadablesList.append (node_name[0]) > > + node_name = libfdt.fdt_get_name(NewFitHeader, FvNode[0]) > > + FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode[0], > NodeDepth) > > + # > > + # Get current Fit Binary FV data > > + # > > + MultiFvList = [] > > + for Item in LoadablesList: > > + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, > ImagesNode, Item) > > + ImageOffset = int.from_bytes (libfdt.fdt_getprop > (NewFitHeader, ImageNode, 'data-offset')[0], 'big') > > + ImageSize = int.from_bytes (libfdt.fdt_getprop > (NewFitHeader, ImageNode, 'data-size')[0], 'big') > > + MultiFvList.append ([Item, Dtb[ImageOffset:ImageOffset + > ImageSize]]) > > + > > + IsFvExist = False > > + for Index in range (0, len (MultiFvList)): > > + if MultiFvList[Index][0] == SectionName: > > + with open (SectionFvFile, 'rb') as File: > > + MultiFvList[Index][1] = File.read () > > + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, > ImagesNode, SectionName) > > + ImageSize = int.from_bytes (libfdt.fdt_getprop > (NewFitHeader, ImageNode, 'data-size')[0], 'big') > > + ReplaceOffset = int.from_bytes (libfdt.fdt_getprop > (NewFitHeader, ImageNode, 'data-offset')[0], 'big') > > + OffsetDelta = len(MultiFvList[Index][1]) - ImageSize > > + FitSize += OffsetDelta > > + IsFvExist = True > > + libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, > 'data-size', len(MultiFvList[Index][1])) > > + > > + # > > + # Update new fit header > > + # > > + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images') > > + if (IsFvExist == False): > > + with open (SectionFvFile, 'rb') as File: > > + SectionFvFileBinary = File.read () > > + MultiFvList.append ([SectionName, SectionFvFileBinary]) > > + FvNode = libfdt.fdt_add_subnode(NewFitHeader, ImagesNode, > SectionName) > > + BuildFvImageNode (NewFitHeader, None, FvNode, FitSize, > len(SectionFvFileBinary), SectionName + " Firmware Volume") > > + FitSize += len(SectionFvFileBinary) > > + else: > > + for Index in range (0, len (MultiFvList)): > > + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, > ImagesNode, MultiFvList[Index][0]) > > + ImageOffset = int.from_bytes (libfdt.fdt_getprop > (NewFitHeader, ImageNode, 'data-offset')[0], 'big') > > + if ImageOffset > ReplaceOffset: > > + libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, > 'data-offset', ImageOffset + OffsetDelta) > > + > > + ConfNodes = libfdt.fdt_subnode_offset(NewFitHeader, 0, > 'configurations') > > + libfdt.fdt_setprop(NewFitHeader, ConfNodes, 'default ', > bytes('conf-1', 'utf-8'), len('conf-1') + 1) > > + ConfNode = libfdt.fdt_subnode_offset(NewFitHeader, > ConfNodes, 'conf-1') > > + > > + libfdt.fdt_setprop_u32(NewFitHeader, 0, 'size', FitSize) > > + > > + # > > + # Generate new fit image > > + # > > + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, > 'images') > > + TianoNode = libfdt.fdt_subnode_offset(NewFitHeader, > ImagesNode, 'tianocore') > > + TianoOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, > TianoNode, 'data-offset')[0], 'big') > > + TianoSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, > TianoNode, 'data-size')[0], 'big') > > + TianoBinary = Dtb[TianoOffset:TianoOffset + TianoSize] > > + > > + print("\nGenerate new fit image:") > > + NewUplBinary = bytearray(FitSize) > > + print("Update fit header\t to 0x0\t\t ~ " + > str(hex(len(NewFitHeader)))) > > + NewUplBinary[:len(NewFitHeader)] = NewFitHeader > > + print("Update tiano image\t to " + str(hex(len(NewFitHeader))) + > "\t ~ " + str(hex(len(NewFitHeader) + len(TianoBinary)))) > > + NewUplBinary[len(NewFitHeader):len(NewFitHeader) + > len(TianoBinary)] = TianoBinary > > + for Index in range (0, len (MultiFvList)): > > + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, > ImagesNode, MultiFvList[Index][0]) > > + ImageOffset = int.from_bytes (libfdt.fdt_getprop > (NewFitHeader, ImageNode, 'data-offset')[0], 'big') > > + ImageSize = int.from_bytes (libfdt.fdt_getprop > (NewFitHeader, ImageNode, 'data-size')[0], 'big') > > + NewUplBinary[ImageOffset:ImageOffset + ImageSize] = > MultiFvList[Index][1] > > + print("Update " + MultiFvList[Index][0] + "\t\t to " + > str(hex(ImageOffset)) + "\t ~ " + str(hex(ImageOffset + ImageSize))) > > + > > + with open (UplBinary, "wb") as File: > > + File.write (NewUplBinary) > > + > > + return 0 > > + except Exception as Ex: > > + print(Ex) > > + return 1 > > diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c > b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c > new file mode 100644 > index 0000000000..a53d988627 > --- /dev/null > +++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c > @@ -0,0 +1,654 @@ > +/** @file > > + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#include "UefiPayloadEntry.h" > > +#include <Library/FdtLib.h> > > +#include <Guid/UniversalPayloadBase.h> > > + > > +#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT > | \ > > + > EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \ > > + EFI_RESOURCE_ATTRIBUTE_TESTED > | \ > > + > EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \ > > + > EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \ > > + > EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \ > > + > EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \ > > + EFI_RESOURCE_ATTRIBUTE_16_BIT_IO > | \ > > + EFI_RESOURCE_ATTRIBUTE_32_BIT_IO > | \ > > + EFI_RESOURCE_ATTRIBUTE_64_BIT_IO > | \ > > + EFI_RESOURCE_ATTRIBUTE_PERSISTENT > ) > > + > > +#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | > \ > > + EFI_RESOURCE_ATTRIBUTE_INITIALIZED > | \ > > + EFI_RESOURCE_ATTRIBUTE_TESTED > ) > > + > > +extern VOID *mHobList; > > + > > +CHAR8 *mLineBuffer = NULL; > > + > > +/** > > + Print all HOBs info from the HOB list. > > + @return The pointer to the HOB list. > > +**/ > > +VOID > > +PrintHob ( > > + IN CONST VOID *HobStart > > + ); > > + > > +/** > > + Find the first substring. > > + @param String Point to the string where to find the substring. > > + @param CharSet Point to the string to be found. > > +**/ > > +UINTN > > +EFIAPI > > +AsciiStrSpn ( > > + IN CHAR8 *String, > > + IN CHAR8 *CharSet > > + ) > > +{ > > + UINTN Count; > > + CHAR8 *Str1; > > + CHAR8 *Str2; > > + > > + Count = 0; > > + > > + for (Str1 = String; *Str1 != L'\0'; Str1++) { > > + for (Str2 = CharSet; *Str2 != L'\0'; Str2++) { > > + if (*Str1 == *Str2) { > > + break; > > + } > > + } > > + > > + if (*Str2 == L'\0') { > > + return Count; > > + } > > + > > + Count++; > > + } > > + > > + return Count; > > +} > > + > > +/** > > + Searches a string for the first occurrence of a character contained in a > > + specified buffer. > > + @param String Point to the string where to find the substring. > > + @param CharSet Point to the string to be found. > > +**/ > > +CHAR8 * > > +EFIAPI > > +AsciiStrBrk ( > > + IN CHAR8 *String, > > + IN CHAR8 *CharSet > > + ) > > +{ > > + CHAR8 *Str1; > > + CHAR8 *Str2; > > + > > + for (Str1 = String; *Str1 != L'\0'; Str1++) { > > + for (Str2 = CharSet; *Str2 != L'\0'; Str2++) { > > + if (*Str1 == *Str2) { > > + return (CHAR8 *)Str1; > > + } > > + } > > + } > > + > > + return NULL; > > +} > > + > > +/** > > + Find the next token after one or more specified characters. > > + @param String Point to the string where to find the substring. > > + @param CharSet Point to the string to be found. > > +**/ > > +CHAR8 * > > +EFIAPI > > +AsciiStrTokenLine ( > > + IN CHAR8 *String OPTIONAL, > > + IN CHAR8 *CharSet > > + ) > > +{ > > + CHAR8 *Begin; > > + CHAR8 *End; > > + > > + Begin = (String == NULL) ? mLineBuffer : String; > > + if (Begin == NULL) { > > + return NULL; > > + } > > + > > + Begin += AsciiStrSpn (Begin, CharSet); > > + if (*Begin == L'\0') { > > + mLineBuffer = NULL; > > + return NULL; > > + } > > + > > + End = AsciiStrBrk (Begin, CharSet); > > + if ((End != NULL) && (*End != L'\0')) { > > + *End = L'\0'; > > + End++; > > + } > > + > > + mLineBuffer = End; > > + return Begin; > > +} > > + > > +/** > > + Some bootloader may pass a pcd database, and UPL also contain a PCD > database. > > + Dxe PCD driver has the assumption that the two PCD database can be > catenated and > > + the local token number should be successive. > > + This function will fix up the UPL PCD database to meet that assumption. > > + @param[in] DxeFv The FV where to find the Universal PCD > database. > > + @retval EFI_SUCCESS If it completed successfully. > > + @retval other Failed to fix up. > > +**/ > > +EFI_STATUS > > +FixUpPcdDatabase ( > > + IN EFI_FIRMWARE_VOLUME_HEADER *DxeFv > > + ) > > +{ > > + EFI_STATUS Status; > > + EFI_FFS_FILE_HEADER *FileHeader; > > + VOID *PcdRawData; > > + PEI_PCD_DATABASE *PeiDatabase; > > + PEI_PCD_DATABASE *UplDatabase; > > + EFI_HOB_GUID_TYPE *GuidHob; > > + DYNAMICEX_MAPPING *ExMapTable; > > + UINTN Index; > > + > > + GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); > > + if (GuidHob == NULL) { > > + // > > + // No fix-up is needed. > > + // > > + return EFI_SUCCESS; > > + } > > + > > + PeiDatabase = (PEI_PCD_DATABASE *)GET_GUID_HOB_DATA (GuidHob); > > + DEBUG ((DEBUG_INFO, "Find the Pei PCD data base, the total local token > number is %d\n", PeiDatabase->LocalTokenCount)); > > + > > + Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DRIVER, PcdGetPtr > (PcdPcdDriverFile), &FileHeader); > > + ASSERT_EFI_ERROR (Status); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData); > > + ASSERT_EFI_ERROR (Status); > > + if (EFI_ERROR (Status)) { > > + return Status; > > + } > > + > > + UplDatabase = (PEI_PCD_DATABASE *)PcdRawData; > > + ExMapTable = (DYNAMICEX_MAPPING *)(UINTN)((UINTN)PcdRawData + > UplDatabase->ExMapTableOffset); > > + > > + for (Index = 0; Index < UplDatabase->ExTokenCount; Index++) { > > + ExMapTable[Index].TokenNumber += PeiDatabase->LocalTokenCount; > > + } > > + > > + DEBUG ((DEBUG_INFO, "Fix up UPL PCD database successfully\n")); > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Add HOB into HOB list > > + @param[in] Hob The HOB to be added into the HOB list. > > +**/ > > +VOID > > +AddNewHob ( > > + IN EFI_PEI_HOB_POINTERS *Hob > > + ) > > +{ > > + EFI_PEI_HOB_POINTERS NewHob; > > + > > + if (Hob->Raw == NULL) { > > + return; > > + } > > + > > + NewHob.Header = CreateHob (Hob->Header->HobType, > Hob->Header->HobLength); > > + > > + if (NewHob.Header != NULL) { > > + CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - > sizeof (EFI_HOB_GENERIC_HEADER)); > > + } > > +} > > + > > +/** > > + Found the Resource Descriptor HOB that contains a range (Base, Top) > > + @param[in] HobList Hob start address > > + @param[in] Base Memory start address > > + @param[in] Top Memory end address. > > + @retval The pointer to the Resource Descriptor HOB. > > +**/ > > +EFI_HOB_RESOURCE_DESCRIPTOR * > > +FindResourceDescriptorByRange ( > > + IN VOID *HobList, > > + IN EFI_PHYSICAL_ADDRESS Base, > > + IN EFI_PHYSICAL_ADDRESS Top > > + ) > > +{ > > + EFI_PEI_HOB_POINTERS Hob; > > + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; > > + > > + for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = > GET_NEXT_HOB (Hob)) { > > + // > > + // Skip all HOBs except Resource Descriptor HOBs > > + // > > + if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { > > + continue; > > + } > > + > > + // > > + // Skip Resource Descriptor HOBs that do not describe tested system > memory > > + // > > + ResourceHob = Hob.ResourceDescriptor; > > + if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) { > > + continue; > > + } > > + > > + if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != > TESTED_MEMORY_ATTRIBUTES) { > > + continue; > > + } > > + > > + // > > + // Skip Resource Descriptor HOBs that do not contain the PHIT range > EfiFreeMemoryBottom..EfiFreeMemoryTop > > + // > > + if (Base < ResourceHob->PhysicalStart) { > > + continue; > > + } > > + > > + if (Top > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) > { > > + continue; > > + } > > + > > + return ResourceHob; > > + } > > + > > + return NULL; > > +} > > + > > +/** > > + Find the highest below 4G memory resource descriptor, except the input > Resource Descriptor. > > + @param[in] HobList Hob start address > > + @param[in] MinimalNeededSize Minimal needed size. > > + @param[in] ExceptResourceHob Ignore this Resource Descriptor. > > + @retval The pointer to the Resource Descriptor HOB. > > +**/ > > +EFI_HOB_RESOURCE_DESCRIPTOR * > > +FindAnotherHighestBelow4GResourceDescriptor ( > > + IN VOID *HobList, > > + IN UINTN MinimalNeededSize, > > + IN EFI_HOB_RESOURCE_DESCRIPTOR *ExceptResourceHob > > + ) > > +{ > > + EFI_PEI_HOB_POINTERS Hob; > > + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; > > + EFI_HOB_RESOURCE_DESCRIPTOR *ReturnResourceHob; > > + > > + ReturnResourceHob = NULL; > > + > > + for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = > GET_NEXT_HOB (Hob)) { > > + // > > + // Skip all HOBs except Resource Descriptor HOBs > > + // > > + if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { > > + continue; > > + } > > + > > + // > > + // Skip Resource Descriptor HOBs that do not describe tested system > memory > > + // > > + ResourceHob = Hob.ResourceDescriptor; > > + if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) { > > + continue; > > + } > > + > > + if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != > TESTED_MEMORY_ATTRIBUTES) { > > + continue; > > + } > > + > > + // > > + // Skip if the Resource Descriptor HOB equals to ExceptResourceHob > > + // > > + if (ResourceHob == ExceptResourceHob) { > > + continue; > > + } > > + > > + // > > + // Skip Resource Descriptor HOBs that are beyond 4G > > + // > > + if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > > BASE_4GB) { > > + continue; > > + } > > + > > + // > > + // Skip Resource Descriptor HOBs that are too small > > + // > > + if (ResourceHob->ResourceLength < MinimalNeededSize) { > > + continue; > > + } > > + > > + // > > + // Return the topest Resource Descriptor > > + // > > + if (ReturnResourceHob == NULL) { > > + ReturnResourceHob = ResourceHob; > > + } else { > > + if (ReturnResourceHob->PhysicalStart < ResourceHob->PhysicalStart) { > > + ReturnResourceHob = ResourceHob; > > + } > > + } > > + } > > + > > + return ReturnResourceHob; > > +} > > + > > +/** > > + Check the HOB and decide if it is need inside Payload > > + Payload maintainer may make decision which HOB is need or needn't > > + Then add the check logic in the function. > > + @param[in] Hob The HOB to check > > + @retval TRUE If HOB is need inside Payload > > + @retval FALSE If HOB is needn't inside Payload > > +**/ > > +BOOLEAN > > +IsHobNeed ( > > + EFI_PEI_HOB_POINTERS Hob > > + ) > > +{ > > + if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) { > > + return FALSE; > > + } > > + > > + if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) { > > + if (CompareGuid > (&Hob.MemoryAllocationModule->MemoryAllocationHeader.Name, > &gEfiHobMemoryAllocModuleGuid)) { > > + return FALSE; > > + } > > + } > > + > > + // Arrive here mean the HOB is need > > + return TRUE; > > +} > > + > > +/** > > + It will build Fv HOBs based on information from bootloaders. > > + @param[out] DxeFv The pointer to the DXE FV in memory. > > + @retval EFI_SUCCESS If it completed successfully. > > + @retval EFI_NOT_FOUND If it failed to find node in fit image. > > + @retval Others If it failed to build required HOBs. > > +**/ > > +EFI_STATUS > > +BuildFitLoadablesFvHob ( > > + OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv > > + ) > > +{ > > + EFI_STATUS Status; > > + VOID *Fdt; > > + UINT8 *GuidHob; > > + UNIVERSAL_PAYLOAD_BASE *PayloadBase; > > + INT32 ConfigNode; > > + INT32 Config1Node; > > + INT32 ImageNode; > > + INT32 FvNode; > > + INT32 Depth; > > + CONST FDT_PROPERTY *PropertyPtr; > > + INT32 TempLen; > > + CONST CHAR8 *Fvname; > > + UINT32 DataOffset; > > + UINT32 DataSize; > > + UINT32 *Data32; > > + > > + GuidHob = GetFirstGuidHob (&gUniversalPayloadBaseGuid); > > + if (GuidHob != NULL) { > > + PayloadBase = (UNIVERSAL_PAYLOAD_BASE *)GET_GUID_HOB_DATA (GuidHob); > > + Fdt = (VOID *)(UINTN)PayloadBase->Entry; > > + DEBUG ((DEBUG_INFO, "PayloadBase Entry = 0x%08x\n", > PayloadBase->Entry)); > > + } > > + > > + Status = FdtCheckHeader (Fdt); > > + if (EFI_ERROR (Status)) { > > + return EFI_UNSUPPORTED; > > + } > > + > > + ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", > (INT32)AsciiStrLen ("configurations")); > > + if (ConfigNode <= 0) { > > + return EFI_NOT_FOUND; > > + } > > + > > + Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", > (INT32)AsciiStrLen ("conf-1")); > > + if (Config1Node <= 0) { > > + return EFI_NOT_FOUND; > > + } > > + > > + ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", > (INT32)AsciiStrLen ("images")); > > + if (ImageNode <= 0) { > > + return EFI_NOT_FOUND; > > + } > > + > > + FvNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, "tianocore", > (INT32)AsciiStrLen ("tianocore")); > > + Depth = FdtNodeDepth (Fdt, FvNode); > > + FvNode = FdtNextNode (Fdt, FvNode, &Depth); > > + Fvname = FdtGetName (Fdt, FvNode, &TempLen); > > + while ((AsciiStrCmp ((Fvname + AsciiStrLen (Fvname) - 2), "fv") == 0)) { > > + if (FvNode <= 0) { > > + return EFI_NOT_FOUND; > > + } > > + > > + PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-offset", &TempLen); > > + Data32 = (UINT32 *)(PropertyPtr->Data); > > + DataOffset = SwapBytes32 (*Data32); > > + > > + PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-size", &TempLen); > > + Data32 = (UINT32 *)(PropertyPtr->Data); > > + DataSize = SwapBytes32 (*Data32); > > + > > + if (AsciiStrCmp (Fvname, "uefi-fv") == 0) { > > + *DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)PayloadBase->Entry + > (UINTN)DataOffset); > > + ASSERT ((*DxeFv)->FvLength == DataSize); > > + } else { > > + BuildFvHob (((UINTN)PayloadBase->Entry + (UINTN)DataOffset), > DataSize); > > + } > > + > > + DEBUG (( > > + DEBUG_INFO, > > + "UPL Multiple fv[%a], Base=0x%08x, size=0x%08x\n", > > + Fvname, > > + ((UINTN)PayloadBase->Entry + (UINTN)DataOffset), > > + DataSize, > > + DataOffset > > + )); > > + Depth = FdtNodeDepth (Fdt, FvNode); > > + FvNode = FdtNextNode (Fdt, FvNode, &Depth); > > + Fvname = FdtGetName (Fdt, FvNode, &TempLen); > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + It will build HOBs based on information from bootloaders. > > + @param[in] BootloaderParameter The starting memory address of > bootloader parameter block. > > + @param[out] DxeFv The pointer to the DXE FV in memory. > > + @retval EFI_SUCCESS If it completed successfully. > > + @retval Others If it failed to build required HOBs. > > +**/ > > +EFI_STATUS > > +BuildHobs ( > > + IN UINTN BootloaderParameter, > > + OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv > > + ) > > +{ > > + EFI_PEI_HOB_POINTERS Hob; > > + UINTN MinimalNeededSize; > > + EFI_PHYSICAL_ADDRESS FreeMemoryBottom; > > + EFI_PHYSICAL_ADDRESS FreeMemoryTop; > > + EFI_PHYSICAL_ADDRESS MemoryBottom; > > + EFI_PHYSICAL_ADDRESS MemoryTop; > > + EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob; > > + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; > > + UINT8 *GuidHob; > > + EFI_HOB_FIRMWARE_VOLUME *FvHob; > > + UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable; > > + ACPI_BOARD_INFO *AcpiBoardInfo; > > + EFI_HOB_HANDOFF_INFO_TABLE *HobInfo; > > + > > + Hob.Raw = (UINT8 *)BootloaderParameter; > > + MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize); > > + > > + ASSERT (Hob.Raw != NULL); > > + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop == > Hob.HandoffInformationTable->EfiFreeMemoryTop); > > + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryTop == > Hob.HandoffInformationTable->EfiMemoryTop); > > + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom == > Hob.HandoffInformationTable->EfiFreeMemoryBottom); > > + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryBottom == > Hob.HandoffInformationTable->EfiMemoryBottom); > > + > > + // > > + // Try to find Resource Descriptor HOB that contains Hob range > EfiMemoryBottom..EfiMemoryTop > > + // > > + PhitResourceHob = FindResourceDescriptorByRange (Hob.Raw, > Hob.HandoffInformationTable->EfiMemoryBottom, > Hob.HandoffInformationTable->EfiMemoryTop); > > + if (PhitResourceHob == NULL) { > > + // > > + // Boot loader's Phit Hob is not in an available Resource Descriptor, > find another Resource Descriptor for new Phit Hob > > + // > > + ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, > MinimalNeededSize, NULL); > > + if (ResourceHob == NULL) { > > + return EFI_NOT_FOUND; > > + } > > + > > + MemoryBottom = ResourceHob->PhysicalStart + > ResourceHob->ResourceLength - MinimalNeededSize; > > + FreeMemoryBottom = MemoryBottom; > > + FreeMemoryTop = ResourceHob->PhysicalStart + > ResourceHob->ResourceLength; > > + MemoryTop = FreeMemoryTop; > > + } else if (PhitResourceHob->PhysicalStart + > PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop > >= MinimalNeededSize) { > > + // > > + // New availiable Memory range in new hob is right above memory top > in old hob. > > + // > > + MemoryBottom = Hob.HandoffInformationTable->EfiFreeMemoryTop; > > + FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop; > > + FreeMemoryTop = FreeMemoryBottom + MinimalNeededSize; > > + MemoryTop = FreeMemoryTop; > > + } else if (Hob.HandoffInformationTable->EfiMemoryBottom - > PhitResourceHob->PhysicalStart >= MinimalNeededSize) { > > + // > > + // New availiable Memory range in new hob is right below memory > bottom in old hob. > > + // > > + MemoryBottom = Hob.HandoffInformationTable->EfiMemoryBottom - > MinimalNeededSize; > > + FreeMemoryBottom = MemoryBottom; > > + FreeMemoryTop = Hob.HandoffInformationTable->EfiMemoryBottom; > > + MemoryTop = Hob.HandoffInformationTable->EfiMemoryTop; > > + } else { > > + // > > + // In the Resource Descriptor HOB contains boot loader Hob, there is > no enough free memory size for payload hob > > + // Find another Resource Descriptor Hob > > + // > > + ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, > MinimalNeededSize, PhitResourceHob); > > + if (ResourceHob == NULL) { > > + return EFI_NOT_FOUND; > > + } > > + > > + MemoryBottom = ResourceHob->PhysicalStart + > ResourceHob->ResourceLength - MinimalNeededSize; > > + FreeMemoryBottom = MemoryBottom; > > + FreeMemoryTop = ResourceHob->PhysicalStart + > ResourceHob->ResourceLength; > > + MemoryTop = FreeMemoryTop; > > + } > > + > > + HobInfo = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID > *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID > *)(UINTN)FreeMemoryTop); > > + HobInfo->BootMode = Hob.HandoffInformationTable->BootMode; > > + // > > + // From now on, mHobList will point to the new Hob range. > > + // > > + > > + // > > + // Create an empty FvHob for the DXE FV that contains DXE core. > > + // > > + BuildFvHob ((EFI_PHYSICAL_ADDRESS)0, 0); > > + // > > + // Since payload created new Hob, move all hobs except PHIT from boot > loader hob list. > > + // > > + while (!END_OF_HOB_LIST (Hob)) { > > + if (IsHobNeed (Hob)) { > > + // Add this hob to payload HOB > > + AddNewHob (&Hob); > > + } > > + > > + Hob.Raw = GET_NEXT_HOB (Hob); > > + } > > + > > + BuildFitLoadablesFvHob (DxeFv); > > + > > + // > > + // Create guid hob for acpi board information > > + // > > + GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid); > > + if (GuidHob != NULL) { > > + AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA > (GuidHob); > > + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid); > > + if (GuidHob == NULL) { > > + AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp); > > + ASSERT (AcpiBoardInfo != NULL); > > + } > > + } > > + > > + // > > + // Update DXE FV information to first fv hob in the hob list, which > > + // is the empty FvHob created before. > > + // > > + FvHob = GetFirstHob (EFI_HOB_TYPE_FV); > > + FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)*DxeFv; > > + FvHob->Length = (*DxeFv)->FvLength; > > + return EFI_SUCCESS; > > +} > > + > > +/** > > + Entry point to the C language phase of UEFI payload. > > + @param[in] BootloaderParameter The starting address of bootloader > parameter block. > > + @retval It will not return if SUCCESS, and return error when > passing bootloader parameter. > > +**/ > > +EFI_STATUS > > +EFIAPI > > +_ModuleEntryPoint ( > > + IN UINTN BootloaderParameter > > + ) > > +{ > > + EFI_STATUS Status; > > + PHYSICAL_ADDRESS DxeCoreEntryPoint; > > + EFI_PEI_HOB_POINTERS Hob; > > + EFI_FIRMWARE_VOLUME_HEADER *DxeFv; > > + > > + mHobList = (VOID *)BootloaderParameter; > > + DxeFv = NULL; > > + // Call constructor for all libraries > > + ProcessLibraryConstructorList (); > > + > > + DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n")); > > + DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN))); > > + > > + DEBUG_CODE ( > > + // > > + // Dump the Hobs from boot loader > > + // > > + PrintHob (mHobList); > > + ); > > + > > + // Initialize floating point operating environment to be compliant with > UEFI spec. > > + InitializeFloatingPointUnits (); > > + > > + // Build HOB based on information from Bootloader > > + Status = BuildHobs (BootloaderParameter, &DxeFv); > > + ASSERT_EFI_ERROR (Status); > > + > > + FixUpPcdDatabase (DxeFv); > > + Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint); > > + ASSERT_EFI_ERROR (Status); > > + > > + // > > + // Mask off all legacy 8259 interrupt sources > > + // > > + IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF); > > + IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF); > > + > > + Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob > (EFI_HOB_TYPE_HANDOFF); > > + HandOffToDxeCore (DxeCoreEntryPoint, Hob); > > + > > + // Should not get here > > + CpuDeadLoop (); > > + return EFI_SUCCESS; > > +} > > diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf > b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf > new file mode 100644 > index 0000000000..a7d1a8c9e5 > --- /dev/null > +++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf > @@ -0,0 +1,98 @@ > +## @file > > +# This is the first module for UEFI payload. > > +# > > +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> > > +# > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > +[Defines] > > + INF_VERSION = 0x00010005 > > + BASE_NAME = FitUniversalPayloadEntry > > + FILE_GUID = CED5A8A9-B6EA-4D5A-8689-577EE88566CF > > + MODULE_TYPE = SEC > > + VERSION_STRING = 1.0 > > + > > +# > > +# The following information is for reference only and not required by the > build tools. > > +# > > +# VALID_ARCHITECTURES = IA32 X64 > > +# > > + > > +[Sources] > > + FitUniversalPayloadEntry.c > > + LoadDxeCore.c > > + MemoryAllocation.c > > + PrintHob.c > > + AcpiTable.c > > + > > +[Sources.Ia32] > > + X64/VirtualMemory.h > > + X64/VirtualMemory.c > > + Ia32/DxeLoadFunc.c > > + Ia32/IdtVectorAsm.nasm > > + > > +[Sources.X64] > > + X64/VirtualMemory.h > > + X64/VirtualMemory.c > > + X64/DxeLoadFunc.c > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + MdeModulePkg/MdeModulePkg.dec > > + UefiCpuPkg/UefiCpuPkg.dec > > + UefiPayloadPkg/UefiPayloadPkg.dec > > + > > +[LibraryClasses] > > + BaseMemoryLib > > + DebugLib > > + BaseLib > > + SerialPortLib > > + IoLib > > + HobLib > > + PeCoffLib > > + CpuLib > > + FdtLib > > + > > +[Guids] > > + gEfiMemoryTypeInformationGuid > > + gEfiFirmwareFileSystem2Guid > > + gEfiGraphicsInfoHobGuid > > + gEfiGraphicsDeviceInfoHobGuid > > + gUefiAcpiBoardInfoGuid > > + gEfiSmbiosTableGuid > > + gUefiSerialPortInfoGuid > > + gUniversalPayloadExtraDataGuid > > + gUniversalPayloadBaseGuid > > + gPcdDataBaseHobGuid > > + gUniversalPayloadSmbiosTableGuid > > + gEfiHobMemoryAllocBspStoreGuid > > + gUniversalPayloadAcpiTableGuid > > + gUniversalPayloadPciRootBridgeInfoGuid > > + gUniversalPayloadSmbios3TableGuid > > + > > +[FeaturePcd.IA32] > > + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## > CONSUMES > > + > > +[FeaturePcd.X64] > > + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ## > CONSUMES > > + > > + > > +[Pcd.IA32,Pcd.X64] > > + gUefiPayloadPkgTokenSpaceGuid.PcdPcdDriverFile > > + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable > ## SOMETIMES_CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask > ## CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask > ## CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask > ## CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard > ## CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase > ## CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize > ## CONSUMES > > + > > + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase > > + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize > > + gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize > > + > > + gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## > SOMETIMES_CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## > SOMETIMES_CONSUMES > > + gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## > SOMETIMES_CONSUMES > > diff --git a/UefiPayloadPkg/UefiPayloadPkg.dec > b/UefiPayloadPkg/UefiPayloadPkg.dec > index e2e4a79db3..2f1fd82487 100644 > --- a/UefiPayloadPkg/UefiPayloadPkg.dec > +++ b/UefiPayloadPkg/UefiPayloadPkg.dec > @@ -24,6 +24,9 @@ > # > > gUefiPayloadPkgTokenSpaceGuid = {0x1d127ea, 0xf6f1, 0x4ef6, {0x94, > 0x15, 0x8a, 0x0, 0x0, 0x93, 0xf8, 0x9d}} > > > > + ## Include/Guid/UniversalPayloadBase.h > > + gUniversalPayloadBaseGuid = { 0x03d4c61d, 0x2713, 0x4ec5, {0xa1, 0xcc, > 0x88, 0x3b, 0xe9, 0xdc, 0x18, 0xe5 } } > > + > > # > > # Gop Temp > > # > > diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc > b/UefiPayloadPkg/UefiPayloadPkg.dsc > index 47812048dd..af9308ef8e 100644 > --- a/UefiPayloadPkg/UefiPayloadPkg.dsc > +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc > @@ -30,7 +30,6 @@ > DEFINE PS2_KEYBOARD_ENABLE = FALSE > > DEFINE RAM_DISK_ENABLE = FALSE > > DEFINE SIO_BUS_ENABLE = FALSE > > - DEFINE UNIVERSAL_PAYLOAD = FALSE > > DEFINE SECURITY_STUB_ENABLE = TRUE > > DEFINE SMM_SUPPORT = FALSE > > DEFINE PLATFORM_BOOT_TIMEOUT = 3 > > @@ -44,6 +43,14 @@ > DEFINE BOOTSPLASH_IMAGE = FALSE > > DEFINE NVME_ENABLE = TRUE > > DEFINE CAPSULE_SUPPORT = FALSE > > + # > > + # Setup Universal Payload > > + # > > + # ELF: Build UniversalPayload file as UniversalPayload.elf > > + # FIT: Build UniversalPayload file as UniversalPayload.fit > > + # > > + DEFINE UNIVERSAL_PAYLOAD = FALSE > > + DEFINE UNIVERSAL_PAYLOAD_FORMAT = ELF > > > > # > > # NULL: NullMemoryTestDxe > > @@ -311,7 +318,7 @@ > > VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf > > CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf > > > ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf > > - > > + FdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf > > [LibraryClasses.common] > > !if $(BOOTSPLASH_IMAGE) > > SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf > > @@ -600,14 +607,26 @@ > !if "IA32" in "$(ARCH)" > > [Components.IA32] > > !if $(UNIVERSAL_PAYLOAD) == TRUE > > - UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf > > + !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF" > > + UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf > > + !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT" > > + UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf > > + !else > > + UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf > > + !endif > > !else > > UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf > > !endif > > !else > > [Components.X64] > > !if $(UNIVERSAL_PAYLOAD) == TRUE > > - UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf > > + !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF" > > + UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf > > + !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT" > > + UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf > > + !else > > + UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf > > + !endif > > !else > > UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf > > !endif > > diff --git a/UefiPayloadPkg/UniversalPayloadBuild.py > b/UefiPayloadPkg/UniversalPayloadBuild.py > index 47f37b3377..9a83fc9e44 100644 > --- a/UefiPayloadPkg/UniversalPayloadBuild.py > +++ b/UefiPayloadPkg/UniversalPayloadBuild.py > @@ -10,10 +10,22 @@ import subprocess > import os > > import shutil > > import sys > > +import pathlib > > from ctypes import * > > -from Tools.ElfFv import ReplaceFv > > + > > sys.dont_write_bytecode = True > > > > +class bcolors: > > + HEADER = '\033[95m' > > + OKBLUE = '\033[94m' > > + OKCYAN = '\033[96m' > > + OKGREEN = '\033[92m' > > + WARNING = '\033[93m' > > + FAIL = '\033[91m' > > + ENDC = '\033[0m' > > + BOLD = '\033[1m' > > + UNDERLINE = '\033[4m' > > + > > class UPLD_INFO_HEADER(LittleEndianStructure): > > _pack_ = 1 > > _fields_ = [ > > @@ -36,40 +48,114 @@ class UPLD_INFO_HEADER(LittleEndianStructure): > self.ImageId = b'UEFI' > > self.ProducerId = b'INTEL' > > > > -def BuildUniversalPayload(Args): > > - def RunCommand(cmd): > > - print(cmd) > > - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, > stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE']) > > - while True: > > - line = p.stdout.readline() > > - if not line: > > - break > > - print(line.strip().decode(errors='ignore')) > > - > > - p.communicate() > > - if p.returncode != 0: > > - print("- Failed - error happened when run command: %s"%cmd) > > - raise Exception("ERROR: when run command: %s"%cmd) > > +def ValidateSpecRevision (Argument): > > + try: > > + (MajorStr, MinorStr) = Argument.split('.') > > + except: > > + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision > format (Major[8-bits].Minor[8-bits]).'.format (Argument)) > > + # > > + # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor > Version. > > + # > > + if len(MinorStr) > 0 and len(MinorStr) < 3: > > + try: > > + Minor = int(MinorStr, 16) if len(MinorStr) == 2 else > (int(MinorStr, 16) << 4) > > + except: > > + raise argparse.ArgumentTypeError ('{} Minor version of > SpecRevision is not a valid integer value.'.format (Argument)) > > + else: > > + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision > format (Major[8-bits].Minor[8-bits]).'.format (Argument)) > > + > > + if len(MajorStr) > 0 and len(MajorStr) < 3: > > + try: > > + Major = int(MajorStr, 16) > > + except: > > + raise argparse.ArgumentTypeError ('{} Major version of > SpecRevision is not a valid integer value.'.format (Argument)) > > + else: > > + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision > format (Major[8-bits].Minor[8-bits]).'.format (Argument)) > > + > > + return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0) > > + > > +def Validate32BitInteger (Argument): > > + try: > > + Value = int (Argument, 0) > > + except: > > + raise argparse.ArgumentTypeError ('{} is not a valid integer > value.'.format (Argument)) > > + if Value < 0: > > + raise argparse.ArgumentTypeError ('{} is a negative > value.'.format (Argument)) > > + if Value > 0xffffffff: > > + raise argparse.ArgumentTypeError ('{} is larger than > 32-bits.'.format (Argument)) > > + return Value > > > > +def ValidateAddFv (Argument): > > + Value = Argument.split ("=") > > + if len (Value) != 2: > > + raise argparse.ArgumentTypeError ('{} is incorrect format with > "xxx_fv=xxx.fv"'.format (Argument)) > > + if Value[0][-3:] != "_fv": > > + raise argparse.ArgumentTypeError ('{} is incorrect format with > "xxx_fv=xxx.fv"'.format (Argument)) > > + if Value[1][-3:].lower () != ".fv": > > + raise argparse.ArgumentTypeError ('{} is incorrect format with > "xxx_fv=xxx.fv"'.format (Argument)) > > + if os.path.exists (Value[1]) == False: > > + raise argparse.ArgumentTypeError ('File {} is not found.'.format > (Value[1])) > > + return Value > > + > > +def RunCommand(cmd): > > + print(cmd) > > + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, > stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE']) > > + while True: > > + line = p.stdout.readline() > > + if not line: > > + break > > + print(line.strip().decode(errors='ignore')) > > + > > + p.communicate() > > + if p.returncode != 0: > > + print("- Failed - error happened when run command: %s"%cmd) > > + raise Exception("ERROR: when run command: %s"%cmd) > > + > > +def BuildUniversalPayload(Args): > > BuildTarget = Args.Target > > ToolChain = Args.ToolChain > > Quiet = "--quiet" if Args.Quiet else "" > > - ElfToolChain = 'CLANGDWARF' > > - BuildDir = os.path.join(os.environ['WORKSPACE'], > os.path.normpath("Build/UefiPayloadPkgX64")) > > - BuildModule = "" > > - BuildArch = "" > > > > + if Args.Fit == True: > > + PayloadEntryToolChain = ToolChain > > + Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=FIT") > > + UpldEntryFile = "FitUniversalPayloadEntry" > > + else: > > + PayloadEntryToolChain = 'CLANGDWARF' > > + Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=ELF") > > + UpldEntryFile = "UniversalPayloadEntry" > > + > > + BuildDir = os.path.join(os.environ['WORKSPACE'], > os.path.normpath("Build/UefiPayloadPkgX64")) > > if Args.Arch == 'X64': > > BuildArch = "X64" > > - EntryOutputDir = os.path.join(BuildDir, "{}_{}".format > (BuildTarget, ElfToolChain), > os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll")) > > + FitArch = "x86_64" > > + ObjCopyFlag = "elf64-x86-64" > > + EntryOutputDir = os.path.join(BuildDir, "{}_{}".format > (BuildTarget, PayloadEntryToolChain), > os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format > (UpldEntryFile, UpldEntryFile))) > > else: > > BuildArch = "IA32 -a X64" > > - EntryOutputDir = os.path.join(BuildDir, "{}_{}".format > (BuildTarget, ElfToolChain), > os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll")) > > + FitArch = "x86" > > + ObjCopyFlag = "elf32-i386" > > + EntryOutputDir = os.path.join(BuildDir, "{}_{}".format > (BuildTarget, PayloadEntryToolChain), > os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format > (UpldEntryFile, UpldEntryFile))) > > > > + EntryModuleInf = > os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/{}.inf".format > (UpldEntryFile)) > > DscPath = os.path.normpath("UefiPayloadPkg/UefiPayloadPkg.dsc") > > + DxeFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, > ToolChain), os.path.normpath("FV/DXEFV.Fv")) > > + BdsFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, > ToolChain), os.path.normpath("FV/BDSFV.Fv")) > > + NetworkFvOutputDir = os.path.join(BuildDir, "{}_{}".format > (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv")) > > + PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt") > > ModuleReportPath = os.path.join(BuildDir, > "UefiUniversalPayloadEntry.txt") > > UpldInfoFile = os.path.join(BuildDir, "UniversalPayloadInfo.bin") > > > > + if "CLANG_BIN" in os.environ: > > + LlvmObjcopyPath = os.path.join(os.environ["CLANG_BIN"], > "llvm-objcopy") > > + else: > > + LlvmObjcopyPath = "llvm-objcopy" > > + try: > > + RunCommand('"%s" --version'%LlvmObjcopyPath) > > + except: > > + print("- Failed - Please check if LLVM is installed or if > CLANG_BIN is set correctly") > > + sys.exit(1) > > + > > Pcds = "" > > if (Args.pcd != None): > > for PcdItem in Args.pcd: > > @@ -84,7 +170,6 @@ def BuildUniversalPayload(Args): > # Building DXE core and DXE drivers as DXEFV. > > # > > if Args.BuildEntryOnly == False: > > - PayloadReportPath = os.path.join(BuildDir, > "UefiUniversalPayload.txt") > > BuildPayload = "build -p {} -b {} -a X64 -t {} -y {} {}".format > (DscPath, BuildTarget, ToolChain, PayloadReportPath, Quiet) > > BuildPayload += Pcds > > BuildPayload += Defines > > @@ -93,94 +178,138 @@ def BuildUniversalPayload(Args): > # Building Universal Payload entry. > > # > > if Args.PreBuildUplBinary is None: > > - EntryModuleInf = > os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf") > > - BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} > {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, ElfToolChain, > ModuleReportPath, Quiet) > > + BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} > {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, > PayloadEntryToolChain, ModuleReportPath, Quiet) > > BuildModule += Pcds > > BuildModule += Defines > > RunCommand(BuildModule) > > > > if Args.PreBuildUplBinary is not None: > > - EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf") > > + if Args.Fit == False: > > + EntryOutputDir = os.path.join(BuildDir, > "UniversalPayload.elf") > > + else: > > + EntryOutputDir = os.path.join(BuildDir, > "UniversalPayload.fit") > > shutil.copy (os.path.abspath(Args.PreBuildUplBinary), > EntryOutputDir) > > > > # > > - # Buid Universal Payload Information Section ".upld_info" > > + # Build Universal Payload Information Section ".upld_info" > > # > > - upld_info_hdr = UPLD_INFO_HEADER() > > - upld_info_hdr.SpecRevision = Args.SpecRevision > > - upld_info_hdr.Revision = Args.Revision > > - upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16] > > - upld_info_hdr.ImageId = Args.ImageId.encode()[:16] > > - upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0 > > - fp = open(UpldInfoFile, 'wb') > > - fp.write(bytearray(upld_info_hdr)) > > - fp.close() > > + if Args.Fit == False: > > + upld_info_hdr = UPLD_INFO_HEADER() > > + upld_info_hdr.SpecRevision = Args.SpecRevision > > + upld_info_hdr.Revision = Args.Revision > > + upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16] > > + upld_info_hdr.ImageId = Args.ImageId.encode()[:16] > > + upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0 > > + fp = open(UpldInfoFile, 'wb') > > + fp.write(bytearray(upld_info_hdr)) > > + fp.close() > > + > > + if Args.BuildEntryOnly == False: > > + import Tools.ElfFv as ElfFv > > + ElfFv.ReplaceFv (EntryOutputDir, UpldInfoFile, '.upld_info', > Alignment = 4) > > + if Args.Fit == False: > > + shutil.copy (EntryOutputDir, os.path.join(BuildDir, > 'UniversalPayload.elf')) > > + else: > > + shutil.copy (EntryOutputDir, os.path.join(BuildDir, > 'UniversalPayload.fit')) > > > > MultiFvList = [] > > if Args.BuildEntryOnly == False: > > MultiFvList = [ > > - ['uefi_fv', os.path.join(BuildDir, "{}_{}".format > (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ], > > - ['bds_fv', os.path.join(BuildDir, "{}_{}".format > (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ], > > - ['network_fv', os.path.join(BuildDir, "{}_{}".format > (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv")) ], > > + ['uefi_fv', os.path.join(BuildDir, "{}_{}".format > (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ], > > + ['bds_fv', os.path.join(BuildDir, "{}_{}".format > (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ], > > + ['network_fv', os.path.join(BuildDir, "{}_{}".format > (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))], > > ] > > - AddSectionName = '.upld_info' > > - ReplaceFv (EntryOutputDir, UpldInfoFile, AddSectionName, > Alignment = 4) > > > > - if Args.PreBuildUplBinary is None: > > - shutil.copy (EntryOutputDir, os.path.join(BuildDir, > 'UniversalPayload.elf')) > > > > - return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf') > > + if Args.Fit == True: > > + import Tools.MkFitImage as MkFitImage > > + import pefile > > + fit_image_info_header = > MkFitImage.FIT_IMAGE_INFO_HEADER() > > + fit_image_info_header.Description = 'Uefi Universal Payload' > > + fit_image_info_header.UplVersion = Args.SpecRevision > > + fit_image_info_header.Type = 'flat-binary' > > + fit_image_info_header.Arch = FitArch > > + fit_image_info_header.Compression = 'none' > > + fit_image_info_header.Revision = Args.Revision > > + fit_image_info_header.BuildType = Args.Target.lower() > > + fit_image_info_header.Capabilities = None > > + fit_image_info_header.Producer = Args.ProducerId.lower() > > + fit_image_info_header.ImageId = Args.ImageId.lower() > > + fit_image_info_header.Binary = os.path.join(BuildDir, > 'UniversalPayload.fit') > > + fit_image_info_header.TargetPath = os.path.join(BuildDir, > 'UniversalPayload.fit') > > + fit_image_info_header.UefifvPath = DxeFvOutputDir > > + fit_image_info_header.BdsfvPath = BdsFvOutputDir > > + fit_image_info_header.NetworkfvPath = NetworkFvOutputDir > > + fit_image_info_header.DataOffset = 0x1000 > > + fit_image_info_header.LoadAddr = Args.LoadAddress > > + fit_image_info_header.Project = 'tianocore' > > + > > + TargetRebaseFile = fit_image_info_header.Binary.replace > (pathlib.Path(fit_image_info_header.Binary).suffix, ".pecoff") > > + TargetRebaseEntryFile = fit_image_info_header.Binary.replace > (pathlib.Path(fit_image_info_header.Binary).suffix, ".entry") > > + > > > > -def main(): > > - def ValidateSpecRevision (Argument): > > - try: > > - (MajorStr, MinorStr) = Argument.split('.') > > - except: > > - raise argparse.ArgumentTypeError ('{} is not a valid > SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) > > # > > - # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor > Version. > > + # Rebase PECOFF to load address > > # > > - if len(MinorStr) > 0 and len(MinorStr) < 3: > > - try: > > - Minor = int(MinorStr, 16) if len(MinorStr) == 2 else > (int(MinorStr, 16) << 4) > > - except: > > - raise argparse.ArgumentTypeError ('{} Minor version of > SpecRevision is not a valid integer value.'.format (Argument)) > > - else: > > - raise argparse.ArgumentTypeError ('{} is not a valid > SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) > > + RunCommand ( > > + "GenFw -e SEC -o {} {}".format ( > > + TargetRebaseFile, > > + fit_image_info_header.Binary > > + )) > > + RunCommand ( > > + "GenFw --rebase 0x{:02X} -o {} {} ".format ( > > + fit_image_info_header.LoadAddr + > fit_image_info_header.DataOffset, > > + TargetRebaseFile, > > + TargetRebaseFile, > > + )) > > > > - if len(MajorStr) > 0 and len(MajorStr) < 3: > > - try: > > - Major = int(MajorStr, 16) > > - except: > > - raise argparse.ArgumentTypeError ('{} Major version of > SpecRevision is not a valid integer value.'.format (Argument)) > > - else: > > - raise argparse.ArgumentTypeError ('{} is not a valid > SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) > > + # > > + # Open PECOFF relocation table binary. > > + # > > + RelocBinary = b'' > > + PeCoff = pefile.PE (TargetRebaseFile) > > + for reloc in PeCoff.DIRECTORY_ENTRY_BASERELOC: > > + for entry in reloc.entries: > > + if (entry.type == 0): > > + continue > > + Type = entry.type > > + Offset = entry.rva + fit_image_info_header.DataOffset > > + RelocBinary += Type.to_bytes (8, 'little') + > Offset.to_bytes (8, 'little') > > + RelocBinary += b'\x00' * (0x1000 - (len(RelocBinary) % 0x1000)) > > > > - return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0) > > + # > > + # Output UniversalPayload.entry > > + # > > + TempBinary = open (TargetRebaseFile, 'rb') > > + TianoBinary = TempBinary.read () > > + TempBinary.close () > > > > - def Validate32BitInteger (Argument): > > - try: > > - Value = int (Argument, 0) > > - except: > > - raise argparse.ArgumentTypeError ('{} is not a valid integer > value.'.format (Argument)) > > - if Value < 0: > > - raise argparse.ArgumentTypeError ('{} is a negative > value.'.format (Argument)) > > - if Value > 0xffffffff: > > - raise argparse.ArgumentTypeError ('{} is larger than > 32-bits.'.format (Argument)) > > - return Value > > - > > - def ValidateAddFv (Argument): > > - Value = Argument.split ("=") > > - if len (Value) != 2: > > - raise argparse.ArgumentTypeError ('{} is incorrect format > with "xxx_fv=xxx.fv"'.format (Argument)) > > - if Value[0][-3:] != "_fv": > > - raise argparse.ArgumentTypeError ('{} is incorrect format > with "xxx_fv=xxx.fv"'.format (Argument)) > > - if Value[1][-3:].lower () != ".fv": > > - raise argparse.ArgumentTypeError ('{} is incorrect format > with "xxx_fv=xxx.fv"'.format (Argument)) > > - if os.path.exists (Value[1]) == False: > > - raise argparse.ArgumentTypeError ('File {} is not > found.'.format (Value[1])) > > - return Value > > + TianoEntryBinary = TianoBinary + RelocBinary > > + TianoEntryBinary += (b'\x00' * (0x1000 - (len(TianoBinary) % > 0x1000))) > > + TianoEntryBinarySize = len (TianoEntryBinary) > > + > > + TempBinary = open(TargetRebaseEntryFile, "wb") > > + TempBinary.truncate() > > + TempBinary.write(TianoEntryBinary) > > + TempBinary.close() > > + > > + # > > + # Calculate entry and update relocation table start address and > data-size. > > + # > > + fit_image_info_header.Entry = > PeCoff.OPTIONAL_HEADER.ImageBase + > PeCoff.OPTIONAL_HEADER.AddressOfEntryPoint > > + fit_image_info_header.RelocStart = > fit_image_info_header.DataOffset + len(TianoBinary) > > + fit_image_info_header.DataSize = TianoEntryBinarySize > > + fit_image_info_header.Binary = TargetRebaseEntryFile > > + > > + if MkFitImage.MakeFitImage(fit_image_info_header) is True: > > + print('\nSuccessfully build Fit Image') > > + else: > > + sys.exit(1) > > + return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.fit') > > + else: > > + return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf') > > > > +def main(): > > parser = argparse.ArgumentParser(description='For building Universal > Payload') > > parser.add_argument('-t', '--ToolChain') > > parser.add_argument('-b', '--Target', default='DEBUG') > > @@ -192,13 +321,16 @@ def main(): > parser.add_argument("-s", "--SpecRevision", > type=ValidateSpecRevision, default ='0.7', help='Indicates compliance with > a revision of this specification in the BCD format.') > > parser.add_argument("-r", "--Revision", type=Validate32BitInteger, > default ='0x0000010105', help='Revision of the Payload binary. > Major.Minor.Revision.Build') > > parser.add_argument("-o", "--ProducerId", default ='INTEL', help='A > null-terminated OEM-supplied string that identifies the payload producer > (16 bytes maximal).') > > + parser.add_argument("-e", "--BuildEntryOnly", action='store_true', > help='Build UniversalPayload Entry file') > > + parser.add_argument("-pb", "--PreBuildUplBinary", default=None, > help='Specify the UniversalPayload file') > > parser.add_argument("-sk", "--SkipBuild", action='store_true', > help='Skip UniversalPayload build') > > parser.add_argument("-af", "--AddFv", type=ValidateAddFv, > action='append', help='Add or replace specific FV into payload, Ex: > uefi_fv=XXX.fv') > > - command_group = parser.add_mutually_exclusive_group() > > - command_group.add_argument("-e", "--BuildEntryOnly", > action='store_true', help='Build UniversalPayload Entry file') > > - command_group.add_argument("-pb", "--PreBuildUplBinary", > default=None, help='Specify the UniversalPayload file') > > + parser.add_argument("-f", "--Fit", action='store_true', help='Build > UniversalPayload file as UniversalPayload.fit', default=False) > > + parser.add_argument('-l', "--LoadAddress", type=int, help='Specify > payload load address', default =0x000800000) > > + > > args = parser.parse_args() > > > > + > > MultiFvList = [] > > UniversalPayloadBinary = args.PreBuildUplBinary > > if (args.SkipBuild == False): > > @@ -208,12 +340,24 @@ def main(): > for (SectionName, SectionFvFile) in args.AddFv: > > MultiFvList.append ([SectionName, SectionFvFile]) > > > > + def ReplaceFv (UplBinary, SectionFvFile, SectionName): > > + print (bcolors.OKGREEN + "Patch {}={} into {}".format > (SectionName, SectionFvFile, UplBinary) + bcolors.ENDC) > > + if (args.Fit == False): > > + import Tools.ElfFv as ElfFv > > + return ElfFv.ReplaceFv (UplBinary, SectionFvFile, > '.upld.{}'.format (SectionName)) > > + else: > > + import Tools.MkFitImage as MkFitImage > > + return MkFitImage.ReplaceFv (UplBinary, SectionFvFile, > SectionName) > > + > > if (UniversalPayloadBinary != None): > > for (SectionName, SectionFvFile) in MultiFvList: > > if os.path.exists (SectionFvFile) == False: > > continue > > - print ("Patch {}={} into {}".format (SectionName, > SectionFvFile, UniversalPayloadBinary)) > > - ReplaceFv (UniversalPayloadBinary, SectionFvFile, > '.upld.{}'.format (SectionName)) > > + > > + status = ReplaceFv (UniversalPayloadBinary, SectionFvFile, > SectionName.replace ("_", "-")) > > + if status != 0: > > + print (bcolors.FAIL + "[Fail] Patch {}={}".format > (SectionName, SectionFvFile) + bcolors.ENDC) > > + return status > > > > print ("\nSuccessfully build Universal Payload") > > > > -- > 2.39.1.windows.1 > > > > > > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108704): https://edk2.groups.io/g/devel/message/108704 Mute This Topic: https://groups.io/mt/101375948/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- [-- Attachment #2: Type: text/html, Size: 138720 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support 2023-09-15 10:26 ` Sheng Lean Tan @ 2023-09-15 10:32 ` Sheng Lean Tan 0 siblings, 0 replies; 10+ messages in thread From: Sheng Lean Tan @ 2023-09-15 10:32 UTC (permalink / raw) To: Sheng Lean Tan, devel [-- Attachment #1: Type: text/plain, Size: 414 bytes --] The spec version should be v.8 instead of v.75 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108705): https://edk2.groups.io/g/devel/message/108705 Mute This Topic: https://groups.io/mt/101375948/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- [-- Attachment #2: Type: text/html, Size: 826 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support 2023-09-15 8:58 ` [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support brucex.wang 2023-09-15 9:02 ` Guo, Gua @ 2023-09-15 9:06 ` Lu, James 1 sibling, 0 replies; 10+ messages in thread From: Lu, James @ 2023-09-15 9:06 UTC (permalink / raw) To: Wang, BruceX, devel@edk2.groups.io; +Cc: Dong, Guo, Rhodes, Sean, Guo, Gua Reviewed-by: James Lu <james.lu@intel.com> Thanks, James -----Original Message----- From: Wang, BruceX <brucex.wang@intel.com> Sent: Friday, September 15, 2023 4:58 PM To: devel@edk2.groups.io Cc: Wang, BruceX <brucex.wang@intel.com>; Dong, Guo <guo.dong@intel.com>; Rhodes, Sean <sean@starlabs.systems>; Lu, James <james.lu@intel.com>; Guo, Gua <gua.guo@intel.com> Subject: [PATCH v2 2/2] UefiPayloadPkg: Add FIT support From: "Brucex.Wang" <brucex.wang@intel.com> Provide Fit format for UniversalPayload, developer can use argument "--Fit" to build UniversalPayload.fit Cc: Guo Dong <guo.dong@intel.com> Cc: Sean Rhodes <sean@starlabs.systems> Cc: James Lu <james.lu@intel.com> Cc: Gua Guo <gua.guo@intel.com> Signed-off-by: BruceX Wang <brucex.wang@intel.com> --- .../Include/Guid/UniversalPayloadBase.h | 21 + UefiPayloadPkg/PayloadLoaderPeim/FitLib.h | 60 ++ .../PayloadLoaderPeim/FitLib/FitLib.c | 127 ++++ .../PayloadLoaderPeim/FitPayloadLoaderPeim.c | 150 ++++ .../FitPayloadLoaderPeim.inf | 59 ++ UefiPayloadPkg/Readme.md | 191 +++++ UefiPayloadPkg/Tools/MkFitImage.py | 272 ++++++++ .../FitUniversalPayloadEntry.c | 654 ++++++++++++++++++ .../FitUniversalPayloadEntry.inf | 98 +++ UefiPayloadPkg/UefiPayloadPkg.dec | 3 + UefiPayloadPkg/UefiPayloadPkg.dsc | 27 +- UefiPayloadPkg/UniversalPayloadBuild.py | 328 ++++++--- 12 files changed, 1894 insertions(+), 96 deletions(-) create mode 100644 UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib.h create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c create mode 100644 UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf create mode 100644 UefiPayloadPkg/Readme.md create mode 100644 UefiPayloadPkg/Tools/MkFitImage.py create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c create mode 100644 UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf diff --git a/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h new file mode 100644 index 0000000000..31c9ec0bfb --- /dev/null +++ b/UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h @@ -0,0 +1,21 @@ +/** @file + Universal Payload general definitions. + +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Revision Reference: + - Universal Payload Specification 0.75 (https://universalpayload.github.io/documentation/) +**/ + +#ifndef UNIVERSAL_PAYLOAD_BASE_H_ +#define UNIVERSAL_PAYLOAD_BASE_H_ + +extern GUID gUniversalPayloadBaseGuid; + +typedef struct { + UNIVERSAL_PAYLOAD_GENERIC_HEADER Header; + EFI_PHYSICAL_ADDRESS Entry; +} UNIVERSAL_PAYLOAD_BASE; + +#endif // UNIVERSAL_PAYLOAD_BASE_H_ diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h new file mode 100644 index 0000000000..0514d675a6 --- /dev/null +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib.h @@ -0,0 +1,60 @@ +/** @file + FIT Load Image Support +Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef FIT_LIB_H_ +#define FIT_LIB_H_ + +#include <PiPei.h> +#include <Library/DebugLib.h> +#include <Library/FdtLib.h> + +typedef struct { + UINT64 RelocateType; + UINT64 Offset; +} FIT_RELOCATE_ITEM; + +typedef struct { + EFI_PHYSICAL_ADDRESS ImageBase; + EFI_PHYSICAL_ADDRESS PayloadBaseAddress; + UINT64 PayloadSize; + UINTN PayloadEntryOffset; + UINTN PayloadEntrySize; + EFI_PHYSICAL_ADDRESS PayloadEntryPoint; + UINTN RelocateTableOffset; + UINTN RelocateTableCount; + EFI_PHYSICAL_ADDRESS PayloadLoadAddress; +} FIT_IMAGE_CONTEXT; + +typedef struct { + UINT8 *Name; + UINT32 Offset; +} PROPERTY_DATA; + +#define IMAGE_BASE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, ImageBase) +#define PAYLOAD_BASE_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadBaseAddress) +#define PAYLOAD_BASE_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadSize) +#define PAYLOAD_ENTRY_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryOffset) +#define PAYLOAD_ENTRY_SIZE_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntrySize) +#define PAYLOAD_ENTRY_POINT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadEntryPoint) +#define RELOCATE_TABLE_OFFSET_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableOffset) +#define RELOCATE_TABLE_COUNT_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, RelocateTableCount) +#define PAYLOAD_LOAD_ADDR_OFFSET OFFSET_OF (FIT_IMAGE_CONTEXT, PayloadLoadAddress) + +/** + Parse the FIT image info. + @param[in] ImageBase Memory address of an image. + @param[out] Context The FIT image context pointer. + @retval EFI_UNSUPPORTED Unsupported binary type. + @retval EFI_SUCCESS FIT binary is loaded successfully. +**/ +EFI_STATUS +EFIAPI +ParseFitImage ( + IN VOID *ImageBase, + OUT FIT_IMAGE_CONTEXT *Context + ); + +#endif diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c new file mode 100644 index 0000000000..9d1d8a4f61 --- /dev/null +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c @@ -0,0 +1,127 @@ +/** @file + FIT Load Image Support +Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "FitLib.h" + +PROPERTY_DATA PropertyData32List[] = { + { "data-offset", PAYLOAD_ENTRY_OFFSET_OFFSET }, + { "data-size", PAYLOAD_ENTRY_SIZE_OFFSET }, + { "reloc-start", RELOCATE_TABLE_OFFSET_OFFSET } +}; + +PROPERTY_DATA PropertyData64List[] = { + { "entry-start", PAYLOAD_ENTRY_POINT_OFFSET }, + { "load", PAYLOAD_LOAD_ADDR_OFFSET } +}; + +/** + Parse the target firmware image info in FIT. + @param[in] Fdt Memory address of a fdt. + @param[in] Firmware Target name of an image. + @param[out] Context The FIT image context pointer. + @retval EFI_NOT_FOUND FIT node dose not find. + @retval EFI_SUCCESS FIT binary is loaded successfully. +**/ +EFI_STATUS +EFIAPI +FitParseFirmwarePropertyData ( + IN VOID *Fdt, + IN CHAR8 *Firmware, + OUT FIT_IMAGE_CONTEXT *Context + ) +{ + CONST FDT_PROPERTY *PropertyPtr; + INT32 ImageNode; + INT32 TianoNode; + INT32 TempLen; + UINT32 *Data32; + UINT64 *Data64; + UINT32 *ContextOffset32; + UINT64 *ContextOffset64; + INT32 Index; + + ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images")); + if (ImageNode <= 0) { + return EFI_NOT_FOUND; + } + + TianoNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, Firmware, (INT32)AsciiStrLen (Firmware)); + if (TianoNode <= 0) { + return EFI_NOT_FOUND; + } + + for (Index = 0; Index < sizeof (PropertyData32List) / sizeof (PROPERTY_DATA); Index++) { + PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData32List[Index].Name, &TempLen); + Data32 = (UINT32 *)(PropertyPtr->Data); + ContextOffset32 = (UINT32 *)((UINTN)Context + PropertyData32List[Index].Offset); + *ContextOffset32 = Fdt32ToCpu (*Data32); + } + + for (Index = 0; Index < sizeof (PropertyData64List)/sizeof (PROPERTY_DATA); Index++) { + PropertyPtr = FdtGetProperty (Fdt, TianoNode, PropertyData64List[Index].Name, &TempLen); + Data64 = (UINT64 *)(PropertyPtr->Data); + ContextOffset64 = (UINT64 *)((UINTN)Context + PropertyData64List[Index].Offset); + *ContextOffset64 = Fdt64ToCpu (*Data64); + } + + return EFI_SUCCESS; +} + +/** + Parse the FIT image info. + @param[in] ImageBase Memory address of an image. + @param[out] Context The FIT image context pointer. + @retval EFI_UNSUPPORTED Unsupported binary type. + @retval EFI_SUCCESS FIT binary is loaded successfully. +**/ +EFI_STATUS +EFIAPI +ParseFitImage ( + IN VOID *ImageBase, + OUT FIT_IMAGE_CONTEXT *Context + ) +{ + VOID *Fdt; + INT32 ConfigNode; + INT32 Config1Node; + CONST FDT_PROPERTY *PropertyPtr; + INT32 TempLen; + UINT32 *Data32; + UINT64 Value; + EFI_STATUS Status; + UINTN UplSize; + CHAR8 *Firmware; + + Status = FdtCheckHeader (ImageBase); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Fdt = ImageBase; + PropertyPtr = FdtGetProperty (Fdt, 0, "size", &TempLen); + Data32 = (UINT32 *)(PropertyPtr->Data); + UplSize = Value = Fdt32ToCpu (*Data32); + ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations")); + if (ConfigNode <= 0) { + return EFI_NOT_FOUND; + } + + Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1")); + if (Config1Node <= 0) { + return EFI_NOT_FOUND; + } + + PropertyPtr = FdtGetProperty (Fdt, Config1Node, "firmware", &TempLen); + Firmware = (CHAR8 *)(PropertyPtr->Data); + + FitParseFirmwarePropertyData (Fdt, Firmware, Context); + + Context->ImageBase = (EFI_PHYSICAL_ADDRESS)ImageBase; + Context->PayloadSize = UplSize; + Context->RelocateTableCount = (Context->PayloadEntrySize - (Context->RelocateTableOffset - Context->PayloadEntryOffset)) / sizeof (FIT_RELOCATE_ITEM); + + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c new file mode 100644 index 0000000000..3c5dacbb65 --- /dev/null +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c @@ -0,0 +1,150 @@ +/** @file + ELF Load Image Support +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include <PiPei.h> +#include <UniversalPayload/UniversalPayload.h> +#include <Guid/UniversalPayloadBase.h> +#include <UniversalPayload/ExtraData.h> + +#include <Ppi/LoadFile.h> + +#include <Library/DebugLib.h> +#include <Library/HobLib.h> +#include <Library/PeiServicesLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/BaseMemoryLib.h> + +#include "FitLib.h" + +/** + The wrapper function of PeiLoadImageLoadImage(). + @param This - Pointer to EFI_PEI_LOAD_FILE_PPI. + @param FileHandle - Pointer to the FFS file header of the image. + @param ImageAddressArg - Pointer to PE/TE image. + @param ImageSizeArg - Size of PE/TE image. + @param EntryPoint - Pointer to entry point of specified image file for output. + @param AuthenticationState - Pointer to attestation authentication state of image. + @return Status of PeiLoadImageLoadImage(). +**/ +EFI_STATUS +EFIAPI +PeiLoadFileLoadPayload ( + IN CONST EFI_PEI_LOAD_FILE_PPI *This, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL, + OUT UINT64 *ImageSizeArg OPTIONAL, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint, + OUT UINT32 *AuthenticationState + ) +{ + EFI_STATUS Status; + FIT_IMAGE_CONTEXT Context; + UINTN Instance; + VOID *Binary; + FIT_RELOCATE_ITEM *RelocateTable; + UNIVERSAL_PAYLOAD_BASE *PayloadBase; + UINTN Length; + UINTN Delta; + UINTN Index; + + Instance = 0; + do { + Status = PeiServicesFfsFindSectionData3 (EFI_SECTION_RAW, Instance++, FileHandle, &Binary, AuthenticationState); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (&Context, sizeof (Context)); + Status = ParseFitImage (Binary, &Context); + } while (EFI_ERROR (Status)); + + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + DEBUG (( + DEBUG_INFO, + "Before Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n", + Context.PayloadBaseAddress, + Context.PayloadSize, + Context.PayloadEntryPoint + )); + Context.PayloadBaseAddress = (EFI_PHYSICAL_ADDRESS)AllocatePages (EFI_SIZE_TO_PAGES (Context.PayloadSize)); + + RelocateTable = (FIT_RELOCATE_ITEM *)(UINTN)(Context.PayloadBaseAddress + Context.RelocateTableOffset); + CopyMem ((VOID *)Context.PayloadBaseAddress, Binary, Context.PayloadSize); + + if (Context.PayloadBaseAddress > Context.PayloadLoadAddress) { + Delta = Context.PayloadBaseAddress - Context.PayloadLoadAddress; + Context.PayloadEntryPoint += Delta; + for (Index = 0; Index < Context.RelocateTableCount; Index++) { + if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) { + *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) + Delta; + } + } + } else { + Delta = Context.PayloadLoadAddress - Context.PayloadBaseAddress; + Context.PayloadEntryPoint -= Delta; + for (Index = 0; Index < Context.RelocateTableCount; Index++) { + if ((RelocateTable[Index].RelocateType == 10) || (RelocateTable[Index].RelocateType == 3)) { + *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) = *((UINT64 *)(Context.PayloadBaseAddress + RelocateTable[Index].Offset)) - Delta; + } + } + } + + DEBUG (( + DEBUG_INFO, + "After Rebase Payload File Base: 0x%08x, File Size: 0x%08X, EntryPoint: 0x%08x\n", + Context.PayloadBaseAddress, + Context.PayloadSize, + Context.PayloadEntryPoint + )); + + Length = sizeof (UNIVERSAL_PAYLOAD_BASE); + PayloadBase = BuildGuidHob ( + &gUniversalPayloadBaseGuid, + Length + ); + PayloadBase->Entry = (EFI_PHYSICAL_ADDRESS)Context.ImageBase; + + *ImageAddressArg = Context.PayloadBaseAddress; + *ImageSizeArg = Context.PayloadSize; + *EntryPoint = Context.PayloadEntryPoint; + + return EFI_SUCCESS; +} + +EFI_PEI_LOAD_FILE_PPI mPeiLoadFilePpi = { + PeiLoadFileLoadPayload +}; + +EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiLoadFilePpiGuid, + &mPeiLoadFilePpi +}; + +/** + Install Pei Load File PPI. + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + @retval EFI_SUCESS The entry point executes successfully. + @retval Others Some error occurs during the execution of this function. +**/ +EFI_STATUS +EFIAPI +InitializeFitPayloadLoaderPeim ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + + Status = PeiServicesInstallPpi (&gPpiLoadFilePpiList); + + return Status; +} diff --git a/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf new file mode 100644 index 0000000000..acb0e09f68 --- /dev/null +++ b/UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf @@ -0,0 +1,59 @@ +## @file +# Produce LoadFile PPI for payload loading. +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FitPayloadLoaderPeim + FILE_GUID = 55AC82C8-FC17-4C56-BCDA-990BB0A73E41 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializeFitPayloadLoaderPeim + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + FitPayloadLoaderPeim.c + FitLib.h + FitLib/FitLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + PcAtChipsetPkg/PcAtChipsetPkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + PcdLib + MemoryAllocationLib + BaseMemoryLib + PeiServicesLib + HobLib + BaseLib + PeimEntryPoint + DebugLib + FdtLib + +[Ppis] + gEfiPeiLoadFilePpiGuid ## PRODUCES + +[Pcd] + gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister + gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister + +[Guids] + gUniversalPayloadExtraDataGuid ## PRODUCES + gUniversalPayloadBaseGuid ## PRODUCES + +[Depex] + TRUE diff --git a/UefiPayloadPkg/Readme.md b/UefiPayloadPkg/Readme.md new file mode 100644 index 0000000000..616a5dd467 --- /dev/null +++ b/UefiPayloadPkg/Readme.md @@ -0,0 +1,191 @@ +# UefiPayloadPkg +Provide UEFI Universal Payload for different bootloader to generate EFI environment + +# Spec + +UniversalPayload URL: https://universalscalablefirmware.github.io/documentation/2_universal_payload.html + +ELF Format URL: https://refspecs.linuxfoundation.org/elf/elf.pdf + +FIT Format URL: https://universalpayload.github.io/spec/chapter2-payload-image-format.html + +# Uefi UniversalPayload Format + | Binary Format | HandOffPayload - HOB | + |---------------|----------------------| + | ELF | V (Default) | + | FIT | V | + +# Binary Format + - ELF + ``` + + +-----------------------+ + | | UniversalPayloadEntry | <----------- UefiPayloadPkg\UefiPayloadEntry\UniversalPayloadEntry.c:_ModuleEntryPoint (HOB) + | +-----------------------+ + | | .upld_info | patch it directly + ELF Format | +-----------------------+ + | | .upld.uefi_fv | patch it directly + | +-----------------------+ + | | .upld.bds_fv | patch it directly + | +-----------------------+ + | | .upld.<afpx>_fv | patch it directly + + +-----------------------+ + ``` + + - FIT + ``` + + +-----------------------+ + FIT Data | | FIT Header | <----------- Generate by pylibfdt + + +-----------------------+ + PECOFF Format | | UniversalPayloadEntry | <----------- UefiPayloadPkg\UefiPayloadEntry\FitUniversalPayloadEntry.c:_ModuleEntryPoint (HOB) + + +-----------------------+ + Relocate Data | | reloc-start | + + +-----------------------+ + | | uefi_fv | patch it directly + | +-----------------------+ + Multi Binary | | bds_fv | patch it directly + | +-----------------------+ + | | afp_xxx_fv | patch it directly + | +-----------------------+ + | | afp_xxx_fv | patch it directly + + +-----------------------+ + ``` + +# Environment + - ELF + ``` + Download and install https://github.com/llvm/llvm-project/releases/tag/llvmorg-10.0.1 + ``` + - FIT + - Windows + ```powershell + Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) + choco install dtc-msys2 + pip3 install pefile + pip3 install swig + pip3 install pylibfdt + ``` + - Ubuntu + ```bash + sudo apt install -y u-boot-tools + pip3 install pefile + pip3 install swig + pip3 install pylibfdt + ``` +# How to build UEFI UniversalPayload + - Windows + - edksetup Rebuild + - Linux + - make -C BaseTools + - source edksetup.sh + + - UniversalPayload.elf + - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG> + - llvm-objdump -h Build/UefiPayloadPkgX64/UniversalPayload.elf + + - UniversalPayload.fit + - python UefiPayloadPkg/UniversalPayloadBuild.py -t <TOOL_CHAIN_TAG> --Fit + - fdtdump Build/UefiPayloadPkgX64/UniversalPayload.fit + +# Edk2boot + UefiUniversalPayload +ELF Edk2boot use below way to support compress and sign. + +- ELF Behavior - Edk2boot + UefiUniversalPayload.elf + ``` + Boot Flow + +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+ + | Platform Init | Universal Loader Interface | OS | + +-------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+-------------------+ + HOBs + SEC -> PEI -> DXE -> DXE IPL -> UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c ------------------------------------------------------------------------------------> Load UniversalPayload.elf -> Operation System + + + | Platform Initialize - Edk2 | UniversalPayload - Edk2 | + +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+ + + Binary Format + + +-------------------+ + | BIOS.rom | + +-------------------+ + | Other Firmware | + +-------------------+ + | ... | FMMT UniversalPayloadBuild.py + +-------------------+<----------------+-----------------------+ GenFfs +-----------------------+ Rsa2048Sha256 Sign +-----------------------+ LzmaCompress +----------------------+ GenSec +--------------------------------+ + | | | EDK2 FFS Header |<-----------| Rsa2048Sha256 Hash |<--------------------| UniversalPayload.lzma |<--------------| EDK2 SEC Header |<--------| UniversalPayload.elf | + | RAW Data | +-----------------------+ +-----------------------+ +-----------------------+ +----------------------+ +--------------------------------+ + | | | Rsa2048Sha256 Hash | | UniversalPayload.lzma | | UniversalPayload.elf | | upld_info | + | | +-----------------------+ +-----------------------+ +----------------------+ +--------------------------------+ + | | | UniversalPayload.lzma | | upld_info | | upld.uefi_fv | + +-------------------+<----------------+-----------------------+ +----------------------+ +--------------------------------+ + | ... | | upld.uefi_fv | | upld.bds_fv | + +-------------------+ +----------------------+ +--------------------------------+ + | Other Firmware | | upld.bds_fv | | upld.AFP1 | + +-------------------+ +----------------------+ +--------------------------------+ + | upld.AFP1 | | upld.AFP2 | + +----------------------+ +--------------------------------+ + | upld.AFP2 | | ... | + +----------------------+ +--------------------------------+ + | ... | | upld.AFPn | + +----------------------+ +--------------------------------+ + | upld.AFPn | + +----------------------+ + ``` + +FIT Edk2boot use below way to support compress and sign +- FIT Behavior - Edk2boot + UefiUniversalPayload.fit + ``` + Boot Flow + +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+ + | Platform Init | Universal Loader Interface | OS | + +-------------------------------------------------------------------------------------+------------------------------------------------------------------------+-------------------+ + HOBs + SEC -> PEI -> DXE -> DXE IPL -> *UefiPayloadPkg\PayloadLoaderPeim\PayloadLoaderPeim.c ----------------------------------------------> Load UniversalPayload.fit -> Operation System + + Binary Format + + | Platform Initialize - Edk2 | UniversalPayload - Edk2 (UniversalPayloadBuild.py --Fit) | + +---------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+ + + +-------------------+ + | BIOS.rom | + +-------------------+ + | Other Firmware | + +-------------------+ + | ... | FMMT UniversalPayloadBuild.py --Fit tianocore -> data-offset + +-------------------+<----------------+--------------------------------+ GenFfs +--------------------------------+ GenSec +--------------------------------+ tianocore -> reloc-start +--------------------------+ + | | | EDK2 FFS Header |<--------| EDK2 SEC Header |<--------| FIT Header |<-------------------------| UniversalPayload.pecoff | + | | +--------------------------------+ +--------------------------------+ | description = "Uefi Payload"; | +--------------------------+ + | | | EDK2 SEC Header | | FIT Header | | ... | + | RAW Data | +--------------------------------+ | | | images { | uefi-fv -> data-offset +--------------------------+ + | | | FIT Header | | | | tianocore {...}; |<-------------------------| uefi_fv | + | | | | +--------------------------------+ | uefi-fv {...}; | bds-fv -> data-offset +--------------------------+ + | | | | | tianocore -> data | | bds-fv {...}; |<-------------------------| bds_fv | + | | +--------------------------------+ +--------------------------------+ | afp1-fv {...}; | AFP1 -> data-offset +--------------------------+ + | | | tianocore -> data | | tianocore -> reloc-start | | ... |<-------------------------| AFP1 | + | | +--------------------------------+ +--------------------------------+ | afpn-fv {...}; | AFP2 -> data-offset +--------------------------+ + | | | tianocore -> reloc-start | | uefi-fv -> data | | } |<-------------------------| AFP2 | + | | +--------------------------------+ +--------------------------------+ | configurations { | ... +--------------------------+ + | | | uefi-fv -> data | | bds-fv -> data | | conf-1 {...} |<-------------------------| ... | + | | +--------------------------------+ +--------------------------------+ | } | AFPn -> data-offset +--------------------------+ + | | | bds-fv -> data | | AFP1-fv -> data | | |<-------------------------| AFPn | + | | +--------------------------------+ +--------------------------------+ | | +--------------------------+ + | | | AFP1-fv -> data | | AFP2-fv -> data | | | + | | +--------------------------------+ +--------------------------------+ +--------------------------------+ + | | | AFP2-fv -> data | | ... | | tianocore -> data | + | | +--------------------------------+ +--------------------------------+ +--------------------------------+ + | | | ... | | AFPn-fv -> data | | tianocore -> reloc-start | + | | +--------------------------------+ +--------------------------------+ +--------------------------------+ + | | | AFPn-fv -> data | | uefi-fv -> data | + +-------------------+<----------------+--------------------------------+ +--------------------------------+ + | ... | | bds-fv -> data | + +-------------------+ +--------------------------------+ + | Other Firmware | | AFP1-fv -> data | + +-------------------+ +--------------------------------+ + | AFP2-fv -> data | + +--------------------------------+ + | ... | + +--------------------------------+ + | AFPn-fv -> data | + +--------------------------------+ + + ``` diff --git a/UefiPayloadPkg/Tools/MkFitImage.py b/UefiPayloadPkg/Tools/MkFitImage.py new file mode 100644 index 0000000000..82ab933d6d --- /dev/null +++ b/UefiPayloadPkg/Tools/MkFitImage.py @@ -0,0 +1,272 @@ +## @file +# This file is a script to build fit image. +# It generate a dtb header and combine a binary file after this header. +# +# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +from os.path import exists +import libfdt +from ctypes import * +import time + +class FIT_IMAGE_INFO_HEADER: + """Class for user setting data to use MakeFitImage() + """ + _pack_ = 1 + _fields_ = [ + ('Compatible', str), + ('UplVersion', int), + ('Description', str), + ('Type', str), + ('Arch', str), + ('Compression', str), + ('Revision', int), + ('BuildType', str), + ('Capabilities', str), + ('Producer', str), + ('ImageId', str), + ('DataOffset', int), + ('DataSize', int), + ('RelocStart', int), + ('LoadAddr', int), + ('Entry', int), + ('Binary', str), + ('TargetPath', str), + ('UefifvPath', str), + ('BdsfvPath', str), + ('NetworkfvPath', str), + ('Project', str), + ] + + def __init__(self): + self.Compatible = 'universal-payload' + self.UplVersion = 0x0100 + self.TargetPath = 'mkimage.fit' + +def CreatFdt(Fdt): + FdtEmptyTree = libfdt.fdt_create_empty_tree(Fdt, len(Fdt)) + if FdtEmptyTree != 0: + print('\n- Failed - Create Fdt failed!') + return False + return True + +def BuildConfNode(Fdt, ParentNode, MultiImage): + ConfNode1 = libfdt.fdt_add_subnode(Fdt, ParentNode, 'conf-1') + + libfdt.fdt_setprop(Fdt, ConfNode1, 'require-fit', b'', 0) + libfdt.fdt_setprop(Fdt, ConfNode1, 'firmware', bytes('tianocore', 'utf-8'), len('tianocore') + 1) + +def BuildFvImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize, Description): + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize) + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset) + libfdt.fdt_setprop(Fdt, ParentNode, 'compression', bytes('none', 'utf-8'), len('none') + 1) + libfdt.fdt_setprop(Fdt, ParentNode, 'project ', bytes('tianocore', 'utf-8'), len('tianocore') + 1) + libfdt.fdt_setprop(Fdt, ParentNode, 'arch', bytes('x86_64', 'utf-8'), len('x86_64') + 1) + libfdt.fdt_setprop(Fdt, ParentNode, 'type', bytes('flat-binary', 'utf-8'), len('flat-binary') + 1) + libfdt.fdt_setprop(Fdt, ParentNode, 'description', bytes(Description, 'utf-8'), len(Description) + 1) + +def BuildTianoImageNode(Fdt, InfoHeader, ParentNode, DataOffset, DataSize, Description): + # + # Set 'load' and 'data-offset' to reserve the memory first. + # They would be set again when Fdt completes or this function parses target binary file. + # + if InfoHeader.LoadAddr is not None: + libfdt.fdt_setprop_u64(Fdt, ParentNode, 'load', InfoHeader.LoadAddr) + if InfoHeader.Entry is not None: + libfdt.fdt_setprop_u64(Fdt, ParentNode, 'entry-start', InfoHeader.Entry) + if InfoHeader.RelocStart is not None: + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'reloc-start', InfoHeader.RelocStart) + if InfoHeader.DataSize is not None: + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-size', DataSize) + if InfoHeader.DataOffset is not None: + libfdt.fdt_setprop_u32(Fdt, ParentNode, 'data-offset', DataOffset) + if InfoHeader.Producer is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'producer ', bytes(InfoHeader.Producer, 'utf-8'), len(InfoHeader.Producer) + 1) + if InfoHeader.Capabilities is not None: + CapStrs = ','.join(InfoHeader.Capabilities) + libfdt.fdt_setprop(Fdt, ParentNode, 'capabilities ', bytes(CapStrs, 'utf-8'), len(CapStrs) + 1) + if InfoHeader.Type is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'type ', bytes(InfoHeader.Type, 'utf-8'), len(InfoHeader.Type) + 1) + if InfoHeader.Arch is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'arch ', bytes(InfoHeader.Arch, 'utf-8'), len(InfoHeader.Arch) + 1) + if InfoHeader.Project is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'project ', bytes(InfoHeader.Project, 'utf-8'), len(InfoHeader.Project) + 1) + if InfoHeader.Description is not None: + libfdt.fdt_setprop(Fdt, ParentNode, 'description', bytes(Description, 'utf-8'), len(Description) + 1) + +# +# The subnode would be inserted from bottom to top of structure block. +# +def BuildFitImage(Fdt, InfoHeader): + MultiImage = [ + ["tianocore", InfoHeader.Binary, BuildTianoImageNode , InfoHeader.Description, None, 0 ], + ["uefi-fv", InfoHeader.UefifvPath, BuildFvImageNode, "UEFI Firmware Volume", None, 0 ], + ["bds-fv", InfoHeader.BdsfvPath, BuildFvImageNode , "BDS Firmware Volume", None, 0 ], + ["network-fv", InfoHeader.NetworkfvPath, BuildFvImageNode , "Network Firmware Volume", None, 0 ], + ] + + # + # Set basic information + # + libfdt.fdt_setprop_u32(Fdt, 0, 'build-revision ', InfoHeader.Revision) + libfdt.fdt_setprop_u32(Fdt, 0, 'spec-version', InfoHeader.UplVersion) + + # + # Build configurations node + # + ConfNode = libfdt.fdt_add_subnode(Fdt, 0, 'configurations') + BuildConfNode(Fdt, ConfNode, MultiImage) + + # Build image + DataOffset = InfoHeader.DataOffset + for Index in range (0, len (MultiImage)): + _, Path, _, _, _, _ = MultiImage[Index] + if exists(Path) == 1: + TempBinary = open(Path, 'rb') + BinaryData = TempBinary.read() + TempBinary.close() + MultiImage[Index][-2] = BinaryData + MultiImage[Index][-1] = DataOffset + DataOffset += len (BinaryData) + libfdt.fdt_setprop_u32(Fdt, 0, 'size', DataOffset) + posix_time = int(time.time()) + libfdt.fdt_setprop_u32(Fdt, 0, 'timestamp', posix_time) + DescriptionFit = 'Uefi OS Loader' + libfdt.fdt_setprop(Fdt, 0, 'description', bytes(DescriptionFit, 'utf-8'), len(DescriptionFit) + 1) + + ImageNode = libfdt.fdt_add_subnode(Fdt, 0, 'images') + for Item in reversed (MultiImage): + Name, Path, BuildFvNode, Description, BinaryData, DataOffset = Item + FvNode = libfdt.fdt_add_subnode(Fdt, ImageNode, Name) + BuildFvNode (Fdt, InfoHeader, FvNode, DataOffset, len(BinaryData), Description) + + # + # Create new image file and combine all binary. + # + DtbFile = open(InfoHeader.TargetPath, "wb") + DtbFile.truncate() + DtbFile.write(Fdt) + for Item in MultiImage: + _, _, _, _, BinaryData, _ = Item + DtbFile.write(BinaryData) + DtbFile.close() + + return True + +def MakeFitImage(InfoHeader): + # + # Allocate fdt byte array. + # + Fdt = bytearray(InfoHeader.DataOffset) + + # + # Create fdt empty tree. + # + if CreatFdt(Fdt) is False: + return False + + # + # Parse args to build fit image. + # + return BuildFitImage(Fdt, InfoHeader) + +def ReplaceFv (UplBinary, SectionFvFile, SectionName): + try: + # + # Get Original Multi Fv + # + with open (UplBinary, "rb") as File: + Dtb = File.read () + Fit = libfdt.Fdt (Dtb) + NewFitHeader = bytearray(Dtb[0:Fit.totalsize()]) + FitSize = len(Dtb) + + LoadablesList = [] + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images') + FvNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, 'uefi-fv') + NodeDepth = libfdt.fdt_node_depth (NewFitHeader, ImagesNode) + node_name = libfdt.fdt_get_name(NewFitHeader, FvNode) + FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode, NodeDepth) + + while node_name[0][-2:] == 'fv': + LoadablesList.append (node_name[0]) + node_name = libfdt.fdt_get_name(NewFitHeader, FvNode[0]) + FvNode = libfdt.fdt_next_node(NewFitHeader, FvNode[0], NodeDepth) + # + # Get current Fit Binary FV data + # + MultiFvList = [] + for Item in LoadablesList: + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, Item) + ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big') + ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big') + MultiFvList.append ([Item, Dtb[ImageOffset:ImageOffset + ImageSize]]) + + IsFvExist = False + for Index in range (0, len (MultiFvList)): + if MultiFvList[Index][0] == SectionName: + with open (SectionFvFile, 'rb') as File: + MultiFvList[Index][1] = File.read () + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, SectionName) + ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big') + ReplaceOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big') + OffsetDelta = len(MultiFvList[Index][1]) - ImageSize + FitSize += OffsetDelta + IsFvExist = True + libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, 'data-size', len(MultiFvList[Index][1])) + + # + # Update new fit header + # + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images') + if (IsFvExist == False): + with open (SectionFvFile, 'rb') as File: + SectionFvFileBinary = File.read () + MultiFvList.append ([SectionName, SectionFvFileBinary]) + FvNode = libfdt.fdt_add_subnode(NewFitHeader, ImagesNode, SectionName) + BuildFvImageNode (NewFitHeader, None, FvNode, FitSize, len(SectionFvFileBinary), SectionName + " Firmware Volume") + FitSize += len(SectionFvFileBinary) + else: + for Index in range (0, len (MultiFvList)): + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, MultiFvList[Index][0]) + ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big') + if ImageOffset > ReplaceOffset: + libfdt.fdt_setprop_u32(NewFitHeader, ImageNode, 'data-offset', ImageOffset + OffsetDelta) + + ConfNodes = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'configurations') + libfdt.fdt_setprop(NewFitHeader, ConfNodes, 'default ', bytes('conf-1', 'utf-8'), len('conf-1') + 1) + ConfNode = libfdt.fdt_subnode_offset(NewFitHeader, ConfNodes, 'conf-1') + + libfdt.fdt_setprop_u32(NewFitHeader, 0, 'size', FitSize) + + # + # Generate new fit image + # + ImagesNode = libfdt.fdt_subnode_offset(NewFitHeader, 0, 'images') + TianoNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, 'tianocore') + TianoOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, TianoNode, 'data-offset')[0], 'big') + TianoSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, TianoNode, 'data-size')[0], 'big') + TianoBinary = Dtb[TianoOffset:TianoOffset + TianoSize] + + print("\nGenerate new fit image:") + NewUplBinary = bytearray(FitSize) + print("Update fit header\t to 0x0\t\t ~ " + str(hex(len(NewFitHeader)))) + NewUplBinary[:len(NewFitHeader)] = NewFitHeader + print("Update tiano image\t to " + str(hex(len(NewFitHeader))) + "\t ~ " + str(hex(len(NewFitHeader) + len(TianoBinary)))) + NewUplBinary[len(NewFitHeader):len(NewFitHeader) + len(TianoBinary)] = TianoBinary + for Index in range (0, len (MultiFvList)): + ImageNode = libfdt.fdt_subnode_offset(NewFitHeader, ImagesNode, MultiFvList[Index][0]) + ImageOffset = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-offset')[0], 'big') + ImageSize = int.from_bytes (libfdt.fdt_getprop (NewFitHeader, ImageNode, 'data-size')[0], 'big') + NewUplBinary[ImageOffset:ImageOffset + ImageSize] = MultiFvList[Index][1] + print("Update " + MultiFvList[Index][0] + "\t\t to " + str(hex(ImageOffset)) + "\t ~ " + str(hex(ImageOffset + ImageSize))) + + with open (UplBinary, "wb") as File: + File.write (NewUplBinary) + + return 0 + except Exception as Ex: + print(Ex) + return 1 diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c new file mode 100644 index 0000000000..a53d988627 --- /dev/null +++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c @@ -0,0 +1,654 @@ +/** @file + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include "UefiPayloadEntry.h" +#include <Library/FdtLib.h> +#include <Guid/UniversalPayloadBase.h> + +#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \ + EFI_RESOURCE_ATTRIBUTE_TESTED | \ + EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_PERSISTENT ) + +#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \ + EFI_RESOURCE_ATTRIBUTE_TESTED ) + +extern VOID *mHobList; + +CHAR8 *mLineBuffer = NULL; + +/** + Print all HOBs info from the HOB list. + @return The pointer to the HOB list. +**/ +VOID +PrintHob ( + IN CONST VOID *HobStart + ); + +/** + Find the first substring. + @param String Point to the string where to find the substring. + @param CharSet Point to the string to be found. +**/ +UINTN +EFIAPI +AsciiStrSpn ( + IN CHAR8 *String, + IN CHAR8 *CharSet + ) +{ + UINTN Count; + CHAR8 *Str1; + CHAR8 *Str2; + + Count = 0; + + for (Str1 = String; *Str1 != L'\0'; Str1++) { + for (Str2 = CharSet; *Str2 != L'\0'; Str2++) { + if (*Str1 == *Str2) { + break; + } + } + + if (*Str2 == L'\0') { + return Count; + } + + Count++; + } + + return Count; +} + +/** + Searches a string for the first occurrence of a character contained in a + specified buffer. + @param String Point to the string where to find the substring. + @param CharSet Point to the string to be found. +**/ +CHAR8 * +EFIAPI +AsciiStrBrk ( + IN CHAR8 *String, + IN CHAR8 *CharSet + ) +{ + CHAR8 *Str1; + CHAR8 *Str2; + + for (Str1 = String; *Str1 != L'\0'; Str1++) { + for (Str2 = CharSet; *Str2 != L'\0'; Str2++) { + if (*Str1 == *Str2) { + return (CHAR8 *)Str1; + } + } + } + + return NULL; +} + +/** + Find the next token after one or more specified characters. + @param String Point to the string where to find the substring. + @param CharSet Point to the string to be found. +**/ +CHAR8 * +EFIAPI +AsciiStrTokenLine ( + IN CHAR8 *String OPTIONAL, + IN CHAR8 *CharSet + ) +{ + CHAR8 *Begin; + CHAR8 *End; + + Begin = (String == NULL) ? mLineBuffer : String; + if (Begin == NULL) { + return NULL; + } + + Begin += AsciiStrSpn (Begin, CharSet); + if (*Begin == L'\0') { + mLineBuffer = NULL; + return NULL; + } + + End = AsciiStrBrk (Begin, CharSet); + if ((End != NULL) && (*End != L'\0')) { + *End = L'\0'; + End++; + } + + mLineBuffer = End; + return Begin; +} + +/** + Some bootloader may pass a pcd database, and UPL also contain a PCD database. + Dxe PCD driver has the assumption that the two PCD database can be catenated and + the local token number should be successive. + This function will fix up the UPL PCD database to meet that assumption. + @param[in] DxeFv The FV where to find the Universal PCD database. + @retval EFI_SUCCESS If it completed successfully. + @retval other Failed to fix up. +**/ +EFI_STATUS +FixUpPcdDatabase ( + IN EFI_FIRMWARE_VOLUME_HEADER *DxeFv + ) +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER *FileHeader; + VOID *PcdRawData; + PEI_PCD_DATABASE *PeiDatabase; + PEI_PCD_DATABASE *UplDatabase; + EFI_HOB_GUID_TYPE *GuidHob; + DYNAMICEX_MAPPING *ExMapTable; + UINTN Index; + + GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); + if (GuidHob == NULL) { + // + // No fix-up is needed. + // + return EFI_SUCCESS; + } + + PeiDatabase = (PEI_PCD_DATABASE *)GET_GUID_HOB_DATA (GuidHob); + DEBUG ((DEBUG_INFO, "Find the Pei PCD data base, the total local token number is %d\n", PeiDatabase->LocalTokenCount)); + + Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DRIVER, PcdGetPtr (PcdPcdDriverFile), &FileHeader); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + UplDatabase = (PEI_PCD_DATABASE *)PcdRawData; + ExMapTable = (DYNAMICEX_MAPPING *)(UINTN)((UINTN)PcdRawData + UplDatabase->ExMapTableOffset); + + for (Index = 0; Index < UplDatabase->ExTokenCount; Index++) { + ExMapTable[Index].TokenNumber += PeiDatabase->LocalTokenCount; + } + + DEBUG ((DEBUG_INFO, "Fix up UPL PCD database successfully\n")); + return EFI_SUCCESS; +} + +/** + Add HOB into HOB list + @param[in] Hob The HOB to be added into the HOB list. +**/ +VOID +AddNewHob ( + IN EFI_PEI_HOB_POINTERS *Hob + ) +{ + EFI_PEI_HOB_POINTERS NewHob; + + if (Hob->Raw == NULL) { + return; + } + + NewHob.Header = CreateHob (Hob->Header->HobType, Hob->Header->HobLength); + + if (NewHob.Header != NULL) { + CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - sizeof (EFI_HOB_GENERIC_HEADER)); + } +} + +/** + Found the Resource Descriptor HOB that contains a range (Base, Top) + @param[in] HobList Hob start address + @param[in] Base Memory start address + @param[in] Top Memory end address. + @retval The pointer to the Resource Descriptor HOB. +**/ +EFI_HOB_RESOURCE_DESCRIPTOR * +FindResourceDescriptorByRange ( + IN VOID *HobList, + IN EFI_PHYSICAL_ADDRESS Base, + IN EFI_PHYSICAL_ADDRESS Top + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + + for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + // + // Skip all HOBs except Resource Descriptor HOBs + // + if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + continue; + } + + // + // Skip Resource Descriptor HOBs that do not describe tested system memory + // + ResourceHob = Hob.ResourceDescriptor; + if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) { + continue; + } + + if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) { + continue; + } + + // + // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop + // + if (Base < ResourceHob->PhysicalStart) { + continue; + } + + if (Top > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) { + continue; + } + + return ResourceHob; + } + + return NULL; +} + +/** + Find the highest below 4G memory resource descriptor, except the input Resource Descriptor. + @param[in] HobList Hob start address + @param[in] MinimalNeededSize Minimal needed size. + @param[in] ExceptResourceHob Ignore this Resource Descriptor. + @retval The pointer to the Resource Descriptor HOB. +**/ +EFI_HOB_RESOURCE_DESCRIPTOR * +FindAnotherHighestBelow4GResourceDescriptor ( + IN VOID *HobList, + IN UINTN MinimalNeededSize, + IN EFI_HOB_RESOURCE_DESCRIPTOR *ExceptResourceHob + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + EFI_HOB_RESOURCE_DESCRIPTOR *ReturnResourceHob; + + ReturnResourceHob = NULL; + + for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { + // + // Skip all HOBs except Resource Descriptor HOBs + // + if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + continue; + } + + // + // Skip Resource Descriptor HOBs that do not describe tested system memory + // + ResourceHob = Hob.ResourceDescriptor; + if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) { + continue; + } + + if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) { + continue; + } + + // + // Skip if the Resource Descriptor HOB equals to ExceptResourceHob + // + if (ResourceHob == ExceptResourceHob) { + continue; + } + + // + // Skip Resource Descriptor HOBs that are beyond 4G + // + if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > BASE_4GB) { + continue; + } + + // + // Skip Resource Descriptor HOBs that are too small + // + if (ResourceHob->ResourceLength < MinimalNeededSize) { + continue; + } + + // + // Return the topest Resource Descriptor + // + if (ReturnResourceHob == NULL) { + ReturnResourceHob = ResourceHob; + } else { + if (ReturnResourceHob->PhysicalStart < ResourceHob->PhysicalStart) { + ReturnResourceHob = ResourceHob; + } + } + } + + return ReturnResourceHob; +} + +/** + Check the HOB and decide if it is need inside Payload + Payload maintainer may make decision which HOB is need or needn't + Then add the check logic in the function. + @param[in] Hob The HOB to check + @retval TRUE If HOB is need inside Payload + @retval FALSE If HOB is needn't inside Payload +**/ +BOOLEAN +IsHobNeed ( + EFI_PEI_HOB_POINTERS Hob + ) +{ + if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) { + return FALSE; + } + + if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) { + if (CompareGuid (&Hob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) { + return FALSE; + } + } + + // Arrive here mean the HOB is need + return TRUE; +} + +/** + It will build Fv HOBs based on information from bootloaders. + @param[out] DxeFv The pointer to the DXE FV in memory. + @retval EFI_SUCCESS If it completed successfully. + @retval EFI_NOT_FOUND If it failed to find node in fit image. + @retval Others If it failed to build required HOBs. +**/ +EFI_STATUS +BuildFitLoadablesFvHob ( + OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv + ) +{ + EFI_STATUS Status; + VOID *Fdt; + UINT8 *GuidHob; + UNIVERSAL_PAYLOAD_BASE *PayloadBase; + INT32 ConfigNode; + INT32 Config1Node; + INT32 ImageNode; + INT32 FvNode; + INT32 Depth; + CONST FDT_PROPERTY *PropertyPtr; + INT32 TempLen; + CONST CHAR8 *Fvname; + UINT32 DataOffset; + UINT32 DataSize; + UINT32 *Data32; + + GuidHob = GetFirstGuidHob (&gUniversalPayloadBaseGuid); + if (GuidHob != NULL) { + PayloadBase = (UNIVERSAL_PAYLOAD_BASE *)GET_GUID_HOB_DATA (GuidHob); + Fdt = (VOID *)(UINTN)PayloadBase->Entry; + DEBUG ((DEBUG_INFO, "PayloadBase Entry = 0x%08x\n", PayloadBase->Entry)); + } + + Status = FdtCheckHeader (Fdt); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations")); + if (ConfigNode <= 0) { + return EFI_NOT_FOUND; + } + + Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1")); + if (Config1Node <= 0) { + return EFI_NOT_FOUND; + } + + ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images")); + if (ImageNode <= 0) { + return EFI_NOT_FOUND; + } + + FvNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, "tianocore", (INT32)AsciiStrLen ("tianocore")); + Depth = FdtNodeDepth (Fdt, FvNode); + FvNode = FdtNextNode (Fdt, FvNode, &Depth); + Fvname = FdtGetName (Fdt, FvNode, &TempLen); + while ((AsciiStrCmp ((Fvname + AsciiStrLen (Fvname) - 2), "fv") == 0)) { + if (FvNode <= 0) { + return EFI_NOT_FOUND; + } + + PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-offset", &TempLen); + Data32 = (UINT32 *)(PropertyPtr->Data); + DataOffset = SwapBytes32 (*Data32); + + PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-size", &TempLen); + Data32 = (UINT32 *)(PropertyPtr->Data); + DataSize = SwapBytes32 (*Data32); + + if (AsciiStrCmp (Fvname, "uefi-fv") == 0) { + *DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)PayloadBase->Entry + (UINTN)DataOffset); + ASSERT ((*DxeFv)->FvLength == DataSize); + } else { + BuildFvHob (((UINTN)PayloadBase->Entry + (UINTN)DataOffset), DataSize); + } + + DEBUG (( + DEBUG_INFO, + "UPL Multiple fv[%a], Base=0x%08x, size=0x%08x\n", + Fvname, + ((UINTN)PayloadBase->Entry + (UINTN)DataOffset), + DataSize, + DataOffset + )); + Depth = FdtNodeDepth (Fdt, FvNode); + FvNode = FdtNextNode (Fdt, FvNode, &Depth); + Fvname = FdtGetName (Fdt, FvNode, &TempLen); + } + + return EFI_SUCCESS; +} + +/** + It will build HOBs based on information from bootloaders. + @param[in] BootloaderParameter The starting memory address of bootloader parameter block. + @param[out] DxeFv The pointer to the DXE FV in memory. + @retval EFI_SUCCESS If it completed successfully. + @retval Others If it failed to build required HOBs. +**/ +EFI_STATUS +BuildHobs ( + IN UINTN BootloaderParameter, + OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv + ) +{ + EFI_PEI_HOB_POINTERS Hob; + UINTN MinimalNeededSize; + EFI_PHYSICAL_ADDRESS FreeMemoryBottom; + EFI_PHYSICAL_ADDRESS FreeMemoryTop; + EFI_PHYSICAL_ADDRESS MemoryBottom; + EFI_PHYSICAL_ADDRESS MemoryTop; + EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + UINT8 *GuidHob; + EFI_HOB_FIRMWARE_VOLUME *FvHob; + UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable; + ACPI_BOARD_INFO *AcpiBoardInfo; + EFI_HOB_HANDOFF_INFO_TABLE *HobInfo; + + Hob.Raw = (UINT8 *)BootloaderParameter; + MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize); + + ASSERT (Hob.Raw != NULL); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop == Hob.HandoffInformationTable->EfiFreeMemoryTop); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryTop == Hob.HandoffInformationTable->EfiMemoryTop); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom == Hob.HandoffInformationTable->EfiFreeMemoryBottom); + ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryBottom == Hob.HandoffInformationTable->EfiMemoryBottom); + + // + // Try to find Resource Descriptor HOB that contains Hob range EfiMemoryBottom..EfiMemoryTop + // + PhitResourceHob = FindResourceDescriptorByRange (Hob.Raw, Hob.HandoffInformationTable->EfiMemoryBottom, Hob.HandoffInformationTable->EfiMemoryTop); + if (PhitResourceHob == NULL) { + // + // Boot loader's Phit Hob is not in an available Resource Descriptor, find another Resource Descriptor for new Phit Hob + // + ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, NULL); + if (ResourceHob == NULL) { + return EFI_NOT_FOUND; + } + + MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize; + FreeMemoryBottom = MemoryBottom; + FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength; + MemoryTop = FreeMemoryTop; + } else if (PhitResourceHob->PhysicalStart + PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop >= MinimalNeededSize) { + // + // New availiable Memory range in new hob is right above memory top in old hob. + // + MemoryBottom = Hob.HandoffInformationTable->EfiFreeMemoryTop; + FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop; + FreeMemoryTop = FreeMemoryBottom + MinimalNeededSize; + MemoryTop = FreeMemoryTop; + } else if (Hob.HandoffInformationTable->EfiMemoryBottom - PhitResourceHob->PhysicalStart >= MinimalNeededSize) { + // + // New availiable Memory range in new hob is right below memory bottom in old hob. + // + MemoryBottom = Hob.HandoffInformationTable->EfiMemoryBottom - MinimalNeededSize; + FreeMemoryBottom = MemoryBottom; + FreeMemoryTop = Hob.HandoffInformationTable->EfiMemoryBottom; + MemoryTop = Hob.HandoffInformationTable->EfiMemoryTop; + } else { + // + // In the Resource Descriptor HOB contains boot loader Hob, there is no enough free memory size for payload hob + // Find another Resource Descriptor Hob + // + ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, PhitResourceHob); + if (ResourceHob == NULL) { + return EFI_NOT_FOUND; + } + + MemoryBottom = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize; + FreeMemoryBottom = MemoryBottom; + FreeMemoryTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength; + MemoryTop = FreeMemoryTop; + } + + HobInfo = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID *)(UINTN)FreeMemoryTop); + HobInfo->BootMode = Hob.HandoffInformationTable->BootMode; + // + // From now on, mHobList will point to the new Hob range. + // + + // + // Create an empty FvHob for the DXE FV that contains DXE core. + // + BuildFvHob ((EFI_PHYSICAL_ADDRESS)0, 0); + // + // Since payload created new Hob, move all hobs except PHIT from boot loader hob list. + // + while (!END_OF_HOB_LIST (Hob)) { + if (IsHobNeed (Hob)) { + // Add this hob to payload HOB + AddNewHob (&Hob); + } + + Hob.Raw = GET_NEXT_HOB (Hob); + } + + BuildFitLoadablesFvHob (DxeFv); + + // + // Create guid hob for acpi board information + // + GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid); + if (GuidHob != NULL) { + AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA (GuidHob); + GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid); + if (GuidHob == NULL) { + AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp); + ASSERT (AcpiBoardInfo != NULL); + } + } + + // + // Update DXE FV information to first fv hob in the hob list, which + // is the empty FvHob created before. + // + FvHob = GetFirstHob (EFI_HOB_TYPE_FV); + FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)*DxeFv; + FvHob->Length = (*DxeFv)->FvLength; + return EFI_SUCCESS; +} + +/** + Entry point to the C language phase of UEFI payload. + @param[in] BootloaderParameter The starting address of bootloader parameter block. + @retval It will not return if SUCCESS, and return error when passing bootloader parameter. +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN UINTN BootloaderParameter + ) +{ + EFI_STATUS Status; + PHYSICAL_ADDRESS DxeCoreEntryPoint; + EFI_PEI_HOB_POINTERS Hob; + EFI_FIRMWARE_VOLUME_HEADER *DxeFv; + + mHobList = (VOID *)BootloaderParameter; + DxeFv = NULL; + // Call constructor for all libraries + ProcessLibraryConstructorList (); + + DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n")); + DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN))); + + DEBUG_CODE ( + // + // Dump the Hobs from boot loader + // + PrintHob (mHobList); + ); + + // Initialize floating point operating environment to be compliant with UEFI spec. + InitializeFloatingPointUnits (); + + // Build HOB based on information from Bootloader + Status = BuildHobs (BootloaderParameter, &DxeFv); + ASSERT_EFI_ERROR (Status); + + FixUpPcdDatabase (DxeFv); + Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint); + ASSERT_EFI_ERROR (Status); + + // + // Mask off all legacy 8259 interrupt sources + // + IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF); + IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF); + + Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob (EFI_HOB_TYPE_HANDOFF); + HandOffToDxeCore (DxeCoreEntryPoint, Hob); + + // Should not get here + CpuDeadLoop (); + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf new file mode 100644 index 0000000000..a7d1a8c9e5 --- /dev/null +++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf @@ -0,0 +1,98 @@ +## @file +# This is the first module for UEFI payload. +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FitUniversalPayloadEntry + FILE_GUID = CED5A8A9-B6EA-4D5A-8689-577EE88566CF + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + FitUniversalPayloadEntry.c + LoadDxeCore.c + MemoryAllocation.c + PrintHob.c + AcpiTable.c + +[Sources.Ia32] + X64/VirtualMemory.h + X64/VirtualMemory.c + Ia32/DxeLoadFunc.c + Ia32/IdtVectorAsm.nasm + +[Sources.X64] + X64/VirtualMemory.h + X64/VirtualMemory.c + X64/DxeLoadFunc.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + UefiPayloadPkg/UefiPayloadPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + BaseLib + SerialPortLib + IoLib + HobLib + PeCoffLib + CpuLib + FdtLib + +[Guids] + gEfiMemoryTypeInformationGuid + gEfiFirmwareFileSystem2Guid + gEfiGraphicsInfoHobGuid + gEfiGraphicsDeviceInfoHobGuid + gUefiAcpiBoardInfoGuid + gEfiSmbiosTableGuid + gUefiSerialPortInfoGuid + gUniversalPayloadExtraDataGuid + gUniversalPayloadBaseGuid + gPcdDataBaseHobGuid + gUniversalPayloadSmbiosTableGuid + gEfiHobMemoryAllocBspStoreGuid + gUniversalPayloadAcpiTableGuid + gUniversalPayloadPciRootBridgeInfoGuid + gUniversalPayloadSmbios3TableGuid + +[FeaturePcd.IA32] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES + +[FeaturePcd.X64] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ## CONSUMES + + +[Pcd.IA32,Pcd.X64] + gUefiPayloadPkgTokenSpaceGuid.PcdPcdDriverFile + gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ## CONSUMES + + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase + gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize + gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize + + gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## SOMETIMES_CONSUMES diff --git a/UefiPayloadPkg/UefiPayloadPkg.dec b/UefiPayloadPkg/UefiPayloadPkg.dec index e2e4a79db3..2f1fd82487 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dec +++ b/UefiPayloadPkg/UefiPayloadPkg.dec @@ -24,6 +24,9 @@ # gUefiPayloadPkgTokenSpaceGuid = {0x1d127ea, 0xf6f1, 0x4ef6, {0x94, 0x15, 0x8a, 0x0, 0x0, 0x93, 0xf8, 0x9d}} + ## Include/Guid/UniversalPayloadBase.h + gUniversalPayloadBaseGuid = { 0x03d4c61d, 0x2713, 0x4ec5, {0xa1, 0xcc, 0x88, 0x3b, 0xe9, 0xdc, 0x18, 0xe5 } } + # # Gop Temp # diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc index 47812048dd..af9308ef8e 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dsc +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -30,7 +30,6 @@ DEFINE PS2_KEYBOARD_ENABLE = FALSE DEFINE RAM_DISK_ENABLE = FALSE DEFINE SIO_BUS_ENABLE = FALSE - DEFINE UNIVERSAL_PAYLOAD = FALSE DEFINE SECURITY_STUB_ENABLE = TRUE DEFINE SMM_SUPPORT = FALSE DEFINE PLATFORM_BOOT_TIMEOUT = 3 @@ -44,6 +43,14 @@ DEFINE BOOTSPLASH_IMAGE = FALSE DEFINE NVME_ENABLE = TRUE DEFINE CAPSULE_SUPPORT = FALSE + # + # Setup Universal Payload + # + # ELF: Build UniversalPayload file as UniversalPayload.elf + # FIT: Build UniversalPayload file as UniversalPayload.fit + # + DEFINE UNIVERSAL_PAYLOAD = FALSE + DEFINE UNIVERSAL_PAYLOAD_FORMAT = ELF # # NULL: NullMemoryTestDxe @@ -311,7 +318,7 @@ VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf - + FdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf [LibraryClasses.common] !if $(BOOTSPLASH_IMAGE) SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf @@ -600,14 +607,26 @@ !if "IA32" in "$(ARCH)" [Components.IA32] !if $(UNIVERSAL_PAYLOAD) == TRUE - UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf + !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF" + UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf + !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT" + UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf + !else + UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf + !endif !else UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf !endif !else [Components.X64] !if $(UNIVERSAL_PAYLOAD) == TRUE - UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf + !if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF" + UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf + !elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT" + UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf + !else + UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf + !endif !else UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf !endif diff --git a/UefiPayloadPkg/UniversalPayloadBuild.py b/UefiPayloadPkg/UniversalPayloadBuild.py index 47f37b3377..9a83fc9e44 100644 --- a/UefiPayloadPkg/UniversalPayloadBuild.py +++ b/UefiPayloadPkg/UniversalPayloadBuild.py @@ -10,10 +10,22 @@ import subprocess import os import shutil import sys +import pathlib from ctypes import * -from Tools.ElfFv import ReplaceFv + sys.dont_write_bytecode = True +class bcolors: + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKCYAN = '\033[96m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + class UPLD_INFO_HEADER(LittleEndianStructure): _pack_ = 1 _fields_ = [ @@ -36,40 +48,114 @@ class UPLD_INFO_HEADER(LittleEndianStructure): self.ImageId = b'UEFI' self.ProducerId = b'INTEL' -def BuildUniversalPayload(Args): - def RunCommand(cmd): - print(cmd) - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE']) - while True: - line = p.stdout.readline() - if not line: - break - print(line.strip().decode(errors='ignore')) - - p.communicate() - if p.returncode != 0: - print("- Failed - error happened when run command: %s"%cmd) - raise Exception("ERROR: when run command: %s"%cmd) +def ValidateSpecRevision (Argument): + try: + (MajorStr, MinorStr) = Argument.split('.') + except: + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + # + # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version. + # + if len(MinorStr) > 0 and len(MinorStr) < 3: + try: + Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4) + except: + raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument)) + else: + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + + if len(MajorStr) > 0 and len(MajorStr) < 3: + try: + Major = int(MajorStr, 16) + except: + raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument)) + else: + raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + + return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0) + +def Validate32BitInteger (Argument): + try: + Value = int (Argument, 0) + except: + raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument)) + if Value < 0: + raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument)) + if Value > 0xffffffff: + raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument)) + return Value +def ValidateAddFv (Argument): + Value = Argument.split ("=") + if len (Value) != 2: + raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) + if Value[0][-3:] != "_fv": + raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) + if Value[1][-3:].lower () != ".fv": + raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) + if os.path.exists (Value[1]) == False: + raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1])) + return Value + +def RunCommand(cmd): + print(cmd) + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,cwd=os.environ['WORKSPACE']) + while True: + line = p.stdout.readline() + if not line: + break + print(line.strip().decode(errors='ignore')) + + p.communicate() + if p.returncode != 0: + print("- Failed - error happened when run command: %s"%cmd) + raise Exception("ERROR: when run command: %s"%cmd) + +def BuildUniversalPayload(Args): BuildTarget = Args.Target ToolChain = Args.ToolChain Quiet = "--quiet" if Args.Quiet else "" - ElfToolChain = 'CLANGDWARF' - BuildDir = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64")) - BuildModule = "" - BuildArch = "" + if Args.Fit == True: + PayloadEntryToolChain = ToolChain + Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=FIT") + UpldEntryFile = "FitUniversalPayloadEntry" + else: + PayloadEntryToolChain = 'CLANGDWARF' + Args.Macro.append("UNIVERSAL_PAYLOAD_FORMAT=ELF") + UpldEntryFile = "UniversalPayloadEntry" + + BuildDir = os.path.join(os.environ['WORKSPACE'], os.path.normpath("Build/UefiPayloadPkgX64")) if Args.Arch == 'X64': BuildArch = "X64" - EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll")) + FitArch = "x86_64" + ObjCopyFlag = "elf64-x86-64" + EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile))) else: BuildArch = "IA32 -a X64" - EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll")) + FitArch = "x86" + ObjCopyFlag = "elf32-i386" + EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (UpldEntryFile, UpldEntryFile))) + EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/{}.inf".format (UpldEntryFile)) DscPath = os.path.normpath("UefiPayloadPkg/UefiPayloadPkg.dsc") + DxeFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) + BdsFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) + NetworkFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv")) + PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt") ModuleReportPath = os.path.join(BuildDir, "UefiUniversalPayloadEntry.txt") UpldInfoFile = os.path.join(BuildDir, "UniversalPayloadInfo.bin") + if "CLANG_BIN" in os.environ: + LlvmObjcopyPath = os.path.join(os.environ["CLANG_BIN"], "llvm-objcopy") + else: + LlvmObjcopyPath = "llvm-objcopy" + try: + RunCommand('"%s" --version'%LlvmObjcopyPath) + except: + print("- Failed - Please check if LLVM is installed or if CLANG_BIN is set correctly") + sys.exit(1) + Pcds = "" if (Args.pcd != None): for PcdItem in Args.pcd: @@ -84,7 +170,6 @@ def BuildUniversalPayload(Args): # Building DXE core and DXE drivers as DXEFV. # if Args.BuildEntryOnly == False: - PayloadReportPath = os.path.join(BuildDir, "UefiUniversalPayload.txt") BuildPayload = "build -p {} -b {} -a X64 -t {} -y {} {}".format (DscPath, BuildTarget, ToolChain, PayloadReportPath, Quiet) BuildPayload += Pcds BuildPayload += Defines @@ -93,94 +178,138 @@ def BuildUniversalPayload(Args): # Building Universal Payload entry. # if Args.PreBuildUplBinary is None: - EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf") - BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, ElfToolChain, ModuleReportPath, Quiet) + BuildModule = "build -p {} -b {} -a {} -m {} -t {} -y {} {}".format (DscPath, BuildTarget, BuildArch, EntryModuleInf, PayloadEntryToolChain, ModuleReportPath, Quiet) BuildModule += Pcds BuildModule += Defines RunCommand(BuildModule) if Args.PreBuildUplBinary is not None: - EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf") + if Args.Fit == False: + EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf") + else: + EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.fit") shutil.copy (os.path.abspath(Args.PreBuildUplBinary), EntryOutputDir) # - # Buid Universal Payload Information Section ".upld_info" + # Build Universal Payload Information Section ".upld_info" # - upld_info_hdr = UPLD_INFO_HEADER() - upld_info_hdr.SpecRevision = Args.SpecRevision - upld_info_hdr.Revision = Args.Revision - upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16] - upld_info_hdr.ImageId = Args.ImageId.encode()[:16] - upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0 - fp = open(UpldInfoFile, 'wb') - fp.write(bytearray(upld_info_hdr)) - fp.close() + if Args.Fit == False: + upld_info_hdr = UPLD_INFO_HEADER() + upld_info_hdr.SpecRevision = Args.SpecRevision + upld_info_hdr.Revision = Args.Revision + upld_info_hdr.ProducerId = Args.ProducerId.encode()[:16] + upld_info_hdr.ImageId = Args.ImageId.encode()[:16] + upld_info_hdr.Attribute |= 1 if BuildTarget == "DEBUG" else 0 + fp = open(UpldInfoFile, 'wb') + fp.write(bytearray(upld_info_hdr)) + fp.close() + + if Args.BuildEntryOnly == False: + import Tools.ElfFv as ElfFv + ElfFv.ReplaceFv (EntryOutputDir, UpldInfoFile, '.upld_info', Alignment = 4) + if Args.Fit == False: + shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf')) + else: + shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.fit')) MultiFvList = [] if Args.BuildEntryOnly == False: MultiFvList = [ - ['uefi_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ], - ['bds_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ], - ['network_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv")) ], + ['uefi_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv")) ], + ['bds_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv")) ], + ['network_fv', os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))], ] - AddSectionName = '.upld_info' - ReplaceFv (EntryOutputDir, UpldInfoFile, AddSectionName, Alignment = 4) - if Args.PreBuildUplBinary is None: - shutil.copy (EntryOutputDir, os.path.join(BuildDir, 'UniversalPayload.elf')) - return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf') + if Args.Fit == True: + import Tools.MkFitImage as MkFitImage + import pefile + fit_image_info_header = MkFitImage.FIT_IMAGE_INFO_HEADER() + fit_image_info_header.Description = 'Uefi Universal Payload' + fit_image_info_header.UplVersion = Args.SpecRevision + fit_image_info_header.Type = 'flat-binary' + fit_image_info_header.Arch = FitArch + fit_image_info_header.Compression = 'none' + fit_image_info_header.Revision = Args.Revision + fit_image_info_header.BuildType = Args.Target.lower() + fit_image_info_header.Capabilities = None + fit_image_info_header.Producer = Args.ProducerId.lower() + fit_image_info_header.ImageId = Args.ImageId.lower() + fit_image_info_header.Binary = os.path.join(BuildDir, 'UniversalPayload.fit') + fit_image_info_header.TargetPath = os.path.join(BuildDir, 'UniversalPayload.fit') + fit_image_info_header.UefifvPath = DxeFvOutputDir + fit_image_info_header.BdsfvPath = BdsFvOutputDir + fit_image_info_header.NetworkfvPath = NetworkFvOutputDir + fit_image_info_header.DataOffset = 0x1000 + fit_image_info_header.LoadAddr = Args.LoadAddress + fit_image_info_header.Project = 'tianocore' + + TargetRebaseFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".pecoff") + TargetRebaseEntryFile = fit_image_info_header.Binary.replace (pathlib.Path(fit_image_info_header.Binary).suffix, ".entry") + -def main(): - def ValidateSpecRevision (Argument): - try: - (MajorStr, MinorStr) = Argument.split('.') - except: - raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) # - # Spec Revision Bits 15 : 8 - Major Version. Bits 7 : 0 - Minor Version. + # Rebase PECOFF to load address # - if len(MinorStr) > 0 and len(MinorStr) < 3: - try: - Minor = int(MinorStr, 16) if len(MinorStr) == 2 else (int(MinorStr, 16) << 4) - except: - raise argparse.ArgumentTypeError ('{} Minor version of SpecRevision is not a valid integer value.'.format (Argument)) - else: - raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + RunCommand ( + "GenFw -e SEC -o {} {}".format ( + TargetRebaseFile, + fit_image_info_header.Binary + )) + RunCommand ( + "GenFw --rebase 0x{:02X} -o {} {} ".format ( + fit_image_info_header.LoadAddr + fit_image_info_header.DataOffset, + TargetRebaseFile, + TargetRebaseFile, + )) - if len(MajorStr) > 0 and len(MajorStr) < 3: - try: - Major = int(MajorStr, 16) - except: - raise argparse.ArgumentTypeError ('{} Major version of SpecRevision is not a valid integer value.'.format (Argument)) - else: - raise argparse.ArgumentTypeError ('{} is not a valid SpecRevision format (Major[8-bits].Minor[8-bits]).'.format (Argument)) + # + # Open PECOFF relocation table binary. + # + RelocBinary = b'' + PeCoff = pefile.PE (TargetRebaseFile) + for reloc in PeCoff.DIRECTORY_ENTRY_BASERELOC: + for entry in reloc.entries: + if (entry.type == 0): + continue + Type = entry.type + Offset = entry.rva + fit_image_info_header.DataOffset + RelocBinary += Type.to_bytes (8, 'little') + Offset.to_bytes (8, 'little') + RelocBinary += b'\x00' * (0x1000 - (len(RelocBinary) % 0x1000)) - return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0) + # + # Output UniversalPayload.entry + # + TempBinary = open (TargetRebaseFile, 'rb') + TianoBinary = TempBinary.read () + TempBinary.close () - def Validate32BitInteger (Argument): - try: - Value = int (Argument, 0) - except: - raise argparse.ArgumentTypeError ('{} is not a valid integer value.'.format (Argument)) - if Value < 0: - raise argparse.ArgumentTypeError ('{} is a negative value.'.format (Argument)) - if Value > 0xffffffff: - raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument)) - return Value - - def ValidateAddFv (Argument): - Value = Argument.split ("=") - if len (Value) != 2: - raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) - if Value[0][-3:] != "_fv": - raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) - if Value[1][-3:].lower () != ".fv": - raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument)) - if os.path.exists (Value[1]) == False: - raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1])) - return Value + TianoEntryBinary = TianoBinary + RelocBinary + TianoEntryBinary += (b'\x00' * (0x1000 - (len(TianoBinary) % 0x1000))) + TianoEntryBinarySize = len (TianoEntryBinary) + + TempBinary = open(TargetRebaseEntryFile, "wb") + TempBinary.truncate() + TempBinary.write(TianoEntryBinary) + TempBinary.close() + + # + # Calculate entry and update relocation table start address and data-size. + # + fit_image_info_header.Entry = PeCoff.OPTIONAL_HEADER.ImageBase + PeCoff.OPTIONAL_HEADER.AddressOfEntryPoint + fit_image_info_header.RelocStart = fit_image_info_header.DataOffset + len(TianoBinary) + fit_image_info_header.DataSize = TianoEntryBinarySize + fit_image_info_header.Binary = TargetRebaseEntryFile + + if MkFitImage.MakeFitImage(fit_image_info_header) is True: + print('\nSuccessfully build Fit Image') + else: + sys.exit(1) + return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.fit') + else: + return MultiFvList, os.path.join(BuildDir, 'UniversalPayload.elf') +def main(): parser = argparse.ArgumentParser(description='For building Universal Payload') parser.add_argument('-t', '--ToolChain') parser.add_argument('-b', '--Target', default='DEBUG') @@ -192,13 +321,16 @@ def main(): parser.add_argument("-s", "--SpecRevision", type=ValidateSpecRevision, default ='0.7', help='Indicates compliance with a revision of this specification in the BCD format.') parser.add_argument("-r", "--Revision", type=Validate32BitInteger, default ='0x0000010105', help='Revision of the Payload binary. Major.Minor.Revision.Build') parser.add_argument("-o", "--ProducerId", default ='INTEL', help='A null-terminated OEM-supplied string that identifies the payload producer (16 bytes maximal).') + parser.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file') + parser.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file') parser.add_argument("-sk", "--SkipBuild", action='store_true', help='Skip UniversalPayload build') parser.add_argument("-af", "--AddFv", type=ValidateAddFv, action='append', help='Add or replace specific FV into payload, Ex: uefi_fv=XXX.fv') - command_group = parser.add_mutually_exclusive_group() - command_group.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file') - command_group.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file') + parser.add_argument("-f", "--Fit", action='store_true', help='Build UniversalPayload file as UniversalPayload.fit', default=False) + parser.add_argument('-l', "--LoadAddress", type=int, help='Specify payload load address', default =0x000800000) + args = parser.parse_args() + MultiFvList = [] UniversalPayloadBinary = args.PreBuildUplBinary if (args.SkipBuild == False): @@ -208,12 +340,24 @@ def main(): for (SectionName, SectionFvFile) in args.AddFv: MultiFvList.append ([SectionName, SectionFvFile]) + def ReplaceFv (UplBinary, SectionFvFile, SectionName): + print (bcolors.OKGREEN + "Patch {}={} into {}".format (SectionName, SectionFvFile, UplBinary) + bcolors.ENDC) + if (args.Fit == False): + import Tools.ElfFv as ElfFv + return ElfFv.ReplaceFv (UplBinary, SectionFvFile, '.upld.{}'.format (SectionName)) + else: + import Tools.MkFitImage as MkFitImage + return MkFitImage.ReplaceFv (UplBinary, SectionFvFile, SectionName) + if (UniversalPayloadBinary != None): for (SectionName, SectionFvFile) in MultiFvList: if os.path.exists (SectionFvFile) == False: continue - print ("Patch {}={} into {}".format (SectionName, SectionFvFile, UniversalPayloadBinary)) - ReplaceFv (UniversalPayloadBinary, SectionFvFile, '.upld.{}'.format (SectionName)) + + status = ReplaceFv (UniversalPayloadBinary, SectionFvFile, SectionName.replace ("_", "-")) + if status != 0: + print (bcolors.FAIL + "[Fail] Patch {}={}".format (SectionName, SectionFvFile) + bcolors.ENDC) + return status print ("\nSuccessfully build Universal Payload") -- 2.39.1.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108701): https://edk2.groups.io/g/devel/message/108701 Mute This Topic: https://groups.io/mt/101375948/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=- ^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2023-09-15 13:03 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-09-15 8:58 [edk2-devel] [PATCH v2 0/2] UefiPayloadPkg supports Fit brucex.wang 2023-09-15 8:58 ` [edk2-devel] [PATCH v2 1/2] MdePkg/BaseFdtLib: Add Fdt function brucex.wang 2023-09-15 9:02 ` Guo, Gua 2023-09-15 9:06 ` Lu, James 2023-09-15 9:09 ` Benny Lin 2023-09-15 8:58 ` [edk2-devel] [PATCH v2 2/2] UefiPayloadPkg: Add FIT support brucex.wang 2023-09-15 9:02 ` Guo, Gua 2023-09-15 10:26 ` Sheng Lean Tan 2023-09-15 10:32 ` Sheng Lean Tan 2023-09-15 9:06 ` Lu, James
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox