public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Yao, Jiewen" <jiewen.yao@intel.com>
To: "Ma, Maurice" <maurice.ma@intel.com>,
	"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Subject: Re: [PATCH] IntelFsp2Pkg/Tools: Add PE32 section rebasing support
Date: Fri, 7 Oct 2016 13:13:40 +0000	[thread overview]
Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503869DA38@shsmsx102.ccr.corp.intel.com> (raw)
In-Reply-To: <417c05153e8c89bfc8b520507c80e4b09bb87c4e.1475626650.git.maurice.ma@intel.com>

Reviewed-by: Jiewen.yao@intel.com

> -----Original Message-----
> From: Ma, Maurice
> Sent: Wednesday, October 5, 2016 8:19 AM
> To: edk2-devel@lists.01.org
> Cc: Ma, Maurice <maurice.ma@intel.com>; Yao, Jiewen
> <jiewen.yao@intel.com>; Mudusuru, Giri P <giri.p.mudusuru@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.BA
> SERELOC].Size
> +            roffset =
> self.PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY.BA
> SERELOC].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



      parent reply	other threads:[~2016-10-07 13:13 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
2016-10-07 13:13 ` Yao, Jiewen [this message]

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=74D8A39837DF1E4DA445A8C0B3885C503869DA38@shsmsx102.ccr.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