* [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support PRM GCC build
@ 2022-02-28 1:14 Huang, Li-Xia
2022-03-01 1:51 ` 回复: " gaoliming
0 siblings, 1 reply; 6+ messages in thread
From: Huang, Li-Xia @ 2022-02-28 1:14 UTC (permalink / raw)
To: devel; +Cc: Lixia Huang, Liming Gao, Bob Feng, Yuwei Chen
Since PRM module needs to support export table in PE-COFF, we'll
enhance GenFw tool to support this.
Add one export flag in GenFw tool. If export flag is set:
Step1: Scan ELF symbol table based on PRM module descriptor to get
descriptor offset address;
Step2: Find PRM handlers number and name in COFF file based on the
address from step1;
Step3: Write PRM info such as handler name and export RVA into COFF
export table.
PRM option currently only supports DXE RUNTIME driver and X64 arch.
Change-Id: I479b7c8b23beea12b5c567677688aef6f7af2085
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Yuwei Chen <yuwei.chen@intel.com>
Signed-off-by: Lixia Huang <lisa.huang@intel.com>
---
BaseTools/Source/C/GenFw/Elf64Convert.c | 242 +++++++++++++++++-
BaseTools/Source/C/GenFw/ElfConvert.c | 8 +
BaseTools/Source/C/GenFw/ElfConvert.h | 43 +++-
BaseTools/Source/C/GenFw/GenFw.c | 20 +-
.../C/Include/IndustryStandard/PeImage.h | 7 +
5 files changed, 315 insertions(+), 5 deletions(-)
diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c b/BaseTools/Source/C/GenFw/Elf64Convert.c
index 0bb3ead228..2aa9bfcc94 100644
--- a/BaseTools/Source/C/GenFw/Elf64Convert.c
+++ b/BaseTools/Source/C/GenFw/Elf64Convert.c
@@ -56,6 +56,12 @@ WriteDebug64 (
VOID
);
+STATIC
+VOID
+WriteExport64 (
+ VOID
+ );
+
STATIC
VOID
SetImageSize64 (
@@ -106,7 +112,7 @@ STATIC UINT32 mCoffAlignment = 0x20;
//
// PE section alignment.
//
-STATIC const UINT16 mCoffNbrSections = 4;
+STATIC UINT16 mCoffNbrSections = 4;
//
// ELF sections to offset in Coff file.
@@ -122,7 +128,7 @@ STATIC UINT32 mDataOffset;
STATIC UINT32 mHiiRsrcOffset;
STATIC UINT32 mRelocOffset;
STATIC UINT32 mDebugOffset;
-
+STATIC UINT32 mExportOffset;
//
// Used for RISC-V relocations.
//
@@ -132,6 +138,14 @@ STATIC Elf64_Half mRiscVPass1SymSecIndex = 0;
STATIC INT32 mRiscVPass1Offset;
STATIC INT32 mRiscVPass1GotFixup;
+//
+// Used for Export section.
+//
+STATIC UINT32 mExportSize;
+STATIC UINT32 mExportRVA[PRM_MODULE_EXPORT_SYMBOL_NUM];
+STATIC UINT32 mExportSymNum;
+STATIC CHAR8 mExportSymName[PRM_MODULE_EXPORT_SYMBOL_NUM][PRM_HANDLER_NAME_MAXIMUM_LENGTH];
+
//
// Initialization Function
//
@@ -171,6 +185,13 @@ InitializeElf64 (
return FALSE;
}
+ if (mExportFlag) {
+ if (mEhdr->e_machine != EM_X86_64) {
+ Error (NULL, 0, 3000, "Unsupported", "--prm option currently only supports X64 arch.");
+ return FALSE;
+ }
+ }
+
//
// Update section header pointers
//
@@ -200,6 +221,11 @@ InitializeElf64 (
ElfFunctions->SetImageSize = SetImageSize64;
ElfFunctions->CleanUp = CleanUp64;
+ if (mExportFlag) {
+ mCoffNbrSections ++;
+ ElfFunctions->WriteExport = WriteExport64;
+ }
+
return TRUE;
}
@@ -263,6 +289,17 @@ IsHiiRsrcShdr (
return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);
}
+STATIC
+BOOLEAN
+IsSymbolShdr (
+ Elf_Shdr *Shdr
+ )
+{
+ Elf_Shdr *Namehdr = GetShdrByIndex(mEhdr->e_shstrndx);
+
+ return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namehdr->sh_offset + Shdr->sh_name, ELF_SYMBOL_SECTION_NAME) == 0);
+}
+
STATIC
BOOLEAN
IsDataShdr (
@@ -335,6 +372,37 @@ GetSymName (
return StrtabContents + Sym->st_name;
}
+//
+// Get Prm Handler number and name
+//
+STATIC
+VOID
+FindPrmHandler (
+ UINT64 Offset
+ )
+{
+ PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER *PrmExport;
+ PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT *PrmHandler;
+ UINT32 HandlerNum;
+
+ PrmExport = (PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER*)((UINT8*)mEhdr + Offset);
+ PrmHandler = (PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT *)(PrmExport + 1);
+
+ for (HandlerNum = 0; HandlerNum < PrmExport->NumberPrmHandlers; HandlerNum++) {
+ strcpy(mExportSymName[mExportSymNum], PrmHandler->PrmHandlerName);
+ mExportSymNum ++;
+ PrmHandler += 1;
+
+ //
+ // Check if PRM handler number is larger than (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)
+ //
+ if (mExportSymNum >= (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)) {
+ Error (NULL, 0, 3000, "Invalid", "FindPrmHandler: Number %u is too high.", mExportSymNum);
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
//
// Find the ELF section hosting the GOT from an ELF Rva
// of a single GOT entry. Normally, GOT is placed in
@@ -717,6 +785,7 @@ ScanSections64 (
UINT32 CoffEntry;
UINT32 SectionCount;
BOOLEAN FoundSection;
+ UINT32 Offset;
CoffEntry = 0;
mCoffOffset = 0;
@@ -880,6 +949,82 @@ ScanSections64 (
Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName);
}
+ //
+ // The Symbol sections.
+ //
+ if (mExportFlag) {
+ UINT32 SymIndex;
+ Elf_Sym *Sym;
+ UINT64 SymNum;
+ const UINT8 *SymName;
+
+ mExportOffset = mCoffOffset;
+ mExportSize = sizeof(EFI_IMAGE_EXPORT_DIRECTORY) + strlen(mInImageName) + 1;
+
+ for (i = 0; i < mEhdr->e_shnum; i++) {
+
+ //
+ // Determine if this is a symbol section.
+ //
+ Elf_Shdr *shdr = GetShdrByIndex(i);
+ if (!IsSymbolShdr(shdr)) {
+ continue;
+ }
+
+ UINT8 *Symtab = (UINT8*)mEhdr + shdr->sh_offset;
+ SymNum = (shdr->sh_size) / (shdr->sh_entsize);
+
+ //
+ // First Get PrmModuleExportDescriptor
+ //
+ for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
+ Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
+ SymName = GetSymName(Sym);
+ if (SymName == NULL) {
+ continue;
+ }
+
+ if (strcmp((CHAR8*)SymName, PRM_MODULE_EXPORT_DESCRIPTOR_NAME) == 0) {
+ //
+ // Find PrmHandler Number and Name
+ //
+ FindPrmHandler(Sym->st_value);
+
+ strcpy(mExportSymName[mExportSymNum], (CHAR8*)SymName);
+ mExportRVA[mExportSymNum] = (UINT32)(Sym->st_value);
+ mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
+ mExportSymNum ++;
+ break;
+ }
+ }
+
+ //
+ // Second Get PrmHandler
+ //
+ for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
+ UINT32 ExpIndex;
+ Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
+ SymName = GetSymName(Sym);
+ if (SymName == NULL) {
+ continue;
+ }
+
+ for (ExpIndex = 0; ExpIndex < (mExportSymNum -1); ExpIndex++) {
+ if (strcmp((CHAR8*)SymName, mExportSymName[ExpIndex]) != 0) {
+ continue;
+ }
+ mExportRVA[ExpIndex] = (UINT32)(Sym->st_value);
+ mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
+ }
+ }
+
+ break;
+ }
+
+ mCoffOffset += mExportSize;
+ mCoffOffset = CoffAlign(mCoffOffset);
+ }
+
//
// The HII resource sections.
//
@@ -989,8 +1134,17 @@ ScanSections64 (
NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
}
+ //
+ // If found symbol, add edata section between data and rsrc section
+ //
+ if(mExportFlag) {
+ Offset = mExportOffset;
+ } else {
+ Offset = mHiiRsrcOffset;
+ }
+
if ((mHiiRsrcOffset - mDataOffset) > 0) {
- CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset,
+ CreateSectionHeader (".data", mDataOffset, Offset - mDataOffset,
EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
| EFI_IMAGE_SCN_MEM_WRITE
| EFI_IMAGE_SCN_MEM_READ);
@@ -999,6 +1153,20 @@ ScanSections64 (
NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
}
+ if(mExportFlag) {
+ if ((mHiiRsrcOffset - mExportOffset) > 0) {
+ CreateSectionHeader (".edata", mExportOffset, mHiiRsrcOffset - mExportOffset,
+ EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
+ | EFI_IMAGE_SCN_MEM_READ);
+ NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size = mHiiRsrcOffset - mExportOffset;
+ NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = mExportOffset;
+
+ } else {
+ // Don't make a section of size 0.
+ NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
+ }
+ }
+
if ((mRelocOffset - mHiiRsrcOffset) > 0) {
CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset,
EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
@@ -1757,4 +1925,72 @@ CleanUp64 (
}
}
+STATIC
+VOID
+WriteExport64 (
+ VOID
+ )
+{
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
+ EFI_IMAGE_EXPORT_DIRECTORY *ExportDir;
+ EFI_IMAGE_DATA_DIRECTORY *DataDir;
+ UINT32 FileNameOffset;
+ UINT32 NameOffset;
+ UINT16 Index;
+ UINT8 *Tdata = NULL;
+
+ ExportDir = (EFI_IMAGE_EXPORT_DIRECTORY*)(mCoffFile + mExportOffset);
+ ExportDir->Characteristics = 0;
+ ExportDir->TimeDateStamp = 0;
+ ExportDir->MajorVersion = 0;
+ ExportDir->MinorVersion =0;
+ ExportDir->Name = 0;
+ ExportDir->NumberOfFunctions = mExportSymNum;
+ ExportDir->NumberOfNames = mExportSymNum;
+ ExportDir->Base = EFI_IMAGE_EXPORT_ORDINAL_BASE;
+ ExportDir->AddressOfFunctions = mExportOffset + sizeof(EFI_IMAGE_EXPORT_DIRECTORY);
+ ExportDir->AddressOfNames = ExportDir->AddressOfFunctions + EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;
+ ExportDir->AddressOfNameOrdinals = ExportDir->AddressOfNames + EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;
+
+ FileNameOffset = ExportDir->AddressOfNameOrdinals + EFI_IMAGE_EXPORT_ORDINAL_SIZE * mExportSymNum;
+ NameOffset = FileNameOffset + strlen(mInImageName) + 1;
+
+ // Write Input image Name RVA
+ ExportDir->Name = FileNameOffset;
+
+ // Write Input image Name
+ strcpy((char *)(mCoffFile + FileNameOffset), mInImageName);
+
+ for (Index = 0; Index < mExportSymNum; Index++) {
+ //
+ // Write Export Address Table
+ //
+ Tdata = mCoffFile + ExportDir->AddressOfFunctions + Index * EFI_IMAGE_EXPORT_ADDR_SIZE;
+ *(UINT32 *)Tdata = mExportRVA[Index];
+
+ //
+ // Write Export Name Pointer Table
+ //
+ Tdata = mCoffFile + ExportDir->AddressOfNames + Index * EFI_IMAGE_EXPORT_ADDR_SIZE;
+ *(UINT32 *)Tdata = NameOffset;
+
+ //
+ // Write Export Ordinal table
+ //
+ Tdata = mCoffFile + ExportDir->AddressOfNameOrdinals + Index * EFI_IMAGE_EXPORT_ORDINAL_SIZE;
+ *(UINT16 *)Tdata = Index;
+
+ //
+ // Write Export Name Table
+ //
+ strcpy((char *)(mCoffFile + NameOffset), mExportSymName[Index]);
+ NameOffset += strlen(mExportSymName[Index]) + 1;
+ }
+
+ NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);
+ DataDir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT];
+ DataDir->VirtualAddress = mExportOffset;
+ DataDir->Size = mExportSize;
+
+}
diff --git a/BaseTools/Source/C/GenFw/ElfConvert.c b/BaseTools/Source/C/GenFw/ElfConvert.c
index 7db8721167..be98544056 100644
--- a/BaseTools/Source/C/GenFw/ElfConvert.c
+++ b/BaseTools/Source/C/GenFw/ElfConvert.c
@@ -223,6 +223,14 @@ ConvertElf (
VerboseMsg ("Write debug info.");
ElfFunctions.WriteDebug ();
+ //
+ // For PRM Driver to Write export info.
+ //
+ if (mExportFlag) {
+ VerboseMsg ("Write export info.");
+ ElfFunctions.WriteExport ();
+ }
+
//
// Make sure image size is correct before returning the new image.
//
diff --git a/BaseTools/Source/C/GenFw/ElfConvert.h b/BaseTools/Source/C/GenFw/ElfConvert.h
index 801e8de4a2..6ab4605227 100644
--- a/BaseTools/Source/C/GenFw/ElfConvert.h
+++ b/BaseTools/Source/C/GenFw/ElfConvert.h
@@ -24,6 +24,7 @@ extern UINT8 *mCoffFile;
extern UINT32 mTableOffset;
extern UINT32 mOutImageType;
extern UINT32 mFileBufferSize;
+extern BOOLEAN mExportFlag;
//
// Common EFI specific data.
@@ -31,6 +32,44 @@ extern UINT32 mFileBufferSize;
#define ELF_HII_SECTION_NAME ".hii"
#define ELF_STRTAB_SECTION_NAME ".strtab"
#define MAX_COFF_ALIGNMENT 0x10000
+#define ELF_SYMBOL_SECTION_NAME ".symtab"
+
+//
+// Platform Runtime Mechanism (PRM) specific data.
+//
+#define PRM_MODULE_EXPORT_SYMBOL_NUM 256
+
+// <to-do> to include PRM header directly once PrmPkg is in main repo
+#define PRM_HANDLER_NAME_MAXIMUM_LENGTH 128
+
+#define PRM_MODULE_EXPORT_DESCRIPTOR_NAME "PrmModuleExportDescriptor"
+#define PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE SIGNATURE_64 ('P', 'R', 'M', '_', 'M', 'E', 'D', 'T')
+#define PRM_MODULE_EXPORT_REVISION 0x0
+
+//
+// Platform Runtime Mechanism (PRM) Export Descriptor Structures
+//
+#pragma pack(push, 1)
+
+typedef struct {
+ EFI_GUID PrmHandlerGuid;
+ CHAR8 PrmHandlerName[PRM_HANDLER_NAME_MAXIMUM_LENGTH];
+} PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT;
+
+typedef struct {
+ UINT64 Signature;
+ UINT16 Revision;
+ UINT16 NumberPrmHandlers;
+ EFI_GUID PlatformGuid;
+ EFI_GUID ModuleGuid;
+} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER;
+
+typedef struct {
+ PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER Header;
+ PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT PrmHandlerExportDescriptors[1];
+} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT;
+
+#pragma pack(pop)
//
// Filter Types
@@ -38,7 +77,8 @@ extern UINT32 mFileBufferSize;
typedef enum {
SECTION_TEXT,
SECTION_HII,
- SECTION_DATA
+ SECTION_DATA,
+ SECTION_SYMBOL
} SECTION_FILTER_TYPES;
@@ -50,6 +90,7 @@ typedef struct {
BOOLEAN (*WriteSections) (SECTION_FILTER_TYPES FilterType);
VOID (*WriteRelocations) ();
VOID (*WriteDebug) ();
+ VOID (*WriteExport) ();
VOID (*SetImageSize) ();
VOID (*CleanUp) ();
diff --git a/BaseTools/Source/C/GenFw/GenFw.c b/BaseTools/Source/C/GenFw/GenFw.c
index 8cab70ba4d..6f61f16788 100644
--- a/BaseTools/Source/C/GenFw/GenFw.c
+++ b/BaseTools/Source/C/GenFw/GenFw.c
@@ -87,7 +87,7 @@ UINT32 mImageTimeStamp = 0;
UINT32 mImageSize = 0;
UINT32 mOutImageType = FW_DUMMY_IMAGE;
BOOLEAN mIsConvertXip = FALSE;
-
+BOOLEAN mExportFlag = FALSE;
STATIC
EFI_STATUS
@@ -279,6 +279,10 @@ Returns:
except for -o or -r option. It is a action option.\n\
If it is combined with other action options, the later\n\
input action option will override the previous one.\n");
+ fprintf (stdout, " --prm Scan symbol section from ELF image and \n\
+ write export table into PE-COFF.\n\
+ This option can be used together with -e.\n\
+ It doesn't work for other options.\n");
fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");
fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");
@@ -1436,6 +1440,20 @@ Returns:
continue;
}
+ if (stricmp (argv[0], "--prm") == 0) {
+ if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") != 0 ){
+ Error (NULL, 0, 1001, "Invalid", "--prm option only supports DXE RUNTIME driver.");
+ goto Finish;
+ }
+
+ if (!mExportFlag) {
+ mExportFlag = TRUE;
+ }
+ argc --;
+ argv ++;
+ continue;
+ }
+
if (argv[0][0] == '-') {
Error (NULL, 0, 1000, "Unknown option", argv[0]);
goto Finish;
diff --git a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
index f17b8ee19b..21c968e650 100644
--- a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
+++ b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
@@ -571,6 +571,13 @@ typedef struct {
UINT32 AddressOfNameOrdinals;
} EFI_IMAGE_EXPORT_DIRECTORY;
+//
+// Based export types.
+//
+#define EFI_IMAGE_EXPORT_ORDINAL_BASE 1
+#define EFI_IMAGE_EXPORT_ADDR_SIZE 4
+#define EFI_IMAGE_EXPORT_ORDINAL_SIZE 2
+
///
/// DLL support.
/// Import Format
--
2.26.2.windows.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* 回复: [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support PRM GCC build
2022-02-28 1:14 [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support PRM GCC build Huang, Li-Xia
@ 2022-03-01 1:51 ` gaoliming
2022-03-14 3:02 ` Huang, Li-Xia
0 siblings, 1 reply; 6+ messages in thread
From: gaoliming @ 2022-03-01 1:51 UTC (permalink / raw)
To: devel, lisa.huang; +Cc: 'Bob Feng', 'Yuwei Chen'
Lisa:
Please add BZ link for this patch.
And, if PRM option currently only supports DXE RUNTIME driver and X64
arch,
does GenFw report error message if PRM option is specified for other arch
or other module type?
Thanks
Liming
> -----邮件原件-----
> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Huang, Li-Xia
> 发送时间: 2022年2月28日 9:14
> 收件人: devel@edk2.groups.io
> 抄送: Lixia Huang <lisa.huang@intel.com>; Liming Gao
> <gaoliming@byosoft.com.cn>; Bob Feng <bob.c.feng@intel.com>; Yuwei Chen
> <yuwei.chen@intel.com>
> 主题: [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support
> PRM GCC build
>
> Since PRM module needs to support export table in PE-COFF, we'll
> enhance GenFw tool to support this.
>
> Add one export flag in GenFw tool. If export flag is set:
> Step1: Scan ELF symbol table based on PRM module descriptor to get
> descriptor offset address;
> Step2: Find PRM handlers number and name in COFF file based on the
> address from step1;
> Step3: Write PRM info such as handler name and export RVA into COFF
> export table.
>
> PRM option currently only supports DXE RUNTIME driver and X64 arch.
>
> Change-Id: I479b7c8b23beea12b5c567677688aef6f7af2085
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Bob Feng <bob.c.feng@intel.com>
> Cc: Yuwei Chen <yuwei.chen@intel.com>
> Signed-off-by: Lixia Huang <lisa.huang@intel.com>
> ---
> BaseTools/Source/C/GenFw/Elf64Convert.c | 242
> +++++++++++++++++-
> BaseTools/Source/C/GenFw/ElfConvert.c | 8 +
> BaseTools/Source/C/GenFw/ElfConvert.h | 43 +++-
> BaseTools/Source/C/GenFw/GenFw.c | 20 +-
> .../C/Include/IndustryStandard/PeImage.h | 7 +
> 5 files changed, 315 insertions(+), 5 deletions(-)
>
> diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c
> b/BaseTools/Source/C/GenFw/Elf64Convert.c
> index 0bb3ead228..2aa9bfcc94 100644
> --- a/BaseTools/Source/C/GenFw/Elf64Convert.c
> +++ b/BaseTools/Source/C/GenFw/Elf64Convert.c
> @@ -56,6 +56,12 @@ WriteDebug64 (
> VOID
>
> );
>
>
>
> +STATIC
>
> +VOID
>
> +WriteExport64 (
>
> + VOID
>
> + );
>
> +
>
> STATIC
>
> VOID
>
> SetImageSize64 (
>
> @@ -106,7 +112,7 @@ STATIC UINT32 mCoffAlignment = 0x20;
> //
>
> // PE section alignment.
>
> //
>
> -STATIC const UINT16 mCoffNbrSections = 4;
>
> +STATIC UINT16 mCoffNbrSections = 4;
>
>
>
> //
>
> // ELF sections to offset in Coff file.
>
> @@ -122,7 +128,7 @@ STATIC UINT32 mDataOffset;
> STATIC UINT32 mHiiRsrcOffset;
>
> STATIC UINT32 mRelocOffset;
>
> STATIC UINT32 mDebugOffset;
>
> -
>
> +STATIC UINT32 mExportOffset;
>
> //
>
> // Used for RISC-V relocations.
>
> //
>
> @@ -132,6 +138,14 @@ STATIC Elf64_Half mRiscVPass1SymSecIndex = 0;
> STATIC INT32 mRiscVPass1Offset;
>
> STATIC INT32 mRiscVPass1GotFixup;
>
>
>
> +//
>
> +// Used for Export section.
>
> +//
>
> +STATIC UINT32 mExportSize;
>
> +STATIC UINT32
> mExportRVA[PRM_MODULE_EXPORT_SYMBOL_NUM];
>
> +STATIC UINT32 mExportSymNum;
>
> +STATIC CHAR8
> mExportSymName[PRM_MODULE_EXPORT_SYMBOL_NUM][PRM_HANDLE
> R_NAME_MAXIMUM_LENGTH];
>
> +
>
> //
>
> // Initialization Function
>
> //
>
> @@ -171,6 +185,13 @@ InitializeElf64 (
> return FALSE;
>
> }
>
>
>
> + if (mExportFlag) {
>
> + if (mEhdr->e_machine != EM_X86_64) {
>
> + Error (NULL, 0, 3000, "Unsupported", "--prm option currently only
> supports X64 arch.");
>
> + return FALSE;
>
> + }
>
> + }
>
> +
>
> //
>
> // Update section header pointers
>
> //
>
> @@ -200,6 +221,11 @@ InitializeElf64 (
> ElfFunctions->SetImageSize = SetImageSize64;
>
> ElfFunctions->CleanUp = CleanUp64;
>
>
>
> + if (mExportFlag) {
>
> + mCoffNbrSections ++;
>
> + ElfFunctions->WriteExport = WriteExport64;
>
> + }
>
> +
>
> return TRUE;
>
> }
>
>
>
> @@ -263,6 +289,17 @@ IsHiiRsrcShdr (
> return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset +
> Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);
>
> }
>
>
>
> +STATIC
>
> +BOOLEAN
>
> +IsSymbolShdr (
>
> + Elf_Shdr *Shdr
>
> + )
>
> +{
>
> + Elf_Shdr *Namehdr = GetShdrByIndex(mEhdr->e_shstrndx);
>
> +
>
> + return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namehdr->sh_offset +
> Shdr->sh_name, ELF_SYMBOL_SECTION_NAME) == 0);
>
> +}
>
> +
>
> STATIC
>
> BOOLEAN
>
> IsDataShdr (
>
> @@ -335,6 +372,37 @@ GetSymName (
> return StrtabContents + Sym->st_name;
>
> }
>
>
>
> +//
>
> +// Get Prm Handler number and name
>
> +//
>
> +STATIC
>
> +VOID
>
> +FindPrmHandler (
>
> + UINT64 Offset
>
> + )
>
> +{
>
> + PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER *PrmExport;
>
> + PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT *PrmHandler;
>
> + UINT32 HandlerNum;
>
> +
>
> + PrmExport =
> (PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER*)((UINT8*)mEhdr
> + Offset);
>
> + PrmHandler = (PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT
> *)(PrmExport + 1);
>
> +
>
> + for (HandlerNum = 0; HandlerNum < PrmExport->NumberPrmHandlers;
> HandlerNum++) {
>
> + strcpy(mExportSymName[mExportSymNum],
> PrmHandler->PrmHandlerName);
>
> + mExportSymNum ++;
>
> + PrmHandler += 1;
>
> +
>
> + //
>
> + // Check if PRM handler number is larger than
> (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)
>
> + //
>
> + if (mExportSymNum >= (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)) {
>
> + Error (NULL, 0, 3000, "Invalid", "FindPrmHandler: Number %u is too
> high.", mExportSymNum);
>
> + exit(EXIT_FAILURE);
>
> + }
>
> + }
>
> +}
>
> +
>
> //
>
> // Find the ELF section hosting the GOT from an ELF Rva
>
> // of a single GOT entry. Normally, GOT is placed in
>
> @@ -717,6 +785,7 @@ ScanSections64 (
> UINT32 CoffEntry;
>
> UINT32 SectionCount;
>
> BOOLEAN FoundSection;
>
> + UINT32 Offset;
>
>
>
> CoffEntry = 0;
>
> mCoffOffset = 0;
>
> @@ -880,6 +949,82 @@ ScanSections64 (
> Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1
> data section. Source level debug might not work correctly.",
mInImageName);
>
> }
>
>
>
> + //
>
> + // The Symbol sections.
>
> + //
>
> + if (mExportFlag) {
>
> + UINT32 SymIndex;
>
> + Elf_Sym *Sym;
>
> + UINT64 SymNum;
>
> + const UINT8 *SymName;
>
> +
>
> + mExportOffset = mCoffOffset;
>
> + mExportSize = sizeof(EFI_IMAGE_EXPORT_DIRECTORY) +
> strlen(mInImageName) + 1;
>
> +
>
> + for (i = 0; i < mEhdr->e_shnum; i++) {
>
> +
>
> + //
>
> + // Determine if this is a symbol section.
>
> + //
>
> + Elf_Shdr *shdr = GetShdrByIndex(i);
>
> + if (!IsSymbolShdr(shdr)) {
>
> + continue;
>
> + }
>
> +
>
> + UINT8 *Symtab = (UINT8*)mEhdr + shdr->sh_offset;
>
> + SymNum = (shdr->sh_size) / (shdr->sh_entsize);
>
> +
>
> + //
>
> + // First Get PrmModuleExportDescriptor
>
> + //
>
> + for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
>
> + Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
>
> + SymName = GetSymName(Sym);
>
> + if (SymName == NULL) {
>
> + continue;
>
> + }
>
> +
>
> + if (strcmp((CHAR8*)SymName,
> PRM_MODULE_EXPORT_DESCRIPTOR_NAME) == 0) {
>
> + //
>
> + // Find PrmHandler Number and Name
>
> + //
>
> + FindPrmHandler(Sym->st_value);
>
> +
>
> + strcpy(mExportSymName[mExportSymNum],
> (CHAR8*)SymName);
>
> + mExportRVA[mExportSymNum] = (UINT32)(Sym->st_value);
>
> + mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE +
> EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
>
> + mExportSymNum ++;
>
> + break;
>
> + }
>
> + }
>
> +
>
> + //
>
> + // Second Get PrmHandler
>
> + //
>
> + for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
>
> + UINT32 ExpIndex;
>
> + Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
>
> + SymName = GetSymName(Sym);
>
> + if (SymName == NULL) {
>
> + continue;
>
> + }
>
> +
>
> + for (ExpIndex = 0; ExpIndex < (mExportSymNum -1); ExpIndex++) {
>
> + if (strcmp((CHAR8*)SymName, mExportSymName[ExpIndex]) !=
> 0) {
>
> + continue;
>
> + }
>
> + mExportRVA[ExpIndex] = (UINT32)(Sym->st_value);
>
> + mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE +
> EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
>
> + }
>
> + }
>
> +
>
> + break;
>
> + }
>
> +
>
> + mCoffOffset += mExportSize;
>
> + mCoffOffset = CoffAlign(mCoffOffset);
>
> + }
>
> +
>
> //
>
> // The HII resource sections.
>
> //
>
> @@ -989,8 +1134,17 @@ ScanSections64 (
> NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
>
> }
>
>
>
> + //
>
> + // If found symbol, add edata section between data and rsrc section
>
> + //
>
> + if(mExportFlag) {
>
> + Offset = mExportOffset;
>
> + } else {
>
> + Offset = mHiiRsrcOffset;
>
> + }
>
> +
>
> if ((mHiiRsrcOffset - mDataOffset) > 0) {
>
> - CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset -
> mDataOffset,
>
> + CreateSectionHeader (".data", mDataOffset, Offset - mDataOffset,
>
> EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
>
> | EFI_IMAGE_SCN_MEM_WRITE
>
> | EFI_IMAGE_SCN_MEM_READ);
>
> @@ -999,6 +1153,20 @@ ScanSections64 (
> NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
>
> }
>
>
>
> + if(mExportFlag) {
>
> + if ((mHiiRsrcOffset - mExportOffset) > 0) {
>
> + CreateSectionHeader (".edata", mExportOffset, mHiiRsrcOffset -
> mExportOffset,
>
> + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
>
> + | EFI_IMAGE_SCN_MEM_READ);
>
> +
> NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_EN
> TRY_EXPORT].Size = mHiiRsrcOffset - mExportOffset;
>
> +
> NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_EN
> TRY_EXPORT].VirtualAddress = mExportOffset;
>
> +
>
> + } else {
>
> + // Don't make a section of size 0.
>
> + NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
>
> + }
>
> + }
>
> +
>
> if ((mRelocOffset - mHiiRsrcOffset) > 0) {
>
> CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset -
> mHiiRsrcOffset,
>
> EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
>
> @@ -1757,4 +1925,72 @@ CleanUp64 (
> }
>
> }
>
>
>
> +STATIC
>
> +VOID
>
> +WriteExport64 (
>
> + VOID
>
> + )
>
> +{
>
> + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
>
> + EFI_IMAGE_EXPORT_DIRECTORY *ExportDir;
>
> + EFI_IMAGE_DATA_DIRECTORY *DataDir;
>
> + UINT32 FileNameOffset;
>
> + UINT32 NameOffset;
>
> + UINT16 Index;
>
> + UINT8 *Tdata = NULL;
>
> +
>
> + ExportDir = (EFI_IMAGE_EXPORT_DIRECTORY*)(mCoffFile +
> mExportOffset);
>
> + ExportDir->Characteristics = 0;
>
> + ExportDir->TimeDateStamp = 0;
>
> + ExportDir->MajorVersion = 0;
>
> + ExportDir->MinorVersion =0;
>
> + ExportDir->Name = 0;
>
> + ExportDir->NumberOfFunctions = mExportSymNum;
>
> + ExportDir->NumberOfNames = mExportSymNum;
>
> + ExportDir->Base = EFI_IMAGE_EXPORT_ORDINAL_BASE;
>
> + ExportDir->AddressOfFunctions = mExportOffset +
> sizeof(EFI_IMAGE_EXPORT_DIRECTORY);
>
> + ExportDir->AddressOfNames = ExportDir->AddressOfFunctions +
> EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;
>
> + ExportDir->AddressOfNameOrdinals = ExportDir->AddressOfNames +
> EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;
>
> +
>
> + FileNameOffset = ExportDir->AddressOfNameOrdinals +
> EFI_IMAGE_EXPORT_ORDINAL_SIZE * mExportSymNum;
>
> + NameOffset = FileNameOffset + strlen(mInImageName) + 1;
>
> +
>
> + // Write Input image Name RVA
>
> + ExportDir->Name = FileNameOffset;
>
> +
>
> + // Write Input image Name
>
> + strcpy((char *)(mCoffFile + FileNameOffset), mInImageName);
>
> +
>
> + for (Index = 0; Index < mExportSymNum; Index++) {
>
> + //
>
> + // Write Export Address Table
>
> + //
>
> + Tdata = mCoffFile + ExportDir->AddressOfFunctions + Index *
> EFI_IMAGE_EXPORT_ADDR_SIZE;
>
> + *(UINT32 *)Tdata = mExportRVA[Index];
>
> +
>
> + //
>
> + // Write Export Name Pointer Table
>
> + //
>
> + Tdata = mCoffFile + ExportDir->AddressOfNames + Index *
> EFI_IMAGE_EXPORT_ADDR_SIZE;
>
> + *(UINT32 *)Tdata = NameOffset;
>
> +
>
> + //
>
> + // Write Export Ordinal table
>
> + //
>
> + Tdata = mCoffFile + ExportDir->AddressOfNameOrdinals + Index *
> EFI_IMAGE_EXPORT_ORDINAL_SIZE;
>
> + *(UINT16 *)Tdata = Index;
>
> +
>
> + //
>
> + // Write Export Name Table
>
> + //
>
> + strcpy((char *)(mCoffFile + NameOffset), mExportSymName[Index]);
>
> + NameOffset += strlen(mExportSymName[Index]) + 1;
>
> + }
>
> +
>
> + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile +
> mNtHdrOffset);
>
> + DataDir =
> &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_E
> NTRY_EXPORT];
>
> + DataDir->VirtualAddress = mExportOffset;
>
> + DataDir->Size = mExportSize;
>
> +
>
> +}
>
>
>
> diff --git a/BaseTools/Source/C/GenFw/ElfConvert.c
> b/BaseTools/Source/C/GenFw/ElfConvert.c
> index 7db8721167..be98544056 100644
> --- a/BaseTools/Source/C/GenFw/ElfConvert.c
> +++ b/BaseTools/Source/C/GenFw/ElfConvert.c
> @@ -223,6 +223,14 @@ ConvertElf (
> VerboseMsg ("Write debug info.");
>
> ElfFunctions.WriteDebug ();
>
>
>
> + //
>
> + // For PRM Driver to Write export info.
>
> + //
>
> + if (mExportFlag) {
>
> + VerboseMsg ("Write export info.");
>
> + ElfFunctions.WriteExport ();
>
> + }
>
> +
>
> //
>
> // Make sure image size is correct before returning the new image.
>
> //
>
> diff --git a/BaseTools/Source/C/GenFw/ElfConvert.h
> b/BaseTools/Source/C/GenFw/ElfConvert.h
> index 801e8de4a2..6ab4605227 100644
> --- a/BaseTools/Source/C/GenFw/ElfConvert.h
> +++ b/BaseTools/Source/C/GenFw/ElfConvert.h
> @@ -24,6 +24,7 @@ extern UINT8 *mCoffFile;
> extern UINT32 mTableOffset;
>
> extern UINT32 mOutImageType;
>
> extern UINT32 mFileBufferSize;
>
> +extern BOOLEAN mExportFlag;
>
>
>
> //
>
> // Common EFI specific data.
>
> @@ -31,6 +32,44 @@ extern UINT32 mFileBufferSize;
> #define ELF_HII_SECTION_NAME ".hii"
>
> #define ELF_STRTAB_SECTION_NAME ".strtab"
>
> #define MAX_COFF_ALIGNMENT 0x10000
>
> +#define ELF_SYMBOL_SECTION_NAME ".symtab"
>
> +
>
> +//
>
> +// Platform Runtime Mechanism (PRM) specific data.
>
> +//
>
> +#define PRM_MODULE_EXPORT_SYMBOL_NUM 256
>
> +
>
> +// <to-do> to include PRM header directly once PrmPkg is in main repo
>
> +#define PRM_HANDLER_NAME_MAXIMUM_LENGTH 128
>
> +
>
> +#define PRM_MODULE_EXPORT_DESCRIPTOR_NAME
> "PrmModuleExportDescriptor"
>
> +#define PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE
> SIGNATURE_64 ('P', 'R', 'M', '_', 'M', 'E', 'D', 'T')
>
> +#define PRM_MODULE_EXPORT_REVISION 0x0
>
> +
>
> +//
>
> +// Platform Runtime Mechanism (PRM) Export Descriptor Structures
>
> +//
>
> +#pragma pack(push, 1)
>
> +
>
> +typedef struct {
>
> + EFI_GUID PrmHandlerGuid;
>
> + CHAR8
> PrmHandlerName[PRM_HANDLER_NAME_MAXIMUM_LENGTH];
>
> +} PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT;
>
> +
>
> +typedef struct {
>
> + UINT64 Signature;
>
> + UINT16 Revision;
>
> + UINT16 NumberPrmHandlers;
>
> + EFI_GUID PlatformGuid;
>
> + EFI_GUID ModuleGuid;
>
> +} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER;
>
> +
>
> +typedef struct {
>
> + PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER Header;
>
> + PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT
> PrmHandlerExportDescriptors[1];
>
> +} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT;
>
> +
>
> +#pragma pack(pop)
>
>
>
> //
>
> // Filter Types
>
> @@ -38,7 +77,8 @@ extern UINT32 mFileBufferSize;
> typedef enum {
>
> SECTION_TEXT,
>
> SECTION_HII,
>
> - SECTION_DATA
>
> + SECTION_DATA,
>
> + SECTION_SYMBOL
>
>
>
> } SECTION_FILTER_TYPES;
>
>
>
> @@ -50,6 +90,7 @@ typedef struct {
> BOOLEAN (*WriteSections) (SECTION_FILTER_TYPES FilterType);
>
> VOID (*WriteRelocations) ();
>
> VOID (*WriteDebug) ();
>
> + VOID (*WriteExport) ();
>
> VOID (*SetImageSize) ();
>
> VOID (*CleanUp) ();
>
>
>
> diff --git a/BaseTools/Source/C/GenFw/GenFw.c
> b/BaseTools/Source/C/GenFw/GenFw.c
> index 8cab70ba4d..6f61f16788 100644
> --- a/BaseTools/Source/C/GenFw/GenFw.c
> +++ b/BaseTools/Source/C/GenFw/GenFw.c
> @@ -87,7 +87,7 @@ UINT32 mImageTimeStamp = 0;
> UINT32 mImageSize = 0;
>
> UINT32 mOutImageType = FW_DUMMY_IMAGE;
>
> BOOLEAN mIsConvertXip = FALSE;
>
> -
>
> +BOOLEAN mExportFlag = FALSE;
>
>
>
> STATIC
>
> EFI_STATUS
>
> @@ -279,6 +279,10 @@ Returns:
> except for -o or -r option. It is a action
> option.\n\
>
> If it is combined with other action options, the
> later\n\
>
> input action option will override the previous
> one.\n");
>
> + fprintf (stdout, " --prm Scan symbol section from
> ELF image and \n\
>
> + write export table into PE-COFF.\n\
>
> + This option can be used together with -e.\n\
>
> + It doesn't work for other options.\n");
>
> fprintf (stdout, " -v, --verbose Turn on verbose output with
> informational messages.\n");
>
> fprintf (stdout, " -q, --quiet Disable all messages except
key
> message and fatal error\n");
>
> fprintf (stdout, " -d, --debug level Enable debug messages, at
input
> debug level.\n");
>
> @@ -1436,6 +1440,20 @@ Returns:
> continue;
>
> }
>
>
>
> + if (stricmp (argv[0], "--prm") == 0) {
>
> + if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") != 0 ){
>
> + Error (NULL, 0, 1001, "Invalid", "--prm option only supports DXE
> RUNTIME driver.");
>
> + goto Finish;
>
> + }
>
> +
>
> + if (!mExportFlag) {
>
> + mExportFlag = TRUE;
>
> + }
>
> + argc --;
>
> + argv ++;
>
> + continue;
>
> + }
>
> +
>
> if (argv[0][0] == '-') {
>
> Error (NULL, 0, 1000, "Unknown option", argv[0]);
>
> goto Finish;
>
> diff --git a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
> b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
> index f17b8ee19b..21c968e650 100644
> --- a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
> +++ b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
> @@ -571,6 +571,13 @@ typedef struct {
> UINT32 AddressOfNameOrdinals;
>
> } EFI_IMAGE_EXPORT_DIRECTORY;
>
>
>
> +//
>
> +// Based export types.
>
> +//
>
> +#define EFI_IMAGE_EXPORT_ORDINAL_BASE 1
>
> +#define EFI_IMAGE_EXPORT_ADDR_SIZE 4
>
> +#define EFI_IMAGE_EXPORT_ORDINAL_SIZE 2
>
> +
>
> ///
>
> /// DLL support.
>
> /// Import Format
>
> --
> 2.26.2.windows.1
>
>
>
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> View/Reply Online (#87040): https://edk2.groups.io/g/devel/message/87040
> Mute This Topic: https://groups.io/mt/89441499/4905953
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub
> [gaoliming@byosoft.com.cn]
> -=-=-=-=-=-=
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support PRM GCC build
2022-03-01 1:51 ` 回复: " gaoliming
@ 2022-03-14 3:02 ` Huang, Li-Xia
0 siblings, 0 replies; 6+ messages in thread
From: Huang, Li-Xia @ 2022-03-14 3:02 UTC (permalink / raw)
To: devel@edk2.groups.io, Gao, Liming; +Cc: Feng, Bob C, Chen, Christine
Hi Liming,
BZ link is added.
PRM option currently only supports DXE RUNTIME driver and X64 arch, GenFw will report error message if PRM option is specified for other arch or other module type.
Thanks.
Regards,
Lisa
-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of gaoliming
Sent: 2022年3月1日 9:52
To: devel@edk2.groups.io; Huang, Li-Xia <lisa.huang@intel.com>
Cc: Feng, Bob C <bob.c.feng@intel.com>; Chen, Christine <yuwei.chen@intel.com>
Subject: 回复: [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support PRM GCC build
Lisa:
Please add BZ link for this patch.
And, if PRM option currently only supports DXE RUNTIME driver and X64 arch,
does GenFw report error message if PRM option is specified for other arch or other module type?
Thanks
Liming
> -----邮件原件-----
> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Huang, Li-Xia
> 发送时间: 2022年2月28日 9:14
> 收件人: devel@edk2.groups.io
> 抄送: Lixia Huang <lisa.huang@intel.com>; Liming Gao
> <gaoliming@byosoft.com.cn>; Bob Feng <bob.c.feng@intel.com>; Yuwei
> Chen <yuwei.chen@intel.com>
> 主题: [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support
> PRM GCC build
>
> Since PRM module needs to support export table in PE-COFF, we'll
> enhance GenFw tool to support this.
>
> Add one export flag in GenFw tool. If export flag is set:
> Step1: Scan ELF symbol table based on PRM module descriptor to get
> descriptor offset address;
> Step2: Find PRM handlers number and name in COFF file based on the
> address from step1;
> Step3: Write PRM info such as handler name and export RVA into COFF
> export table.
>
> PRM option currently only supports DXE RUNTIME driver and X64 arch.
>
> Change-Id: I479b7c8b23beea12b5c567677688aef6f7af2085
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Bob Feng <bob.c.feng@intel.com>
> Cc: Yuwei Chen <yuwei.chen@intel.com>
> Signed-off-by: Lixia Huang <lisa.huang@intel.com>
> ---
> BaseTools/Source/C/GenFw/Elf64Convert.c | 242
> +++++++++++++++++-
> BaseTools/Source/C/GenFw/ElfConvert.c | 8 +
> BaseTools/Source/C/GenFw/ElfConvert.h | 43 +++-
> BaseTools/Source/C/GenFw/GenFw.c | 20 +-
> .../C/Include/IndustryStandard/PeImage.h | 7 +
> 5 files changed, 315 insertions(+), 5 deletions(-)
>
> diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c
> b/BaseTools/Source/C/GenFw/Elf64Convert.c
> index 0bb3ead228..2aa9bfcc94 100644
> --- a/BaseTools/Source/C/GenFw/Elf64Convert.c
> +++ b/BaseTools/Source/C/GenFw/Elf64Convert.c
> @@ -56,6 +56,12 @@ WriteDebug64 (
> VOID
>
> );
>
>
>
> +STATIC
>
> +VOID
>
> +WriteExport64 (
>
> + VOID
>
> + );
>
> +
>
> STATIC
>
> VOID
>
> SetImageSize64 (
>
> @@ -106,7 +112,7 @@ STATIC UINT32 mCoffAlignment = 0x20; //
>
> // PE section alignment.
>
> //
>
> -STATIC const UINT16 mCoffNbrSections = 4;
>
> +STATIC UINT16 mCoffNbrSections = 4;
>
>
>
> //
>
> // ELF sections to offset in Coff file.
>
> @@ -122,7 +128,7 @@ STATIC UINT32 mDataOffset; STATIC UINT32
> mHiiRsrcOffset;
>
> STATIC UINT32 mRelocOffset;
>
> STATIC UINT32 mDebugOffset;
>
> -
>
> +STATIC UINT32 mExportOffset;
>
> //
>
> // Used for RISC-V relocations.
>
> //
>
> @@ -132,6 +138,14 @@ STATIC Elf64_Half mRiscVPass1SymSecIndex = 0;
> STATIC INT32 mRiscVPass1Offset;
>
> STATIC INT32 mRiscVPass1GotFixup;
>
>
>
> +//
>
> +// Used for Export section.
>
> +//
>
> +STATIC UINT32 mExportSize;
>
> +STATIC UINT32
> mExportRVA[PRM_MODULE_EXPORT_SYMBOL_NUM];
>
> +STATIC UINT32 mExportSymNum;
>
> +STATIC CHAR8
> mExportSymName[PRM_MODULE_EXPORT_SYMBOL_NUM][PRM_HANDLE
> R_NAME_MAXIMUM_LENGTH];
>
> +
>
> //
>
> // Initialization Function
>
> //
>
> @@ -171,6 +185,13 @@ InitializeElf64 (
> return FALSE;
>
> }
>
>
>
> + if (mExportFlag) {
>
> + if (mEhdr->e_machine != EM_X86_64) {
>
> + Error (NULL, 0, 3000, "Unsupported", "--prm option currently
> + only
> supports X64 arch.");
>
> + return FALSE;
>
> + }
>
> + }
>
> +
>
> //
>
> // Update section header pointers
>
> //
>
> @@ -200,6 +221,11 @@ InitializeElf64 (
> ElfFunctions->SetImageSize = SetImageSize64;
>
> ElfFunctions->CleanUp = CleanUp64;
>
>
>
> + if (mExportFlag) {
>
> + mCoffNbrSections ++;
>
> + ElfFunctions->WriteExport = WriteExport64;
>
> + }
>
> +
>
> return TRUE;
>
> }
>
>
>
> @@ -263,6 +289,17 @@ IsHiiRsrcShdr (
> return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset +
> Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);
>
> }
>
>
>
> +STATIC
>
> +BOOLEAN
>
> +IsSymbolShdr (
>
> + Elf_Shdr *Shdr
>
> + )
>
> +{
>
> + Elf_Shdr *Namehdr = GetShdrByIndex(mEhdr->e_shstrndx);
>
> +
>
> + return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namehdr->sh_offset +
> Shdr->sh_name, ELF_SYMBOL_SECTION_NAME) == 0);
>
> +}
>
> +
>
> STATIC
>
> BOOLEAN
>
> IsDataShdr (
>
> @@ -335,6 +372,37 @@ GetSymName (
> return StrtabContents + Sym->st_name;
>
> }
>
>
>
> +//
>
> +// Get Prm Handler number and name
>
> +//
>
> +STATIC
>
> +VOID
>
> +FindPrmHandler (
>
> + UINT64 Offset
>
> + )
>
> +{
>
> + PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER *PrmExport;
>
> + PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT *PrmHandler;
>
> + UINT32 HandlerNum;
>
> +
>
> + PrmExport =
> (PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER*)((UINT8*)mEhdr
> + Offset);
>
> + PrmHandler = (PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT
> *)(PrmExport + 1);
>
> +
>
> + for (HandlerNum = 0; HandlerNum < PrmExport->NumberPrmHandlers;
> HandlerNum++) {
>
> + strcpy(mExportSymName[mExportSymNum],
> PrmHandler->PrmHandlerName);
>
> + mExportSymNum ++;
>
> + PrmHandler += 1;
>
> +
>
> + //
>
> + // Check if PRM handler number is larger than
> (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)
>
> + //
>
> + if (mExportSymNum >= (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)) {
>
> + Error (NULL, 0, 3000, "Invalid", "FindPrmHandler: Number %u is
> + too
> high.", mExportSymNum);
>
> + exit(EXIT_FAILURE);
>
> + }
>
> + }
>
> +}
>
> +
>
> //
>
> // Find the ELF section hosting the GOT from an ELF Rva
>
> // of a single GOT entry. Normally, GOT is placed in
>
> @@ -717,6 +785,7 @@ ScanSections64 (
> UINT32 CoffEntry;
>
> UINT32 SectionCount;
>
> BOOLEAN FoundSection;
>
> + UINT32 Offset;
>
>
>
> CoffEntry = 0;
>
> mCoffOffset = 0;
>
> @@ -880,6 +949,82 @@ ScanSections64 (
> Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged
> into 1 data section. Source level debug might not work correctly.",
mInImageName);
>
> }
>
>
>
> + //
>
> + // The Symbol sections.
>
> + //
>
> + if (mExportFlag) {
>
> + UINT32 SymIndex;
>
> + Elf_Sym *Sym;
>
> + UINT64 SymNum;
>
> + const UINT8 *SymName;
>
> +
>
> + mExportOffset = mCoffOffset;
>
> + mExportSize = sizeof(EFI_IMAGE_EXPORT_DIRECTORY) +
> strlen(mInImageName) + 1;
>
> +
>
> + for (i = 0; i < mEhdr->e_shnum; i++) {
>
> +
>
> + //
>
> + // Determine if this is a symbol section.
>
> + //
>
> + Elf_Shdr *shdr = GetShdrByIndex(i);
>
> + if (!IsSymbolShdr(shdr)) {
>
> + continue;
>
> + }
>
> +
>
> + UINT8 *Symtab = (UINT8*)mEhdr + shdr->sh_offset;
>
> + SymNum = (shdr->sh_size) / (shdr->sh_entsize);
>
> +
>
> + //
>
> + // First Get PrmModuleExportDescriptor
>
> + //
>
> + for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
>
> + Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
>
> + SymName = GetSymName(Sym);
>
> + if (SymName == NULL) {
>
> + continue;
>
> + }
>
> +
>
> + if (strcmp((CHAR8*)SymName,
> PRM_MODULE_EXPORT_DESCRIPTOR_NAME) == 0) {
>
> + //
>
> + // Find PrmHandler Number and Name
>
> + //
>
> + FindPrmHandler(Sym->st_value);
>
> +
>
> + strcpy(mExportSymName[mExportSymNum],
> (CHAR8*)SymName);
>
> + mExportRVA[mExportSymNum] = (UINT32)(Sym->st_value);
>
> + mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE +
> EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
>
> + mExportSymNum ++;
>
> + break;
>
> + }
>
> + }
>
> +
>
> + //
>
> + // Second Get PrmHandler
>
> + //
>
> + for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
>
> + UINT32 ExpIndex;
>
> + Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
>
> + SymName = GetSymName(Sym);
>
> + if (SymName == NULL) {
>
> + continue;
>
> + }
>
> +
>
> + for (ExpIndex = 0; ExpIndex < (mExportSymNum -1); ExpIndex++)
> + {
>
> + if (strcmp((CHAR8*)SymName, mExportSymName[ExpIndex]) !=
> 0) {
>
> + continue;
>
> + }
>
> + mExportRVA[ExpIndex] = (UINT32)(Sym->st_value);
>
> + mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE +
> EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
>
> + }
>
> + }
>
> +
>
> + break;
>
> + }
>
> +
>
> + mCoffOffset += mExportSize;
>
> + mCoffOffset = CoffAlign(mCoffOffset);
>
> + }
>
> +
>
> //
>
> // The HII resource sections.
>
> //
>
> @@ -989,8 +1134,17 @@ ScanSections64 (
> NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
>
> }
>
>
>
> + //
>
> + // If found symbol, add edata section between data and rsrc section
>
> + //
>
> + if(mExportFlag) {
>
> + Offset = mExportOffset;
>
> + } else {
>
> + Offset = mHiiRsrcOffset;
>
> + }
>
> +
>
> if ((mHiiRsrcOffset - mDataOffset) > 0) {
>
> - CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset -
> mDataOffset,
>
> + CreateSectionHeader (".data", mDataOffset, Offset - mDataOffset,
>
> EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
>
> | EFI_IMAGE_SCN_MEM_WRITE
>
> | EFI_IMAGE_SCN_MEM_READ);
>
> @@ -999,6 +1153,20 @@ ScanSections64 (
> NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
>
> }
>
>
>
> + if(mExportFlag) {
>
> + if ((mHiiRsrcOffset - mExportOffset) > 0) {
>
> + CreateSectionHeader (".edata", mExportOffset, mHiiRsrcOffset -
> mExportOffset,
>
> + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
>
> + | EFI_IMAGE_SCN_MEM_READ);
>
> +
> NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_EN
> TRY_EXPORT].Size = mHiiRsrcOffset - mExportOffset;
>
> +
> NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_EN
> TRY_EXPORT].VirtualAddress = mExportOffset;
>
> +
>
> + } else {
>
> + // Don't make a section of size 0.
>
> + NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
>
> + }
>
> + }
>
> +
>
> if ((mRelocOffset - mHiiRsrcOffset) > 0) {
>
> CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset -
> mHiiRsrcOffset,
>
> EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
>
> @@ -1757,4 +1925,72 @@ CleanUp64 (
> }
>
> }
>
>
>
> +STATIC
>
> +VOID
>
> +WriteExport64 (
>
> + VOID
>
> + )
>
> +{
>
> + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
>
> + EFI_IMAGE_EXPORT_DIRECTORY *ExportDir;
>
> + EFI_IMAGE_DATA_DIRECTORY *DataDir;
>
> + UINT32 FileNameOffset;
>
> + UINT32 NameOffset;
>
> + UINT16 Index;
>
> + UINT8 *Tdata = NULL;
>
> +
>
> + ExportDir = (EFI_IMAGE_EXPORT_DIRECTORY*)(mCoffFile +
> mExportOffset);
>
> + ExportDir->Characteristics = 0;
>
> + ExportDir->TimeDateStamp = 0;
>
> + ExportDir->MajorVersion = 0;
>
> + ExportDir->MinorVersion =0;
>
> + ExportDir->Name = 0;
>
> + ExportDir->NumberOfFunctions = mExportSymNum;
>
> + ExportDir->NumberOfNames = mExportSymNum;
>
> + ExportDir->Base = EFI_IMAGE_EXPORT_ORDINAL_BASE;
>
> + ExportDir->AddressOfFunctions = mExportOffset +
> sizeof(EFI_IMAGE_EXPORT_DIRECTORY);
>
> + ExportDir->AddressOfNames = ExportDir->AddressOfFunctions +
> EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;
>
> + ExportDir->AddressOfNameOrdinals = ExportDir->AddressOfNames +
> EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;
>
> +
>
> + FileNameOffset = ExportDir->AddressOfNameOrdinals +
> EFI_IMAGE_EXPORT_ORDINAL_SIZE * mExportSymNum;
>
> + NameOffset = FileNameOffset + strlen(mInImageName) + 1;
>
> +
>
> + // Write Input image Name RVA
>
> + ExportDir->Name = FileNameOffset;
>
> +
>
> + // Write Input image Name
>
> + strcpy((char *)(mCoffFile + FileNameOffset), mInImageName);
>
> +
>
> + for (Index = 0; Index < mExportSymNum; Index++) {
>
> + //
>
> + // Write Export Address Table
>
> + //
>
> + Tdata = mCoffFile + ExportDir->AddressOfFunctions + Index *
> EFI_IMAGE_EXPORT_ADDR_SIZE;
>
> + *(UINT32 *)Tdata = mExportRVA[Index];
>
> +
>
> + //
>
> + // Write Export Name Pointer Table
>
> + //
>
> + Tdata = mCoffFile + ExportDir->AddressOfNames + Index *
> EFI_IMAGE_EXPORT_ADDR_SIZE;
>
> + *(UINT32 *)Tdata = NameOffset;
>
> +
>
> + //
>
> + // Write Export Ordinal table
>
> + //
>
> + Tdata = mCoffFile + ExportDir->AddressOfNameOrdinals + Index *
> EFI_IMAGE_EXPORT_ORDINAL_SIZE;
>
> + *(UINT16 *)Tdata = Index;
>
> +
>
> + //
>
> + // Write Export Name Table
>
> + //
>
> + strcpy((char *)(mCoffFile + NameOffset), mExportSymName[Index]);
>
> + NameOffset += strlen(mExportSymName[Index]) + 1;
>
> + }
>
> +
>
> + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile +
> mNtHdrOffset);
>
> + DataDir =
> &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_E
> NTRY_EXPORT];
>
> + DataDir->VirtualAddress = mExportOffset;
>
> + DataDir->Size = mExportSize;
>
> +
>
> +}
>
>
>
> diff --git a/BaseTools/Source/C/GenFw/ElfConvert.c
> b/BaseTools/Source/C/GenFw/ElfConvert.c
> index 7db8721167..be98544056 100644
> --- a/BaseTools/Source/C/GenFw/ElfConvert.c
> +++ b/BaseTools/Source/C/GenFw/ElfConvert.c
> @@ -223,6 +223,14 @@ ConvertElf (
> VerboseMsg ("Write debug info.");
>
> ElfFunctions.WriteDebug ();
>
>
>
> + //
>
> + // For PRM Driver to Write export info.
>
> + //
>
> + if (mExportFlag) {
>
> + VerboseMsg ("Write export info.");
>
> + ElfFunctions.WriteExport ();
>
> + }
>
> +
>
> //
>
> // Make sure image size is correct before returning the new image.
>
> //
>
> diff --git a/BaseTools/Source/C/GenFw/ElfConvert.h
> b/BaseTools/Source/C/GenFw/ElfConvert.h
> index 801e8de4a2..6ab4605227 100644
> --- a/BaseTools/Source/C/GenFw/ElfConvert.h
> +++ b/BaseTools/Source/C/GenFw/ElfConvert.h
> @@ -24,6 +24,7 @@ extern UINT8 *mCoffFile; extern UINT32
> mTableOffset;
>
> extern UINT32 mOutImageType;
>
> extern UINT32 mFileBufferSize;
>
> +extern BOOLEAN mExportFlag;
>
>
>
> //
>
> // Common EFI specific data.
>
> @@ -31,6 +32,44 @@ extern UINT32 mFileBufferSize; #define
> ELF_HII_SECTION_NAME ".hii"
>
> #define ELF_STRTAB_SECTION_NAME ".strtab"
>
> #define MAX_COFF_ALIGNMENT 0x10000
>
> +#define ELF_SYMBOL_SECTION_NAME ".symtab"
>
> +
>
> +//
>
> +// Platform Runtime Mechanism (PRM) specific data.
>
> +//
>
> +#define PRM_MODULE_EXPORT_SYMBOL_NUM 256
>
> +
>
> +// <to-do> to include PRM header directly once PrmPkg is in main repo
>
> +#define PRM_HANDLER_NAME_MAXIMUM_LENGTH 128
>
> +
>
> +#define PRM_MODULE_EXPORT_DESCRIPTOR_NAME
> "PrmModuleExportDescriptor"
>
> +#define PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE
> SIGNATURE_64 ('P', 'R', 'M', '_', 'M', 'E', 'D', 'T')
>
> +#define PRM_MODULE_EXPORT_REVISION 0x0
>
> +
>
> +//
>
> +// Platform Runtime Mechanism (PRM) Export Descriptor Structures
>
> +//
>
> +#pragma pack(push, 1)
>
> +
>
> +typedef struct {
>
> + EFI_GUID PrmHandlerGuid;
>
> + CHAR8
> PrmHandlerName[PRM_HANDLER_NAME_MAXIMUM_LENGTH];
>
> +} PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT;
>
> +
>
> +typedef struct {
>
> + UINT64 Signature;
>
> + UINT16 Revision;
>
> + UINT16 NumberPrmHandlers;
>
> + EFI_GUID PlatformGuid;
>
> + EFI_GUID ModuleGuid;
>
> +} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER;
>
> +
>
> +typedef struct {
>
> + PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER Header;
>
> + PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT
> PrmHandlerExportDescriptors[1];
>
> +} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT;
>
> +
>
> +#pragma pack(pop)
>
>
>
> //
>
> // Filter Types
>
> @@ -38,7 +77,8 @@ extern UINT32 mFileBufferSize; typedef enum {
>
> SECTION_TEXT,
>
> SECTION_HII,
>
> - SECTION_DATA
>
> + SECTION_DATA,
>
> + SECTION_SYMBOL
>
>
>
> } SECTION_FILTER_TYPES;
>
>
>
> @@ -50,6 +90,7 @@ typedef struct {
> BOOLEAN (*WriteSections) (SECTION_FILTER_TYPES FilterType);
>
> VOID (*WriteRelocations) ();
>
> VOID (*WriteDebug) ();
>
> + VOID (*WriteExport) ();
>
> VOID (*SetImageSize) ();
>
> VOID (*CleanUp) ();
>
>
>
> diff --git a/BaseTools/Source/C/GenFw/GenFw.c
> b/BaseTools/Source/C/GenFw/GenFw.c
> index 8cab70ba4d..6f61f16788 100644
> --- a/BaseTools/Source/C/GenFw/GenFw.c
> +++ b/BaseTools/Source/C/GenFw/GenFw.c
> @@ -87,7 +87,7 @@ UINT32 mImageTimeStamp = 0;
> UINT32 mImageSize = 0;
>
> UINT32 mOutImageType = FW_DUMMY_IMAGE;
>
> BOOLEAN mIsConvertXip = FALSE;
>
> -
>
> +BOOLEAN mExportFlag = FALSE;
>
>
>
> STATIC
>
> EFI_STATUS
>
> @@ -279,6 +279,10 @@ Returns:
> except for -o or -r option. It is a action
> option.\n\
>
> If it is combined with other action options,
> the later\n\
>
> input action option will override the
> previous one.\n");
>
> + fprintf (stdout, " --prm Scan symbol section from
> ELF image and \n\
>
> + write export table into PE-COFF.\n\
>
> + This option can be used together with -e.\n\
>
> + It doesn't work for other options.\n");
>
> fprintf (stdout, " -v, --verbose Turn on verbose output with
> informational messages.\n");
>
> fprintf (stdout, " -q, --quiet Disable all messages except
key
> message and fatal error\n");
>
> fprintf (stdout, " -d, --debug level Enable debug messages, at
input
> debug level.\n");
>
> @@ -1436,6 +1440,20 @@ Returns:
> continue;
>
> }
>
>
>
> + if (stricmp (argv[0], "--prm") == 0) {
>
> + if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") != 0 ){
>
> + Error (NULL, 0, 1001, "Invalid", "--prm option only supports
> + DXE
> RUNTIME driver.");
>
> + goto Finish;
>
> + }
>
> +
>
> + if (!mExportFlag) {
>
> + mExportFlag = TRUE;
>
> + }
>
> + argc --;
>
> + argv ++;
>
> + continue;
>
> + }
>
> +
>
> if (argv[0][0] == '-') {
>
> Error (NULL, 0, 1000, "Unknown option", argv[0]);
>
> goto Finish;
>
> diff --git a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
> b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
> index f17b8ee19b..21c968e650 100644
> --- a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
> +++ b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
> @@ -571,6 +571,13 @@ typedef struct {
> UINT32 AddressOfNameOrdinals;
>
> } EFI_IMAGE_EXPORT_DIRECTORY;
>
>
>
> +//
>
> +// Based export types.
>
> +//
>
> +#define EFI_IMAGE_EXPORT_ORDINAL_BASE 1
>
> +#define EFI_IMAGE_EXPORT_ADDR_SIZE 4
>
> +#define EFI_IMAGE_EXPORT_ORDINAL_SIZE 2
>
> +
>
> ///
>
> /// DLL support.
>
> /// Import Format
>
> --
> 2.26.2.windows.1
>
>
>
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> View/Reply Online (#87040):
> https://edk2.groups.io/g/devel/message/87040
> Mute This Topic: https://groups.io/mt/89441499/4905953
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub
> [gaoliming@byosoft.com.cn]
> -=-=-=-=-=-=
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support PRM GCC build
@ 2022-03-14 5:27 Huang, Li-Xia
2022-03-14 6:44 ` Bob Feng
[not found] ` <16DC2C4DB8F2565E.23528@groups.io>
0 siblings, 2 replies; 6+ messages in thread
From: Huang, Li-Xia @ 2022-03-14 5:27 UTC (permalink / raw)
To: devel; +Cc: Lixia Huang, Liming Gao, Bob Feng, Yuwei Chen
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3802
Since PRM module needs to support export table in PE-COFF, we'll
enhance GenFw tool to support this.
Add one export flag in GenFw tool. If export flag is set:
Step1: Scan ELF symbol table based on PRM module descriptor to get
descriptor offset address;
Step2: Find PRM handlers number and name in COFF file based on the
address from step1;
Step3: Write PRM info such as handler name and export RVA into COFF
export table.
PRM option currently only supports DXE RUNTIME driver and X64 arch.
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Yuwei Chen <yuwei.chen@intel.com>
Signed-off-by: Lixia Huang <lisa.huang@intel.com>
---
BaseTools/Source/C/GenFw/Elf64Convert.c | 242 +++++++++++++++++-
BaseTools/Source/C/GenFw/ElfConvert.c | 8 +
BaseTools/Source/C/GenFw/ElfConvert.h | 43 +++-
BaseTools/Source/C/GenFw/GenFw.c | 20 +-
.../C/Include/IndustryStandard/PeImage.h | 7 +
5 files changed, 315 insertions(+), 5 deletions(-)
diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c b/BaseTools/Source/C/GenFw/Elf64Convert.c
index 0bb3ead228..2aa9bfcc94 100644
--- a/BaseTools/Source/C/GenFw/Elf64Convert.c
+++ b/BaseTools/Source/C/GenFw/Elf64Convert.c
@@ -56,6 +56,12 @@ WriteDebug64 (
VOID
);
+STATIC
+VOID
+WriteExport64 (
+ VOID
+ );
+
STATIC
VOID
SetImageSize64 (
@@ -106,7 +112,7 @@ STATIC UINT32 mCoffAlignment = 0x20;
//
// PE section alignment.
//
-STATIC const UINT16 mCoffNbrSections = 4;
+STATIC UINT16 mCoffNbrSections = 4;
//
// ELF sections to offset in Coff file.
@@ -122,7 +128,7 @@ STATIC UINT32 mDataOffset;
STATIC UINT32 mHiiRsrcOffset;
STATIC UINT32 mRelocOffset;
STATIC UINT32 mDebugOffset;
-
+STATIC UINT32 mExportOffset;
//
// Used for RISC-V relocations.
//
@@ -132,6 +138,14 @@ STATIC Elf64_Half mRiscVPass1SymSecIndex = 0;
STATIC INT32 mRiscVPass1Offset;
STATIC INT32 mRiscVPass1GotFixup;
+//
+// Used for Export section.
+//
+STATIC UINT32 mExportSize;
+STATIC UINT32 mExportRVA[PRM_MODULE_EXPORT_SYMBOL_NUM];
+STATIC UINT32 mExportSymNum;
+STATIC CHAR8 mExportSymName[PRM_MODULE_EXPORT_SYMBOL_NUM][PRM_HANDLER_NAME_MAXIMUM_LENGTH];
+
//
// Initialization Function
//
@@ -171,6 +185,13 @@ InitializeElf64 (
return FALSE;
}
+ if (mExportFlag) {
+ if (mEhdr->e_machine != EM_X86_64) {
+ Error (NULL, 0, 3000, "Unsupported", "--prm option currently only supports X64 arch.");
+ return FALSE;
+ }
+ }
+
//
// Update section header pointers
//
@@ -200,6 +221,11 @@ InitializeElf64 (
ElfFunctions->SetImageSize = SetImageSize64;
ElfFunctions->CleanUp = CleanUp64;
+ if (mExportFlag) {
+ mCoffNbrSections ++;
+ ElfFunctions->WriteExport = WriteExport64;
+ }
+
return TRUE;
}
@@ -263,6 +289,17 @@ IsHiiRsrcShdr (
return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);
}
+STATIC
+BOOLEAN
+IsSymbolShdr (
+ Elf_Shdr *Shdr
+ )
+{
+ Elf_Shdr *Namehdr = GetShdrByIndex(mEhdr->e_shstrndx);
+
+ return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namehdr->sh_offset + Shdr->sh_name, ELF_SYMBOL_SECTION_NAME) == 0);
+}
+
STATIC
BOOLEAN
IsDataShdr (
@@ -335,6 +372,37 @@ GetSymName (
return StrtabContents + Sym->st_name;
}
+//
+// Get Prm Handler number and name
+//
+STATIC
+VOID
+FindPrmHandler (
+ UINT64 Offset
+ )
+{
+ PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER *PrmExport;
+ PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT *PrmHandler;
+ UINT32 HandlerNum;
+
+ PrmExport = (PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER*)((UINT8*)mEhdr + Offset);
+ PrmHandler = (PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT *)(PrmExport + 1);
+
+ for (HandlerNum = 0; HandlerNum < PrmExport->NumberPrmHandlers; HandlerNum++) {
+ strcpy(mExportSymName[mExportSymNum], PrmHandler->PrmHandlerName);
+ mExportSymNum ++;
+ PrmHandler += 1;
+
+ //
+ // Check if PRM handler number is larger than (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)
+ //
+ if (mExportSymNum >= (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)) {
+ Error (NULL, 0, 3000, "Invalid", "FindPrmHandler: Number %u is too high.", mExportSymNum);
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
//
// Find the ELF section hosting the GOT from an ELF Rva
// of a single GOT entry. Normally, GOT is placed in
@@ -717,6 +785,7 @@ ScanSections64 (
UINT32 CoffEntry;
UINT32 SectionCount;
BOOLEAN FoundSection;
+ UINT32 Offset;
CoffEntry = 0;
mCoffOffset = 0;
@@ -880,6 +949,82 @@ ScanSections64 (
Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName);
}
+ //
+ // The Symbol sections.
+ //
+ if (mExportFlag) {
+ UINT32 SymIndex;
+ Elf_Sym *Sym;
+ UINT64 SymNum;
+ const UINT8 *SymName;
+
+ mExportOffset = mCoffOffset;
+ mExportSize = sizeof(EFI_IMAGE_EXPORT_DIRECTORY) + strlen(mInImageName) + 1;
+
+ for (i = 0; i < mEhdr->e_shnum; i++) {
+
+ //
+ // Determine if this is a symbol section.
+ //
+ Elf_Shdr *shdr = GetShdrByIndex(i);
+ if (!IsSymbolShdr(shdr)) {
+ continue;
+ }
+
+ UINT8 *Symtab = (UINT8*)mEhdr + shdr->sh_offset;
+ SymNum = (shdr->sh_size) / (shdr->sh_entsize);
+
+ //
+ // First Get PrmModuleExportDescriptor
+ //
+ for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
+ Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
+ SymName = GetSymName(Sym);
+ if (SymName == NULL) {
+ continue;
+ }
+
+ if (strcmp((CHAR8*)SymName, PRM_MODULE_EXPORT_DESCRIPTOR_NAME) == 0) {
+ //
+ // Find PrmHandler Number and Name
+ //
+ FindPrmHandler(Sym->st_value);
+
+ strcpy(mExportSymName[mExportSymNum], (CHAR8*)SymName);
+ mExportRVA[mExportSymNum] = (UINT32)(Sym->st_value);
+ mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
+ mExportSymNum ++;
+ break;
+ }
+ }
+
+ //
+ // Second Get PrmHandler
+ //
+ for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {
+ UINT32 ExpIndex;
+ Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);
+ SymName = GetSymName(Sym);
+ if (SymName == NULL) {
+ continue;
+ }
+
+ for (ExpIndex = 0; ExpIndex < (mExportSymNum -1); ExpIndex++) {
+ if (strcmp((CHAR8*)SymName, mExportSymName[ExpIndex]) != 0) {
+ continue;
+ }
+ mExportRVA[ExpIndex] = (UINT32)(Sym->st_value);
+ mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;
+ }
+ }
+
+ break;
+ }
+
+ mCoffOffset += mExportSize;
+ mCoffOffset = CoffAlign(mCoffOffset);
+ }
+
//
// The HII resource sections.
//
@@ -989,8 +1134,17 @@ ScanSections64 (
NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
}
+ //
+ // If found symbol, add edata section between data and rsrc section
+ //
+ if(mExportFlag) {
+ Offset = mExportOffset;
+ } else {
+ Offset = mHiiRsrcOffset;
+ }
+
if ((mHiiRsrcOffset - mDataOffset) > 0) {
- CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset,
+ CreateSectionHeader (".data", mDataOffset, Offset - mDataOffset,
EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
| EFI_IMAGE_SCN_MEM_WRITE
| EFI_IMAGE_SCN_MEM_READ);
@@ -999,6 +1153,20 @@ ScanSections64 (
NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
}
+ if(mExportFlag) {
+ if ((mHiiRsrcOffset - mExportOffset) > 0) {
+ CreateSectionHeader (".edata", mExportOffset, mHiiRsrcOffset - mExportOffset,
+ EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
+ | EFI_IMAGE_SCN_MEM_READ);
+ NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size = mHiiRsrcOffset - mExportOffset;
+ NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = mExportOffset;
+
+ } else {
+ // Don't make a section of size 0.
+ NtHdr->Pe32Plus.FileHeader.NumberOfSections--;
+ }
+ }
+
if ((mRelocOffset - mHiiRsrcOffset) > 0) {
CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset,
EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
@@ -1757,4 +1925,72 @@ CleanUp64 (
}
}
+STATIC
+VOID
+WriteExport64 (
+ VOID
+ )
+{
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
+ EFI_IMAGE_EXPORT_DIRECTORY *ExportDir;
+ EFI_IMAGE_DATA_DIRECTORY *DataDir;
+ UINT32 FileNameOffset;
+ UINT32 NameOffset;
+ UINT16 Index;
+ UINT8 *Tdata = NULL;
+
+ ExportDir = (EFI_IMAGE_EXPORT_DIRECTORY*)(mCoffFile + mExportOffset);
+ ExportDir->Characteristics = 0;
+ ExportDir->TimeDateStamp = 0;
+ ExportDir->MajorVersion = 0;
+ ExportDir->MinorVersion =0;
+ ExportDir->Name = 0;
+ ExportDir->NumberOfFunctions = mExportSymNum;
+ ExportDir->NumberOfNames = mExportSymNum;
+ ExportDir->Base = EFI_IMAGE_EXPORT_ORDINAL_BASE;
+ ExportDir->AddressOfFunctions = mExportOffset + sizeof(EFI_IMAGE_EXPORT_DIRECTORY);
+ ExportDir->AddressOfNames = ExportDir->AddressOfFunctions + EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;
+ ExportDir->AddressOfNameOrdinals = ExportDir->AddressOfNames + EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;
+
+ FileNameOffset = ExportDir->AddressOfNameOrdinals + EFI_IMAGE_EXPORT_ORDINAL_SIZE * mExportSymNum;
+ NameOffset = FileNameOffset + strlen(mInImageName) + 1;
+
+ // Write Input image Name RVA
+ ExportDir->Name = FileNameOffset;
+
+ // Write Input image Name
+ strcpy((char *)(mCoffFile + FileNameOffset), mInImageName);
+
+ for (Index = 0; Index < mExportSymNum; Index++) {
+ //
+ // Write Export Address Table
+ //
+ Tdata = mCoffFile + ExportDir->AddressOfFunctions + Index * EFI_IMAGE_EXPORT_ADDR_SIZE;
+ *(UINT32 *)Tdata = mExportRVA[Index];
+
+ //
+ // Write Export Name Pointer Table
+ //
+ Tdata = mCoffFile + ExportDir->AddressOfNames + Index * EFI_IMAGE_EXPORT_ADDR_SIZE;
+ *(UINT32 *)Tdata = NameOffset;
+
+ //
+ // Write Export Ordinal table
+ //
+ Tdata = mCoffFile + ExportDir->AddressOfNameOrdinals + Index * EFI_IMAGE_EXPORT_ORDINAL_SIZE;
+ *(UINT16 *)Tdata = Index;
+
+ //
+ // Write Export Name Table
+ //
+ strcpy((char *)(mCoffFile + NameOffset), mExportSymName[Index]);
+ NameOffset += strlen(mExportSymName[Index]) + 1;
+ }
+
+ NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);
+ DataDir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT];
+ DataDir->VirtualAddress = mExportOffset;
+ DataDir->Size = mExportSize;
+
+}
diff --git a/BaseTools/Source/C/GenFw/ElfConvert.c b/BaseTools/Source/C/GenFw/ElfConvert.c
index 7db8721167..be98544056 100644
--- a/BaseTools/Source/C/GenFw/ElfConvert.c
+++ b/BaseTools/Source/C/GenFw/ElfConvert.c
@@ -223,6 +223,14 @@ ConvertElf (
VerboseMsg ("Write debug info.");
ElfFunctions.WriteDebug ();
+ //
+ // For PRM Driver to Write export info.
+ //
+ if (mExportFlag) {
+ VerboseMsg ("Write export info.");
+ ElfFunctions.WriteExport ();
+ }
+
//
// Make sure image size is correct before returning the new image.
//
diff --git a/BaseTools/Source/C/GenFw/ElfConvert.h b/BaseTools/Source/C/GenFw/ElfConvert.h
index 801e8de4a2..6ab4605227 100644
--- a/BaseTools/Source/C/GenFw/ElfConvert.h
+++ b/BaseTools/Source/C/GenFw/ElfConvert.h
@@ -24,6 +24,7 @@ extern UINT8 *mCoffFile;
extern UINT32 mTableOffset;
extern UINT32 mOutImageType;
extern UINT32 mFileBufferSize;
+extern BOOLEAN mExportFlag;
//
// Common EFI specific data.
@@ -31,6 +32,44 @@ extern UINT32 mFileBufferSize;
#define ELF_HII_SECTION_NAME ".hii"
#define ELF_STRTAB_SECTION_NAME ".strtab"
#define MAX_COFF_ALIGNMENT 0x10000
+#define ELF_SYMBOL_SECTION_NAME ".symtab"
+
+//
+// Platform Runtime Mechanism (PRM) specific data.
+//
+#define PRM_MODULE_EXPORT_SYMBOL_NUM 256
+
+// <to-do> to include PRM header directly once PrmPkg is in main repo
+#define PRM_HANDLER_NAME_MAXIMUM_LENGTH 128
+
+#define PRM_MODULE_EXPORT_DESCRIPTOR_NAME "PrmModuleExportDescriptor"
+#define PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE SIGNATURE_64 ('P', 'R', 'M', '_', 'M', 'E', 'D', 'T')
+#define PRM_MODULE_EXPORT_REVISION 0x0
+
+//
+// Platform Runtime Mechanism (PRM) Export Descriptor Structures
+//
+#pragma pack(push, 1)
+
+typedef struct {
+ EFI_GUID PrmHandlerGuid;
+ CHAR8 PrmHandlerName[PRM_HANDLER_NAME_MAXIMUM_LENGTH];
+} PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT;
+
+typedef struct {
+ UINT64 Signature;
+ UINT16 Revision;
+ UINT16 NumberPrmHandlers;
+ EFI_GUID PlatformGuid;
+ EFI_GUID ModuleGuid;
+} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER;
+
+typedef struct {
+ PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER Header;
+ PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT PrmHandlerExportDescriptors[1];
+} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT;
+
+#pragma pack(pop)
//
// Filter Types
@@ -38,7 +77,8 @@ extern UINT32 mFileBufferSize;
typedef enum {
SECTION_TEXT,
SECTION_HII,
- SECTION_DATA
+ SECTION_DATA,
+ SECTION_SYMBOL
} SECTION_FILTER_TYPES;
@@ -50,6 +90,7 @@ typedef struct {
BOOLEAN (*WriteSections) (SECTION_FILTER_TYPES FilterType);
VOID (*WriteRelocations) ();
VOID (*WriteDebug) ();
+ VOID (*WriteExport) ();
VOID (*SetImageSize) ();
VOID (*CleanUp) ();
diff --git a/BaseTools/Source/C/GenFw/GenFw.c b/BaseTools/Source/C/GenFw/GenFw.c
index 8cab70ba4d..6f61f16788 100644
--- a/BaseTools/Source/C/GenFw/GenFw.c
+++ b/BaseTools/Source/C/GenFw/GenFw.c
@@ -87,7 +87,7 @@ UINT32 mImageTimeStamp = 0;
UINT32 mImageSize = 0;
UINT32 mOutImageType = FW_DUMMY_IMAGE;
BOOLEAN mIsConvertXip = FALSE;
-
+BOOLEAN mExportFlag = FALSE;
STATIC
EFI_STATUS
@@ -279,6 +279,10 @@ Returns:
except for -o or -r option. It is a action option.\n\
If it is combined with other action options, the later\n\
input action option will override the previous one.\n");
+ fprintf (stdout, " --prm Scan symbol section from ELF image and \n\
+ write export table into PE-COFF.\n\
+ This option can be used together with -e.\n\
+ It doesn't work for other options.\n");
fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");
fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");
@@ -1436,6 +1440,20 @@ Returns:
continue;
}
+ if (stricmp (argv[0], "--prm") == 0) {
+ if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") != 0 ){
+ Error (NULL, 0, 1001, "Invalid", "--prm option only supports DXE RUNTIME driver.");
+ goto Finish;
+ }
+
+ if (!mExportFlag) {
+ mExportFlag = TRUE;
+ }
+ argc --;
+ argv ++;
+ continue;
+ }
+
if (argv[0][0] == '-') {
Error (NULL, 0, 1000, "Unknown option", argv[0]);
goto Finish;
diff --git a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
index f17b8ee19b..21c968e650 100644
--- a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
+++ b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
@@ -571,6 +571,13 @@ typedef struct {
UINT32 AddressOfNameOrdinals;
} EFI_IMAGE_EXPORT_DIRECTORY;
+//
+// Based export types.
+//
+#define EFI_IMAGE_EXPORT_ORDINAL_BASE 1
+#define EFI_IMAGE_EXPORT_ADDR_SIZE 4
+#define EFI_IMAGE_EXPORT_ORDINAL_SIZE 2
+
///
/// DLL support.
/// Import Format
--
2.26.2.windows.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support PRM GCC build
2022-03-14 5:27 Huang, Li-Xia
@ 2022-03-14 6:44 ` Bob Feng
[not found] ` <16DC2C4DB8F2565E.23528@groups.io>
1 sibling, 0 replies; 6+ messages in thread
From: Bob Feng @ 2022-03-14 6:44 UTC (permalink / raw)
To: Huang, Li-Xia, devel@edk2.groups.io; +Cc: Gao, Liming, Chen, Christine
This patch looks good to me.
Reviewed-by: Bob Feng <bob.c.feng@intel.com>
-----Original Message-----
From: Huang, Li-Xia <lisa.huang@intel.com>
Sent: Monday, March 14, 2022 1:27 PM
To: devel@edk2.groups.io
Cc: Huang, Li-Xia <lisa.huang@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Feng, Bob C <bob.c.feng@intel.com>; Chen, Christine <yuwei.chen@intel.com>
Subject: [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support PRM GCC build
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3802
Since PRM module needs to support export table in PE-COFF, we'll enhance GenFw tool to support this.
Add one export flag in GenFw tool. If export flag is set:
Step1: Scan ELF symbol table based on PRM module descriptor to get descriptor offset address;
Step2: Find PRM handlers number and name in COFF file based on the address from step1;
Step3: Write PRM info such as handler name and export RVA into COFF export table.
PRM option currently only supports DXE RUNTIME driver and X64 arch.
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Yuwei Chen <yuwei.chen@intel.com>
Signed-off-by: Lixia Huang <lisa.huang@intel.com>
---
BaseTools/Source/C/GenFw/Elf64Convert.c | 242 +++++++++++++++++-
BaseTools/Source/C/GenFw/ElfConvert.c | 8 +
BaseTools/Source/C/GenFw/ElfConvert.h | 43 +++-
BaseTools/Source/C/GenFw/GenFw.c | 20 +-
.../C/Include/IndustryStandard/PeImage.h | 7 +
5 files changed, 315 insertions(+), 5 deletions(-)
diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c b/BaseTools/Source/C/GenFw/Elf64Convert.c
index 0bb3ead228..2aa9bfcc94 100644
--- a/BaseTools/Source/C/GenFw/Elf64Convert.c
+++ b/BaseTools/Source/C/GenFw/Elf64Convert.c
@@ -56,6 +56,12 @@ WriteDebug64 (
VOID ); +STATIC+VOID+WriteExport64 (+ VOID+ );+ STATIC VOID SetImageSize64 (@@ -106,7 +112,7 @@ STATIC UINT32 mCoffAlignment = 0x20;
// // PE section alignment. //-STATIC const UINT16 mCoffNbrSections = 4;+STATIC UINT16 mCoffNbrSections = 4; // // ELF sections to offset in Coff file.@@ -122,7 +128,7 @@ STATIC UINT32 mDataOffset; STATIC UINT32 mHiiRsrcOffset; STATIC UINT32 mRelocOffset; STATIC UINT32 mDebugOffset;-+STATIC UINT32 mExportOffset; // // Used for RISC-V relocations. //@@ -132,6 +138,14 @@ STATIC Elf64_Half mRiscVPass1SymSecIndex = 0;
STATIC INT32 mRiscVPass1Offset; STATIC INT32 mRiscVPass1GotFixup; +//+// Used for Export section.+//+STATIC UINT32 mExportSize;+STATIC UINT32 mExportRVA[PRM_MODULE_EXPORT_SYMBOL_NUM];+STATIC UINT32 mExportSymNum;+STATIC CHAR8 mExportSymName[PRM_MODULE_EXPORT_SYMBOL_NUM][PRM_HANDLER_NAME_MAXIMUM_LENGTH];+ // // Initialization Function //@@ -171,6 +185,13 @@ InitializeElf64 (
return FALSE; } + if (mExportFlag) {+ if (mEhdr->e_machine != EM_X86_64) {+ Error (NULL, 0, 3000, "Unsupported", "--prm option currently only supports X64 arch.");+ return FALSE;+ }+ }+ // // Update section header pointers //@@ -200,6 +221,11 @@ InitializeElf64 (
ElfFunctions->SetImageSize = SetImageSize64; ElfFunctions->CleanUp = CleanUp64; + if (mExportFlag) {+ mCoffNbrSections ++;+ ElfFunctions->WriteExport = WriteExport64;+ }+ return TRUE; } @@ -263,6 +289,17 @@ IsHiiRsrcShdr (
return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0); } +STATIC+BOOLEAN+IsSymbolShdr (+ Elf_Shdr *Shdr+ )+{+ Elf_Shdr *Namehdr = GetShdrByIndex(mEhdr->e_shstrndx);++ return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namehdr->sh_offset + Shdr->sh_name, ELF_SYMBOL_SECTION_NAME) == 0);+}+ STATIC BOOLEAN IsDataShdr (@@ -335,6 +372,37 @@ GetSymName (
return StrtabContents + Sym->st_name; } +//+// Get Prm Handler number and name+//+STATIC+VOID+FindPrmHandler (+ UINT64 Offset+ )+{+ PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER *PrmExport;+ PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT *PrmHandler;+ UINT32 HandlerNum;++ PrmExport = (PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER*)((UINT8*)mEhdr + Offset);+ PrmHandler = (PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT *)(PrmExport + 1);++ for (HandlerNum = 0; HandlerNum < PrmExport->NumberPrmHandlers; HandlerNum++) {+ strcpy(mExportSymName[mExportSymNum], PrmHandler->PrmHandlerName);+ mExportSymNum ++;+ PrmHandler += 1;++ //+ // Check if PRM handler number is larger than (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)+ //+ if (mExportSymNum >= (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)) {+ Error (NULL, 0, 3000, "Invalid", "FindPrmHandler: Number %u is too high.", mExportSymNum);+ exit(EXIT_FAILURE);+ }+ }+}+ // // Find the ELF section hosting the GOT from an ELF Rva // of a single GOT entry. Normally, GOT is placed in@@ -717,6 +785,7 @@ ScanSections64 (
UINT32 CoffEntry; UINT32 SectionCount; BOOLEAN FoundSection;+ UINT32 Offset; CoffEntry = 0; mCoffOffset = 0;@@ -880,6 +949,82 @@ ScanSections64 (
Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName); } + //+ // The Symbol sections.+ //+ if (mExportFlag) {+ UINT32 SymIndex;+ Elf_Sym *Sym;+ UINT64 SymNum;+ const UINT8 *SymName;++ mExportOffset = mCoffOffset;+ mExportSize = sizeof(EFI_IMAGE_EXPORT_DIRECTORY) + strlen(mInImageName) + 1;++ for (i = 0; i < mEhdr->e_shnum; i++) {++ //+ // Determine if this is a symbol section.+ //+ Elf_Shdr *shdr = GetShdrByIndex(i);+ if (!IsSymbolShdr(shdr)) {+ continue;+ }++ UINT8 *Symtab = (UINT8*)mEhdr + shdr->sh_offset;+ SymNum = (shdr->sh_size) / (shdr->sh_entsize);++ //+ // First Get PrmModuleExportDescriptor+ //+ for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {+ Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);+ SymName = GetSymName(Sym);+ if (SymName == NULL) {+ continue;+ }++ if (strcmp((CHAR8*)SymName, PRM_MODULE_EXPORT_DESCRIPTOR_NAME) == 0) {+ //+ // Find PrmHandler Number and Name+ //+ FindPrmHandler(Sym->st_value);++ strcpy(mExportSymName[mExportSymNum], (CHAR8*)SymName);+ mExportRVA[mExportSymNum] = (UINT32)(Sym->st_value);+ mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;+ mExportSymNum ++;+ break;+ }+ }++ //+ // Second Get PrmHandler+ //+ for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {+ UINT32 ExpIndex;+ Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);+ SymName = GetSymName(Sym);+ if (SymName == NULL) {+ continue;+ }++ for (ExpIndex = 0; ExpIndex < (mExportSymNum -1); ExpIndex++) {+ if (strcmp((CHAR8*)SymName, mExportSymName[ExpIndex]) != 0) {+ continue;+ }+ mExportRVA[ExpIndex] = (UINT32)(Sym->st_value);+ mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;+ }+ }++ break;+ }++ mCoffOffset += mExportSize;+ mCoffOffset = CoffAlign(mCoffOffset);+ }+ // // The HII resource sections. //@@ -989,8 +1134,17 @@ ScanSections64 (
NtHdr->Pe32Plus.FileHeader.NumberOfSections--; } + //+ // If found symbol, add edata section between data and rsrc section+ //+ if(mExportFlag) {+ Offset = mExportOffset;+ } else {+ Offset = mHiiRsrcOffset;+ }+ if ((mHiiRsrcOffset - mDataOffset) > 0) {- CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset,+ CreateSectionHeader (".data", mDataOffset, Offset - mDataOffset, EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_WRITE | EFI_IMAGE_SCN_MEM_READ);@@ -999,6 +1153,20 @@ ScanSections64 (
NtHdr->Pe32Plus.FileHeader.NumberOfSections--; } + if(mExportFlag) {+ if ((mHiiRsrcOffset - mExportOffset) > 0) {+ CreateSectionHeader (".edata", mExportOffset, mHiiRsrcOffset - mExportOffset,+ EFI_IMAGE_SCN_CNT_INITIALIZED_DATA+ | EFI_IMAGE_SCN_MEM_READ);+ NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size = mHiiRsrcOffset - mExportOffset;+ NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = mExportOffset;++ } else {+ // Don't make a section of size 0.+ NtHdr->Pe32Plus.FileHeader.NumberOfSections--;+ }+ }+ if ((mRelocOffset - mHiiRsrcOffset) > 0) { CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset, EFI_IMAGE_SCN_CNT_INITIALIZED_DATA@@ -1757,4 +1925,72 @@ CleanUp64 (
} } +STATIC+VOID+WriteExport64 (+ VOID+ )+{+ EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;+ EFI_IMAGE_EXPORT_DIRECTORY *ExportDir;+ EFI_IMAGE_DATA_DIRECTORY *DataDir;+ UINT32 FileNameOffset;+ UINT32 NameOffset;+ UINT16 Index;+ UINT8 *Tdata = NULL;++ ExportDir = (EFI_IMAGE_EXPORT_DIRECTORY*)(mCoffFile + mExportOffset);+ ExportDir->Characteristics = 0;+ ExportDir->TimeDateStamp = 0;+ ExportDir->MajorVersion = 0;+ ExportDir->MinorVersion =0;+ ExportDir->Name = 0;+ ExportDir->NumberOfFunctions = mExportSymNum;+ ExportDir->NumberOfNames = mExportSymNum;+ ExportDir->Base = EFI_IMAGE_EXPORT_ORDINAL_BASE;+ ExportDir->AddressOfFunctions = mExportOffset + sizeof(EFI_IMAGE_EXPORT_DIRECTORY);+ ExportDir->AddressOfNames = ExportDir->AddressOfFunctions + EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;+ ExportDir->AddressOfNameOrdinals = ExportDir->AddressOfNames + EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;++ FileNameOffset = ExportDir->AddressOfNameOrdinals + EFI_IMAGE_EXPORT_ORDINAL_SIZE * mExportSymNum;+ NameOffset = FileNameOffset + strlen(mInImageName) + 1;++ // Write Input image Name RVA+ ExportDir->Name = FileNameOffset;++ // Write Input image Name+ strcpy((char *)(mCoffFile + FileNameOffset), mInImageName);++ for (Index = 0; Index < mExportSymNum; Index++) {+ //+ // Write Export Address Table+ //+ Tdata = mCoffFile + ExportDir->AddressOfFunctions + Index * EFI_IMAGE_EXPORT_ADDR_SIZE;+ *(UINT32 *)Tdata = mExportRVA[Index];++ //+ // Write Export Name Pointer Table+ //+ Tdata = mCoffFile + ExportDir->AddressOfNames + Index * EFI_IMAGE_EXPORT_ADDR_SIZE;+ *(UINT32 *)Tdata = NameOffset;++ //+ // Write Export Ordinal table+ //+ Tdata = mCoffFile + ExportDir->AddressOfNameOrdinals + Index * EFI_IMAGE_EXPORT_ORDINAL_SIZE;+ *(UINT16 *)Tdata = Index;++ //+ // Write Export Name Table+ //+ strcpy((char *)(mCoffFile + NameOffset), mExportSymName[Index]);+ NameOffset += strlen(mExportSymName[Index]) + 1;+ }++ NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);+ DataDir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT];+ DataDir->VirtualAddress = mExportOffset;+ DataDir->Size = mExportSize;++} diff --git a/BaseTools/Source/C/GenFw/ElfConvert.c b/BaseTools/Source/C/GenFw/ElfConvert.c
index 7db8721167..be98544056 100644
--- a/BaseTools/Source/C/GenFw/ElfConvert.c
+++ b/BaseTools/Source/C/GenFw/ElfConvert.c
@@ -223,6 +223,14 @@ ConvertElf (
VerboseMsg ("Write debug info."); ElfFunctions.WriteDebug (); + //+ // For PRM Driver to Write export info.+ //+ if (mExportFlag) {+ VerboseMsg ("Write export info.");+ ElfFunctions.WriteExport ();+ }+ // // Make sure image size is correct before returning the new image. //diff --git a/BaseTools/Source/C/GenFw/ElfConvert.h b/BaseTools/Source/C/GenFw/ElfConvert.h
index 801e8de4a2..6ab4605227 100644
--- a/BaseTools/Source/C/GenFw/ElfConvert.h
+++ b/BaseTools/Source/C/GenFw/ElfConvert.h
@@ -24,6 +24,7 @@ extern UINT8 *mCoffFile; extern UINT32 mTableOffset; extern UINT32 mOutImageType; extern UINT32 mFileBufferSize;+extern BOOLEAN mExportFlag; // // Common EFI specific data.@@ -31,6 +32,44 @@ extern UINT32 mFileBufferSize;
#define ELF_HII_SECTION_NAME ".hii" #define ELF_STRTAB_SECTION_NAME ".strtab" #define MAX_COFF_ALIGNMENT 0x10000+#define ELF_SYMBOL_SECTION_NAME ".symtab"++//+// Platform Runtime Mechanism (PRM) specific data.+//+#define PRM_MODULE_EXPORT_SYMBOL_NUM 256++// <to-do> to include PRM header directly once PrmPkg is in main repo+#define PRM_HANDLER_NAME_MAXIMUM_LENGTH 128++#define PRM_MODULE_EXPORT_DESCRIPTOR_NAME "PrmModuleExportDescriptor"+#define PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE SIGNATURE_64 ('P', 'R', 'M', '_', 'M', 'E', 'D', 'T')+#define PRM_MODULE_EXPORT_REVISION 0x0++//+// Platform Runtime Mechanism (PRM) Export Descriptor Structures+//+#pragma pack(push, 1)++typedef struct {+ EFI_GUID PrmHandlerGuid;+ CHAR8 PrmHandlerName[PRM_HANDLER_NAME_MAXIMUM_LENGTH];+} PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT;++typedef struct {+ UINT64 Signature;+ UINT16 Revision;+ UINT16 NumberPrmHandlers;+ EFI_GUID PlatformGuid;+ EFI_GUID ModuleGuid;+} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER;++typedef struct {+ PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER Header;+ PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT PrmHandlerExportDescriptors[1];+} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT;++#pragma pack(pop) // // Filter Types@@ -38,7 +77,8 @@ extern UINT32 mFileBufferSize;
typedef enum { SECTION_TEXT, SECTION_HII,- SECTION_DATA+ SECTION_DATA,+ SECTION_SYMBOL } SECTION_FILTER_TYPES; @@ -50,6 +90,7 @@ typedef struct {
BOOLEAN (*WriteSections) (SECTION_FILTER_TYPES FilterType); VOID (*WriteRelocations) (); VOID (*WriteDebug) ();+ VOID (*WriteExport) (); VOID (*SetImageSize) (); VOID (*CleanUp) (); diff --git a/BaseTools/Source/C/GenFw/GenFw.c b/BaseTools/Source/C/GenFw/GenFw.c
index 8cab70ba4d..6f61f16788 100644
--- a/BaseTools/Source/C/GenFw/GenFw.c
+++ b/BaseTools/Source/C/GenFw/GenFw.c
@@ -87,7 +87,7 @@ UINT32 mImageTimeStamp = 0;
UINT32 mImageSize = 0; UINT32 mOutImageType = FW_DUMMY_IMAGE; BOOLEAN mIsConvertXip = FALSE;-+BOOLEAN mExportFlag = FALSE; STATIC EFI_STATUS@@ -279,6 +279,10 @@ Returns:
except for -o or -r option. It is a action option.\n\ If it is combined with other action options, the later\n\ input action option will override the previous one.\n");+ fprintf (stdout, " --prm Scan symbol section from ELF image and \n\+ write export table into PE-COFF.\n\+ This option can be used together with -e.\n\+ It doesn't work for other options.\n"); fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n"); fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");@@ -1436,6 +1440,20 @@ Returns:
continue; } + if (stricmp (argv[0], "--prm") == 0) {+ if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") != 0 ){+ Error (NULL, 0, 1001, "Invalid", "--prm option only supports DXE RUNTIME driver.");+ goto Finish;+ }++ if (!mExportFlag) {+ mExportFlag = TRUE;+ }+ argc --;+ argv ++;+ continue;+ }+ if (argv[0][0] == '-') { Error (NULL, 0, 1000, "Unknown option", argv[0]); goto Finish;diff --git a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
index f17b8ee19b..21c968e650 100644
--- a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
+++ b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
@@ -571,6 +571,13 @@ typedef struct {
UINT32 AddressOfNameOrdinals; } EFI_IMAGE_EXPORT_DIRECTORY; +//+// Based export types.+//+#define EFI_IMAGE_EXPORT_ORDINAL_BASE 1+#define EFI_IMAGE_EXPORT_ADDR_SIZE 4+#define EFI_IMAGE_EXPORT_ORDINAL_SIZE 2+ /// /// DLL support. /// Import Format--
2.26.2.windows.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
[parent not found: <16DC2C4DB8F2565E.23528@groups.io>]
* Re: [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support PRM GCC build
[not found] ` <16DC2C4DB8F2565E.23528@groups.io>
@ 2022-03-14 23:46 ` Bob Feng
0 siblings, 0 replies; 6+ messages in thread
From: Bob Feng @ 2022-03-14 23:46 UTC (permalink / raw)
To: devel@edk2.groups.io, Feng, Bob C, Huang, Li-Xia
Cc: Gao, Liming, Chen, Christine
Created a PR: https://github.com/tianocore/edk2/pull/2622
-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Bob Feng
Sent: Monday, March 14, 2022 2:45 PM
To: Huang, Li-Xia <lisa.huang@intel.com>; devel@edk2.groups.io
Cc: Gao, Liming <gaoliming@byosoft.com.cn>; Chen, Christine <yuwei.chen@intel.com>
Subject: Re: [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support PRM GCC build
This patch looks good to me.
Reviewed-by: Bob Feng <bob.c.feng@intel.com>
-----Original Message-----
From: Huang, Li-Xia <lisa.huang@intel.com>
Sent: Monday, March 14, 2022 1:27 PM
To: devel@edk2.groups.io
Cc: Huang, Li-Xia <lisa.huang@intel.com>; Gao, Liming <gaoliming@byosoft.com.cn>; Feng, Bob C <bob.c.feng@intel.com>; Chen, Christine <yuwei.chen@intel.com>
Subject: [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support PRM GCC build
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3802
Since PRM module needs to support export table in PE-COFF, we'll enhance GenFw tool to support this.
Add one export flag in GenFw tool. If export flag is set:
Step1: Scan ELF symbol table based on PRM module descriptor to get descriptor offset address;
Step2: Find PRM handlers number and name in COFF file based on the address from step1;
Step3: Write PRM info such as handler name and export RVA into COFF export table.
PRM option currently only supports DXE RUNTIME driver and X64 arch.
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Yuwei Chen <yuwei.chen@intel.com>
Signed-off-by: Lixia Huang <lisa.huang@intel.com>
---
BaseTools/Source/C/GenFw/Elf64Convert.c | 242 +++++++++++++++++-
BaseTools/Source/C/GenFw/ElfConvert.c | 8 +
BaseTools/Source/C/GenFw/ElfConvert.h | 43 +++-
BaseTools/Source/C/GenFw/GenFw.c | 20 +-
.../C/Include/IndustryStandard/PeImage.h | 7 +
5 files changed, 315 insertions(+), 5 deletions(-)
diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c b/BaseTools/Source/C/GenFw/Elf64Convert.c
index 0bb3ead228..2aa9bfcc94 100644
--- a/BaseTools/Source/C/GenFw/Elf64Convert.c
+++ b/BaseTools/Source/C/GenFw/Elf64Convert.c
@@ -56,6 +56,12 @@ WriteDebug64 (
VOID ); +STATIC+VOID+WriteExport64 (+ VOID+ );+ STATIC VOID SetImageSize64 (@@ -106,7 +112,7 @@ STATIC UINT32 mCoffAlignment = 0x20;
// // PE section alignment. //-STATIC const UINT16 mCoffNbrSections = 4;+STATIC UINT16 mCoffNbrSections = 4; // // ELF sections to offset in Coff file.@@ -122,7 +128,7 @@ STATIC UINT32 mDataOffset; STATIC UINT32 mHiiRsrcOffset; STATIC UINT32 mRelocOffset; STATIC UINT32 mDebugOffset;-+STATIC UINT32 mExportOffset; // // Used for RISC-V relocations. //@@ -132,6 +138,14 @@ STATIC Elf64_Half mRiscVPass1SymSecIndex = 0;
STATIC INT32 mRiscVPass1Offset; STATIC INT32 mRiscVPass1GotFixup; +//+// Used for Export section.+//+STATIC UINT32 mExportSize;+STATIC UINT32 mExportRVA[PRM_MODULE_EXPORT_SYMBOL_NUM];+STATIC UINT32 mExportSymNum;+STATIC CHAR8 mExportSymName[PRM_MODULE_EXPORT_SYMBOL_NUM][PRM_HANDLER_NAME_MAXIMUM_LENGTH];+ // // Initialization Function //@@ -171,6 +185,13 @@ InitializeElf64 (
return FALSE; } + if (mExportFlag) {+ if (mEhdr->e_machine != EM_X86_64) {+ Error (NULL, 0, 3000, "Unsupported", "--prm option currently only supports X64 arch.");+ return FALSE;+ }+ }+ // // Update section header pointers //@@ -200,6 +221,11 @@ InitializeElf64 (
ElfFunctions->SetImageSize = SetImageSize64; ElfFunctions->CleanUp = CleanUp64; + if (mExportFlag) {+ mCoffNbrSections ++;+ ElfFunctions->WriteExport = WriteExport64;+ }+ return TRUE; } @@ -263,6 +289,17 @@ IsHiiRsrcShdr (
return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0); } +STATIC+BOOLEAN+IsSymbolShdr (+ Elf_Shdr *Shdr+ )+{+ Elf_Shdr *Namehdr = GetShdrByIndex(mEhdr->e_shstrndx);++ return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namehdr->sh_offset + Shdr->sh_name, ELF_SYMBOL_SECTION_NAME) == 0);+}+ STATIC BOOLEAN IsDataShdr (@@ -335,6 +372,37 @@ GetSymName (
return StrtabContents + Sym->st_name; } +//+// Get Prm Handler number and name+//+STATIC+VOID+FindPrmHandler (+ UINT64 Offset+ )+{+ PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER *PrmExport;+ PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT *PrmHandler;+ UINT32 HandlerNum;++ PrmExport = (PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER*)((UINT8*)mEhdr + Offset);+ PrmHandler = (PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT *)(PrmExport + 1);++ for (HandlerNum = 0; HandlerNum < PrmExport->NumberPrmHandlers; HandlerNum++) {+ strcpy(mExportSymName[mExportSymNum], PrmHandler->PrmHandlerName);+ mExportSymNum ++;+ PrmHandler += 1;++ //+ // Check if PRM handler number is larger than (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)+ //+ if (mExportSymNum >= (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)) {+ Error (NULL, 0, 3000, "Invalid", "FindPrmHandler: Number %u is too high.", mExportSymNum);+ exit(EXIT_FAILURE);+ }+ }+}+ // // Find the ELF section hosting the GOT from an ELF Rva // of a single GOT entry. Normally, GOT is placed in@@ -717,6 +785,7 @@ ScanSections64 (
UINT32 CoffEntry; UINT32 SectionCount; BOOLEAN FoundSection;+ UINT32 Offset; CoffEntry = 0; mCoffOffset = 0;@@ -880,6 +949,82 @@ ScanSections64 (
Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName); } + //+ // The Symbol sections.+ //+ if (mExportFlag) {+ UINT32 SymIndex;+ Elf_Sym *Sym;+ UINT64 SymNum;+ const UINT8 *SymName;++ mExportOffset = mCoffOffset;+ mExportSize = sizeof(EFI_IMAGE_EXPORT_DIRECTORY) + strlen(mInImageName) + 1;++ for (i = 0; i < mEhdr->e_shnum; i++) {++ //+ // Determine if this is a symbol section.+ //+ Elf_Shdr *shdr = GetShdrByIndex(i);+ if (!IsSymbolShdr(shdr)) {+ continue;+ }++ UINT8 *Symtab = (UINT8*)mEhdr + shdr->sh_offset;+ SymNum = (shdr->sh_size) / (shdr->sh_entsize);++ //+ // First Get PrmModuleExportDescriptor+ //+ for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {+ Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);+ SymName = GetSymName(Sym);+ if (SymName == NULL) {+ continue;+ }++ if (strcmp((CHAR8*)SymName, PRM_MODULE_EXPORT_DESCRIPTOR_NAME) == 0) {+ //+ // Find PrmHandler Number and Name+ //+ FindPrmHandler(Sym->st_value);++ strcpy(mExportSymName[mExportSymNum], (CHAR8*)SymName);+ mExportRVA[mExportSymNum] = (UINT32)(Sym->st_value);+ mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;+ mExportSymNum ++;+ break;+ }+ }++ //+ // Second Get PrmHandler+ //+ for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {+ UINT32 ExpIndex;+ Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);+ SymName = GetSymName(Sym);+ if (SymName == NULL) {+ continue;+ }++ for (ExpIndex = 0; ExpIndex < (mExportSymNum -1); ExpIndex++) {+ if (strcmp((CHAR8*)SymName, mExportSymName[ExpIndex]) != 0) {+ continue;+ }+ mExportRVA[ExpIndex] = (UINT32)(Sym->st_value);+ mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;+ }+ }++ break;+ }++ mCoffOffset += mExportSize;+ mCoffOffset = CoffAlign(mCoffOffset);+ }+ // // The HII resource sections. //@@ -989,8 +1134,17 @@ ScanSections64 (
NtHdr->Pe32Plus.FileHeader.NumberOfSections--; } + //+ // If found symbol, add edata section between data and rsrc section+ //+ if(mExportFlag) {+ Offset = mExportOffset;+ } else {+ Offset = mHiiRsrcOffset;+ }+ if ((mHiiRsrcOffset - mDataOffset) > 0) {- CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset,+ CreateSectionHeader (".data", mDataOffset, Offset - mDataOffset, EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_WRITE | EFI_IMAGE_SCN_MEM_READ);@@ -999,6 +1153,20 @@ ScanSections64 (
NtHdr->Pe32Plus.FileHeader.NumberOfSections--; } + if(mExportFlag) {+ if ((mHiiRsrcOffset - mExportOffset) > 0) {+ CreateSectionHeader (".edata", mExportOffset, mHiiRsrcOffset - mExportOffset,+ EFI_IMAGE_SCN_CNT_INITIALIZED_DATA+ | EFI_IMAGE_SCN_MEM_READ);+ NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size = mHiiRsrcOffset - mExportOffset;+ NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = mExportOffset;++ } else {+ // Don't make a section of size 0.+ NtHdr->Pe32Plus.FileHeader.NumberOfSections--;+ }+ }+ if ((mRelocOffset - mHiiRsrcOffset) > 0) { CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset, EFI_IMAGE_SCN_CNT_INITIALIZED_DATA@@ -1757,4 +1925,72 @@ CleanUp64 (
} } +STATIC+VOID+WriteExport64 (+ VOID+ )+{+ EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;+ EFI_IMAGE_EXPORT_DIRECTORY *ExportDir;+ EFI_IMAGE_DATA_DIRECTORY *DataDir;+ UINT32 FileNameOffset;+ UINT32 NameOffset;+ UINT16 Index;+ UINT8 *Tdata = NULL;++ ExportDir = (EFI_IMAGE_EXPORT_DIRECTORY*)(mCoffFile + mExportOffset);+ ExportDir->Characteristics = 0;+ ExportDir->TimeDateStamp = 0;+ ExportDir->MajorVersion = 0;+ ExportDir->MinorVersion =0;+ ExportDir->Name = 0;+ ExportDir->NumberOfFunctions = mExportSymNum;+ ExportDir->NumberOfNames = mExportSymNum;+ ExportDir->Base = EFI_IMAGE_EXPORT_ORDINAL_BASE;+ ExportDir->AddressOfFunctions = mExportOffset + sizeof(EFI_IMAGE_EXPORT_DIRECTORY);+ ExportDir->AddressOfNames = ExportDir->AddressOfFunctions + EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;+ ExportDir->AddressOfNameOrdinals = ExportDir->AddressOfNames + EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;++ FileNameOffset = ExportDir->AddressOfNameOrdinals + EFI_IMAGE_EXPORT_ORDINAL_SIZE * mExportSymNum;+ NameOffset = FileNameOffset + strlen(mInImageName) + 1;++ // Write Input image Name RVA+ ExportDir->Name = FileNameOffset;++ // Write Input image Name+ strcpy((char *)(mCoffFile + FileNameOffset), mInImageName);++ for (Index = 0; Index < mExportSymNum; Index++) {+ //+ // Write Export Address Table+ //+ Tdata = mCoffFile + ExportDir->AddressOfFunctions + Index * EFI_IMAGE_EXPORT_ADDR_SIZE;+ *(UINT32 *)Tdata = mExportRVA[Index];++ //+ // Write Export Name Pointer Table+ //+ Tdata = mCoffFile + ExportDir->AddressOfNames + Index * EFI_IMAGE_EXPORT_ADDR_SIZE;+ *(UINT32 *)Tdata = NameOffset;++ //+ // Write Export Ordinal table+ //+ Tdata = mCoffFile + ExportDir->AddressOfNameOrdinals + Index * EFI_IMAGE_EXPORT_ORDINAL_SIZE;+ *(UINT16 *)Tdata = Index;++ //+ // Write Export Name Table+ //+ strcpy((char *)(mCoffFile + NameOffset), mExportSymName[Index]);+ NameOffset += strlen(mExportSymName[Index]) + 1;+ }++ NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);+ DataDir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT];+ DataDir->VirtualAddress = mExportOffset;+ DataDir->Size = mExportSize;++} diff --git a/BaseTools/Source/C/GenFw/ElfConvert.c b/BaseTools/Source/C/GenFw/ElfConvert.c
index 7db8721167..be98544056 100644
--- a/BaseTools/Source/C/GenFw/ElfConvert.c
+++ b/BaseTools/Source/C/GenFw/ElfConvert.c
@@ -223,6 +223,14 @@ ConvertElf (
VerboseMsg ("Write debug info."); ElfFunctions.WriteDebug (); + //+ // For PRM Driver to Write export info.+ //+ if (mExportFlag) {+ VerboseMsg ("Write export info.");+ ElfFunctions.WriteExport ();+ }+ // // Make sure image size is correct before returning the new image. //diff --git a/BaseTools/Source/C/GenFw/ElfConvert.h b/BaseTools/Source/C/GenFw/ElfConvert.h
index 801e8de4a2..6ab4605227 100644
--- a/BaseTools/Source/C/GenFw/ElfConvert.h
+++ b/BaseTools/Source/C/GenFw/ElfConvert.h
@@ -24,6 +24,7 @@ extern UINT8 *mCoffFile; extern UINT32 mTableOffset; extern UINT32 mOutImageType; extern UINT32 mFileBufferSize;+extern BOOLEAN mExportFlag; // // Common EFI specific data.@@ -31,6 +32,44 @@ extern UINT32 mFileBufferSize;
#define ELF_HII_SECTION_NAME ".hii" #define ELF_STRTAB_SECTION_NAME ".strtab" #define MAX_COFF_ALIGNMENT 0x10000+#define ELF_SYMBOL_SECTION_NAME ".symtab"++//+// Platform Runtime Mechanism (PRM) specific data.+//+#define PRM_MODULE_EXPORT_SYMBOL_NUM 256++// <to-do> to include PRM header directly once PrmPkg is in main repo+#define PRM_HANDLER_NAME_MAXIMUM_LENGTH 128++#define PRM_MODULE_EXPORT_DESCRIPTOR_NAME "PrmModuleExportDescriptor"+#define PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE SIGNATURE_64 ('P', 'R', 'M', '_', 'M', 'E', 'D', 'T')+#define PRM_MODULE_EXPORT_REVISION 0x0++//+// Platform Runtime Mechanism (PRM) Export Descriptor Structures+//+#pragma pack(push, 1)++typedef struct {+ EFI_GUID PrmHandlerGuid;+ CHAR8 PrmHandlerName[PRM_HANDLER_NAME_MAXIMUM_LENGTH];+} PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT;++typedef struct {+ UINT64 Signature;+ UINT16 Revision;+ UINT16 NumberPrmHandlers;+ EFI_GUID PlatformGuid;+ EFI_GUID ModuleGuid;+} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER;++typedef struct {+ PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER Header;+ PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT PrmHandlerExportDescriptors[1];+} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT;++#pragma pack(pop) // // Filter Types@@ -38,7 +77,8 @@ extern UINT32 mFileBufferSize;
typedef enum { SECTION_TEXT, SECTION_HII,- SECTION_DATA+ SECTION_DATA,+ SECTION_SYMBOL } SECTION_FILTER_TYPES; @@ -50,6 +90,7 @@ typedef struct {
BOOLEAN (*WriteSections) (SECTION_FILTER_TYPES FilterType); VOID (*WriteRelocations) (); VOID (*WriteDebug) ();+ VOID (*WriteExport) (); VOID (*SetImageSize) (); VOID (*CleanUp) (); diff --git a/BaseTools/Source/C/GenFw/GenFw.c b/BaseTools/Source/C/GenFw/GenFw.c
index 8cab70ba4d..6f61f16788 100644
--- a/BaseTools/Source/C/GenFw/GenFw.c
+++ b/BaseTools/Source/C/GenFw/GenFw.c
@@ -87,7 +87,7 @@ UINT32 mImageTimeStamp = 0;
UINT32 mImageSize = 0; UINT32 mOutImageType = FW_DUMMY_IMAGE; BOOLEAN mIsConvertXip = FALSE;-+BOOLEAN mExportFlag = FALSE; STATIC EFI_STATUS@@ -279,6 +279,10 @@ Returns:
except for -o or -r option. It is a action option.\n\ If it is combined with other action options, the later\n\ input action option will override the previous one.\n");+ fprintf (stdout, " --prm Scan symbol section from ELF image and \n\+ write export table into PE-COFF.\n\+ This option can be used together with -e.\n\+ It doesn't work for other options.\n"); fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n"); fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");@@ -1436,6 +1440,20 @@ Returns:
continue; } + if (stricmp (argv[0], "--prm") == 0) {+ if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") != 0 ){+ Error (NULL, 0, 1001, "Invalid", "--prm option only supports DXE RUNTIME driver.");+ goto Finish;+ }++ if (!mExportFlag) {+ mExportFlag = TRUE;+ }+ argc --;+ argv ++;+ continue;+ }+ if (argv[0][0] == '-') { Error (NULL, 0, 1000, "Unknown option", argv[0]); goto Finish;diff --git a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
index f17b8ee19b..21c968e650 100644
--- a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
+++ b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h
@@ -571,6 +571,13 @@ typedef struct {
UINT32 AddressOfNameOrdinals; } EFI_IMAGE_EXPORT_DIRECTORY; +//+// Based export types.+//+#define EFI_IMAGE_EXPORT_ORDINAL_BASE 1+#define EFI_IMAGE_EXPORT_ADDR_SIZE 4+#define EFI_IMAGE_EXPORT_ORDINAL_SIZE 2+ /// /// DLL support. /// Import Format--
2.26.2.windows.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2022-03-14 23:46 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-02-28 1:14 [edk2-devel] [PATCH v2] BaseTools/GenFw: Enhance GenFw to support PRM GCC build Huang, Li-Xia
2022-03-01 1:51 ` 回复: " gaoliming
2022-03-14 3:02 ` Huang, Li-Xia
-- strict thread matches above, loose matches on Subject: below --
2022-03-14 5:27 Huang, Li-Xia
2022-03-14 6:44 ` Bob Feng
[not found] ` <16DC2C4DB8F2565E.23528@groups.io>
2022-03-14 23:46 ` Bob Feng
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox