public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Yarlagadda, Satya P" <satya.p.yarlagadda@intel.com>
To: "Ma, Maurice" <maurice.ma@intel.com>,
	"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Yao, Jiewen" <jiewen.yao@intel.com>
Subject: Re: [PATCH] IntelFsp2Pkg/Tools: Add PE32 section rebasing support
Date: Wed, 5 Oct 2016 16:53:06 +0000	[thread overview]
Message-ID: <C9D207FA7245494E8DE500778D4BFA9A37427088@BGSMSX103.gar.corp.intel.com> (raw)
In-Reply-To: <417c05153e8c89bfc8b520507c80e4b09bb87c4e.1475626650.git.maurice.ma@intel.com>

Reviewed-by: Satya Yarlagadda <Satya.p.yarlagadda@intel.com>

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Maurice Ma
Sent: Wednesday, October 05, 2016 5:49 AM
To: edk2-devel@lists.01.org
Cc: Yao, Jiewen <jiewen.yao@intel.com>
Subject: [edk2] [PATCH] IntelFsp2Pkg/Tools: Add PE32 section rebasing support

The current SplitFspBin.py can only support TE image format rebasing in an FSP binary. This patch adds PE32 image format rebasing support.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Giri P Mudusuru <giri.p.mudusuru@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Maurice Ma <maurice.ma@intel.com>
---
 IntelFsp2Pkg/Tools/SplitFspBin.py | 174 +++++++++++++++++++++++++++++++-------
 1 file changed, 145 insertions(+), 29 deletions(-)

diff --git a/IntelFsp2Pkg/Tools/SplitFspBin.py b/IntelFsp2Pkg/Tools/SplitFspBin.py
index ef759f0dc46a..e4c3aa6d0b28 100644
--- a/IntelFsp2Pkg/Tools/SplitFspBin.py
+++ b/IntelFsp2Pkg/Tools/SplitFspBin.py
@@ -159,12 +159,102 @@ class EFI_TE_IMAGE_HEADER(Structure):
         ('DataDirectoryDebug',      EFI_IMAGE_DATA_DIRECTORY)
         ]
 
+class EFI_IMAGE_DOS_HEADER(Structure):
+    _fields_ = [
+        ('e_magic',              c_uint16),
+        ('e_cblp',               c_uint16),
+        ('e_cp',                 c_uint16),
+        ('e_crlc',               c_uint16),
+        ('e_cparhdr',            c_uint16),
+        ('e_minalloc',           c_uint16),
+        ('e_maxalloc',           c_uint16),
+        ('e_ss',                 c_uint16),
+        ('e_sp',                 c_uint16),
+        ('e_csum',               c_uint16),
+        ('e_ip',                 c_uint16),
+        ('e_cs',                 c_uint16),
+        ('e_lfarlc',             c_uint16),
+        ('e_ovno',               c_uint16),
+        ('e_res',                ARRAY(c_uint16, 4)),
+        ('e_oemid',              c_uint16),
+        ('e_oeminfo',            c_uint16),
+        ('e_res2',               ARRAY(c_uint16, 10)),
+        ('e_lfanew',             c_uint16)
+        ]
+
+class EFI_IMAGE_FILE_HEADER(Structure):
+    _fields_ = [
+        ('Machine',               c_uint16),
+        ('NumberOfSections',      c_uint16),
+        ('TimeDateStamp',         c_uint32),
+        ('PointerToSymbolTable',  c_uint32),
+        ('NumberOfSymbols',       c_uint32),
+        ('SizeOfOptionalHeader',  c_uint16),
+        ('Characteristics',       c_uint16)
+        ]
+
 class PE_RELOC_BLOCK_HEADER(Structure):
     _fields_ = [
         ('PageRVA',              c_uint32),
         ('BlockSize',            c_uint32)
         ]
 
+class EFI_IMAGE_OPTIONAL_HEADER32(Structure):
+    _fields_ = [
+        ('Magic',                         c_uint16),
+        ('MajorLinkerVersion',            c_uint8),
+        ('MinorLinkerVersion',            c_uint8),
+        ('SizeOfCode',                    c_uint32),
+        ('SizeOfInitializedData',         c_uint32),
+        ('SizeOfUninitializedData',       c_uint32),
+        ('AddressOfEntryPoint',           c_uint32),
+        ('BaseOfCode',                    c_uint32),
+        ('BaseOfData',                    c_uint32),
+        ('ImageBase',                     c_uint32),
+        ('SectionAlignment',              c_uint32),
+        ('FileAlignment',                 c_uint32),
+        ('MajorOperatingSystemVersion',   c_uint16),
+        ('MinorOperatingSystemVersion',   c_uint16),
+        ('MajorImageVersion',             c_uint16),
+        ('MinorImageVersion',             c_uint16),
+        ('MajorSubsystemVersion',         c_uint16),
+        ('MinorSubsystemVersion',         c_uint16),
+        ('Win32VersionValue',             c_uint32),
+        ('SizeOfImage',                   c_uint32),
+        ('SizeOfHeaders',                 c_uint32),
+        ('CheckSum'     ,                 c_uint32),
+        ('Subsystem',                     c_uint16),
+        ('DllCharacteristics',            c_uint16),
+        ('SizeOfStackReserve',            c_uint32),
+        ('SizeOfStackCommit' ,            c_uint32),
+        ('SizeOfHeapReserve',             c_uint32),
+        ('SizeOfHeapCommit' ,             c_uint32),
+        ('LoaderFlags'     ,              c_uint32),
+        ('NumberOfRvaAndSizes',           c_uint32),
+        ('DataDirectory',                 ARRAY(EFI_IMAGE_DATA_DIRECTORY, 16))
+        ]
+
+class EFI_IMAGE_NT_HEADERS32(Structure):
+    _fields_ = [
+        ('Signature',            c_uint32),
+        ('FileHeader',           EFI_IMAGE_FILE_HEADER),
+        ('OptionalHeader',       EFI_IMAGE_OPTIONAL_HEADER32)
+        ]
+
+
+class EFI_IMAGE_DIRECTORY_ENTRY:
+    EXPORT                     = 0
+    IMPORT                     = 1
+    RESOURCE                   = 2
+    EXCEPTION                  = 3
+    SECURITY                   = 4
+    BASERELOC                  = 5
+    DEBUG                      = 6
+    COPYRIGHT                  = 7
+    GLOBALPTR                  = 8
+    TLS                        = 9
+    LOAD_CONFIG                = 10
+
 class EFI_FV_FILETYPE:
     ALL                        = 0x00
     RAW                        = 0x01
@@ -431,26 +521,47 @@ class FirmwareDevice:
                     raise Exception("ERROR: Incorrect FV size in image !")
         self.CheckFsp ()
 
-class TeImage:
-    def __init__(self, offset, tedata):
-        self.Offset = offset
-        self.TeHdr     = EFI_TE_IMAGE_HEADER.from_buffer (tedata, 0)
-        self.TeData    = tedata
+class PeTeImage:
+    def __init__(self, offset, data):
+        self.Offset    = offset
+        tehdr          = EFI_TE_IMAGE_HEADER.from_buffer (data, 0)
+        if   tehdr.Signature == 'VZ': # TE image
+            self.TeHdr   = tehdr
+        elif tehdr.Signature == 'MZ': # PE32 image
+            self.TeHdr   = None
+            self.DosHdr  = EFI_IMAGE_DOS_HEADER.from_buffer (data, 0)
+            self.PeHdr   = EFI_IMAGE_NT_HEADERS32.from_buffer (data, self.DosHdr.e_lfanew)
+            if self.PeHdr.Signature != 0x4550:
+                raise Exception("ERROR: Invalid PE32 header !")
+            if self.PeHdr.FileHeader.SizeOfOptionalHeader < EFI_IMAGE_OPTIONAL_HEADER32.DataDirectory.offset:
+                raise Exception("ERROR: Unsupported PE32 image !")
+            if self.PeHdr.OptionalHeader.NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC:
+                raise Exception("ERROR: No relocation information available !")
+        self.Offset    = offset
+        self.Data      = data
         self.RelocList = []
 
+    def IsTeImage(self):
+        return  self.TeHdr is not None
+
     def ParseReloc(self):
-        rsize   = self.TeHdr.DataDirectoryBaseReloc.Size
-        roffset   = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + self.TeHdr.DataDirectoryBaseReloc.VirtualAddress
+        if self.IsTeImage():
+            rsize   = self.TeHdr.DataDirectoryBaseReloc.Size
+            roffset = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + self.TeHdr.DataDirectoryBaseReloc.VirtualAddress
+        else:
+            rsize   = self.PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASERELOC].Size
+            roffset = 
+ self.PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BASE
+ RELOC].VirtualAddress
+
         alignment = 4
         offset = roffset
         while offset < roffset + rsize:
             offset = AlignPtr(offset, 4)
-            blkhdr = PE_RELOC_BLOCK_HEADER.from_buffer(self.TeData, offset)
+            blkhdr = PE_RELOC_BLOCK_HEADER.from_buffer(self.Data, 
+ offset)
             offset += sizeof(blkhdr)
             # Read relocation type,offset pairs
             rlen  = blkhdr.BlockSize - sizeof(PE_RELOC_BLOCK_HEADER)
             rnum  = rlen/sizeof(c_uint16)
-            rdata = (c_uint16 * rnum).from_buffer(self.TeData, offset)
+            rdata = (c_uint16 * rnum).from_buffer(self.Data, offset)
             for each in rdata:
                 roff  = each & 0xfff
                 rtype = each >> 12
@@ -459,7 +570,9 @@ class TeImage:
                 if rtype != 3: # IMAGE_REL_BASED_HIGHLOW
                     raise Exception("ERROR: Unsupported relocation type %d!" % rtype)
                 # Calculate the offset of the relocation
-                aoff = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + blkhdr.PageRVA + roff
+                aoff  = blkhdr.PageRVA + roff
+                if self.IsTeImage():
+                    aoff += sizeof(self.TeHdr) - 
+ self.TeHdr.StrippedSize
                 self.RelocList.append((rtype, aoff))
             offset += sizeof(rdata)
 
@@ -478,10 +591,17 @@ class TeImage:
             else:
                 raise Exception('ERROR: Unknown relocation type %d !' % rtype)
 
-        tehdr = self.TeHdr
-        tehdr.ImageBase += delta
-        offset = self.Offset
-        fdbin[offset:offset+sizeof(tehdr)] = bytearray(tehdr)
+        if self.IsTeImage():
+            offset  = self.Offset + EFI_TE_IMAGE_HEADER.ImageBase.offset
+            size    = EFI_TE_IMAGE_HEADER.ImageBase.size
+        else:
+            offset  = self.Offset + self.DosHdr.e_lfanew
+            offset += EFI_IMAGE_NT_HEADERS32.OptionalHeader.offset
+            offset += EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.offset
+            size    = EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.size
+
+        value  = Bytes2Val(fdbin[offset:offset+size]) + delta
+        fdbin[offset:offset+size] = Val2Bytes(value, size)
 
         return count
 
@@ -588,28 +708,24 @@ def RebaseFspBin (FspBinary, FspComponent, FspBase, OutputDir, OutputFile):
         delta = newbase - oldbase
         print "Rebase FSP-%c from 0x%08X to 0x%08X:" % (ftype.upper(),oldbase,newbase)
 
-        telist = []
+        imglist = []
         for fvidx in fsp.FvIdxList:
             fv = fd.FvList[fvidx]
             for ffs in fv.FfsList:
                 for sec in ffs.SecList:
-                    if sec.SecHdr.Type == EFI_SECTION_TYPE.TE:   # TE
+                    if sec.SecHdr.Type in [EFI_SECTION_TYPE.TE, EFI_SECTION_TYPE.PE32]:   # TE or PE32
                         offset = fd.Offset + fv.Offset + ffs.Offset + sec.Offset + sizeof(sec.SecHdr)
-                        telist.append ((offset, len(sec.SecData) - sizeof(sec.SecHdr)))
-                    elif sec.SecHdr.Type == EFI_SECTION_TYPE.PE32: # PE
-                        raise Exception("ERROR: PE32 Section is not supported !")
+                        imglist.append ((offset, len(sec.SecData) - 
+ sizeof(sec.SecHdr)))
 
         fcount  = 0
-        tecount = 0
-        for (teoffset, telen) in telist:
-            tehdr = EFI_TE_IMAGE_HEADER.from_buffer (fd.FdData, teoffset)
-            if 'VZ' != tehdr.Signature:
-                raise Exception("ERROR: Invalid TE header !")
-            te = TeImage(teoffset, fd.FdData[teoffset:teoffset + telen])
-            te.ParseReloc()
-            tecount += te.Rebase(delta, newfspbin)
-            fcount  += 1
-        print "  Patched %d entries in %d TE images." % (tecount, fcount)
+        pcount  = 0
+        for (offset, length) in imglist:
+            img = PeTeImage(offset, fd.FdData[offset:offset + length])
+            img.ParseReloc()
+            pcount += img.Rebase(delta, newfspbin)
+            fcount += 1
+
+        print "  Patched %d entries in %d TE/PE32 images." % (pcount, 
+ fcount)
 
         (count, applied) = fsp.Patch(delta, newfspbin)
         print "  Patched %d entries using FSP patch table." % applied
--
1.9.5.msysgit.0

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


  reply	other threads:[~2016-10-05 16:53 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-05  0:18 [PATCH] IntelFsp2Pkg/Tools: Add PE32 section rebasing support Maurice Ma
2016-10-05 16:53 ` Yarlagadda, Satya P [this message]
2016-10-07 13:13 ` Yao, Jiewen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=C9D207FA7245494E8DE500778D4BFA9A37427088@BGSMSX103.gar.corp.intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox