## @ FspTool.py\r
#\r
-# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
# This program and the accompanying materials are licensed and made available under\r
# the terms and conditions of the BSD License that accompanies this distribution.\r
# The full text of the license may be found at\r
('DataDirectoryDebug', EFI_IMAGE_DATA_DIRECTORY)\r
]\r
\r
+class EFI_IMAGE_DOS_HEADER(Structure):\r
+ _fields_ = [\r
+ ('e_magic', c_uint16),\r
+ ('e_cblp', c_uint16),\r
+ ('e_cp', c_uint16),\r
+ ('e_crlc', c_uint16),\r
+ ('e_cparhdr', c_uint16),\r
+ ('e_minalloc', c_uint16),\r
+ ('e_maxalloc', c_uint16),\r
+ ('e_ss', c_uint16),\r
+ ('e_sp', c_uint16),\r
+ ('e_csum', c_uint16),\r
+ ('e_ip', c_uint16),\r
+ ('e_cs', c_uint16),\r
+ ('e_lfarlc', c_uint16),\r
+ ('e_ovno', c_uint16),\r
+ ('e_res', ARRAY(c_uint16, 4)),\r
+ ('e_oemid', c_uint16),\r
+ ('e_oeminfo', c_uint16),\r
+ ('e_res2', ARRAY(c_uint16, 10)),\r
+ ('e_lfanew', c_uint16)\r
+ ]\r
+\r
+class EFI_IMAGE_FILE_HEADER(Structure):\r
+ _fields_ = [\r
+ ('Machine', c_uint16),\r
+ ('NumberOfSections', c_uint16),\r
+ ('TimeDateStamp', c_uint32),\r
+ ('PointerToSymbolTable', c_uint32),\r
+ ('NumberOfSymbols', c_uint32),\r
+ ('SizeOfOptionalHeader', c_uint16),\r
+ ('Characteristics', c_uint16)\r
+ ]\r
+\r
class PE_RELOC_BLOCK_HEADER(Structure):\r
_fields_ = [\r
('PageRVA', c_uint32),\r
('BlockSize', c_uint32)\r
]\r
\r
+class EFI_IMAGE_OPTIONAL_HEADER32(Structure):\r
+ _fields_ = [\r
+ ('Magic', c_uint16),\r
+ ('MajorLinkerVersion', c_uint8),\r
+ ('MinorLinkerVersion', c_uint8),\r
+ ('SizeOfCode', c_uint32),\r
+ ('SizeOfInitializedData', c_uint32),\r
+ ('SizeOfUninitializedData', c_uint32),\r
+ ('AddressOfEntryPoint', c_uint32),\r
+ ('BaseOfCode', c_uint32),\r
+ ('BaseOfData', c_uint32),\r
+ ('ImageBase', c_uint32),\r
+ ('SectionAlignment', c_uint32),\r
+ ('FileAlignment', c_uint32),\r
+ ('MajorOperatingSystemVersion', c_uint16),\r
+ ('MinorOperatingSystemVersion', c_uint16),\r
+ ('MajorImageVersion', c_uint16),\r
+ ('MinorImageVersion', c_uint16),\r
+ ('MajorSubsystemVersion', c_uint16),\r
+ ('MinorSubsystemVersion', c_uint16),\r
+ ('Win32VersionValue', c_uint32),\r
+ ('SizeOfImage', c_uint32),\r
+ ('SizeOfHeaders', c_uint32),\r
+ ('CheckSum' , c_uint32),\r
+ ('Subsystem', c_uint16),\r
+ ('DllCharacteristics', c_uint16),\r
+ ('SizeOfStackReserve', c_uint32),\r
+ ('SizeOfStackCommit' , c_uint32),\r
+ ('SizeOfHeapReserve', c_uint32),\r
+ ('SizeOfHeapCommit' , c_uint32),\r
+ ('LoaderFlags' , c_uint32),\r
+ ('NumberOfRvaAndSizes', c_uint32),\r
+ ('DataDirectory', ARRAY(EFI_IMAGE_DATA_DIRECTORY, 16))\r
+ ]\r
+\r
+class EFI_IMAGE_OPTIONAL_HEADER32_PLUS(Structure):\r
+ _fields_ = [\r
+ ('Magic', c_uint16),\r
+ ('MajorLinkerVersion', c_uint8),\r
+ ('MinorLinkerVersion', c_uint8),\r
+ ('SizeOfCode', c_uint32),\r
+ ('SizeOfInitializedData', c_uint32),\r
+ ('SizeOfUninitializedData', c_uint32),\r
+ ('AddressOfEntryPoint', c_uint32),\r
+ ('BaseOfCode', c_uint32),\r
+ ('ImageBase', c_uint64),\r
+ ('SectionAlignment', c_uint32),\r
+ ('FileAlignment', c_uint32),\r
+ ('MajorOperatingSystemVersion', c_uint16),\r
+ ('MinorOperatingSystemVersion', c_uint16),\r
+ ('MajorImageVersion', c_uint16),\r
+ ('MinorImageVersion', c_uint16),\r
+ ('MajorSubsystemVersion', c_uint16),\r
+ ('MinorSubsystemVersion', c_uint16),\r
+ ('Win32VersionValue', c_uint32),\r
+ ('SizeOfImage', c_uint32),\r
+ ('SizeOfHeaders', c_uint32),\r
+ ('CheckSum' , c_uint32),\r
+ ('Subsystem', c_uint16),\r
+ ('DllCharacteristics', c_uint16),\r
+ ('SizeOfStackReserve', c_uint64),\r
+ ('SizeOfStackCommit' , c_uint64),\r
+ ('SizeOfHeapReserve', c_uint64),\r
+ ('SizeOfHeapCommit' , c_uint64),\r
+ ('LoaderFlags' , c_uint32),\r
+ ('NumberOfRvaAndSizes', c_uint32),\r
+ ('DataDirectory', ARRAY(EFI_IMAGE_DATA_DIRECTORY, 16))\r
+ ]\r
+\r
+class EFI_IMAGE_OPTIONAL_HEADER(Union):\r
+ _fields_ = [\r
+ ('PeOptHdr', EFI_IMAGE_OPTIONAL_HEADER32),\r
+ ('PePlusOptHdr', EFI_IMAGE_OPTIONAL_HEADER32_PLUS)\r
+ ]\r
+\r
+class EFI_IMAGE_NT_HEADERS32(Structure):\r
+ _fields_ = [\r
+ ('Signature', c_uint32),\r
+ ('FileHeader', EFI_IMAGE_FILE_HEADER),\r
+ ('OptionalHeader', EFI_IMAGE_OPTIONAL_HEADER)\r
+ ]\r
+\r
+\r
+class EFI_IMAGE_DIRECTORY_ENTRY:\r
+ EXPORT = 0\r
+ IMPORT = 1\r
+ RESOURCE = 2\r
+ EXCEPTION = 3\r
+ SECURITY = 4\r
+ BASERELOC = 5\r
+ DEBUG = 6\r
+ COPYRIGHT = 7\r
+ GLOBALPTR = 8\r
+ TLS = 9\r
+ LOAD_CONFIG = 10\r
+\r
class EFI_FV_FILETYPE:\r
ALL = 0x00\r
RAW = 0x01\r
raise Exception("ERROR: Incorrect FV size in image !")\r
self.CheckFsp ()\r
\r
-class TeImage:\r
- def __init__(self, offset, tedata):\r
- self.Offset = offset\r
- self.TeHdr = EFI_TE_IMAGE_HEADER.from_buffer (tedata, 0)\r
- self.TeData = tedata\r
+class PeTeImage:\r
+ def __init__(self, offset, data):\r
+ self.Offset = offset\r
+ tehdr = EFI_TE_IMAGE_HEADER.from_buffer (data, 0)\r
+ if tehdr.Signature == 'VZ': # TE image\r
+ self.TeHdr = tehdr\r
+ elif tehdr.Signature == 'MZ': # PE image\r
+ self.TeHdr = None\r
+ self.DosHdr = EFI_IMAGE_DOS_HEADER.from_buffer (data, 0)\r
+ self.PeHdr = EFI_IMAGE_NT_HEADERS32.from_buffer (data, self.DosHdr.e_lfanew)\r
+ if self.PeHdr.Signature != 0x4550:\r
+ raise Exception("ERROR: Invalid PE32 header !")\r
+ if self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x10b: # PE32 image\r
+ if self.PeHdr.FileHeader.SizeOfOptionalHeader < EFI_IMAGE_OPTIONAL_HEADER32.DataDirectory.offset:\r
+ raise Exception("ERROR: Unsupported PE32 image !")\r
+ if self.PeHdr.OptionalHeader.PeOptHdr.NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC:\r
+ raise Exception("ERROR: No relocation information available !")\r
+ elif self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x20b: # PE32+ image\r
+ if self.PeHdr.FileHeader.SizeOfOptionalHeader < EFI_IMAGE_OPTIONAL_HEADER32_PLUS.DataDirectory.offset:\r
+ raise Exception("ERROR: Unsupported PE32+ image !")\r
+ if self.PeHdr.OptionalHeader.PePlusOptHdr.NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC:\r
+ raise Exception("ERROR: No relocation information available !")\r
+ else:\r
+ raise Exception("ERROR: Invalid PE32 optional header !")\r
+ self.Offset = offset\r
+ self.Data = data\r
self.RelocList = []\r
\r
+ def IsTeImage(self):\r
+ return self.TeHdr is not None\r
+\r
def ParseReloc(self):\r
- rsize = self.TeHdr.DataDirectoryBaseReloc.Size\r
- roffset = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + self.TeHdr.DataDirectoryBaseReloc.VirtualAddress\r
+ if self.IsTeImage():\r
+ rsize = self.TeHdr.DataDirectoryBaseReloc.Size\r
+ roffset = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + self.TeHdr.DataDirectoryBaseReloc.VirtualAddress\r
+ else:\r
+ if self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x10b: # PE32 image\r
+ rsize = self.PeHdr.OptionalHeader.PeOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].Size\r
+ roffset = self.PeHdr.OptionalHeader.PeOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].VirtualAddress\r
+ if self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x20b: # PE32+ image\r
+ rsize = self.PeHdr.OptionalHeader.PePlusOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].Size\r
+ roffset = self.PeHdr.OptionalHeader.PePlusOptHdr.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].VirtualAddress\r
+\r
alignment = 4\r
offset = roffset\r
while offset < roffset + rsize:\r
offset = AlignPtr(offset, 4)\r
- blkhdr = PE_RELOC_BLOCK_HEADER.from_buffer(self.TeData, offset)\r
+ blkhdr = PE_RELOC_BLOCK_HEADER.from_buffer(self.Data, offset)\r
offset += sizeof(blkhdr)\r
# Read relocation type,offset pairs\r
rlen = blkhdr.BlockSize - sizeof(PE_RELOC_BLOCK_HEADER)\r
rnum = rlen/sizeof(c_uint16)\r
- rdata = (c_uint16 * rnum).from_buffer(self.TeData, offset)\r
+ rdata = (c_uint16 * rnum).from_buffer(self.Data, offset)\r
for each in rdata:\r
roff = each & 0xfff\r
rtype = each >> 12\r
- if rtype == 0: # IMAGE_REL_BASED.ABSOLUTE:\r
+ if rtype == 0: # IMAGE_REL_BASED_ABSOLUTE:\r
continue\r
- if rtype != 3: # IMAGE_REL_BASED_HIGHLOW\r
+ if ((rtype != 3) and (rtype != 10)): # IMAGE_REL_BASED_HIGHLOW and IMAGE_REL_BASED_DIR64\r
raise Exception("ERROR: Unsupported relocation type %d!" % rtype)\r
# Calculate the offset of the relocation\r
- aoff = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + blkhdr.PageRVA + roff\r
+ aoff = blkhdr.PageRVA + roff\r
+ if self.IsTeImage():\r
+ aoff += sizeof(self.TeHdr) - self.TeHdr.StrippedSize\r
self.RelocList.append((rtype, aoff))\r
offset += sizeof(rdata)\r
\r
return count\r
\r
for (rtype, roff) in self.RelocList:\r
- if rtype == 0x03: # HIGHLOW\r
+ if rtype == 3: # IMAGE_REL_BASED_HIGHLOW\r
offset = roff + self.Offset\r
value = Bytes2Val(fdbin[offset:offset+sizeof(c_uint32)])\r
value += delta\r
fdbin[offset:offset+sizeof(c_uint32)] = Val2Bytes(value, sizeof(c_uint32))\r
count += 1\r
+ elif rtype == 10: # IMAGE_REL_BASED_DIR64\r
+ offset = roff + self.Offset\r
+ value = Bytes2Val(fdbin[offset:offset+sizeof(c_uint64)])\r
+ value += delta\r
+ fdbin[offset:offset+sizeof(c_uint64)] = Val2Bytes(value, sizeof(c_uint64))\r
+ count += 1\r
else:\r
raise Exception('ERROR: Unknown relocation type %d !' % rtype)\r
\r
- tehdr = self.TeHdr\r
- tehdr.ImageBase += delta\r
- offset = self.Offset\r
- fdbin[offset:offset+sizeof(tehdr)] = bytearray(tehdr)\r
+ if self.IsTeImage():\r
+ offset = self.Offset + EFI_TE_IMAGE_HEADER.ImageBase.offset\r
+ size = EFI_TE_IMAGE_HEADER.ImageBase.size\r
+ else:\r
+ offset = self.Offset + self.DosHdr.e_lfanew\r
+ offset += EFI_IMAGE_NT_HEADERS32.OptionalHeader.offset\r
+ offset += EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.offset\r
+ size = EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.size\r
+\r
+ value = Bytes2Val(fdbin[offset:offset+size]) + delta\r
+ fdbin[offset:offset+size] = Val2Bytes(value, size)\r
\r
return count\r
\r
fspname, ext = os.path.splitext(os.path.basename(nametemplate))\r
filename = os.path.join(outdir, fspname + '_' + fsp.Type + ext)\r
hfsp = open(filename, 'wb')\r
- print ("Ceate FSP component file '%s'" % filename)\r
+ print ("Create FSP component file '%s'" % filename)\r
for fvidx in fsp.FvIdxList:\r
fv = fd.FvList[fvidx]\r
hfsp.write(fv.FvData)\r
delta = newbase - oldbase\r
print "Rebase FSP-%c from 0x%08X to 0x%08X:" % (ftype.upper(),oldbase,newbase)\r
\r
- telist = []\r
+ imglist = []\r
for fvidx in fsp.FvIdxList:\r
fv = fd.FvList[fvidx]\r
for ffs in fv.FfsList:\r
for sec in ffs.SecList:\r
- if sec.SecHdr.Type == EFI_SECTION_TYPE.TE: # TE\r
+ if sec.SecHdr.Type in [EFI_SECTION_TYPE.TE, EFI_SECTION_TYPE.PE32]: # TE or PE32\r
offset = fd.Offset + fv.Offset + ffs.Offset + sec.Offset + sizeof(sec.SecHdr)\r
- telist.append ((offset, len(sec.SecData) - sizeof(sec.SecHdr)))\r
- elif sec.SecHdr.Type == EFI_SECTION_TYPE.PE32: # PE\r
- raise Exception("ERROR: PE32 Section is not supported !")\r
+ imglist.append ((offset, len(sec.SecData) - sizeof(sec.SecHdr)))\r
\r
fcount = 0\r
- tecount = 0\r
- for (teoffset, telen) in telist:\r
- tehdr = EFI_TE_IMAGE_HEADER.from_buffer (fd.FdData, teoffset)\r
- if 'VZ' != tehdr.Signature:\r
- raise Exception("ERROR: Invalid TE header !")\r
- te = TeImage(teoffset, fd.FdData[teoffset:teoffset + telen])\r
- te.ParseReloc()\r
- tecount += te.Rebase(delta, newfspbin)\r
- fcount += 1\r
- print " Patched %d entries in %d TE images." % (tecount, fcount)\r
+ pcount = 0\r
+ for (offset, length) in imglist:\r
+ img = PeTeImage(offset, fd.FdData[offset:offset + length])\r
+ img.ParseReloc()\r
+ pcount += img.Rebase(delta, newfspbin)\r
+ fcount += 1\r
+\r
+ print " Patched %d entries in %d TE/PE32 images." % (pcount, fcount)\r
\r
(count, applied) = fsp.Patch(delta, newfspbin)\r
print " Patched %d entries using FSP patch table." % applied\r