mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-27 07:34:06 +02:00
UefiPayloadPkg: Add FIT support
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> Reviewed-by: Gua Guo <gua.guo@intel.com> Signed-off-by: BruceX Wang <brucex.wang@intel.com>
This commit is contained in:
parent
d6b05375b4
commit
39f3c26e8c
@ -413,7 +413,7 @@ EFIAPI
|
|||||||
FdtGetName (
|
FdtGetName (
|
||||||
IN VOID *Fdt,
|
IN VOID *Fdt,
|
||||||
IN INT32 NodeOffset,
|
IN INT32 NodeOffset,
|
||||||
IN UINT32 *Length
|
IN INT32 *Length
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -418,10 +418,10 @@ EFIAPI
|
|||||||
FdtGetName (
|
FdtGetName (
|
||||||
IN VOID *Fdt,
|
IN VOID *Fdt,
|
||||||
IN INT32 NodeOffset,
|
IN INT32 NodeOffset,
|
||||||
IN UINT32 *Length
|
IN INT32 *Length
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return fdt_get_name (Fdt, NodeOffset, (int *)Length);
|
return fdt_get_name (Fdt, NodeOffset, Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
19
UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
Normal file
19
UefiPayloadPkg/Include/Guid/UniversalPayloadBase.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/** @file
|
||||||
|
Universal Payload general definitions.
|
||||||
|
|
||||||
|
Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#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_
|
60
UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
Normal file
60
UefiPayloadPkg/PayloadLoaderPeim/FitLib.h
Normal file
@ -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 {
|
||||||
|
CHAR8 *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
|
127
UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
Normal file
127
UefiPayloadPkg/PayloadLoaderPeim/FitLib/FitLib.c
Normal file
@ -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;
|
||||||
|
}
|
150
UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
Normal file
150
UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.c
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/** @file
|
||||||
|
FIT Load Image Support
|
||||||
|
Copyright (c) 2023, 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;
|
||||||
|
}
|
59
UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
Normal file
59
UefiPayloadPkg/PayloadLoaderPeim/FitPayloadLoaderPeim.inf
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
## @file
|
||||||
|
# Produce LoadFile PPI for payload loading.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023, 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
|
189
UefiPayloadPkg/Readme.md
Normal file
189
UefiPayloadPkg/Readme.md
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
# UefiPayloadPkg
|
||||||
|
Provide UEFI Universal Payload for different bootloader to generate EFI environment
|
||||||
|
|
||||||
|
# Spec
|
||||||
|
UniversalPayload URL: https://universalscalablefirmware.github.io/documentation/2_universal_payload.html
|
||||||
|
UniversalPayload URL: https://universalpayload.github.io/spec/
|
||||||
|
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 |
|
||||||
|
+--------------------------------+
|
||||||
|
|
||||||
|
```
|
272
UefiPayloadPkg/Tools/MkFitImage.py
Normal file
272
UefiPayloadPkg/Tools/MkFitImage.py
Normal file
@ -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
|
653
UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
Normal file
653
UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
Normal file
@ -0,0 +1,653 @@
|
|||||||
|
/** @file
|
||||||
|
Copyright (c) 2023, 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
|
||||||
|
));
|
||||||
|
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;
|
||||||
|
}
|
98
UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
Normal file
98
UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
## @file
|
||||||
|
# This is the first module for UEFI payload.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023, 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
|
@ -24,6 +24,9 @@
|
|||||||
#
|
#
|
||||||
gUefiPayloadPkgTokenSpaceGuid = {0x1d127ea, 0xf6f1, 0x4ef6, {0x94, 0x15, 0x8a, 0x0, 0x0, 0x93, 0xf8, 0x9d}}
|
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
|
# Gop Temp
|
||||||
#
|
#
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
DEFINE PS2_KEYBOARD_ENABLE = FALSE
|
DEFINE PS2_KEYBOARD_ENABLE = FALSE
|
||||||
DEFINE RAM_DISK_ENABLE = FALSE
|
DEFINE RAM_DISK_ENABLE = FALSE
|
||||||
DEFINE SIO_BUS_ENABLE = FALSE
|
DEFINE SIO_BUS_ENABLE = FALSE
|
||||||
DEFINE UNIVERSAL_PAYLOAD = FALSE
|
|
||||||
DEFINE SECURITY_STUB_ENABLE = TRUE
|
DEFINE SECURITY_STUB_ENABLE = TRUE
|
||||||
DEFINE SMM_SUPPORT = FALSE
|
DEFINE SMM_SUPPORT = FALSE
|
||||||
DEFINE PLATFORM_BOOT_TIMEOUT = 3
|
DEFINE PLATFORM_BOOT_TIMEOUT = 3
|
||||||
@ -44,6 +43,14 @@
|
|||||||
DEFINE BOOTSPLASH_IMAGE = FALSE
|
DEFINE BOOTSPLASH_IMAGE = FALSE
|
||||||
DEFINE NVME_ENABLE = TRUE
|
DEFINE NVME_ENABLE = TRUE
|
||||||
DEFINE CAPSULE_SUPPORT = FALSE
|
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
|
# NULL: NullMemoryTestDxe
|
||||||
@ -311,7 +318,7 @@
|
|||||||
VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
|
VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
|
||||||
CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
|
CcExitLib|UefiCpuPkg/Library/CcExitLibNull/CcExitLibNull.inf
|
||||||
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
|
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
|
||||||
|
FdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf
|
||||||
[LibraryClasses.common]
|
[LibraryClasses.common]
|
||||||
!if $(BOOTSPLASH_IMAGE)
|
!if $(BOOTSPLASH_IMAGE)
|
||||||
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
|
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
|
||||||
@ -600,14 +607,26 @@
|
|||||||
!if "IA32" in "$(ARCH)"
|
!if "IA32" in "$(ARCH)"
|
||||||
[Components.IA32]
|
[Components.IA32]
|
||||||
!if $(UNIVERSAL_PAYLOAD) == TRUE
|
!if $(UNIVERSAL_PAYLOAD) == TRUE
|
||||||
|
!if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF"
|
||||||
UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
|
UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
|
||||||
|
!elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT"
|
||||||
|
UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
|
||||||
|
!else
|
||||||
|
UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
|
||||||
|
!endif
|
||||||
!else
|
!else
|
||||||
UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
|
UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
|
||||||
!endif
|
!endif
|
||||||
!else
|
!else
|
||||||
[Components.X64]
|
[Components.X64]
|
||||||
!if $(UNIVERSAL_PAYLOAD) == TRUE
|
!if $(UNIVERSAL_PAYLOAD) == TRUE
|
||||||
|
!if $(UNIVERSAL_PAYLOAD_FORMAT) == "ELF"
|
||||||
UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
|
UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
|
||||||
|
!elseif $(UNIVERSAL_PAYLOAD_FORMAT) == "FIT"
|
||||||
|
UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.inf
|
||||||
|
!else
|
||||||
|
UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
|
||||||
|
!endif
|
||||||
!else
|
!else
|
||||||
UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
|
UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
|
||||||
!endif
|
!endif
|
||||||
|
@ -10,10 +10,22 @@ import subprocess
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
import pathlib
|
||||||
from ctypes import *
|
from ctypes import *
|
||||||
from Tools.ElfFv import ReplaceFv
|
|
||||||
sys.dont_write_bytecode = True
|
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):
|
class UPLD_INFO_HEADER(LittleEndianStructure):
|
||||||
_pack_ = 1
|
_pack_ = 1
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
@ -36,103 +48,7 @@ class UPLD_INFO_HEADER(LittleEndianStructure):
|
|||||||
self.ImageId = b'UEFI'
|
self.ImageId = b'UEFI'
|
||||||
self.ProducerId = b'INTEL'
|
self.ProducerId = b'INTEL'
|
||||||
|
|
||||||
def BuildUniversalPayload(Args):
|
def ValidateSpecRevision (Argument):
|
||||||
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)
|
|
||||||
|
|
||||||
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.Arch == 'X64':
|
|
||||||
BuildArch = "X64"
|
|
||||||
EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("X64/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
|
|
||||||
else:
|
|
||||||
BuildArch = "IA32 -a X64"
|
|
||||||
EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ElfToolChain), os.path.normpath("IA32/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry/DEBUG/UniversalPayloadEntry.dll"))
|
|
||||||
|
|
||||||
DscPath = os.path.normpath("UefiPayloadPkg/UefiPayloadPkg.dsc")
|
|
||||||
ModuleReportPath = os.path.join(BuildDir, "UefiUniversalPayloadEntry.txt")
|
|
||||||
UpldInfoFile = os.path.join(BuildDir, "UniversalPayloadInfo.bin")
|
|
||||||
|
|
||||||
Pcds = ""
|
|
||||||
if (Args.pcd != None):
|
|
||||||
for PcdItem in Args.pcd:
|
|
||||||
Pcds += " --pcd {}".format (PcdItem)
|
|
||||||
|
|
||||||
Defines = ""
|
|
||||||
if (Args.Macro != None):
|
|
||||||
for MacroItem in Args.Macro:
|
|
||||||
Defines += " -D {}".format (MacroItem)
|
|
||||||
|
|
||||||
#
|
|
||||||
# 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
|
|
||||||
RunCommand(BuildPayload)
|
|
||||||
#
|
|
||||||
# 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 += Pcds
|
|
||||||
BuildModule += Defines
|
|
||||||
RunCommand(BuildModule)
|
|
||||||
|
|
||||||
if Args.PreBuildUplBinary is not None:
|
|
||||||
EntryOutputDir = os.path.join(BuildDir, "UniversalPayload.elf")
|
|
||||||
shutil.copy (os.path.abspath(Args.PreBuildUplBinary), EntryOutputDir)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Buid 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()
|
|
||||||
|
|
||||||
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")) ],
|
|
||||||
]
|
|
||||||
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')
|
|
||||||
|
|
||||||
def main():
|
|
||||||
def ValidateSpecRevision (Argument):
|
|
||||||
try:
|
try:
|
||||||
(MajorStr, MinorStr) = Argument.split('.')
|
(MajorStr, MinorStr) = Argument.split('.')
|
||||||
except:
|
except:
|
||||||
@ -158,7 +74,7 @@ def main():
|
|||||||
|
|
||||||
return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
|
return int('0x{0:02x}{1:02x}'.format(Major, Minor), 0)
|
||||||
|
|
||||||
def Validate32BitInteger (Argument):
|
def Validate32BitInteger (Argument):
|
||||||
try:
|
try:
|
||||||
Value = int (Argument, 0)
|
Value = int (Argument, 0)
|
||||||
except:
|
except:
|
||||||
@ -169,7 +85,7 @@ def main():
|
|||||||
raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument))
|
raise argparse.ArgumentTypeError ('{} is larger than 32-bits.'.format (Argument))
|
||||||
return Value
|
return Value
|
||||||
|
|
||||||
def ValidateAddFv (Argument):
|
def ValidateAddFv (Argument):
|
||||||
Value = Argument.split ("=")
|
Value = Argument.split ("=")
|
||||||
if len (Value) != 2:
|
if len (Value) != 2:
|
||||||
raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
|
raise argparse.ArgumentTypeError ('{} is incorrect format with "xxx_fv=xxx.fv"'.format (Argument))
|
||||||
@ -181,6 +97,220 @@ def main():
|
|||||||
raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1]))
|
raise argparse.ArgumentTypeError ('File {} is not found.'.format (Value[1]))
|
||||||
return Value
|
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 ""
|
||||||
|
|
||||||
|
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"
|
||||||
|
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"
|
||||||
|
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:
|
||||||
|
Pcds += " --pcd {}".format (PcdItem)
|
||||||
|
|
||||||
|
Defines = ""
|
||||||
|
if (Args.Macro != None):
|
||||||
|
for MacroItem in Args.Macro:
|
||||||
|
Defines += " -D {}".format (MacroItem)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Building DXE core and DXE drivers as DXEFV.
|
||||||
|
#
|
||||||
|
if Args.BuildEntryOnly == False:
|
||||||
|
BuildPayload = "build -p {} -b {} -a X64 -t {} -y {} {}".format (DscPath, BuildTarget, ToolChain, PayloadReportPath, Quiet)
|
||||||
|
BuildPayload += Pcds
|
||||||
|
BuildPayload += Defines
|
||||||
|
RunCommand(BuildPayload)
|
||||||
|
#
|
||||||
|
# Building Universal Payload entry.
|
||||||
|
#
|
||||||
|
if Args.PreBuildUplBinary is None:
|
||||||
|
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:
|
||||||
|
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)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build Universal Payload Information Section ".upld_info"
|
||||||
|
#
|
||||||
|
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.PreBuildUplBinary is None:
|
||||||
|
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"))],
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Rebase PECOFF to load address
|
||||||
|
#
|
||||||
|
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,
|
||||||
|
))
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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))
|
||||||
|
|
||||||
|
#
|
||||||
|
# Output UniversalPayload.entry
|
||||||
|
#
|
||||||
|
TempBinary = open (TargetRebaseFile, 'rb')
|
||||||
|
TianoBinary = TempBinary.read ()
|
||||||
|
TempBinary.close ()
|
||||||
|
|
||||||
|
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 = argparse.ArgumentParser(description='For building Universal Payload')
|
||||||
parser.add_argument('-t', '--ToolChain')
|
parser.add_argument('-t', '--ToolChain')
|
||||||
parser.add_argument('-b', '--Target', default='DEBUG')
|
parser.add_argument('-b', '--Target', default='DEBUG')
|
||||||
@ -192,13 +322,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("-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("-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("-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("-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')
|
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()
|
parser.add_argument("-f", "--Fit", action='store_true', help='Build UniversalPayload file as UniversalPayload.fit', default=False)
|
||||||
command_group.add_argument("-e", "--BuildEntryOnly", action='store_true', help='Build UniversalPayload Entry file')
|
parser.add_argument('-l', "--LoadAddress", type=int, help='Specify payload load address', default =0x000800000)
|
||||||
command_group.add_argument("-pb", "--PreBuildUplBinary", default=None, help='Specify the UniversalPayload file')
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
MultiFvList = []
|
MultiFvList = []
|
||||||
UniversalPayloadBinary = args.PreBuildUplBinary
|
UniversalPayloadBinary = args.PreBuildUplBinary
|
||||||
if (args.SkipBuild == False):
|
if (args.SkipBuild == False):
|
||||||
@ -208,12 +341,26 @@ def main():
|
|||||||
for (SectionName, SectionFvFile) in args.AddFv:
|
for (SectionName, SectionFvFile) in args.AddFv:
|
||||||
MultiFvList.append ([SectionName, SectionFvFile])
|
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):
|
if (UniversalPayloadBinary != None):
|
||||||
for (SectionName, SectionFvFile) in MultiFvList:
|
for (SectionName, SectionFvFile) in MultiFvList:
|
||||||
if os.path.exists (SectionFvFile) == False:
|
if os.path.exists (SectionFvFile) == False:
|
||||||
continue
|
continue
|
||||||
print ("Patch {}={} into {}".format (SectionName, SectionFvFile, UniversalPayloadBinary))
|
if (args.Fit == False):
|
||||||
ReplaceFv (UniversalPayloadBinary, SectionFvFile, '.upld.{}'.format (SectionName))
|
status = ReplaceFv (UniversalPayloadBinary, SectionFvFile, SectionName)
|
||||||
|
else:
|
||||||
|
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")
|
print ("\nSuccessfully build Universal Payload")
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user