297847cdab9167da8c468e178c8572896ccd46a1
[mirror_edk2.git] / BaseTools / Source / Python / Eot / Eot.py
1 ## @file
2 # This file is used to be the main entrance of EOT tool
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 ##
15 # Import Modules
16 #
17 import Common.LongFilePathOs as os, time, glob
18 import Common.EdkLogger as EdkLogger
19 import EotGlobalData
20 from optparse import OptionParser
21 from Common.StringUtils import NormPath
22 from Common import BuildToolError
23 from Common.Misc import GuidStructureStringToGuidString, sdict
24 from InfParserLite import *
25 import c
26 import Database
27 from array import array
28 from Report import Report
29 from Common.BuildVersion import gBUILD_VERSION
30 from Parser import ConvertGuid
31 from Common.LongFilePathSupport import OpenLongFilePath as open
32 import struct
33 import uuid
34 import copy
35 import codecs
36
37 gGuidStringFormat = "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"
38 gPeiAprioriFileNameGuid = '1b45cc0a-156a-428a-af62-49864da0e6e6'
39 gAprioriGuid = 'fc510ee7-ffdc-11d4-bd41-0080c73c8881'
40 gIndention = -4
41
42 class Image(array):
43 _HEADER_ = struct.Struct("")
44 _HEADER_SIZE_ = _HEADER_.size
45
46 def __new__(cls, *args, **kwargs):
47 return array.__new__(cls, 'B')
48
49 def __init__(self, ID=None):
50 if ID is None:
51 self._ID_ = str(uuid.uuid1()).upper()
52 else:
53 self._ID_ = ID
54 self._BUF_ = None
55 self._LEN_ = None
56 self._OFF_ = None
57
58 self._SubImages = sdict() # {offset: Image()}
59
60 array.__init__(self, 'B')
61
62 def __repr__(self):
63 return self._ID_
64
65 def __len__(self):
66 Len = array.__len__(self)
67 for Offset in self._SubImages:
68 Len += len(self._SubImages[Offset])
69 return Len
70
71 def _Unpack(self):
72 self.extend(self._BUF_[self._OFF_ : self._OFF_ + self._LEN_])
73 return len(self)
74
75 def _Pack(self, PadByte=0xFF):
76 raise NotImplementedError
77
78 def frombuffer(self, Buffer, Offset=0, Size=None):
79 self._BUF_ = Buffer
80 self._OFF_ = Offset
81 # we may need the Size information in advance if it's given
82 self._LEN_ = Size
83 self._LEN_ = self._Unpack()
84
85 def empty(self):
86 del self[0:]
87
88 def GetField(self, FieldStruct, Offset=0):
89 return FieldStruct.unpack_from(self, Offset)
90
91 def SetField(self, FieldStruct, Offset, *args):
92 # check if there's enough space
93 Size = FieldStruct.size
94 if Size > len(self):
95 self.extend([0] * (Size - len(self)))
96 FieldStruct.pack_into(self, Offset, *args)
97
98 def _SetData(self, Data):
99 if len(self) < self._HEADER_SIZE_:
100 self.extend([0] * (self._HEADER_SIZE_ - len(self)))
101 else:
102 del self[self._HEADER_SIZE_:]
103 self.extend(Data)
104
105 def _GetData(self):
106 if len(self) > self._HEADER_SIZE_:
107 return self[self._HEADER_SIZE_:]
108 return None
109
110 Data = property(_GetData, _SetData)
111
112 ## CompressedImage() class
113 #
114 # A class for Compressed Image
115 #
116 class CompressedImage(Image):
117 # UncompressedLength = 4-byte
118 # CompressionType = 1-byte
119 _HEADER_ = struct.Struct("1I 1B")
120 _HEADER_SIZE_ = _HEADER_.size
121
122 _ORIG_SIZE_ = struct.Struct("1I")
123 _CMPRS_TYPE_ = struct.Struct("4x 1B")
124
125 def __init__(m, CompressedData=None, CompressionType=None, UncompressedLength=None):
126 Image.__init__(m)
127 if UncompressedLength is not None:
128 m.UncompressedLength = UncompressedLength
129 if CompressionType is not None:
130 m.CompressionType = CompressionType
131 if CompressedData is not None:
132 m.Data = CompressedData
133
134 def __str__(m):
135 global gIndention
136 S = "algorithm=%s uncompressed=%x" % (m.CompressionType, m.UncompressedLength)
137 for Sec in m.Sections:
138 S += '\n' + str(Sec)
139
140 return S
141
142 def _SetOriginalSize(m, Size):
143 m.SetField(m._ORIG_SIZE_, 0, Size)
144
145 def _GetOriginalSize(m):
146 return m.GetField(m._ORIG_SIZE_)[0]
147
148 def _SetCompressionType(m, Type):
149 m.SetField(m._CMPRS_TYPE_, 0, Type)
150
151 def _GetCompressionType(m):
152 return m.GetField(m._CMPRS_TYPE_)[0]
153
154 def _GetSections(m):
155 try:
156 import EfiCompressor
157 TmpData = EfiCompressor.FrameworkDecompress(
158 m[m._HEADER_SIZE_:],
159 len(m) - m._HEADER_SIZE_
160 )
161 DecData = array('B')
162 DecData.fromstring(TmpData)
163 except:
164 import EfiCompressor
165 TmpData = EfiCompressor.UefiDecompress(
166 m[m._HEADER_SIZE_:],
167 len(m) - m._HEADER_SIZE_
168 )
169 DecData = array('B')
170 DecData.fromstring(TmpData)
171
172 SectionList = []
173 Offset = 0
174 while Offset < len(DecData):
175 Sec = Section()
176 try:
177 Sec.frombuffer(DecData, Offset)
178 Offset += Sec.Size
179 # the section is aligned to 4-byte boundary
180 except:
181 break
182 SectionList.append(Sec)
183 return SectionList
184
185 UncompressedLength = property(_GetOriginalSize, _SetOriginalSize)
186 CompressionType = property(_GetCompressionType, _SetCompressionType)
187 Sections = property(_GetSections)
188
189 ## Ui() class
190 #
191 # A class for Ui
192 #
193 class Ui(Image):
194 _HEADER_ = struct.Struct("")
195 _HEADER_SIZE_ = 0
196
197 def __init__(m):
198 Image.__init__(m)
199
200 def __str__(m):
201 return m.String
202
203 def _Unpack(m):
204 # keep header in this Image object
205 m.empty()
206 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
207 return len(m)
208
209 def _GetUiString(m):
210 return codecs.utf_16_decode(m[0:-2].tostring())[0]
211
212 String = property(_GetUiString)
213
214 ## Depex() class
215 #
216 # A class for Depex
217 #
218 class Depex(Image):
219 _HEADER_ = struct.Struct("")
220 _HEADER_SIZE_ = 0
221
222 _GUID_ = struct.Struct("1I2H8B")
223 _OPCODE_ = struct.Struct("1B")
224
225 _OPCODE_STRING_ = {
226 0x00 : "BEFORE",
227 0x01 : "AFTER",
228 0x02 : "PUSH",
229 0x03 : "AND",
230 0x04 : "OR",
231 0x05 : "NOT",
232 0x06 : "TRUE",
233 0x07 : "FALSE",
234 0x08 : "END",
235 0x09 : "SOR"
236 }
237
238 _NEXT_ = {
239 -1 : _OPCODE_, # first one in depex must be an opcdoe
240 0x00 : _GUID_, #"BEFORE",
241 0x01 : _GUID_, #"AFTER",
242 0x02 : _GUID_, #"PUSH",
243 0x03 : _OPCODE_, #"AND",
244 0x04 : _OPCODE_, #"OR",
245 0x05 : _OPCODE_, #"NOT",
246 0x06 : _OPCODE_, #"TRUE",
247 0x07 : _OPCODE_, #"FALSE",
248 0x08 : None, #"END",
249 0x09 : _OPCODE_, #"SOR"
250 }
251
252 def __init__(m):
253 Image.__init__(m)
254 m._ExprList = []
255
256 def __str__(m):
257 global gIndention
258 gIndention += 4
259 Indention = ' ' * gIndention
260 S = '\n'
261 for T in m.Expression:
262 if T in m._OPCODE_STRING_:
263 S += Indention + m._OPCODE_STRING_[T]
264 if T not in [0x00, 0x01, 0x02]:
265 S += '\n'
266 else:
267 S += ' ' + gGuidStringFormat % T + '\n'
268 gIndention -= 4
269 return S
270
271 def _Unpack(m):
272 # keep header in this Image object
273 m.empty()
274 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
275 return len(m)
276
277 def _GetExpression(m):
278 if m._ExprList == []:
279 Offset = 0
280 CurrentData = m._OPCODE_
281 while Offset < len(m):
282 Token = CurrentData.unpack_from(m, Offset)
283 Offset += CurrentData.size
284 if len(Token) == 1:
285 Token = Token[0]
286 if Token in m._NEXT_:
287 CurrentData = m._NEXT_[Token]
288 else:
289 CurrentData = m._GUID_
290 else:
291 CurrentData = m._OPCODE_
292 m._ExprList.append(Token)
293 if CurrentData is None:
294 break
295 return m._ExprList
296
297 Expression = property(_GetExpression)
298
299 ## FirmwareVolume() class
300 #
301 # A class for Firmware Volume
302 #
303 class FirmwareVolume(Image):
304 # Read FvLength, Attributes, HeaderLength, Checksum
305 _HEADER_ = struct.Struct("16x 1I2H8B 1Q 4x 1I 1H 1H")
306 _HEADER_SIZE_ = _HEADER_.size
307
308 _FfsGuid = "8C8CE578-8A3D-4F1C-9935-896185C32DD3"
309
310 _GUID_ = struct.Struct("16x 1I2H8B")
311 _LENGTH_ = struct.Struct("16x 16x 1Q")
312 _SIG_ = struct.Struct("16x 16x 8x 1I")
313 _ATTR_ = struct.Struct("16x 16x 8x 4x 1I")
314 _HLEN_ = struct.Struct("16x 16x 8x 4x 4x 1H")
315 _CHECKSUM_ = struct.Struct("16x 16x 8x 4x 4x 2x 1H")
316
317 def __init__(self, Name=''):
318 Image.__init__(self)
319 self.Name = Name
320 self.FfsDict = sdict()
321 self.OrderedFfsDict = sdict()
322 self.UnDispatchedFfsDict = sdict()
323 self.ProtocolList = sdict()
324
325 def CheckArchProtocol(self):
326 for Item in EotGlobalData.gArchProtocolGuids:
327 if Item.lower() not in EotGlobalData.gProtocolList:
328
329 return False
330
331 return True
332
333 def ParseDepex(self, Depex, Type):
334 List = None
335 if Type == 'Ppi':
336 List = EotGlobalData.gPpiList
337 if Type == 'Protocol':
338 List = EotGlobalData.gProtocolList
339 DepexStack = []
340 DepexList = []
341 DepexString = ''
342 FileDepex = None
343 CouldBeLoaded = True
344 for Index in range(0, len(Depex.Expression)):
345 Item = Depex.Expression[Index]
346 if Item == 0x00:
347 Index = Index + 1
348 Guid = gGuidStringFormat % Depex.Expression[Index]
349 if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
350 return (True, 'BEFORE %s' % Guid, [Guid, 'BEFORE'])
351 elif Item == 0x01:
352 Index = Index + 1
353 Guid = gGuidStringFormat % Depex.Expression[Index]
354 if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
355 return (True, 'AFTER %s' % Guid, [Guid, 'AFTER'])
356 elif Item == 0x02:
357 Index = Index + 1
358 Guid = gGuidStringFormat % Depex.Expression[Index]
359 if Guid.lower() in List:
360 DepexStack.append(True)
361 DepexList.append(Guid)
362 else:
363 DepexStack.append(False)
364 DepexList.append(Guid)
365 continue
366 elif Item == 0x03 or Item == 0x04:
367 DepexStack.append(eval(str(DepexStack.pop()) + ' ' + Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
368 DepexList.append(str(DepexList.pop()) + ' ' + Depex._OPCODE_STRING_[Item].upper() + ' ' + str(DepexList.pop()))
369 elif Item == 0x05:
370 DepexStack.append(eval(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
371 DepexList.append(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexList.pop()))
372 elif Item == 0x06:
373 DepexStack.append(True)
374 DepexList.append('TRUE')
375 DepexString = DepexString + 'TRUE' + ' '
376 elif Item == 0x07:
377 DepexStack.append(False)
378 DepexList.append('False')
379 DepexString = DepexString + 'FALSE' + ' '
380 elif Item == 0x08:
381 if Index != len(Depex.Expression) - 1:
382 CouldBeLoaded = False
383 else:
384 CouldBeLoaded = DepexStack.pop()
385 else:
386 CouldBeLoaded = False
387 if DepexList != []:
388 DepexString = DepexList[0].strip()
389 return (CouldBeLoaded, DepexString, FileDepex)
390
391 def Dispatch(self, Db = None):
392 if Db is None:
393 return False
394 self.UnDispatchedFfsDict = copy.copy(self.FfsDict)
395 # Find PeiCore, DexCore, PeiPriori, DxePriori first
396 FfsSecCoreGuid = None
397 FfsPeiCoreGuid = None
398 FfsDxeCoreGuid = None
399 FfsPeiPrioriGuid = None
400 FfsDxePrioriGuid = None
401 for FfsID in self.UnDispatchedFfsDict:
402 Ffs = self.UnDispatchedFfsDict[FfsID]
403 if Ffs.Type == 0x03:
404 FfsSecCoreGuid = FfsID
405 continue
406 if Ffs.Type == 0x04:
407 FfsPeiCoreGuid = FfsID
408 continue
409 if Ffs.Type == 0x05:
410 FfsDxeCoreGuid = FfsID
411 continue
412 if Ffs.Guid.lower() == gPeiAprioriFileNameGuid:
413 FfsPeiPrioriGuid = FfsID
414 continue
415 if Ffs.Guid.lower() == gAprioriGuid:
416 FfsDxePrioriGuid = FfsID
417 continue
418
419 # Parse SEC_CORE first
420 if FfsSecCoreGuid is not None:
421 self.OrderedFfsDict[FfsSecCoreGuid] = self.UnDispatchedFfsDict.pop(FfsSecCoreGuid)
422 self.LoadPpi(Db, FfsSecCoreGuid)
423
424 # Parse PEI first
425 if FfsPeiCoreGuid is not None:
426 self.OrderedFfsDict[FfsPeiCoreGuid] = self.UnDispatchedFfsDict.pop(FfsPeiCoreGuid)
427 self.LoadPpi(Db, FfsPeiCoreGuid)
428 if FfsPeiPrioriGuid is not None:
429 # Load PEIM described in priori file
430 FfsPeiPriori = self.UnDispatchedFfsDict.pop(FfsPeiPrioriGuid)
431 if len(FfsPeiPriori.Sections) == 1:
432 Section = FfsPeiPriori.Sections.popitem()[1]
433 if Section.Type == 0x19:
434 GuidStruct = struct.Struct('1I2H8B')
435 Start = 4
436 while len(Section) > Start:
437 Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
438 GuidString = gGuidStringFormat % Guid
439 Start = Start + 16
440 if GuidString in self.UnDispatchedFfsDict:
441 self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
442 self.LoadPpi(Db, GuidString)
443
444 self.DisPatchPei(Db)
445
446 # Parse DXE then
447 if FfsDxeCoreGuid is not None:
448 self.OrderedFfsDict[FfsDxeCoreGuid] = self.UnDispatchedFfsDict.pop(FfsDxeCoreGuid)
449 self.LoadProtocol(Db, FfsDxeCoreGuid)
450 if FfsDxePrioriGuid is not None:
451 # Load PEIM described in priori file
452 FfsDxePriori = self.UnDispatchedFfsDict.pop(FfsDxePrioriGuid)
453 if len(FfsDxePriori.Sections) == 1:
454 Section = FfsDxePriori.Sections.popitem()[1]
455 if Section.Type == 0x19:
456 GuidStruct = struct.Struct('1I2H8B')
457 Start = 4
458 while len(Section) > Start:
459 Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
460 GuidString = gGuidStringFormat % Guid
461 Start = Start + 16
462 if GuidString in self.UnDispatchedFfsDict:
463 self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
464 self.LoadProtocol(Db, GuidString)
465
466 self.DisPatchDxe(Db)
467
468 def LoadProtocol(self, Db, ModuleGuid):
469 SqlCommand = """select GuidValue from Report
470 where SourceFileFullPath in
471 (select Value1 from Inf where BelongsToFile =
472 (select BelongsToFile from Inf
473 where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
474 and Model = %s)
475 and ItemType = 'Protocol' and ItemMode = 'Produced'""" \
476 % (ModuleGuid, 5001, 3007)
477 RecordSet = Db.TblReport.Exec(SqlCommand)
478 for Record in RecordSet:
479 SqlCommand = """select Value2 from Inf where BelongsToFile =
480 (select DISTINCT BelongsToFile from Inf
481 where Value1 =
482 (select SourceFileFullPath from Report
483 where GuidValue like '%s' and ItemMode = 'Callback'))
484 and Value1 = 'FILE_GUID'""" % Record[0]
485 CallBackSet = Db.TblReport.Exec(SqlCommand)
486 if CallBackSet != []:
487 EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
488 else:
489 EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
490
491 def LoadPpi(self, Db, ModuleGuid):
492 SqlCommand = """select GuidValue from Report
493 where SourceFileFullPath in
494 (select Value1 from Inf where BelongsToFile =
495 (select BelongsToFile from Inf
496 where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
497 and Model = %s)
498 and ItemType = 'Ppi' and ItemMode = 'Produced'""" \
499 % (ModuleGuid, 5001, 3007)
500 RecordSet = Db.TblReport.Exec(SqlCommand)
501 for Record in RecordSet:
502 EotGlobalData.gPpiList[Record[0].lower()] = ModuleGuid
503
504 def DisPatchDxe(self, Db):
505 IsInstalled = False
506 ScheduleList = sdict()
507 for FfsID in self.UnDispatchedFfsDict:
508 CouldBeLoaded = False
509 DepexString = ''
510 FileDepex = None
511 Ffs = self.UnDispatchedFfsDict[FfsID]
512 if Ffs.Type == 0x07:
513 # Get Depex
514 IsFoundDepex = False
515 for Section in Ffs.Sections.values():
516 # Find Depex
517 if Section.Type == 0x13:
518 IsFoundDepex = True
519 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Protocol')
520 break
521 if Section.Type == 0x01:
522 CompressSections = Section._SubImages[4]
523 for CompressSection in CompressSections.Sections:
524 if CompressSection.Type == 0x13:
525 IsFoundDepex = True
526 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Protocol')
527 break
528 if CompressSection.Type == 0x02:
529 NewSections = CompressSection._SubImages[4]
530 for NewSection in NewSections.Sections:
531 if NewSection.Type == 0x13:
532 IsFoundDepex = True
533 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Protocol')
534 break
535
536 # Not find Depex
537 if not IsFoundDepex:
538 CouldBeLoaded = self.CheckArchProtocol()
539 DepexString = ''
540 FileDepex = None
541
542 # Append New Ffs
543 if CouldBeLoaded:
544 IsInstalled = True
545 NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
546 NewFfs.Depex = DepexString
547 if FileDepex is not None:
548 ScheduleList.insert(FileDepex[1], FfsID, NewFfs, FileDepex[0])
549 else:
550 ScheduleList[FfsID] = NewFfs
551 else:
552 self.UnDispatchedFfsDict[FfsID].Depex = DepexString
553
554 for FfsID in ScheduleList:
555 NewFfs = ScheduleList.pop(FfsID)
556 FfsName = 'UnKnown'
557 self.OrderedFfsDict[FfsID] = NewFfs
558 self.LoadProtocol(Db, FfsID)
559
560 SqlCommand = """select Value2 from Inf
561 where BelongsToFile = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)
562 and Model = %s and Value1='BASE_NAME'""" % (FfsID, 5001, 5001)
563 RecordSet = Db.TblReport.Exec(SqlCommand)
564 if RecordSet != []:
565 FfsName = RecordSet[0][0]
566
567 if IsInstalled:
568 self.DisPatchDxe(Db)
569
570 def DisPatchPei(self, Db):
571 IsInstalled = False
572 for FfsID in self.UnDispatchedFfsDict:
573 CouldBeLoaded = True
574 DepexString = ''
575 FileDepex = None
576 Ffs = self.UnDispatchedFfsDict[FfsID]
577 if Ffs.Type == 0x06 or Ffs.Type == 0x08:
578 # Get Depex
579 for Section in Ffs.Sections.values():
580 if Section.Type == 0x1B:
581 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Ppi')
582 break
583
584 if Section.Type == 0x01:
585 CompressSections = Section._SubImages[4]
586 for CompressSection in CompressSections.Sections:
587 if CompressSection.Type == 0x1B:
588 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Ppi')
589 break
590 if CompressSection.Type == 0x02:
591 NewSections = CompressSection._SubImages[4]
592 for NewSection in NewSections.Sections:
593 if NewSection.Type == 0x1B:
594 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Ppi')
595 break
596
597 # Append New Ffs
598 if CouldBeLoaded:
599 IsInstalled = True
600 NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
601 NewFfs.Depex = DepexString
602 self.OrderedFfsDict[FfsID] = NewFfs
603 self.LoadPpi(Db, FfsID)
604 else:
605 self.UnDispatchedFfsDict[FfsID].Depex = DepexString
606
607 if IsInstalled:
608 self.DisPatchPei(Db)
609
610
611 def __str__(self):
612 global gIndention
613 gIndention += 4
614 FvInfo = '\n' + ' ' * gIndention
615 FvInfo += "[FV:%s] file_system=%s size=%x checksum=%s\n" % (self.Name, self.FileSystemGuid, self.Size, self.Checksum)
616 FfsInfo = "\n".join([str(self.FfsDict[FfsId]) for FfsId in self.FfsDict])
617 gIndention -= 4
618 return FvInfo + FfsInfo
619
620 def _Unpack(self):
621 Size = self._LENGTH_.unpack_from(self._BUF_, self._OFF_)[0]
622 self.empty()
623 self.extend(self._BUF_[self._OFF_:self._OFF_+Size])
624
625 # traverse the FFS
626 EndOfFv = Size
627 FfsStartAddress = self.HeaderSize
628 LastFfsObj = None
629 while FfsStartAddress < EndOfFv:
630 FfsObj = Ffs()
631 FfsObj.frombuffer(self, FfsStartAddress)
632 FfsId = repr(FfsObj)
633 if ((self.Attributes & 0x00000800) != 0 and len(FfsObj) == 0xFFFFFF) \
634 or ((self.Attributes & 0x00000800) == 0 and len(FfsObj) == 0):
635 if LastFfsObj is not None:
636 LastFfsObj.FreeSpace = EndOfFv - LastFfsObj._OFF_ - len(LastFfsObj)
637 else:
638 if FfsId in self.FfsDict:
639 EdkLogger.error("FV", 0, "Duplicate GUID in FFS",
640 ExtraData="\t%s @ %s\n\t%s @ %s" \
641 % (FfsObj.Guid, FfsObj.Offset,
642 self.FfsDict[FfsId].Guid, self.FfsDict[FfsId].Offset))
643 self.FfsDict[FfsId] = FfsObj
644 if LastFfsObj is not None:
645 LastFfsObj.FreeSpace = FfsStartAddress - LastFfsObj._OFF_ - len(LastFfsObj)
646
647 FfsStartAddress += len(FfsObj)
648 #
649 # align to next 8-byte aligned address: A = (A + 8 - 1) & (~(8 - 1))
650 # The next FFS must be at the latest next 8-byte aligned address
651 #
652 FfsStartAddress = (FfsStartAddress + 7) & (~7)
653 LastFfsObj = FfsObj
654
655 def _GetAttributes(self):
656 return self.GetField(self._ATTR_, 0)[0]
657
658 def _GetSize(self):
659 return self.GetField(self._LENGTH_, 0)[0]
660
661 def _GetChecksum(self):
662 return self.GetField(self._CHECKSUM_, 0)[0]
663
664 def _GetHeaderLength(self):
665 return self.GetField(self._HLEN_, 0)[0]
666
667 def _GetFileSystemGuid(self):
668 return gGuidStringFormat % self.GetField(self._GUID_, 0)
669
670 Attributes = property(_GetAttributes)
671 Size = property(_GetSize)
672 Checksum = property(_GetChecksum)
673 HeaderSize = property(_GetHeaderLength)
674 FileSystemGuid = property(_GetFileSystemGuid)
675
676 ## GuidDefinedImage() class
677 #
678 # A class for GUID Defined Image
679 #
680 class GuidDefinedImage(Image):
681 _HEADER_ = struct.Struct("1I2H8B 1H 1H")
682 _HEADER_SIZE_ = _HEADER_.size
683
684 _GUID_ = struct.Struct("1I2H8B")
685 _DATA_OFFSET_ = struct.Struct("16x 1H")
686 _ATTR_ = struct.Struct("18x 1H")
687
688 CRC32_GUID = "FC1BCDB0-7D31-49AA-936A-A4600D9DD083"
689 TIANO_COMPRESS_GUID = 'A31280AD-481E-41B6-95E8-127F4C984779'
690 LZMA_COMPRESS_GUID = 'EE4E5898-3914-4259-9D6E-DC7BD79403CF'
691
692 def __init__(m, SectionDefinitionGuid=None, DataOffset=None, Attributes=None, Data=None):
693 Image.__init__(m)
694 if SectionDefinitionGuid is not None:
695 m.SectionDefinitionGuid = SectionDefinitionGuid
696 if DataOffset is not None:
697 m.DataOffset = DataOffset
698 if Attributes is not None:
699 m.Attributes = Attributes
700 if Data is not None:
701 m.Data = Data
702
703 def __str__(m):
704 S = "guid=%s" % (gGuidStringFormat % m.SectionDefinitionGuid)
705 for Sec in m.Sections:
706 S += "\n" + str(Sec)
707 return S
708
709 def _Unpack(m):
710 # keep header in this Image object
711 m.empty()
712 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])
713 return len(m)
714
715 def _SetAttribute(m, Attribute):
716 m.SetField(m._ATTR_, 0, Attribute)
717
718 def _GetAttribute(m):
719 return m.GetField(m._ATTR_)[0]
720
721 def _SetGuid(m, Guid):
722 m.SetField(m._GUID_, 0, Guid)
723
724 def _GetGuid(m):
725 return m.GetField(m._GUID_)
726
727 def _SetDataOffset(m, Offset):
728 m.SetField(m._DATA_OFFSET_, 0, Offset)
729
730 def _GetDataOffset(m):
731 return m.GetField(m._DATA_OFFSET_)[0]
732
733 def _GetSections(m):
734 SectionList = []
735 Guid = gGuidStringFormat % m.SectionDefinitionGuid
736 if Guid == m.CRC32_GUID:
737 # skip the CRC32 value, we don't do CRC32 verification here
738 Offset = m.DataOffset - 4
739 while Offset < len(m):
740 Sec = Section()
741 try:
742 Sec.frombuffer(m, Offset)
743 Offset += Sec.Size
744 # the section is aligned to 4-byte boundary
745 Offset = (Offset + 3) & (~3)
746 except:
747 break
748 SectionList.append(Sec)
749 elif Guid == m.TIANO_COMPRESS_GUID:
750 try:
751 import EfiCompressor
752 # skip the header
753 Offset = m.DataOffset - 4
754 TmpData = EfiCompressor.FrameworkDecompress(m[Offset:], len(m)-Offset)
755 DecData = array('B')
756 DecData.fromstring(TmpData)
757 Offset = 0
758 while Offset < len(DecData):
759 Sec = Section()
760 try:
761 Sec.frombuffer(DecData, Offset)
762 Offset += Sec.Size
763 # the section is aligned to 4-byte boundary
764 Offset = (Offset + 3) & (~3)
765 except:
766 break
767 SectionList.append(Sec)
768 except:
769 pass
770 elif Guid == m.LZMA_COMPRESS_GUID:
771 try:
772 import LzmaCompressor
773 # skip the header
774 Offset = m.DataOffset - 4
775 TmpData = LzmaCompressor.LzmaDecompress(m[Offset:], len(m)-Offset)
776 DecData = array('B')
777 DecData.fromstring(TmpData)
778 Offset = 0
779 while Offset < len(DecData):
780 Sec = Section()
781 try:
782 Sec.frombuffer(DecData, Offset)
783 Offset += Sec.Size
784 # the section is aligned to 4-byte boundary
785 Offset = (Offset + 3) & (~3)
786 except:
787 break
788 SectionList.append(Sec)
789 except:
790 pass
791
792 return SectionList
793
794 Attributes = property(_GetAttribute, _SetAttribute)
795 SectionDefinitionGuid = property(_GetGuid, _SetGuid)
796 DataOffset = property(_GetDataOffset, _SetDataOffset)
797 Sections = property(_GetSections)
798
799 ## Section() class
800 #
801 # A class for Section
802 #
803 class Section(Image):
804 _TypeName = {
805 0x00 : "<unknown>",
806 0x01 : "COMPRESSION",
807 0x02 : "GUID_DEFINED",
808 0x10 : "PE32",
809 0x11 : "PIC",
810 0x12 : "TE",
811 0x13 : "DXE_DEPEX",
812 0x14 : "VERSION",
813 0x15 : "USER_INTERFACE",
814 0x16 : "COMPATIBILITY16",
815 0x17 : "FIRMWARE_VOLUME_IMAGE",
816 0x18 : "FREEFORM_SUBTYPE_GUID",
817 0x19 : "RAW",
818 0x1B : "PEI_DEPEX"
819 }
820
821 _SectionSubImages = {
822 0x01 : CompressedImage,
823 0x02 : GuidDefinedImage,
824 0x17 : FirmwareVolume,
825 0x13 : Depex,
826 0x1B : Depex,
827 0x15 : Ui
828 }
829
830 # Size = 3-byte
831 # Type = 1-byte
832 _HEADER_ = struct.Struct("3B 1B")
833 _HEADER_SIZE_ = _HEADER_.size
834
835 # SubTypeGuid
836 # _FREE_FORM_SUBTYPE_GUID_HEADER_ = struct.Struct("1I2H8B")
837
838 _SIZE_ = struct.Struct("3B")
839 _TYPE_ = struct.Struct("3x 1B")
840
841 def __init__(m, Type=None, Size=None):
842 Image.__init__(m)
843 m._Alignment = 1
844 if Type is not None:
845 m.Type = Type
846 if Size is not None:
847 m.Size = Size
848
849 def __str__(m):
850 global gIndention
851 gIndention += 4
852 SectionInfo = ' ' * gIndention
853 if m.Type in m._TypeName:
854 SectionInfo += "[SECTION:%s] offset=%x size=%x" % (m._TypeName[m.Type], m._OFF_, m.Size)
855 else:
856 SectionInfo += "[SECTION:%x<unknown>] offset=%x size=%x " % (m.Type, m._OFF_, m.Size)
857 for Offset in m._SubImages:
858 SectionInfo += ", " + str(m._SubImages[Offset])
859 gIndention -= 4
860 return SectionInfo
861
862 def _Unpack(m):
863 m.empty()
864 Type, = m._TYPE_.unpack_from(m._BUF_, m._OFF_)
865 Size1, Size2, Size3 = m._SIZE_.unpack_from(m._BUF_, m._OFF_)
866 Size = Size1 + (Size2 << 8) + (Size3 << 16)
867
868 if Type not in m._SectionSubImages:
869 # no need to extract sub-image, keep all in this Image object
870 m.extend(m._BUF_[m._OFF_ : m._OFF_ + Size])
871 else:
872 # keep header in this Image object
873 m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._HEADER_SIZE_])
874 #
875 # use new Image object to represent payload, which may be another kind
876 # of image such as PE32
877 #
878 PayloadOffset = m._HEADER_SIZE_
879 PayloadLen = m.Size - m._HEADER_SIZE_
880 Payload = m._SectionSubImages[m.Type]()
881 Payload.frombuffer(m._BUF_, m._OFF_ + m._HEADER_SIZE_, PayloadLen)
882 m._SubImages[PayloadOffset] = Payload
883
884 return Size
885
886 def _SetSize(m, Size):
887 Size1 = Size & 0xFF
888 Size2 = (Size & 0xFF00) >> 8
889 Size3 = (Size & 0xFF0000) >> 16
890 m.SetField(m._SIZE_, 0, Size1, Size2, Size3)
891
892 def _GetSize(m):
893 Size1, Size2, Size3 = m.GetField(m._SIZE_)
894 return Size1 + (Size2 << 8) + (Size3 << 16)
895
896 def _SetType(m, Type):
897 m.SetField(m._TYPE_, 0, Type)
898
899 def _GetType(m):
900 return m.GetField(m._TYPE_)[0]
901
902 def _GetAlignment(m):
903 return m._Alignment
904
905 def _SetAlignment(m, Alignment):
906 m._Alignment = Alignment
907 AlignmentMask = Alignment - 1
908 # section alignment is actually for payload, so we need to add header size
909 PayloadOffset = m._OFF_ + m._HEADER_SIZE_
910 if (PayloadOffset & (~AlignmentMask)) == 0:
911 return
912 NewOffset = (PayloadOffset + AlignmentMask) & (~AlignmentMask)
913 while (NewOffset - PayloadOffset) < m._HEADER_SIZE_:
914 NewOffset += m._Alignment
915
916 def tofile(m, f):
917 m.Size = len(m)
918 Image.tofile(m, f)
919 for Offset in m._SubImages:
920 m._SubImages[Offset].tofile(f)
921
922 Type = property(_GetType, _SetType)
923 Size = property(_GetSize, _SetSize)
924 Alignment = property(_GetAlignment, _SetAlignment)
925
926 ## Ffs() class
927 #
928 # A class for Ffs Section
929 #
930 class Ffs(Image):
931 _FfsFormat = "24B%(payload_size)sB"
932 # skip IntegrityCheck
933 _HEADER_ = struct.Struct("1I2H8B 2x 1B 1B 3B 1B")
934 _HEADER_SIZE_ = _HEADER_.size
935
936 _NAME_ = struct.Struct("1I2H8B")
937 _INT_CHECK_ = struct.Struct("16x 1H")
938 _TYPE_ = struct.Struct("18x 1B")
939 _ATTR_ = struct.Struct("19x 1B")
940 _SIZE_ = struct.Struct("20x 3B")
941 _STATE_ = struct.Struct("23x 1B")
942
943 VTF_GUID = "1BA0062E-C779-4582-8566-336AE8F78F09"
944
945 FFS_ATTRIB_FIXED = 0x04
946 FFS_ATTRIB_DATA_ALIGNMENT = 0x38
947 FFS_ATTRIB_CHECKSUM = 0x40
948
949 _TypeName = {
950 0x00 : "<unknown>",
951 0x01 : "RAW",
952 0x02 : "FREEFORM",
953 0x03 : "SECURITY_CORE",
954 0x04 : "PEI_CORE",
955 0x05 : "DXE_CORE",
956 0x06 : "PEIM",
957 0x07 : "DRIVER",
958 0x08 : "COMBINED_PEIM_DRIVER",
959 0x09 : "APPLICATION",
960 0x0A : "SMM",
961 0x0B : "FIRMWARE_VOLUME_IMAGE",
962 0x0C : "COMBINED_SMM_DXE",
963 0x0D : "SMM_CORE",
964 0x0E : "MM_STANDALONE",
965 0x0F : "MM_CORE_STANDALONE",
966 0xc0 : "OEM_MIN",
967 0xdf : "OEM_MAX",
968 0xe0 : "DEBUG_MIN",
969 0xef : "DEBUG_MAX",
970 0xf0 : "FFS_MIN",
971 0xff : "FFS_MAX",
972 0xf0 : "FFS_PAD",
973 }
974
975 def __init__(self):
976 Image.__init__(self)
977 self.FreeSpace = 0
978
979 self.Sections = sdict()
980 self.Depex = ''
981
982 self.__ID__ = None
983
984 def __str__(self):
985 global gIndention
986 gIndention += 4
987 Indention = ' ' * gIndention
988 FfsInfo = Indention
989 FfsInfo += "[FFS:%s] offset=%x size=%x guid=%s free_space=%x alignment=%s\n" % \
990 (Ffs._TypeName[self.Type], self._OFF_, self.Size, self.Guid, self.FreeSpace, self.Alignment)
991 SectionInfo = '\n'.join([str(self.Sections[Offset]) for Offset in self.Sections])
992 gIndention -= 4
993 return FfsInfo + SectionInfo + "\n"
994
995 def __len__(self):
996 return self.Size
997
998 def __repr__(self):
999 return self.__ID__
1000
1001 def _Unpack(self):
1002 Size1, Size2, Size3 = self._SIZE_.unpack_from(self._BUF_, self._OFF_)
1003 Size = Size1 + (Size2 << 8) + (Size3 << 16)
1004 self.empty()
1005 self.extend(self._BUF_[self._OFF_ : self._OFF_ + Size])
1006
1007 # Pad FFS may use the same GUID. We need to avoid it.
1008 if self.Type == 0xf0:
1009 self.__ID__ = str(uuid.uuid1()).upper()
1010 else:
1011 self.__ID__ = self.Guid
1012
1013 # Traverse the SECTION. RAW and PAD do not have sections
1014 if self.Type not in [0xf0, 0x01] and Size > 0 and Size < 0xFFFFFF:
1015 EndOfFfs = Size
1016 SectionStartAddress = self._HEADER_SIZE_
1017 while SectionStartAddress < EndOfFfs:
1018 SectionObj = Section()
1019 SectionObj.frombuffer(self, SectionStartAddress)
1020 #f = open(repr(SectionObj), 'wb')
1021 #SectionObj.Size = 0
1022 #SectionObj.tofile(f)
1023 #f.close()
1024 self.Sections[SectionStartAddress] = SectionObj
1025 SectionStartAddress += len(SectionObj)
1026 SectionStartAddress = (SectionStartAddress + 3) & (~3)
1027
1028 def Pack(self):
1029 pass
1030
1031 def SetFreeSpace(self, Size):
1032 self.FreeSpace = Size
1033
1034 def _GetGuid(self):
1035 return gGuidStringFormat % self.Name
1036
1037 def _SetName(self, Value):
1038 # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
1039 self.SetField(self._NAME_, 0, Value)
1040
1041 def _GetName(self):
1042 # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
1043 return self.GetField(self._NAME_)
1044
1045 def _SetSize(m, Size):
1046 Size1 = Size & 0xFF
1047 Size2 = (Size & 0xFF00) >> 8
1048 Size3 = (Size & 0xFF0000) >> 16
1049 m.SetField(m._SIZE_, 0, Size1, Size2, Size3)
1050
1051 def _GetSize(m):
1052 Size1, Size2, Size3 = m.GetField(m._SIZE_)
1053 return Size1 + (Size2 << 8) + (Size3 << 16)
1054
1055 def _SetType(m, Type):
1056 m.SetField(m._TYPE_, 0, Type)
1057
1058 def _GetType(m):
1059 return m.GetField(m._TYPE_)[0]
1060
1061 def _SetAttributes(self, Value):
1062 self.SetField(m._ATTR_, 0, Value)
1063
1064 def _GetAttributes(self):
1065 return self.GetField(self._ATTR_)[0]
1066
1067 def _GetFixed(self):
1068 if (self.Attributes & self.FFS_ATTRIB_FIXED) != 0:
1069 return True
1070 return False
1071
1072 def _GetCheckSum(self):
1073 if (self.Attributes & self.FFS_ATTRIB_CHECKSUM) != 0:
1074 return True
1075 return False
1076
1077 def _GetAlignment(self):
1078 return (self.Attributes & self.FFS_ATTRIB_DATA_ALIGNMENT) >> 3
1079
1080 def _SetState(self, Value):
1081 self.SetField(m._STATE_, 0, Value)
1082
1083 def _GetState(self):
1084 return self.GetField(m._STATE_)[0]
1085
1086 Name = property(_GetName, _SetName)
1087 Guid = property(_GetGuid)
1088 Type = property(_GetType, _SetType)
1089 Size = property(_GetSize, _SetSize)
1090 Attributes = property(_GetAttributes, _SetAttributes)
1091 Fixed = property(_GetFixed)
1092 Checksum = property(_GetCheckSum)
1093 Alignment = property(_GetAlignment)
1094 State = property(_GetState, _SetState)
1095
1096 ## FirmwareVolume() class
1097 #
1098 # A class for Firmware Volume
1099 #
1100 class FirmwareVolume(Image):
1101 # Read FvLength, Attributes, HeaderLength, Checksum
1102 _HEADER_ = struct.Struct("16x 1I2H8B 1Q 4x 1I 1H 1H")
1103 _HEADER_SIZE_ = _HEADER_.size
1104
1105 _FfsGuid = "8C8CE578-8A3D-4F1C-9935-896185C32DD3"
1106
1107 _GUID_ = struct.Struct("16x 1I2H8B")
1108 _LENGTH_ = struct.Struct("16x 16x 1Q")
1109 _SIG_ = struct.Struct("16x 16x 8x 1I")
1110 _ATTR_ = struct.Struct("16x 16x 8x 4x 1I")
1111 _HLEN_ = struct.Struct("16x 16x 8x 4x 4x 1H")
1112 _CHECKSUM_ = struct.Struct("16x 16x 8x 4x 4x 2x 1H")
1113
1114 def __init__(self, Name=''):
1115 Image.__init__(self)
1116 self.Name = Name
1117 self.FfsDict = sdict()
1118 self.OrderedFfsDict = sdict()
1119 self.UnDispatchedFfsDict = sdict()
1120 self.ProtocolList = sdict()
1121
1122 def CheckArchProtocol(self):
1123 for Item in EotGlobalData.gArchProtocolGuids:
1124 if Item.lower() not in EotGlobalData.gProtocolList:
1125
1126 return False
1127
1128 return True
1129
1130 def ParseDepex(self, Depex, Type):
1131 List = None
1132 if Type == 'Ppi':
1133 List = EotGlobalData.gPpiList
1134 if Type == 'Protocol':
1135 List = EotGlobalData.gProtocolList
1136 DepexStack = []
1137 DepexList = []
1138 DepexString = ''
1139 FileDepex = None
1140 CouldBeLoaded = True
1141 for Index in range(0, len(Depex.Expression)):
1142 Item = Depex.Expression[Index]
1143 if Item == 0x00:
1144 Index = Index + 1
1145 Guid = gGuidStringFormat % Depex.Expression[Index]
1146 if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
1147 return (True, 'BEFORE %s' % Guid, [Guid, 'BEFORE'])
1148 elif Item == 0x01:
1149 Index = Index + 1
1150 Guid = gGuidStringFormat % Depex.Expression[Index]
1151 if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:
1152 return (True, 'AFTER %s' % Guid, [Guid, 'AFTER'])
1153 elif Item == 0x02:
1154 Index = Index + 1
1155 Guid = gGuidStringFormat % Depex.Expression[Index]
1156 if Guid.lower() in List:
1157 DepexStack.append(True)
1158 DepexList.append(Guid)
1159 else:
1160 DepexStack.append(False)
1161 DepexList.append(Guid)
1162 continue
1163 elif Item == 0x03 or Item == 0x04:
1164 DepexStack.append(eval(str(DepexStack.pop()) + ' ' + Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
1165 DepexList.append(str(DepexList.pop()) + ' ' + Depex._OPCODE_STRING_[Item].upper() + ' ' + str(DepexList.pop()))
1166 elif Item == 0x05:
1167 DepexStack.append(eval(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))
1168 DepexList.append(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexList.pop()))
1169 elif Item == 0x06:
1170 DepexStack.append(True)
1171 DepexList.append('TRUE')
1172 DepexString = DepexString + 'TRUE' + ' '
1173 elif Item == 0x07:
1174 DepexStack.append(False)
1175 DepexList.append('False')
1176 DepexString = DepexString + 'FALSE' + ' '
1177 elif Item == 0x08:
1178 if Index != len(Depex.Expression) - 1:
1179 CouldBeLoaded = False
1180 else:
1181 CouldBeLoaded = DepexStack.pop()
1182 else:
1183 CouldBeLoaded = False
1184 if DepexList != []:
1185 DepexString = DepexList[0].strip()
1186 return (CouldBeLoaded, DepexString, FileDepex)
1187
1188 def Dispatch(self, Db = None):
1189 if Db is None:
1190 return False
1191 self.UnDispatchedFfsDict = copy.copy(self.FfsDict)
1192 # Find PeiCore, DexCore, PeiPriori, DxePriori first
1193 FfsSecCoreGuid = None
1194 FfsPeiCoreGuid = None
1195 FfsDxeCoreGuid = None
1196 FfsPeiPrioriGuid = None
1197 FfsDxePrioriGuid = None
1198 for FfsID in self.UnDispatchedFfsDict:
1199 Ffs = self.UnDispatchedFfsDict[FfsID]
1200 if Ffs.Type == 0x03:
1201 FfsSecCoreGuid = FfsID
1202 continue
1203 if Ffs.Type == 0x04:
1204 FfsPeiCoreGuid = FfsID
1205 continue
1206 if Ffs.Type == 0x05:
1207 FfsDxeCoreGuid = FfsID
1208 continue
1209 if Ffs.Guid.lower() == gPeiAprioriFileNameGuid:
1210 FfsPeiPrioriGuid = FfsID
1211 continue
1212 if Ffs.Guid.lower() == gAprioriGuid:
1213 FfsDxePrioriGuid = FfsID
1214 continue
1215
1216 # Parse SEC_CORE first
1217 if FfsSecCoreGuid is not None:
1218 self.OrderedFfsDict[FfsSecCoreGuid] = self.UnDispatchedFfsDict.pop(FfsSecCoreGuid)
1219 self.LoadPpi(Db, FfsSecCoreGuid)
1220
1221 # Parse PEI first
1222 if FfsPeiCoreGuid is not None:
1223 self.OrderedFfsDict[FfsPeiCoreGuid] = self.UnDispatchedFfsDict.pop(FfsPeiCoreGuid)
1224 self.LoadPpi(Db, FfsPeiCoreGuid)
1225 if FfsPeiPrioriGuid is not None:
1226 # Load PEIM described in priori file
1227 FfsPeiPriori = self.UnDispatchedFfsDict.pop(FfsPeiPrioriGuid)
1228 if len(FfsPeiPriori.Sections) == 1:
1229 Section = FfsPeiPriori.Sections.popitem()[1]
1230 if Section.Type == 0x19:
1231 GuidStruct = struct.Struct('1I2H8B')
1232 Start = 4
1233 while len(Section) > Start:
1234 Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
1235 GuidString = gGuidStringFormat % Guid
1236 Start = Start + 16
1237 if GuidString in self.UnDispatchedFfsDict:
1238 self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
1239 self.LoadPpi(Db, GuidString)
1240
1241 self.DisPatchPei(Db)
1242
1243 # Parse DXE then
1244 if FfsDxeCoreGuid is not None:
1245 self.OrderedFfsDict[FfsDxeCoreGuid] = self.UnDispatchedFfsDict.pop(FfsDxeCoreGuid)
1246 self.LoadProtocol(Db, FfsDxeCoreGuid)
1247 if FfsDxePrioriGuid is not None:
1248 # Load PEIM described in priori file
1249 FfsDxePriori = self.UnDispatchedFfsDict.pop(FfsDxePrioriGuid)
1250 if len(FfsDxePriori.Sections) == 1:
1251 Section = FfsDxePriori.Sections.popitem()[1]
1252 if Section.Type == 0x19:
1253 GuidStruct = struct.Struct('1I2H8B')
1254 Start = 4
1255 while len(Section) > Start:
1256 Guid = GuidStruct.unpack_from(Section[Start : Start + 16])
1257 GuidString = gGuidStringFormat % Guid
1258 Start = Start + 16
1259 if GuidString in self.UnDispatchedFfsDict:
1260 self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)
1261 self.LoadProtocol(Db, GuidString)
1262
1263 self.DisPatchDxe(Db)
1264
1265 def LoadProtocol(self, Db, ModuleGuid):
1266 SqlCommand = """select GuidValue from Report
1267 where SourceFileFullPath in
1268 (select Value1 from Inf where BelongsToFile =
1269 (select BelongsToFile from Inf
1270 where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
1271 and Model = %s)
1272 and ItemType = 'Protocol' and ItemMode = 'Produced'""" \
1273 % (ModuleGuid, 5001, 3007)
1274 RecordSet = Db.TblReport.Exec(SqlCommand)
1275 for Record in RecordSet:
1276 SqlCommand = """select Value2 from Inf where BelongsToFile =
1277 (select DISTINCT BelongsToFile from Inf
1278 where Value1 =
1279 (select SourceFileFullPath from Report
1280 where GuidValue like '%s' and ItemMode = 'Callback'))
1281 and Value1 = 'FILE_GUID'""" % Record[0]
1282 CallBackSet = Db.TblReport.Exec(SqlCommand)
1283 if CallBackSet != []:
1284 EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
1285 else:
1286 EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid
1287
1288 def LoadPpi(self, Db, ModuleGuid):
1289 SqlCommand = """select GuidValue from Report
1290 where SourceFileFullPath in
1291 (select Value1 from Inf where BelongsToFile =
1292 (select BelongsToFile from Inf
1293 where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)
1294 and Model = %s)
1295 and ItemType = 'Ppi' and ItemMode = 'Produced'""" \
1296 % (ModuleGuid, 5001, 3007)
1297 RecordSet = Db.TblReport.Exec(SqlCommand)
1298 for Record in RecordSet:
1299 EotGlobalData.gPpiList[Record[0].lower()] = ModuleGuid
1300
1301 def DisPatchDxe(self, Db):
1302 IsInstalled = False
1303 ScheduleList = sdict()
1304 for FfsID in self.UnDispatchedFfsDict:
1305 CouldBeLoaded = False
1306 DepexString = ''
1307 FileDepex = None
1308 Ffs = self.UnDispatchedFfsDict[FfsID]
1309 if Ffs.Type == 0x07:
1310 # Get Depex
1311 IsFoundDepex = False
1312 for Section in Ffs.Sections.values():
1313 # Find Depex
1314 if Section.Type == 0x13:
1315 IsFoundDepex = True
1316 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Protocol')
1317 break
1318 if Section.Type == 0x01:
1319 CompressSections = Section._SubImages[4]
1320 for CompressSection in CompressSections.Sections:
1321 if CompressSection.Type == 0x13:
1322 IsFoundDepex = True
1323 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Protocol')
1324 break
1325 if CompressSection.Type == 0x02:
1326 NewSections = CompressSection._SubImages[4]
1327 for NewSection in NewSections.Sections:
1328 if NewSection.Type == 0x13:
1329 IsFoundDepex = True
1330 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Protocol')
1331 break
1332
1333 # Not find Depex
1334 if not IsFoundDepex:
1335 CouldBeLoaded = self.CheckArchProtocol()
1336 DepexString = ''
1337 FileDepex = None
1338
1339 # Append New Ffs
1340 if CouldBeLoaded:
1341 IsInstalled = True
1342 NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
1343 NewFfs.Depex = DepexString
1344 if FileDepex is not None:
1345 ScheduleList.insert(FileDepex[1], FfsID, NewFfs, FileDepex[0])
1346 else:
1347 ScheduleList[FfsID] = NewFfs
1348 else:
1349 self.UnDispatchedFfsDict[FfsID].Depex = DepexString
1350
1351 for FfsID in ScheduleList:
1352 NewFfs = ScheduleList.pop(FfsID)
1353 FfsName = 'UnKnown'
1354 self.OrderedFfsDict[FfsID] = NewFfs
1355 self.LoadProtocol(Db, FfsID)
1356
1357 SqlCommand = """select Value2 from Inf
1358 where BelongsToFile = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)
1359 and Model = %s and Value1='BASE_NAME'""" % (FfsID, 5001, 5001)
1360 RecordSet = Db.TblReport.Exec(SqlCommand)
1361 if RecordSet != []:
1362 FfsName = RecordSet[0][0]
1363
1364 if IsInstalled:
1365 self.DisPatchDxe(Db)
1366
1367 def DisPatchPei(self, Db):
1368 IsInstalled = False
1369 for FfsID in self.UnDispatchedFfsDict:
1370 CouldBeLoaded = True
1371 DepexString = ''
1372 FileDepex = None
1373 Ffs = self.UnDispatchedFfsDict[FfsID]
1374 if Ffs.Type == 0x06 or Ffs.Type == 0x08:
1375 # Get Depex
1376 for Section in Ffs.Sections.values():
1377 if Section.Type == 0x1B:
1378 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Ppi')
1379 break
1380
1381 if Section.Type == 0x01:
1382 CompressSections = Section._SubImages[4]
1383 for CompressSection in CompressSections.Sections:
1384 if CompressSection.Type == 0x1B:
1385 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Ppi')
1386 break
1387 if CompressSection.Type == 0x02:
1388 NewSections = CompressSection._SubImages[4]
1389 for NewSection in NewSections.Sections:
1390 if NewSection.Type == 0x1B:
1391 CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Ppi')
1392 break
1393
1394 # Append New Ffs
1395 if CouldBeLoaded:
1396 IsInstalled = True
1397 NewFfs = self.UnDispatchedFfsDict.pop(FfsID)
1398 NewFfs.Depex = DepexString
1399 self.OrderedFfsDict[FfsID] = NewFfs
1400 self.LoadPpi(Db, FfsID)
1401 else:
1402 self.UnDispatchedFfsDict[FfsID].Depex = DepexString
1403
1404 if IsInstalled:
1405 self.DisPatchPei(Db)
1406
1407
1408 def __str__(self):
1409 global gIndention
1410 gIndention += 4
1411 FvInfo = '\n' + ' ' * gIndention
1412 FvInfo += "[FV:%s] file_system=%s size=%x checksum=%s\n" % (self.Name, self.FileSystemGuid, self.Size, self.Checksum)
1413 FfsInfo = "\n".join([str(self.FfsDict[FfsId]) for FfsId in self.FfsDict])
1414 gIndention -= 4
1415 return FvInfo + FfsInfo
1416
1417 def _Unpack(self):
1418 Size = self._LENGTH_.unpack_from(self._BUF_, self._OFF_)[0]
1419 self.empty()
1420 self.extend(self._BUF_[self._OFF_:self._OFF_+Size])
1421
1422 # traverse the FFS
1423 EndOfFv = Size
1424 FfsStartAddress = self.HeaderSize
1425 LastFfsObj = None
1426 while FfsStartAddress < EndOfFv:
1427 FfsObj = Ffs()
1428 FfsObj.frombuffer(self, FfsStartAddress)
1429 FfsId = repr(FfsObj)
1430 if ((self.Attributes & 0x00000800) != 0 and len(FfsObj) == 0xFFFFFF) \
1431 or ((self.Attributes & 0x00000800) == 0 and len(FfsObj) == 0):
1432 if LastFfsObj is not None:
1433 LastFfsObj.FreeSpace = EndOfFv - LastFfsObj._OFF_ - len(LastFfsObj)
1434 else:
1435 if FfsId in self.FfsDict:
1436 EdkLogger.error("FV", 0, "Duplicate GUID in FFS",
1437 ExtraData="\t%s @ %s\n\t%s @ %s" \
1438 % (FfsObj.Guid, FfsObj.Offset,
1439 self.FfsDict[FfsId].Guid, self.FfsDict[FfsId].Offset))
1440 self.FfsDict[FfsId] = FfsObj
1441 if LastFfsObj is not None:
1442 LastFfsObj.FreeSpace = FfsStartAddress - LastFfsObj._OFF_ - len(LastFfsObj)
1443
1444 FfsStartAddress += len(FfsObj)
1445 #
1446 # align to next 8-byte aligned address: A = (A + 8 - 1) & (~(8 - 1))
1447 # The next FFS must be at the latest next 8-byte aligned address
1448 #
1449 FfsStartAddress = (FfsStartAddress + 7) & (~7)
1450 LastFfsObj = FfsObj
1451
1452 def _GetAttributes(self):
1453 return self.GetField(self._ATTR_, 0)[0]
1454
1455 def _GetSize(self):
1456 return self.GetField(self._LENGTH_, 0)[0]
1457
1458 def _GetChecksum(self):
1459 return self.GetField(self._CHECKSUM_, 0)[0]
1460
1461 def _GetHeaderLength(self):
1462 return self.GetField(self._HLEN_, 0)[0]
1463
1464 def _GetFileSystemGuid(self):
1465 return gGuidStringFormat % self.GetField(self._GUID_, 0)
1466
1467 Attributes = property(_GetAttributes)
1468 Size = property(_GetSize)
1469 Checksum = property(_GetChecksum)
1470 HeaderSize = property(_GetHeaderLength)
1471 FileSystemGuid = property(_GetFileSystemGuid)
1472
1473 ## MultipleFv() class
1474 #
1475 # A class for Multiple FV
1476 #
1477 class MultipleFv(FirmwareVolume):
1478 def __init__(self, FvList):
1479 FirmwareVolume.__init__(self)
1480 self.BasicInfo = []
1481 for FvPath in FvList:
1482 FvName = os.path.splitext(os.path.split(FvPath)[1])[0]
1483 Fd = open(FvPath, 'rb')
1484 Buf = array('B')
1485 try:
1486 Buf.fromfile(Fd, os.path.getsize(FvPath))
1487 except EOFError:
1488 pass
1489
1490 Fv = FirmwareVolume(FvName)
1491 Fv.frombuffer(Buf, 0, len(Buf))
1492
1493 self.BasicInfo.append([Fv.Name, Fv.FileSystemGuid, Fv.Size])
1494 self.FfsDict.append(Fv.FfsDict)
1495
1496 ## Class Eot
1497 #
1498 # This class is used to define Eot main entrance
1499 #
1500 # @param object: Inherited from object class
1501 #
1502 class Eot(object):
1503 ## The constructor
1504 #
1505 # @param self: The object pointer
1506 #
1507 def __init__(self, CommandLineOption=True, IsInit=True, SourceFileList=None, \
1508 IncludeDirList=None, DecFileList=None, GuidList=None, LogFile=None,
1509 FvFileList="", MapFileList="", Report='Report.html', Dispatch=None):
1510 # Version and Copyright
1511 self.VersionNumber = ("0.02" + " " + gBUILD_VERSION)
1512 self.Version = "%prog Version " + self.VersionNumber
1513 self.Copyright = "Copyright (c) 2008 - 2018, Intel Corporation All rights reserved."
1514 self.Report = Report
1515
1516 self.IsInit = IsInit
1517 self.SourceFileList = SourceFileList
1518 self.IncludeDirList = IncludeDirList
1519 self.DecFileList = DecFileList
1520 self.GuidList = GuidList
1521 self.LogFile = LogFile
1522 self.FvFileList = FvFileList
1523 self.MapFileList = MapFileList
1524 self.Dispatch = Dispatch
1525
1526 # Check workspace environment
1527 if "EFI_SOURCE" not in os.environ:
1528 if "EDK_SOURCE" not in os.environ:
1529 pass
1530 else:
1531 EotGlobalData.gEDK_SOURCE = os.path.normpath(os.getenv("EDK_SOURCE"))
1532 else:
1533 EotGlobalData.gEFI_SOURCE = os.path.normpath(os.getenv("EFI_SOURCE"))
1534 EotGlobalData.gEDK_SOURCE = os.path.join(EotGlobalData.gEFI_SOURCE, 'Edk')
1535
1536 if "WORKSPACE" not in os.environ:
1537 EdkLogger.error("EOT", BuildToolError.ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found",
1538 ExtraData="WORKSPACE")
1539 else:
1540 EotGlobalData.gWORKSPACE = os.path.normpath(os.getenv("WORKSPACE"))
1541
1542 EotGlobalData.gMACRO['WORKSPACE'] = EotGlobalData.gWORKSPACE
1543 EotGlobalData.gMACRO['EFI_SOURCE'] = EotGlobalData.gEFI_SOURCE
1544 EotGlobalData.gMACRO['EDK_SOURCE'] = EotGlobalData.gEDK_SOURCE
1545
1546 # Parse the options and args
1547 if CommandLineOption:
1548 self.ParseOption()
1549
1550 if self.FvFileList:
1551 for FvFile in GetSplitValueList(self.FvFileList, ' '):
1552 FvFile = os.path.normpath(FvFile)
1553 if not os.path.isfile(FvFile):
1554 EdkLogger.error("Eot", EdkLogger.EOT_ERROR, "Can not find file %s " % FvFile)
1555 EotGlobalData.gFV_FILE.append(FvFile)
1556 else:
1557 EdkLogger.error("Eot", EdkLogger.EOT_ERROR, "The fv file list of target platform was not specified")
1558
1559 if self.MapFileList:
1560 for MapFile in GetSplitValueList(self.MapFileList, ' '):
1561 MapFile = os.path.normpath(MapFile)
1562 if not os.path.isfile(MapFile):
1563 EdkLogger.error("Eot", EdkLogger.EOT_ERROR, "Can not find file %s " % MapFile)
1564 EotGlobalData.gMAP_FILE.append(MapFile)
1565
1566 # Generate source file list
1567 self.GenerateSourceFileList(self.SourceFileList, self.IncludeDirList)
1568
1569 # Generate guid list of dec file list
1570 self.ParseDecFile(self.DecFileList)
1571
1572 # Generate guid list from GUID list file
1573 self.ParseGuidList(self.GuidList)
1574
1575 # Init Eot database
1576 EotGlobalData.gDb = Database.Database(Database.DATABASE_PATH)
1577 EotGlobalData.gDb.InitDatabase(self.IsInit)
1578
1579 # Build ECC database
1580 self.BuildDatabase()
1581
1582 # Parse Ppi/Protocol
1583 self.ParseExecutionOrder()
1584
1585 # Merge Identifier tables
1586 self.GenerateQueryTable()
1587
1588 # Generate report database
1589 self.GenerateReportDatabase()
1590
1591 # Load Fv Info
1592 self.LoadFvInfo()
1593
1594 # Load Map Info
1595 self.LoadMapInfo()
1596
1597 # Generate Report
1598 self.GenerateReport()
1599
1600 # Convert log file
1601 self.ConvertLogFile(self.LogFile)
1602
1603 # DONE
1604 EdkLogger.quiet("EOT FINISHED!")
1605
1606 # Close Database
1607 EotGlobalData.gDb.Close()
1608
1609 ## ParseDecFile() method
1610 #
1611 # parse DEC file and get all GUID names with GUID values as {GuidName : GuidValue}
1612 # The Dict is stored in EotGlobalData.gGuidDict
1613 #
1614 # @param self: The object pointer
1615 # @param DecFileList: A list of all DEC files
1616 #
1617 def ParseDecFile(self, DecFileList):
1618 if DecFileList:
1619 path = os.path.normpath(DecFileList)
1620 lfr = open(path, 'rb')
1621 for line in lfr:
1622 path = os.path.normpath(os.path.join(EotGlobalData.gWORKSPACE, line.strip()))
1623 if os.path.exists(path):
1624 dfr = open(path, 'rb')
1625 for line in dfr:
1626 line = CleanString(line)
1627 list = line.split('=')
1628 if len(list) == 2:
1629 EotGlobalData.gGuidDict[list[0].strip()] = GuidStructureStringToGuidString(list[1].strip())
1630
1631
1632 ## ParseGuidList() method
1633 #
1634 # Parse Guid list and get all GUID names with GUID values as {GuidName : GuidValue}
1635 # The Dict is stored in EotGlobalData.gGuidDict
1636 #
1637 # @param self: The object pointer
1638 # @param GuidList: A list of all GUID and its value
1639 #
1640 def ParseGuidList(self, GuidList):
1641 Path = os.path.join(EotGlobalData.gWORKSPACE, GuidList)
1642 if os.path.isfile(Path):
1643 for Line in open(Path):
1644 (GuidName, GuidValue) = Line.split()
1645 EotGlobalData.gGuidDict[GuidName] = GuidValue
1646
1647 ## ConvertLogFile() method
1648 #
1649 # Parse a real running log file to get real dispatch order
1650 # The result is saved to old file name + '.new'
1651 #
1652 # @param self: The object pointer
1653 # @param LogFile: A real running log file name
1654 #
1655 def ConvertLogFile(self, LogFile):
1656 newline = []
1657 lfr = None
1658 lfw = None
1659 if LogFile:
1660 lfr = open(LogFile, 'rb')
1661 lfw = open(LogFile + '.new', 'wb')
1662 for line in lfr:
1663 line = line.strip()
1664 line = line.replace('.efi', '')
1665 index = line.find("Loading PEIM at ")
1666 if index > -1:
1667 newline.append(line[index + 55 : ])
1668 continue
1669 index = line.find("Loading driver at ")
1670 if index > -1:
1671 newline.append(line[index + 57 : ])
1672 continue
1673
1674 for line in newline:
1675 lfw.write(line + '\r\n')
1676
1677 if lfr:
1678 lfr.close()
1679 if lfw:
1680 lfw.close()
1681
1682 ## GenerateSourceFileList() method
1683 #
1684 # Generate a list of all source files
1685 # 1. Search the file list one by one
1686 # 2. Store inf file name with source file names under it like
1687 # { INF file name: [source file1, source file2, ...]}
1688 # 3. Search the include list to find all .h files
1689 # 4. Store source file list to EotGlobalData.gSOURCE_FILES
1690 # 5. Store INF file list to EotGlobalData.gINF_FILES
1691 #
1692 # @param self: The object pointer
1693 # @param SourceFileList: A list of all source files
1694 # @param IncludeFileList: A list of all include files
1695 #
1696 def GenerateSourceFileList(self, SourceFileList, IncludeFileList):
1697 EdkLogger.quiet("Generating source files list ... ")
1698 mSourceFileList = []
1699 mInfFileList = []
1700 mDecFileList = []
1701 mFileList = {}
1702 mCurrentInfFile = ''
1703 mCurrentSourceFileList = []
1704
1705 if SourceFileList:
1706 sfl = open(SourceFileList, 'rb')
1707 for line in sfl:
1708 line = os.path.normpath(os.path.join(EotGlobalData.gWORKSPACE, line.strip()))
1709 if line[-2:].upper() == '.C' or line[-2:].upper() == '.H':
1710 if line not in mCurrentSourceFileList:
1711 mCurrentSourceFileList.append(line)
1712 mSourceFileList.append(line)
1713 EotGlobalData.gOP_SOURCE_FILES.write('%s\n' % line)
1714 if line[-4:].upper() == '.INF':
1715 if mCurrentInfFile != '':
1716 mFileList[mCurrentInfFile] = mCurrentSourceFileList
1717 mCurrentSourceFileList = []
1718 mCurrentInfFile = os.path.normpath(os.path.join(EotGlobalData.gWORKSPACE, line))
1719 EotGlobalData.gOP_INF.write('%s\n' % mCurrentInfFile)
1720 if mCurrentInfFile not in mFileList:
1721 mFileList[mCurrentInfFile] = mCurrentSourceFileList
1722
1723 # Get all include files from packages
1724 if IncludeFileList:
1725 ifl = open(IncludeFileList, 'rb')
1726 for line in ifl:
1727 if not line.strip():
1728 continue
1729 newline = os.path.normpath(os.path.join(EotGlobalData.gWORKSPACE, line.strip()))
1730 for Root, Dirs, Files in os.walk(str(newline)):
1731 for File in Files:
1732 FullPath = os.path.normpath(os.path.join(Root, File))
1733 if FullPath not in mSourceFileList and File[-2:].upper() == '.H':
1734 mSourceFileList.append(FullPath)
1735 EotGlobalData.gOP_SOURCE_FILES.write('%s\n' % FullPath)
1736 if FullPath not in mDecFileList and File.upper().find('.DEC') > -1:
1737 mDecFileList.append(FullPath)
1738
1739 EotGlobalData.gSOURCE_FILES = mSourceFileList
1740 EotGlobalData.gOP_SOURCE_FILES.close()
1741
1742 EotGlobalData.gINF_FILES = mFileList
1743 EotGlobalData.gOP_INF.close()
1744
1745 ## GenerateReport() method
1746 #
1747 # Generate final HTML report
1748 #
1749 # @param self: The object pointer
1750 #
1751 def GenerateReport(self):
1752 EdkLogger.quiet("Generating report file ... ")
1753 Rep = Report(self.Report, EotGlobalData.gFV, self.Dispatch)
1754 Rep.GenerateReport()
1755
1756 ## LoadMapInfo() method
1757 #
1758 # Load map files and parse them
1759 #
1760 # @param self: The object pointer
1761 #
1762 def LoadMapInfo(self):
1763 if EotGlobalData.gMAP_FILE != []:
1764 EdkLogger.quiet("Parsing Map file ... ")
1765 EotGlobalData.gMap = ParseMapFile(EotGlobalData.gMAP_FILE)
1766
1767 ## LoadFvInfo() method
1768 #
1769 # Load FV binary files and parse them
1770 #
1771 # @param self: The object pointer
1772 #
1773 def LoadFvInfo(self):
1774 EdkLogger.quiet("Parsing FV file ... ")
1775 EotGlobalData.gFV = MultipleFv(EotGlobalData.gFV_FILE)
1776 EotGlobalData.gFV.Dispatch(EotGlobalData.gDb)
1777
1778 for Protocol in EotGlobalData.gProtocolList:
1779 EotGlobalData.gOP_UN_MATCHED_IN_LIBRARY_CALLING.write('%s\n' %Protocol)
1780
1781 ## GenerateReportDatabase() method
1782 #
1783 # Generate data for the information needed by report
1784 # 1. Update name, macro and value of all found PPI/PROTOCOL GUID
1785 # 2. Install hard coded PPI/PROTOCOL
1786 #
1787 # @param self: The object pointer
1788 #
1789 def GenerateReportDatabase(self):
1790 EdkLogger.quiet("Generating the cross-reference table of GUID for Ppi/Protocol ... ")
1791
1792 # Update Protocol/Ppi Guid
1793 SqlCommand = """select DISTINCT GuidName from Report"""
1794 RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1795 for Record in RecordSet:
1796 GuidName = Record[0]
1797 GuidMacro = ''
1798 GuidMacro2 = ''
1799 GuidValue = ''
1800
1801 # Find guid value defined in Dec file
1802 if GuidName in EotGlobalData.gGuidDict:
1803 GuidValue = EotGlobalData.gGuidDict[GuidName]
1804 SqlCommand = """update Report set GuidMacro = '%s', GuidValue = '%s' where GuidName = '%s'""" %(GuidMacro, GuidValue, GuidName)
1805 EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1806 continue
1807
1808 # Search defined Macros for guid name
1809 SqlCommand ="""select DISTINCT Value, Modifier from Query where Name like '%s'""" % GuidName
1810 GuidMacroSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1811 # Ignore NULL result
1812 if not GuidMacroSet:
1813 continue
1814 GuidMacro = GuidMacroSet[0][0].strip()
1815 if not GuidMacro:
1816 continue
1817 # Find Guid value of Guid Macro
1818 SqlCommand ="""select DISTINCT Value from Query2 where Value like '%%%s%%' and Model = %s""" % (GuidMacro, MODEL_IDENTIFIER_MACRO_DEFINE)
1819 GuidValueSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1820 if GuidValueSet != []:
1821 GuidValue = GuidValueSet[0][0]
1822 GuidValue = GuidValue[GuidValue.find(GuidMacro) + len(GuidMacro) :]
1823 GuidValue = GuidValue.lower().replace('\\', '').replace('\r', '').replace('\n', '').replace('l', '').strip()
1824 GuidValue = GuidStructureStringToGuidString(GuidValue)
1825 SqlCommand = """update Report set GuidMacro = '%s', GuidValue = '%s' where GuidName = '%s'""" %(GuidMacro, GuidValue, GuidName)
1826 EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1827 continue
1828
1829 # Update Hard Coded Ppi/Protocol
1830 SqlCommand = """select DISTINCT GuidValue, ItemType from Report where ModuleID = -2 and ItemMode = 'Produced'"""
1831 RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1832 for Record in RecordSet:
1833 if Record[1] == 'Ppi':
1834 EotGlobalData.gPpiList[Record[0].lower()] = -2
1835 if Record[1] == 'Protocol':
1836 EotGlobalData.gProtocolList[Record[0].lower()] = -2
1837
1838 ## GenerateQueryTable() method
1839 #
1840 # Generate two tables improve query performance
1841 #
1842 # @param self: The object pointer
1843 #
1844 def GenerateQueryTable(self):
1845 EdkLogger.quiet("Generating temp query table for analysis ... ")
1846 for Identifier in EotGlobalData.gIdentifierTableList:
1847 SqlCommand = """insert into Query (Name, Modifier, Value, Model)
1848 select Name, Modifier, Value, Model from %s where (Model = %s or Model = %s)""" \
1849 % (Identifier[0], MODEL_IDENTIFIER_VARIABLE, MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION)
1850 EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1851 SqlCommand = """insert into Query2 (Name, Modifier, Value, Model)
1852 select Name, Modifier, Value, Model from %s where Model = %s""" \
1853 % (Identifier[0], MODEL_IDENTIFIER_MACRO_DEFINE)
1854 EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1855
1856 ## ParseExecutionOrder() method
1857 #
1858 # Get final execution order
1859 # 1. Search all PPI
1860 # 2. Search all PROTOCOL
1861 #
1862 # @param self: The object pointer
1863 #
1864 def ParseExecutionOrder(self):
1865 EdkLogger.quiet("Searching Ppi/Protocol ... ")
1866 for Identifier in EotGlobalData.gIdentifierTableList:
1867 ModuleID, ModuleName, ModuleGuid, SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, Enabled = \
1868 -1, '', '', -1, '', '', '', '', '', '', '', '', 0
1869
1870 SourceFileID = Identifier[0].replace('Identifier', '')
1871 SourceFileFullPath = Identifier[1]
1872 Identifier = Identifier[0]
1873
1874 # Find Ppis
1875 ItemMode = 'Produced'
1876 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1877 where (Name like '%%%s%%' or Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1878 % (Identifier, '.InstallPpi', '->InstallPpi', 'PeiInstallPpi', MODEL_IDENTIFIER_FUNCTION_CALLING)
1879 SearchPpi(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode)
1880
1881 ItemMode = 'Produced'
1882 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1883 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1884 % (Identifier, '.ReInstallPpi', '->ReInstallPpi', MODEL_IDENTIFIER_FUNCTION_CALLING)
1885 SearchPpi(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode, 2)
1886
1887 SearchPpiCallFunction(Identifier, SourceFileID, SourceFileFullPath, ItemMode)
1888
1889 ItemMode = 'Consumed'
1890 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1891 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1892 % (Identifier, '.LocatePpi', '->LocatePpi', MODEL_IDENTIFIER_FUNCTION_CALLING)
1893 SearchPpi(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode)
1894
1895 SearchFunctionCalling(Identifier, SourceFileID, SourceFileFullPath, 'Ppi', ItemMode)
1896
1897 ItemMode = 'Callback'
1898 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1899 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1900 % (Identifier, '.NotifyPpi', '->NotifyPpi', MODEL_IDENTIFIER_FUNCTION_CALLING)
1901 SearchPpi(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode)
1902
1903 # Find Procotols
1904 ItemMode = 'Produced'
1905 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1906 where (Name like '%%%s%%' or Name like '%%%s%%' or Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1907 % (Identifier, '.InstallProtocolInterface', '.ReInstallProtocolInterface', '->InstallProtocolInterface', '->ReInstallProtocolInterface', MODEL_IDENTIFIER_FUNCTION_CALLING)
1908 SearchProtocols(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode, 1)
1909
1910 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1911 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1912 % (Identifier, '.InstallMultipleProtocolInterfaces', '->InstallMultipleProtocolInterfaces', MODEL_IDENTIFIER_FUNCTION_CALLING)
1913 SearchProtocols(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode, 2)
1914
1915 SearchFunctionCalling(Identifier, SourceFileID, SourceFileFullPath, 'Protocol', ItemMode)
1916
1917 ItemMode = 'Consumed'
1918 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1919 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1920 % (Identifier, '.LocateProtocol', '->LocateProtocol', MODEL_IDENTIFIER_FUNCTION_CALLING)
1921 SearchProtocols(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode, 0)
1922
1923 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1924 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1925 % (Identifier, '.HandleProtocol', '->HandleProtocol', MODEL_IDENTIFIER_FUNCTION_CALLING)
1926 SearchProtocols(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode, 1)
1927
1928 SearchFunctionCalling(Identifier, SourceFileID, SourceFileFullPath, 'Protocol', ItemMode)
1929
1930 ItemMode = 'Callback'
1931 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1932 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1933 % (Identifier, '.RegisterProtocolNotify', '->RegisterProtocolNotify', MODEL_IDENTIFIER_FUNCTION_CALLING)
1934 SearchProtocols(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode, 0)
1935
1936 SearchFunctionCalling(Identifier, SourceFileID, SourceFileFullPath, 'Protocol', ItemMode)
1937
1938 # Hard Code
1939 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gEfiSecPlatformInformationPpiGuid', '', '', '', 0)
1940 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gEfiNtLoadAsDllPpiGuid', '', '', '', 0)
1941 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gNtPeiLoadFileGuid', '', '', '', 0)
1942 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiNtAutoScanPpiGuid', '', '', '', 0)
1943 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gNtFwhPpiGuid', '', '', '', 0)
1944 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiNtThunkPpiGuid', '', '', '', 0)
1945 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiPlatformTypePpiGuid', '', '', '', 0)
1946 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiFrequencySelectionCpuPpiGuid', '', '', '', 0)
1947 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiCachePpiGuid', '', '', '', 0)
1948
1949 EotGlobalData.gDb.Conn.commit()
1950
1951
1952 ## BuildDatabase() methoc
1953 #
1954 # Build the database for target
1955 #
1956 # @param self: The object pointer
1957 #
1958 def BuildDatabase(self):
1959 # Clean report table
1960 EotGlobalData.gDb.TblReport.Drop()
1961 EotGlobalData.gDb.TblReport.Create()
1962
1963 # Build database
1964 if self.IsInit:
1965 self.BuildMetaDataFileDatabase(EotGlobalData.gINF_FILES)
1966 EdkLogger.quiet("Building database for source code ...")
1967 c.CreateCCodeDB(EotGlobalData.gSOURCE_FILES)
1968 EdkLogger.quiet("Building database for source code done!")
1969
1970 EotGlobalData.gIdentifierTableList = GetTableList((MODEL_FILE_C, MODEL_FILE_H), 'Identifier', EotGlobalData.gDb)
1971
1972 ## BuildMetaDataFileDatabase() method
1973 #
1974 # Build the database for meta data files
1975 #
1976 # @param self: The object pointer
1977 # @param Inf_Files: A list for all INF files
1978 #
1979 def BuildMetaDataFileDatabase(self, Inf_Files):
1980 EdkLogger.quiet("Building database for meta data files ...")
1981 for InfFile in Inf_Files:
1982 EdkLogger.quiet("Parsing %s ..." % str(InfFile))
1983 EdkInfParser(InfFile, EotGlobalData.gDb, Inf_Files[InfFile], '')
1984
1985 EotGlobalData.gDb.Conn.commit()
1986 EdkLogger.quiet("Building database for meta data files done!")
1987
1988 ## ParseOption() method
1989 #
1990 # Parse command line options
1991 #
1992 # @param self: The object pointer
1993 #
1994 def ParseOption(self):
1995 (Options, Target) = self.EotOptionParser()
1996
1997 # Set log level
1998 self.SetLogLevel(Options)
1999
2000 if Options.FvFileList:
2001 self.FvFileList = Options.FvFileList
2002
2003 if Options.MapFileList:
2004 self.MapFileList = Options.FvMapFileList
2005
2006 if Options.SourceFileList:
2007 self.SourceFileList = Options.SourceFileList
2008
2009 if Options.IncludeDirList:
2010 self.IncludeDirList = Options.IncludeDirList
2011
2012 if Options.DecFileList:
2013 self.DecFileList = Options.DecFileList
2014
2015 if Options.GuidList:
2016 self.GuidList = Options.GuidList
2017
2018 if Options.LogFile:
2019 self.LogFile = Options.LogFile
2020
2021 if Options.keepdatabase:
2022 self.IsInit = False
2023
2024 ## SetLogLevel() method
2025 #
2026 # Set current log level of the tool based on args
2027 #
2028 # @param self: The object pointer
2029 # @param Option: The option list including log level setting
2030 #
2031 def SetLogLevel(self, Option):
2032 if Option.verbose is not None:
2033 EdkLogger.SetLevel(EdkLogger.VERBOSE)
2034 elif Option.quiet is not None:
2035 EdkLogger.SetLevel(EdkLogger.QUIET)
2036 elif Option.debug is not None:
2037 EdkLogger.SetLevel(Option.debug + 1)
2038 else:
2039 EdkLogger.SetLevel(EdkLogger.INFO)
2040
2041 ## EotOptionParser() method
2042 #
2043 # Using standard Python module optparse to parse command line option of this tool.
2044 #
2045 # @param self: The object pointer
2046 #
2047 # @retval Opt A optparse.Values object containing the parsed options
2048 # @retval Args Target of build command
2049 #
2050 def EotOptionParser(self):
2051 Parser = OptionParser(description = self.Copyright, version = self.Version, prog = "Eot.exe", usage = "%prog [options]")
2052 Parser.add_option("-m", "--makefile filename", action="store", type="string", dest='MakeFile',
2053 help="Specify a makefile for the platform.")
2054 Parser.add_option("-c", "--dsc filename", action="store", type="string", dest="DscFile",
2055 help="Specify a dsc file for the platform.")
2056 Parser.add_option("-f", "--fv filename", action="store", type="string", dest="FvFileList",
2057 help="Specify fv file list, quoted by \"\".")
2058 Parser.add_option("-a", "--map filename", action="store", type="string", dest="MapFileList",
2059 help="Specify map file list, quoted by \"\".")
2060 Parser.add_option("-s", "--source files", action="store", type="string", dest="SourceFileList",
2061 help="Specify source file list by a file")
2062 Parser.add_option("-i", "--include dirs", action="store", type="string", dest="IncludeDirList",
2063 help="Specify include dir list by a file")
2064 Parser.add_option("-e", "--dec files", action="store", type="string", dest="DecFileList",
2065 help="Specify dec file list by a file")
2066 Parser.add_option("-g", "--guid list", action="store", type="string", dest="GuidList",
2067 help="Specify guid file list by a file")
2068 Parser.add_option("-l", "--log filename", action="store", type="string", dest="LogFile",
2069 help="Specify real execution log file")
2070
2071 Parser.add_option("-k", "--keepdatabase", action="store_true", type=None, help="The existing Eot database will not be cleaned except report information if this option is specified.")
2072
2073 Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
2074 Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\
2075 "including library instances selected, final dependency expression, "\
2076 "and warning messages, etc.")
2077 Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")
2078
2079 (Opt, Args)=Parser.parse_args()
2080
2081 return (Opt, Args)
2082
2083 ##
2084 #
2085 # This acts like the main() function for the script, unless it is 'import'ed into another
2086 # script.
2087 #
2088 if __name__ == '__main__':
2089 # Initialize log system
2090 EdkLogger.Initialize()
2091 EdkLogger.IsRaiseError = False
2092 EdkLogger.quiet(time.strftime("%H:%M:%S, %b.%d %Y ", time.localtime()) + "[00:00]" + "\n")
2093
2094 StartTime = time.clock()
2095 Eot = Eot()
2096 FinishTime = time.clock()
2097
2098 BuildDuration = time.strftime("%M:%S", time.gmtime(int(round(FinishTime - StartTime))))
2099 EdkLogger.quiet("\n%s [%s]" % (time.strftime("%H:%M:%S, %b.%d %Y", time.localtime()), BuildDuration))