X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FCommon%2FMisc.py;h=8ba5819cc1e337af0b26f7c7c7f47f6e0c1954cc;hp=19a1319639a54326364ea47f29888eaa908e4436;hb=a3251d844695f90711bfe094f12755fd01742369;hpb=9b9500a1c9e620c9aac565679e2eb77255ba3306 diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py index 19a1319639..8ba5819cc1 100644 --- a/BaseTools/Source/Python/Common/Misc.py +++ b/BaseTools/Source/Python/Common/Misc.py @@ -1,7 +1,7 @@ ## @file # Common routines used by all tools # -# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.
# 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 @@ -24,6 +24,7 @@ import re import cPickle import array import shutil +from struct import pack from UserDict import IterableUserDict from UserList import UserList @@ -44,6 +45,134 @@ gFileTimeStampCache = {} # {file path : file time stamp} ## Dictionary used to store dependencies of files gDependencyDatabase = {} # arch : {file path : [dependent files list]} +def GetVariableOffset(mapfilepath, efifilepath, varnames): + """ Parse map file to get variable offset in current EFI file + @param mapfilepath Map file absolution path + @param efifilepath: EFI binary file full path + @param varnames iteratable container whose elements are variable names to be searched + + @return List whos elements are tuple with variable name and raw offset + """ + lines = [] + try: + f = open(mapfilepath, 'r') + lines = f.readlines() + f.close() + except: + return None + + if len(lines) == 0: return None + firstline = lines[0].strip() + if (firstline.startswith("Archive member included ") and + firstline.endswith(" file (symbol)")): + return _parseForGCC(lines, efifilepath, varnames) + return _parseGeneral(lines, efifilepath, varnames) + +def _parseForGCC(lines, efifilepath, varnames): + """ Parse map file generated by GCC linker """ + status = 0 + sections = [] + varoffset = [] + for line in lines: + line = line.strip() + # status machine transection + if status == 0 and line == "Memory Configuration": + status = 1 + continue + elif status == 1 and line == 'Linker script and memory map': + status = 2 + continue + elif status ==2 and line == 'START GROUP': + status = 3 + continue + + # status handler + if status == 2: + m = re.match('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$', line) + if m != None: + sections.append(m.groups(0)) + for varname in varnames: + m = re.match("^([\da-fA-Fx]+) +[_]*(%s)$" % varname, line) + if m != None: + varoffset.append((varname, int(m.groups(0)[0], 16) , int(sections[-1][1], 16), sections[-1][0])) + + if not varoffset: + return [] + # get section information from efi file + efisecs = PeImageClass(efifilepath).SectionHeaderList + if efisecs == None or len(efisecs) == 0: + return [] + #redirection + redirection = 0 + for efisec in efisecs: + for section in sections: + if section[0].strip() == efisec[0].strip() and section[0].strip() == '.text': + redirection = int(section[1], 16) - efisec[1] + + ret = [] + for var in varoffset: + for efisec in efisecs: + if var[1] >= efisec[1] and var[1] < efisec[1]+efisec[3]: + ret.append((var[0], hex(efisec[2] + var[1] - efisec[1] - redirection))) + return ret + +def _parseGeneral(lines, efifilepath, varnames): + status = 0 #0 - beginning of file; 1 - PE section definition; 2 - symbol table + secs = [] # key = section name + varoffset = [] + secRe = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\da-fA-F]+)[Hh]? +([.\w\$]+) +(\w+)', re.UNICODE) + symRe = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\.:\\\\\w\?@\$]+) +([\da-fA-F]+)', re.UNICODE) + + for line in lines: + line = line.strip() + if re.match("^Start[' ']+Length[' ']+Name[' ']+Class", line): + status = 1 + continue + if re.match("^Address[' ']+Publics by Value[' ']+Rva\+Base", line): + status = 2 + continue + if re.match("^entry point at", line): + status = 3 + continue + if status == 1 and len(line) != 0: + m = secRe.match(line) + assert m != None, "Fail to parse the section in map file , line is %s" % line + sec_no, sec_start, sec_length, sec_name, sec_class = m.groups(0) + secs.append([int(sec_no, 16), int(sec_start, 16), int(sec_length, 16), sec_name, sec_class]) + if status == 2 and len(line) != 0: + for varname in varnames: + m = symRe.match(line) + assert m != None, "Fail to parse the symbol in map file, line is %s" % line + sec_no, sym_offset, sym_name, vir_addr = m.groups(0) + sec_no = int(sec_no, 16) + sym_offset = int(sym_offset, 16) + vir_addr = int(vir_addr, 16) + m2 = re.match('^[_]*(%s)' % varname, sym_name) + if m2 != None: + # fond a binary pcd entry in map file + for sec in secs: + if sec[0] == sec_no and (sym_offset >= sec[1] and sym_offset < sec[1] + sec[2]): + varoffset.append([varname, sec[3], sym_offset, vir_addr, sec_no]) + + if not varoffset: return [] + + # get section information from efi file + efisecs = PeImageClass(efifilepath).SectionHeaderList + if efisecs == None or len(efisecs) == 0: + return [] + + ret = [] + for var in varoffset: + index = 0 + for efisec in efisecs: + index = index + 1 + if var[1].strip() == efisec[0].strip(): + ret.append((var[0], hex(efisec[2] + var[2]))) + elif var[4] == index: + ret.append((var[0], hex(efisec[2] + var[2]))) + + return ret + ## Routine to process duplicated INF # # This function is called by following two cases: @@ -1380,15 +1509,17 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''): return [VpdOffset, Size, Value], IsValid, 2 elif PcdType in (MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII): HiiString = FieldList[0] - Guid = Offset = Value = '' + Guid = Offset = Value = Attribute = '' if len(FieldList) > 1: Guid = FieldList[1] if len(FieldList) > 2: Offset = FieldList[2] if len(FieldList) > 3: Value = FieldList[3] - IsValid = (3 <= len(FieldList) <= 4) - return [HiiString, Guid, Offset, Value], IsValid, 3 + if len(FieldList) > 4: + Attribute = FieldList[4] + IsValid = (3 <= len(FieldList) <= 5) + return [HiiString, Guid, Offset, Value, Attribute], IsValid, 3 return [], False, 0 ## AnalyzePcdData @@ -1825,17 +1956,26 @@ class SkuClass(): self.AvailableSkuIds = sdict() self.SkuIdSet = [] - + self.SkuIdNumberSet = [] if SkuIdentifier == '' or SkuIdentifier is None: self.SkuIdSet = ['DEFAULT'] + self.SkuIdNumberSet = ['0U'] elif SkuIdentifier == 'ALL': self.SkuIdSet = SkuIds.keys() + self.SkuIdNumberSet = [num.strip() + 'U' for num in SkuIds.values()] else: r = SkuIdentifier.split('|') self.SkuIdSet=[r[k].strip() for k in range(len(r))] + k = None + try: + self.SkuIdNumberSet = [SkuIds[k].strip() + 'U' for k in self.SkuIdSet] + except Exception: + EdkLogger.error("build", PARAMETER_INVALID, + ExtraData = "SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]" + % (k, " ".join(SkuIds.keys()))) if len(self.SkuIdSet) == 2 and 'DEFAULT' in self.SkuIdSet and SkuIdentifier != 'ALL': self.SkuIdSet.remove('DEFAULT') - + self.SkuIdNumberSet.remove('0U') for each in self.SkuIdSet: if each in SkuIds: self.AvailableSkuIds[each] = SkuIds[each] @@ -1862,10 +2002,31 @@ class SkuClass(): return self.SkuIdSet[0] else: return 'DEFAULT' - + def __GetAvailableSkuIdNumber(self): + return self.SkuIdNumberSet SystemSkuId = property(__GetSystemSkuID) AvailableSkuIdSet = property(__GetAvailableSkuIds) SkuUsageType = property(__SkuUsageType) + AvailableSkuIdNumSet = property(__GetAvailableSkuIdNumber) + +# +# Pack a registry format GUID +# +def PackRegistryFormatGuid(Guid): + Guid = Guid.split('-') + return pack('=LHHBBBBBBBB', + int(Guid[0], 16), + int(Guid[1], 16), + int(Guid[2], 16), + int(Guid[3][-4:-2], 16), + int(Guid[3][-2:], 16), + int(Guid[4][-12:-10], 16), + int(Guid[4][-10:-8], 16), + int(Guid[4][-8:-6], 16), + int(Guid[4][-6:-4], 16), + int(Guid[4][-4:-2], 16), + int(Guid[4][-2:], 16) + ) ## #