2 # This file is used to be the main entrance of EOT tool
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
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.
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
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
39 from GenFds
.AprioriSection
import DXE_APRIORI_GUID
, PEI_APRIORI_GUID
41 gGuidStringFormat
= "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"
45 _HEADER_
= struct
.Struct("")
46 _HEADER_SIZE_
= _HEADER_
.size
48 def __new__(cls
, *args
, **kwargs
):
49 return array
.__new
__(cls
, 'B')
51 def __init__(self
, ID
=None):
53 self
._ID
_ = str(uuid
.uuid1()).upper()
60 self
._SubImages
= sdict() # {offset: Image()}
68 Len
= array
.__len
__(self
)
69 for Offset
in self
._SubImages
.keys():
70 Len
+= len(self
._SubImages
[Offset
])
74 self
.extend(self
._BUF
_[self
._OFF
_ : self
._OFF
_ + self
._LEN
_])
77 def _Pack(self
, PadByte
=0xFF):
78 raise NotImplementedError
80 def frombuffer(self
, Buffer
, Offset
=0, Size
=None):
83 # we may need the Size information in advance if it's given
85 self
._LEN
_ = self
._Unpack
()
90 def GetField(self
, FieldStruct
, Offset
=0):
91 return FieldStruct
.unpack_from(self
, Offset
)
93 def SetField(self
, FieldStruct
, Offset
, *args
):
94 # check if there's enough space
95 Size
= FieldStruct
.size
97 self
.extend([0] * (Size
- len(self
)))
98 FieldStruct
.pack_into(self
, Offset
, *args
)
100 def _SetData(self
, Data
):
101 if len(self
) < self
._HEADER
_SIZE
_:
102 self
.extend([0] * (self
._HEADER
_SIZE
_ - len(self
)))
104 del self
[self
._HEADER
_SIZE
_:]
108 if len(self
) > self
._HEADER
_SIZE
_:
109 return self
[self
._HEADER
_SIZE
_:]
112 Data
= property(_GetData
, _SetData
)
114 ## CompressedImage() class
116 # A class for Compressed Image
118 class CompressedImage(Image
):
119 # UncompressedLength = 4-byte
120 # CompressionType = 1-byte
121 _HEADER_
= struct
.Struct("1I 1B")
122 _HEADER_SIZE_
= _HEADER_
.size
124 _ORIG_SIZE_
= struct
.Struct("1I")
125 _CMPRS_TYPE_
= struct
.Struct("4x 1B")
127 def __init__(self
, CompressedData
=None, CompressionType
=None, UncompressedLength
=None):
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
138 S
= "algorithm=%s uncompressed=%x" % (self
.CompressionType
, self
.UncompressedLength
)
139 for Sec
in self
.Sections
:
144 def _SetOriginalSize(self
, Size
):
145 self
.SetField(self
._ORIG
_SIZE
_, 0, Size
)
147 def _GetOriginalSize(self
):
148 return self
.GetField(self
._ORIG
_SIZE
_)[0]
150 def _SetCompressionType(self
, Type
):
151 self
.SetField(self
._CMPRS
_TYPE
_, 0, Type
)
153 def _GetCompressionType(self
):
154 return self
.GetField(self
._CMPRS
_TYPE
_)[0]
156 def _GetSections(self
):
158 TmpData
= DeCompress('Efi', self
[self
._HEADER
_SIZE
_:])
160 DecData
.fromstring(TmpData
)
162 TmpData
= DeCompress('Framework', self
[self
._HEADER
_SIZE
_:])
164 DecData
.fromstring(TmpData
)
168 while Offset
< len(DecData
):
171 Sec
.frombuffer(DecData
, Offset
)
173 # the section is aligned to 4-byte boundary
176 SectionList
.append(Sec
)
179 UncompressedLength
= property(_GetOriginalSize
, _SetOriginalSize
)
180 CompressionType
= property(_GetCompressionType
, _SetCompressionType
)
181 Sections
= property(_GetSections
)
188 _HEADER_
= struct
.Struct("")
198 # keep header in this Image object
200 self
.extend(self
._BUF
_[self
._OFF
_ : self
._OFF
_ + self
._LEN
_])
203 def _GetUiString(self
):
204 return codecs
.utf_16_decode(self
[0:-2].tostring())[0]
206 String
= property(_GetUiString
)
213 _HEADER_
= struct
.Struct("")
216 _GUID_
= struct
.Struct("1I2H8B")
217 _OPCODE_
= struct
.Struct("1B")
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",
243 0x09 : _OPCODE_
, #"SOR"
253 Indention
= ' ' * gIndention
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]:
261 S
+= ' ' + gGuidStringFormat
% T
+ '\n'
266 # keep header in this Image object
268 self
.extend(self
._BUF
_[self
._OFF
_ : self
._OFF
_ + self
._LEN
_])
271 def _GetExpression(self
):
272 if self
._ExprList
== []:
274 CurrentData
= self
._OPCODE
_
275 while Offset
< len(self
):
276 Token
= CurrentData
.unpack_from(self
, Offset
)
277 Offset
+= CurrentData
.size
280 if Token
in self
._NEXT
_:
281 CurrentData
= self
._NEXT
_[Token
]
283 CurrentData
= self
._GUID
_
285 CurrentData
= self
._OPCODE
_
286 self
._ExprList
.append(Token
)
287 if CurrentData
is None:
289 return self
._ExprList
291 Expression
= property(_GetExpression
)
293 # # FirmwareVolume() class
295 # A class for Firmware Volume
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
302 _FfsGuid
= "8C8CE578-8A3D-4F1C-9935-896185C32DD3"
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")
311 def __init__(self
, Name
=''):
314 self
.FfsDict
= sdict()
315 self
.OrderedFfsDict
= sdict()
316 self
.UnDispatchedFfsDict
= sdict()
317 self
.ProtocolList
= sdict()
319 def CheckArchProtocol(self
):
320 for Item
in EotGlobalData
.gArchProtocolGuids
:
321 if Item
.lower() not in EotGlobalData
.gProtocolList
:
325 def ParseDepex(self
, Depex
, Type
):
328 List
= EotGlobalData
.gPpiList
329 if Type
== 'Protocol':
330 List
= EotGlobalData
.gProtocolList
336 for Index
in range(0, len(Depex
.Expression
)):
337 Item
= Depex
.Expression
[Index
]
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'])
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'])
350 Guid
= gGuidStringFormat
% Depex
.Expression
[Index
]
351 if Guid
.lower() in List
:
352 DepexStack
.append(True)
353 DepexList
.append(Guid
)
355 DepexStack
.append(False)
356 DepexList
.append(Guid
)
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()))
362 DepexStack
.append(eval(Depex
._OPCODE
_STRING
_[Item
].lower() + ' ' + str(DepexStack
.pop())))
363 DepexList
.append(Depex
._OPCODE
_STRING
_[Item
].lower() + ' ' + str(DepexList
.pop()))
365 DepexStack
.append(True)
366 DepexList
.append('TRUE')
367 DepexString
= DepexString
+ 'TRUE' + ' '
369 DepexStack
.append(False)
370 DepexList
.append('False')
371 DepexString
= DepexString
+ 'FALSE' + ' '
373 if Index
!= len(Depex
.Expression
) - 1:
374 CouldBeLoaded
= False
376 CouldBeLoaded
= DepexStack
.pop()
378 CouldBeLoaded
= False
380 DepexString
= DepexList
[0].strip()
381 return (CouldBeLoaded
, DepexString
, FileDepex
)
383 def Dispatch(self
, Db
=None):
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
]
396 FfsSecCoreGuid
= FfsID
399 FfsPeiCoreGuid
= FfsID
402 FfsDxeCoreGuid
= FfsID
404 if Ffs
.Guid
.lower() == PEI_APRIORI_GUID
.lower():
405 FfsPeiPrioriGuid
= FfsID
407 if Ffs
.Guid
.lower() == DXE_APRIORI_GUID
.lower():
408 FfsDxePrioriGuid
= FfsID
411 # Parse SEC_CORE first
412 if FfsSecCoreGuid
is not None:
413 self
.OrderedFfsDict
[FfsSecCoreGuid
] = self
.UnDispatchedFfsDict
.pop(FfsSecCoreGuid
)
414 self
.LoadPpi(Db
, FfsSecCoreGuid
)
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')
428 while len(Section
) > Start
:
429 Guid
= GuidStruct
.unpack_from(Section
[Start
: Start
+ 16])
430 GuidString
= gGuidStringFormat
% Guid
432 if GuidString
in self
.UnDispatchedFfsDict
:
433 self
.OrderedFfsDict
[GuidString
] = self
.UnDispatchedFfsDict
.pop(GuidString
)
434 self
.LoadPpi(Db
, GuidString
)
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')
450 while len(Section
) > Start
:
451 Guid
= GuidStruct
.unpack_from(Section
[Start
: Start
+ 16])
452 GuidString
= gGuidStringFormat
% Guid
454 if GuidString
in self
.UnDispatchedFfsDict
:
455 self
.OrderedFfsDict
[GuidString
] = self
.UnDispatchedFfsDict
.pop(GuidString
)
456 self
.LoadProtocol(Db
, GuidString
)
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)
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
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
481 EotGlobalData
.gProtocolList
[Record
[0].lower()] = ModuleGuid
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)
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
496 def DisPatchDxe(self
, Db
):
498 ScheduleList
= sdict()
499 for FfsID
in self
.UnDispatchedFfsDict
.keys():
500 CouldBeLoaded
= False
503 Ffs
= self
.UnDispatchedFfsDict
[FfsID
]
507 for Section
in Ffs
.Sections
.values():
509 if Section
.Type
== 0x13:
511 CouldBeLoaded
, DepexString
, FileDepex
= self
.ParseDepex(Section
._SubImages
[4], 'Protocol')
513 if Section
.Type
== 0x01:
514 CompressSections
= Section
._SubImages
[4]
515 for CompressSection
in CompressSections
.Sections
:
516 if CompressSection
.Type
== 0x13:
518 CouldBeLoaded
, DepexString
, FileDepex
= self
.ParseDepex(CompressSection
._SubImages
[4], 'Protocol')
520 if CompressSection
.Type
== 0x02:
521 NewSections
= CompressSection
._SubImages
[4]
522 for NewSection
in NewSections
.Sections
:
523 if NewSection
.Type
== 0x13:
525 CouldBeLoaded
, DepexString
, FileDepex
= self
.ParseDepex(NewSection
._SubImages
[4], 'Protocol')
530 CouldBeLoaded
= self
.CheckArchProtocol()
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])
542 ScheduleList
[FfsID
] = NewFfs
544 self
.UnDispatchedFfsDict
[FfsID
].Depex
= DepexString
546 for FfsID
in ScheduleList
.keys():
547 NewFfs
= ScheduleList
.pop(FfsID
)
549 self
.OrderedFfsDict
[FfsID
] = NewFfs
550 self
.LoadProtocol(Db
, FfsID
)
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
)
557 FfsName
= RecordSet
[0][0]
562 def DisPatchPei(self
, Db
):
564 for FfsID
in self
.UnDispatchedFfsDict
.keys():
568 Ffs
= self
.UnDispatchedFfsDict
[FfsID
]
569 if Ffs
.Type
== 0x06 or Ffs
.Type
== 0x08:
571 for Section
in Ffs
.Sections
.values():
572 if Section
.Type
== 0x1B:
573 CouldBeLoaded
, DepexString
, FileDepex
= self
.ParseDepex(Section
._SubImages
[4], 'Ppi')
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')
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')
591 NewFfs
= self
.UnDispatchedFfsDict
.pop(FfsID
)
592 NewFfs
.Depex
= DepexString
593 self
.OrderedFfsDict
[FfsID
] = NewFfs
594 self
.LoadPpi(Db
, FfsID
)
596 self
.UnDispatchedFfsDict
[FfsID
].Depex
= DepexString
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
])
609 return FvInfo
+ FfsInfo
612 Size
= self
._LENGTH
_.unpack_from(self
._BUF
_, self
._OFF
_)[0]
614 self
.extend(self
._BUF
_[self
._OFF
_:self
._OFF
_ + Size
])
618 FfsStartAddress
= self
.HeaderSize
620 while FfsStartAddress
< EndOfFv
:
622 FfsObj
.frombuffer(self
, FfsStartAddress
)
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
)
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
)
638 FfsStartAddress
+= len(FfsObj
)
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
643 FfsStartAddress
= (FfsStartAddress
+ 7) & (~
7)
646 def _GetAttributes(self
):
647 return self
.GetField(self
._ATTR
_, 0)[0]
650 return self
.GetField(self
._LENGTH
_, 0)[0]
652 def _GetChecksum(self
):
653 return self
.GetField(self
._CHECKSUM
_, 0)[0]
655 def _GetHeaderLength(self
):
656 return self
.GetField(self
._HLEN
_, 0)[0]
658 def _GetFileSystemGuid(self
):
659 return gGuidStringFormat
% self
.GetField(self
._GUID
_, 0)
661 Attributes
= property(_GetAttributes
)
662 Size
= property(_GetSize
)
663 Checksum
= property(_GetChecksum
)
664 HeaderSize
= property(_GetHeaderLength
)
665 FileSystemGuid
= property(_GetFileSystemGuid
)
667 ## GuidDefinedImage() class
669 # A class for GUID Defined Image
671 class GuidDefinedImage(Image
):
672 _HEADER_
= struct
.Struct("1I2H8B 1H 1H")
673 _HEADER_SIZE_
= _HEADER_
.size
675 _GUID_
= struct
.Struct("1I2H8B")
676 _DATA_OFFSET_
= struct
.Struct("16x 1H")
677 _ATTR_
= struct
.Struct("18x 1H")
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'
683 def __init__(self
, SectionDefinitionGuid
=None, DataOffset
=None, Attributes
=None, Data
=None):
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
695 S
= "guid=%s" % (gGuidStringFormat
% self
.SectionDefinitionGuid
)
696 for Sec
in self
.Sections
:
701 # keep header in this Image object
703 self
.extend(self
._BUF
_[self
._OFF
_ : self
._OFF
_ + self
._LEN
_])
706 def _SetAttribute(self
, Attribute
):
707 self
.SetField(self
._ATTR
_, 0, Attribute
)
709 def _GetAttribute(self
):
710 return self
.GetField(self
._ATTR
_)[0]
712 def _SetGuid(self
, Guid
):
713 self
.SetField(self
._GUID
_, 0, Guid
)
716 return self
.GetField(self
._GUID
_)
718 def _SetDataOffset(self
, Offset
):
719 self
.SetField(self
._DATA
_OFFSET
_, 0, Offset
)
721 def _GetDataOffset(self
):
722 return self
.GetField(self
._DATA
_OFFSET
_)[0]
724 def _GetSections(self
):
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
):
733 Sec
.frombuffer(self
, Offset
)
735 # the section is aligned to 4-byte boundary
736 Offset
= (Offset
+ 3) & (~
3)
739 SectionList
.append(Sec
)
740 elif Guid
== self
.TIANO_COMPRESS_GUID
:
743 Offset
= self
.DataOffset
- 4
744 TmpData
= DeCompress('Framework', self
[self
.Offset
:])
746 DecData
.fromstring(TmpData
)
748 while Offset
< len(DecData
):
751 Sec
.frombuffer(DecData
, Offset
)
753 # the section is aligned to 4-byte boundary
754 Offset
= (Offset
+ 3) & (~
3)
757 SectionList
.append(Sec
)
760 elif Guid
== self
.LZMA_COMPRESS_GUID
:
763 Offset
= self
.DataOffset
- 4
765 TmpData
= DeCompress('Lzma', self
[self
.Offset
:])
767 DecData
.fromstring(TmpData
)
769 while Offset
< len(DecData
):
772 Sec
.frombuffer(DecData
, Offset
)
774 # the section is aligned to 4-byte boundary
775 Offset
= (Offset
+ 3) & (~
3)
778 SectionList
.append(Sec
)
784 Attributes
= property(_GetAttribute
, _SetAttribute
)
785 SectionDefinitionGuid
= property(_GetGuid
, _SetGuid
)
786 DataOffset
= property(_GetDataOffset
, _SetDataOffset
)
787 Sections
= property(_GetSections
)
791 # A class for Section
793 class Section(Image
):
796 0x01 : "COMPRESSION",
797 0x02 : "GUID_DEFINED",
803 0x15 : "USER_INTERFACE",
804 0x16 : "COMPATIBILITY16",
805 0x17 : "FIRMWARE_VOLUME_IMAGE",
806 0x18 : "FREEFORM_SUBTYPE_GUID",
811 _SectionSubImages
= {
812 0x01 : CompressedImage
,
813 0x02 : GuidDefinedImage
,
814 0x17 : FirmwareVolume
,
822 _HEADER_
= struct
.Struct("3B 1B")
823 _HEADER_SIZE_
= _HEADER_
.size
826 # _FREE_FORM_SUBTYPE_GUID_HEADER_ = struct.Struct("1I2H8B")
827 _SIZE_
= struct
.Struct("3B")
828 _TYPE_
= struct
.Struct("3x 1B")
830 def __init__(self
, Type
=None, Size
=None):
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
)
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
])
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)
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
])
861 # keep header in this Image object
862 self
.extend(self
._BUF
_[self
._OFF
_ : self
._OFF
_ + self
._HEADER
_SIZE
_])
864 # use new Image object to represent payload, which may be another kind
865 # of image such as PE32
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
875 def _SetSize(self
, Size
):
877 Size2
= (Size
& 0xFF00) >> 8
878 Size3
= (Size
& 0xFF0000) >> 16
879 self
.SetField(self
._SIZE
_, 0, Size1
, Size2
, Size3
)
882 Size1
, Size2
, Size3
= self
.GetField(self
._SIZE
_)
883 return Size1
+ (Size2
<< 8) + (Size3
<< 16)
885 def _SetType(self
, Type
):
886 self
.SetField(self
._TYPE
_, 0, Type
)
889 return self
.GetField(self
._TYPE
_)[0]
891 def _GetAlignment(self
):
892 return self
._Alignment
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:
901 NewOffset
= (PayloadOffset
+ AlignmentMask
) & (~AlignmentMask
)
902 while (NewOffset
- PayloadOffset
) < self
._HEADER
_SIZE
_:
903 NewOffset
+= self
._Alignment
906 self
.Size
= len(self
)
907 Image
.tofile(self
, f
)
908 for Offset
in self
._SubImages
:
909 self
._SubImages
[Offset
].tofile(f
)
911 Type
= property(_GetType
, _SetType
)
912 Size
= property(_GetSize
, _SetSize
)
913 Alignment
= property(_GetAlignment
, _SetAlignment
)
917 # A class for Ffs Section
920 _FfsFormat
= "24B%(payload_size)sB"
921 # skip IntegrityCheck
922 _HEADER_
= struct
.Struct("1I2H8B 2x 1B 1B 3B 1B")
923 _HEADER_SIZE_
= _HEADER_
.size
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")
932 FFS_ATTRIB_FIXED
= 0x04
933 FFS_ATTRIB_DATA_ALIGNMENT
= 0x38
934 FFS_ATTRIB_CHECKSUM
= 0x40
940 0x03 : "SECURITY_CORE",
945 0x08 : "COMBINED_PEIM_DRIVER",
946 0x09 : "APPLICATION",
948 0x0B : "FIRMWARE_VOLUME_IMAGE",
949 0x0C : "COMBINED_SMM_DXE",
951 0x0E : "MM_STANDALONE",
952 0x0F : "MM_CORE_STANDALONE",
966 self
.Sections
= sdict()
974 Indention
= ' ' * gIndention
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()])
980 return FfsInfo
+ SectionInfo
+ "\n"
989 Size1
, Size2
, Size3
= self
._SIZE
_.unpack_from(self
._BUF
_, self
._OFF
_)
990 Size
= Size1
+ (Size2
<< 8) + (Size3
<< 16)
992 self
.extend(self
._BUF
_[self
._OFF
_ : self
._OFF
_ + Size
])
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()
998 self
.__ID
__ = self
.Guid
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:
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)
1011 self
.Sections
[SectionStartAddress
] = SectionObj
1012 SectionStartAddress
+= len(SectionObj
)
1013 SectionStartAddress
= (SectionStartAddress
+ 3) & (~
3)
1018 def SetFreeSpace(self
, Size
):
1019 self
.FreeSpace
= Size
1022 return gGuidStringFormat
% self
.Name
1024 def _SetName(self
, Value
):
1025 # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
1026 self
.SetField(self
._NAME
_, 0, Value
)
1029 # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
1030 return self
.GetField(self
._NAME
_)
1032 def _SetSize(self
, Size
):
1034 Size2
= (Size
& 0xFF00) >> 8
1035 Size3
= (Size
& 0xFF0000) >> 16
1036 self
.SetField(self
._SIZE
_, 0, Size1
, Size2
, Size3
)
1039 Size1
, Size2
, Size3
= self
.GetField(self
._SIZE
_)
1040 return Size1
+ (Size2
<< 8) + (Size3
<< 16)
1042 def _SetType(self
, Type
):
1043 self
.SetField(self
._TYPE
_, 0, Type
)
1046 return self
.GetField(self
._TYPE
_)[0]
1048 def _SetAttributes(self
, Value
):
1049 self
.SetField(self
._ATTR
_, 0, Value
)
1051 def _GetAttributes(self
):
1052 return self
.GetField(self
._ATTR
_)[0]
1054 def _GetFixed(self
):
1055 if (self
.Attributes
& self
.FFS_ATTRIB_FIXED
) != 0:
1059 def _GetCheckSum(self
):
1060 if (self
.Attributes
& self
.FFS_ATTRIB_CHECKSUM
) != 0:
1064 def _GetAlignment(self
):
1065 return (self
.Attributes
& self
.FFS_ATTRIB_DATA_ALIGNMENT
) >> 3
1067 def _SetState(self
, Value
):
1068 self
.SetField(self
._STATE
_, 0, Value
)
1070 def _GetState(self
):
1071 return self
.GetField(self
._STATE
_)[0]
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
)
1084 ## MultipleFv() class
1086 # A class for Multiple FV
1088 class MultipleFv(FirmwareVolume
):
1089 def __init__(self
, FvList
):
1090 FirmwareVolume
.__init
__(self
)
1092 for FvPath
in FvList
:
1094 FvName
= os
.path
.splitext(os
.path
.split(FvPath
)[1])[0]
1096 Fd
= open(FvPath
, 'rb')
1099 Buf
.fromfile(Fd
, os
.path
.getsize(FvPath
))
1103 Fv
= FirmwareVolume(FvName
)
1104 Fv
.frombuffer(Buf
, 0, len(Buf
))
1106 self
.BasicInfo
.append([Fv
.Name
, Fv
.FileSystemGuid
, Fv
.Size
])
1107 self
.FfsDict
.append(Fv
.FfsDict
)
1111 # This class is used to define Eot main entrance
1113 # @param object: Inherited from object class
1118 # @param self: The object pointer
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
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
1139 # Check workspace environment
1140 if "EFI_SOURCE" not in os
.environ
:
1141 if "EDK_SOURCE" not in os
.environ
:
1144 EotGlobalData
.gEDK_SOURCE
= os
.path
.normpath(os
.getenv("EDK_SOURCE"))
1146 EotGlobalData
.gEFI_SOURCE
= os
.path
.normpath(os
.getenv("EFI_SOURCE"))
1147 EotGlobalData
.gEDK_SOURCE
= os
.path
.join(EotGlobalData
.gEFI_SOURCE
, 'Edk')
1149 if "WORKSPACE" not in os
.environ
:
1150 EdkLogger
.error("EOT", BuildToolError
.ATTRIBUTE_NOT_AVAILABLE
, "Environment variable not found",
1151 ExtraData
="WORKSPACE")
1153 EotGlobalData
.gWORKSPACE
= os
.path
.normpath(os
.getenv("WORKSPACE"))
1155 EotGlobalData
.gMACRO
['WORKSPACE'] = EotGlobalData
.gWORKSPACE
1156 EotGlobalData
.gMACRO
['EFI_SOURCE'] = EotGlobalData
.gEFI_SOURCE
1157 EotGlobalData
.gMACRO
['EDK_SOURCE'] = EotGlobalData
.gEDK_SOURCE
1159 # Parse the options and args
1160 if CommandLineOption
:
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
)
1170 EdkLogger
.error("Eot", EdkLogger
.EOT_ERROR
, "The fv file list of target platform was not specified")
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
)
1179 # Generate source file list
1180 self
.GenerateSourceFileList(self
.SourceFileList
, self
.IncludeDirList
)
1182 # Generate guid list of dec file list
1183 self
.ParseDecFile(self
.DecFileList
)
1185 # Generate guid list from GUID list file
1186 self
.ParseGuidList(self
.GuidList
)
1189 EotGlobalData
.gDb
= Database
.Database(Database
.DATABASE_PATH
)
1190 EotGlobalData
.gDb
.InitDatabase(self
.IsInit
)
1192 # Build ECC database
1193 self
.BuildDatabase()
1195 # Parse Ppi/Protocol
1196 self
.ParseExecutionOrder()
1198 # Merge Identifier tables
1199 self
.GenerateQueryTable()
1201 # Generate report database
1202 self
.GenerateReportDatabase()
1211 self
.GenerateReport()
1214 self
.ConvertLogFile(self
.LogFile
)
1217 EdkLogger
.quiet("EOT FINISHED!")
1220 EotGlobalData
.gDb
.Close()
1222 ## ParseDecFile() method
1224 # parse DEC file and get all GUID names with GUID values as {GuidName : GuidValue}
1225 # The Dict is stored in EotGlobalData.gGuidDict
1227 # @param self: The object pointer
1228 # @param DecFileList: A list of all DEC files
1230 def ParseDecFile(self
, DecFileList
):
1232 path
= os
.path
.normpath(DecFileList
)
1233 lfr
= open(path
, 'rb')
1235 path
= os
.path
.normpath(os
.path
.join(EotGlobalData
.gWORKSPACE
, line
.strip()))
1236 if os
.path
.exists(path
):
1237 dfr
= open(path
, 'rb')
1239 line
= CleanString(line
)
1240 list = line
.split('=')
1242 EotGlobalData
.gGuidDict
[list[0].strip()] = GuidStructureStringToGuidString(list[1].strip())
1245 ## ParseGuidList() method
1247 # Parse Guid list and get all GUID names with GUID values as {GuidName : GuidValue}
1248 # The Dict is stored in EotGlobalData.gGuidDict
1250 # @param self: The object pointer
1251 # @param GuidList: A list of all GUID and its value
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
):
1258 (GuidName
, GuidValue
) = Line
.split()
1259 EotGlobalData
.gGuidDict
[GuidName
] = GuidValue
1261 ## ConvertLogFile() method
1263 # Parse a real running log file to get real dispatch order
1264 # The result is saved to old file name + '.new'
1266 # @param self: The object pointer
1267 # @param LogFile: A real running log file name
1269 def ConvertLogFile(self
, LogFile
):
1274 lfr
= open(LogFile
, 'rb')
1275 lfw
= open(LogFile
+ '.new', 'wb')
1278 line
= line
.replace('.efi', '')
1279 index
= line
.find("Loading PEIM at ")
1281 newline
.append(line
[index
+ 55 : ])
1283 index
= line
.find("Loading driver at ")
1285 newline
.append(line
[index
+ 57 : ])
1288 for line
in newline
:
1289 lfw
.write(line
+ '\r\n')
1296 ## GenerateSourceFileList() method
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
1306 # @param self: The object pointer
1307 # @param SourceFileList: A list of all source files
1308 # @param IncludeFileList: A list of all include files
1310 def GenerateSourceFileList(self
, SourceFileList
, IncludeFileList
):
1311 EdkLogger
.quiet("Generating source files list ... ")
1312 mSourceFileList
= []
1316 mCurrentInfFile
= ''
1317 mCurrentSourceFileList
= []
1320 sfl
= open(SourceFileList
, 'r')
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
1337 # Get all include files from packages
1339 ifl
= open(IncludeFileList
, 'rb')
1341 if not line
.strip():
1343 newline
= os
.path
.normpath(os
.path
.join(EotGlobalData
.gWORKSPACE
, line
.strip()))
1344 for Root
, Dirs
, Files
in os
.walk(str(newline
)):
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
)
1353 EotGlobalData
.gSOURCE_FILES
= mSourceFileList
1354 EotGlobalData
.gOP_SOURCE_FILES
.close()
1356 EotGlobalData
.gINF_FILES
= mFileList
1357 EotGlobalData
.gOP_INF
.close()
1359 ## GenerateReport() method
1361 # Generate final HTML report
1363 # @param self: The object pointer
1365 def GenerateReport(self
):
1366 EdkLogger
.quiet("Generating report file ... ")
1367 Rep
= Report(self
.Report
, EotGlobalData
.gFV
, self
.Dispatch
)
1368 Rep
.GenerateReport()
1370 ## LoadMapInfo() method
1372 # Load map files and parse them
1374 # @param self: The object pointer
1376 def LoadMapInfo(self
):
1377 if EotGlobalData
.gMAP_FILE
!= []:
1378 EdkLogger
.quiet("Parsing Map file ... ")
1379 EotGlobalData
.gMap
= ParseMapFile(EotGlobalData
.gMAP_FILE
)
1381 ## LoadFvInfo() method
1383 # Load FV binary files and parse them
1385 # @param self: The object pointer
1387 def LoadFvInfo(self
):
1388 EdkLogger
.quiet("Parsing FV file ... ")
1389 EotGlobalData
.gFV
= MultipleFv(EotGlobalData
.gFV_FILE
)
1390 EotGlobalData
.gFV
.Dispatch(EotGlobalData
.gDb
)
1392 for Protocol
in EotGlobalData
.gProtocolList
:
1393 EotGlobalData
.gOP_UN_MATCHED_IN_LIBRARY_CALLING
.write('%s\n' %Protocol
)
1395 ## GenerateReportDatabase() method
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
1401 # @param self: The object pointer
1403 def GenerateReportDatabase(self
):
1404 EdkLogger
.quiet("Generating the cross-reference table of GUID for Ppi/Protocol ... ")
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]
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
)
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
:
1428 GuidMacro
= GuidMacroSet
[0][0].strip()
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
)
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
1452 ## GenerateQueryTable() method
1454 # Generate two tables improve query performance
1456 # @param self: The object pointer
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
)
1470 ## ParseExecutionOrder() method
1472 # Get final execution order
1474 # 2. Search all PROTOCOL
1476 # @param self: The object pointer
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
1484 SourceFileID
= Identifier
[0].replace('Identifier', '')
1485 SourceFileFullPath
= Identifier
[1]
1486 Identifier
= Identifier
[0]
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
)
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)
1501 SearchPpiCallFunction(Identifier
, SourceFileID
, SourceFileFullPath
, ItemMode
)
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
)
1509 SearchFunctionCalling(Identifier
, SourceFileID
, SourceFileFullPath
, 'Ppi', ItemMode
)
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
)
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)
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)
1529 SearchFunctionCalling(Identifier
, SourceFileID
, SourceFileFullPath
, 'Protocol', ItemMode
)
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)
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)
1542 SearchFunctionCalling(Identifier
, SourceFileID
, SourceFileFullPath
, 'Protocol', ItemMode
)
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)
1550 SearchFunctionCalling(Identifier
, SourceFileID
, SourceFileFullPath
, 'Protocol', ItemMode
)
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)
1563 EotGlobalData
.gDb
.Conn
.commit()
1566 ## BuildDatabase() methoc
1568 # Build the database for target
1570 # @param self: The object pointer
1572 def BuildDatabase(self
):
1573 # Clean report table
1574 EotGlobalData
.gDb
.TblReport
.Drop()
1575 EotGlobalData
.gDb
.TblReport
.Create()
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!")
1584 EotGlobalData
.gIdentifierTableList
= GetTableList((MODEL_FILE_C
, MODEL_FILE_H
), 'Identifier', EotGlobalData
.gDb
)
1586 ## BuildMetaDataFileDatabase() method
1588 # Build the database for meta data files
1590 # @param self: The object pointer
1591 # @param Inf_Files: A list for all INF files
1593 def BuildMetaDataFileDatabase(self
, Inf_Files
):
1594 EdkLogger
.quiet("Building database for meta data files ...")
1595 for InfFile
in Inf_Files
:
1598 EdkLogger
.quiet("Parsing %s ..." % str(InfFile
))
1599 EdkInfParser(InfFile
, EotGlobalData
.gDb
, Inf_Files
[InfFile
], '')
1601 EotGlobalData
.gDb
.Conn
.commit()
1602 EdkLogger
.quiet("Building database for meta data files done!")
1604 ## ParseOption() method
1606 # Parse command line options
1608 # @param self: The object pointer
1610 def ParseOption(self
):
1611 (Options
, Target
) = self
.EotOptionParser()
1614 self
.SetLogLevel(Options
)
1616 if Options
.FvFileList
:
1617 self
.FvFileList
= Options
.FvFileList
1619 if Options
.MapFileList
:
1620 self
.MapFileList
= Options
.FvMapFileList
1622 if Options
.SourceFileList
:
1623 self
.SourceFileList
= Options
.SourceFileList
1625 if Options
.IncludeDirList
:
1626 self
.IncludeDirList
= Options
.IncludeDirList
1628 if Options
.DecFileList
:
1629 self
.DecFileList
= Options
.DecFileList
1631 if Options
.GuidList
:
1632 self
.GuidList
= Options
.GuidList
1635 self
.LogFile
= Options
.LogFile
1637 if Options
.keepdatabase
:
1640 ## SetLogLevel() method
1642 # Set current log level of the tool based on args
1644 # @param self: The object pointer
1645 # @param Option: The option list including log level setting
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)
1655 EdkLogger
.SetLevel(EdkLogger
.INFO
)
1657 ## EotOptionParser() method
1659 # Using standard Python module optparse to parse command line option of this tool.
1661 # @param self: The object pointer
1663 # @retval Opt A optparse.Values object containing the parsed options
1664 # @retval Args Target of build command
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")
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.")
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.")
1695 (Opt
, Args
)=Parser
.parse_args()
1701 # This acts like the main() function for the script, unless it is 'import'ed into another
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")
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()
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
))