]>
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 - 2018, 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 ========================================
21 import Common
.LongFilePathOs
as os
25 from Common
.BuildToolError
import *
26 import Common
.EdkLogger
as EdkLogger
27 from Common
.Misc
import PeImageClass
28 from Common
.BuildVersion
import gBUILD_VERSION
29 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
31 # Version and Copyright
32 __version_number__
= ("0.10" + " " + gBUILD_VERSION
)
33 __version__
= "%prog Version " + __version_number__
34 __copyright__
= "Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved."
36 #====================================== Internal Libraries ========================================
38 #============================================== Code ===============================================
39 secRe
= re
.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\da-fA-F]+)[Hh]? +([.\w\$]+) +(\w+)', re
.UNICODE
)
40 symRe
= re
.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\.\-:\\\\\w\?@\$<>]+) +([\da-fA-F]+)', re
.UNICODE
)
42 def parsePcdInfoFromMapFile(mapfilepath
, efifilepath
):
43 """ Parse map file to get binary patch pcd information
44 @param path Map file absolution path
46 @return a list which element hold (PcdName, Offset, SectionName)
50 f
= open(mapfilepath
, 'r')
56 if len(lines
) == 0: return None
57 firstline
= lines
[0].strip()
58 if (firstline
.startswith("Archive member included ") and
59 firstline
.endswith(" file (symbol)")):
60 return _parseForGCC(lines
, efifilepath
)
61 if firstline
.startswith("# Path:"):
62 return _parseForXcode(lines
, efifilepath
)
63 return _parseGeneral(lines
, efifilepath
)
65 def _parseForXcode(lines
, efifilepath
):
70 if status
== 0 and line
== "# Symbols:":
73 if status
== 1 and len(line
) != 0:
74 if '_gPcd_BinaryPatch_' in line
:
75 m
= re
.match('^([\da-fA-FxX]+)([\s\S]*)([_]*_gPcd_BinaryPatch_([\w]+))', line
)
77 pcds
.append((m
.groups(0)[3], int(m
.groups(0)[0], 16)))
80 def _parseForGCC(lines
, efifilepath
):
81 """ Parse map file generated by GCC linker """
86 for index
, line
in enumerate(lines
):
88 # status machine transection
89 if status
== 0 and line
== "Memory Configuration":
92 elif status
== 1 and line
== 'Linker script and memory map':
95 elif status
==2 and line
== 'START GROUP':
101 m
= re
.match('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$', line
)
103 sections
.append(m
.groups(0))
105 m
= re
.match('^.data._gPcd_BinaryPatch_([\w_\d]+)$', line
)
108 PcdName
= m
.groups(0)[0]
109 m
= re
.match('^([\da-fA-Fx]+) +([\da-fA-Fx]+)', lines
[index
+ 1].strip())
111 bpcds
.append((PcdName
, int(m
.groups(0)[0], 16) , int(sections
[-1][1], 16), sections
[-1][0]))
113 # get section information from efi file
114 efisecs
= PeImageClass(efifilepath
).SectionHeaderList
115 if efisecs
is None or len(efisecs
) == 0:
119 for efisec
in efisecs
:
120 for section
in sections
:
121 if section
[0].strip() == efisec
[0].strip() and section
[0].strip() == '.text':
122 redirection
= int(section
[1], 16) - efisec
[1]
125 for efisec
in efisecs
:
126 if pcd
[1] >= efisec
[1] and pcd
[1] < efisec
[1]+efisec
[3]:
127 #assert efisec[0].strip() == pcd[3].strip() and efisec[1] + redirection == pcd[2], "There are some differences between map file and efi file"
128 pcds
.append([pcd
[0], efisec
[2] + pcd
[1] - efisec
[1] - redirection
, efisec
[0]])
131 def _parseGeneral(lines
, efifilepath
):
132 """ For MSFT, ICC, EBC
133 @param lines line array for map file
135 @return a list which element hold (PcdName, Offset, SectionName)
137 status
= 0 #0 - beginning of file; 1 - PE section definition; 2 - symbol table
138 secs
= [] # key = section name
144 if re
.match("^Start[' ']+Length[' ']+Name[' ']+Class", line
):
147 if re
.match("^Address[' ']+Publics by Value[' ']+Rva\+Base", line
):
150 if re
.match("^entry point at", line
):
153 if status
== 1 and len(line
) != 0:
154 m
= secRe
.match(line
)
155 assert m
is not None, "Fail to parse the section in map file , line is %s" % line
156 sec_no
, sec_start
, sec_length
, sec_name
, sec_class
= m
.groups(0)
157 secs
.append([int(sec_no
, 16), int(sec_start
, 16), int(sec_length
, 16), sec_name
, sec_class
])
158 if status
== 2 and len(line
) != 0:
159 m
= symRe
.match(line
)
160 assert m
is not None, "Fail to parse the symbol in map file, line is %s" % line
161 sec_no
, sym_offset
, sym_name
, vir_addr
= m
.groups(0)
162 sec_no
= int(sec_no
, 16)
163 sym_offset
= int(sym_offset
, 16)
164 vir_addr
= int(vir_addr
, 16)
165 m2
= re
.match('^[_]+gPcd_BinaryPatch_([\w]+)', sym_name
)
167 # fond a binary pcd entry in map file
169 if sec
[0] == sec_no
and (sym_offset
>= sec
[1] and sym_offset
< sec
[1] + sec
[2]):
170 bPcds
.append([m2
.groups(0)[0], sec
[3], sym_offset
, vir_addr
, sec_no
])
172 if len(bPcds
) == 0: return None
174 # get section information from efi file
175 efisecs
= PeImageClass(efifilepath
).SectionHeaderList
176 if efisecs
is None or len(efisecs
) == 0:
182 for efisec
in efisecs
:
184 if pcd
[1].strip() == efisec
[0].strip():
185 pcds
.append([pcd
[0], efisec
[2] + pcd
[2], efisec
[0]])
186 elif pcd
[4] == index
:
187 pcds
.append([pcd
[0], efisec
[2] + pcd
[2], efisec
[0]])
190 def generatePcdTable(list, pcdpath
):
192 f
= open(pcdpath
, 'w')
196 f
.write('PCD Name Offset Section Name\r\n')
199 f
.write('%-30s 0x%-08X %-6s\r\n' % (pcditem
[0], pcditem
[1], pcditem
[2]))
202 #print 'Success to generate Binary Patch PCD table at %s!' % pcdpath
204 if __name__
== '__main__':
205 UsageString
= "%prog -m <MapFile> -e <EfiFile> -o <OutFile>"
206 AdditionalNotes
= "\nPCD table is generated in file name with .BinaryPcdTable.txt postfix"
207 parser
= optparse
.OptionParser(description
=__copyright__
, version
=__version__
, usage
=UsageString
)
208 parser
.add_option('-m', '--mapfile', action
='store', dest
='mapfile',
209 help='Absolute path of module map file.')
210 parser
.add_option('-e', '--efifile', action
='store', dest
='efifile',
211 help='Absolute path of EFI binary file.')
212 parser
.add_option('-o', '--outputfile', action
='store', dest
='outfile',
213 help='Absolute path of output file to store the got patchable PCD table.')
215 (options
, args
) = parser
.parse_args()
217 if options
.mapfile
is None or options
.efifile
is None:
218 print parser
.get_usage()
219 elif os
.path
.exists(options
.mapfile
) and os
.path
.exists(options
.efifile
):
220 list = parsePcdInfoFromMapFile(options
.mapfile
, options
.efifile
)
222 if options
.outfile
is not None:
223 generatePcdTable(list, options
.outfile
)
225 generatePcdTable(list, options
.mapfile
.replace('.map', '.BinaryPcdTable.txt'))
227 print 'Fail to generate Patch PCD Table based on map file and efi file'
229 print 'Fail to generate Patch PCD Table for fail to find map file or efi file!'