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
25 from collections
import OrderedDict
as sdict
26 from Eot
.Parser
import *
27 from Eot
.InfParserLite
import EdkInfParser
28 from Common
.StringUtils
import GetSplitValueList
30 from Eot
import Database
31 from array
import array
32 from Eot
.Report
import Report
33 from Common
.BuildVersion
import gBUILD_VERSION
34 from Eot
.Parser
import ConvertGuid
35 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
40 from GenFds
.AprioriSection
import DXE_APRIORI_GUID
, PEI_APRIORI_GUID
42 gGuidStringFormat
= "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"
46 _HEADER_
= struct
.Struct("")
47 _HEADER_SIZE_
= _HEADER_
.size
49 def __new__(cls
, *args
, **kwargs
):
50 return array
.__new
__(cls
, 'B')
52 def __init__(self
, ID
=None):
54 self
._ID
_ = str(uuid
.uuid1()).upper()
61 self
._SubImages
= sdict() # {offset: Image()}
69 Len
= array
.__len
__(self
)
70 for Offset
in self
._SubImages
.keys():
71 Len
+= len(self
._SubImages
[Offset
])
75 self
.extend(self
._BUF
_[self
._OFF
_ : self
._OFF
_ + self
._LEN
_])
78 def _Pack(self
, PadByte
=0xFF):
79 raise NotImplementedError
81 def frombuffer(self
, Buffer
, Offset
=0, Size
=None):
84 # we may need the Size information in advance if it's given
86 self
._LEN
_ = self
._Unpack
()
91 def GetField(self
, FieldStruct
, Offset
=0):
92 return FieldStruct
.unpack_from(self
, Offset
)
94 def SetField(self
, FieldStruct
, Offset
, *args
):
95 # check if there's enough space
96 Size
= FieldStruct
.size
98 self
.extend([0] * (Size
- len(self
)))
99 FieldStruct
.pack_into(self
, Offset
, *args
)
101 def _SetData(self
, Data
):
102 if len(self
) < self
._HEADER
_SIZE
_:
103 self
.extend([0] * (self
._HEADER
_SIZE
_ - len(self
)))
105 del self
[self
._HEADER
_SIZE
_:]
109 if len(self
) > self
._HEADER
_SIZE
_:
110 return self
[self
._HEADER
_SIZE
_:]
113 Data
= property(_GetData
, _SetData
)
115 ## CompressedImage() class
117 # A class for Compressed Image
119 class CompressedImage(Image
):
120 # UncompressedLength = 4-byte
121 # CompressionType = 1-byte
122 _HEADER_
= struct
.Struct("1I 1B")
123 _HEADER_SIZE_
= _HEADER_
.size
125 _ORIG_SIZE_
= struct
.Struct("1I")
126 _CMPRS_TYPE_
= struct
.Struct("4x 1B")
128 def __init__(self
, CompressedData
=None, CompressionType
=None, UncompressedLength
=None):
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
139 S
= "algorithm=%s uncompressed=%x" % (self
.CompressionType
, self
.UncompressedLength
)
140 for Sec
in self
.Sections
:
145 def _SetOriginalSize(self
, Size
):
146 self
.SetField(self
._ORIG
_SIZE
_, 0, Size
)
148 def _GetOriginalSize(self
):
149 return self
.GetField(self
._ORIG
_SIZE
_)[0]
151 def _SetCompressionType(self
, Type
):
152 self
.SetField(self
._CMPRS
_TYPE
_, 0, Type
)
154 def _GetCompressionType(self
):
155 return self
.GetField(self
._CMPRS
_TYPE
_)[0]
157 def _GetSections(self
):
159 TmpData
= DeCompress('Efi', self
[self
._HEADER
_SIZE
_:])
161 DecData
.fromstring(TmpData
)
163 TmpData
= DeCompress('Framework', self
[self
._HEADER
_SIZE
_:])
165 DecData
.fromstring(TmpData
)
169 while Offset
< len(DecData
):
172 Sec
.frombuffer(DecData
, Offset
)
174 # the section is aligned to 4-byte boundary
177 SectionList
.append(Sec
)
180 UncompressedLength
= property(_GetOriginalSize
, _SetOriginalSize
)
181 CompressionType
= property(_GetCompressionType
, _SetCompressionType
)
182 Sections
= property(_GetSections
)
189 _HEADER_
= struct
.Struct("")
199 # keep header in this Image object
201 self
.extend(self
._BUF
_[self
._OFF
_ : self
._OFF
_ + self
._LEN
_])
204 def _GetUiString(self
):
205 return codecs
.utf_16_decode(self
[0:-2].tostring())[0]
207 String
= property(_GetUiString
)
214 _HEADER_
= struct
.Struct("")
217 _GUID_
= struct
.Struct("1I2H8B")
218 _OPCODE_
= struct
.Struct("1B")
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",
244 0x09 : _OPCODE_
, #"SOR"
254 Indention
= ' ' * gIndention
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]:
262 S
+= ' ' + gGuidStringFormat
% T
+ '\n'
267 # keep header in this Image object
269 self
.extend(self
._BUF
_[self
._OFF
_ : self
._OFF
_ + self
._LEN
_])
272 def _GetExpression(self
):
273 if self
._ExprList
== []:
275 CurrentData
= self
._OPCODE
_
276 while Offset
< len(self
):
277 Token
= CurrentData
.unpack_from(self
, Offset
)
278 Offset
+= CurrentData
.size
281 if Token
in self
._NEXT
_:
282 CurrentData
= self
._NEXT
_[Token
]
284 CurrentData
= self
._GUID
_
286 CurrentData
= self
._OPCODE
_
287 self
._ExprList
.append(Token
)
288 if CurrentData
is None:
290 return self
._ExprList
292 Expression
= property(_GetExpression
)
294 # # FirmwareVolume() class
296 # A class for Firmware Volume
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
303 _FfsGuid
= "8C8CE578-8A3D-4F1C-9935-896185C32DD3"
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")
312 def __init__(self
, Name
=''):
315 self
.FfsDict
= sdict()
316 self
.OrderedFfsDict
= sdict()
317 self
.UnDispatchedFfsDict
= sdict()
318 self
.ProtocolList
= sdict()
320 def CheckArchProtocol(self
):
321 for Item
in EotGlobalData
.gArchProtocolGuids
:
322 if Item
.lower() not in EotGlobalData
.gProtocolList
:
326 def ParseDepex(self
, Depex
, Type
):
329 List
= EotGlobalData
.gPpiList
330 if Type
== 'Protocol':
331 List
= EotGlobalData
.gProtocolList
337 for Index
in range(0, len(Depex
.Expression
)):
338 Item
= Depex
.Expression
[Index
]
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'])
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'])
351 Guid
= gGuidStringFormat
% Depex
.Expression
[Index
]
352 if Guid
.lower() in List
:
353 DepexStack
.append(True)
354 DepexList
.append(Guid
)
356 DepexStack
.append(False)
357 DepexList
.append(Guid
)
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()))
363 DepexStack
.append(eval(Depex
._OPCODE
_STRING
_[Item
].lower() + ' ' + str(DepexStack
.pop())))
364 DepexList
.append(Depex
._OPCODE
_STRING
_[Item
].lower() + ' ' + str(DepexList
.pop()))
366 DepexStack
.append(True)
367 DepexList
.append('TRUE')
368 DepexString
= DepexString
+ 'TRUE' + ' '
370 DepexStack
.append(False)
371 DepexList
.append('False')
372 DepexString
= DepexString
+ 'FALSE' + ' '
374 if Index
!= len(Depex
.Expression
) - 1:
375 CouldBeLoaded
= False
377 CouldBeLoaded
= DepexStack
.pop()
379 CouldBeLoaded
= False
381 DepexString
= DepexList
[0].strip()
382 return (CouldBeLoaded
, DepexString
, FileDepex
)
384 def Dispatch(self
, Db
=None):
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 list(self
.UnDispatchedFfsDict
.keys()):
395 Ffs
= self
.UnDispatchedFfsDict
[FfsID
]
397 FfsSecCoreGuid
= FfsID
400 FfsPeiCoreGuid
= FfsID
403 FfsDxeCoreGuid
= FfsID
405 if Ffs
.Guid
.lower() == PEI_APRIORI_GUID
.lower():
406 FfsPeiPrioriGuid
= FfsID
408 if Ffs
.Guid
.lower() == DXE_APRIORI_GUID
.lower():
409 FfsDxePrioriGuid
= FfsID
412 # Parse SEC_CORE first
413 if FfsSecCoreGuid
is not None:
414 self
.OrderedFfsDict
[FfsSecCoreGuid
] = self
.UnDispatchedFfsDict
.pop(FfsSecCoreGuid
)
415 self
.LoadPpi(Db
, FfsSecCoreGuid
)
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')
429 while len(Section
) > Start
:
430 Guid
= GuidStruct
.unpack_from(Section
[Start
: Start
+ 16])
431 GuidString
= gGuidStringFormat
% Guid
433 if GuidString
in self
.UnDispatchedFfsDict
:
434 self
.OrderedFfsDict
[GuidString
] = self
.UnDispatchedFfsDict
.pop(GuidString
)
435 self
.LoadPpi(Db
, GuidString
)
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')
451 while len(Section
) > Start
:
452 Guid
= GuidStruct
.unpack_from(Section
[Start
: Start
+ 16])
453 GuidString
= gGuidStringFormat
% Guid
455 if GuidString
in self
.UnDispatchedFfsDict
:
456 self
.OrderedFfsDict
[GuidString
] = self
.UnDispatchedFfsDict
.pop(GuidString
)
457 self
.LoadProtocol(Db
, GuidString
)
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)
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
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
482 EotGlobalData
.gProtocolList
[Record
[0].lower()] = ModuleGuid
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)
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
497 def DisPatchDxe(self
, Db
):
499 ScheduleList
= sdict()
500 for FfsID
in list(self
.UnDispatchedFfsDict
.keys()):
501 CouldBeLoaded
= False
504 Ffs
= self
.UnDispatchedFfsDict
[FfsID
]
508 for Section
in Ffs
.Sections
.values():
510 if Section
.Type
== 0x13:
512 CouldBeLoaded
, DepexString
, FileDepex
= self
.ParseDepex(Section
._SubImages
[4], 'Protocol')
514 if Section
.Type
== 0x01:
515 CompressSections
= Section
._SubImages
[4]
516 for CompressSection
in CompressSections
.Sections
:
517 if CompressSection
.Type
== 0x13:
519 CouldBeLoaded
, DepexString
, FileDepex
= self
.ParseDepex(CompressSection
._SubImages
[4], 'Protocol')
521 if CompressSection
.Type
== 0x02:
522 NewSections
= CompressSection
._SubImages
[4]
523 for NewSection
in NewSections
.Sections
:
524 if NewSection
.Type
== 0x13:
526 CouldBeLoaded
, DepexString
, FileDepex
= self
.ParseDepex(NewSection
._SubImages
[4], 'Protocol')
531 CouldBeLoaded
= self
.CheckArchProtocol()
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])
543 ScheduleList
[FfsID
] = NewFfs
545 self
.UnDispatchedFfsDict
[FfsID
].Depex
= DepexString
547 for FfsID
in ScheduleList
.keys():
548 NewFfs
= ScheduleList
.pop(FfsID
)
550 self
.OrderedFfsDict
[FfsID
] = NewFfs
551 self
.LoadProtocol(Db
, FfsID
)
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
)
558 FfsName
= RecordSet
[0][0]
563 def DisPatchPei(self
, Db
):
565 for FfsID
in list(self
.UnDispatchedFfsDict
.keys()):
569 Ffs
= self
.UnDispatchedFfsDict
[FfsID
]
570 if Ffs
.Type
== 0x06 or Ffs
.Type
== 0x08:
572 for Section
in Ffs
.Sections
.values():
573 if Section
.Type
== 0x1B:
574 CouldBeLoaded
, DepexString
, FileDepex
= self
.ParseDepex(Section
._SubImages
[4], 'Ppi')
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')
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')
592 NewFfs
= self
.UnDispatchedFfsDict
.pop(FfsID
)
593 NewFfs
.Depex
= DepexString
594 self
.OrderedFfsDict
[FfsID
] = NewFfs
595 self
.LoadPpi(Db
, FfsID
)
597 self
.UnDispatchedFfsDict
[FfsID
].Depex
= DepexString
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
])
610 return FvInfo
+ FfsInfo
613 Size
= self
._LENGTH
_.unpack_from(self
._BUF
_, self
._OFF
_)[0]
615 self
.extend(self
._BUF
_[self
._OFF
_:self
._OFF
_ + Size
])
619 FfsStartAddress
= self
.HeaderSize
621 while FfsStartAddress
< EndOfFv
:
623 FfsObj
.frombuffer(self
, FfsStartAddress
)
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
)
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
)
639 FfsStartAddress
+= len(FfsObj
)
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
644 FfsStartAddress
= (FfsStartAddress
+ 7) & (~
7)
647 def _GetAttributes(self
):
648 return self
.GetField(self
._ATTR
_, 0)[0]
651 return self
.GetField(self
._LENGTH
_, 0)[0]
653 def _GetChecksum(self
):
654 return self
.GetField(self
._CHECKSUM
_, 0)[0]
656 def _GetHeaderLength(self
):
657 return self
.GetField(self
._HLEN
_, 0)[0]
659 def _GetFileSystemGuid(self
):
660 return gGuidStringFormat
% self
.GetField(self
._GUID
_, 0)
662 Attributes
= property(_GetAttributes
)
663 Size
= property(_GetSize
)
664 Checksum
= property(_GetChecksum
)
665 HeaderSize
= property(_GetHeaderLength
)
666 FileSystemGuid
= property(_GetFileSystemGuid
)
668 ## GuidDefinedImage() class
670 # A class for GUID Defined Image
672 class GuidDefinedImage(Image
):
673 _HEADER_
= struct
.Struct("1I2H8B 1H 1H")
674 _HEADER_SIZE_
= _HEADER_
.size
676 _GUID_
= struct
.Struct("1I2H8B")
677 _DATA_OFFSET_
= struct
.Struct("16x 1H")
678 _ATTR_
= struct
.Struct("18x 1H")
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'
684 def __init__(self
, SectionDefinitionGuid
=None, DataOffset
=None, Attributes
=None, Data
=None):
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
696 S
= "guid=%s" % (gGuidStringFormat
% self
.SectionDefinitionGuid
)
697 for Sec
in self
.Sections
:
702 # keep header in this Image object
704 self
.extend(self
._BUF
_[self
._OFF
_ : self
._OFF
_ + self
._LEN
_])
707 def _SetAttribute(self
, Attribute
):
708 self
.SetField(self
._ATTR
_, 0, Attribute
)
710 def _GetAttribute(self
):
711 return self
.GetField(self
._ATTR
_)[0]
713 def _SetGuid(self
, Guid
):
714 self
.SetField(self
._GUID
_, 0, Guid
)
717 return self
.GetField(self
._GUID
_)
719 def _SetDataOffset(self
, Offset
):
720 self
.SetField(self
._DATA
_OFFSET
_, 0, Offset
)
722 def _GetDataOffset(self
):
723 return self
.GetField(self
._DATA
_OFFSET
_)[0]
725 def _GetSections(self
):
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
):
734 Sec
.frombuffer(self
, Offset
)
736 # the section is aligned to 4-byte boundary
737 Offset
= (Offset
+ 3) & (~
3)
740 SectionList
.append(Sec
)
741 elif Guid
== self
.TIANO_COMPRESS_GUID
:
744 Offset
= self
.DataOffset
- 4
745 TmpData
= DeCompress('Framework', self
[self
.Offset
:])
747 DecData
.fromstring(TmpData
)
749 while Offset
< len(DecData
):
752 Sec
.frombuffer(DecData
, Offset
)
754 # the section is aligned to 4-byte boundary
755 Offset
= (Offset
+ 3) & (~
3)
758 SectionList
.append(Sec
)
761 elif Guid
== self
.LZMA_COMPRESS_GUID
:
764 Offset
= self
.DataOffset
- 4
766 TmpData
= DeCompress('Lzma', self
[self
.Offset
:])
768 DecData
.fromstring(TmpData
)
770 while Offset
< len(DecData
):
773 Sec
.frombuffer(DecData
, Offset
)
775 # the section is aligned to 4-byte boundary
776 Offset
= (Offset
+ 3) & (~
3)
779 SectionList
.append(Sec
)
785 Attributes
= property(_GetAttribute
, _SetAttribute
)
786 SectionDefinitionGuid
= property(_GetGuid
, _SetGuid
)
787 DataOffset
= property(_GetDataOffset
, _SetDataOffset
)
788 Sections
= property(_GetSections
)
792 # A class for Section
794 class Section(Image
):
797 0x01 : "COMPRESSION",
798 0x02 : "GUID_DEFINED",
804 0x15 : "USER_INTERFACE",
805 0x16 : "COMPATIBILITY16",
806 0x17 : "FIRMWARE_VOLUME_IMAGE",
807 0x18 : "FREEFORM_SUBTYPE_GUID",
812 _SectionSubImages
= {
813 0x01 : CompressedImage
,
814 0x02 : GuidDefinedImage
,
815 0x17 : FirmwareVolume
,
823 _HEADER_
= struct
.Struct("3B 1B")
824 _HEADER_SIZE_
= _HEADER_
.size
827 # _FREE_FORM_SUBTYPE_GUID_HEADER_ = struct.Struct("1I2H8B")
828 _SIZE_
= struct
.Struct("3B")
829 _TYPE_
= struct
.Struct("3x 1B")
831 def __init__(self
, Type
=None, Size
=None):
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
)
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
])
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)
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
])
862 # keep header in this Image object
863 self
.extend(self
._BUF
_[self
._OFF
_ : self
._OFF
_ + self
._HEADER
_SIZE
_])
865 # use new Image object to represent payload, which may be another kind
866 # of image such as PE32
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
876 def _SetSize(self
, Size
):
878 Size2
= (Size
& 0xFF00) >> 8
879 Size3
= (Size
& 0xFF0000) >> 16
880 self
.SetField(self
._SIZE
_, 0, Size1
, Size2
, Size3
)
883 Size1
, Size2
, Size3
= self
.GetField(self
._SIZE
_)
884 return Size1
+ (Size2
<< 8) + (Size3
<< 16)
886 def _SetType(self
, Type
):
887 self
.SetField(self
._TYPE
_, 0, Type
)
890 return self
.GetField(self
._TYPE
_)[0]
892 def _GetAlignment(self
):
893 return self
._Alignment
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:
902 NewOffset
= (PayloadOffset
+ AlignmentMask
) & (~AlignmentMask
)
903 while (NewOffset
- PayloadOffset
) < self
._HEADER
_SIZE
_:
904 NewOffset
+= self
._Alignment
907 self
.Size
= len(self
)
908 Image
.tofile(self
, f
)
909 for Offset
in self
._SubImages
:
910 self
._SubImages
[Offset
].tofile(f
)
912 Type
= property(_GetType
, _SetType
)
913 Size
= property(_GetSize
, _SetSize
)
914 Alignment
= property(_GetAlignment
, _SetAlignment
)
918 # A class for Ffs Section
921 _FfsFormat
= "24B%(payload_size)sB"
922 # skip IntegrityCheck
923 _HEADER_
= struct
.Struct("1I2H8B 2x 1B 1B 3B 1B")
924 _HEADER_SIZE_
= _HEADER_
.size
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")
933 FFS_ATTRIB_FIXED
= 0x04
934 FFS_ATTRIB_DATA_ALIGNMENT
= 0x38
935 FFS_ATTRIB_CHECKSUM
= 0x40
941 0x03 : "SECURITY_CORE",
946 0x08 : "COMBINED_PEIM_DRIVER",
947 0x09 : "APPLICATION",
949 0x0B : "FIRMWARE_VOLUME_IMAGE",
950 0x0C : "COMBINED_SMM_DXE",
952 0x0E : "MM_STANDALONE",
953 0x0F : "MM_CORE_STANDALONE",
967 self
.Sections
= sdict()
975 Indention
= ' ' * gIndention
977 FfsInfo
+= "[FFS:%s] offset=%x size=%x guid=%s free_space=%x alignment=%s\n" % \
978 (Ffs
._TypeName
[self
.Type
], self
._OFF
_, self
.Size
, self
.Guid
, self
.FreeSpace
, self
.Alignment
)
979 SectionInfo
= '\n'.join([str(self
.Sections
[Offset
]) for Offset
in self
.Sections
.keys()])
981 return FfsInfo
+ SectionInfo
+ "\n"
990 Size1
, Size2
, Size3
= self
._SIZE
_.unpack_from(self
._BUF
_, self
._OFF
_)
991 Size
= Size1
+ (Size2
<< 8) + (Size3
<< 16)
993 self
.extend(self
._BUF
_[self
._OFF
_ : self
._OFF
_ + Size
])
995 # Pad FFS may use the same GUID. We need to avoid it.
996 if self
.Type
== 0xf0:
997 self
.__ID
__ = str(uuid
.uuid1()).upper()
999 self
.__ID
__ = self
.Guid
1001 # Traverse the SECTION. RAW and PAD do not have sections
1002 if self
.Type
not in [0xf0, 0x01] and Size
> 0 and Size
< 0xFFFFFF:
1004 SectionStartAddress
= self
._HEADER
_SIZE
_
1005 while SectionStartAddress
< EndOfFfs
:
1006 SectionObj
= Section()
1007 SectionObj
.frombuffer(self
, SectionStartAddress
)
1008 #f = open(repr(SectionObj), 'wb')
1009 #SectionObj.Size = 0
1010 #SectionObj.tofile(f)
1012 self
.Sections
[SectionStartAddress
] = SectionObj
1013 SectionStartAddress
+= len(SectionObj
)
1014 SectionStartAddress
= (SectionStartAddress
+ 3) & (~
3)
1019 def SetFreeSpace(self
, Size
):
1020 self
.FreeSpace
= Size
1023 return gGuidStringFormat
% self
.Name
1025 def _SetName(self
, Value
):
1026 # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
1027 self
.SetField(self
._NAME
_, 0, Value
)
1030 # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11
1031 return self
.GetField(self
._NAME
_)
1033 def _SetSize(self
, Size
):
1035 Size2
= (Size
& 0xFF00) >> 8
1036 Size3
= (Size
& 0xFF0000) >> 16
1037 self
.SetField(self
._SIZE
_, 0, Size1
, Size2
, Size3
)
1040 Size1
, Size2
, Size3
= self
.GetField(self
._SIZE
_)
1041 return Size1
+ (Size2
<< 8) + (Size3
<< 16)
1043 def _SetType(self
, Type
):
1044 self
.SetField(self
._TYPE
_, 0, Type
)
1047 return self
.GetField(self
._TYPE
_)[0]
1049 def _SetAttributes(self
, Value
):
1050 self
.SetField(self
._ATTR
_, 0, Value
)
1052 def _GetAttributes(self
):
1053 return self
.GetField(self
._ATTR
_)[0]
1055 def _GetFixed(self
):
1056 if (self
.Attributes
& self
.FFS_ATTRIB_FIXED
) != 0:
1060 def _GetCheckSum(self
):
1061 if (self
.Attributes
& self
.FFS_ATTRIB_CHECKSUM
) != 0:
1065 def _GetAlignment(self
):
1066 return (self
.Attributes
& self
.FFS_ATTRIB_DATA_ALIGNMENT
) >> 3
1068 def _SetState(self
, Value
):
1069 self
.SetField(self
._STATE
_, 0, Value
)
1071 def _GetState(self
):
1072 return self
.GetField(self
._STATE
_)[0]
1074 Name
= property(_GetName
, _SetName
)
1075 Guid
= property(_GetGuid
)
1076 Type
= property(_GetType
, _SetType
)
1077 Size
= property(_GetSize
, _SetSize
)
1078 Attributes
= property(_GetAttributes
, _SetAttributes
)
1079 Fixed
= property(_GetFixed
)
1080 Checksum
= property(_GetCheckSum
)
1081 Alignment
= property(_GetAlignment
)
1082 State
= property(_GetState
, _SetState
)
1085 ## MultipleFv() class
1087 # A class for Multiple FV
1089 class MultipleFv(FirmwareVolume
):
1090 def __init__(self
, FvList
):
1091 FirmwareVolume
.__init
__(self
)
1093 for FvPath
in FvList
:
1095 FvName
= os
.path
.splitext(os
.path
.split(FvPath
)[1])[0]
1097 Fd
= open(FvPath
, 'rb')
1100 Buf
.fromfile(Fd
, os
.path
.getsize(FvPath
))
1104 Fv
= FirmwareVolume(FvName
)
1105 Fv
.frombuffer(Buf
, 0, len(Buf
))
1107 self
.BasicInfo
.append([Fv
.Name
, Fv
.FileSystemGuid
, Fv
.Size
])
1108 self
.FfsDict
.update(Fv
.FfsDict
)
1112 # This class is used to define Eot main entrance
1114 # @param object: Inherited from object class
1119 # @param self: The object pointer
1121 def __init__(self
, CommandLineOption
=True, IsInit
=True, SourceFileList
=None, \
1122 IncludeDirList
=None, DecFileList
=None, GuidList
=None, LogFile
=None,
1123 FvFileList
="", MapFileList
="", Report
='Report.html', Dispatch
=None):
1124 # Version and Copyright
1125 self
.VersionNumber
= ("0.02" + " " + gBUILD_VERSION
)
1126 self
.Version
= "%prog Version " + self
.VersionNumber
1127 self
.Copyright
= "Copyright (c) 2008 - 2018, Intel Corporation All rights reserved."
1128 self
.Report
= Report
1130 self
.IsInit
= IsInit
1131 self
.SourceFileList
= SourceFileList
1132 self
.IncludeDirList
= IncludeDirList
1133 self
.DecFileList
= DecFileList
1134 self
.GuidList
= GuidList
1135 self
.LogFile
= LogFile
1136 self
.FvFileList
= FvFileList
1137 self
.MapFileList
= MapFileList
1138 self
.Dispatch
= Dispatch
1140 # Check workspace environment
1141 if "EFI_SOURCE" not in os
.environ
:
1142 if "EDK_SOURCE" not in os
.environ
:
1145 EotGlobalData
.gEDK_SOURCE
= os
.path
.normpath(os
.getenv("EDK_SOURCE"))
1147 EotGlobalData
.gEFI_SOURCE
= os
.path
.normpath(os
.getenv("EFI_SOURCE"))
1148 EotGlobalData
.gEDK_SOURCE
= os
.path
.join(EotGlobalData
.gEFI_SOURCE
, 'Edk')
1150 if "WORKSPACE" not in os
.environ
:
1151 EdkLogger
.error("EOT", BuildToolError
.ATTRIBUTE_NOT_AVAILABLE
, "Environment variable not found",
1152 ExtraData
="WORKSPACE")
1154 EotGlobalData
.gWORKSPACE
= os
.path
.normpath(os
.getenv("WORKSPACE"))
1156 EotGlobalData
.gMACRO
['WORKSPACE'] = EotGlobalData
.gWORKSPACE
1157 EotGlobalData
.gMACRO
['EFI_SOURCE'] = EotGlobalData
.gEFI_SOURCE
1158 EotGlobalData
.gMACRO
['EDK_SOURCE'] = EotGlobalData
.gEDK_SOURCE
1160 # Parse the options and args
1161 if CommandLineOption
:
1165 for FvFile
in GetSplitValueList(self
.FvFileList
, ' '):
1166 FvFile
= os
.path
.normpath(FvFile
)
1167 if not os
.path
.isfile(FvFile
):
1168 EdkLogger
.error("Eot", EdkLogger
.EOT_ERROR
, "Can not find file %s " % FvFile
)
1169 EotGlobalData
.gFV_FILE
.append(FvFile
)
1171 EdkLogger
.error("Eot", EdkLogger
.EOT_ERROR
, "The fv file list of target platform was not specified")
1173 if self
.MapFileList
:
1174 for MapFile
in GetSplitValueList(self
.MapFileList
, ' '):
1175 MapFile
= os
.path
.normpath(MapFile
)
1176 if not os
.path
.isfile(MapFile
):
1177 EdkLogger
.error("Eot", EdkLogger
.EOT_ERROR
, "Can not find file %s " % MapFile
)
1178 EotGlobalData
.gMAP_FILE
.append(MapFile
)
1180 # Generate source file list
1181 self
.GenerateSourceFileList(self
.SourceFileList
, self
.IncludeDirList
)
1183 # Generate guid list of dec file list
1184 self
.ParseDecFile(self
.DecFileList
)
1186 # Generate guid list from GUID list file
1187 self
.ParseGuidList(self
.GuidList
)
1190 EotGlobalData
.gDb
= Database
.Database(Database
.DATABASE_PATH
)
1191 EotGlobalData
.gDb
.InitDatabase(self
.IsInit
)
1193 # Build ECC database
1194 self
.BuildDatabase()
1196 # Parse Ppi/Protocol
1197 self
.ParseExecutionOrder()
1199 # Merge Identifier tables
1200 self
.GenerateQueryTable()
1202 # Generate report database
1203 self
.GenerateReportDatabase()
1212 self
.GenerateReport()
1215 self
.ConvertLogFile(self
.LogFile
)
1218 EdkLogger
.quiet("EOT FINISHED!")
1221 EotGlobalData
.gDb
.Close()
1223 ## ParseDecFile() method
1225 # parse DEC file and get all GUID names with GUID values as {GuidName : GuidValue}
1226 # The Dict is stored in EotGlobalData.gGuidDict
1228 # @param self: The object pointer
1229 # @param DecFileList: A list of all DEC files
1231 def ParseDecFile(self
, DecFileList
):
1233 path
= os
.path
.normpath(DecFileList
)
1234 lfr
= open(path
, 'rb')
1236 path
= os
.path
.normpath(os
.path
.join(EotGlobalData
.gWORKSPACE
, line
.strip()))
1237 if os
.path
.exists(path
):
1238 dfr
= open(path
, 'rb')
1240 line
= CleanString(line
)
1241 list = line
.split('=')
1243 EotGlobalData
.gGuidDict
[list[0].strip()] = GuidStructureStringToGuidString(list[1].strip())
1246 ## ParseGuidList() method
1248 # Parse Guid list and get all GUID names with GUID values as {GuidName : GuidValue}
1249 # The Dict is stored in EotGlobalData.gGuidDict
1251 # @param self: The object pointer
1252 # @param GuidList: A list of all GUID and its value
1254 def ParseGuidList(self
, GuidList
):
1255 Path
= os
.path
.join(EotGlobalData
.gWORKSPACE
, GuidList
)
1256 if os
.path
.isfile(Path
):
1257 for Line
in open(Path
):
1259 (GuidName
, GuidValue
) = Line
.split()
1260 EotGlobalData
.gGuidDict
[GuidName
] = GuidValue
1262 ## ConvertLogFile() method
1264 # Parse a real running log file to get real dispatch order
1265 # The result is saved to old file name + '.new'
1267 # @param self: The object pointer
1268 # @param LogFile: A real running log file name
1270 def ConvertLogFile(self
, LogFile
):
1275 lfr
= open(LogFile
, 'rb')
1276 lfw
= open(LogFile
+ '.new', 'wb')
1279 line
= line
.replace('.efi', '')
1280 index
= line
.find("Loading PEIM at ")
1282 newline
.append(line
[index
+ 55 : ])
1284 index
= line
.find("Loading driver at ")
1286 newline
.append(line
[index
+ 57 : ])
1289 for line
in newline
:
1290 lfw
.write(line
+ '\r\n')
1297 ## GenerateSourceFileList() method
1299 # Generate a list of all source files
1300 # 1. Search the file list one by one
1301 # 2. Store inf file name with source file names under it like
1302 # { INF file name: [source file1, source file2, ...]}
1303 # 3. Search the include list to find all .h files
1304 # 4. Store source file list to EotGlobalData.gSOURCE_FILES
1305 # 5. Store INF file list to EotGlobalData.gINF_FILES
1307 # @param self: The object pointer
1308 # @param SourceFileList: A list of all source files
1309 # @param IncludeFileList: A list of all include files
1311 def GenerateSourceFileList(self
, SourceFileList
, IncludeFileList
):
1312 EdkLogger
.quiet("Generating source files list ... ")
1313 mSourceFileList
= []
1317 mCurrentInfFile
= ''
1318 mCurrentSourceFileList
= []
1321 sfl
= open(SourceFileList
, 'r')
1323 line
= os
.path
.normpath(os
.path
.join(EotGlobalData
.gWORKSPACE
, line
.strip()))
1324 if line
[-2:].upper() == '.C' or line
[-2:].upper() == '.H':
1325 if line
not in mCurrentSourceFileList
:
1326 mCurrentSourceFileList
.append(line
)
1327 mSourceFileList
.append(line
)
1328 EotGlobalData
.gOP_SOURCE_FILES
.write('%s\n' % line
)
1329 if line
[-4:].upper() == '.INF':
1330 if mCurrentInfFile
!= '':
1331 mFileList
[mCurrentInfFile
] = mCurrentSourceFileList
1332 mCurrentSourceFileList
= []
1333 mCurrentInfFile
= os
.path
.normpath(os
.path
.join(EotGlobalData
.gWORKSPACE
, line
))
1334 EotGlobalData
.gOP_INF
.write('%s\n' % mCurrentInfFile
)
1335 if mCurrentInfFile
not in mFileList
:
1336 mFileList
[mCurrentInfFile
] = mCurrentSourceFileList
1338 # Get all include files from packages
1340 ifl
= open(IncludeFileList
, 'rb')
1342 if not line
.strip():
1344 newline
= os
.path
.normpath(os
.path
.join(EotGlobalData
.gWORKSPACE
, line
.strip()))
1345 for Root
, Dirs
, Files
in os
.walk(str(newline
)):
1347 FullPath
= os
.path
.normpath(os
.path
.join(Root
, File
))
1348 if FullPath
not in mSourceFileList
and File
[-2:].upper() == '.H':
1349 mSourceFileList
.append(FullPath
)
1350 EotGlobalData
.gOP_SOURCE_FILES
.write('%s\n' % FullPath
)
1351 if FullPath
not in mDecFileList
and File
.upper().find('.DEC') > -1:
1352 mDecFileList
.append(FullPath
)
1354 EotGlobalData
.gSOURCE_FILES
= mSourceFileList
1355 EotGlobalData
.gOP_SOURCE_FILES
.close()
1357 EotGlobalData
.gINF_FILES
= mFileList
1358 EotGlobalData
.gOP_INF
.close()
1360 ## GenerateReport() method
1362 # Generate final HTML report
1364 # @param self: The object pointer
1366 def GenerateReport(self
):
1367 EdkLogger
.quiet("Generating report file ... ")
1368 Rep
= Report(self
.Report
, EotGlobalData
.gFV
, self
.Dispatch
)
1369 Rep
.GenerateReport()
1371 ## LoadMapInfo() method
1373 # Load map files and parse them
1375 # @param self: The object pointer
1377 def LoadMapInfo(self
):
1378 if EotGlobalData
.gMAP_FILE
!= []:
1379 EdkLogger
.quiet("Parsing Map file ... ")
1380 EotGlobalData
.gMap
= ParseMapFile(EotGlobalData
.gMAP_FILE
)
1382 ## LoadFvInfo() method
1384 # Load FV binary files and parse them
1386 # @param self: The object pointer
1388 def LoadFvInfo(self
):
1389 EdkLogger
.quiet("Parsing FV file ... ")
1390 EotGlobalData
.gFV
= MultipleFv(EotGlobalData
.gFV_FILE
)
1391 EotGlobalData
.gFV
.Dispatch(EotGlobalData
.gDb
)
1393 for Protocol
in EotGlobalData
.gProtocolList
:
1394 EotGlobalData
.gOP_UN_MATCHED_IN_LIBRARY_CALLING
.write('%s\n' %Protocol
)
1396 ## GenerateReportDatabase() method
1398 # Generate data for the information needed by report
1399 # 1. Update name, macro and value of all found PPI/PROTOCOL GUID
1400 # 2. Install hard coded PPI/PROTOCOL
1402 # @param self: The object pointer
1404 def GenerateReportDatabase(self
):
1405 EdkLogger
.quiet("Generating the cross-reference table of GUID for Ppi/Protocol ... ")
1407 # Update Protocol/Ppi Guid
1408 SqlCommand
= """select DISTINCT GuidName from Report"""
1409 RecordSet
= EotGlobalData
.gDb
.TblReport
.Exec(SqlCommand
)
1410 for Record
in RecordSet
:
1411 GuidName
= Record
[0]
1416 # Find guid value defined in Dec file
1417 if GuidName
in EotGlobalData
.gGuidDict
:
1418 GuidValue
= EotGlobalData
.gGuidDict
[GuidName
]
1419 SqlCommand
= """update Report set GuidMacro = '%s', GuidValue = '%s' where GuidName = '%s'""" %(GuidMacro
, GuidValue
, GuidName
)
1420 EotGlobalData
.gDb
.TblReport
.Exec(SqlCommand
)
1423 # Search defined Macros for guid name
1424 SqlCommand
="""select DISTINCT Value, Modifier from Query where Name like '%s'""" % GuidName
1425 GuidMacroSet
= EotGlobalData
.gDb
.TblReport
.Exec(SqlCommand
)
1426 # Ignore NULL result
1427 if not GuidMacroSet
:
1429 GuidMacro
= GuidMacroSet
[0][0].strip()
1432 # Find Guid value of Guid Macro
1433 SqlCommand
="""select DISTINCT Value from Query2 where Value like '%%%s%%' and Model = %s""" % (GuidMacro
, MODEL_IDENTIFIER_MACRO_DEFINE
)
1434 GuidValueSet
= EotGlobalData
.gDb
.TblReport
.Exec(SqlCommand
)
1435 if GuidValueSet
!= []:
1436 GuidValue
= GuidValueSet
[0][0]
1437 GuidValue
= GuidValue
[GuidValue
.find(GuidMacro
) + len(GuidMacro
) :]
1438 GuidValue
= GuidValue
.lower().replace('\\', '').replace('\r', '').replace('\n', '').replace('l', '').strip()
1439 GuidValue
= GuidStructureStringToGuidString(GuidValue
)
1440 SqlCommand
= """update Report set GuidMacro = '%s', GuidValue = '%s' where GuidName = '%s'""" %(GuidMacro
, GuidValue
, GuidName
)
1441 EotGlobalData
.gDb
.TblReport
.Exec(SqlCommand
)
1444 # Update Hard Coded Ppi/Protocol
1445 SqlCommand
= """select DISTINCT GuidValue, ItemType from Report where ModuleID = -2 and ItemMode = 'Produced'"""
1446 RecordSet
= EotGlobalData
.gDb
.TblReport
.Exec(SqlCommand
)
1447 for Record
in RecordSet
:
1448 if Record
[1] == 'Ppi':
1449 EotGlobalData
.gPpiList
[Record
[0].lower()] = -2
1450 if Record
[1] == 'Protocol':
1451 EotGlobalData
.gProtocolList
[Record
[0].lower()] = -2
1453 ## GenerateQueryTable() method
1455 # Generate two tables improve query performance
1457 # @param self: The object pointer
1459 def GenerateQueryTable(self
):
1460 EdkLogger
.quiet("Generating temp query table for analysis ... ")
1461 for Identifier
in EotGlobalData
.gIdentifierTableList
:
1462 SqlCommand
= """insert into Query (Name, Modifier, Value, Model)
1463 select Name, Modifier, Value, Model from %s where (Model = %s or Model = %s)""" \
1464 % (Identifier
[0], MODEL_IDENTIFIER_VARIABLE
, MODEL_IDENTIFIER_ASSIGNMENT_EXPRESSION
)
1465 EotGlobalData
.gDb
.TblReport
.Exec(SqlCommand
)
1466 SqlCommand
= """insert into Query2 (Name, Modifier, Value, Model)
1467 select Name, Modifier, Value, Model from %s where Model = %s""" \
1468 % (Identifier
[0], MODEL_IDENTIFIER_MACRO_DEFINE
)
1469 EotGlobalData
.gDb
.TblReport
.Exec(SqlCommand
)
1471 ## ParseExecutionOrder() method
1473 # Get final execution order
1475 # 2. Search all PROTOCOL
1477 # @param self: The object pointer
1479 def ParseExecutionOrder(self
):
1480 EdkLogger
.quiet("Searching Ppi/Protocol ... ")
1481 for Identifier
in EotGlobalData
.gIdentifierTableList
:
1482 ModuleID
, ModuleName
, ModuleGuid
, SourceFileID
, SourceFileFullPath
, ItemName
, ItemType
, ItemMode
, GuidName
, GuidMacro
, GuidValue
, BelongsToFunction
, Enabled
= \
1483 -1, '', '', -1, '', '', '', '', '', '', '', '', 0
1485 SourceFileID
= Identifier
[0].replace('Identifier', '')
1486 SourceFileFullPath
= Identifier
[1]
1487 Identifier
= Identifier
[0]
1490 ItemMode
= 'Produced'
1491 SqlCommand
= """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1492 where (Name like '%%%s%%' or Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1493 % (Identifier
, '.InstallPpi', '->InstallPpi', 'PeiInstallPpi', MODEL_IDENTIFIER_FUNCTION_CALLING
)
1494 SearchPpi(SqlCommand
, Identifier
, SourceFileID
, SourceFileFullPath
, ItemMode
)
1496 ItemMode
= 'Produced'
1497 SqlCommand
= """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1498 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1499 % (Identifier
, '.ReInstallPpi', '->ReInstallPpi', MODEL_IDENTIFIER_FUNCTION_CALLING
)
1500 SearchPpi(SqlCommand
, Identifier
, SourceFileID
, SourceFileFullPath
, ItemMode
, 2)
1502 SearchPpiCallFunction(Identifier
, SourceFileID
, SourceFileFullPath
, ItemMode
)
1504 ItemMode
= 'Consumed'
1505 SqlCommand
= """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1506 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1507 % (Identifier
, '.LocatePpi', '->LocatePpi', MODEL_IDENTIFIER_FUNCTION_CALLING
)
1508 SearchPpi(SqlCommand
, Identifier
, SourceFileID
, SourceFileFullPath
, ItemMode
)
1510 SearchFunctionCalling(Identifier
, SourceFileID
, SourceFileFullPath
, 'Ppi', ItemMode
)
1512 ItemMode
= 'Callback'
1513 SqlCommand
= """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1514 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1515 % (Identifier
, '.NotifyPpi', '->NotifyPpi', MODEL_IDENTIFIER_FUNCTION_CALLING
)
1516 SearchPpi(SqlCommand
, Identifier
, SourceFileID
, SourceFileFullPath
, ItemMode
)
1519 ItemMode
= 'Produced'
1520 SqlCommand
= """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1521 where (Name like '%%%s%%' or Name like '%%%s%%' or Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1522 % (Identifier
, '.InstallProtocolInterface', '.ReInstallProtocolInterface', '->InstallProtocolInterface', '->ReInstallProtocolInterface', MODEL_IDENTIFIER_FUNCTION_CALLING
)
1523 SearchProtocols(SqlCommand
, Identifier
, SourceFileID
, SourceFileFullPath
, ItemMode
, 1)
1525 SqlCommand
= """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1526 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1527 % (Identifier
, '.InstallMultipleProtocolInterfaces', '->InstallMultipleProtocolInterfaces', MODEL_IDENTIFIER_FUNCTION_CALLING
)
1528 SearchProtocols(SqlCommand
, Identifier
, SourceFileID
, SourceFileFullPath
, ItemMode
, 2)
1530 SearchFunctionCalling(Identifier
, SourceFileID
, SourceFileFullPath
, 'Protocol', ItemMode
)
1532 ItemMode
= 'Consumed'
1533 SqlCommand
= """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1534 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1535 % (Identifier
, '.LocateProtocol', '->LocateProtocol', MODEL_IDENTIFIER_FUNCTION_CALLING
)
1536 SearchProtocols(SqlCommand
, Identifier
, SourceFileID
, SourceFileFullPath
, ItemMode
, 0)
1538 SqlCommand
= """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1539 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1540 % (Identifier
, '.HandleProtocol', '->HandleProtocol', MODEL_IDENTIFIER_FUNCTION_CALLING
)
1541 SearchProtocols(SqlCommand
, Identifier
, SourceFileID
, SourceFileFullPath
, ItemMode
, 1)
1543 SearchFunctionCalling(Identifier
, SourceFileID
, SourceFileFullPath
, 'Protocol', ItemMode
)
1545 ItemMode
= 'Callback'
1546 SqlCommand
= """select Value, Name, BelongsToFile, StartLine, EndLine from %s
1547 where (Name like '%%%s%%' or Name like '%%%s%%') and Model = %s""" \
1548 % (Identifier
, '.RegisterProtocolNotify', '->RegisterProtocolNotify', MODEL_IDENTIFIER_FUNCTION_CALLING
)
1549 SearchProtocols(SqlCommand
, Identifier
, SourceFileID
, SourceFileFullPath
, ItemMode
, 0)
1551 SearchFunctionCalling(Identifier
, SourceFileID
, SourceFileFullPath
, 'Protocol', ItemMode
)
1554 EotGlobalData
.gDb
.TblReport
.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gEfiSecPlatformInformationPpiGuid', '', '', '', 0)
1555 EotGlobalData
.gDb
.TblReport
.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gEfiNtLoadAsDllPpiGuid', '', '', '', 0)
1556 EotGlobalData
.gDb
.TblReport
.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gNtPeiLoadFileGuid', '', '', '', 0)
1557 EotGlobalData
.gDb
.TblReport
.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiNtAutoScanPpiGuid', '', '', '', 0)
1558 EotGlobalData
.gDb
.TblReport
.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gNtFwhPpiGuid', '', '', '', 0)
1559 EotGlobalData
.gDb
.TblReport
.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiNtThunkPpiGuid', '', '', '', 0)
1560 EotGlobalData
.gDb
.TblReport
.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiPlatformTypePpiGuid', '', '', '', 0)
1561 EotGlobalData
.gDb
.TblReport
.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiFrequencySelectionCpuPpiGuid', '', '', '', 0)
1562 EotGlobalData
.gDb
.TblReport
.Insert(-2, '', '', -1, '', '', 'Ppi', 'Produced', 'gPeiCachePpiGuid', '', '', '', 0)
1564 EotGlobalData
.gDb
.Conn
.commit()
1567 ## BuildDatabase() methoc
1569 # Build the database for target
1571 # @param self: The object pointer
1573 def BuildDatabase(self
):
1574 # Clean report table
1575 EotGlobalData
.gDb
.TblReport
.Drop()
1576 EotGlobalData
.gDb
.TblReport
.Create()
1580 self
.BuildMetaDataFileDatabase(EotGlobalData
.gINF_FILES
)
1581 EdkLogger
.quiet("Building database for source code ...")
1582 c
.CreateCCodeDB(EotGlobalData
.gSOURCE_FILES
)
1583 EdkLogger
.quiet("Building database for source code done!")
1585 EotGlobalData
.gIdentifierTableList
= GetTableList((MODEL_FILE_C
, MODEL_FILE_H
), 'Identifier', EotGlobalData
.gDb
)
1587 ## BuildMetaDataFileDatabase() method
1589 # Build the database for meta data files
1591 # @param self: The object pointer
1592 # @param Inf_Files: A list for all INF files
1594 def BuildMetaDataFileDatabase(self
, Inf_Files
):
1595 EdkLogger
.quiet("Building database for meta data files ...")
1596 for InfFile
in Inf_Files
:
1599 EdkLogger
.quiet("Parsing %s ..." % str(InfFile
))
1600 EdkInfParser(InfFile
, EotGlobalData
.gDb
, Inf_Files
[InfFile
])
1602 EotGlobalData
.gDb
.Conn
.commit()
1603 EdkLogger
.quiet("Building database for meta data files done!")
1605 ## ParseOption() method
1607 # Parse command line options
1609 # @param self: The object pointer
1611 def ParseOption(self
):
1612 (Options
, Target
) = self
.EotOptionParser()
1615 self
.SetLogLevel(Options
)
1617 if Options
.FvFileList
:
1618 self
.FvFileList
= Options
.FvFileList
1620 if Options
.MapFileList
:
1621 self
.MapFileList
= Options
.FvMapFileList
1623 if Options
.SourceFileList
:
1624 self
.SourceFileList
= Options
.SourceFileList
1626 if Options
.IncludeDirList
:
1627 self
.IncludeDirList
= Options
.IncludeDirList
1629 if Options
.DecFileList
:
1630 self
.DecFileList
= Options
.DecFileList
1632 if Options
.GuidList
:
1633 self
.GuidList
= Options
.GuidList
1636 self
.LogFile
= Options
.LogFile
1638 if Options
.keepdatabase
:
1641 ## SetLogLevel() method
1643 # Set current log level of the tool based on args
1645 # @param self: The object pointer
1646 # @param Option: The option list including log level setting
1648 def SetLogLevel(self
, Option
):
1649 if Option
.verbose
is not None:
1650 EdkLogger
.SetLevel(EdkLogger
.VERBOSE
)
1651 elif Option
.quiet
is not None:
1652 EdkLogger
.SetLevel(EdkLogger
.QUIET
)
1653 elif Option
.debug
is not None:
1654 EdkLogger
.SetLevel(Option
.debug
+ 1)
1656 EdkLogger
.SetLevel(EdkLogger
.INFO
)
1658 ## EotOptionParser() method
1660 # Using standard Python module optparse to parse command line option of this tool.
1662 # @param self: The object pointer
1664 # @retval Opt A optparse.Values object containing the parsed options
1665 # @retval Args Target of build command
1667 def EotOptionParser(self
):
1668 Parser
= OptionParser(description
= self
.Copyright
, version
= self
.Version
, prog
= "Eot.exe", usage
= "%prog [options]")
1669 Parser
.add_option("-m", "--makefile filename", action
="store", type="string", dest
='MakeFile',
1670 help="Specify a makefile for the platform.")
1671 Parser
.add_option("-c", "--dsc filename", action
="store", type="string", dest
="DscFile",
1672 help="Specify a dsc file for the platform.")
1673 Parser
.add_option("-f", "--fv filename", action
="store", type="string", dest
="FvFileList",
1674 help="Specify fv file list, quoted by \"\".")
1675 Parser
.add_option("-a", "--map filename", action
="store", type="string", dest
="MapFileList",
1676 help="Specify map file list, quoted by \"\".")
1677 Parser
.add_option("-s", "--source files", action
="store", type="string", dest
="SourceFileList",
1678 help="Specify source file list by a file")
1679 Parser
.add_option("-i", "--include dirs", action
="store", type="string", dest
="IncludeDirList",
1680 help="Specify include dir list by a file")
1681 Parser
.add_option("-e", "--dec files", action
="store", type="string", dest
="DecFileList",
1682 help="Specify dec file list by a file")
1683 Parser
.add_option("-g", "--guid list", action
="store", type="string", dest
="GuidList",
1684 help="Specify guid file list by a file")
1685 Parser
.add_option("-l", "--log filename", action
="store", type="string", dest
="LogFile",
1686 help="Specify real execution log file")
1688 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.")
1690 Parser
.add_option("-q", "--quiet", action
="store_true", type=None, help="Disable all messages except FATAL ERRORS.")
1691 Parser
.add_option("-v", "--verbose", action
="store_true", type=None, help="Turn on verbose output with informational messages printed, "\
1692 "including library instances selected, final dependency expression, "\
1693 "and warning messages, etc.")
1694 Parser
.add_option("-d", "--debug", action
="store", type="int", help="Enable debug messages at specified level.")
1696 (Opt
, Args
)=Parser
.parse_args()
1702 # This acts like the main() function for the script, unless it is 'import'ed into another
1705 if __name__
== '__main__':
1706 # Initialize log system
1707 EdkLogger
.Initialize()
1708 EdkLogger
.IsRaiseError
= False
1709 EdkLogger
.quiet(time
.strftime("%H:%M:%S, %b.%d %Y ", time
.localtime()) + "[00:00]" + "\n")
1711 StartTime
= time
.clock()
1712 Eot
= Eot(CommandLineOption
=False,
1713 SourceFileList
=r
'C:\TestEot\Source.txt',
1714 GuidList
=r
'C:\TestEot\Guid.txt',
1715 FvFileList
=r
'C:\TestEot\FVRECOVERY.Fv')
1716 FinishTime
= time
.clock()
1718 BuildDuration
= time
.strftime("%M:%S", time
.gmtime(int(round(FinishTime
- StartTime
))))
1719 EdkLogger
.quiet("\n%s [%s]" % (time
.strftime("%H:%M:%S, %b.%d %Y", time
.localtime()), BuildDuration
))