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(-)
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
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#87530): https://edk2.groups.io/g/devel/message/87530
Mute This Topic: https://groups.io/mt/89765933/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
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 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#87532): https://edk2.groups.io/g/devel/message/87532 Mute This Topic: https://groups.io/mt/89765933/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2024 Red Hat, Inc.