]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenPatchPcdTable/GenPatchPcdTable.py
2 # Generate PCD table for 'Patchable In Module' type PCD with given .map file.
3 # The Patch PCD table like:
5 # PCD Name Offset in binary
6 # ======== ================
8 # Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
9 # This program and the accompanying materials
10 # are licensed and made available under the terms and conditions of the BSD License
11 # which accompanies this distribution. The full text of the license may be found at
12 # http://opensource.org/licenses/bsd-license.php
14 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #====================================== External Libraries ========================================
25 from Common
.BuildToolError
import *
26 import Common
.EdkLogger
as EdkLogger
27 from Common
.Misc
import PeImageClass
28 from Common
.BuildVersion
import gBUILD_VERSION
30 # Version and Copyright
31 __version_number__
= ("0.10" + " " + gBUILD_VERSION
)
32 __version__
= "%prog Version " + __version_number__
33 __copyright__
= "Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved."
35 #====================================== Internal Libraries ========================================
37 #============================================== Code ===============================================
38 secRe
= re
.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\da-fA-F]+)[Hh]? +([.\w\$]+) +(\w+)', re
.UNICODE
)
39 symRe
= re
.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\.:\\\\\w\?@\$]+) +([\da-fA-F]+)', re
.UNICODE
)
41 def parsePcdInfoFromMapFile(mapfilepath
, efifilepath
):
42 """ Parse map file to get binary patch pcd information
43 @param path Map file absolution path
45 @return a list which element hold (PcdName, Offset, SectionName)
49 f
= open(mapfilepath
, 'r')
55 if len(lines
) == 0: return None
56 if lines
[0].strip().find("Archive member included because of file (symbol)") != -1:
57 return _parseForGCC(lines
, efifilepath
)
58 return _parseGeneral(lines
, efifilepath
)
60 def _parseForGCC(lines
, efifilepath
):
61 """ Parse map file generated by GCC linker """
68 # status machine transection
69 if status
== 0 and line
== "Memory Configuration":
72 elif status
== 1 and line
== 'Linker script and memory map':
75 elif status
==2 and line
== 'START GROUP':
81 m
= re
.match('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$', line
)
83 sections
.append(m
.groups(0))
85 m
= re
.match("^([\da-fA-Fx]+) +[_]+gPcd_BinaryPatch_([\w_\d]+)$", line
)
87 bpcds
.append((m
.groups(0)[1], int(m
.groups(0)[0], 16) , int(sections
[-1][1], 16), sections
[-1][0]))
89 # get section information from efi file
90 efisecs
= PeImageClass(efifilepath
).SectionHeaderList
91 if efisecs
== None or len(efisecs
) == 0:
95 for efisec
in efisecs
:
96 for section
in sections
:
97 if section
[0].strip() == efisec
[0].strip() and section
[0].strip() == '.text':
98 redirection
= int(section
[1], 16) - efisec
[1]
101 for efisec
in efisecs
:
102 if pcd
[1] >= efisec
[1] and pcd
[1] < efisec
[1]+efisec
[3]:
103 #assert efisec[0].strip() == pcd[3].strip() and efisec[1] + redirection == pcd[2], "There are some differences between map file and efi file"
104 pcds
.append([pcd
[0], efisec
[2] + pcd
[1] - efisec
[1] - redirection
, efisec
[0]])
107 def _parseGeneral(lines
, efifilepath
):
108 """ For MSFT, ICC, EBC
109 @param lines line array for map file
111 @return a list which element hold (PcdName, Offset, SectionName)
113 status
= 0 #0 - beginning of file; 1 - PE section definition; 2 - symbol table
114 secs
= [] # key = section name
120 if re
.match("^Start[' ']+Length[' ']+Name[' ']+Class", line
):
123 if re
.match("^Address[' ']+Publics by Value[' ']+Rva\+Base", line
):
126 if re
.match("^entry point at", line
):
129 if status
== 1 and len(line
) != 0:
130 m
= secRe
.match(line
)
131 assert m
!= None, "Fail to parse the section in map file , line is %s" % line
132 sec_no
, sec_start
, sec_length
, sec_name
, sec_class
= m
.groups(0)
133 secs
.append([int(sec_no
, 16), int(sec_start
, 16), int(sec_length
, 16), sec_name
, sec_class
])
134 if status
== 2 and len(line
) != 0:
135 m
= symRe
.match(line
)
136 assert m
!= None, "Fail to parse the symbol in map file, line is %s" % line
137 sec_no
, sym_offset
, sym_name
, vir_addr
= m
.groups(0)
138 sec_no
= int(sec_no
, 16)
139 sym_offset
= int(sym_offset
, 16)
140 vir_addr
= int(vir_addr
, 16)
141 m2
= re
.match('^[_]+gPcd_BinaryPatch_([\w]+)', sym_name
)
143 # fond a binary pcd entry in map file
145 if sec
[0] == sec_no
and (sym_offset
>= sec
[1] and sym_offset
< sec
[1] + sec
[2]):
146 bPcds
.append([m2
.groups(0)[0], sec
[3], sym_offset
, vir_addr
, sec_no
])
148 if len(bPcds
) == 0: return None
150 # get section information from efi file
151 efisecs
= PeImageClass(efifilepath
).SectionHeaderList
152 if efisecs
== None or len(efisecs
) == 0:
158 for efisec
in efisecs
:
160 if pcd
[1].strip() == efisec
[0].strip():
161 pcds
.append([pcd
[0], efisec
[2] + pcd
[2], efisec
[0]])
162 elif pcd
[4] == index
:
163 pcds
.append([pcd
[0], efisec
[2] + pcd
[2], efisec
[0]])
166 def generatePcdTable(list, pcdpath
):
168 f
= open(pcdpath
, 'w')
172 f
.write('PCD Name Offset Section Name\r\n')
175 f
.write('%-30s 0x%-08X %-6s\r\n' % (pcditem
[0], pcditem
[1], pcditem
[2]))
178 #print 'Success to generate Binary Patch PCD table at %s!' % pcdpath
180 if __name__
== '__main__':
181 UsageString
= "%prog -m <MapFile> -e <EfiFile> -o <OutFile>"
182 AdditionalNotes
= "\nPCD table is generated in file name with .BinaryPcdTable.txt postfix"
183 parser
= optparse
.OptionParser(description
=__copyright__
, version
=__version__
, usage
=UsageString
)
184 parser
.add_option('-m', '--mapfile', action
='store', dest
='mapfile',
185 help='Absolute path of module map file.')
186 parser
.add_option('-e', '--efifile', action
='store', dest
='efifile',
187 help='Absolute path of EFI binary file.')
188 parser
.add_option('-o', '--outputfile', action
='store', dest
='outfile',
189 help='Absolute path of output file to store the got patchable PCD table.')
191 (options
, args
) = parser
.parse_args()
193 if options
.mapfile
== None or options
.efifile
== None:
194 print parser
.get_usage()
195 elif os
.path
.exists(options
.mapfile
) and os
.path
.exists(options
.efifile
):
196 list = parsePcdInfoFromMapFile(options
.mapfile
, options
.efifile
)
198 if options
.outfile
!= None:
199 generatePcdTable(list, options
.outfile
)
201 generatePcdTable(list, options
.mapfile
.replace('.map', '.BinaryPcdTable.txt'))
203 print 'Fail to generate Patch PCD Table based on map file and efi file'
205 print 'Fail to generate Patch PCD Table for fail to find map file or efi file!'