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