]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFsp2Pkg/Tools/SplitFspBin.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / IntelFsp2Pkg / Tools / SplitFspBin.py
index 5d56aebbd730eb9a054bec7414a5933c920d4d2b..419e5ba9850ef42057c43dfa549fa59d434c2b1c 100644 (file)
@@ -1,13 +1,7 @@
-## @ FspTool.py\r
+## @ SplitFspBin.py\r
 #\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
-# http://opensource.org/licenses/bsd-license.php.\r
-#\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+# Copyright (c) 2015 - 2022, Intel Corporation. All rights reserved.<BR>\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
 #\r
 ##\r
 \r
@@ -18,14 +12,15 @@ import copy
 import struct\r
 import argparse\r
 from   ctypes import *\r
+from functools import reduce\r
 \r
 """\r
-This utility supports some operations for Intel FSP 2.0 image.\r
+This utility supports some operations for Intel FSP 1.x/2.x image.\r
 It supports:\r
-    - Display FSP 2.0 information header\r
-    - Split FSP 2.0 image into individual FSP-T/M/S/O component\r
-    - Rebase FSP 2.0 components to a different base address\r
-    - Generate FSP mapping C header file\r
+    - Display FSP 1.x/2.x information header\r
+    - Split FSP 2.x image into individual FSP-T/M/S/O component\r
+    - Rebase FSP 1.x/2.x components to a different base address\r
+    - Generate FSP 1.x/2.x mapping C header file\r
 """\r
 \r
 CopyRightHeaderFile = """/*\r
@@ -108,26 +103,31 @@ class FSP_COMMON_HEADER(Structure):
 \r
 class FSP_INFORMATION_HEADER(Structure):\r
      _fields_ = [\r
-        ('Signature',            ARRAY(c_char, 4)),\r
-        ('HeaderLength',         c_uint32),\r
-        ('Reserved1',            c_uint16),\r
-        ('SpecVersion',          c_uint8),\r
-        ('HeaderRevision',       c_uint8),\r
-        ('ImageRevision',        c_uint32),\r
-        ('ImageId',              ARRAY(c_char, 8)),\r
-        ('ImageSize',            c_uint32),\r
-        ('ImageBase',            c_uint32),\r
-        ('ImageAttribute',       c_uint16),\r
-        ('ComponentAttribute',   c_uint16),\r
-        ('CfgRegionOffset',      c_uint32),\r
-        ('CfgRegionSize',        c_uint32),\r
-        ('Reserved2',            c_uint32),\r
-        ('TempRamInitEntryOffset',     c_uint32),\r
-        ('Reserved3',                  c_uint32),\r
-        ('NotifyPhaseEntryOffset',     c_uint32),\r
-        ('FspMemoryInitEntryOffset',   c_uint32),\r
-        ('TempRamExitEntryOffset',     c_uint32),\r
-        ('FspSiliconInitEntryOffset',  c_uint32)\r
+        ('Signature',                       ARRAY(c_char, 4)),\r
+        ('HeaderLength',                    c_uint32),\r
+        ('Reserved1',                       c_uint16),\r
+        ('SpecVersion',                     c_uint8),\r
+        ('HeaderRevision',                  c_uint8),\r
+        ('ImageRevision',                   c_uint32),\r
+        ('ImageId',                         ARRAY(c_char, 8)),\r
+        ('ImageSize',                       c_uint32),\r
+        ('ImageBase',                       c_uint32),\r
+        ('ImageAttribute',                  c_uint16),\r
+        ('ComponentAttribute',              c_uint16),\r
+        ('CfgRegionOffset',                 c_uint32),\r
+        ('CfgRegionSize',                   c_uint32),\r
+        ('Reserved2',                       c_uint32),\r
+        ('TempRamInitEntryOffset',          c_uint32),\r
+        ('Reserved3',                       c_uint32),\r
+        ('NotifyPhaseEntryOffset',          c_uint32),\r
+        ('FspMemoryInitEntryOffset',        c_uint32),\r
+        ('TempRamExitEntryOffset',          c_uint32),\r
+        ('FspSiliconInitEntryOffset',       c_uint32),\r
+        ('FspMultiPhaseSiInitEntryOffset',  c_uint32),\r
+        ('ExtendedImageRevision',           c_uint16),\r
+        ('Reserved4',                       c_uint16),\r
+        ('FspMultiPhaseMemInitEntryOffset', c_uint32),\r
+        ('FspSmmInitEntryOffset',           c_uint32)\r
     ]\r
 \r
 class FSP_PATCH_TABLE(Structure):\r
@@ -346,6 +346,31 @@ def Bytes2Val (bytes):
 def Val2Bytes (value, blen):\r
     return [(value>>(i*8) & 0xff) for i in range(blen)]\r
 \r
+def IsIntegerType (val):\r
+    if sys.version_info[0] < 3:\r
+        if type(val) in (int, long):\r
+            return True\r
+    else:\r
+        if type(val) is int:\r
+            return True\r
+    return False\r
+\r
+def IsStrType (val):\r
+    if sys.version_info[0] < 3:\r
+        if type(val) is str:\r
+            return True\r
+    else:\r
+        if type(val) is bytes:\r
+            return True\r
+    return False\r
+\r
+def HandleNameStr (val):\r
+    if sys.version_info[0] < 3:\r
+        rep = "0x%X ('%s')" % (Bytes2Val (bytearray (val)), val)\r
+    else:\r
+        rep = "0x%X ('%s')" % (Bytes2Val (bytearray (val)), str (val, 'utf-8'))\r
+    return rep\r
+\r
 def OutputStruct (obj, indent = 0, plen = 0):\r
     if indent:\r
         body = ''\r
@@ -367,15 +392,38 @@ def OutputStruct (obj, indent = 0, plen = 0):
             body += OutputStruct (val, indent + 1)\r
             plen -= sizeof(val)\r
         else:\r
-            if type(val) is str:\r
-                rep = "0x%X ('%s')" % (Bytes2Val(bytearray(val)), val)\r
-            elif type(val) in (int, long):\r
-                rep = '0x%X' % val\r
+            if IsStrType (val):\r
+                rep = HandleNameStr (val)\r
+            elif IsIntegerType (val):\r
+                if (key == 'ImageRevision'):\r
+                    FspImageRevisionMajor       = ((val >> 24) & 0xFF)\r
+                    FspImageRevisionMinor       = ((val >> 16) & 0xFF)\r
+                    FspImageRevisionRevision    = ((val >> 8) & 0xFF)\r
+                    FspImageRevisionBuildNumber = (val & 0xFF)\r
+                    rep = '0x%08X' % val\r
+                elif (key == 'ExtendedImageRevision'):\r
+                    FspImageRevisionRevision    |= (val & 0xFF00)\r
+                    FspImageRevisionBuildNumber |= ((val << 8) & 0xFF00)\r
+                    rep = "0x%04X ('%02X.%02X.%04X.%04X')" % (val, FspImageRevisionMajor, FspImageRevisionMinor, FspImageRevisionRevision, FspImageRevisionBuildNumber)\r
+                elif field[1] == c_uint64:\r
+                    rep = '0x%016X' % val\r
+                elif field[1] == c_uint32:\r
+                    rep = '0x%08X' % val\r
+                elif field[1] == c_uint16:\r
+                    rep = '0x%04X' % val\r
+                elif field[1] == c_uint8:\r
+                    rep = '0x%02X' % val\r
+                else:\r
+                    rep = '0x%X' % val\r
             elif isinstance(val, c_uint24):\r
                 rep = '0x%X' % val.get_value()\r
             elif 'c_ubyte_Array' in str(type(val)):\r
                 if sizeof(val) == 16:\r
-                    rep = str(uuid.UUID(bytes = str(bytearray(val)))).upper()\r
+                    if sys.version_info[0] < 3:\r
+                        rep = str(bytearray(val))\r
+                    else:\r
+                        rep = bytes(val)\r
+                    rep = str(uuid.UUID(bytes_le = rep)).upper()\r
                 else:\r
                     res = ['0x%02X'%i for i in bytearray(val)]\r
                     rep = '[%s]' % (','.join(res))\r
@@ -404,7 +452,7 @@ class FirmwareFile:
         ffssize = len(self.FfsData)\r
         offset  = sizeof(self.FfsHdr)\r
         if self.FfsHdr.Name != '\xff' * 16:\r
-            while offset < ffssize:\r
+            while offset < (ffssize - sizeof (EFI_COMMON_SECTION_HEADER)):\r
                 sechdr = EFI_COMMON_SECTION_HEADER.from_buffer (self.FfsData, offset)\r
                 sec = Section (offset, self.FfsData[offset:offset + int(sechdr.Size)])\r
                 self.SecList.append(sec)\r
@@ -429,7 +477,7 @@ class FirmwareVolume:
         else:\r
             offset = self.FvHdr.HeaderLength\r
         offset = AlignPtr(offset)\r
-        while offset < fvsize:\r
+        while offset < (fvsize - sizeof (EFI_FFS_FILE_HEADER)):\r
             ffshdr = EFI_FFS_FILE_HEADER.from_buffer (self.FvData, offset)\r
             if (ffshdr.Name == '\xff' * 16) and (int(ffshdr.Size) == 0xFFFFFF):\r
                 offset = fvsize\r
@@ -446,7 +494,7 @@ class FspImage:
         self.FihOffset = fihoff\r
         self.Offset    = offset\r
         self.FvIdxList = []\r
-        self.Type      = "XTMSXXXXOXXXXXXX"[(fih.ComponentAttribute >> 12) & 0x0F]\r
+        self.Type      = "XTMSIXXXOXXXXXXX"[(fih.ComponentAttribute >> 12) & 0x0F]\r
         self.PatchList = patch\r
         self.PatchList.append(fihoff + 0x1C)\r
 \r
@@ -491,9 +539,9 @@ class FirmwareDevice:
         offset = 0\r
         fdsize = len(self.FdData)\r
         self.FvList  = []\r
-        while offset < fdsize:\r
+        while offset < (fdsize - sizeof (EFI_FIRMWARE_VOLUME_HEADER)):\r
             fvh = EFI_FIRMWARE_VOLUME_HEADER.from_buffer (self.FdData, offset)\r
-            if '_FVH' != fvh.Signature:\r
+            if b'_FVH' != fvh.Signature:\r
                 raise Exception("ERROR: Invalid FV header !")\r
             fv = FirmwareVolume (offset, self.FdData[offset:offset + fvh.FvLength])\r
             fv.ParseFv ()\r
@@ -506,8 +554,6 @@ class FirmwareDevice:
 \r
         fih = None\r
         for fsp in self.FspList:\r
-            if fsp.Fih.HeaderRevision < 3:\r
-                raise Exception("ERROR: FSP 1.x is not supported by this tool !")\r
             if not fih:\r
                 fih = fsp.Fih\r
             else:\r
@@ -532,7 +578,7 @@ class FirmwareDevice:
                 fspoffset = fv.Offset\r
                 offset    = fspoffset + fihoffset\r
                 fih = FSP_INFORMATION_HEADER.from_buffer (self.FdData, offset)\r
-                if 'FSPH' != fih.Signature:\r
+                if b'FSPH' != fih.Signature:\r
                     continue\r
 \r
                 offset += fih.HeaderLength\r
@@ -540,7 +586,7 @@ class FirmwareDevice:
                 plist  = []\r
                 while True:\r
                     fch = FSP_COMMON_HEADER.from_buffer (self.FdData, offset)\r
-                    if 'FSPP' != fch.Signature:\r
+                    if b'FSPP' != fch.Signature:\r
                         offset += fch.HeaderLength\r
                         offset = AlignPtr(offset, 4)\r
                     else:\r
@@ -565,9 +611,9 @@ class PeTeImage:
     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
+        if   tehdr.Signature == b'VZ': # TE image\r
             self.TeHdr   = tehdr\r
-        elif tehdr.Signature == 'MZ': # PE image\r
+        elif tehdr.Signature == b'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
@@ -597,10 +643,10 @@ class PeTeImage:
             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
+            # Assuming PE32 image type (self.PeHdr.OptionalHeader.PeOptHdr.Magic == 0x10b)\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.PePlusOptHdr.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
@@ -612,7 +658,7 @@ class PeTeImage:
             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
+            rnum  = int (rlen/sizeof(c_uint16))\r
             rdata = (c_uint16 * rnum).from_buffer(self.Data, offset)\r
             for each in rdata:\r
                 roff  = each & 0xfff\r
@@ -655,8 +701,12 @@ class PeTeImage:
         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
+            if self.PeHdr.OptionalHeader.PePlusOptHdr.Magic == 0x20b: # PE32+ image\r
+                offset += EFI_IMAGE_OPTIONAL_HEADER32_PLUS.ImageBase.offset\r
+                size    = EFI_IMAGE_OPTIONAL_HEADER32_PLUS.ImageBase.size\r
+            else:\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
@@ -674,8 +724,11 @@ def ShowFspInfo (fspfile):
         if not name:\r
             name = '\xff' * 16\r
         else:\r
-            name = str(bytearray(name))\r
-        guid = uuid.UUID(bytes = name)\r
+            if sys.version_info[0] < 3:\r
+                name = str(bytearray(name))\r
+            else:\r
+                name = bytes(name)\r
+        guid = uuid.UUID(bytes_le = name)\r
         print ("FV%d:" % idx)\r
         print ("  GUID   : %s" % str(guid).upper())\r
         print ("  Offset : 0x%08X" %  fv.Offset)\r
@@ -703,7 +756,10 @@ def GenFspHdr (fspfile, outdir, hfile):
     for fsp in fd.FspList:\r
         fih = fsp.Fih\r
         if firstfv:\r
-            hfsp.write("#define  FSP_IMAGE_ID    0x%016X    /* '%s' */\n" % (Bytes2Val(bytearray(fih.ImageId)), fih.ImageId))\r
+            if sys.version_info[0] < 3:\r
+                hfsp.write("#define  FSP_IMAGE_ID    0x%016X    /* '%s' */\n" % (Bytes2Val(bytearray(fih.ImageId)), fih.ImageId))\r
+            else:\r
+                hfsp.write("#define  FSP_IMAGE_ID    0x%016X    /* '%s' */\n" % (Bytes2Val(bytearray(fih.ImageId)), str (fih.ImageId, 'utf-8')))\r
             hfsp.write("#define  FSP_IMAGE_REV   0x%08X \n\n" % fih.ImageRevision)\r
             firstfv = False\r
         fv = fd.FvList[fsp.FvIdxList[0]]\r
@@ -719,6 +775,8 @@ def SplitFspBin (fspfile, outdir, nametemplate):
     fd.ParseFsp ()\r
 \r
     for fsp in fd.FspList:\r
+        if fsp.Fih.HeaderRevision < 3:\r
+            raise Exception("ERROR: FSP 1.x is not supported by the split command !")\r
         ftype = fsp.Type\r
         if not nametemplate:\r
             nametemplate = fspfile\r
@@ -739,7 +797,7 @@ def RebaseFspBin (FspBinary, FspComponent, FspBase, OutputDir, OutputFile):
     numcomp  = len(FspComponent)\r
     baselist = FspBase\r
     if numcomp != len(baselist):\r
-        print "ERROR: Required number of base does not match number of FSP component !"\r
+        print ("ERROR: Required number of base does not match number of FSP component !")\r
         return\r
 \r
     newfspbin = fd.FdData[:]\r
@@ -748,13 +806,18 @@ def RebaseFspBin (FspBinary, FspComponent, FspBase, OutputDir, OutputFile):
 \r
         found = False\r
         for fsp in fd.FspList:\r
+            # Is this FSP 1.x single binary?\r
+            if fsp.Fih.HeaderRevision < 3:\r
+                found = True\r
+                ftype = 'X'\r
+                break\r
             ftype = fsp.Type.lower()\r
             if ftype == fspcomp:\r
                 found = True\r
                 break\r
 \r
         if not found:\r
-            print "ERROR: Could not find FSP_%c component to rebase !" % fspcomp.upper()\r
+            print ("ERROR: Could not find FSP_%c component to rebase !" % fspcomp.upper())\r
             return\r
 \r
         fspbase = baselist[idx]\r
@@ -764,7 +827,7 @@ def RebaseFspBin (FspBinary, FspComponent, FspBase, OutputDir, OutputFile):
             newbase = int(fspbase)\r
         oldbase = fsp.Fih.ImageBase\r
         delta = newbase - oldbase\r
-        print "Rebase FSP-%c from 0x%08X to 0x%08X:" % (ftype.upper(),oldbase,newbase)\r
+        print ("Rebase FSP-%c from 0x%08X to 0x%08X:" % (ftype.upper(),oldbase,newbase))\r
 \r
         imglist = []\r
         for fvidx in fsp.FvIdxList:\r
@@ -783,12 +846,12 @@ def RebaseFspBin (FspBinary, FspComponent, FspBase, OutputDir, OutputFile):
             pcount += img.Rebase(delta, newfspbin)\r
             fcount += 1\r
 \r
-        print "  Patched %d entries in %d TE/PE32 images." % (pcount, fcount)\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
+        print ("  Patched %d entries using FSP patch table." % applied)\r
         if count != applied:\r
-            print "  %d invalid entries are ignored !" % (count - applied)\r
+            print ("  %d invalid entries are ignored !" % (count - applied))\r
 \r
     if OutputFile == '':\r
         filename = os.path.basename(FspBinary)\r
@@ -803,12 +866,12 @@ def RebaseFspBin (FspBinary, FspComponent, FspBase, OutputDir, OutputFile):
 \r
 def main ():\r
     parser     = argparse.ArgumentParser()\r
-    subparsers = parser.add_subparsers(title='commands')\r
+    subparsers = parser.add_subparsers(title='commands', dest="which")\r
 \r
     parser_rebase  = subparsers.add_parser('rebase',  help='rebase a FSP into a new base address')\r
     parser_rebase.set_defaults(which='rebase')\r
     parser_rebase.add_argument('-f',  '--fspbin' , dest='FspBinary',  type=str, help='FSP binary file path', required = True)\r
-    parser_rebase.add_argument('-c',  '--fspcomp', choices=['t','m','s','o'],  nargs='+', dest='FspComponent', type=str, help='FSP component to rebase', default = "['t']", required = True)\r
+    parser_rebase.add_argument('-c',  '--fspcomp', choices=['t','m','s','o','i'],  nargs='+', dest='FspComponent', type=str, help='FSP component to rebase', default = "['t']", required = True)\r
     parser_rebase.add_argument('-b',  '--newbase', dest='FspBase', nargs='+', type=str, help='Rebased FSP binary file name', default = '', required = True)\r
     parser_rebase.add_argument('-o',  '--outdir' , dest='OutputDir',  type=str, help='Output directory path', default = '.')\r
     parser_rebase.add_argument('-n',  '--outfile', dest='OutputFile', type=str, help='Rebased FSP binary file name', default = '')\r
@@ -845,7 +908,7 @@ def main ():
     elif args.which == 'info':\r
         ShowFspInfo (args.FspBinary)\r
     else:\r
-        pass\r
+        parser.print_help()\r
 \r
     return 0\r
 \r