## @file
# Parse FV image
#
# Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
## Import Modules
#
import os
import re
import sys
import uuid
import struct
import codecs
import copy
from CommonDataClass import *
import EotGlobalData
# Global definiton
gFfsPrintTitle = "%-36s %-21s %8s %8s %8s %-4s %-36s" % ("GUID", "TYPE", "OFFSET", "SIZE", "FREE", "ALIGN", "NAME")
## Image() class
#
# A class for Image
#
if ID == None:
else:
m._BUF_ = None
m._LEN_ = None
m._OFF_ = None
def __repr__(m):
return m._ID_
def __len__(m):
for Offset in m._SubImages:
return Len
def _Unpack(m):
return len(m)
raise NotImplementedError
# we may need the Size information in advance if it's given
def empty(m):
del m[0:]
# check if there's enough space
if len(m) < m._HEADER_SIZE_:
else:
del m[m._HEADER_SIZE_:]
def _GetData(m):
if len(m) > m._HEADER_SIZE_:
return m[m._HEADER_SIZE_:]
return None
## FirmwareVolume() class
#
# A class for Firmware Volume
#
# Read FvLength, Attributes, HeaderLength, Checksum
return False
return True
List = None
if Type == 'Ppi':
if Type == 'Protocol':
DepexStack = []
DepexList = []
DepexString = ''
FileDepex = None
if Item == 0x00:
elif Item == 0x01:
elif Item == 0x02:
else:
continue
DepexStack.append(eval(str(DepexStack.pop()) + ' ' + Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
DepexList.append(str(DepexList.pop()) + ' ' + Depex._OPCODE_STRING_[Item].upper() + ' ' + str(DepexList.pop()))
elif Item == 0x05:
elif Item == 0x06:
elif Item == 0x07:
elif Item == 0x08:
else:
else:
if DepexList != []:
if Db == None:
return False
# Find PeiCore, DexCore, PeiPriori, DxePriori first
FfsSecCoreGuid = None
FfsPeiCoreGuid = None
FfsDxeCoreGuid = None
FfsPeiPrioriGuid = None
FfsDxePrioriGuid = None
continue
continue
continue
continue
continue
# Parse SEC_CORE first
if FfsSecCoreGuid != None:
# Parse PEI first
if FfsPeiCoreGuid != None:
if FfsPeiPrioriGuid != None:
# Load PEIM described in priori file
Start = 4
# Parse DXE then
if FfsDxeCoreGuid != None:
if FfsDxePrioriGuid != None:
# Load PEIM described in priori file
Start = 4
# Last Load Drivers without Depex
return True
continue
if IsLoad:
SqlCommand = """select GuidValue from Report
where SourceFileFullPath in
(select Value1 from Inf where BelongsToFile =
(select BelongsToFile from Inf
where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
and Model = %s)
and ItemType = 'Protocol' and ItemMode = 'Produced'""" \
SqlCommand = """select Value2 from Inf where BelongsToFile =
(select DISTINCT BelongsToFile from Inf
where Value1 =
(select SourceFileFullPath from Report
where GuidValue like '%s' and ItemMode = 'Callback'))
if CallBackSet != []:
else:
SqlCommand = """select GuidValue from Report
where SourceFileFullPath in
(select Value1 from Inf where BelongsToFile =
(select BelongsToFile from Inf
where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
and Model = %s)
and ItemType = 'Ppi' and ItemMode = 'Produced'""" \
ScheduleList = sdict()
DepexString = ''
FileDepex = None
# Get Depex
# Find Depex
break
break
break
# Not find Depex
if not IsFoundDepex:
DepexString = ''
FileDepex = None
# Append New Ffs
if CouldBeLoaded:
if FileDepex != None:
else:
else:
for FfsID in ScheduleList:
FfsName = 'UnKnown'
SqlCommand = """select Value2 from Inf
where BelongsToFile = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)
if RecordSet != []:
if IsInstalled:
DepexString = ''
FileDepex = None
# Get Depex
break
break
break
# Append New Ffs
if CouldBeLoaded:
else:
if IsInstalled:
global gIndention
gIndention += 4
FvInfo += "[FV:%s] file_system=%s size=%x checksum=%s\n" % (self.Name, self.FileSystemGuid, self.Size, self.Checksum)
gIndention -= 4
# traverse the FFS
LastFfsObj = None
while FfsStartAddress < EndOfFv:
if LastFfsObj != None:
else:
ExtraData="\t%s @ %s\n\t%s @ %s" \
if LastFfsObj != None:
#
# align to next 8-byte aligned address: A = (A + 8 - 1) & (~(8 - 1))
# The next FFS must be at the latest next 8-byte aligned address
#
## CompressedImage() class
#
# A class for Compressed Image
#
# UncompressedLength = 4-byte
# CompressionType = 1-byte
if UncompressedLength != None:
if CompressionType != None:
if CompressedData != None:
m.Data = CompressedData
def __str__(m):
global gIndention
return S
def _GetOriginalSize(m):
def _GetCompressionType(m):
def _GetSections(m):
try:
import EfiCompressor
m[m._HEADER_SIZE_:],
len(m) - m._HEADER_SIZE_
)
except:
import EfiCompressor
m[m._HEADER_SIZE_:],
len(m) - m._HEADER_SIZE_
)
SectionList = []
Offset = 0
try:
# the section is aligned to 4-byte boundary
except:
break
return SectionList
## GuidDefinedImage() class
#
# A class for GUID Defined Image
#
if SectionDefinitionGuid != None:
if DataOffset != None:
m.DataOffset = DataOffset
if Attributes != None:
m.Attributes = Attributes
if Data != None:
def __str__(m):
return S
def _Unpack(m):
# keep header in this Image object
m.empty()
return len(m)
def _GetAttribute(m):
def _GetGuid(m):
def _GetDataOffset(m):
def _GetSections(m):
SectionList = []
if Guid == m.CRC32_GUID:
# skip the CRC32 value, we don't do CRC32 verification here
try:
# the section is aligned to 4-byte boundary
except:
break
elif Guid == m.TIANO_COMPRESS_GUID:
try:
import EfiCompressor
# skip the header
Offset = 0
try:
# the section is aligned to 4-byte boundary
except:
break
except:
pass
elif Guid == m.LZMA_COMPRESS_GUID:
try:
import LzmaCompressor
# skip the header
Offset = 0
try:
# the section is aligned to 4-byte boundary
except:
break
except:
pass
return SectionList
## Depex() class
#
# A class for Depex
#
_OPCODE_STRING_ = {
0x00 : "BEFORE",
0x01 : "AFTER",
0x02 : "PUSH",
0x03 : "AND",
0x04 : "OR",
0x05 : "NOT",
0x06 : "TRUE",
0x07 : "FALSE",
0x08 : "END",
0x09 : "SOR"
}
_NEXT_ = {
0x08 : None, #"END",
}
def __init__(m):
m._ExprList = []
def __str__(m):
global gIndention
gIndention += 4
S = '\n'
for T in m.Expression:
if T in m._OPCODE_STRING_:
S += Indention + m._OPCODE_STRING_[T]
if T not in [0x00, 0x01, 0x02]:
S += '\n'
else:
gIndention -= 4
return S
def _Unpack(m):
# keep header in this Image object
m.empty()
return len(m)
def _GetExpression(m):
if m._ExprList == []:
Offset = 0
CurrentData = m._OPCODE_
else:
CurrentData = m._GUID_
else:
CurrentData = m._OPCODE_
if CurrentData == None:
break
return m._ExprList
## Ui() class
#
# A class for Ui
#
def __init__(m):
def __str__(m):
return m.String
def _Unpack(m):
# keep header in this Image object
m.empty()
return len(m)
def _GetUiString(m):
## Section() class
#
# A class for Section
#
_TypeName = {
0x00 : "<unknown>",
0x01 : "COMPRESSION",
0x02 : "GUID_DEFINED",
0x10 : "PE32",
0x11 : "PIC",
0x12 : "TE",
0x13 : "DXE_DEPEX",
0x14 : "VERSION",
0x15 : "USER_INTERFACE",
0x16 : "COMPATIBILITY16",
0x17 : "FIRMWARE_VOLUME_IMAGE",
0x18 : "FREEFORM_SUBTYPE_GUID",
0x19 : "RAW",
0x1B : "PEI_DEPEX"
}
0x01 : CompressedImage,
0x02 : GuidDefinedImage,
0x17 : FirmwareVolume,
0x13 : Depex,
0x1B : Depex,
0x15 : Ui
}
# Size = 3-byte
# Type = 1-byte
# SubTypeGuid
# _FREE_FORM_SUBTYPE_GUID_HEADER_ = struct.Struct("1I2H8B")
m._Alignment = 1
if Type != None:
if Size != None:
def __str__(m):
global gIndention
gIndention += 4
else:
for Offset in m._SubImages:
gIndention -= 4
return SectionInfo
def _Unpack(m):
m.empty()
if Type not in m._SectionSubImages:
# no need to extract sub-image, keep all in this Image object
else:
# keep header in this Image object
#
# use new Image object to represent payload, which may be another kind
# of image such as PE32
#
return Size
def _GetSize(m):
def _GetType(m):
def _GetAlignment(m):
return m._Alignment
m._Alignment = Alignment
# section alignment is actually for payload, so we need to add header size
return
NewOffset += m._Alignment
def tofile(m, f):
for Offset in m._SubImages:
# SubTypeGuid = property(_GetGuid, _SetGuid)
## PadSection() class
#
# A class for Pad Section
#
m.Type = 0x19
## Ffs() class
#
# A class for Ffs Section
#
# skip IntegrityCheck
_TypeName = {
0x00 : "<unknown>",
0x01 : "RAW",
0x02 : "FREEFORM",
0x03 : "SECURITY_CORE",
0x04 : "PEI_CORE",
0x05 : "DXE_CORE",
0x06 : "PEIM",
0x07 : "DRIVER",
0x08 : "COMBINED_PEIM_DRIVER",
0x09 : "APPLICATION",
0x0A : "SMM",
0x0B : "FIRMWARE_VOLUME_IMAGE",
0x0C : "COMBINED_SMM_DXE",
0x0D : "SMM_CORE",
0xc0 : "OEM_MIN",
0xdf : "OEM_MAX",
0xe0 : "DEBUG_MIN",
0xef : "DEBUG_MAX",
0xf0 : "FFS_MIN",
0xff : "FFS_MAX",
0xf0 : "FFS_PAD",
}
global gIndention
gIndention += 4
FfsInfo += "[FFS:%s] offset=%x size=%x guid=%s free_space=%x alignment=%s\n" % \
gIndention -= 4
# Pad FFS may use the same GUID. We need to avoid it.
else:
# Traverse the SECTION. RAW and PAD do not have sections
while SectionStartAddress < EndOfFfs:
SectionObj = Section()
#f = open(repr(SectionObj), 'wb')
#SectionObj.Size = 0
#SectionObj.tofile(f)
#f.close()
pass
# Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
# Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
def _GetSize(m):
def _GetType(m):
return True
return False
return True
return False
## PeImage() class
#
# A class for PE Image
#
class PeImage:
#
# just extract e_lfanew
#
#
# Machine
# NumberOfSections
# SizeOfOptionalHeader
#
#
# Magic
# SizeOfImage
# SizeOfHeaders
# CheckSum
# NumberOfRvaAndSizes
#
self._SectionList = []
pass
# from DOS header, get the offset of PE header
# from FILE header, get the optional header size
print "Machine=%x NumberOfSections=%x SizeOfOptionalHeader=%x" % (self.Machine, self.NumberOfSections, self.SizeOfOptionalHeader)
# optional header follows the FILE header
print "Magic=%x SizeOfImage=%x SizeOfHeaders=%x, Checksum=%x, NumberOfRvaAndSizes=%x" % (Magic, self.SizeOfImage, SizeOfHeaders, self.Checksum, NumberOfRvaAndSizes)
PeSections = PeSectionTable(self._PeImageBuf, self.Offset + PeImageSectionTableOffset, self.NumberOfSections)
## PeSectionTable() class
#
# A class for PE Section Table
#
class PeSectionTable:
self._SectionList = []
print SectionHeader
## PeSectionHeader() class
#
# A class for PE Section Header
#
class PeSectionHeader:
#
# VirtualAddress
# SizeOfRawData
# PointerToRawData
#
return "VirtualAddress=%x, SizeOfRawData=%x, PointerToRawData=%x" % (self.VirtualAddressStart, self.SizeOfRawData, self.PointerToRawData)
return self._HeaderLength
## LinkMap() class
#
# A class for Link Map
#
class LinkMap:
_StartFlag = {
}
_MappingFormat = {
}
try:
if not MappingStart:
continue
continue
finally:
return None
## MultipleFv() class
#
# A class for Multiple FV
#
try:
except EOFError:
pass
# Version and Copyright
## Parse command line options
#
# Using standard Python module optparse to parse command line option of this tool.
#
# @retval Options A optparse.Values object containing the parsed options
# @retval InputFile Path of file to be trimmed
#
def GetOptions():
OptionList = [
help="The input file is preprocessed source code, including C or assembly code"),
help="The input file is preprocessed VFR file"),
help="Convert standard hex format (0xabcd) to MASM format (abcdh)"),
help="Convert standard hex format (0xabcd) to MASM format (abcdh)"),
help="File to store the trimmed content"),
help=""),
help=""),
help=""),
help="Run verbosely"),
help="Run with debug information"),
help="Run quietly"),
]
# use clearer usage to override default usage message
UsageString = "%prog [-a ARCH] [-p PLATFORM] [-m MODULE] [-t TOOLCHAIN_TAG] [-k] [-g] [-v|-d <debug_level>|-q] [-o <output_directory>] [GenC|GenMake]"
Parser = OptionParser(description=__copyright__, version=__version__, option_list=OptionList, usage=UsageString)
else:
# error check
else:
return Options
## Entrance method
#
# This method mainly dispatch specific methods per the command line options.
# If no error found, return zero value so the caller of this tool can know
# if it's executed successfully or not.
#
# @retval 0 Tool was successful
# @retval 1 Tool failed
#
def Main():
try:
Option = GetOptions()
except Exception, e:
print e
return 1
return 0
# This acts like the main() function for the script, unless it is 'import'ed into another script.
if __name__ == '__main__':
# sys.exit(Main())
try:
except EOFError:
pass
#fv.Dispatch(None)
print fv
try:
except EOFError:
pass
sf += ".sec"