BaseTools: remove duplicate function name
[mirror_edk2.git] / BaseTools / Source / Python / Eot / FvImage.py
1 ## @file
2 # Parse FV image
3 #
4 # Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13
14 ## Import Modules
15 #
16 import Common.LongFilePathOs as os
17 import re
18 import sys
19 import uuid
20 import struct
21 import codecs
22 import copy
23
24 from UserDict import IterableUserDict
25 from cStringIO import StringIO
26 from array import array
27 from Common.LongFilePathSupport import OpenLongFilePath as open
28 from CommonDataClass import *
29 from Common.Misc import sdict, GuidStructureStringToGuidString
30
31 import Common.EdkLogger as EdkLogger
32
33 import EotGlobalData
34
35 # Global definiton
36 gFfsPrintTitle = "%-36s %-21s %8s %8s %8s %-4s %-36s" % ("GUID", "TYPE", "OFFSET", "SIZE", "FREE", "ALIGN", "NAME")
37 gFfsPrintFormat = "%36s %-21s %8X %8X %8X %4s %-36s"
38 gGuidStringFormat = "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"
39 gPeiAprioriFileNameGuid = '1b45cc0a-156a-428a-af62-49864da0e6e6'
40 gAprioriGuid = 'fc510ee7-ffdc-11d4-bd41-0080c73c8881'
41 gIndention = -4
42
43 ## Image() class
44 #
45 # A class for Image
46 #
47 class Image(array):
48 _HEADER_ = struct.Struct("")
49 _HEADER_SIZE_ = _HEADER_.size
50
51 def __new__(cls, *args, **kwargs):
52 return array.__new__(cls, 'B')
53
54 def __init__(m, ID=None):
55 if ID is None:
56 m._ID_ = str(uuid.uuid1()).upper()
57 else:
58 m._ID_ = ID
59 m._BUF_ = None
60 m._LEN_ = None
61 m._OFF_ = None
62
63 m._SubImages = sdict() # {offset: Image()}
64
65 array.__init__(m, 'B')
66
67 def __repr__(m):
68 return m._ID_
69
70 def __len__(m):
71 Len = array.__len__(m)
72 for Offset in m._SubImages:
73 Len += len(m._SubImages[Offset])
74 return Len
75
76 def _Unpack(m):
77 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
78 return len(m)
79
80 def _Pack(m, PadByte=0xFF):
81 raise NotImplementedError
82
83 def frombuffer(m, Buffer, Offset=0, Size=None):
84 m._BUF_ = Buffer
85 m._OFF_ = Offset
86 # we may need the Size information in advance if it's given
87 m._LEN_ = Size
88 m._LEN_ = m._Unpack()
89
90 def empty(m):
91 del m[0:]
92
93 def GetField(m, FieldStruct, Offset=0):
94 return FieldStruct.unpack_from(m, Offset)
95
96 def SetField(m, FieldStruct, Offset, *args):
97 # check if there's enough space
98 Size = FieldStruct.size
99 if Size > len(m):
100 m.extend([0] * (Size - len(m)))
101 FieldStruct.pack_into(m, Offset, *args)
102
103 def _SetData(m, Data):
104 if len(m) < m._HEADER_SIZE_:
105 m.extend([0] * (m._HEADER_SIZE_ - len(m)))
106 else:
107 del m[m._HEADER_SIZE_:]
108 m.extend(Data)
109
110 def _GetData(m):
111 if len(m) > m._HEADER_SIZE_:
112 return m[m._HEADER_SIZE_:]
113 return None
114
115 Data = property(_GetData, _SetData)
116
117 ## FirmwareVolume() class
118 #
119 # A class for Firmware Volume
120 #
121 class FirmwareVolume(Image):
122 # Read FvLength, Attributes, HeaderLength, Checksum
123 _HEADER_ = struct.Struct("16x 1I2H8B 1Q 4x 1I 1H 1H")
124 _HEADER_SIZE_ = _HEADER_.size
125
126 _FfsGuid = "8C8CE578-8A3D-4F1C-9935-896185C32DD3"
127
128 _GUID_ = struct.Struct("16x 1I2H8B")
129 _LENGTH_ = struct.Struct("16x 16x 1Q")
130 _SIG_ = struct.Struct("16x 16x 8x 1I")
131 _ATTR_ = struct.Struct("16x 16x 8x 4x 1I")
132 _HLEN_ = struct.Struct("16x 16x 8x 4x 4x 1H")
133 _CHECKSUM_ = struct.Struct("16x 16x 8x 4x 4x 2x 1H")
134
135 def __init__(self, Name=''):
136 Image.__init__(self)
137 self.Name = Name
138 self.FfsDict = sdict()
139 self.OrderedFfsDict = sdict()
140 self.UnDispatchedFfsDict = sdict()
141 self.ProtocolList = sdict()
142
143 def CheckArchProtocol(self):
144 for Item in EotGlobalData.gArchProtocolGuids:
145 if Item.lower() not in EotGlobalData.gProtocolList:
146
147 return False
148
149 return True
150
151 def ParseDepex(self, Depex, Type):
152 List = None
153 if Type == 'Ppi':
154 List = EotGlobalData.gPpiList
155 if Type == 'Protocol':
156 List = EotGlobalData.gProtocolList
157 DepexStack = []
158 DepexList = []
159 DepexString = ''
160 FileDepex = None
161 CouldBeLoaded = True
162 for Index in range(0, len(Depex.Expression)):
163 Item = Depex.Expression[Index]
164 if Item == 0x00:
165 Index = Index + 1
166 Guid = gGuidStringFormat % Depex.Expression[Index]
167 if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
168 return (True, 'BEFORE %s' % Guid, [Guid, 'BEFORE'])
169 elif Item == 0x01:
170 Index = Index + 1
171 Guid = gGuidStringFormat % Depex.Expression[Index]
172 if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
173 return (True, 'AFTER %s' % Guid, [Guid, 'AFTER'])
174 elif Item == 0x02:
175 Index = Index + 1
176 Guid = gGuidStringFormat % Depex.Expression[Index]
177 if Guid.lower() in List:
178 DepexStack.append(True)
179 DepexList.append(Guid)
180 else:
181 DepexStack.append(False)
182 DepexList.append(Guid)
183 continue
184 elif Item == 0x03 or Item == 0x04:
185 DepexStack.append(eval(str(DepexStack.pop()) + ' ' + Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
186 DepexList.append(str(DepexList.pop()) + ' ' + Depex._OPCODE_STRING_[Item].upper() + ' ' + str(DepexList.pop()))
187 elif Item == 0x05:
188 DepexStack.append(eval(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
189 DepexList.append(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexList.pop()))
190 elif Item == 0x06:
191 DepexStack.append(True)
192 DepexList.append('TRUE')
193 DepexString = DepexString + 'TRUE' + ' '
194 elif Item == 0x07:
195 DepexStack.append(False)
196 DepexList.append('False')
197 DepexString = DepexString + 'FALSE' + ' '
198 elif Item == 0x08:
199 if Index != len(Depex.Expression) - 1:
200 CouldBeLoaded = False
201 else:
202 CouldBeLoaded = DepexStack.pop()
203 else:
204 CouldBeLoaded = False
205 if DepexList != []:
206 DepexString = DepexList[0].strip()
207 return (CouldBeLoaded, DepexString, FileDepex)
208
209 def Dispatch(self, Db = None):
210 if Db is None:
211 return False
212 self.UnDispatchedFfsDict = copy.copy(self.FfsDict)
213 # Find PeiCore, DexCore, PeiPriori, DxePriori first
214 FfsSecCoreGuid = None
215 FfsPeiCoreGuid = None
216 FfsDxeCoreGuid = None
217 FfsPeiPrioriGuid = None
218 FfsDxePrioriGuid = None
219 for FfsID in self.UnDispatchedFfsDict:
220 Ffs = self.UnDispatchedFfsDict[FfsID]
221 if Ffs.Type == 0x03:
222 FfsSecCoreGuid = FfsID
223 continue
224 if Ffs.Type == 0x04:
225 FfsPeiCoreGuid = FfsID
226 continue
227 if Ffs.Type == 0x05:
228 FfsDxeCoreGuid = FfsID
229 continue
230 if Ffs.Guid.lower() == gPeiAprioriFileNameGuid:
231 FfsPeiPrioriGuid = FfsID
232 continue
233 if Ffs.Guid.lower() == gAprioriGuid:
234 FfsDxePrioriGuid = FfsID
235 continue
236
237 # Parse SEC_CORE first
238 if FfsSecCoreGuid is not None:
239 self.OrderedFfsDict[FfsSecCoreGuid] = self.UnDispatchedFfsDict.pop(FfsSecCoreGuid)
240 self.LoadPpi(Db, FfsSecCoreGuid)
241
242 # Parse PEI first
243 if FfsPeiCoreGuid is not None:
244 self.OrderedFfsDict[FfsPeiCoreGuid] = self.UnDispatchedFfsDict.pop(FfsPeiCoreGuid)
245 self.LoadPpi(Db, FfsPeiCoreGuid)
246 if FfsPeiPrioriGuid is not None:
247 # Load PEIM described in priori file
248 FfsPeiPriori = self.UnDispatchedFfsDict.pop(FfsPeiPrioriGuid)
249 if len(FfsPeiPriori.Sections) == 1:
250 Section = FfsPeiPriori.Sections.popitem()[1]
251 if Section.Type == 0x19:
252 GuidStruct = struct.Struct('1I2H8B')
253 Start = 4
254 while len(Section) > Start:
255 Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
256 GuidString = gGuidStringFormat % Guid
257 Start = Start + 16
258 if GuidString in self.UnDispatchedFfsDict:
259 self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
260 self.LoadPpi(Db, GuidString)
261
262 self.DisPatchPei(Db)
263
264 # Parse DXE then
265 if FfsDxeCoreGuid is not None:
266 self.OrderedFfsDict[FfsDxeCoreGuid] = self.UnDispatchedFfsDict.pop(FfsDxeCoreGuid)
267 self.LoadProtocol(Db, FfsDxeCoreGuid)
268 if FfsDxePrioriGuid is not None:
269 # Load PEIM described in priori file
270 FfsDxePriori = self.UnDispatchedFfsDict.pop(FfsDxePrioriGuid)
271 if len(FfsDxePriori.Sections) == 1:
272 Section = FfsDxePriori.Sections.popitem()[1]
273 if Section.Type == 0x19:
274 GuidStruct = struct.Struct('1I2H8B')
275 Start = 4
276 while len(Section) > Start:
277 Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
278 GuidString = gGuidStringFormat % Guid
279 Start = Start + 16
280 if GuidString in self.UnDispatchedFfsDict:
281 self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
282 self.LoadProtocol(Db, GuidString)
283
284 self.DisPatchDxe(Db)
285
286 def LoadProtocol(self, Db, ModuleGuid):
287 SqlCommand = """select GuidValue from Report
288 where SourceFileFullPath in
289 (select Value1 from Inf where BelongsToFile =
290 (select BelongsToFile from Inf
291 where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
292 and Model = %s)
293 and ItemType = 'Protocol' and ItemMode = 'Produced'""" \
294 % (ModuleGuid, 5001, 3007)
295 RecordSet = Db.TblReport.Exec(SqlCommand)
296 for Record in RecordSet:
297 SqlCommand = """select Value2 from Inf where BelongsToFile =
298 (select DISTINCT BelongsToFile from Inf
299 where Value1 =
300 (select SourceFileFullPath from Report
301 where GuidValue like '%s' and ItemMode = 'Callback'))
302 and Value1 = 'FILE_GUID'""" % Record[0]
303 CallBackSet = Db.TblReport.Exec(SqlCommand)
304 if CallBackSet != []:
305 EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
306 else:
307 EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
308
309 def LoadPpi(self, Db, ModuleGuid):
310 SqlCommand = """select GuidValue from Report
311 where SourceFileFullPath in
312 (select Value1 from Inf where BelongsToFile =
313 (select BelongsToFile from Inf
314 where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
315 and Model = %s)
316 and ItemType = 'Ppi' and ItemMode = 'Produced'""" \
317 % (ModuleGuid, 5001, 3007)
318 RecordSet = Db.TblReport.Exec(SqlCommand)
319 for Record in RecordSet:
320 EotGlobalData.gPpiList[Record[0].lower()] = ModuleGuid
321
322 def DisPatchDxe(self, Db):
323 IsInstalled = False
324 ScheduleList = sdict()
325 for FfsID in self.UnDispatchedFfsDict:
326 CouldBeLoaded = False
327 DepexString = ''
328 FileDepex = None
329 Ffs = self.UnDispatchedFfsDict[FfsID]
330 if Ffs.Type == 0x07:
331 # Get Depex
332 IsFoundDepex = False
333 for Section in Ffs.Sections.values():
334 # Find Depex
335 if Section.Type == 0x13:
336 IsFoundDepex = True
337 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Protocol')
338 break
339 if Section.Type == 0x01:
340 CompressSections = Section._SubImages[4]
341 for CompressSection in CompressSections.Sections:
342 if CompressSection.Type == 0x13:
343 IsFoundDepex = True
344 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Protocol')
345 break
346 if CompressSection.Type == 0x02:
347 NewSections = CompressSection._SubImages[4]
348 for NewSection in NewSections.Sections:
349 if NewSection.Type == 0x13:
350 IsFoundDepex = True
351 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Protocol')
352 break
353
354 # Not find Depex
355 if not IsFoundDepex:
356 CouldBeLoaded = self.CheckArchProtocol()
357 DepexString = ''
358 FileDepex = None
359
360 # Append New Ffs
361 if CouldBeLoaded:
362 IsInstalled = True
363 NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
364 NewFfs.Depex = DepexString
365 if FileDepex is not None:
366 ScheduleList.insert(FileDepex[1], FfsID, NewFfs, FileDepex[0])
367 else:
368 ScheduleList[FfsID] = NewFfs
369 else:
370 self.UnDispatchedFfsDict[FfsID].Depex = DepexString
371
372 for FfsID in ScheduleList:
373 NewFfs = ScheduleList.pop(FfsID)
374 FfsName = 'UnKnown'
375 self.OrderedFfsDict[FfsID] = NewFfs
376 self.LoadProtocol(Db, FfsID)
377
378 SqlCommand = """select Value2 from Inf
379 where BelongsToFile = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)
380 and Model = %s and Value1='BASE_NAME'""" % (FfsID, 5001, 5001)
381 RecordSet = Db.TblReport.Exec(SqlCommand)
382 if RecordSet != []:
383 FfsName = RecordSet[0][0]
384
385 if IsInstalled:
386 self.DisPatchDxe(Db)
387
388 def DisPatchPei(self, Db):
389 IsInstalled = False
390 for FfsID in self.UnDispatchedFfsDict:
391 CouldBeLoaded = True
392 DepexString = ''
393 FileDepex = None
394 Ffs = self.UnDispatchedFfsDict[FfsID]
395 if Ffs.Type == 0x06 or Ffs.Type == 0x08:
396 # Get Depex
397 for Section in Ffs.Sections.values():
398 if Section.Type == 0x1B:
399 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Ppi')
400 break
401
402 if Section.Type == 0x01:
403 CompressSections = Section._SubImages[4]
404 for CompressSection in CompressSections.Sections:
405 if CompressSection.Type == 0x1B:
406 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Ppi')
407 break
408 if CompressSection.Type == 0x02:
409 NewSections = CompressSection._SubImages[4]
410 for NewSection in NewSections.Sections:
411 if NewSection.Type == 0x1B:
412 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Ppi')
413 break
414
415 # Append New Ffs
416 if CouldBeLoaded:
417 IsInstalled = True
418 NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
419 NewFfs.Depex = DepexString
420 self.OrderedFfsDict[FfsID] = NewFfs
421 self.LoadPpi(Db, FfsID)
422 else:
423 self.UnDispatchedFfsDict[FfsID].Depex = DepexString
424
425 if IsInstalled:
426 self.DisPatchPei(Db)
427
428
429 def __str__(self):
430 global gIndention
431 gIndention += 4
432 FvInfo = '\n' + ' ' * gIndention
433 FvInfo += "[FV:%s] file_system=%s size=%x checksum=%s\n" % (self.Name, self.FileSystemGuid, self.Size, self.Checksum)
434 FfsInfo = "\n".join([str(self.FfsDict[FfsId]) for FfsId in self.FfsDict])
435 gIndention -= 4
436 return FvInfo + FfsInfo
437
438 def _Unpack(self):
439 Size = self._LENGTH_.unpack_from(self._BUF_, self._OFF_)[0]
440 self.empty()
441 self.extend(self._BUF_[self._OFF_:self._OFF_+Size])
442
443 # traverse the FFS
444 EndOfFv = Size
445 FfsStartAddress = self.HeaderSize
446 LastFfsObj = None
447 while FfsStartAddress < EndOfFv:
448 FfsObj = Ffs()
449 FfsObj.frombuffer(self, FfsStartAddress)
450 FfsId = repr(FfsObj)
451 if ((self.Attributes & 0x00000800) != 0 and len(FfsObj) == 0xFFFFFF) \
452 or ((self.Attributes & 0x00000800) == 0 and len(FfsObj) == 0):
453 if LastFfsObj is not None:
454 LastFfsObj.FreeSpace = EndOfFv - LastFfsObj._OFF_ - len(LastFfsObj)
455 else:
456 if FfsId in self.FfsDict:
457 EdkLogger.error("FV", 0, "Duplicate GUID in FFS",
458 ExtraData="\t%s @ %s\n\t%s @ %s" \
459 % (FfsObj.Guid, FfsObj.Offset,
460 self.FfsDict[FfsId].Guid, self.FfsDict[FfsId].Offset))
461 self.FfsDict[FfsId] = FfsObj
462 if LastFfsObj is not None:
463 LastFfsObj.FreeSpace = FfsStartAddress - LastFfsObj._OFF_ - len(LastFfsObj)
464
465 FfsStartAddress += len(FfsObj)
466 #
467 # align to next 8-byte aligned address: A = (A + 8 - 1) & (~(8 - 1))
468 # The next FFS must be at the latest next 8-byte aligned address
469 #
470 FfsStartAddress = (FfsStartAddress + 7) & (~7)
471 LastFfsObj = FfsObj
472
473 def _GetAttributes(self):
474 return self.GetField(self._ATTR_, 0)[0]
475
476 def _GetSize(self):
477 return self.GetField(self._LENGTH_, 0)[0]
478
479 def _GetChecksum(self):
480 return self.GetField(self._CHECKSUM_, 0)[0]
481
482 def _GetHeaderLength(self):
483 return self.GetField(self._HLEN_, 0)[0]
484
485 def _GetFileSystemGuid(self):
486 return gGuidStringFormat % self.GetField(self._GUID_, 0)
487
488 Attributes = property(_GetAttributes)
489 Size = property(_GetSize)
490 Checksum = property(_GetChecksum)
491 HeaderSize = property(_GetHeaderLength)
492 FileSystemGuid = property(_GetFileSystemGuid)
493
494 ## CompressedImage() class
495 #
496 # A class for Compressed Image
497 #
498 class CompressedImage(Image):
499 # UncompressedLength = 4-byte
500 # CompressionType = 1-byte
501 _HEADER_ = struct.Struct("1I 1B")
502 _HEADER_SIZE_ = _HEADER_.size
503
504 _ORIG_SIZE_ = struct.Struct("1I")
505 _CMPRS_TYPE_ = struct.Struct("4x 1B")
506
507 def __init__(m, CompressedData=None, CompressionType=None, UncompressedLength=None):
508 Image.__init__(m)
509 if UncompressedLength is not None:
510 m.UncompressedLength = UncompressedLength
511 if CompressionType is not None:
512 m.CompressionType = CompressionType
513 if CompressedData is not None:
514 m.Data = CompressedData
515
516 def __str__(m):
517 global gIndention
518 S = "algorithm=%s uncompressed=%x" % (m.CompressionType, m.UncompressedLength)
519 for Sec in m.Sections:
520 S += '\n' + str(Sec)
521
522 return S
523
524 def _SetOriginalSize(m, Size):
525 m.SetField(m._ORIG_SIZE_, 0, Size)
526
527 def _GetOriginalSize(m):
528 return m.GetField(m._ORIG_SIZE_)[0]
529
530 def _SetCompressionType(m, Type):
531 m.SetField(m._CMPRS_TYPE_, 0, Type)
532
533 def _GetCompressionType(m):
534 return m.GetField(m._CMPRS_TYPE_)[0]
535
536 def _GetSections(m):
537 try:
538 import EfiCompressor
539 TmpData = EfiCompressor.FrameworkDecompress(
540 m[m._HEADER_SIZE_:],
541 len(m) - m._HEADER_SIZE_
542 )
543 DecData = array('B')
544 DecData.fromstring(TmpData)
545 except:
546 import EfiCompressor
547 TmpData = EfiCompressor.UefiDecompress(
548 m[m._HEADER_SIZE_:],
549 len(m) - m._HEADER_SIZE_
550 )
551 DecData = array('B')
552 DecData.fromstring(TmpData)
553
554 SectionList = []
555 Offset = 0
556 while Offset < len(DecData):
557 Sec = Section()
558 try:
559 Sec.frombuffer(DecData, Offset)
560 Offset += Sec.Size
561 # the section is aligned to 4-byte boundary
562 except:
563 break
564 SectionList.append(Sec)
565 return SectionList
566
567 UncompressedLength = property(_GetOriginalSize, _SetOriginalSize)
568 CompressionType = property(_GetCompressionType, _SetCompressionType)
569 Sections = property(_GetSections)
570
571 ## GuidDefinedImage() class
572 #
573 # A class for GUID Defined Image
574 #
575 class GuidDefinedImage(Image):
576 _HEADER_ = struct.Struct("1I2H8B 1H 1H")
577 _HEADER_SIZE_ = _HEADER_.size
578
579 _GUID_ = struct.Struct("1I2H8B")
580 _DATA_OFFSET_ = struct.Struct("16x 1H")
581 _ATTR_ = struct.Struct("18x 1H")
582
583 CRC32_GUID = "FC1BCDB0-7D31-49AA-936A-A4600D9DD083"
584 TIANO_COMPRESS_GUID = 'A31280AD-481E-41B6-95E8-127F4C984779'
585 LZMA_COMPRESS_GUID = 'EE4E5898-3914-4259-9D6E-DC7BD79403CF'
586
587 def __init__(m, SectionDefinitionGuid=None, DataOffset=None, Attributes=None, Data=None):
588 Image.__init__(m)
589 if SectionDefinitionGuid is not None:
590 m.SectionDefinitionGuid = SectionDefinitionGuid
591 if DataOffset is not None:
592 m.DataOffset = DataOffset
593 if Attributes is not None:
594 m.Attributes = Attributes
595 if Data is not None:
596 m.Data = Data
597
598 def __str__(m):
599 S = "guid=%s" % (gGuidStringFormat % m.SectionDefinitionGuid)
600 for Sec in m.Sections:
601 S += "\n" + str(Sec)
602 return S
603
604 def _Unpack(m):
605 # keep header in this Image object
606 m.empty()
607 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
608 return len(m)
609
610 def _SetAttribute(m, Attribute):
611 m.SetField(m._ATTR_, 0, Attribute)
612
613 def _GetAttribute(m):
614 return m.GetField(m._ATTR_)[0]
615
616 def _SetGuid(m, Guid):
617 m.SetField(m._GUID_, 0, Guid)
618
619 def _GetGuid(m):
620 return m.GetField(m._GUID_)
621
622 def _SetDataOffset(m, Offset):
623 m.SetField(m._DATA_OFFSET_, 0, Offset)
624
625 def _GetDataOffset(m):
626 return m.GetField(m._DATA_OFFSET_)[0]
627
628 def _GetSections(m):
629 SectionList = []
630 Guid = gGuidStringFormat % m.SectionDefinitionGuid
631 if Guid == m.CRC32_GUID:
632 # skip the CRC32 value, we don't do CRC32 verification here
633 Offset = m.DataOffset - 4
634 while Offset < len(m):
635 Sec = Section()
636 try:
637 Sec.frombuffer(m, Offset)
638 Offset += Sec.Size
639 # the section is aligned to 4-byte boundary
640 Offset = (Offset + 3) & (~3)
641 except:
642 break
643 SectionList.append(Sec)
644 elif Guid == m.TIANO_COMPRESS_GUID:
645 try:
646 import EfiCompressor
647 # skip the header
648 Offset = m.DataOffset - 4
649 TmpData = EfiCompressor.FrameworkDecompress(m[Offset:], len(m)-Offset)
650 DecData = array('B')
651 DecData.fromstring(TmpData)
652 Offset = 0
653 while Offset < len(DecData):
654 Sec = Section()
655 try:
656 Sec.frombuffer(DecData, Offset)
657 Offset += Sec.Size
658 # the section is aligned to 4-byte boundary
659 Offset = (Offset + 3) & (~3)
660 except:
661 break
662 SectionList.append(Sec)
663 except:
664 pass
665 elif Guid == m.LZMA_COMPRESS_GUID:
666 try:
667 import LzmaCompressor
668 # skip the header
669 Offset = m.DataOffset - 4
670 TmpData = LzmaCompressor.LzmaDecompress(m[Offset:], len(m)-Offset)
671 DecData = array('B')
672 DecData.fromstring(TmpData)
673 Offset = 0
674 while Offset < len(DecData):
675 Sec = Section()
676 try:
677 Sec.frombuffer(DecData, Offset)
678 Offset += Sec.Size
679 # the section is aligned to 4-byte boundary
680 Offset = (Offset + 3) & (~3)
681 except:
682 break
683 SectionList.append(Sec)
684 except:
685 pass
686
687 return SectionList
688
689 Attributes = property(_GetAttribute, _SetAttribute)
690 SectionDefinitionGuid = property(_GetGuid, _SetGuid)
691 DataOffset = property(_GetDataOffset, _SetDataOffset)
692 Sections = property(_GetSections)
693
694 ## Depex() class
695 #
696 # A class for Depex
697 #
698 class Depex(Image):
699 _HEADER_ = struct.Struct("")
700 _HEADER_SIZE_ = 0
701
702 _GUID_ = struct.Struct("1I2H8B")
703 _OPCODE_ = struct.Struct("1B")
704
705 _OPCODE_STRING_ = {
706 0x00 : "BEFORE",
707 0x01 : "AFTER",
708 0x02 : "PUSH",
709 0x03 : "AND",
710 0x04 : "OR",
711 0x05 : "NOT",
712 0x06 : "TRUE",
713 0x07 : "FALSE",
714 0x08 : "END",
715 0x09 : "SOR"
716 }
717
718 _NEXT_ = {
719 -1 : _OPCODE_, # first one in depex must be an opcdoe
720 0x00 : _GUID_, #"BEFORE",
721 0x01 : _GUID_, #"AFTER",
722 0x02 : _GUID_, #"PUSH",
723 0x03 : _OPCODE_, #"AND",
724 0x04 : _OPCODE_, #"OR",
725 0x05 : _OPCODE_, #"NOT",
726 0x06 : _OPCODE_, #"TRUE",
727 0x07 : _OPCODE_, #"FALSE",
728 0x08 : None, #"END",
729 0x09 : _OPCODE_, #"SOR"
730 }
731
732 def __init__(m):
733 Image.__init__(m)
734 m._ExprList = []
735
736 def __str__(m):
737 global gIndention
738 gIndention += 4
739 Indention = ' ' * gIndention
740 S = '\n'
741 for T in m.Expression:
742 if T in m._OPCODE_STRING_:
743 S += Indention + m._OPCODE_STRING_[T]
744 if T not in [0x00, 0x01, 0x02]:
745 S += '\n'
746 else:
747 S += ' ' + gGuidStringFormat % T + '\n'
748 gIndention -= 4
749 return S
750
751 def _Unpack(m):
752 # keep header in this Image object
753 m.empty()
754 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
755 return len(m)
756
757 def _GetExpression(m):
758 if m._ExprList == []:
759 Offset = 0
760 CurrentData = m._OPCODE_
761 while Offset < len(m):
762 Token = CurrentData.unpack_from(m, Offset)
763 Offset += CurrentData.size
764 if len(Token) == 1:
765 Token = Token[0]
766 if Token in m._NEXT_:
767 CurrentData = m._NEXT_[Token]
768 else:
769 CurrentData = m._GUID_
770 else:
771 CurrentData = m._OPCODE_
772 m._ExprList.append(Token)
773 if CurrentData is None:
774 break
775 return m._ExprList
776
777 Expression = property(_GetExpression)
778
779 ## Ui() class
780 #
781 # A class for Ui
782 #
783 class Ui(Image):
784 _HEADER_ = struct.Struct("")
785 _HEADER_SIZE_ = 0
786
787 def __init__(m):
788 Image.__init__(m)
789
790 def __str__(m):
791 return m.String
792
793 def _Unpack(m):
794 # keep header in this Image object
795 m.empty()
796 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
797 return len(m)
798
799 def _GetUiString(m):
800 return codecs.utf_16_decode(m[0:-2].tostring())[0]
801
802 String = property(_GetUiString)
803
804 ## Section() class
805 #
806 # A class for Section
807 #
808 class Section(Image):
809 _TypeName = {
810 0x00 : "<unknown>",
811 0x01 : "COMPRESSION",
812 0x02 : "GUID_DEFINED",
813 0x10 : "PE32",
814 0x11 : "PIC",
815 0x12 : "TE",
816 0x13 : "DXE_DEPEX",
817 0x14 : "VERSION",
818 0x15 : "USER_INTERFACE",
819 0x16 : "COMPATIBILITY16",
820 0x17 : "FIRMWARE_VOLUME_IMAGE",
821 0x18 : "FREEFORM_SUBTYPE_GUID",
822 0x19 : "RAW",
823 0x1B : "PEI_DEPEX"
824 }
825
826 _SectionSubImages = {
827 0x01 : CompressedImage,
828 0x02 : GuidDefinedImage,
829 0x17 : FirmwareVolume,
830 0x13 : Depex,
831 0x1B : Depex,
832 0x15 : Ui
833 }
834
835 # Size = 3-byte
836 # Type = 1-byte
837 _HEADER_ = struct.Struct("3B 1B")
838 _HEADER_SIZE_ = _HEADER_.size
839
840 # SubTypeGuid
841 # _FREE_FORM_SUBTYPE_GUID_HEADER_ = struct.Struct("1I2H8B")
842
843 _SIZE_ = struct.Struct("3B")
844 _TYPE_ = struct.Struct("3x 1B")
845
846 def __init__(m, Type=None, Size=None):
847 Image.__init__(m)
848 m._Alignment = 1
849 if Type is not None:
850 m.Type = Type
851 if Size is not None:
852 m.Size = Size
853
854 def __str__(m):
855 global gIndention
856 gIndention += 4
857 SectionInfo = ' ' * gIndention
858 if m.Type in m._TypeName:
859 SectionInfo += "[SECTION:%s] offset=%x size=%x" % (m._TypeName[m.Type], m._OFF_, m.Size)
860 else:
861 SectionInfo += "[SECTION:%x<unknown>] offset=%x size=%x " % (m.Type, m._OFF_, m.Size)
862 for Offset in m._SubImages:
863 SectionInfo += ", " + str(m._SubImages[Offset])
864 gIndention -= 4
865 return SectionInfo
866
867 def _Unpack(m):
868 m.empty()
869 Type, = m._TYPE_.unpack_from(m._BUF_, m._OFF_)
870 Size1, Size2, Size3 = m._SIZE_.unpack_from(m._BUF_, m._OFF_)
871 Size = Size1 + (Size2 << 8) + (Size3 << 16)
872
873 if Type not in m._SectionSubImages:
874 # no need to extract sub-image, keep all in this Image object
875 m.extend(m._BUF_[m._OFF_ : m._OFF_ + Size])
876 else:
877 # keep header in this Image object
878 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._HEADER_SIZE_])
879 #
880 # use new Image object to represent payload, which may be another kind
881 # of image such as PE32
882 #
883 PayloadOffset = m._HEADER_SIZE_
884 PayloadLen = m.Size - m._HEADER_SIZE_
885 Payload = m._SectionSubImages[m.Type]()
886 Payload.frombuffer(m._BUF_, m._OFF_ + m._HEADER_SIZE_, PayloadLen)
887 m._SubImages[PayloadOffset] = Payload
888
889 return Size
890
891 def _SetSize(m, Size):
892 Size1 = Size & 0xFF
893 Size2 = (Size & 0xFF00) >> 8
894 Size3 = (Size & 0xFF0000) >> 16
895 m.SetField(m._SIZE_, 0, Size1, Size2, Size3)
896
897 def _GetSize(m):
898 Size1, Size2, Size3 = m.GetField(m._SIZE_)
899 return Size1 + (Size2 << 8) + (Size3 << 16)
900
901 def _SetType(m, Type):
902 m.SetField(m._TYPE_, 0, Type)
903
904 def _GetType(m):
905 return m.GetField(m._TYPE_)[0]
906
907 def _GetAlignment(m):
908 return m._Alignment
909
910 def _SetAlignment(m, Alignment):
911 m._Alignment = Alignment
912 AlignmentMask = Alignment - 1
913 # section alignment is actually for payload, so we need to add header size
914 PayloadOffset = m._OFF_ + m._HEADER_SIZE_
915 if (PayloadOffset & (~AlignmentMask)) == 0:
916 return
917 NewOffset = (PayloadOffset + AlignmentMask) & (~AlignmentMask)
918 while (NewOffset - PayloadOffset) < m._HEADER_SIZE_:
919 NewOffset += m._Alignment
920
921 def tofile(m, f):
922 m.Size = len(m)
923 Image.tofile(m, f)
924 for Offset in m._SubImages:
925 m._SubImages[Offset].tofile(f)
926
927 Type = property(_GetType, _SetType)
928 Size = property(_GetSize, _SetSize)
929 Alignment = property(_GetAlignment, _SetAlignment)
930 # SubTypeGuid = property(_GetGuid, _SetGuid)
931
932 ## PadSection() class
933 #
934 # A class for Pad Section
935 #
936 class PadSection(Section):
937 def __init__(m, Size):
938 Section.__init__(m)
939 m.Type = 0x19
940 m.Size = Size
941 m.Data = [0] * (Size - m._HEADER_SIZE_)
942
943 ## Ffs() class
944 #
945 # A class for Ffs Section
946 #
947 class Ffs(Image):
948 _FfsFormat = "24B%(payload_size)sB"
949 # skip IntegrityCheck
950 _HEADER_ = struct.Struct("1I2H8B 2x 1B 1B 3B 1B")
951 _HEADER_SIZE_ = _HEADER_.size
952
953 _NAME_ = struct.Struct("1I2H8B")
954 _INT_CHECK_ = struct.Struct("16x 1H")
955 _TYPE_ = struct.Struct("18x 1B")
956 _ATTR_ = struct.Struct("19x 1B")
957 _SIZE_ = struct.Struct("20x 3B")
958 _STATE_ = struct.Struct("23x 1B")
959
960 VTF_GUID = "1BA0062E-C779-4582-8566-336AE8F78F09"
961
962 FFS_ATTRIB_FIXED = 0x04
963 FFS_ATTRIB_DATA_ALIGNMENT = 0x38
964 FFS_ATTRIB_CHECKSUM = 0x40
965
966 _TypeName = {
967 0x00 : "<unknown>",
968 0x01 : "RAW",
969 0x02 : "FREEFORM",
970 0x03 : "SECURITY_CORE",
971 0x04 : "PEI_CORE",
972 0x05 : "DXE_CORE",
973 0x06 : "PEIM",
974 0x07 : "DRIVER",
975 0x08 : "COMBINED_PEIM_DRIVER",
976 0x09 : "APPLICATION",
977 0x0A : "SMM",
978 0x0B : "FIRMWARE_VOLUME_IMAGE",
979 0x0C : "COMBINED_SMM_DXE",
980 0x0D : "SMM_CORE",
981 0x0E : "MM_STANDALONE",
982 0x0F : "MM_CORE_STANDALONE",
983 0xc0 : "OEM_MIN",
984 0xdf : "OEM_MAX",
985 0xe0 : "DEBUG_MIN",
986 0xef : "DEBUG_MAX",
987 0xf0 : "FFS_MIN",
988 0xff : "FFS_MAX",
989 0xf0 : "FFS_PAD",
990 }
991
992 def __init__(self):
993 Image.__init__(self)
994 self.FreeSpace = 0
995
996 self.Sections = sdict()
997 self.Depex = ''
998
999 self.__ID__ = None
1000
1001 def __str__(self):
1002 global gIndention
1003 gIndention += 4
1004 Indention = ' ' * gIndention
1005 FfsInfo = Indention
1006 FfsInfo += "[FFS:%s] offset=%x size=%x guid=%s free_space=%x alignment=%s\n" % \
1007 (Ffs._TypeName[self.Type], self._OFF_, self.Size, self.Guid, self.FreeSpace, self.Alignment)
1008 SectionInfo = '\n'.join([str(self.Sections[Offset]) for Offset in self.Sections])
1009 gIndention -= 4
1010 return FfsInfo + SectionInfo + "\n"
1011
1012 def __len__(self):
1013 return self.Size
1014
1015 def __repr__(self):
1016 return self.__ID__
1017
1018 def _Unpack(self):
1019 Size1, Size2, Size3 = self._SIZE_.unpack_from(self._BUF_, self._OFF_)
1020 Size = Size1 + (Size2 << 8) + (Size3 << 16)
1021 self.empty()
1022 self.extend(self._BUF_[self._OFF_ : self._OFF_ + Size])
1023
1024 # Pad FFS may use the same GUID. We need to avoid it.
1025 if self.Type == 0xf0:
1026 self.__ID__ = str(uuid.uuid1()).upper()
1027 else:
1028 self.__ID__ = self.Guid
1029
1030 # Traverse the SECTION. RAW and PAD do not have sections
1031 if self.Type not in [0xf0, 0x01] and Size > 0 and Size < 0xFFFFFF:
1032 EndOfFfs = Size
1033 SectionStartAddress = self._HEADER_SIZE_
1034 while SectionStartAddress < EndOfFfs:
1035 SectionObj = Section()
1036 SectionObj.frombuffer(self, SectionStartAddress)
1037 #f = open(repr(SectionObj), 'wb')
1038 #SectionObj.Size = 0
1039 #SectionObj.tofile(f)
1040 #f.close()
1041 self.Sections[SectionStartAddress] = SectionObj
1042 SectionStartAddress += len(SectionObj)
1043 SectionStartAddress = (SectionStartAddress + 3) & (~3)
1044
1045 def Pack(self):
1046 pass
1047
1048 def SetFreeSpace(self, Size):
1049 self.FreeSpace = Size
1050
1051 def _GetGuid(self):
1052 return gGuidStringFormat % self.Name
1053
1054 def _SetName(self, Value):
1055 # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
1056 self.SetField(self._NAME_, 0, Value)
1057
1058 def _GetName(self):
1059 # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
1060 return self.GetField(self._NAME_)
1061
1062 def _SetSize(m, Size):
1063 Size1 = Size & 0xFF
1064 Size2 = (Size & 0xFF00) >> 8
1065 Size3 = (Size & 0xFF0000) >> 16
1066 m.SetField(m._SIZE_, 0, Size1, Size2, Size3)
1067
1068 def _GetSize(m):
1069 Size1, Size2, Size3 = m.GetField(m._SIZE_)
1070 return Size1 + (Size2 << 8) + (Size3 << 16)
1071
1072 def _SetType(m, Type):
1073 m.SetField(m._TYPE_, 0, Type)
1074
1075 def _GetType(m):
1076 return m.GetField(m._TYPE_)[0]
1077
1078 def _SetAttributes(self, Value):
1079 self.SetField(m._ATTR_, 0, Value)
1080
1081 def _GetAttributes(self):
1082 return self.GetField(self._ATTR_)[0]
1083
1084 def _GetFixed(self):
1085 if (self.Attributes & self.FFS_ATTRIB_FIXED) != 0:
1086 return True
1087 return False
1088
1089 def _GetCheckSum(self):
1090 if (self.Attributes & self.FFS_ATTRIB_CHECKSUM) != 0:
1091 return True
1092 return False
1093
1094 def _GetAlignment(self):
1095 return (self.Attributes & self.FFS_ATTRIB_DATA_ALIGNMENT) >> 3
1096
1097 def _SetState(self, Value):
1098 self.SetField(m._STATE_, 0, Value)
1099
1100 def _GetState(self):
1101 return self.GetField(m._STATE_)[0]
1102
1103 Name = property(_GetName, _SetName)
1104 Guid = property(_GetGuid)
1105 Type = property(_GetType, _SetType)
1106 Size = property(_GetSize, _SetSize)
1107 Attributes = property(_GetAttributes, _SetAttributes)
1108 Fixed = property(_GetFixed)
1109 Checksum = property(_GetCheckSum)
1110 Alignment = property(_GetAlignment)
1111 State = property(_GetState, _SetState)
1112
1113 ## PeImage() class
1114 #
1115 # A class for PE Image
1116 #
1117 class PeImage:
1118 #
1119 # just extract e_lfanew
1120 #
1121 _DosHeaderFormat = "60x 1I"
1122 #
1123 # Machine
1124 # NumberOfSections
1125 # SizeOfOptionalHeader
1126 #
1127 _FileHeaderFormat = "4x 1H 1H 4x 4x 4x 1H 2x"
1128 #
1129 # Magic
1130 # SizeOfImage
1131 # SizeOfHeaders
1132 # CheckSum
1133 # NumberOfRvaAndSizes
1134 #
1135 _OptionalHeader32Format = "1H 54x 1I 1I 1I 24x 1I"
1136 _OptionalHeader64Format = ""
1137 def __init__(self, Buf, Offset, Size):
1138 self.Offset = Offset
1139 self.Size = Size
1140 self.Machine = 0x014c # IA32
1141 self.NumberOfSections = 0
1142 self.SizeOfImage = 0
1143 self.SizeOfOptionalHeader = 0
1144 self.Checksum = 0
1145 self._PeImageBuf = Buf
1146 self._SectionList = []
1147
1148 self._DosHeader = struct.Struct(PeImage._DosHeaderFormat)
1149 self._FileHeader = struct.Struct(PeImage._FileHeaderFormat)
1150 self._OptionalHeader32 = struct.Struct(PeImage._OptionalHeader32Format)
1151
1152 self.Buffer = None
1153
1154 self._Unpack()
1155
1156 def __str__(self):
1157 pass
1158
1159 def __len__(self):
1160 return self.Size
1161
1162 def _Unpack(self):
1163 # from DOS header, get the offset of PE header
1164 FileHeaderOffset, = self._DosHeader.unpack_from(self._PeImageBuf, self.Offset)
1165 if FileHeaderOffset < struct.calcsize(self._DosHeaderFormat):
1166 EdkLogger.error("PE+", 0, "Invalid offset of IMAGE_FILE_HEADER: %s" % FileHeaderOffset)
1167
1168 # from FILE header, get the optional header size
1169 self.Machine, self.NumberOfSections, self.SizeOfOptionalHeader = \
1170 self._FileHeader.unpack_from(self._PeImageBuf, self.Offset + FileHeaderOffset)
1171
1172 print "Machine=%x NumberOfSections=%x SizeOfOptionalHeader=%x" % (self.Machine, self.NumberOfSections, self.SizeOfOptionalHeader)
1173 # optional header follows the FILE header
1174 OptionalHeaderOffset = FileHeaderOffset + struct.calcsize(self._FileHeaderFormat)
1175 Magic, self.SizeOfImage, SizeOfHeaders, self.Checksum, NumberOfRvaAndSizes = \
1176 self._OptionalHeader32.unpack_from(self._PeImageBuf, self.Offset + OptionalHeaderOffset)
1177 print "Magic=%x SizeOfImage=%x SizeOfHeaders=%x, Checksum=%x, NumberOfRvaAndSizes=%x" % (Magic, self.SizeOfImage, SizeOfHeaders, self.Checksum, NumberOfRvaAndSizes)
1178
1179 PeImageSectionTableOffset = OptionalHeaderOffset + self.SizeOfOptionalHeader
1180 PeSections = PeSectionTable(self._PeImageBuf, self.Offset + PeImageSectionTableOffset, self.NumberOfSections)
1181
1182 print "%x" % PeSections.GetFileAddress(0x3920)
1183
1184 ## PeSectionTable() class
1185 #
1186 # A class for PE Section Table
1187 #
1188 class PeSectionTable:
1189 def __init__(self, Buf, Offset, NumberOfSections):
1190 self._SectionList = []
1191
1192 SectionHeaderOffset = Offset
1193 for TableIndex in range(0, NumberOfSections):
1194 SectionHeader = PeSectionHeader(Buf, SectionHeaderOffset)
1195 self._SectionList.append(SectionHeader)
1196 SectionHeaderOffset += len(SectionHeader)
1197 print SectionHeader
1198
1199 def GetFileAddress(self, Rva):
1200 for PeSection in self._SectionList:
1201 if Rva in PeSection:
1202 return PeSection[Rva]
1203
1204 ## PeSectionHeader() class
1205 #
1206 # A class for PE Section Header
1207 #
1208 class PeSectionHeader:
1209 #
1210 # VirtualAddress
1211 # SizeOfRawData
1212 # PointerToRawData
1213 #
1214 _HeaderFormat = "12x 1I 1I 1I 16x"
1215 _HeaderLength = struct.calcsize(_HeaderFormat)
1216
1217 def __init__(self, Buf, Offset):
1218 self.VirtualAddressStart, self.SizeOfRawData, self.PointerToRawData = \
1219 struct.unpack_from(self._HeaderFormat, Buf, Offset)
1220 self.VirtualAddressEnd = self.VirtualAddressStart + self.SizeOfRawData - 1
1221
1222 def __str__(self):
1223 return "VirtualAddress=%x, SizeOfRawData=%x, PointerToRawData=%x" % (self.VirtualAddressStart, self.SizeOfRawData, self.PointerToRawData)
1224
1225 def __len__(self):
1226 return self._HeaderLength
1227
1228 def __contains__(self, Rva):
1229 return Rva >= self.VirtualAddressStart and Rva <= self.VirtualAddressEnd
1230
1231 def __getitem__(self, Rva):
1232 return Rva - self.VirtualAddressStart + self.PointerToRawData
1233
1234 ## LinkMap() class
1235 #
1236 # A class for Link Map
1237 #
1238 class LinkMap:
1239 _StartFlag = {
1240 "MSFT" : re.compile("Address +Publics by Value +Rva\+Base +Lib:Object"),
1241 "GCC" : re.compile("^\.(text|bss|data|edata)"),
1242 }
1243
1244 _MappingFormat = {
1245 "MSFT" : re.compile("([0-9a-f]+):([0-9a-f]+)\s+_+([0-9A-Za-z]+)\s+([0-9a-f]+)\s+"),
1246 "GCC" : re.compile("^(\.\w)?\s+(0x[0-9a-f]+)\s+_+([0-9A-Za-z]+)"),
1247 }
1248
1249 def __init__(self, MapFile, MapType="MSFT"):
1250 self.File = MapFile
1251 self.MapType = MapType
1252 self._Globals = {} # global:RVA
1253
1254 self._Parse()
1255
1256 def _Parse(self):
1257 MapFile = open(self.File, 'r')
1258 MappingTitle = self._StartFlag[self.MapType]
1259 MappingFormat = self._MappingFormat[self.MapType]
1260 MappingStart = False
1261 try:
1262 for Line in MapFile:
1263 Line = Line.strip()
1264 if not MappingStart:
1265 if MappingTitle.match(Line) is not None:
1266 MappingStart = True
1267 continue
1268 ResultList = MappingFormat.findall(Line)
1269 if len(ResultList) == 0 or len(ResultList[0]) != 4:
1270 continue
1271 self._Globals[ResultList[2]] = int(ResultList[3], 16)
1272 EdkLogger.verbose(ResultList[0])
1273 finally:
1274 MapFile.close()
1275
1276 def __contains__(self, Var):
1277 return Var in self._Globals
1278
1279 def __getitem__(self, Var):
1280 if Var not in self._Globals:
1281 return None
1282 return self._Globals[Var]
1283
1284 ## MultipleFv() class
1285 #
1286 # A class for Multiple FV
1287 #
1288 class MultipleFv(FirmwareVolume):
1289 def __init__(self, FvList):
1290 FirmwareVolume.__init__(self)
1291 self.BasicInfo = []
1292 for FvPath in FvList:
1293 FvName = os.path.splitext(os.path.split(FvPath)[1])[0]
1294 Fd = open(FvPath, 'rb')
1295 Buf = array('B')
1296 try:
1297 Buf.fromfile(Fd, os.path.getsize(FvPath))
1298 except EOFError:
1299 pass
1300
1301 Fv = FirmwareVolume(FvName)
1302 Fv.frombuffer(Buf, 0, len(Buf))
1303
1304 self.BasicInfo.append([Fv.Name, Fv.FileSystemGuid, Fv.Size])
1305 self.FfsDict.append(Fv.FfsDict)
1306
1307 # Version and Copyright
1308 __version_number__ = "0.01"
1309 __version__ = "%prog Version " + __version_number__
1310 __copyright__ = "Copyright (c) 2008, Intel Corporation. All rights reserved."
1311
1312 ## Parse command line options
1313 #
1314 # Using standard Python module optparse to parse command line option of this tool.
1315 #
1316 # @retval Options A optparse.Values object containing the parsed options
1317 # @retval InputFile Path of file to be trimmed
1318 #
1319 def GetOptions():
1320 OptionList = [
1321 make_option("-a", "--arch", dest="Arch",
1322 help="The input file is preprocessed source code, including C or assembly code"),
1323 make_option("-p", "--platform", dest="ActivePlatform",
1324 help="The input file is preprocessed VFR file"),
1325 make_option("-m", "--module", dest="ActiveModule",
1326 help="Convert standard hex format (0xabcd) to MASM format (abcdh)"),
1327 make_option("-f", "--FDF-file", dest="FdfFile",
1328 help="Convert standard hex format (0xabcd) to MASM format (abcdh)"),
1329 make_option("-o", "--output", dest="OutputDirectory",
1330 help="File to store the trimmed content"),
1331 make_option("-t", "--toolchain-tag", dest="ToolChain",
1332 help=""),
1333 make_option("-k", "--msft", dest="MakefileType", action="store_const", const="nmake",
1334 help=""),
1335 make_option("-g", "--gcc", dest="MakefileType", action="store_const", const="gmake",
1336 help=""),
1337 make_option("-v", "--verbose", dest="LogLevel", action="store_const", const=EdkLogger.VERBOSE,
1338 help="Run verbosely"),
1339 make_option("-d", "--debug", dest="LogLevel", type="int",
1340 help="Run with debug information"),
1341 make_option("-q", "--quiet", dest="LogLevel", action="store_const", const=EdkLogger.QUIET,
1342 help="Run quietly"),
1343 make_option("-?", action="help", help="show this help message and exit"),
1344 ]
1345
1346 # use clearer usage to override default usage message
1347 UsageString = "%prog [-a ARCH] [-p PLATFORM] [-m MODULE] [-t TOOLCHAIN_TAG] [-k] [-g] [-v|-d <debug_level>|-q] [-o <output_directory>] [GenC|GenMake]"
1348
1349 Parser = OptionParser(description=__copyright__, version=__version__, option_list=OptionList, usage=UsageString)
1350 Parser.set_defaults(Arch=[])
1351 Parser.set_defaults(ActivePlatform=None)
1352 Parser.set_defaults(ActiveModule=None)
1353 Parser.set_defaults(OutputDirectory="build")
1354 Parser.set_defaults(FdfFile=None)
1355 Parser.set_defaults(ToolChain="MYTOOLS")
1356 if sys.platform == "win32":
1357 Parser.set_defaults(MakefileType="nmake")
1358 else:
1359 Parser.set_defaults(MakefileType="gmake")
1360 Parser.set_defaults(LogLevel=EdkLogger.INFO)
1361
1362 Options, Args = Parser.parse_args()
1363
1364 # error check
1365 if len(Args) == 0:
1366 Options.Target = "genmake"
1367 sys.argv.append("genmake")
1368 elif len(Args) == 1:
1369 Options.Target = Args[0].lower()
1370 if Options.Target not in ["genc", "genmake"]:
1371 EdkLogger.error("AutoGen", OPTION_NOT_SUPPORTED, "Not supported target",
1372 ExtraData="%s\n\n%s" % (Options.Target, Parser.get_usage()))
1373 else:
1374 EdkLogger.error("AutoGen", OPTION_NOT_SUPPORTED, "Too many targets",
1375 ExtraData=Parser.get_usage())
1376
1377 return Options
1378
1379 ## Entrance method
1380 #
1381 # This method mainly dispatch specific methods per the command line options.
1382 # If no error found, return zero value so the caller of this tool can know
1383 # if it's executed successfully or not.
1384 #
1385 # @retval 0 Tool was successful
1386 # @retval 1 Tool failed
1387 #
1388 def Main():
1389 from build import build
1390 try:
1391 Option = GetOptions()
1392 build.main()
1393 except Exception, e:
1394 print e
1395 return 1
1396
1397 return 0
1398
1399 # This acts like the main() function for the script, unless it is 'import'ed into another script.
1400 if __name__ == '__main__':
1401 EdkLogger.Initialize()
1402 # sys.exit(Main())
1403
1404 if len(sys.argv) > 1:
1405 FilePath = sys.argv[1]
1406 if FilePath.lower().endswith(".fv"):
1407 fd = open(FilePath, 'rb')
1408 buf = array('B')
1409 try:
1410 buf.fromfile(fd, os.path.getsize(FilePath))
1411 except EOFError:
1412 pass
1413
1414 fv = FirmwareVolume("FVRECOVERY")
1415 fv.frombuffer(buf, 0, len(buf))
1416 #fv.Dispatch(None)
1417 print fv
1418 elif FilePath.endswith(".efi"):
1419 fd = open(FilePath, 'rb')
1420 buf = array('B')
1421 Size = os.path.getsize(FilePath)
1422
1423 try:
1424 buf.fromfile(fd, Size)
1425 except EOFError:
1426 pass
1427
1428 PeSection = Section(Type=0x10)
1429 PeSection.Data = buf
1430 sf, ext = os.path.splitext(os.path.basename(FilePath))
1431 sf += ".sec"
1432 PeSection.tofile(open(sf, 'wb'))
1433 elif FilePath.endswith(".map"):
1434 mf = LinkMap(FilePath)