]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Eot/EotMain.py
fd4bee6f901e3e30eebe2e0f750ba3b95809688a
[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 FFS_ATTRIB_FIXED = 0x04
933 FFS_ATTRIB_DATA_ALIGNMENT = 0x38
934 FFS_ATTRIB_CHECKSUM = 0x40
935
936 _TypeName = {
937 0x00 : "<unknown>",
938 0x01 : "RAW",
939 0x02 : "FREEFORM",
940 0x03 : "SECURITY_CORE",
941 0x04 : "PEI_CORE",
942 0x05 : "DXE_CORE",
943 0x06 : "PEIM",
944 0x07 : "DRIVER",
945 0x08 : "COMBINED_PEIM_DRIVER",
946 0x09 : "APPLICATION",
947 0x0A : "SMM",
948 0x0B : "FIRMWARE_VOLUME_IMAGE",
949 0x0C : "COMBINED_SMM_DXE",
950 0x0D : "SMM_CORE",
951 0x0E : "MM_STANDALONE",
952 0x0F : "MM_CORE_STANDALONE",
953 0xc0 : "OEM_MIN",
954 0xdf : "OEM_MAX",
955 0xe0 : "DEBUG_MIN",
956 0xef : "DEBUG_MAX",
957 0xf0 : "FFS_MIN",
958 0xff : "FFS_MAX",
959 0xf0 : "FFS_PAD",
960 }
961
962 def __init__(self):
963 Image.__init__(self)
964 self.FreeSpace = 0
965
966 self.Sections = sdict()
967 self.Depex = ''
968
969 self.__ID__ = None
970
971 def __str__(self):
972 global gIndention
973 gIndention += 4
974 Indention = ' ' * gIndention
975 FfsInfo = Indention
976 FfsInfo += "[FFS:%s] offset=%x size=%x guid=%s free_space=%x alignment=%s\n" % \
977 (Ffs._TypeName[self.Type], self._OFF_, self.Size, self.Guid, self.FreeSpace, self.Alignment)
978 SectionInfo = '\n'.join([str(self.Sections[Offset]) for Offset in self.Sections.keys()])
979 gIndention -= 4
980 return FfsInfo + SectionInfo + "\n"
981
982 def __len__(self):
983 return self.Size
984
985 def __repr__(self):
986 return self.__ID__
987
988 def _Unpack(self):
989 Size1, Size2, Size3 = self._SIZE_.unpack_from(self._BUF_, self._OFF_)
990 Size = Size1 + (Size2 << 8) + (Size3 << 16)
991 self.empty()
992 self.extend(self._BUF_[self._OFF_ : self._OFF_ + Size])
993
994 # Pad FFS may use the same GUID. We need to avoid it.
995 if self.Type == 0xf0:
996 self.__ID__ = str(uuid.uuid1()).upper()
997 else:
998 self.__ID__ = self.Guid
999
1000 # Traverse the SECTION. RAW and PAD do not have sections
1001 if self.Type not in [0xf0, 0x01] and Size > 0 and Size < 0xFFFFFF:
1002 EndOfFfs = Size
1003 SectionStartAddress = self._HEADER_SIZE_
1004 while SectionStartAddress < EndOfFfs:
1005 SectionObj = Section()
1006 SectionObj.frombuffer(self, SectionStartAddress)
1007 #f = open(repr(SectionObj), 'wb')
1008 #SectionObj.Size = 0
1009 #SectionObj.tofile(f)
1010 #f.close()
1011 self.Sections[SectionStartAddress] = SectionObj
1012 SectionStartAddress += len(SectionObj)
1013 SectionStartAddress = (SectionStartAddress + 3) & (~3)
1014
1015 def Pack(self):
1016 pass
1017
1018 def SetFreeSpace(self, Size):
1019 self.FreeSpace = Size
1020
1021 def _GetGuid(self):
1022 return gGuidStringFormat % self.Name
1023
1024 def _SetName(self, Value):
1025 # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
1026 self.SetField(self._NAME_, 0, Value)
1027
1028 def _GetName(self):
1029 # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
1030 return self.GetField(self._NAME_)
1031
1032 def _SetSize(self, Size):
1033 Size1 = Size & 0xFF
1034 Size2 = (Size & 0xFF00) >> 8
1035 Size3 = (Size & 0xFF0000) >> 16
1036 self.SetField(self._SIZE_, 0, Size1, Size2, Size3)
1037
1038 def _GetSize(self):
1039 Size1, Size2, Size3 = self.GetField(self._SIZE_)
1040 return Size1 + (Size2 << 8) + (Size3 << 16)
1041
1042 def _SetType(self, Type):
1043 self.SetField(self._TYPE_, 0, Type)
1044
1045 def _GetType(self):
1046 return self.GetField(self._TYPE_)[0]
1047
1048 def _SetAttributes(self, Value):
1049 self.SetField(self._ATTR_, 0, Value)
1050
1051 def _GetAttributes(self):
1052 return self.GetField(self._ATTR_)[0]
1053
1054 def _GetFixed(self):
1055 if (self.Attributes & self.FFS_ATTRIB_FIXED) != 0:
1056 return True
1057 return False
1058
1059 def _GetCheckSum(self):
1060 if (self.Attributes & self.FFS_ATTRIB_CHECKSUM) != 0:
1061 return True
1062 return False
1063
1064 def _GetAlignment(self):
1065 return (self.Attributes & self.FFS_ATTRIB_DATA_ALIGNMENT) >> 3
1066
1067 def _SetState(self, Value):
1068 self.SetField(self._STATE_, 0, Value)
1069
1070 def _GetState(self):
1071 return self.GetField(self._STATE_)[0]
1072
1073 Name = property(_GetName, _SetName)
1074 Guid = property(_GetGuid)
1075 Type = property(_GetType, _SetType)
1076 Size = property(_GetSize, _SetSize)
1077 Attributes = property(_GetAttributes, _SetAttributes)
1078 Fixed = property(_GetFixed)
1079 Checksum = property(_GetCheckSum)
1080 Alignment = property(_GetAlignment)
1081 State = property(_GetState, _SetState)
1082
1083
1084 ## MultipleFv() class
1085 #
1086 # A class for Multiple FV
1087 #
1088 class MultipleFv(FirmwareVolume):
1089 def __init__(self, FvList):
1090 FirmwareVolume.__init__(self)
1091 self.BasicInfo = []
1092 for FvPath in FvList:
1093 Fd = None
1094 FvName = os.path.splitext(os.path.split(FvPath)[1])[0]
1095 if FvPath.strip():
1096 Fd = open(FvPath, 'rb')
1097 Buf = array('B')
1098 try:
1099 Buf.fromfile(Fd, os.path.getsize(FvPath))
1100 except EOFError:
1101 pass
1102
1103 Fv = FirmwareVolume(FvName)
1104 Fv.frombuffer(Buf, 0, len(Buf))
1105
1106 self.BasicInfo.append([Fv.Name, Fv.FileSystemGuid, Fv.Size])
1107 self.FfsDict.append(Fv.FfsDict)
1108
1109 ## Class Eot
1110 #
1111 # This class is used to define Eot main entrance
1112 #
1113 # @param object: Inherited from object class
1114 #
1115 class Eot(object):
1116 ## The constructor
1117 #
1118 # @param self: The object pointer
1119 #
1120 def __init__(self, CommandLineOption=True, IsInit=True, SourceFileList=None, \
1121 IncludeDirList=None, DecFileList=None, GuidList=None, LogFile=None,
1122 FvFileList="", MapFileList="", Report='Report.html', Dispatch=None):
1123 # Version and Copyright
1124 self.VersionNumber = ("0.02" + " " + gBUILD_VERSION)
1125 self.Version = "%prog Version " + self.VersionNumber
1126 self.Copyright = "Copyright (c) 2008 - 2018, Intel Corporation All rights reserved."
1127 self.Report = Report
1128
1129 self.IsInit = IsInit
1130 self.SourceFileList = SourceFileList
1131 self.IncludeDirList = IncludeDirList
1132 self.DecFileList = DecFileList
1133 self.GuidList = GuidList
1134 self.LogFile = LogFile
1135 self.FvFileList = FvFileList
1136 self.MapFileList = MapFileList
1137 self.Dispatch = Dispatch
1138
1139 # Check workspace environment
1140 if "EFI_SOURCE" not in os.environ:
1141 if "EDK_SOURCE" not in os.environ:
1142 pass
1143 else:
1144 EotGlobalData.gEDK_SOURCE = os.path.normpath(os.getenv("EDK_SOURCE"))
1145 else:
1146 EotGlobalData.gEFI_SOURCE = os.path.normpath(os.getenv("EFI_SOURCE"))
1147 EotGlobalData.gEDK_SOURCE = os.path.join(EotGlobalData.gEFI_SOURCE, 'Edk')
1148
1149 if "WORKSPACE" not in os.environ:
1150 EdkLogger.error("EOT", BuildToolError.ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found",
1151 ExtraData="WORKSPACE")
1152 else:
1153 EotGlobalData.gWORKSPACE = os.path.normpath(os.getenv("WORKSPACE"))
1154
1155 EotGlobalData.gMACRO['WORKSPACE'] = EotGlobalData.gWORKSPACE
1156 EotGlobalData.gMACRO['EFI_SOURCE'] = EotGlobalData.gEFI_SOURCE
1157 EotGlobalData.gMACRO['EDK_SOURCE'] = EotGlobalData.gEDK_SOURCE
1158
1159 # Parse the options and args
1160 if CommandLineOption:
1161 self.ParseOption()
1162
1163 if self.FvFileList:
1164 for FvFile in GetSplitValueList(self.FvFileList, ' '):
1165 FvFile = os.path.normpath(FvFile)
1166 if not os.path.isfile(FvFile):
1167 EdkLogger.error("Eot", EdkLogger.EOT_ERROR, "Can not find file %s " % FvFile)
1168 EotGlobalData.gFV_FILE.append(FvFile)
1169 else:
1170 EdkLogger.error("Eot", EdkLogger.EOT_ERROR, "The fv file list of target platform was not specified")
1171
1172 if self.MapFileList:
1173 for MapFile in GetSplitValueList(self.MapFileList, ' '):
1174 MapFile = os.path.normpath(MapFile)
1175 if not os.path.isfile(MapFile):
1176 EdkLogger.error("Eot", EdkLogger.EOT_ERROR, "Can not find file %s " % MapFile)
1177 EotGlobalData.gMAP_FILE.append(MapFile)
1178
1179 # Generate source file list
1180 self.GenerateSourceFileList(self.SourceFileList, self.IncludeDirList)
1181
1182 # Generate guid list of dec file list
1183 self.ParseDecFile(self.DecFileList)
1184
1185 # Generate guid list from GUID list file
1186 self.ParseGuidList(self.GuidList)
1187
1188 # Init Eot database
1189 EotGlobalData.gDb = Database.Database(Database.DATABASE_PATH)
1190 EotGlobalData.gDb.InitDatabase(self.IsInit)
1191
1192 # Build ECC database
1193 self.BuildDatabase()
1194
1195 # Parse Ppi/Protocol
1196 self.ParseExecutionOrder()
1197
1198 # Merge Identifier tables
1199 self.GenerateQueryTable()
1200
1201 # Generate report database
1202 self.GenerateReportDatabase()
1203
1204 # Load Fv Info
1205 self.LoadFvInfo()
1206
1207 # Load Map Info
1208 self.LoadMapInfo()
1209
1210 # Generate Report
1211 self.GenerateReport()
1212
1213 # Convert log file
1214 self.ConvertLogFile(self.LogFile)
1215
1216 # DONE
1217 EdkLogger.quiet("EOT FINISHED!")
1218
1219 # Close Database
1220 EotGlobalData.gDb.Close()
1221
1222 ## ParseDecFile() method
1223 #
1224 # parse DEC file and get all GUID names with GUID values as {GuidName : GuidValue}
1225 # The Dict is stored in EotGlobalData.gGuidDict
1226 #
1227 # @param self: The object pointer
1228 # @param DecFileList: A list of all DEC files
1229 #
1230 def ParseDecFile(self, DecFileList):
1231 if DecFileList:
1232 path = os.path.normpath(DecFileList)
1233 lfr = open(path, 'rb')
1234 for line in lfr:
1235 path = os.path.normpath(os.path.join(EotGlobalData.gWORKSPACE, line.strip()))
1236 if os.path.exists(path):
1237 dfr = open(path, 'rb')
1238 for line in dfr:
1239 line = CleanString(line)
1240 list = line.split('=')
1241 if len(list) == 2:
1242 EotGlobalData.gGuidDict[list[0].strip()] = GuidStructureStringToGuidString(list[1].strip())
1243
1244
1245 ## ParseGuidList() method
1246 #
1247 # Parse Guid list and get all GUID names with GUID values as {GuidName : GuidValue}
1248 # The Dict is stored in EotGlobalData.gGuidDict
1249 #
1250 # @param self: The object pointer
1251 # @param GuidList: A list of all GUID and its value
1252 #
1253 def ParseGuidList(self, GuidList):
1254 Path = os.path.join(EotGlobalData.gWORKSPACE, GuidList)
1255 if os.path.isfile(Path):
1256 for Line in open(Path):
1257 if Line.strip():
1258 (GuidName, GuidValue) = Line.split()
1259 EotGlobalData.gGuidDict[GuidName] = GuidValue
1260
1261 ## ConvertLogFile() method
1262 #
1263 # Parse a real running log file to get real dispatch order
1264 # The result is saved to old file name + '.new'
1265 #
1266 # @param self: The object pointer
1267 # @param LogFile: A real running log file name
1268 #
1269 def ConvertLogFile(self, LogFile):
1270 newline = []
1271 lfr = None
1272 lfw = None
1273 if LogFile:
1274 lfr = open(LogFile, 'rb')
1275 lfw = open(LogFile + '.new', 'wb')
1276 for line in lfr:
1277 line = line.strip()
1278 line = line.replace('.efi', '')
1279 index = line.find("Loading PEIM at ")
1280 if index > -1:
1281 newline.append(line[index + 55 : ])
1282 continue
1283 index = line.find("Loading driver at ")
1284 if index > -1:
1285 newline.append(line[index + 57 : ])
1286 continue
1287
1288 for line in newline:
1289 lfw.write(line + '\r\n')
1290
1291 if lfr:
1292 lfr.close()
1293 if lfw:
1294 lfw.close()
1295
1296 ## GenerateSourceFileList() method
1297 #
1298 # Generate a list of all source files
1299 # 1. Search the file list one by one
1300 # 2. Store inf file name with source file names under it like
1301 # { INF file name: [source file1, source file2, ...]}
1302 # 3. Search the include list to find all .h files
1303 # 4. Store source file list to EotGlobalData.gSOURCE_FILES
1304 # 5. Store INF file list to EotGlobalData.gINF_FILES
1305 #
1306 # @param self: The object pointer
1307 # @param SourceFileList: A list of all source files
1308 # @param IncludeFileList: A list of all include files
1309 #
1310 def GenerateSourceFileList(self, SourceFileList, IncludeFileList):
1311 EdkLogger.quiet("Generating source files list ... ")
1312 mSourceFileList = []
1313 mInfFileList = []
1314 mDecFileList = []
1315 mFileList = {}
1316 mCurrentInfFile = ''
1317 mCurrentSourceFileList = []
1318
1319 if SourceFileList:
1320 sfl = open(SourceFileList, 'r')
1321 for line in sfl:
1322 line = os.path.normpath(os.path.join(EotGlobalData.gWORKSPACE, line.strip()))
1323 if line[-2:].upper() == '.C' or line[-2:].upper() == '.H':
1324 if line not in mCurrentSourceFileList:
1325 mCurrentSourceFileList.append(line)
1326 mSourceFileList.append(line)
1327 EotGlobalData.gOP_SOURCE_FILES.write('%s\n' % line)
1328 if line[-4:].upper() == '.INF':
1329 if mCurrentInfFile != '':
1330 mFileList[mCurrentInfFile] = mCurrentSourceFileList
1331 mCurrentSourceFileList = []
1332 mCurrentInfFile = os.path.normpath(os.path.join(EotGlobalData.gWORKSPACE, line))
1333 EotGlobalData.gOP_INF.write('%s\n' % mCurrentInfFile)
1334 if mCurrentInfFile not in mFileList:
1335 mFileList[mCurrentInfFile] = mCurrentSourceFileList
1336
1337 # Get all include files from packages
1338 if IncludeFileList:
1339 ifl = open(IncludeFileList, 'rb')
1340 for line in ifl:
1341 if not line.strip():
1342 continue
1343 newline = os.path.normpath(os.path.join(EotGlobalData.gWORKSPACE, line.strip()))
1344 for Root, Dirs, Files in os.walk(str(newline)):
1345 for File in Files:
1346 FullPath = os.path.normpath(os.path.join(Root, File))
1347 if FullPath not in mSourceFileList and File[-2:].upper() == '.H':
1348 mSourceFileList.append(FullPath)
1349 EotGlobalData.gOP_SOURCE_FILES.write('%s\n' % FullPath)
1350 if FullPath not in mDecFileList and File.upper().find('.DEC') > -1:
1351 mDecFileList.append(FullPath)
1352
1353 EotGlobalData.gSOURCE_FILES = mSourceFileList
1354 EotGlobalData.gOP_SOURCE_FILES.close()
1355
1356 EotGlobalData.gINF_FILES = mFileList
1357 EotGlobalData.gOP_INF.close()
1358
1359 ## GenerateReport() method
1360 #
1361 # Generate final HTML report
1362 #
1363 # @param self: The object pointer
1364 #
1365 def GenerateReport(self):
1366 EdkLogger.quiet("Generating report file ... ")
1367 Rep = Report(self.Report, EotGlobalData.gFV, self.Dispatch)
1368 Rep.GenerateReport()
1369
1370 ## LoadMapInfo() method
1371 #
1372 # Load map files and parse them
1373 #
1374 # @param self: The object pointer
1375 #
1376 def LoadMapInfo(self):
1377 if EotGlobalData.gMAP_FILE != []:
1378 EdkLogger.quiet("Parsing Map file ... ")
1379 EotGlobalData.gMap = ParseMapFile(EotGlobalData.gMAP_FILE)
1380
1381 ## LoadFvInfo() method
1382 #
1383 # Load FV binary files and parse them
1384 #
1385 # @param self: The object pointer
1386 #
1387 def LoadFvInfo(self):
1388 EdkLogger.quiet("Parsing FV file ... ")
1389 EotGlobalData.gFV = MultipleFv(EotGlobalData.gFV_FILE)
1390 EotGlobalData.gFV.Dispatch(EotGlobalData.gDb)
1391
1392 for Protocol in EotGlobalData.gProtocolList:
1393 EotGlobalData.gOP_UN_MATCHED_IN_LIBRARY_CALLING.write('%s\n' %Protocol)
1394
1395 ## GenerateReportDatabase() method
1396 #
1397 # Generate data for the information needed by report
1398 # 1. Update name, macro and value of all found PPI/PROTOCOL GUID
1399 # 2. Install hard coded PPI/PROTOCOL
1400 #
1401 # @param self: The object pointer
1402 #
1403 def GenerateReportDatabase(self):
1404 EdkLogger.quiet("Generating the cross-reference table of GUID for Ppi/Protocol ... ")
1405
1406 # Update Protocol/Ppi Guid
1407 SqlCommand = """select DISTINCT GuidName from Report"""
1408 RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1409 for Record in RecordSet:
1410 GuidName = Record[0]
1411 GuidMacro = ''
1412 GuidMacro2 = ''
1413 GuidValue = ''
1414
1415 # Find guid value defined in Dec file
1416 if GuidName in EotGlobalData.gGuidDict:
1417 GuidValue = EotGlobalData.gGuidDict[GuidName]
1418 SqlCommand = """update Report set GuidMacro = '%s', GuidValue = '%s' where GuidName = '%s'""" %(GuidMacro, GuidValue, GuidName)
1419 EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1420 continue
1421
1422 # Search defined Macros for guid name
1423 SqlCommand ="""select DISTINCT Value, Modifier from Query where Name like '%s'""" % GuidName
1424 GuidMacroSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1425 # Ignore NULL result
1426 if not GuidMacroSet:
1427 continue
1428 GuidMacro = GuidMacroSet[0][0].strip()
1429 if not GuidMacro:
1430 continue
1431 # Find Guid value of Guid Macro
1432 SqlCommand ="""select DISTINCT Value from Query2 where Value like '%%%s%%' and Model = %s""" % (GuidMacro, MODEL_IDENTIFIER_MACRO_DEFINE)
1433 GuidValueSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1434 if GuidValueSet != []:
1435 GuidValue = GuidValueSet[0][0]
1436 GuidValue = GuidValue[GuidValue.find(GuidMacro) + len(GuidMacro) :]
1437 GuidValue = GuidValue.lower().replace('\\', '').replace('\r', '').replace('\n', '').replace('l', '').strip()
1438 GuidValue = GuidStructureStringToGuidString(GuidValue)
1439 SqlCommand = """update Report set GuidMacro = '%s', GuidValue = '%s' where GuidName = '%s'""" %(GuidMacro, GuidValue, GuidName)
1440 EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1441 continue
1442
1443 # Update Hard Coded Ppi/Protocol
1444 SqlCommand = """select DISTINCT GuidValue, ItemType from Report where ModuleID = -2 and ItemMode = 'Produced'"""
1445 RecordSet = EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1446 for Record in RecordSet:
1447 if Record[1] == 'Ppi':
1448 EotGlobalData.gPpiList[Record[0].lower()] = -2
1449 if Record[1] == 'Protocol':
1450 EotGlobalData.gProtocolList[Record[0].lower()] = -2
1451
1452 ## GenerateQueryTable() method
1453 #
1454 # Generate two tables improve query performance
1455 #
1456 # @param self: The object pointer
1457 #
1458 def GenerateQueryTable(self):
1459 EdkLogger.quiet("Generating temp query table for analysis ... ")
1460 for Identifier in EotGlobalData.gIdentifierTableList:
1461 SqlCommand = """insert into Query (Name, Modifier, Value, Model)
1462 select Name, Modifier, Value, Model from %s where (Model = %s or Model = %s)""" \
1463 % (Identifier[0], MODEL_IDENTIFIER_VARIABLE, MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION)
1464 EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1465 SqlCommand = """insert into Query2 (Name, Modifier, Value, Model)
1466 select Name, Modifier, Value, Model from %s where Model = %s""" \
1467 % (Identifier[0], MODEL_IDENTIFIER_MACRO_DEFINE)
1468 EotGlobalData.gDb.TblReport.Exec(SqlCommand)
1469
1470 ## ParseExecutionOrder() method
1471 #
1472 # Get final execution order
1473 # 1. Search all PPI
1474 # 2. Search all PROTOCOL
1475 #
1476 # @param self: The object pointer
1477 #
1478 def ParseExecutionOrder(self):
1479 EdkLogger.quiet("Searching Ppi/Protocol ... ")
1480 for Identifier in EotGlobalData.gIdentifierTableList:
1481 ModuleID, ModuleName, ModuleGuid, SourceFileID, SourceFileFullPath, ItemName, ItemType, ItemMode, GuidName, GuidMacro, GuidValue, BelongsToFunction, Enabled = \
1482 -1, '', '', -1, '', '', '', '', '', '', '', '', 0
1483
1484 SourceFileID = Identifier[0].replace('Identifier', '')
1485 SourceFileFullPath = Identifier[1]
1486 Identifier = Identifier[0]
1487
1488 # Find Ppis
1489 ItemMode = 'Produced'
1490 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1491 where (Name like '%%%s%%' or Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1492 % (Identifier, '.InstallPpi', '->InstallPpi', 'PeiInstallPpi', MODEL_IDENTIFIER_FUNCTION_CALLING)
1493 SearchPpi(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode)
1494
1495 ItemMode = 'Produced'
1496 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1497 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1498 % (Identifier, '.ReInstallPpi', '->ReInstallPpi', MODEL_IDENTIFIER_FUNCTION_CALLING)
1499 SearchPpi(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode, 2)
1500
1501 SearchPpiCallFunction(Identifier, SourceFileID, SourceFileFullPath, ItemMode)
1502
1503 ItemMode = 'Consumed'
1504 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1505 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1506 % (Identifier, '.LocatePpi', '->LocatePpi', MODEL_IDENTIFIER_FUNCTION_CALLING)
1507 SearchPpi(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode)
1508
1509 SearchFunctionCalling(Identifier, SourceFileID, SourceFileFullPath, 'Ppi', ItemMode)
1510
1511 ItemMode = 'Callback'
1512 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1513 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1514 % (Identifier, '.NotifyPpi', '->NotifyPpi', MODEL_IDENTIFIER_FUNCTION_CALLING)
1515 SearchPpi(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode)
1516
1517 # Find Procotols
1518 ItemMode = 'Produced'
1519 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1520 where (Name like '%%%s%%' or Name like '%%%s%%' or Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1521 % (Identifier, '.InstallProtocolInterface', '.ReInstallProtocolInterface', '->InstallProtocolInterface', '->ReInstallProtocolInterface', MODEL_IDENTIFIER_FUNCTION_CALLING)
1522 SearchProtocols(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode, 1)
1523
1524 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1525 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1526 % (Identifier, '.InstallMultipleProtocolInterfaces', '->InstallMultipleProtocolInterfaces', MODEL_IDENTIFIER_FUNCTION_CALLING)
1527 SearchProtocols(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode, 2)
1528
1529 SearchFunctionCalling(Identifier, SourceFileID, SourceFileFullPath, 'Protocol', ItemMode)
1530
1531 ItemMode = 'Consumed'
1532 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1533 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1534 % (Identifier, '.LocateProtocol', '->LocateProtocol', MODEL_IDENTIFIER_FUNCTION_CALLING)
1535 SearchProtocols(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode, 0)
1536
1537 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1538 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1539 % (Identifier, '.HandleProtocol', '->HandleProtocol', MODEL_IDENTIFIER_FUNCTION_CALLING)
1540 SearchProtocols(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode, 1)
1541
1542 SearchFunctionCalling(Identifier, SourceFileID, SourceFileFullPath, 'Protocol', ItemMode)
1543
1544 ItemMode = 'Callback'
1545 SqlCommand = """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1546 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1547 % (Identifier, '.RegisterProtocolNotify', '->RegisterProtocolNotify', MODEL_IDENTIFIER_FUNCTION_CALLING)
1548 SearchProtocols(SqlCommand, Identifier, SourceFileID, SourceFileFullPath, ItemMode, 0)
1549
1550 SearchFunctionCalling(Identifier, SourceFileID, SourceFileFullPath, 'Protocol', ItemMode)
1551
1552 # Hard Code
1553 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gEfiSecPlatformInformationPpiGuid', '', '', '', 0)
1554 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gEfiNtLoadAsDllPpiGuid', '', '', '', 0)
1555 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gNtPeiLoadFileGuid', '', '', '', 0)
1556 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiNtAutoScanPpiGuid', '', '', '', 0)
1557 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gNtFwhPpiGuid', '', '', '', 0)
1558 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiNtThunkPpiGuid', '', '', '', 0)
1559 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiPlatformTypePpiGuid', '', '', '', 0)
1560 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiFrequencySelectionCpuPpiGuid', '', '', '', 0)
1561 EotGlobalData.gDb.TblReport.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiCachePpiGuid', '', '', '', 0)
1562
1563 EotGlobalData.gDb.Conn.commit()
1564
1565
1566 ## BuildDatabase() methoc
1567 #
1568 # Build the database for target
1569 #
1570 # @param self: The object pointer
1571 #
1572 def BuildDatabase(self):
1573 # Clean report table
1574 EotGlobalData.gDb.TblReport.Drop()
1575 EotGlobalData.gDb.TblReport.Create()
1576
1577 # Build database
1578 if self.IsInit:
1579 self.BuildMetaDataFileDatabase(EotGlobalData.gINF_FILES)
1580 EdkLogger.quiet("Building database for source code ...")
1581 c.CreateCCodeDB(EotGlobalData.gSOURCE_FILES)
1582 EdkLogger.quiet("Building database for source code done!")
1583
1584 EotGlobalData.gIdentifierTableList = GetTableList((MODEL_FILE_C, MODEL_FILE_H), 'Identifier', EotGlobalData.gDb)
1585
1586 ## BuildMetaDataFileDatabase() method
1587 #
1588 # Build the database for meta data files
1589 #
1590 # @param self: The object pointer
1591 # @param Inf_Files: A list for all INF files
1592 #
1593 def BuildMetaDataFileDatabase(self, Inf_Files):
1594 EdkLogger.quiet("Building database for meta data files ...")
1595 for InfFile in Inf_Files:
1596 if not InfFile:
1597 continue
1598 EdkLogger.quiet("Parsing %s ..." % str(InfFile))
1599 EdkInfParser(InfFile, EotGlobalData.gDb, Inf_Files[InfFile], '')
1600
1601 EotGlobalData.gDb.Conn.commit()
1602 EdkLogger.quiet("Building database for meta data files done!")
1603
1604 ## ParseOption() method
1605 #
1606 # Parse command line options
1607 #
1608 # @param self: The object pointer
1609 #
1610 def ParseOption(self):
1611 (Options, Target) = self.EotOptionParser()
1612
1613 # Set log level
1614 self.SetLogLevel(Options)
1615
1616 if Options.FvFileList:
1617 self.FvFileList = Options.FvFileList
1618
1619 if Options.MapFileList:
1620 self.MapFileList = Options.FvMapFileList
1621
1622 if Options.SourceFileList:
1623 self.SourceFileList = Options.SourceFileList
1624
1625 if Options.IncludeDirList:
1626 self.IncludeDirList = Options.IncludeDirList
1627
1628 if Options.DecFileList:
1629 self.DecFileList = Options.DecFileList
1630
1631 if Options.GuidList:
1632 self.GuidList = Options.GuidList
1633
1634 if Options.LogFile:
1635 self.LogFile = Options.LogFile
1636
1637 if Options.keepdatabase:
1638 self.IsInit = False
1639
1640 ## SetLogLevel() method
1641 #
1642 # Set current log level of the tool based on args
1643 #
1644 # @param self: The object pointer
1645 # @param Option: The option list including log level setting
1646 #
1647 def SetLogLevel(self, Option):
1648 if Option.verbose is not None:
1649 EdkLogger.SetLevel(EdkLogger.VERBOSE)
1650 elif Option.quiet is not None:
1651 EdkLogger.SetLevel(EdkLogger.QUIET)
1652 elif Option.debug is not None:
1653 EdkLogger.SetLevel(Option.debug + 1)
1654 else:
1655 EdkLogger.SetLevel(EdkLogger.INFO)
1656
1657 ## EotOptionParser() method
1658 #
1659 # Using standard Python module optparse to parse command line option of this tool.
1660 #
1661 # @param self: The object pointer
1662 #
1663 # @retval Opt A optparse.Values object containing the parsed options
1664 # @retval Args Target of build command
1665 #
1666 def EotOptionParser(self):
1667 Parser = OptionParser(description = self.Copyright, version = self.Version, prog = "Eot.exe", usage = "%prog [options]")
1668 Parser.add_option("-m", "--makefile filename", action="store", type="string", dest='MakeFile',
1669 help="Specify a makefile for the platform.")
1670 Parser.add_option("-c", "--dsc filename", action="store", type="string", dest="DscFile",
1671 help="Specify a dsc file for the platform.")
1672 Parser.add_option("-f", "--fv filename", action="store", type="string", dest="FvFileList",
1673 help="Specify fv file list, quoted by \"\".")
1674 Parser.add_option("-a", "--map filename", action="store", type="string", dest="MapFileList",
1675 help="Specify map file list, quoted by \"\".")
1676 Parser.add_option("-s", "--source files", action="store", type="string", dest="SourceFileList",
1677 help="Specify source file list by a file")
1678 Parser.add_option("-i", "--include dirs", action="store", type="string", dest="IncludeDirList",
1679 help="Specify include dir list by a file")
1680 Parser.add_option("-e", "--dec files", action="store", type="string", dest="DecFileList",
1681 help="Specify dec file list by a file")
1682 Parser.add_option("-g", "--guid list", action="store", type="string", dest="GuidList",
1683 help="Specify guid file list by a file")
1684 Parser.add_option("-l", "--log filename", action="store", type="string", dest="LogFile",
1685 help="Specify real execution log file")
1686
1687 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.")
1688
1689 Parser.add_option("-q", "--quiet", action="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
1690 Parser.add_option("-v", "--verbose", action="store_true", type=None, help="Turn on verbose output with informational messages printed, "\
1691 "including library instances selected, final dependency expression, "\
1692 "and warning messages, etc.")
1693 Parser.add_option("-d", "--debug", action="store", type="int", help="Enable debug messages at specified level.")
1694
1695 (Opt, Args)=Parser.parse_args()
1696
1697 return (Opt, Args)
1698
1699 ##
1700 #
1701 # This acts like the main() function for the script, unless it is 'import'ed into another
1702 # script.
1703 #
1704 if __name__ == '__main__':
1705 # Initialize log system
1706 EdkLogger.Initialize()
1707 EdkLogger.IsRaiseError = False
1708 EdkLogger.quiet(time.strftime("%H:%M:%S, %b.%d %Y ", time.localtime()) + "[00:00]" + "\n")
1709
1710 StartTime = time.clock()
1711 Eot = Eot(CommandLineOption=False,
1712 SourceFileList=r'C:\TestEot\Source.txt',
1713 GuidList=r'C:\TestEot\Guid.txt',
1714 FvFileList=r'C:\TestEot\FVRECOVERY.Fv')
1715 FinishTime = time.clock()
1716
1717 BuildDuration = time.strftime("%M:%S", time.gmtime(int(round(FinishTime - StartTime))))
1718 EdkLogger.quiet("\n%s [%s]" % (time.strftime("%H:%M:%S, %b.%d %Y", time.localtime()), BuildDuration))