Hi Lixia,

This patch introduce a new command line option --PRM. Could you add the help 
information about --PRM?

Could you provide more information about the below change? Would there be 
side-effect?

@@ -750,7 +818,7 @@ ScanSections64 (
     if (shdr->sh_addralign <= mCoffAlignment) {
       continue;
     }
-    if (IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr)) {
+    if (IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr) || 
IsSymbolShdr(shdr)) {
       mCoffAlignment = (UINT32)shdr->sh_addralign;
     }
   }



Thanks,
Bob 

-----Original Message-----
From: Huang, Li-Xia <[email protected]> 
Sent: Wednesday, January 12, 2022 3:44 PM
To: [email protected]
Cc: Huang, Li-Xia <[email protected]>; Gao, Liming 
<[email protected]>; Feng, Bob C <[email protected]>; Chen, Christine 
<[email protected]>
Subject: [edk2-devel][PATCH] BaseTools/GenFw: Enhance to add export table in 
PE-COFF

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.

Cc: Liming Gao <[email protected]>
Cc: Bob Feng <[email protected]>
Cc: Yuwei Chen <[email protected]>
Signed-off-by: Lixia Huang <[email protected]>
---
 BaseTools/Source/C/GenFw/Elf64Convert.c       | 254 +++++++++++++++++-
 BaseTools/Source/C/GenFw/ElfConvert.c         |  10 +
 BaseTools/Source/C/GenFw/ElfConvert.h         |  42 ++-
 BaseTools/Source/C/GenFw/GenFw.c              |  11 +-
 .../C/Include/IndustryStandard/PeImage.h      |   7 +
 5 files changed, 318 insertions(+), 6 deletions(-)

diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c 
b/BaseTools/Source/C/GenFw/Elf64Convert.c
index 0bb3ead228..0079507356 100644
--- a/BaseTools/Source/C/GenFw/Elf64Convert.c
+++ b/BaseTools/Source/C/GenFw/Elf64Convert.c
@@ -56,6 +56,18 @@ WriteDebug64 (
   VOID   ); +STATIC+VOID+ScanSymbol64 (+  VOID+  );++STATIC+VOID+WriteExport64 
(+  VOID+  );+ STATIC VOID SetImageSize64 (@@ -122,7 +134,7 @@ STATIC UINT32 
mDataOffset;
 STATIC UINT32 mHiiRsrcOffset; STATIC UINT32 mRelocOffset; STATIC UINT32 
mDebugOffset;-+STATIC UINT32 mExportOffset; // // Used for RISC-V relocations. 
//@@ -132,6 +144,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 //@@ -200,6 +220,10 @@ InitializeElf64 (
   ElfFunctions->SetImageSize = SetImageSize64;   ElfFunctions->CleanUp = 
CleanUp64; +  if (mExportFlag) {+    ElfFunctions->ScanSymbol = ScanSymbol64;+  
  ElfFunctions->WriteExport = WriteExport64;+  }   return TRUE; } @@ -263,6 
+287,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 +370,38 
@@ GetSymName (
   return StrtabContents + Sym->st_name; } +//+// Get Prm Handler number and 
name+//+STATIC+VOID+FindPrmHandler (+  UINT64 Offset+  )+{+  
PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER *PrmExport;+  UINT32   NameOffset;+  
UINT32   HandlerNum;+  UINT32   Index;+  UINT8    
SymName[PRM_HANDLER_NAME_MAXIMUM_LENGTH];++  PrmExport = 
(PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER*)(mCoffFile + Offset);+  NameOffset 
= sizeof(PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER) + sizeof(EFI_GUID);++  for 
(HandlerNum = 0; HandlerNum < PrmExport->NumberPrmHandlers; HandlerNum++) {+    
for (Index = 0; Index < PRM_HANDLER_NAME_MAXIMUM_LENGTH; Index++) {+      
SymName[Index] = *((UINT8 *)PrmExport + NameOffset + Index);+      if 
(SymName[Index] == 0) {+        break;+      }+    }++    
strcpy(mExportSymName[mExportSymNum], (CHAR8*)SymName);+    NameOffset += 
PRM_HANDLER_NAME_MAXIMUM_LENGTH + sizeof(EFI_GUID);+    mExportSymNum ++;+  
}+}+ // // Find the ELF section hosting the GOT from an ELF Rva //   of a 
single GOT entry.  Normally, GOT is placed in@@ -717,6 +784,7 @@ ScanSections64 
(
   UINT32                          CoffEntry;   UINT32                          
SectionCount;   BOOLEAN                         FoundSection;+  UINT32          
                Offset;    CoffEntry = 0;   mCoffOffset = 0;@@ -750,7 +818,7 @@ 
ScanSections64 (
     if (shdr->sh_addralign <= mCoffAlignment) {       continue;     }-    if 
(IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr)) {+    if 
(IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr) || 
IsSymbolShdr(shdr)) {       mCoffAlignment = (UINT32)shdr->sh_addralign;     }  
 }@@ -880,6 +948,16 @@ 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) {+    mExportOffset = 
mCoffOffset;+    mExportSize = sizeof(EFI_IMAGE_EXPORT_DIRECTORY) + 
strlen(mInImageName) + 1;+    mCoffOffset += mExportSize;+    mCoffOffset = 
CoffAlign(mCoffOffset);+  }+   //   //  The HII resource sections.   //@@ 
-962,7 +1040,11 @@ ScanSections64 (
     | EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE;    
NtHdr->Pe32Plus.OptionalHeader.SizeOfCode = mDataOffset - mTextOffset;-  
NtHdr->Pe32Plus.OptionalHeader.SizeOfInitializedData = mRelocOffset - 
mDataOffset;+  if(mExportFlag) {+    
NtHdr->Pe32Plus.OptionalHeader.SizeOfInitializedData = mRelocOffset - 
mExportOffset;+  } else {+    
NtHdr->Pe32Plus.OptionalHeader.SizeOfInitializedData = mRelocOffset - 
mDataOffset;+  }   NtHdr->Pe32Plus.OptionalHeader.SizeOfUninitializedData = 0;  
 NtHdr->Pe32Plus.OptionalHeader.AddressOfEntryPoint = CoffEntry; @@ -989,8 
+1071,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 +1090,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;+      NtHdr->Pe32Plus.FileHeader.NumberOfSections++;+    } 
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 +1862,145 @@ CleanUp64 (
   } } +STATIC+VOID+ScanSymbol64 (+  VOID+  )+{+  UINT32      shIndex;+  UINT32 
     SymIndex;+  Elf_Sym     *Sym;+  UINT64      SymNum;+  const UINT8 
*SymName;++  for (shIndex = 0; shIndex < mEhdr->e_shnum; shIndex++) {+    //+   
 // Determine if this is a symbol section.+    //+    Elf_Shdr *shdr = 
GetShdrByIndex(shIndex);+    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;+  }+}++STATIC+VOID+WriteExport64 (+  
VOID+  )+{+  EFI_IMAGE_OPTIONAL_HEADER_UNION     *NtHdr;+  
EFI_IMAGE_EXPORT_DIRECTORY          *ExportDir;+  EFI_IMAGE_DATA_DIRECTORY      
      *DataDir;+  UINT32                              FileNameOffset;+  UINT32  
                            FuncOffset;+  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;+  FuncOffset = FileNameOffset + strlen(mInImageName) + 1;++  // 
Write Input image Name RVA+  Tdata = mCoffFile + 12;+  *(UINT32 *)Tdata = 
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 = FuncOffset;++    //+    // Write Export Ordinal table+    //+    
Tdata = mCoffFile + ExportDir->AddressOfNameOrdinals + Index * 
EFI_IMAGE_EXPORT_ORDINAL_SIZE;+    *(UINT16 *)Tdata = Index;++    //+    // 
Write Export Name Table+    //+    strcpy((char *)(mCoffFile + FuncOffset), 
mExportSymName[Index]);+    FuncOffset += 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..795cdbd743 100644
--- a/BaseTools/Source/C/GenFw/ElfConvert.c
+++ b/BaseTools/Source/C/GenFw/ElfConvert.c
@@ -223,6 +223,16 @@ ConvertElf (
   VerboseMsg ("Write debug info.");   ElfFunctions.WriteDebug (); +  //+  // 
For PRM Driver to Write export info.+  //+  if (mExportFlag) {+    VerboseMsg 
("Scan symbol info.");+    ElfFunctions.ScanSymbol ();+    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..7920765fbb 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,42 @@ 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 10+#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 +75,8 @@ extern UINT32 mFileBufferSize;
 typedef enum {   SECTION_TEXT,   SECTION_HII,-  SECTION_DATA+  SECTION_DATA,+  
SECTION_SYMBOL  } SECTION_FILTER_TYPES; @@ -50,6 +88,8 @@ typedef struct {
   BOOLEAN (*WriteSections) (SECTION_FILTER_TYPES  FilterType);   VOID    
(*WriteRelocations) ();   VOID    (*WriteDebug) ();+  VOID    (*ScanSymbol) 
();+  VOID    (*WriteExport) ();   VOID    (*SetImageSize) ();   VOID    
(*CleanUp) (); diff --git a/BaseTools/Source/C/GenFw/GenFw.c 
b/BaseTools/Source/C/GenFw/GenFw.c
index 8cab70ba4d..c7de5b89d8 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@@ 
-1436,6 +1436,15 @@ Returns:
       continue;     } +    if (stricmp (argv[0], "--PRM") == 0) {+      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 (#85708): https://edk2.groups.io/g/devel/message/85708
Mute This Topic: https://groups.io/mt/88373239/21656
Group Owner: [email protected]
Unsubscribe: https://edk2.groups.io/g/devel/unsub [[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to