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