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