VOID\r
);\r
\r
+STATIC\r
+VOID\r
+WriteExport64 (\r
+ VOID\r
+ );\r
+\r
STATIC\r
VOID\r
SetImageSize64 (\r
//\r
// PE section alignment.\r
//\r
-STATIC const UINT16 mCoffNbrSections = 4;\r
+STATIC UINT16 mCoffNbrSections = 4;\r
\r
//\r
// ELF sections to offset in Coff file.\r
STATIC UINT32 mHiiRsrcOffset;\r
STATIC UINT32 mRelocOffset;\r
STATIC UINT32 mDebugOffset;\r
-\r
+STATIC UINT32 mExportOffset;\r
//\r
// Used for RISC-V relocations.\r
//\r
STATIC INT32 mRiscVPass1Offset;\r
STATIC INT32 mRiscVPass1GotFixup;\r
\r
+//\r
+// Used for Export section.\r
+//\r
+STATIC UINT32 mExportSize;\r
+STATIC UINT32 mExportRVA[PRM_MODULE_EXPORT_SYMBOL_NUM];\r
+STATIC UINT32 mExportSymNum;\r
+STATIC CHAR8 mExportSymName[PRM_MODULE_EXPORT_SYMBOL_NUM][PRM_HANDLER_NAME_MAXIMUM_LENGTH];\r
+\r
//\r
// Initialization Function\r
//\r
return FALSE;\r
}\r
\r
+ if (mExportFlag) {\r
+ if (mEhdr->e_machine != EM_X86_64) {\r
+ Error (NULL, 0, 3000, "Unsupported", "--prm option currently only supports X64 arch.");\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
//\r
// Update section header pointers\r
//\r
ElfFunctions->SetImageSize = SetImageSize64;\r
ElfFunctions->CleanUp = CleanUp64;\r
\r
+ if (mExportFlag) {\r
+ mCoffNbrSections ++;\r
+ ElfFunctions->WriteExport = WriteExport64;\r
+ }\r
+\r
return TRUE;\r
}\r
\r
return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0);\r
}\r
\r
+STATIC\r
+BOOLEAN\r
+IsSymbolShdr (\r
+ Elf_Shdr *Shdr\r
+ )\r
+{\r
+ Elf_Shdr *Namehdr = GetShdrByIndex(mEhdr->e_shstrndx);\r
+\r
+ return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namehdr->sh_offset + Shdr->sh_name, ELF_SYMBOL_SECTION_NAME) == 0);\r
+}\r
+\r
STATIC\r
BOOLEAN\r
IsDataShdr (\r
return StrtabContents + Sym->st_name;\r
}\r
\r
+//\r
+// Get Prm Handler number and name\r
+//\r
+STATIC\r
+VOID\r
+FindPrmHandler (\r
+ UINT64 Offset\r
+ )\r
+{\r
+ PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER *PrmExport;\r
+ PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT *PrmHandler;\r
+ UINT32 HandlerNum;\r
+\r
+ PrmExport = (PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER*)((UINT8*)mEhdr + Offset);\r
+ PrmHandler = (PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT *)(PrmExport + 1);\r
+\r
+ for (HandlerNum = 0; HandlerNum < PrmExport->NumberPrmHandlers; HandlerNum++) {\r
+ strcpy(mExportSymName[mExportSymNum], PrmHandler->PrmHandlerName);\r
+ mExportSymNum ++;\r
+ PrmHandler += 1;\r
+\r
+ //\r
+ // Check if PRM handler number is larger than (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)\r
+ //\r
+ if (mExportSymNum >= (PRM_MODULE_EXPORT_SYMBOL_NUM - 1)) {\r
+ Error (NULL, 0, 3000, "Invalid", "FindPrmHandler: Number %u is too high.", mExportSymNum);\r
+ exit(EXIT_FAILURE);\r
+ }\r
+ }\r
+}\r
+\r
//\r
// Find the ELF section hosting the GOT from an ELF Rva\r
// of a single GOT entry. Normally, GOT is placed in\r
UINT32 CoffEntry;\r
UINT32 SectionCount;\r
BOOLEAN FoundSection;\r
+ UINT32 Offset;\r
\r
CoffEntry = 0;\r
mCoffOffset = 0;\r
Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName);\r
}\r
\r
+ //\r
+ // The Symbol sections.\r
+ //\r
+ if (mExportFlag) {\r
+ UINT32 SymIndex;\r
+ Elf_Sym *Sym;\r
+ UINT64 SymNum;\r
+ const UINT8 *SymName;\r
+\r
+ mExportOffset = mCoffOffset;\r
+ mExportSize = sizeof(EFI_IMAGE_EXPORT_DIRECTORY) + strlen(mInImageName) + 1;\r
+\r
+ for (i = 0; i < mEhdr->e_shnum; i++) {\r
+\r
+ //\r
+ // Determine if this is a symbol section.\r
+ //\r
+ Elf_Shdr *shdr = GetShdrByIndex(i);\r
+ if (!IsSymbolShdr(shdr)) {\r
+ continue;\r
+ }\r
+\r
+ UINT8 *Symtab = (UINT8*)mEhdr + shdr->sh_offset;\r
+ SymNum = (shdr->sh_size) / (shdr->sh_entsize);\r
+\r
+ //\r
+ // First Get PrmModuleExportDescriptor\r
+ //\r
+ for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {\r
+ Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);\r
+ SymName = GetSymName(Sym);\r
+ if (SymName == NULL) {\r
+ continue;\r
+ }\r
+\r
+ if (strcmp((CHAR8*)SymName, PRM_MODULE_EXPORT_DESCRIPTOR_NAME) == 0) {\r
+ //\r
+ // Find PrmHandler Number and Name\r
+ //\r
+ FindPrmHandler(Sym->st_value);\r
+\r
+ strcpy(mExportSymName[mExportSymNum], (CHAR8*)SymName);\r
+ mExportRVA[mExportSymNum] = (UINT32)(Sym->st_value);\r
+ mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;\r
+ mExportSymNum ++;\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Second Get PrmHandler\r
+ //\r
+ for (SymIndex = 0; SymIndex < SymNum; SymIndex++) {\r
+ UINT32 ExpIndex;\r
+ Sym = (Elf_Sym *)(Symtab + SymIndex * shdr->sh_entsize);\r
+ SymName = GetSymName(Sym);\r
+ if (SymName == NULL) {\r
+ continue;\r
+ }\r
+\r
+ for (ExpIndex = 0; ExpIndex < (mExportSymNum -1); ExpIndex++) {\r
+ if (strcmp((CHAR8*)SymName, mExportSymName[ExpIndex]) != 0) {\r
+ continue;\r
+ }\r
+ mExportRVA[ExpIndex] = (UINT32)(Sym->st_value);\r
+ mExportSize += 2 * EFI_IMAGE_EXPORT_ADDR_SIZE + EFI_IMAGE_EXPORT_ORDINAL_SIZE + strlen((CHAR8 *)SymName) + 1;\r
+ }\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ mCoffOffset += mExportSize;\r
+ mCoffOffset = CoffAlign(mCoffOffset);\r
+ }\r
+\r
//\r
// The HII resource sections.\r
//\r
NtHdr->Pe32Plus.FileHeader.NumberOfSections--;\r
}\r
\r
+ //\r
+ // If found symbol, add edata section between data and rsrc section\r
+ //\r
+ if(mExportFlag) {\r
+ Offset = mExportOffset;\r
+ } else {\r
+ Offset = mHiiRsrcOffset;\r
+ }\r
+\r
if ((mHiiRsrcOffset - mDataOffset) > 0) {\r
- CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset,\r
+ CreateSectionHeader (".data", mDataOffset, Offset - mDataOffset,\r
EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
| EFI_IMAGE_SCN_MEM_WRITE\r
| EFI_IMAGE_SCN_MEM_READ);\r
NtHdr->Pe32Plus.FileHeader.NumberOfSections--;\r
}\r
\r
+ if(mExportFlag) {\r
+ if ((mHiiRsrcOffset - mExportOffset) > 0) {\r
+ CreateSectionHeader (".edata", mExportOffset, mHiiRsrcOffset - mExportOffset,\r
+ EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
+ | EFI_IMAGE_SCN_MEM_READ);\r
+ NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size = mHiiRsrcOffset - mExportOffset;\r
+ NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = mExportOffset;\r
+\r
+ } else {\r
+ // Don't make a section of size 0.\r
+ NtHdr->Pe32Plus.FileHeader.NumberOfSections--;\r
+ }\r
+ }\r
+\r
if ((mRelocOffset - mHiiRsrcOffset) > 0) {\r
CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset,\r
EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
}\r
}\r
\r
+STATIC\r
+VOID\r
+WriteExport64 (\r
+ VOID\r
+ )\r
+{\r
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
+ EFI_IMAGE_EXPORT_DIRECTORY *ExportDir;\r
+ EFI_IMAGE_DATA_DIRECTORY *DataDir;\r
+ UINT32 FileNameOffset;\r
+ UINT32 NameOffset;\r
+ UINT16 Index;\r
+ UINT8 *Tdata = NULL;\r
+\r
+ ExportDir = (EFI_IMAGE_EXPORT_DIRECTORY*)(mCoffFile + mExportOffset);\r
+ ExportDir->Characteristics = 0;\r
+ ExportDir->TimeDateStamp = 0;\r
+ ExportDir->MajorVersion = 0;\r
+ ExportDir->MinorVersion =0;\r
+ ExportDir->Name = 0;\r
+ ExportDir->NumberOfFunctions = mExportSymNum;\r
+ ExportDir->NumberOfNames = mExportSymNum;\r
+ ExportDir->Base = EFI_IMAGE_EXPORT_ORDINAL_BASE;\r
+ ExportDir->AddressOfFunctions = mExportOffset + sizeof(EFI_IMAGE_EXPORT_DIRECTORY);\r
+ ExportDir->AddressOfNames = ExportDir->AddressOfFunctions + EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;\r
+ ExportDir->AddressOfNameOrdinals = ExportDir->AddressOfNames + EFI_IMAGE_EXPORT_ADDR_SIZE * mExportSymNum;\r
+\r
+ FileNameOffset = ExportDir->AddressOfNameOrdinals + EFI_IMAGE_EXPORT_ORDINAL_SIZE * mExportSymNum;\r
+ NameOffset = FileNameOffset + strlen(mInImageName) + 1;\r
+\r
+ // Write Input image Name RVA\r
+ ExportDir->Name = FileNameOffset;\r
+\r
+ // Write Input image Name\r
+ strcpy((char *)(mCoffFile + FileNameOffset), mInImageName);\r
+\r
+ for (Index = 0; Index < mExportSymNum; Index++) {\r
+ //\r
+ // Write Export Address Table\r
+ //\r
+ Tdata = mCoffFile + ExportDir->AddressOfFunctions + Index * EFI_IMAGE_EXPORT_ADDR_SIZE;\r
+ *(UINT32 *)Tdata = mExportRVA[Index];\r
+\r
+ //\r
+ // Write Export Name Pointer Table\r
+ //\r
+ Tdata = mCoffFile + ExportDir->AddressOfNames + Index * EFI_IMAGE_EXPORT_ADDR_SIZE;\r
+ *(UINT32 *)Tdata = NameOffset;\r
+\r
+ //\r
+ // Write Export Ordinal table\r
+ //\r
+ Tdata = mCoffFile + ExportDir->AddressOfNameOrdinals + Index * EFI_IMAGE_EXPORT_ORDINAL_SIZE;\r
+ *(UINT16 *)Tdata = Index;\r
+\r
+ //\r
+ // Write Export Name Table\r
+ //\r
+ strcpy((char *)(mCoffFile + NameOffset), mExportSymName[Index]);\r
+ NameOffset += strlen(mExportSymName[Index]) + 1;\r
+ }\r
+\r
+ NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset);\r
+ DataDir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT];\r
+ DataDir->VirtualAddress = mExportOffset;\r
+ DataDir->Size = mExportSize;\r
+\r
+}\r
\r
extern UINT32 mTableOffset;\r
extern UINT32 mOutImageType;\r
extern UINT32 mFileBufferSize;\r
+extern BOOLEAN mExportFlag;\r
\r
//\r
// Common EFI specific data.\r
#define ELF_HII_SECTION_NAME ".hii"\r
#define ELF_STRTAB_SECTION_NAME ".strtab"\r
#define MAX_COFF_ALIGNMENT 0x10000\r
+#define ELF_SYMBOL_SECTION_NAME ".symtab"\r
+\r
+//\r
+// Platform Runtime Mechanism (PRM) specific data.\r
+//\r
+#define PRM_MODULE_EXPORT_SYMBOL_NUM 256\r
+\r
+// <to-do> to include PRM header directly once PrmPkg is in main repo\r
+#define PRM_HANDLER_NAME_MAXIMUM_LENGTH 128\r
+\r
+#define PRM_MODULE_EXPORT_DESCRIPTOR_NAME "PrmModuleExportDescriptor"\r
+#define PRM_MODULE_EXPORT_DESCRIPTOR_SIGNATURE SIGNATURE_64 ('P', 'R', 'M', '_', 'M', 'E', 'D', 'T')\r
+#define PRM_MODULE_EXPORT_REVISION 0x0\r
+\r
+//\r
+// Platform Runtime Mechanism (PRM) Export Descriptor Structures\r
+//\r
+#pragma pack(push, 1)\r
+\r
+typedef struct {\r
+ EFI_GUID PrmHandlerGuid;\r
+ CHAR8 PrmHandlerName[PRM_HANDLER_NAME_MAXIMUM_LENGTH];\r
+} PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT;\r
+\r
+typedef struct {\r
+ UINT64 Signature;\r
+ UINT16 Revision;\r
+ UINT16 NumberPrmHandlers;\r
+ EFI_GUID PlatformGuid;\r
+ EFI_GUID ModuleGuid;\r
+} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER;\r
+\r
+typedef struct {\r
+ PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT_HEADER Header;\r
+ PRM_HANDLER_EXPORT_DESCRIPTOR_STRUCT PrmHandlerExportDescriptors[1];\r
+} PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT;\r
+\r
+#pragma pack(pop)\r
\r
//\r
// Filter Types\r
typedef enum {\r
SECTION_TEXT,\r
SECTION_HII,\r
- SECTION_DATA\r
+ SECTION_DATA,\r
+ SECTION_SYMBOL\r
\r
} SECTION_FILTER_TYPES;\r
\r
BOOLEAN (*WriteSections) (SECTION_FILTER_TYPES FilterType);\r
VOID (*WriteRelocations) ();\r
VOID (*WriteDebug) ();\r
+ VOID (*WriteExport) ();\r
VOID (*SetImageSize) ();\r
VOID (*CleanUp) ();\r
\r