]>
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 firstline
= lines
[0].strip()
57 if (firstline
.startswith("Archive member included ") and
58 firstline
.endswith(" file (symbol)")):
59 return _parseForGCC(lines
, efifilepath
)
60 return _parseGeneral(lines
, efifilepath
)
62 def _parseForGCC(lines
, efifilepath
):
63 """ Parse map file generated by GCC linker """
70 # status machine transection
71 if status
== 0 and line
== "Memory Configuration":
74 elif status
== 1 and line
== 'Linker script and memory map':
77 elif status
==2 and line
== 'START GROUP':
83 m
= re
.match('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$', line
)
85 sections
.append(m
.groups(0))
87 m
= re
.match("^([\da-fA-Fx]+) +[_]+gPcd_BinaryPatch_([\w_\d]+)$", line
)
89 bpcds
.append((m
.groups(0)[1], int(m
.groups(0)[0], 16) , int(sections
[-1][1], 16), sections
[-1][0]))
91 # get section information from efi file
92 efisecs
= PeImageClass(efifilepath
).SectionHeaderList
93 if efisecs
== None or len(efisecs
) == 0:
97 for efisec
in efisecs
:
98 for section
in sections
:
99 if section
[0].strip() == efisec
[0].strip() and section
[0].strip() == '.text':
100 redirection
= int(section
[1], 16) - efisec
[1]
103 for efisec
in efisecs
:
104 if pcd
[1] >= efisec
[1] and pcd
[1] < efisec
[1]+efisec
[3]:
105 #assert efisec[0].strip() == pcd[3].strip() and efisec[1] + redirection == pcd[2], "There are some differences between map file and efi file"
106 pcds
.append([pcd
[0], efisec
[2] + pcd
[1] - efisec
[1] - redirection
, efisec
[0]])
109 def _parseGeneral(lines
, efifilepath
):
110 """ For MSFT, ICC, EBC
111 @param lines line array for map file
113 @return a list which element hold (PcdName, Offset, SectionName)
115 status
= 0 #0 - beginning of file; 1 - PE section definition; 2 - symbol table
116 secs
= [] # key = section name
122 if re
.match("^Start[' ']+Length[' ']+Name[' ']+Class", line
):
125 if re
.match("^Address[' ']+Publics by Value[' ']+Rva\+Base", line
):
128 if re
.match("^entry point at", line
):
131 if status
== 1 and len(line
) != 0:
132 m
= secRe
.match(line
)
133 assert m
!= None, "Fail to parse the section in map file , line is %s" % line
134 sec_no
, sec_start
, sec_length
, sec_name
, sec_class
= m
.groups(0)
135 secs
.append([int(sec_no
, 16), int(sec_start
, 16), int(sec_length
, 16), sec_name
, sec_class
])
136 if status
== 2 and len(line
) != 0:
137 m
= symRe
.match(line
)
138 assert m
!= None, "Fail to parse the symbol in map file, line is %s" % line
139 sec_no
, sym_offset
, sym_name
, vir_addr
= m
.groups(0)
140 sec_no
= int(sec_no
, 16)
141 sym_offset
= int(sym_offset
, 16)
142 vir_addr
= int(vir_addr
, 16)
143 m2
= re
.match('^[_]+gPcd_BinaryPatch_([\w]+)', sym_name
)
145 # fond a binary pcd entry in map file
147 if sec
[0] == sec_no
and (sym_offset
>= sec
[1] and sym_offset
< sec
[1] + sec
[2]):
148 bPcds
.append([m2
.groups(0)[0], sec
[3], sym_offset
, vir_addr
, sec_no
])
150 if len(bPcds
) == 0: return None
152 # get section information from efi file
153 efisecs
= PeImageClass(efifilepath
).SectionHeaderList
154 if efisecs
== None or len(efisecs
) == 0:
160 for efisec
in efisecs
:
162 if pcd
[1].strip() == efisec
[0].strip():
163 pcds
.append([pcd
[0], efisec
[2] + pcd
[2], efisec
[0]])
164 elif pcd
[4] == index
:
165 pcds
.append([pcd
[0], efisec
[2] + pcd
[2], efisec
[0]])
168 def generatePcdTable(list, pcdpath
):
170 f
= open(pcdpath
, 'w')
174 f
.write('PCD Name Offset Section Name\r\n')
177 f
.write('%-30s 0x%-08X %-6s\r\n' % (pcditem
[0], pcditem
[1], pcditem
[2]))
180 #print 'Success to generate Binary Patch PCD table at %s!' % pcdpath
182 if __name__
== '__main__':
183 UsageString
= "%prog -m <MapFile> -e <EfiFile> -o <OutFile>"
184 AdditionalNotes
= "\nPCD table is generated in file name with .BinaryPcdTable.txt postfix"
185 parser
= optparse
.OptionParser(description
=__copyright__
, version
=__version__
, usage
=UsageString
)
186 parser
.add_option('-m', '--mapfile', action
='store', dest
='mapfile',
187 help='Absolute path of module map file.')
188 parser
.add_option('-e', '--efifile', action
='store', dest
='efifile',
189 help='Absolute path of EFI binary file.')
190 parser
.add_option('-o', '--outputfile', action
='store', dest
='outfile',
191 help='Absolute path of output file to store the got patchable PCD table.')
193 (options
, args
) = parser
.parse_args()
195 if options
.mapfile
== None or options
.efifile
== None:
196 print parser
.get_usage()
197 elif os
.path
.exists(options
.mapfile
) and os
.path
.exists(options
.efifile
):
198 list = parsePcdInfoFromMapFile(options
.mapfile
, options
.efifile
)
200 if options
.outfile
!= None:
201 generatePcdTable(list, options
.outfile
)
203 generatePcdTable(list, options
.mapfile
.replace('.map', '.BinaryPcdTable.txt'))
205 print 'Fail to generate Patch PCD Table based on map file and efi file'
207 print 'Fail to generate Patch PCD Table for fail to find map file or efi file!'