STATIC VOID WriteDebug64 ( VOID ) { UINT32 Len; UINT32 DebugOffset; EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; EFI_IMAGE_DATA_DIRECTORY *DataDir; EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir; EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10; Len = strlen(mInImageName) + 1; DebugOffset = mCoffOffset; mCoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len; mCoffOffset = CoffAlign(mCoffOffset); mCoffFile = realloc(mCoffFile, mCoffOffset); memset(mCoffFile + DebugOffset, 0, mCoffOffset - DebugOffset); Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + DebugOffset); Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW; Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len; Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1); Nb10->Signature = CODEVIEW_SIGNATURE_NB10; strcpy ((char *)(Nb10 + 1), mInImageName); NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); DataDir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]; DataDir->VirtualAddress = DebugOffset; DataDir->Size = mCoffOffset - DebugOffset; if (DataDir->Size == 0) { // If no debug, null out the directory entry and don't add the .debug section DataDir->VirtualAddress = 0; NtHdr->Pe32Plus.FileHeader.NumberOfSections--; } else { DataDir->VirtualAddress = DebugOffset; CreateSectionHeader (".debug", DebugOffset, mCoffOffset - DebugOffset, EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_DISCARDABLE | EFI_IMAGE_SCN_MEM_READ); } }
STATIC VOID ScanSections32 ( VOID ) { UINT32 i; EFI_IMAGE_DOS_HEADER *DosHdr; EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; UINT32 CoffEntry; UINT32 SectionCount; BOOLEAN FoundSection; CoffEntry = 0; mCoffOffset = 0; // // Coff file start with a DOS header. // mCoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40; mNtHdrOffset = mCoffOffset; switch (mEhdr->e_machine) { case EM_386: case EM_ARM: mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32); break; default: VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine); mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32); break; } mTableOffset = mCoffOffset; mCoffOffset += mCoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER); // // First text sections. // mCoffOffset = CoffAlign(mCoffOffset); mTextOffset = mCoffOffset; FoundSection = FALSE; SectionCount = 0; for (i = 0; i < mEhdr->e_shnum; i++) { Elf_Shdr *shdr = GetShdrByIndex(i); if (IsTextShdr(shdr)) { if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { // the alignment field is valid if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { // if the section address is aligned we must align PE/COFF mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) { // ARM RVCT tools have behavior outside of the ELF specification to try // and make images smaller. If sh_addr is not aligned to sh_addralign // then the section needs to preserve sh_addr MOD sh_addralign. // Normally doing nothing here works great. Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment."); } } /* Relocate entry. */ if ((mEhdr->e_entry >= shdr->sh_addr) && (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) { CoffEntry = mCoffOffset + mEhdr->e_entry - shdr->sh_addr; } // // Set mTextOffset with the offset of the first '.text' section // if (!FoundSection) { mTextOffset = mCoffOffset; FoundSection = TRUE; } mCoffSectionsOffset[i] = mCoffOffset; mCoffOffset += shdr->sh_size; SectionCount ++; } } if (!FoundSection) { Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section."); assert (FALSE); } if (mEhdr->e_machine != EM_ARM) { mCoffOffset = CoffAlign(mCoffOffset); } if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) { Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName); } // // Then data sections. // mDataOffset = mCoffOffset; FoundSection = FALSE; SectionCount = 0; for (i = 0; i < mEhdr->e_shnum; i++) { Elf_Shdr *shdr = GetShdrByIndex(i); if (IsDataShdr(shdr)) { if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { // the alignment field is valid if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { // if the section address is aligned we must align PE/COFF mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) { // ARM RVCT tools have behavior outside of the ELF specification to try // and make images smaller. If sh_addr is not aligned to sh_addralign // then the section needs to preserve sh_addr MOD sh_addralign. // Normally doing nothing here works great. Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment."); } } // // Set mDataOffset with the offset of the first '.data' section // if (!FoundSection) { mDataOffset = mCoffOffset; FoundSection = TRUE; } mCoffSectionsOffset[i] = mCoffOffset; mCoffOffset += shdr->sh_size; SectionCount ++; } } mCoffOffset = CoffAlign(mCoffOffset); if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) { Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName); } // // The HII resource sections. // mHiiRsrcOffset = mCoffOffset; for (i = 0; i < mEhdr->e_shnum; i++) { Elf_Shdr *shdr = GetShdrByIndex(i); if (IsHiiRsrcShdr(shdr)) { if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { // the alignment field is valid if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { // if the section address is aligned we must align PE/COFF mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); } else if ((shdr->sh_addr % shdr->sh_addralign) != (mCoffOffset % shdr->sh_addralign)) { // ARM RVCT tools have behavior outside of the ELF specification to try // and make images smaller. If sh_addr is not aligned to sh_addralign // then the section needs to preserve sh_addr MOD sh_addralign. // Normally doing nothing here works great. Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment."); } } if (shdr->sh_size != 0) { mHiiRsrcOffset = mCoffOffset; mCoffSectionsOffset[i] = mCoffOffset; mCoffOffset += shdr->sh_size; mCoffOffset = CoffAlign(mCoffOffset); SetHiiResourceHeader ((UINT8*) mEhdr + shdr->sh_offset, mHiiRsrcOffset); } break; } } mRelocOffset = mCoffOffset; // // Allocate base Coff file. Will be expanded later for relocations. // mCoffFile = (UINT8 *)malloc(mCoffOffset); memset(mCoffFile, 0, mCoffOffset); // // Fill headers. // DosHdr = (EFI_IMAGE_DOS_HEADER *)mCoffFile; DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE; DosHdr->e_lfanew = mNtHdrOffset; NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(mCoffFile + mNtHdrOffset); NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE; switch (mEhdr->e_machine) { case EM_386: NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32; NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; break; case EM_ARM: NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT; NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; break; default: VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine); NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32; NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; } NtHdr->Pe32.FileHeader.NumberOfSections = mCoffNbrSections; NtHdr->Pe32.FileHeader.TimeDateStamp = (UINT32) time(NULL); mImageTimeStamp = NtHdr->Pe32.FileHeader.TimeDateStamp; NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0; NtHdr->Pe32.FileHeader.NumberOfSymbols = 0; NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader); NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED | EFI_IMAGE_FILE_32BIT_MACHINE; NtHdr->Pe32.OptionalHeader.SizeOfCode = mDataOffset - mTextOffset; NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = mRelocOffset - mDataOffset; NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0; NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry; NtHdr->Pe32.OptionalHeader.BaseOfCode = mTextOffset; NtHdr->Pe32.OptionalHeader.BaseOfData = mDataOffset; NtHdr->Pe32.OptionalHeader.ImageBase = 0; NtHdr->Pe32.OptionalHeader.SectionAlignment = mCoffAlignment; NtHdr->Pe32.OptionalHeader.FileAlignment = mCoffAlignment; NtHdr->Pe32.OptionalHeader.SizeOfImage = 0; NtHdr->Pe32.OptionalHeader.SizeOfHeaders = mTextOffset; NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; // // Section headers. // if ((mDataOffset - mTextOffset) > 0) { CreateSectionHeader (".text", mTextOffset, mDataOffset - mTextOffset, EFI_IMAGE_SCN_CNT_CODE | EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_MEM_READ); } else { // Don't make a section of size 0. NtHdr->Pe32.FileHeader.NumberOfSections--; } if ((mHiiRsrcOffset - mDataOffset) > 0) { CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset, EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_WRITE | EFI_IMAGE_SCN_MEM_READ); } else { // Don't make a section of size 0. NtHdr->Pe32.FileHeader.NumberOfSections--; } if ((mRelocOffset - mHiiRsrcOffset) > 0) { CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset, EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_READ); NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset; NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset; } else { // Don't make a section of size 0. NtHdr->Pe32.FileHeader.NumberOfSections--; } }
STATIC VOID WriteRelocations64 ( VOID ) { UINT32 Index; EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; EFI_IMAGE_DATA_DIRECTORY *Dir; for (Index = 0; Index < mEhdr->e_shnum; Index++) { Elf_Shdr *RelShdr = GetShdrByIndex(Index); if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) { Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info); if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) { UINT64 RelIdx; for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) { Elf_Rela *Rel = (Elf_Rela *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx); if (mEhdr->e_machine == EM_X86_64) { switch (ELF_R_TYPE(Rel->r_info)) { case R_X86_64_NONE: case R_X86_64_PC32: break; case R_X86_64_64: VerboseMsg ("EFI_IMAGE_REL_BASED_DIR64 Offset: 0x%08X", mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)); CoffAddFixup( (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)), EFI_IMAGE_REL_BASED_DIR64); break; case R_X86_64_32S: case R_X86_64_32: VerboseMsg ("EFI_IMAGE_REL_BASED_HIGHLOW Offset: 0x%08X", mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)); CoffAddFixup( (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)), EFI_IMAGE_REL_BASED_HIGHLOW); break; default: Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_X86_64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); } } else { Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) mEhdr->e_machine); } } } } } // // Pad by adding empty entries. // while (mCoffOffset & (mCoffAlignment - 1)) { CoffAddFixupEntry(0); } NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); Dir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; Dir->Size = mCoffOffset - mRelocOffset; if (Dir->Size == 0) { // If no relocations, null out the directory entry and don't add the .reloc section Dir->VirtualAddress = 0; NtHdr->Pe32Plus.FileHeader.NumberOfSections--; } else { Dir->VirtualAddress = mRelocOffset; CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset, EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_DISCARDABLE | EFI_IMAGE_SCN_MEM_READ); } }
STATIC VOID ScanSections32 ( VOID ) { UINT32 i; EFI_IMAGE_DOS_HEADER *DosHdr; EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; UINT32 CoffEntry; UINT32 SectionCount; BOOLEAN FoundSection; CoffEntry = 0; mCoffOffset = 0; // // Coff file start with a DOS header. // mCoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40; mNtHdrOffset = mCoffOffset; switch (mEhdr->e_machine) { case EM_386: case EM_ARM: mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32); break; default: VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine); mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32); break; } mTableOffset = mCoffOffset; mCoffOffset += mCoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER); // // Set mCoffAlignment to the maximum alignment of the input sections // we care about // for (i = 0; i < mEhdr->e_shnum; i++) { Elf_Shdr *shdr = GetShdrByIndex(i); if (shdr->sh_addralign <= mCoffAlignment) { continue; } if (IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr)) { mCoffAlignment = (UINT32)shdr->sh_addralign; } } // // Move the PE/COFF header right before the first section. This will help us // save space when converting to TE. // if (mCoffAlignment > mCoffOffset) { mNtHdrOffset += mCoffAlignment - mCoffOffset; mTableOffset += mCoffAlignment - mCoffOffset; mCoffOffset = mCoffAlignment; } // // First text sections. // mCoffOffset = CoffAlign(mCoffOffset); mTextOffset = mCoffOffset; FoundSection = FALSE; SectionCount = 0; for (i = 0; i < mEhdr->e_shnum; i++) { Elf_Shdr *shdr = GetShdrByIndex(i); if (IsTextShdr(shdr)) { if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { // the alignment field is valid if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { // if the section address is aligned we must align PE/COFF mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); } else { Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); } } /* Relocate entry. */ if ((mEhdr->e_entry >= shdr->sh_addr) && (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) { CoffEntry = mCoffOffset + mEhdr->e_entry - shdr->sh_addr; } // // Set mTextOffset with the offset of the first '.text' section // if (!FoundSection) { mTextOffset = mCoffOffset; FoundSection = TRUE; } mCoffSectionsOffset[i] = mCoffOffset; mCoffOffset += shdr->sh_size; SectionCount ++; } } if (!FoundSection) { Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section."); assert (FALSE); } mDebugOffset = DebugRvaAlign(mCoffOffset); mCoffOffset = CoffAlign(mCoffOffset); if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) { Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName); } // // Then data sections. // mDataOffset = mCoffOffset; FoundSection = FALSE; SectionCount = 0; for (i = 0; i < mEhdr->e_shnum; i++) { Elf_Shdr *shdr = GetShdrByIndex(i); if (IsDataShdr(shdr)) { if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { // the alignment field is valid if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { // if the section address is aligned we must align PE/COFF mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); } else { Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); } } // // Set mDataOffset with the offset of the first '.data' section // if (!FoundSection) { mDataOffset = mCoffOffset; FoundSection = TRUE; } mCoffSectionsOffset[i] = mCoffOffset; mCoffOffset += shdr->sh_size; SectionCount ++; } } if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) { Warning (NULL, 0, 0, NULL, "Mulitple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName); } // // Make room for .debug data in .data (or .text if .data is empty) instead of // putting it in a section of its own. This is explicitly allowed by the // PE/COFF spec, and prevents bloat in the binary when using large values for // section alignment. // if (SectionCount > 0) { mDebugOffset = DebugRvaAlign(mCoffOffset); } mCoffOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + strlen(mInImageName) + 1; mCoffOffset = CoffAlign(mCoffOffset); if (SectionCount == 0) { mDataOffset = mCoffOffset; } // // The HII resource sections. // mHiiRsrcOffset = mCoffOffset; for (i = 0; i < mEhdr->e_shnum; i++) { Elf_Shdr *shdr = GetShdrByIndex(i); if (IsHiiRsrcShdr(shdr)) { if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { // the alignment field is valid if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { // if the section address is aligned we must align PE/COFF mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); } else { Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); } } if (shdr->sh_size != 0) { mHiiRsrcOffset = mCoffOffset; mCoffSectionsOffset[i] = mCoffOffset; mCoffOffset += shdr->sh_size; mCoffOffset = CoffAlign(mCoffOffset); SetHiiResourceHeader ((UINT8*) mEhdr + shdr->sh_offset, mHiiRsrcOffset); } break; } } mRelocOffset = mCoffOffset; // // Allocate base Coff file. Will be expanded later for relocations. // mCoffFile = (UINT8 *)malloc(mCoffOffset); memset(mCoffFile, 0, mCoffOffset); // // Fill headers. // DosHdr = (EFI_IMAGE_DOS_HEADER *)mCoffFile; DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE; DosHdr->e_lfanew = mNtHdrOffset; NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(mCoffFile + mNtHdrOffset); NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE; switch (mEhdr->e_machine) { case EM_386: NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32; NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; break; case EM_ARM: NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT; NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; break; default: VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine); NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32; NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; } NtHdr->Pe32.FileHeader.NumberOfSections = mCoffNbrSections; NtHdr->Pe32.FileHeader.TimeDateStamp = (UINT32) time(NULL); mImageTimeStamp = NtHdr->Pe32.FileHeader.TimeDateStamp; NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0; NtHdr->Pe32.FileHeader.NumberOfSymbols = 0; NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader); NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED | EFI_IMAGE_FILE_32BIT_MACHINE; NtHdr->Pe32.OptionalHeader.SizeOfCode = mDataOffset - mTextOffset; NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = mRelocOffset - mDataOffset; NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0; NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry; NtHdr->Pe32.OptionalHeader.BaseOfCode = mTextOffset; NtHdr->Pe32.OptionalHeader.BaseOfData = mDataOffset; NtHdr->Pe32.OptionalHeader.ImageBase = 0; NtHdr->Pe32.OptionalHeader.SectionAlignment = mCoffAlignment; NtHdr->Pe32.OptionalHeader.FileAlignment = mCoffAlignment; NtHdr->Pe32.OptionalHeader.SizeOfImage = 0; NtHdr->Pe32.OptionalHeader.SizeOfHeaders = mTextOffset; NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; // // Section headers. // if ((mDataOffset - mTextOffset) > 0) { CreateSectionHeader (".text", mTextOffset, mDataOffset - mTextOffset, EFI_IMAGE_SCN_CNT_CODE | EFI_IMAGE_SCN_MEM_EXECUTE | EFI_IMAGE_SCN_MEM_READ); } else { // Don't make a section of size 0. NtHdr->Pe32.FileHeader.NumberOfSections--; } if ((mHiiRsrcOffset - mDataOffset) > 0) { CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset, EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_WRITE | EFI_IMAGE_SCN_MEM_READ); } else { // Don't make a section of size 0. NtHdr->Pe32.FileHeader.NumberOfSections--; } if ((mRelocOffset - mHiiRsrcOffset) > 0) { CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset, EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_READ); NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset; NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset; } else { // Don't make a section of size 0. NtHdr->Pe32.FileHeader.NumberOfSections--; } }