152302d4dee589a5df43a464420c9fe68ba83937dlgao## @file 252302d4dee589a5df43a464420c9fe68ba83937dlgao# Generate PCD table for 'Patchable In Module' type PCD with given .map file. 3f51461c829c124288a930829a78e2a5a799f4039Gao, Liming# The Patch PCD table like: 4f51461c829c124288a930829a78e2a5a799f4039Gao, Liming# 5f51461c829c124288a930829a78e2a5a799f4039Gao, Liming# PCD Name Offset in binary 652302d4dee589a5df43a464420c9fe68ba83937dlgao# ======== ================ 752302d4dee589a5df43a464420c9fe68ba83937dlgao# 81be2ed90a20618d71ddf34b8a07d038da0b36854Hess Chen# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR> 940d841f6a8f84e75409178e19e69b95e01bada0flgao# This program and the accompanying materials 1052302d4dee589a5df43a464420c9fe68ba83937dlgao# are licensed and made available under the terms and conditions of the BSD License 1152302d4dee589a5df43a464420c9fe68ba83937dlgao# which accompanies this distribution. The full text of the license may be found at 1252302d4dee589a5df43a464420c9fe68ba83937dlgao# http://opensource.org/licenses/bsd-license.php 1352302d4dee589a5df43a464420c9fe68ba83937dlgao# 1452302d4dee589a5df43a464420c9fe68ba83937dlgao# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 1552302d4dee589a5df43a464420c9fe68ba83937dlgao# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 1652302d4dee589a5df43a464420c9fe68ba83937dlgao# 17f51461c829c124288a930829a78e2a5a799f4039Gao, Liming# 18f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 19f51461c829c124288a930829a78e2a5a799f4039Gao, Liming#====================================== External Libraries ======================================== 20f51461c829c124288a930829a78e2a5a799f4039Gao, Limingimport optparse 211be2ed90a20618d71ddf34b8a07d038da0b36854Hess Chenimport Common.LongFilePathOs as os 22f51461c829c124288a930829a78e2a5a799f4039Gao, Limingimport re 23f51461c829c124288a930829a78e2a5a799f4039Gao, Limingimport array 24f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 25f51461c829c124288a930829a78e2a5a799f4039Gao, Limingfrom Common.BuildToolError import * 26f51461c829c124288a930829a78e2a5a799f4039Gao, Limingimport Common.EdkLogger as EdkLogger 2752302d4dee589a5df43a464420c9fe68ba83937dlgaofrom Common.Misc import PeImageClass 28b36d134faf4305247830522b8e2bb255e98c5699lgaofrom Common.BuildVersion import gBUILD_VERSION 291be2ed90a20618d71ddf34b8a07d038da0b36854Hess Chenfrom Common.LongFilePathSupport import OpenLongFilePath as open 30f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 31f51461c829c124288a930829a78e2a5a799f4039Gao, Liming# Version and Copyright 32f51461c829c124288a930829a78e2a5a799f4039Gao, Liming__version_number__ = ("0.10" + " " + gBUILD_VERSION) 33f51461c829c124288a930829a78e2a5a799f4039Gao, Liming__version__ = "%prog Version " + __version_number__ 34f51461c829c124288a930829a78e2a5a799f4039Gao, Liming__copyright__ = "Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved." 35f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 36f51461c829c124288a930829a78e2a5a799f4039Gao, Liming#====================================== Internal Libraries ======================================== 37f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 38f51461c829c124288a930829a78e2a5a799f4039Gao, Liming#============================================== Code =============================================== 39f51461c829c124288a930829a78e2a5a799f4039Gao, LimingsecRe = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\da-fA-F]+)[Hh]? +([.\w\$]+) +(\w+)', re.UNICODE) 40f51461c829c124288a930829a78e2a5a799f4039Gao, LimingsymRe = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\.:\\\\\w\?@\$]+) +([\da-fA-F]+)', re.UNICODE) 41f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 42f51461c829c124288a930829a78e2a5a799f4039Gao, Limingdef parsePcdInfoFromMapFile(mapfilepath, efifilepath): 43f51461c829c124288a930829a78e2a5a799f4039Gao, Liming """ Parse map file to get binary patch pcd information 44f51461c829c124288a930829a78e2a5a799f4039Gao, Liming @param path Map file absolution path 45f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 46f51461c829c124288a930829a78e2a5a799f4039Gao, Liming @return a list which element hold (PcdName, Offset, SectionName) 47f51461c829c124288a930829a78e2a5a799f4039Gao, Liming """ 48f51461c829c124288a930829a78e2a5a799f4039Gao, Liming lines = [] 49f51461c829c124288a930829a78e2a5a799f4039Gao, Liming try: 50f51461c829c124288a930829a78e2a5a799f4039Gao, Liming f = open(mapfilepath, 'r') 51f51461c829c124288a930829a78e2a5a799f4039Gao, Liming lines = f.readlines() 52f51461c829c124288a930829a78e2a5a799f4039Gao, Liming f.close() 53f51461c829c124288a930829a78e2a5a799f4039Gao, Liming except: 54f51461c829c124288a930829a78e2a5a799f4039Gao, Liming return None 55f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 56f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if len(lines) == 0: return None 57e4ac870fe95adc7d178a79b73ad2792e0c8bfeb8Gao, Liming firstline = lines[0].strip() 58e4ac870fe95adc7d178a79b73ad2792e0c8bfeb8Gao, Liming if (firstline.startswith("Archive member included ") and 59e4ac870fe95adc7d178a79b73ad2792e0c8bfeb8Gao, Liming firstline.endswith(" file (symbol)")): 60f51461c829c124288a930829a78e2a5a799f4039Gao, Liming return _parseForGCC(lines, efifilepath) 61f51461c829c124288a930829a78e2a5a799f4039Gao, Liming return _parseGeneral(lines, efifilepath) 62f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 63f51461c829c124288a930829a78e2a5a799f4039Gao, Limingdef _parseForGCC(lines, efifilepath): 64f51461c829c124288a930829a78e2a5a799f4039Gao, Liming """ Parse map file generated by GCC linker """ 65f51461c829c124288a930829a78e2a5a799f4039Gao, Liming status = 0 66f51461c829c124288a930829a78e2a5a799f4039Gao, Liming imageBase = -1 67f51461c829c124288a930829a78e2a5a799f4039Gao, Liming sections = [] 68f51461c829c124288a930829a78e2a5a799f4039Gao, Liming bpcds = [] 69f51461c829c124288a930829a78e2a5a799f4039Gao, Liming for line in lines: 70f51461c829c124288a930829a78e2a5a799f4039Gao, Liming line = line.strip() 71f51461c829c124288a930829a78e2a5a799f4039Gao, Liming # status machine transection 72f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if status == 0 and line == "Memory Configuration": 73f51461c829c124288a930829a78e2a5a799f4039Gao, Liming status = 1 74f51461c829c124288a930829a78e2a5a799f4039Gao, Liming continue 75f51461c829c124288a930829a78e2a5a799f4039Gao, Liming elif status == 1 and line == 'Linker script and memory map': 76f51461c829c124288a930829a78e2a5a799f4039Gao, Liming status = 2 77f51461c829c124288a930829a78e2a5a799f4039Gao, Liming continue 78f51461c829c124288a930829a78e2a5a799f4039Gao, Liming elif status ==2 and line == 'START GROUP': 79f51461c829c124288a930829a78e2a5a799f4039Gao, Liming status = 3 80f51461c829c124288a930829a78e2a5a799f4039Gao, Liming continue 81f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 82e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao # status handler 83f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if status == 2: 84f51461c829c124288a930829a78e2a5a799f4039Gao, Liming m = re.match('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$', line) 85f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if m != None: 86f51461c829c124288a930829a78e2a5a799f4039Gao, Liming sections.append(m.groups(0)) 87f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if status == 2: 88f51461c829c124288a930829a78e2a5a799f4039Gao, Liming m = re.match("^([\da-fA-Fx]+) +[_]+gPcd_BinaryPatch_([\w_\d]+)$", line) 89f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if m != None: 90f51461c829c124288a930829a78e2a5a799f4039Gao, Liming bpcds.append((m.groups(0)[1], int(m.groups(0)[0], 16) , int(sections[-1][1], 16), sections[-1][0])) 91e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao 92e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao # get section information from efi file 93e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao efisecs = PeImageClass(efifilepath).SectionHeaderList 94e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao if efisecs == None or len(efisecs) == 0: 95e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao return None 96e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao #redirection 97e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao redirection = 0 98e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao for efisec in efisecs: 99e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao for section in sections: 100e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao if section[0].strip() == efisec[0].strip() and section[0].strip() == '.text': 101e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao redirection = int(section[1], 16) - efisec[1] 102e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao pcds = [] 103e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao for pcd in bpcds: 104e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao for efisec in efisecs: 105e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao if pcd[1] >= efisec[1] and pcd[1] < efisec[1]+efisec[3]: 106e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao #assert efisec[0].strip() == pcd[3].strip() and efisec[1] + redirection == pcd[2], "There are some differences between map file and efi file" 107e8a47801a1dfdb148b1bfcd5bdc8ebc3bf51f92dLiming Gao pcds.append([pcd[0], efisec[2] + pcd[1] - efisec[1] - redirection, efisec[0]]) 108f51461c829c124288a930829a78e2a5a799f4039Gao, Liming return pcds 109f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 110f51461c829c124288a930829a78e2a5a799f4039Gao, Limingdef _parseGeneral(lines, efifilepath): 111f51461c829c124288a930829a78e2a5a799f4039Gao, Liming """ For MSFT, ICC, EBC 112f51461c829c124288a930829a78e2a5a799f4039Gao, Liming @param lines line array for map file 113f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 114f51461c829c124288a930829a78e2a5a799f4039Gao, Liming @return a list which element hold (PcdName, Offset, SectionName) 11547fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu """ 116f51461c829c124288a930829a78e2a5a799f4039Gao, Liming status = 0 #0 - beginning of file; 1 - PE section definition; 2 - symbol table 11747fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu secs = [] # key = section name 118f51461c829c124288a930829a78e2a5a799f4039Gao, Liming bPcds = [] 11947fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu 120f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 121f51461c829c124288a930829a78e2a5a799f4039Gao, Liming for line in lines: 122f51461c829c124288a930829a78e2a5a799f4039Gao, Liming line = line.strip() 123f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if re.match("^Start[' ']+Length[' ']+Name[' ']+Class", line): 124f51461c829c124288a930829a78e2a5a799f4039Gao, Liming status = 1 125f51461c829c124288a930829a78e2a5a799f4039Gao, Liming continue 126f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if re.match("^Address[' ']+Publics by Value[' ']+Rva\+Base", line): 127f51461c829c124288a930829a78e2a5a799f4039Gao, Liming status = 2 128f51461c829c124288a930829a78e2a5a799f4039Gao, Liming continue 129f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if re.match("^entry point at", line): 130f51461c829c124288a930829a78e2a5a799f4039Gao, Liming status = 3 13147fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu continue 132f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if status == 1 and len(line) != 0: 13347fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu m = secRe.match(line) 134f51461c829c124288a930829a78e2a5a799f4039Gao, Liming assert m != None, "Fail to parse the section in map file , line is %s" % line 135f51461c829c124288a930829a78e2a5a799f4039Gao, Liming sec_no, sec_start, sec_length, sec_name, sec_class = m.groups(0) 136f51461c829c124288a930829a78e2a5a799f4039Gao, Liming secs.append([int(sec_no, 16), int(sec_start, 16), int(sec_length, 16), sec_name, sec_class]) 137f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if status == 2 and len(line) != 0: 138f51461c829c124288a930829a78e2a5a799f4039Gao, Liming m = symRe.match(line) 139f51461c829c124288a930829a78e2a5a799f4039Gao, Liming assert m != None, "Fail to parse the symbol in map file, line is %s" % line 140f51461c829c124288a930829a78e2a5a799f4039Gao, Liming sec_no, sym_offset, sym_name, vir_addr = m.groups(0) 14147fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu sec_no = int(sec_no, 16) 142f51461c829c124288a930829a78e2a5a799f4039Gao, Liming sym_offset = int(sym_offset, 16) 14347fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu vir_addr = int(vir_addr, 16) 144f51461c829c124288a930829a78e2a5a799f4039Gao, Liming m2 = re.match('^[_]+gPcd_BinaryPatch_([\w]+)', sym_name) 145f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if m2 != None: 146f51461c829c124288a930829a78e2a5a799f4039Gao, Liming # fond a binary pcd entry in map file 147f51461c829c124288a930829a78e2a5a799f4039Gao, Liming for sec in secs: 148f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if sec[0] == sec_no and (sym_offset >= sec[1] and sym_offset < sec[1] + sec[2]): 149f51461c829c124288a930829a78e2a5a799f4039Gao, Liming bPcds.append([m2.groups(0)[0], sec[3], sym_offset, vir_addr, sec_no]) 150f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 151f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if len(bPcds) == 0: return None 152f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 153f51461c829c124288a930829a78e2a5a799f4039Gao, Liming # get section information from efi file 154f51461c829c124288a930829a78e2a5a799f4039Gao, Liming efisecs = PeImageClass(efifilepath).SectionHeaderList 155f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if efisecs == None or len(efisecs) == 0: 156f51461c829c124288a930829a78e2a5a799f4039Gao, Liming return None 157f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 158f51461c829c124288a930829a78e2a5a799f4039Gao, Liming pcds = [] 159f51461c829c124288a930829a78e2a5a799f4039Gao, Liming for pcd in bPcds: 160f51461c829c124288a930829a78e2a5a799f4039Gao, Liming index = 0 161f51461c829c124288a930829a78e2a5a799f4039Gao, Liming for efisec in efisecs: 162f51461c829c124288a930829a78e2a5a799f4039Gao, Liming index = index + 1 163f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if pcd[1].strip() == efisec[0].strip(): 164f51461c829c124288a930829a78e2a5a799f4039Gao, Liming pcds.append([pcd[0], efisec[2] + pcd[2], efisec[0]]) 165f51461c829c124288a930829a78e2a5a799f4039Gao, Liming elif pcd[4] == index: 166f51461c829c124288a930829a78e2a5a799f4039Gao, Liming pcds.append([pcd[0], efisec[2] + pcd[2], efisec[0]]) 167f51461c829c124288a930829a78e2a5a799f4039Gao, Liming return pcds 168f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 169f51461c829c124288a930829a78e2a5a799f4039Gao, Limingdef generatePcdTable(list, pcdpath): 170f51461c829c124288a930829a78e2a5a799f4039Gao, Liming try: 171f51461c829c124288a930829a78e2a5a799f4039Gao, Liming f = open(pcdpath, 'w') 172f51461c829c124288a930829a78e2a5a799f4039Gao, Liming except: 173f51461c829c124288a930829a78e2a5a799f4039Gao, Liming pass 174f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 175f51461c829c124288a930829a78e2a5a799f4039Gao, Liming f.write('PCD Name Offset Section Name\r\n') 176f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 177f51461c829c124288a930829a78e2a5a799f4039Gao, Liming for pcditem in list: 178f51461c829c124288a930829a78e2a5a799f4039Gao, Liming f.write('%-30s 0x%-08X %-6s\r\n' % (pcditem[0], pcditem[1], pcditem[2])) 179f51461c829c124288a930829a78e2a5a799f4039Gao, Liming f.close() 180f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 181f51461c829c124288a930829a78e2a5a799f4039Gao, Liming #print 'Success to generate Binary Patch PCD table at %s!' % pcdpath 18247fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu 183f51461c829c124288a930829a78e2a5a799f4039Gao, Limingif __name__ == '__main__': 184f51461c829c124288a930829a78e2a5a799f4039Gao, Liming UsageString = "%prog -m <MapFile> -e <EfiFile> -o <OutFile>" 185f51461c829c124288a930829a78e2a5a799f4039Gao, Liming AdditionalNotes = "\nPCD table is generated in file name with .BinaryPcdTable.txt postfix" 186f51461c829c124288a930829a78e2a5a799f4039Gao, Liming parser = optparse.OptionParser(description=__copyright__, version=__version__, usage=UsageString) 187f51461c829c124288a930829a78e2a5a799f4039Gao, Liming parser.add_option('-m', '--mapfile', action='store', dest='mapfile', 188f51461c829c124288a930829a78e2a5a799f4039Gao, Liming help='Absolute path of module map file.') 189f51461c829c124288a930829a78e2a5a799f4039Gao, Liming parser.add_option('-e', '--efifile', action='store', dest='efifile', 190f51461c829c124288a930829a78e2a5a799f4039Gao, Liming help='Absolute path of EFI binary file.') 191f51461c829c124288a930829a78e2a5a799f4039Gao, Liming parser.add_option('-o', '--outputfile', action='store', dest='outfile', 192f51461c829c124288a930829a78e2a5a799f4039Gao, Liming help='Absolute path of output file to store the got patchable PCD table.') 193f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 194f51461c829c124288a930829a78e2a5a799f4039Gao, Liming (options, args) = parser.parse_args() 195f51461c829c124288a930829a78e2a5a799f4039Gao, Liming 196f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if options.mapfile == None or options.efifile == None: 197f51461c829c124288a930829a78e2a5a799f4039Gao, Liming print parser.get_usage() 198f51461c829c124288a930829a78e2a5a799f4039Gao, Liming elif os.path.exists(options.mapfile) and os.path.exists(options.efifile): 19947fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu list = parsePcdInfoFromMapFile(options.mapfile, options.efifile) 200f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if list != None: 201f51461c829c124288a930829a78e2a5a799f4039Gao, Liming if options.outfile != None: 202f51461c829c124288a930829a78e2a5a799f4039Gao, Liming generatePcdTable(list, options.outfile) 203f51461c829c124288a930829a78e2a5a799f4039Gao, Liming else: 20447fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu generatePcdTable(list, options.mapfile.replace('.map', '.BinaryPcdTable.txt')) 205f51461c829c124288a930829a78e2a5a799f4039Gao, Liming else: 206f51461c829c124288a930829a78e2a5a799f4039Gao, Liming print 'Fail to generate Patch PCD Table based on map file and efi file' 207f51461c829c124288a930829a78e2a5a799f4039Gao, Liming else: 208f51461c829c124288a930829a78e2a5a799f4039Gao, Liming print 'Fail to generate Patch PCD Table for fail to find map file or efi file!' 209