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