152302d4dee589a5df43a464420c9fe68ba83937dlgao## @file
252302d4dee589a5df43a464420c9fe68ba83937dlgao# Routines for generating build report.
352302d4dee589a5df43a464420c9fe68ba83937dlgao#
452302d4dee589a5df43a464420c9fe68ba83937dlgao# This module contains the functionality to generate build report after
552302d4dee589a5df43a464420c9fe68ba83937dlgao# build all target completes successfully.
652302d4dee589a5df43a464420c9fe68ba83937dlgao#
71be2ed90a20618d71ddf34b8a07d038da0b36854Hess Chen# Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
840d841f6a8f84e75409178e19e69b95e01bada0flgao# This program and the accompanying materials
952302d4dee589a5df43a464420c9fe68ba83937dlgao# are licensed and made available under the terms and conditions of the BSD License
1052302d4dee589a5df43a464420c9fe68ba83937dlgao# which accompanies this distribution.  The full text of the license may be found at
1152302d4dee589a5df43a464420c9fe68ba83937dlgao# http://opensource.org/licenses/bsd-license.php
1252302d4dee589a5df43a464420c9fe68ba83937dlgao#
1352302d4dee589a5df43a464420c9fe68ba83937dlgao# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
1452302d4dee589a5df43a464420c9fe68ba83937dlgao# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
1552302d4dee589a5df43a464420c9fe68ba83937dlgao#
1652302d4dee589a5df43a464420c9fe68ba83937dlgao
1752302d4dee589a5df43a464420c9fe68ba83937dlgao## Import Modules
1852302d4dee589a5df43a464420c9fe68ba83937dlgao#
191be2ed90a20618d71ddf34b8a07d038da0b36854Hess Chenimport Common.LongFilePathOs as os
2052302d4dee589a5df43a464420c9fe68ba83937dlgaoimport re
2152302d4dee589a5df43a464420c9fe68ba83937dlgaoimport platform
2252302d4dee589a5df43a464420c9fe68ba83937dlgaoimport textwrap
2352302d4dee589a5df43a464420c9fe68ba83937dlgaoimport traceback
2452302d4dee589a5df43a464420c9fe68ba83937dlgaoimport sys
2540d841f6a8f84e75409178e19e69b95e01bada0flgaoimport time
26e56468c072e0d53834787f4ad0e292b33cc6be08qhuangimport struct
2752302d4dee589a5df43a464420c9fe68ba83937dlgaofrom datetime import datetime
2840d841f6a8f84e75409178e19e69b95e01bada0flgaofrom StringIO import StringIO
2952302d4dee589a5df43a464420c9fe68ba83937dlgaofrom Common import EdkLogger
3040d841f6a8f84e75409178e19e69b95e01bada0flgaofrom Common.Misc import SaveFileOnChange
3152302d4dee589a5df43a464420c9fe68ba83937dlgaofrom Common.Misc import GuidStructureByteArrayToGuidString
3252302d4dee589a5df43a464420c9fe68ba83937dlgaofrom Common.Misc import GuidStructureStringToGuidString
3352302d4dee589a5df43a464420c9fe68ba83937dlgaofrom Common.InfClassObject import gComponentType2ModuleType
3452302d4dee589a5df43a464420c9fe68ba83937dlgaofrom Common.BuildToolError import FILE_WRITE_FAILURE
3552302d4dee589a5df43a464420c9fe68ba83937dlgaofrom Common.BuildToolError import CODE_ERROR
3664b2609fcff9d6412eea4c74c8e74bed33dc3235lgaofrom Common.DataType import TAB_LINE_BREAK
3764b2609fcff9d6412eea4c74c8e74bed33dc3235lgaofrom Common.DataType import TAB_DEPEX
3864b2609fcff9d6412eea4c74c8e74bed33dc3235lgaofrom Common.DataType import TAB_SLASH
3964b2609fcff9d6412eea4c74c8e74bed33dc3235lgaofrom Common.DataType import TAB_SPACE_SPLIT
4064b2609fcff9d6412eea4c74c8e74bed33dc3235lgaofrom Common.DataType import TAB_BRG_PCD
4164b2609fcff9d6412eea4c74c8e74bed33dc3235lgaofrom Common.DataType import TAB_BRG_LIBRARY
4225918452ed5e9d12ea56b3bb2193df9ab96666b1lgaofrom Common.DataType import TAB_BACK_SLASH
431be2ed90a20618d71ddf34b8a07d038da0b36854Hess Chenfrom Common.LongFilePathSupport import OpenLongFilePath as open
4405cc51ad5894c8904d0fe5cdcf3f4d0a07dab85dLi YangXfrom Common.MultipleWorkspace import MultipleWorkspace as mws
4552302d4dee589a5df43a464420c9fe68ba83937dlgao
4652302d4dee589a5df43a464420c9fe68ba83937dlgao## Pattern to extract contents in EDK DXS files
4752302d4dee589a5df43a464420c9fe68ba83937dlgaogDxsDependencyPattern = re.compile(r"DEPENDENCY_START(.+)DEPENDENCY_END", re.DOTALL)
4852302d4dee589a5df43a464420c9fe68ba83937dlgao
4952302d4dee589a5df43a464420c9fe68ba83937dlgao## Pattern to find total FV total size, occupied size in flash report intermediate file
5052302d4dee589a5df43a464420c9fe68ba83937dlgaogFvTotalSizePattern = re.compile(r"EFI_FV_TOTAL_SIZE = (0x[0-9a-fA-F]+)")
5152302d4dee589a5df43a464420c9fe68ba83937dlgaogFvTakenSizePattern = re.compile(r"EFI_FV_TAKEN_SIZE = (0x[0-9a-fA-F]+)")
5252302d4dee589a5df43a464420c9fe68ba83937dlgao
5352302d4dee589a5df43a464420c9fe68ba83937dlgao## Pattern to find module size and time stamp in module summary report intermediate file
5452302d4dee589a5df43a464420c9fe68ba83937dlgaogModuleSizePattern = re.compile(r"MODULE_SIZE = (\d+)")
5552302d4dee589a5df43a464420c9fe68ba83937dlgaogTimeStampPattern  = re.compile(r"TIME_STAMP = (\d+)")
5652302d4dee589a5df43a464420c9fe68ba83937dlgao
5752302d4dee589a5df43a464420c9fe68ba83937dlgao## Pattern to find GUID value in flash description files
5852302d4dee589a5df43a464420c9fe68ba83937dlgaogPcdGuidPattern = re.compile(r"PCD\((\w+)[.](\w+)\)")
5952302d4dee589a5df43a464420c9fe68ba83937dlgao
6052302d4dee589a5df43a464420c9fe68ba83937dlgao## Pattern to collect offset, GUID value pair in the flash report intermediate file
6152302d4dee589a5df43a464420c9fe68ba83937dlgaogOffsetGuidPattern = re.compile(r"(0x[0-9A-Fa-f]+) ([-A-Fa-f0-9]+)")
6252302d4dee589a5df43a464420c9fe68ba83937dlgao
6352302d4dee589a5df43a464420c9fe68ba83937dlgao## Pattern to find module base address and entry point in fixed flash map file
6452302d4dee589a5df43a464420c9fe68ba83937dlgaogModulePattern = r"\n[-\w]+\s*\(([^,]+),\s*BaseAddress=%(Address)s,\s*EntryPoint=%(Address)s\)\s*\(GUID=([-0-9A-Fa-f]+)[^)]*\)"
6552302d4dee589a5df43a464420c9fe68ba83937dlgaogMapFileItemPattern = re.compile(gModulePattern % {"Address" : "(-?0[xX][0-9A-Fa-f]+)"})
6652302d4dee589a5df43a464420c9fe68ba83937dlgao
6752302d4dee589a5df43a464420c9fe68ba83937dlgao## Pattern to find all module referenced header files in source files
6852302d4dee589a5df43a464420c9fe68ba83937dlgaogIncludePattern  = re.compile(r'#include\s*["<]([^">]+)[">]')
6952302d4dee589a5df43a464420c9fe68ba83937dlgaogIncludePattern2 = re.compile(r"#include\s+EFI_([A-Z_]+)\s*[(]\s*(\w+)\s*[)]")
7052302d4dee589a5df43a464420c9fe68ba83937dlgao
7152302d4dee589a5df43a464420c9fe68ba83937dlgao## Pattern to find the entry point for EDK module using EDKII Glue library
7252302d4dee589a5df43a464420c9fe68ba83937dlgaogGlueLibEntryPoint = re.compile(r"__EDKII_GLUE_MODULE_ENTRY_POINT__\s*=\s*(\w+)")
7352302d4dee589a5df43a464420c9fe68ba83937dlgao
7464b2609fcff9d6412eea4c74c8e74bed33dc3235lgao## Tags for MaxLength of line in report
7564b2609fcff9d6412eea4c74c8e74bed33dc3235lgaogLineMaxLength = 120
7664b2609fcff9d6412eea4c74c8e74bed33dc3235lgao
774afd3d042215afe68d00b9ab8c32f063a3a1c03fLiming Gao## Tags for end of line in report
784afd3d042215afe68d00b9ab8c32f063a3a1c03fLiming GaogEndOfLine = "\r\n"
794afd3d042215afe68d00b9ab8c32f063a3a1c03fLiming Gao
8052302d4dee589a5df43a464420c9fe68ba83937dlgao## Tags for section start, end and separator
8147fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong ZhugSectionStart = ">" + "=" * (gLineMaxLength - 2) + "<"
8247fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong ZhugSectionEnd = "<" + "=" * (gLineMaxLength - 2) + ">" + "\n"
8364b2609fcff9d6412eea4c74c8e74bed33dc3235lgaogSectionSep = "=" * gLineMaxLength
8452302d4dee589a5df43a464420c9fe68ba83937dlgao
8552302d4dee589a5df43a464420c9fe68ba83937dlgao## Tags for subsection start, end and separator
8647fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong ZhugSubSectionStart = ">" + "-" * (gLineMaxLength - 2) + "<"
8747fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong ZhugSubSectionEnd = "<" + "-" * (gLineMaxLength - 2) + ">"
8864b2609fcff9d6412eea4c74c8e74bed33dc3235lgaogSubSectionSep = "-" * gLineMaxLength
8964b2609fcff9d6412eea4c74c8e74bed33dc3235lgao
9052302d4dee589a5df43a464420c9fe68ba83937dlgao
9152302d4dee589a5df43a464420c9fe68ba83937dlgao## The look up table to map PCD type to pair of report display type and DEC type
9252302d4dee589a5df43a464420c9fe68ba83937dlgaogPcdTypeMap = {
9352302d4dee589a5df43a464420c9fe68ba83937dlgao  'FixedAtBuild'     : ('FIXED',  'FixedAtBuild'),
9452302d4dee589a5df43a464420c9fe68ba83937dlgao  'PatchableInModule': ('PATCH',  'PatchableInModule'),
9552302d4dee589a5df43a464420c9fe68ba83937dlgao  'FeatureFlag'      : ('FLAG',   'FeatureFlag'),
9652302d4dee589a5df43a464420c9fe68ba83937dlgao  'Dynamic'          : ('DYN',    'Dynamic'),
9752302d4dee589a5df43a464420c9fe68ba83937dlgao  'DynamicHii'       : ('DYNHII', 'Dynamic'),
9852302d4dee589a5df43a464420c9fe68ba83937dlgao  'DynamicVpd'       : ('DYNVPD', 'Dynamic'),
994afd3d042215afe68d00b9ab8c32f063a3a1c03fLiming Gao  'DynamicEx'        : ('DEX',    'DynamicEx'),
1004afd3d042215afe68d00b9ab8c32f063a3a1c03fLiming Gao  'DynamicExHii'     : ('DEXHII', 'DynamicEx'),
1014afd3d042215afe68d00b9ab8c32f063a3a1c03fLiming Gao  'DynamicExVpd'     : ('DEXVPD', 'DynamicEx'),
10252302d4dee589a5df43a464420c9fe68ba83937dlgao  }
10352302d4dee589a5df43a464420c9fe68ba83937dlgao
10452302d4dee589a5df43a464420c9fe68ba83937dlgao## The look up table to map module type to driver type
10552302d4dee589a5df43a464420c9fe68ba83937dlgaogDriverTypeMap = {
10652302d4dee589a5df43a464420c9fe68ba83937dlgao  'SEC'               : '0x3 (SECURITY_CORE)',
10752302d4dee589a5df43a464420c9fe68ba83937dlgao  'PEI_CORE'          : '0x4 (PEI_CORE)',
10852302d4dee589a5df43a464420c9fe68ba83937dlgao  'PEIM'              : '0x6 (PEIM)',
10952302d4dee589a5df43a464420c9fe68ba83937dlgao  'DXE_CORE'          : '0x5 (DXE_CORE)',
11052302d4dee589a5df43a464420c9fe68ba83937dlgao  'DXE_DRIVER'        : '0x7 (DRIVER)',
11152302d4dee589a5df43a464420c9fe68ba83937dlgao  'DXE_SAL_DRIVER'    : '0x7 (DRIVER)',
11252302d4dee589a5df43a464420c9fe68ba83937dlgao  'DXE_SMM_DRIVER'    : '0x7 (DRIVER)',
11352302d4dee589a5df43a464420c9fe68ba83937dlgao  'DXE_RUNTIME_DRIVER': '0x7 (DRIVER)',
11452302d4dee589a5df43a464420c9fe68ba83937dlgao  'UEFI_DRIVER'       : '0x7 (DRIVER)',
11552302d4dee589a5df43a464420c9fe68ba83937dlgao  'UEFI_APPLICATION'  : '0x9 (APPLICATION)',
11652302d4dee589a5df43a464420c9fe68ba83937dlgao  'SMM_CORE'          : '0xD (SMM_CORE)',
11752302d4dee589a5df43a464420c9fe68ba83937dlgao  'SMM_DRIVER'        : '0xA (SMM)', # Extension of module type to support PI 1.1 SMM drivers
11852302d4dee589a5df43a464420c9fe68ba83937dlgao  }
11952302d4dee589a5df43a464420c9fe68ba83937dlgao
120e56468c072e0d53834787f4ad0e292b33cc6be08qhuang## The look up table of the supported opcode in the dependency expression binaries
121e56468c072e0d53834787f4ad0e292b33cc6be08qhuanggOpCodeList = ["BEFORE", "AFTER", "PUSH", "AND", "OR", "NOT", "TRUE", "FALSE", "END", "SOR"]
122e56468c072e0d53834787f4ad0e292b33cc6be08qhuang
12352302d4dee589a5df43a464420c9fe68ba83937dlgao##
12452302d4dee589a5df43a464420c9fe68ba83937dlgao# Writes a string to the file object.
12552302d4dee589a5df43a464420c9fe68ba83937dlgao#
12652302d4dee589a5df43a464420c9fe68ba83937dlgao# This function writes a string to the file object and a new line is appended
12752302d4dee589a5df43a464420c9fe68ba83937dlgao# afterwards. It may optionally wraps the string for better readability.
12852302d4dee589a5df43a464420c9fe68ba83937dlgao#
12952302d4dee589a5df43a464420c9fe68ba83937dlgao# @File                      The file object to write
13052302d4dee589a5df43a464420c9fe68ba83937dlgao# @String                    The string to be written to the file
13152302d4dee589a5df43a464420c9fe68ba83937dlgao# @Wrapper                   Indicates whether to wrap the string
13252302d4dee589a5df43a464420c9fe68ba83937dlgao#
13352302d4dee589a5df43a464420c9fe68ba83937dlgaodef FileWrite(File, String, Wrapper=False):
13452302d4dee589a5df43a464420c9fe68ba83937dlgao    if Wrapper:
13552302d4dee589a5df43a464420c9fe68ba83937dlgao        String = textwrap.fill(String, 120)
1364afd3d042215afe68d00b9ab8c32f063a3a1c03fLiming Gao    File.write(String + gEndOfLine)
13752302d4dee589a5df43a464420c9fe68ba83937dlgao
13852302d4dee589a5df43a464420c9fe68ba83937dlgao##
13952302d4dee589a5df43a464420c9fe68ba83937dlgao# Find all the header file that the module source directly includes.
14052302d4dee589a5df43a464420c9fe68ba83937dlgao#
14152302d4dee589a5df43a464420c9fe68ba83937dlgao# This function scans source code to find all header files the module may
14252302d4dee589a5df43a464420c9fe68ba83937dlgao# include. This is not accurate but very effective to find all the header
14352302d4dee589a5df43a464420c9fe68ba83937dlgao# file the module might include with #include statement.
14452302d4dee589a5df43a464420c9fe68ba83937dlgao#
14552302d4dee589a5df43a464420c9fe68ba83937dlgao# @Source                    The source file name
14652302d4dee589a5df43a464420c9fe68ba83937dlgao# @IncludePathList           The list of include path to find the source file.
14752302d4dee589a5df43a464420c9fe68ba83937dlgao# @IncludeFiles              The dictionary of current found include files.
14852302d4dee589a5df43a464420c9fe68ba83937dlgao#
14952302d4dee589a5df43a464420c9fe68ba83937dlgaodef FindIncludeFiles(Source, IncludePathList, IncludeFiles):
15052302d4dee589a5df43a464420c9fe68ba83937dlgao    FileContents = open(Source).read()
15152302d4dee589a5df43a464420c9fe68ba83937dlgao    #
15252302d4dee589a5df43a464420c9fe68ba83937dlgao    # Find header files with pattern #include "XXX.h" or #include <XXX.h>
15352302d4dee589a5df43a464420c9fe68ba83937dlgao    #
15452302d4dee589a5df43a464420c9fe68ba83937dlgao    for Match in gIncludePattern.finditer(FileContents):
15552302d4dee589a5df43a464420c9fe68ba83937dlgao        FileName = Match.group(1).strip()
15652302d4dee589a5df43a464420c9fe68ba83937dlgao        for Dir in [os.path.dirname(Source)] + IncludePathList:
15752302d4dee589a5df43a464420c9fe68ba83937dlgao            FullFileName = os.path.normpath(os.path.join(Dir, FileName))
15852302d4dee589a5df43a464420c9fe68ba83937dlgao            if os.path.exists(FullFileName):
15952302d4dee589a5df43a464420c9fe68ba83937dlgao                IncludeFiles[FullFileName.lower().replace("\\", "/")] = FullFileName
16052302d4dee589a5df43a464420c9fe68ba83937dlgao                break
16152302d4dee589a5df43a464420c9fe68ba83937dlgao
16252302d4dee589a5df43a464420c9fe68ba83937dlgao    #
16352302d4dee589a5df43a464420c9fe68ba83937dlgao    # Find header files with pattern like #include EFI_PPI_CONSUMER(XXX)
16452302d4dee589a5df43a464420c9fe68ba83937dlgao    #
16552302d4dee589a5df43a464420c9fe68ba83937dlgao    for Match in gIncludePattern2.finditer(FileContents):
16652302d4dee589a5df43a464420c9fe68ba83937dlgao        Key = Match.group(2)
16752302d4dee589a5df43a464420c9fe68ba83937dlgao        Type = Match.group(1)
16852302d4dee589a5df43a464420c9fe68ba83937dlgao        if "ARCH_PROTOCOL" in Type:
16952302d4dee589a5df43a464420c9fe68ba83937dlgao            FileName = "ArchProtocol/%(Key)s/%(Key)s.h" % {"Key" : Key}
17052302d4dee589a5df43a464420c9fe68ba83937dlgao        elif "PROTOCOL" in Type:
17152302d4dee589a5df43a464420c9fe68ba83937dlgao            FileName = "Protocol/%(Key)s/%(Key)s.h" % {"Key" : Key}
17252302d4dee589a5df43a464420c9fe68ba83937dlgao        elif "PPI" in Type:
17352302d4dee589a5df43a464420c9fe68ba83937dlgao            FileName = "Ppi/%(Key)s/%(Key)s.h" % {"Key" : Key}
17452302d4dee589a5df43a464420c9fe68ba83937dlgao        elif "GUID" in Type:
17552302d4dee589a5df43a464420c9fe68ba83937dlgao            FileName = "Guid/%(Key)s/%(Key)s.h" % {"Key" : Key}
17652302d4dee589a5df43a464420c9fe68ba83937dlgao        else:
17752302d4dee589a5df43a464420c9fe68ba83937dlgao            continue
17852302d4dee589a5df43a464420c9fe68ba83937dlgao        for Dir in IncludePathList:
17952302d4dee589a5df43a464420c9fe68ba83937dlgao            FullFileName = os.path.normpath(os.path.join(Dir, FileName))
18052302d4dee589a5df43a464420c9fe68ba83937dlgao            if os.path.exists(FullFileName):
18152302d4dee589a5df43a464420c9fe68ba83937dlgao                IncludeFiles[FullFileName.lower().replace("\\", "/")] = FullFileName
18252302d4dee589a5df43a464420c9fe68ba83937dlgao                break
18352302d4dee589a5df43a464420c9fe68ba83937dlgao
18464b2609fcff9d6412eea4c74c8e74bed33dc3235lgao## Split each lines in file
18564b2609fcff9d6412eea4c74c8e74bed33dc3235lgao#
18664b2609fcff9d6412eea4c74c8e74bed33dc3235lgao#  This method is used to split the lines in file to make the length of each line
18764b2609fcff9d6412eea4c74c8e74bed33dc3235lgao#  less than MaxLength.
18864b2609fcff9d6412eea4c74c8e74bed33dc3235lgao#
18964b2609fcff9d6412eea4c74c8e74bed33dc3235lgao#  @param      Content           The content of file
19064b2609fcff9d6412eea4c74c8e74bed33dc3235lgao#  @param      MaxLength         The Max Length of the line
19164b2609fcff9d6412eea4c74c8e74bed33dc3235lgao#
19264b2609fcff9d6412eea4c74c8e74bed33dc3235lgaodef FileLinesSplit(Content=None, MaxLength=None):
19364b2609fcff9d6412eea4c74c8e74bed33dc3235lgao    ContentList = Content.split(TAB_LINE_BREAK)
19464b2609fcff9d6412eea4c74c8e74bed33dc3235lgao    NewContent = ''
19564b2609fcff9d6412eea4c74c8e74bed33dc3235lgao    NewContentList = []
19664b2609fcff9d6412eea4c74c8e74bed33dc3235lgao    for Line in ContentList:
19764b2609fcff9d6412eea4c74c8e74bed33dc3235lgao        while len(Line.rstrip()) > MaxLength:
19864b2609fcff9d6412eea4c74c8e74bed33dc3235lgao            LineSpaceIndex = Line.rfind(TAB_SPACE_SPLIT, 0, MaxLength)
19964b2609fcff9d6412eea4c74c8e74bed33dc3235lgao            LineSlashIndex = Line.rfind(TAB_SLASH, 0, MaxLength)
20025918452ed5e9d12ea56b3bb2193df9ab96666b1lgao            LineBackSlashIndex = Line.rfind(TAB_BACK_SLASH, 0, MaxLength)
20125918452ed5e9d12ea56b3bb2193df9ab96666b1lgao            if max(LineSpaceIndex, LineSlashIndex, LineBackSlashIndex) > 0:
20225918452ed5e9d12ea56b3bb2193df9ab96666b1lgao                LineBreakIndex = max(LineSpaceIndex, LineSlashIndex, LineBackSlashIndex)
20325918452ed5e9d12ea56b3bb2193df9ab96666b1lgao            else:
20425918452ed5e9d12ea56b3bb2193df9ab96666b1lgao                LineBreakIndex = MaxLength
20564b2609fcff9d6412eea4c74c8e74bed33dc3235lgao            NewContentList.append(Line[:LineBreakIndex])
20664b2609fcff9d6412eea4c74c8e74bed33dc3235lgao            Line = Line[LineBreakIndex:]
20764b2609fcff9d6412eea4c74c8e74bed33dc3235lgao        if Line:
20864b2609fcff9d6412eea4c74c8e74bed33dc3235lgao            NewContentList.append(Line)
20964b2609fcff9d6412eea4c74c8e74bed33dc3235lgao    for NewLine in NewContentList:
21064b2609fcff9d6412eea4c74c8e74bed33dc3235lgao        NewContent += NewLine + TAB_LINE_BREAK
2114afd3d042215afe68d00b9ab8c32f063a3a1c03fLiming Gao
2124afd3d042215afe68d00b9ab8c32f063a3a1c03fLiming Gao    NewContent = NewContent.replace(TAB_LINE_BREAK, gEndOfLine).replace('\r\r\n', gEndOfLine)
21364b2609fcff9d6412eea4c74c8e74bed33dc3235lgao    return NewContent
21464b2609fcff9d6412eea4c74c8e74bed33dc3235lgao
21564b2609fcff9d6412eea4c74c8e74bed33dc3235lgao
21664b2609fcff9d6412eea4c74c8e74bed33dc3235lgao
21752302d4dee589a5df43a464420c9fe68ba83937dlgao##
218e56468c072e0d53834787f4ad0e292b33cc6be08qhuang# Parse binary dependency expression section
219e56468c072e0d53834787f4ad0e292b33cc6be08qhuang#
220e56468c072e0d53834787f4ad0e292b33cc6be08qhuang# This utility class parses the dependency expression section and translate the readable
221e56468c072e0d53834787f4ad0e292b33cc6be08qhuang# GUID name and value.
222e56468c072e0d53834787f4ad0e292b33cc6be08qhuang#
223e56468c072e0d53834787f4ad0e292b33cc6be08qhuangclass DepexParser(object):
224e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    ##
225e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # Constructor function for class DepexParser
226e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    #
227e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # This constructor function collect GUID values so that the readable
228e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # GUID name can be translated.
229e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    #
230e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # @param self            The object pointer
231e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # @param Wa              Workspace context information
232e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    #
233e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    def __init__(self, Wa):
234e56468c072e0d53834787f4ad0e292b33cc6be08qhuang        self._GuidDb = {}
2350d2711a69397d2971079121df4326d84736c181elgao        for Pa in Wa.AutoGenObjectList:
23647fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu            for Package in Pa.PackageList:
2370d2711a69397d2971079121df4326d84736c181elgao                for Protocol in Package.Protocols:
2380d2711a69397d2971079121df4326d84736c181elgao                    GuidValue = GuidStructureStringToGuidString(Package.Protocols[Protocol])
2390d2711a69397d2971079121df4326d84736c181elgao                    self._GuidDb[GuidValue.upper()] = Protocol
2400d2711a69397d2971079121df4326d84736c181elgao                for Ppi in Package.Ppis:
2410d2711a69397d2971079121df4326d84736c181elgao                    GuidValue = GuidStructureStringToGuidString(Package.Ppis[Ppi])
2420d2711a69397d2971079121df4326d84736c181elgao                    self._GuidDb[GuidValue.upper()] = Ppi
2430d2711a69397d2971079121df4326d84736c181elgao                for Guid in Package.Guids:
2440d2711a69397d2971079121df4326d84736c181elgao                    GuidValue = GuidStructureStringToGuidString(Package.Guids[Guid])
2450d2711a69397d2971079121df4326d84736c181elgao                    self._GuidDb[GuidValue.upper()] = Guid
246e56468c072e0d53834787f4ad0e292b33cc6be08qhuang
247e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    ##
248e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # Parse the binary dependency expression files.
249e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    #
250e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # This function parses the binary dependency expression file and translate it
251e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # to the instruction list.
252e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    #
253e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # @param self            The object pointer
254e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # @param DepexFileName   The file name of binary dependency expression file.
255e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    #
256e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    def ParseDepexFile(self, DepexFileName):
257e56468c072e0d53834787f4ad0e292b33cc6be08qhuang        DepexFile = open(DepexFileName, "rb")
258e56468c072e0d53834787f4ad0e292b33cc6be08qhuang        DepexStatement = []
259e56468c072e0d53834787f4ad0e292b33cc6be08qhuang        OpCode = DepexFile.read(1)
260e56468c072e0d53834787f4ad0e292b33cc6be08qhuang        while OpCode:
261e56468c072e0d53834787f4ad0e292b33cc6be08qhuang            Statement = gOpCodeList[struct.unpack("B", OpCode)[0]]
262e56468c072e0d53834787f4ad0e292b33cc6be08qhuang            if Statement in ["BEFORE", "AFTER", "PUSH"]:
263e56468c072e0d53834787f4ad0e292b33cc6be08qhuang                GuidValue = "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X" % \
2642bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming                            struct.unpack("=LHHBBBBBBBB", DepexFile.read(16))
265e56468c072e0d53834787f4ad0e292b33cc6be08qhuang                GuidString = self._GuidDb.get(GuidValue, GuidValue)
266e56468c072e0d53834787f4ad0e292b33cc6be08qhuang                Statement = "%s %s" % (Statement, GuidString)
267e56468c072e0d53834787f4ad0e292b33cc6be08qhuang            DepexStatement.append(Statement)
26847fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu            OpCode = DepexFile.read(1)
26947fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu
270e56468c072e0d53834787f4ad0e292b33cc6be08qhuang        return DepexStatement
271e56468c072e0d53834787f4ad0e292b33cc6be08qhuang
272e56468c072e0d53834787f4ad0e292b33cc6be08qhuang##
27352302d4dee589a5df43a464420c9fe68ba83937dlgao# Reports library information
27452302d4dee589a5df43a464420c9fe68ba83937dlgao#
27552302d4dee589a5df43a464420c9fe68ba83937dlgao# This class reports the module library subsection in the build report file.
27652302d4dee589a5df43a464420c9fe68ba83937dlgao#
27752302d4dee589a5df43a464420c9fe68ba83937dlgaoclass LibraryReport(object):
27852302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
27952302d4dee589a5df43a464420c9fe68ba83937dlgao    # Constructor function for class LibraryReport
28052302d4dee589a5df43a464420c9fe68ba83937dlgao    #
28152302d4dee589a5df43a464420c9fe68ba83937dlgao    # This constructor function generates LibraryReport object for
28252302d4dee589a5df43a464420c9fe68ba83937dlgao    # a module.
28352302d4dee589a5df43a464420c9fe68ba83937dlgao    #
28452302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
28552302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param M               Module context information
28652302d4dee589a5df43a464420c9fe68ba83937dlgao    #
28752302d4dee589a5df43a464420c9fe68ba83937dlgao    def __init__(self, M):
28852302d4dee589a5df43a464420c9fe68ba83937dlgao        self.LibraryList = []
28952302d4dee589a5df43a464420c9fe68ba83937dlgao        if int(str(M.AutoGenVersion), 0) >= 0x00010005:
29052302d4dee589a5df43a464420c9fe68ba83937dlgao            self._EdkIIModule = True
29152302d4dee589a5df43a464420c9fe68ba83937dlgao        else:
29252302d4dee589a5df43a464420c9fe68ba83937dlgao            self._EdkIIModule = False
29352302d4dee589a5df43a464420c9fe68ba83937dlgao
29452302d4dee589a5df43a464420c9fe68ba83937dlgao        for Lib in M.DependentLibraryList:
29552302d4dee589a5df43a464420c9fe68ba83937dlgao            LibInfPath = str(Lib)
29652302d4dee589a5df43a464420c9fe68ba83937dlgao            LibClassList = Lib.LibraryClass[0].LibraryClass
29752302d4dee589a5df43a464420c9fe68ba83937dlgao            LibConstructorList = Lib.ConstructorList
29852302d4dee589a5df43a464420c9fe68ba83937dlgao            LibDesstructorList = Lib.DestructorList
29952302d4dee589a5df43a464420c9fe68ba83937dlgao            LibDepexList = Lib.DepexExpression[M.Arch, M.ModuleType]
30052302d4dee589a5df43a464420c9fe68ba83937dlgao            self.LibraryList.append((LibInfPath, LibClassList, LibConstructorList, LibDesstructorList, LibDepexList))
30152302d4dee589a5df43a464420c9fe68ba83937dlgao
30252302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
30352302d4dee589a5df43a464420c9fe68ba83937dlgao    # Generate report for module library information
30452302d4dee589a5df43a464420c9fe68ba83937dlgao    #
30552302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function generates report for the module library.
30652302d4dee589a5df43a464420c9fe68ba83937dlgao    # If the module is EDKII style one, the additional library class, library
30752302d4dee589a5df43a464420c9fe68ba83937dlgao    # constructor/destructor and dependency expression may also be reported.
30852302d4dee589a5df43a464420c9fe68ba83937dlgao    #
30952302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
31052302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param File            The file object for report
31152302d4dee589a5df43a464420c9fe68ba83937dlgao    #
31252302d4dee589a5df43a464420c9fe68ba83937dlgao    def GenerateReport(self, File):
31352302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSubSectionStart)
31464b2609fcff9d6412eea4c74c8e74bed33dc3235lgao        FileWrite(File, TAB_BRG_LIBRARY)
31552302d4dee589a5df43a464420c9fe68ba83937dlgao        if len(self.LibraryList) > 0:
31652302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, gSubSectionSep)
31752302d4dee589a5df43a464420c9fe68ba83937dlgao            for LibraryItem in self.LibraryList:
31852302d4dee589a5df43a464420c9fe68ba83937dlgao                LibInfPath = LibraryItem[0]
31952302d4dee589a5df43a464420c9fe68ba83937dlgao                FileWrite(File, LibInfPath)
32052302d4dee589a5df43a464420c9fe68ba83937dlgao
32152302d4dee589a5df43a464420c9fe68ba83937dlgao                #
32252302d4dee589a5df43a464420c9fe68ba83937dlgao                # Report library class, library constructor and destructor for
32352302d4dee589a5df43a464420c9fe68ba83937dlgao                # EDKII style module.
32452302d4dee589a5df43a464420c9fe68ba83937dlgao                #
32552302d4dee589a5df43a464420c9fe68ba83937dlgao                if self._EdkIIModule:
32652302d4dee589a5df43a464420c9fe68ba83937dlgao                    LibClass = LibraryItem[1]
32752302d4dee589a5df43a464420c9fe68ba83937dlgao                    EdkIILibInfo = ""
32852302d4dee589a5df43a464420c9fe68ba83937dlgao                    LibConstructor = " ".join(LibraryItem[2])
32952302d4dee589a5df43a464420c9fe68ba83937dlgao                    if LibConstructor:
33052302d4dee589a5df43a464420c9fe68ba83937dlgao                        EdkIILibInfo += " C = " + LibConstructor
33152302d4dee589a5df43a464420c9fe68ba83937dlgao                    LibDestructor = " ".join(LibraryItem[3])
33252302d4dee589a5df43a464420c9fe68ba83937dlgao                    if LibDestructor:
333636f2be673b2f43518167d8fddae56b714f19314lgao                        EdkIILibInfo += " D = " + LibDestructor
33452302d4dee589a5df43a464420c9fe68ba83937dlgao                    LibDepex = " ".join(LibraryItem[4])
33552302d4dee589a5df43a464420c9fe68ba83937dlgao                    if LibDepex:
33652302d4dee589a5df43a464420c9fe68ba83937dlgao                        EdkIILibInfo += " Depex = " + LibDepex
33752302d4dee589a5df43a464420c9fe68ba83937dlgao                    if EdkIILibInfo:
33852302d4dee589a5df43a464420c9fe68ba83937dlgao                        FileWrite(File, "{%s: %s}" % (LibClass, EdkIILibInfo))
33952302d4dee589a5df43a464420c9fe68ba83937dlgao                    else:
34052302d4dee589a5df43a464420c9fe68ba83937dlgao                        FileWrite(File, "{%s}" % LibClass)
34152302d4dee589a5df43a464420c9fe68ba83937dlgao
34252302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSubSectionEnd)
34352302d4dee589a5df43a464420c9fe68ba83937dlgao
34452302d4dee589a5df43a464420c9fe68ba83937dlgao##
34552302d4dee589a5df43a464420c9fe68ba83937dlgao# Reports dependency expression information
34652302d4dee589a5df43a464420c9fe68ba83937dlgao#
34752302d4dee589a5df43a464420c9fe68ba83937dlgao# This class reports the module dependency expression subsection in the build report file.
34852302d4dee589a5df43a464420c9fe68ba83937dlgao#
34952302d4dee589a5df43a464420c9fe68ba83937dlgaoclass DepexReport(object):
35052302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
35152302d4dee589a5df43a464420c9fe68ba83937dlgao    # Constructor function for class DepexReport
35252302d4dee589a5df43a464420c9fe68ba83937dlgao    #
35352302d4dee589a5df43a464420c9fe68ba83937dlgao    # This constructor function generates DepexReport object for
35452302d4dee589a5df43a464420c9fe68ba83937dlgao    # a module. If the module source contains the DXS file (usually EDK
35552302d4dee589a5df43a464420c9fe68ba83937dlgao    # style module), it uses the dependency in DXS file; otherwise,
35652302d4dee589a5df43a464420c9fe68ba83937dlgao    # it uses the dependency expression from its own INF [Depex] section
35752302d4dee589a5df43a464420c9fe68ba83937dlgao    # and then merges with the ones from its dependent library INF.
35852302d4dee589a5df43a464420c9fe68ba83937dlgao    #
35952302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
36052302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param M               Module context information
36152302d4dee589a5df43a464420c9fe68ba83937dlgao    #
36252302d4dee589a5df43a464420c9fe68ba83937dlgao    def __init__(self, M):
36352302d4dee589a5df43a464420c9fe68ba83937dlgao        self.Depex = ""
36447fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu        self._DepexFileName = os.path.join(M.BuildDir, "OUTPUT", M.Module.BaseName + ".depex")
36552302d4dee589a5df43a464420c9fe68ba83937dlgao        ModuleType = M.ModuleType
36652302d4dee589a5df43a464420c9fe68ba83937dlgao        if not ModuleType:
36752302d4dee589a5df43a464420c9fe68ba83937dlgao            ModuleType = gComponentType2ModuleType.get(M.ComponentType, "")
368636f2be673b2f43518167d8fddae56b714f19314lgao
369636f2be673b2f43518167d8fddae56b714f19314lgao        if ModuleType in ["SEC", "PEI_CORE", "DXE_CORE", "SMM_CORE", "UEFI_APPLICATION"]:
37052302d4dee589a5df43a464420c9fe68ba83937dlgao            return
37152302d4dee589a5df43a464420c9fe68ba83937dlgao
37252302d4dee589a5df43a464420c9fe68ba83937dlgao        for Source in M.SourceFileList:
37352302d4dee589a5df43a464420c9fe68ba83937dlgao            if os.path.splitext(Source.Path)[1].lower() == ".dxs":
37452302d4dee589a5df43a464420c9fe68ba83937dlgao                Match = gDxsDependencyPattern.search(open(Source.Path).read())
37552302d4dee589a5df43a464420c9fe68ba83937dlgao                if Match:
37652302d4dee589a5df43a464420c9fe68ba83937dlgao                    self.Depex = Match.group(1).strip()
37752302d4dee589a5df43a464420c9fe68ba83937dlgao                    self.Source = "DXS"
37852302d4dee589a5df43a464420c9fe68ba83937dlgao                    break
37952302d4dee589a5df43a464420c9fe68ba83937dlgao        else:
38052302d4dee589a5df43a464420c9fe68ba83937dlgao            self.Depex = M.DepexExpressionList.get(M.ModuleType, "")
38152302d4dee589a5df43a464420c9fe68ba83937dlgao            self.ModuleDepex = " ".join(M.Module.DepexExpression[M.Arch, M.ModuleType])
38252302d4dee589a5df43a464420c9fe68ba83937dlgao            if not self.ModuleDepex:
38352302d4dee589a5df43a464420c9fe68ba83937dlgao                self.ModuleDepex = "(None)"
38452302d4dee589a5df43a464420c9fe68ba83937dlgao
38552302d4dee589a5df43a464420c9fe68ba83937dlgao            LibDepexList = []
38652302d4dee589a5df43a464420c9fe68ba83937dlgao            for Lib in M.DependentLibraryList:
38752302d4dee589a5df43a464420c9fe68ba83937dlgao                LibDepex = " ".join(Lib.DepexExpression[M.Arch, M.ModuleType]).strip()
38852302d4dee589a5df43a464420c9fe68ba83937dlgao                if LibDepex != "":
38952302d4dee589a5df43a464420c9fe68ba83937dlgao                    LibDepexList.append("(" + LibDepex + ")")
39052302d4dee589a5df43a464420c9fe68ba83937dlgao            self.LibraryDepex = " AND ".join(LibDepexList)
39152302d4dee589a5df43a464420c9fe68ba83937dlgao            if not self.LibraryDepex:
39252302d4dee589a5df43a464420c9fe68ba83937dlgao                self.LibraryDepex = "(None)"
39352302d4dee589a5df43a464420c9fe68ba83937dlgao            self.Source = "INF"
39452302d4dee589a5df43a464420c9fe68ba83937dlgao
39552302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
39652302d4dee589a5df43a464420c9fe68ba83937dlgao    # Generate report for module dependency expression information
39752302d4dee589a5df43a464420c9fe68ba83937dlgao    #
39852302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function generates report for the module dependency expression.
39952302d4dee589a5df43a464420c9fe68ba83937dlgao    #
400e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # @param self              The object pointer
401e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # @param File              The file object for report
402e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # @param GlobalDepexParser The platform global Dependency expression parser object
40352302d4dee589a5df43a464420c9fe68ba83937dlgao    #
404e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    def GenerateReport(self, File, GlobalDepexParser):
40552302d4dee589a5df43a464420c9fe68ba83937dlgao        if not self.Depex:
40664b2609fcff9d6412eea4c74c8e74bed33dc3235lgao            FileWrite(File, gSubSectionStart)
40764b2609fcff9d6412eea4c74c8e74bed33dc3235lgao            FileWrite(File, TAB_DEPEX)
40864b2609fcff9d6412eea4c74c8e74bed33dc3235lgao            FileWrite(File, gSubSectionEnd)
40952302d4dee589a5df43a464420c9fe68ba83937dlgao            return
41052302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSubSectionStart)
411e56468c072e0d53834787f4ad0e292b33cc6be08qhuang        if os.path.isfile(self._DepexFileName):
412e56468c072e0d53834787f4ad0e292b33cc6be08qhuang            try:
413e56468c072e0d53834787f4ad0e292b33cc6be08qhuang                DepexStatements = GlobalDepexParser.ParseDepexFile(self._DepexFileName)
414e56468c072e0d53834787f4ad0e292b33cc6be08qhuang                FileWrite(File, "Final Dependency Expression (DEPEX) Instructions")
415e56468c072e0d53834787f4ad0e292b33cc6be08qhuang                for DepexStatement in DepexStatements:
416e56468c072e0d53834787f4ad0e292b33cc6be08qhuang                    FileWrite(File, "  %s" % DepexStatement)
417e56468c072e0d53834787f4ad0e292b33cc6be08qhuang                FileWrite(File, gSubSectionSep)
418e56468c072e0d53834787f4ad0e292b33cc6be08qhuang            except:
419e56468c072e0d53834787f4ad0e292b33cc6be08qhuang                EdkLogger.warn(None, "Dependency expression file is corrupted", self._DepexFileName)
420e56468c072e0d53834787f4ad0e292b33cc6be08qhuang
42152302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Dependency Expression (DEPEX) from %s" % self.Source)
42252302d4dee589a5df43a464420c9fe68ba83937dlgao
42352302d4dee589a5df43a464420c9fe68ba83937dlgao        if self.Source == "INF":
42452302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "%s" % self.Depex, True)
42552302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, gSubSectionSep)
42652302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "From Module INF:  %s" % self.ModuleDepex, True)
42752302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "From Library INF: %s" % self.LibraryDepex, True)
42852302d4dee589a5df43a464420c9fe68ba83937dlgao        else:
42952302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "%s" % self.Depex)
43052302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSubSectionEnd)
43152302d4dee589a5df43a464420c9fe68ba83937dlgao
43252302d4dee589a5df43a464420c9fe68ba83937dlgao##
43352302d4dee589a5df43a464420c9fe68ba83937dlgao# Reports dependency expression information
43452302d4dee589a5df43a464420c9fe68ba83937dlgao#
43552302d4dee589a5df43a464420c9fe68ba83937dlgao# This class reports the module build flags subsection in the build report file.
43652302d4dee589a5df43a464420c9fe68ba83937dlgao#
43752302d4dee589a5df43a464420c9fe68ba83937dlgaoclass BuildFlagsReport(object):
43852302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
43952302d4dee589a5df43a464420c9fe68ba83937dlgao    # Constructor function for class BuildFlagsReport
44052302d4dee589a5df43a464420c9fe68ba83937dlgao    #
44152302d4dee589a5df43a464420c9fe68ba83937dlgao    # This constructor function generates BuildFlagsReport object for
44252302d4dee589a5df43a464420c9fe68ba83937dlgao    # a module. It reports the build tool chain tag and all relevant
44352302d4dee589a5df43a464420c9fe68ba83937dlgao    # build flags to build the module.
44452302d4dee589a5df43a464420c9fe68ba83937dlgao    #
44552302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
44652302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param M               Module context information
44752302d4dee589a5df43a464420c9fe68ba83937dlgao    #
44852302d4dee589a5df43a464420c9fe68ba83937dlgao    def __init__(self, M):
44952302d4dee589a5df43a464420c9fe68ba83937dlgao        BuildOptions = {}
45052302d4dee589a5df43a464420c9fe68ba83937dlgao        #
45152302d4dee589a5df43a464420c9fe68ba83937dlgao        # Add build flags according to source file extension so that
45252302d4dee589a5df43a464420c9fe68ba83937dlgao        # irrelevant ones can be filtered out.
45352302d4dee589a5df43a464420c9fe68ba83937dlgao        #
45452302d4dee589a5df43a464420c9fe68ba83937dlgao        for Source in M.SourceFileList:
45552302d4dee589a5df43a464420c9fe68ba83937dlgao            Ext = os.path.splitext(Source.File)[1].lower()
45652302d4dee589a5df43a464420c9fe68ba83937dlgao            if Ext in [".c", ".cc", ".cpp"]:
45752302d4dee589a5df43a464420c9fe68ba83937dlgao                BuildOptions["CC"] = 1
45852302d4dee589a5df43a464420c9fe68ba83937dlgao            elif Ext in [".s", ".asm"]:
45952302d4dee589a5df43a464420c9fe68ba83937dlgao                BuildOptions["PP"] = 1
46052302d4dee589a5df43a464420c9fe68ba83937dlgao                BuildOptions["ASM"] = 1
46152302d4dee589a5df43a464420c9fe68ba83937dlgao            elif Ext in [".vfr"]:
46252302d4dee589a5df43a464420c9fe68ba83937dlgao                BuildOptions["VFRPP"] = 1
46352302d4dee589a5df43a464420c9fe68ba83937dlgao                BuildOptions["VFR"] = 1
46452302d4dee589a5df43a464420c9fe68ba83937dlgao            elif Ext in [".dxs"]:
46552302d4dee589a5df43a464420c9fe68ba83937dlgao                BuildOptions["APP"] = 1
46652302d4dee589a5df43a464420c9fe68ba83937dlgao                BuildOptions["CC"] = 1
46752302d4dee589a5df43a464420c9fe68ba83937dlgao            elif Ext in [".asl"]:
46852302d4dee589a5df43a464420c9fe68ba83937dlgao                BuildOptions["ASLPP"] = 1
46952302d4dee589a5df43a464420c9fe68ba83937dlgao                BuildOptions["ASL"] = 1
47052302d4dee589a5df43a464420c9fe68ba83937dlgao            elif Ext in [".aslc"]:
47152302d4dee589a5df43a464420c9fe68ba83937dlgao                BuildOptions["ASLCC"] = 1
47252302d4dee589a5df43a464420c9fe68ba83937dlgao                BuildOptions["ASLDLINK"] = 1
47352302d4dee589a5df43a464420c9fe68ba83937dlgao                BuildOptions["CC"] = 1
47452302d4dee589a5df43a464420c9fe68ba83937dlgao            elif Ext in [".asm16"]:
47552302d4dee589a5df43a464420c9fe68ba83937dlgao                BuildOptions["ASMLINK"] = 1
47652302d4dee589a5df43a464420c9fe68ba83937dlgao            BuildOptions["SLINK"] = 1
47752302d4dee589a5df43a464420c9fe68ba83937dlgao            BuildOptions["DLINK"] = 1
47852302d4dee589a5df43a464420c9fe68ba83937dlgao
47952302d4dee589a5df43a464420c9fe68ba83937dlgao        #
48052302d4dee589a5df43a464420c9fe68ba83937dlgao        # Save module build flags.
48152302d4dee589a5df43a464420c9fe68ba83937dlgao        #
48252302d4dee589a5df43a464420c9fe68ba83937dlgao        self.ToolChainTag = M.ToolChain
48352302d4dee589a5df43a464420c9fe68ba83937dlgao        self.BuildFlags = {}
48452302d4dee589a5df43a464420c9fe68ba83937dlgao        for Tool in BuildOptions:
48552302d4dee589a5df43a464420c9fe68ba83937dlgao            self.BuildFlags[Tool + "_FLAGS"] = M.BuildOption.get(Tool, {}).get("FLAGS", "")
48652302d4dee589a5df43a464420c9fe68ba83937dlgao
48752302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
48852302d4dee589a5df43a464420c9fe68ba83937dlgao    # Generate report for module build flags information
48952302d4dee589a5df43a464420c9fe68ba83937dlgao    #
49052302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function generates report for the module build flags expression.
49152302d4dee589a5df43a464420c9fe68ba83937dlgao    #
49252302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
49352302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param File            The file object for report
49452302d4dee589a5df43a464420c9fe68ba83937dlgao    #
49552302d4dee589a5df43a464420c9fe68ba83937dlgao    def GenerateReport(self, File):
49652302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSubSectionStart)
49752302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Build Flags")
49852302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Tool Chain Tag: %s" % self.ToolChainTag)
49952302d4dee589a5df43a464420c9fe68ba83937dlgao        for Tool in self.BuildFlags:
50052302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, gSubSectionSep)
50152302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "%s = %s" % (Tool, self.BuildFlags[Tool]), True)
50252302d4dee589a5df43a464420c9fe68ba83937dlgao
50352302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSubSectionEnd)
50452302d4dee589a5df43a464420c9fe68ba83937dlgao
50552302d4dee589a5df43a464420c9fe68ba83937dlgao
50652302d4dee589a5df43a464420c9fe68ba83937dlgao##
50752302d4dee589a5df43a464420c9fe68ba83937dlgao# Reports individual module information
50852302d4dee589a5df43a464420c9fe68ba83937dlgao#
50952302d4dee589a5df43a464420c9fe68ba83937dlgao# This class reports the module section in the build report file.
51052302d4dee589a5df43a464420c9fe68ba83937dlgao# It comprises of module summary, module PCD, library, dependency expression,
51152302d4dee589a5df43a464420c9fe68ba83937dlgao# build flags sections.
51252302d4dee589a5df43a464420c9fe68ba83937dlgao#
51352302d4dee589a5df43a464420c9fe68ba83937dlgaoclass ModuleReport(object):
51452302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
51552302d4dee589a5df43a464420c9fe68ba83937dlgao    # Constructor function for class ModuleReport
51652302d4dee589a5df43a464420c9fe68ba83937dlgao    #
51752302d4dee589a5df43a464420c9fe68ba83937dlgao    # This constructor function generates ModuleReport object for
51852302d4dee589a5df43a464420c9fe68ba83937dlgao    # a separate module in a platform build.
51952302d4dee589a5df43a464420c9fe68ba83937dlgao    #
52052302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
52152302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param M               Module context information
52252302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param ReportType      The kind of report items in the final report file
52352302d4dee589a5df43a464420c9fe68ba83937dlgao    #
52452302d4dee589a5df43a464420c9fe68ba83937dlgao    def __init__(self, M, ReportType):
52552302d4dee589a5df43a464420c9fe68ba83937dlgao        self.ModuleName = M.Module.BaseName
52652302d4dee589a5df43a464420c9fe68ba83937dlgao        self.ModuleInfPath = M.MetaFile.File
52752302d4dee589a5df43a464420c9fe68ba83937dlgao        self.FileGuid = M.Guid
52852302d4dee589a5df43a464420c9fe68ba83937dlgao        self.Size = 0
52952302d4dee589a5df43a464420c9fe68ba83937dlgao        self.BuildTimeStamp = None
53052302d4dee589a5df43a464420c9fe68ba83937dlgao        self.DriverType = ""
531636f2be673b2f43518167d8fddae56b714f19314lgao        if not M.IsLibrary:
532636f2be673b2f43518167d8fddae56b714f19314lgao            ModuleType = M.ModuleType
533636f2be673b2f43518167d8fddae56b714f19314lgao            if not ModuleType:
534636f2be673b2f43518167d8fddae56b714f19314lgao                ModuleType = gComponentType2ModuleType.get(M.ComponentType, "")
535636f2be673b2f43518167d8fddae56b714f19314lgao            #
536636f2be673b2f43518167d8fddae56b714f19314lgao            # If a module complies to PI 1.1, promote Module type to "SMM_DRIVER"
537636f2be673b2f43518167d8fddae56b714f19314lgao            #
538636f2be673b2f43518167d8fddae56b714f19314lgao            if ModuleType == "DXE_SMM_DRIVER":
53947fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu                PiSpec = M.Module.Specification.get("PI_SPECIFICATION_VERSION", "0x00010000")
5400d2711a69397d2971079121df4326d84736c181elgao                if int(PiSpec, 0) >= 0x0001000A:
541636f2be673b2f43518167d8fddae56b714f19314lgao                    ModuleType = "SMM_DRIVER"
542636f2be673b2f43518167d8fddae56b714f19314lgao            self.DriverType = gDriverTypeMap.get(ModuleType, "0x2 (FREE_FORM)")
54352302d4dee589a5df43a464420c9fe68ba83937dlgao        self.UefiSpecVersion = M.Module.Specification.get("UEFI_SPECIFICATION_VERSION", "")
54452302d4dee589a5df43a464420c9fe68ba83937dlgao        self.PiSpecVersion = M.Module.Specification.get("PI_SPECIFICATION_VERSION", "")
54552302d4dee589a5df43a464420c9fe68ba83937dlgao        self.PciDeviceId = M.Module.Defines.get("PCI_DEVICE_ID", "")
54652302d4dee589a5df43a464420c9fe68ba83937dlgao        self.PciVendorId = M.Module.Defines.get("PCI_VENDOR_ID", "")
54752302d4dee589a5df43a464420c9fe68ba83937dlgao        self.PciClassCode = M.Module.Defines.get("PCI_CLASS_CODE", "")
54852302d4dee589a5df43a464420c9fe68ba83937dlgao
54952302d4dee589a5df43a464420c9fe68ba83937dlgao        self._BuildDir = M.BuildDir
55052302d4dee589a5df43a464420c9fe68ba83937dlgao        self.ModulePcdSet = {}
55152302d4dee589a5df43a464420c9fe68ba83937dlgao        if "PCD" in ReportType:
55252302d4dee589a5df43a464420c9fe68ba83937dlgao            #
55352302d4dee589a5df43a464420c9fe68ba83937dlgao            # Collect all module used PCD set: module INF referenced directly or indirectly.
55452302d4dee589a5df43a464420c9fe68ba83937dlgao            # It also saves module INF default values of them in case they exist.
55552302d4dee589a5df43a464420c9fe68ba83937dlgao            #
55652302d4dee589a5df43a464420c9fe68ba83937dlgao            for Pcd in M.ModulePcdList + M.LibraryPcdList:
55752302d4dee589a5df43a464420c9fe68ba83937dlgao                self.ModulePcdSet.setdefault((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Type), (Pcd.InfDefaultValue, Pcd.DefaultValue))
55852302d4dee589a5df43a464420c9fe68ba83937dlgao
55952302d4dee589a5df43a464420c9fe68ba83937dlgao        self.LibraryReport = None
56052302d4dee589a5df43a464420c9fe68ba83937dlgao        if "LIBRARY" in ReportType:
56152302d4dee589a5df43a464420c9fe68ba83937dlgao            self.LibraryReport = LibraryReport(M)
56252302d4dee589a5df43a464420c9fe68ba83937dlgao
56352302d4dee589a5df43a464420c9fe68ba83937dlgao        self.DepexReport = None
56452302d4dee589a5df43a464420c9fe68ba83937dlgao        if "DEPEX" in ReportType:
56552302d4dee589a5df43a464420c9fe68ba83937dlgao            self.DepexReport = DepexReport(M)
56652302d4dee589a5df43a464420c9fe68ba83937dlgao
56752302d4dee589a5df43a464420c9fe68ba83937dlgao        if "BUILD_FLAGS" in ReportType:
56852302d4dee589a5df43a464420c9fe68ba83937dlgao            self.BuildFlagsReport = BuildFlagsReport(M)
56952302d4dee589a5df43a464420c9fe68ba83937dlgao
57052302d4dee589a5df43a464420c9fe68ba83937dlgao
57152302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
57252302d4dee589a5df43a464420c9fe68ba83937dlgao    # Generate report for module information
57352302d4dee589a5df43a464420c9fe68ba83937dlgao    #
57452302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function generates report for separate module expression
57552302d4dee589a5df43a464420c9fe68ba83937dlgao    # in a platform build.
57652302d4dee589a5df43a464420c9fe68ba83937dlgao    #
577e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # @param self                   The object pointer
578e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # @param File                   The file object for report
579e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # @param GlobalPcdReport        The platform global PCD report object
580e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # @param GlobalPredictionReport The platform global Prediction report object
581e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # @param GlobalDepexParser      The platform global Dependency expression parser object
582e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    # @param ReportType             The kind of report items in the final report file
58352302d4dee589a5df43a464420c9fe68ba83937dlgao    #
584e56468c072e0d53834787f4ad0e292b33cc6be08qhuang    def GenerateReport(self, File, GlobalPcdReport, GlobalPredictionReport, GlobalDepexParser, ReportType):
58552302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSectionStart)
58652302d4dee589a5df43a464420c9fe68ba83937dlgao
58752302d4dee589a5df43a464420c9fe68ba83937dlgao        FwReportFileName = os.path.join(self._BuildDir, "DEBUG", self.ModuleName + ".txt")
58852302d4dee589a5df43a464420c9fe68ba83937dlgao        if os.path.isfile(FwReportFileName):
58952302d4dee589a5df43a464420c9fe68ba83937dlgao            try:
59052302d4dee589a5df43a464420c9fe68ba83937dlgao                FileContents = open(FwReportFileName).read()
59152302d4dee589a5df43a464420c9fe68ba83937dlgao                Match = gModuleSizePattern.search(FileContents)
59252302d4dee589a5df43a464420c9fe68ba83937dlgao                if Match:
59352302d4dee589a5df43a464420c9fe68ba83937dlgao                    self.Size = int(Match.group(1))
59452302d4dee589a5df43a464420c9fe68ba83937dlgao
59552302d4dee589a5df43a464420c9fe68ba83937dlgao                Match = gTimeStampPattern.search(FileContents)
59652302d4dee589a5df43a464420c9fe68ba83937dlgao                if Match:
59752302d4dee589a5df43a464420c9fe68ba83937dlgao                    self.BuildTimeStamp = datetime.fromtimestamp(int(Match.group(1)))
59852302d4dee589a5df43a464420c9fe68ba83937dlgao            except IOError:
59952302d4dee589a5df43a464420c9fe68ba83937dlgao                EdkLogger.warn(None, "Fail to read report file", FwReportFileName)
60052302d4dee589a5df43a464420c9fe68ba83937dlgao
60152302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Module Summary")
60252302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Module Name:          %s" % self.ModuleName)
60352302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Module INF Path:      %s" % self.ModuleInfPath)
60452302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "File GUID:            %s" % self.FileGuid)
60552302d4dee589a5df43a464420c9fe68ba83937dlgao        if self.Size:
60652302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "Size:                 0x%X (%.2fK)" % (self.Size, self.Size / 1024.0))
60752302d4dee589a5df43a464420c9fe68ba83937dlgao        if self.BuildTimeStamp:
60852302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "Build Time Stamp:     %s" % self.BuildTimeStamp)
60952302d4dee589a5df43a464420c9fe68ba83937dlgao        if self.DriverType:
61052302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "Driver Type:          %s" % self.DriverType)
61152302d4dee589a5df43a464420c9fe68ba83937dlgao        if self.UefiSpecVersion:
61252302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "UEFI Spec Version:    %s" % self.UefiSpecVersion)
61352302d4dee589a5df43a464420c9fe68ba83937dlgao        if self.PiSpecVersion:
61452302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "PI Spec Version:      %s" % self.PiSpecVersion)
61552302d4dee589a5df43a464420c9fe68ba83937dlgao        if self.PciDeviceId:
61652302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "PCI Device ID:        %s" % self.PciDeviceId)
61752302d4dee589a5df43a464420c9fe68ba83937dlgao        if self.PciVendorId:
61852302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "PCI Vendor ID:        %s" % self.PciVendorId)
61952302d4dee589a5df43a464420c9fe68ba83937dlgao        if self.PciClassCode:
62052302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "PCI Class Code:       %s" % self.PciClassCode)
62152302d4dee589a5df43a464420c9fe68ba83937dlgao
62252302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSectionSep)
62352302d4dee589a5df43a464420c9fe68ba83937dlgao
62452302d4dee589a5df43a464420c9fe68ba83937dlgao        if "PCD" in ReportType:
62552302d4dee589a5df43a464420c9fe68ba83937dlgao            GlobalPcdReport.GenerateReport(File, self.ModulePcdSet)
62652302d4dee589a5df43a464420c9fe68ba83937dlgao
62752302d4dee589a5df43a464420c9fe68ba83937dlgao        if "LIBRARY" in ReportType:
62852302d4dee589a5df43a464420c9fe68ba83937dlgao            self.LibraryReport.GenerateReport(File)
62952302d4dee589a5df43a464420c9fe68ba83937dlgao
63052302d4dee589a5df43a464420c9fe68ba83937dlgao        if "DEPEX" in ReportType:
631e56468c072e0d53834787f4ad0e292b33cc6be08qhuang            self.DepexReport.GenerateReport(File, GlobalDepexParser)
63252302d4dee589a5df43a464420c9fe68ba83937dlgao
63352302d4dee589a5df43a464420c9fe68ba83937dlgao        if "BUILD_FLAGS" in ReportType:
63452302d4dee589a5df43a464420c9fe68ba83937dlgao            self.BuildFlagsReport.GenerateReport(File)
63552302d4dee589a5df43a464420c9fe68ba83937dlgao
63652302d4dee589a5df43a464420c9fe68ba83937dlgao        if "FIXED_ADDRESS" in ReportType and self.FileGuid:
63752302d4dee589a5df43a464420c9fe68ba83937dlgao            GlobalPredictionReport.GenerateReport(File, self.FileGuid)
63852302d4dee589a5df43a464420c9fe68ba83937dlgao
63952302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSectionEnd)
64052302d4dee589a5df43a464420c9fe68ba83937dlgao
64152302d4dee589a5df43a464420c9fe68ba83937dlgao##
64252302d4dee589a5df43a464420c9fe68ba83937dlgao# Reports platform and module PCD information
64352302d4dee589a5df43a464420c9fe68ba83937dlgao#
64452302d4dee589a5df43a464420c9fe68ba83937dlgao# This class reports the platform PCD section and module PCD subsection
64552302d4dee589a5df43a464420c9fe68ba83937dlgao# in the build report file.
64652302d4dee589a5df43a464420c9fe68ba83937dlgao#
64752302d4dee589a5df43a464420c9fe68ba83937dlgaoclass PcdReport(object):
64852302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
64952302d4dee589a5df43a464420c9fe68ba83937dlgao    # Constructor function for class PcdReport
65052302d4dee589a5df43a464420c9fe68ba83937dlgao    #
65152302d4dee589a5df43a464420c9fe68ba83937dlgao    # This constructor function generates PcdReport object a platform build.
65252302d4dee589a5df43a464420c9fe68ba83937dlgao    # It collects the whole PCD database from platform DSC files, platform
65352302d4dee589a5df43a464420c9fe68ba83937dlgao    # flash description file and package DEC files.
65452302d4dee589a5df43a464420c9fe68ba83937dlgao    #
65552302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
65652302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param Wa              Workspace context information
65752302d4dee589a5df43a464420c9fe68ba83937dlgao    #
65852302d4dee589a5df43a464420c9fe68ba83937dlgao    def __init__(self, Wa):
65952302d4dee589a5df43a464420c9fe68ba83937dlgao        self.AllPcds = {}
66052302d4dee589a5df43a464420c9fe68ba83937dlgao        self.MaxLen = 0
66152302d4dee589a5df43a464420c9fe68ba83937dlgao        if Wa.FdfProfile:
66252302d4dee589a5df43a464420c9fe68ba83937dlgao            self.FdfPcdSet = Wa.FdfProfile.PcdDict
66352302d4dee589a5df43a464420c9fe68ba83937dlgao        else:
66452302d4dee589a5df43a464420c9fe68ba83937dlgao            self.FdfPcdSet = {}
66552302d4dee589a5df43a464420c9fe68ba83937dlgao
66652302d4dee589a5df43a464420c9fe68ba83937dlgao        self.ModulePcdOverride = {}
66752302d4dee589a5df43a464420c9fe68ba83937dlgao        for Pa in Wa.AutoGenObjectList:
66852302d4dee589a5df43a464420c9fe68ba83937dlgao            #
66952302d4dee589a5df43a464420c9fe68ba83937dlgao            # Collect all platform referenced PCDs and grouped them by PCD token space
67052302d4dee589a5df43a464420c9fe68ba83937dlgao            # GUID C Names
67152302d4dee589a5df43a464420c9fe68ba83937dlgao            #
67252302d4dee589a5df43a464420c9fe68ba83937dlgao            for Pcd in Pa.AllPcdList:
67352302d4dee589a5df43a464420c9fe68ba83937dlgao                PcdList = self.AllPcds.setdefault(Pcd.TokenSpaceGuidCName, {}).setdefault(Pcd.Type, [])
67452302d4dee589a5df43a464420c9fe68ba83937dlgao                if Pcd not in PcdList:
67552302d4dee589a5df43a464420c9fe68ba83937dlgao                    PcdList.append(Pcd)
67652302d4dee589a5df43a464420c9fe68ba83937dlgao                if len(Pcd.TokenCName) > self.MaxLen:
67752302d4dee589a5df43a464420c9fe68ba83937dlgao                    self.MaxLen = len(Pcd.TokenCName)
67852302d4dee589a5df43a464420c9fe68ba83937dlgao
67952302d4dee589a5df43a464420c9fe68ba83937dlgao            for Module in Pa.Platform.Modules.values():
68052302d4dee589a5df43a464420c9fe68ba83937dlgao                #
68152302d4dee589a5df43a464420c9fe68ba83937dlgao                # Collect module override PCDs
68252302d4dee589a5df43a464420c9fe68ba83937dlgao                #
68352302d4dee589a5df43a464420c9fe68ba83937dlgao                for ModulePcd in Module.M.ModulePcdList + Module.M.LibraryPcdList:
68452302d4dee589a5df43a464420c9fe68ba83937dlgao                    TokenCName = ModulePcd.TokenCName
68552302d4dee589a5df43a464420c9fe68ba83937dlgao                    TokenSpaceGuid = ModulePcd.TokenSpaceGuidCName
68652302d4dee589a5df43a464420c9fe68ba83937dlgao                    ModuleDefault = ModulePcd.DefaultValue
68752302d4dee589a5df43a464420c9fe68ba83937dlgao                    ModulePath = os.path.basename(Module.M.MetaFile.File)
68852302d4dee589a5df43a464420c9fe68ba83937dlgao                    self.ModulePcdOverride.setdefault((TokenCName, TokenSpaceGuid), {})[ModulePath] = ModuleDefault
68952302d4dee589a5df43a464420c9fe68ba83937dlgao
69052302d4dee589a5df43a464420c9fe68ba83937dlgao
69152302d4dee589a5df43a464420c9fe68ba83937dlgao        #
69252302d4dee589a5df43a464420c9fe68ba83937dlgao        # Collect PCD DEC default value.
69352302d4dee589a5df43a464420c9fe68ba83937dlgao        #
69452302d4dee589a5df43a464420c9fe68ba83937dlgao        self.DecPcdDefault = {}
6950d2711a69397d2971079121df4326d84736c181elgao        for Pa in Wa.AutoGenObjectList:
6960d2711a69397d2971079121df4326d84736c181elgao            for Package in Pa.PackageList:
6970d2711a69397d2971079121df4326d84736c181elgao                for (TokenCName, TokenSpaceGuidCName, DecType) in Package.Pcds:
6980d2711a69397d2971079121df4326d84736c181elgao                    DecDefaultValue = Package.Pcds[TokenCName, TokenSpaceGuidCName, DecType].DefaultValue
6990d2711a69397d2971079121df4326d84736c181elgao                    self.DecPcdDefault.setdefault((TokenCName, TokenSpaceGuidCName, DecType), DecDefaultValue)
70052302d4dee589a5df43a464420c9fe68ba83937dlgao        #
70152302d4dee589a5df43a464420c9fe68ba83937dlgao        # Collect PCDs defined in DSC common section
70252302d4dee589a5df43a464420c9fe68ba83937dlgao        #
70352302d4dee589a5df43a464420c9fe68ba83937dlgao        self.DscPcdDefault = {}
7044afd3d042215afe68d00b9ab8c32f063a3a1c03fLiming Gao        for Arch in Wa.ArchList:
7054afd3d042215afe68d00b9ab8c32f063a3a1c03fLiming Gao            Platform = Wa.BuildDatabase[Wa.MetaFile, Arch, Wa.BuildTarget, Wa.ToolChain]
70652302d4dee589a5df43a464420c9fe68ba83937dlgao            for (TokenCName, TokenSpaceGuidCName) in Platform.Pcds:
70752302d4dee589a5df43a464420c9fe68ba83937dlgao                DscDefaultValue = Platform.Pcds[(TokenCName, TokenSpaceGuidCName)].DefaultValue
70840d841f6a8f84e75409178e19e69b95e01bada0flgao                if DscDefaultValue:
70940d841f6a8f84e75409178e19e69b95e01bada0flgao                    self.DscPcdDefault[(TokenCName, TokenSpaceGuidCName)] = DscDefaultValue
71052302d4dee589a5df43a464420c9fe68ba83937dlgao
71152302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
71252302d4dee589a5df43a464420c9fe68ba83937dlgao    # Generate report for PCD information
71352302d4dee589a5df43a464420c9fe68ba83937dlgao    #
71452302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function generates report for separate module expression
71552302d4dee589a5df43a464420c9fe68ba83937dlgao    # in a platform build.
71652302d4dee589a5df43a464420c9fe68ba83937dlgao    #
71752302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
71852302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param File            The file object for report
71952302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param ModulePcdSet    Set of all PCDs referenced by module or None for
72052302d4dee589a5df43a464420c9fe68ba83937dlgao    #                        platform PCD report
72152302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param DscOverridePcds Module DSC override PCDs set
72252302d4dee589a5df43a464420c9fe68ba83937dlgao    #
72352302d4dee589a5df43a464420c9fe68ba83937dlgao    def GenerateReport(self, File, ModulePcdSet):
72452302d4dee589a5df43a464420c9fe68ba83937dlgao        if ModulePcdSet == None:
72552302d4dee589a5df43a464420c9fe68ba83937dlgao            #
72652302d4dee589a5df43a464420c9fe68ba83937dlgao            # For platform global PCD section
72752302d4dee589a5df43a464420c9fe68ba83937dlgao            #
72852302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, gSectionStart)
72952302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "Platform Configuration Database Report")
73052302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "  *P  - Platform scoped PCD override in DSC file")
73152302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "  *F  - Platform scoped PCD override in FDF file")
73279714906ae765f161969dfddc34adee857be97d6qhuang            FileWrite(File, "  *M  - Module scoped PCD override")
73352302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, gSectionSep)
73452302d4dee589a5df43a464420c9fe68ba83937dlgao        else:
73552302d4dee589a5df43a464420c9fe68ba83937dlgao            #
73652302d4dee589a5df43a464420c9fe68ba83937dlgao            # For module PCD sub-section
73752302d4dee589a5df43a464420c9fe68ba83937dlgao            #
73852302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, gSubSectionStart)
73964b2609fcff9d6412eea4c74c8e74bed33dc3235lgao            FileWrite(File, TAB_BRG_PCD)
74052302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, gSubSectionSep)
74152302d4dee589a5df43a464420c9fe68ba83937dlgao
74252302d4dee589a5df43a464420c9fe68ba83937dlgao        for Key in self.AllPcds:
74352302d4dee589a5df43a464420c9fe68ba83937dlgao            #
74452302d4dee589a5df43a464420c9fe68ba83937dlgao            # Group PCD by their token space GUID C Name
74552302d4dee589a5df43a464420c9fe68ba83937dlgao            #
74652302d4dee589a5df43a464420c9fe68ba83937dlgao            First = True
74752302d4dee589a5df43a464420c9fe68ba83937dlgao            for Type in self.AllPcds[Key]:
74852302d4dee589a5df43a464420c9fe68ba83937dlgao                #
74952302d4dee589a5df43a464420c9fe68ba83937dlgao                # Group PCD by their usage type
75052302d4dee589a5df43a464420c9fe68ba83937dlgao                #
75152302d4dee589a5df43a464420c9fe68ba83937dlgao                TypeName, DecType = gPcdTypeMap.get(Type, ("", Type))
75252302d4dee589a5df43a464420c9fe68ba83937dlgao                for Pcd in self.AllPcds[Key][Type]:
75352302d4dee589a5df43a464420c9fe68ba83937dlgao                    #
75452302d4dee589a5df43a464420c9fe68ba83937dlgao                    # Get PCD default value and their override relationship
75552302d4dee589a5df43a464420c9fe68ba83937dlgao                    #
75652302d4dee589a5df43a464420c9fe68ba83937dlgao                    DecDefaultValue = self.DecPcdDefault.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, DecType))
75752302d4dee589a5df43a464420c9fe68ba83937dlgao                    DscDefaultValue = self.DscPcdDefault.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))
75852302d4dee589a5df43a464420c9fe68ba83937dlgao                    DscDefaultValue = self.FdfPcdSet.get((Pcd.TokenCName, Key), DscDefaultValue)
75952302d4dee589a5df43a464420c9fe68ba83937dlgao                    InfDefaultValue = None
76052302d4dee589a5df43a464420c9fe68ba83937dlgao
76152302d4dee589a5df43a464420c9fe68ba83937dlgao                    PcdValue = DecDefaultValue
76252302d4dee589a5df43a464420c9fe68ba83937dlgao                    if DscDefaultValue:
76352302d4dee589a5df43a464420c9fe68ba83937dlgao                        PcdValue = DscDefaultValue
76452302d4dee589a5df43a464420c9fe68ba83937dlgao                    if ModulePcdSet != None:
76552302d4dee589a5df43a464420c9fe68ba83937dlgao                        if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Type) not in ModulePcdSet:
76652302d4dee589a5df43a464420c9fe68ba83937dlgao                            continue
76752302d4dee589a5df43a464420c9fe68ba83937dlgao                        InfDefault, PcdValue = ModulePcdSet[Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Type]
76852302d4dee589a5df43a464420c9fe68ba83937dlgao                        if InfDefault == "":
76952302d4dee589a5df43a464420c9fe68ba83937dlgao                            InfDefault = None
77052302d4dee589a5df43a464420c9fe68ba83937dlgao                    if First:
77152302d4dee589a5df43a464420c9fe68ba83937dlgao                        if ModulePcdSet == None:
77252302d4dee589a5df43a464420c9fe68ba83937dlgao                            FileWrite(File, "")
77352302d4dee589a5df43a464420c9fe68ba83937dlgao                        FileWrite(File, Key)
77452302d4dee589a5df43a464420c9fe68ba83937dlgao                        First = False
77552302d4dee589a5df43a464420c9fe68ba83937dlgao
77652302d4dee589a5df43a464420c9fe68ba83937dlgao
77752302d4dee589a5df43a464420c9fe68ba83937dlgao                    if Pcd.DatumType in ('UINT8', 'UINT16', 'UINT32', 'UINT64'):
77852302d4dee589a5df43a464420c9fe68ba83937dlgao                        PcdValueNumber = int(PcdValue.strip(), 0)
77952302d4dee589a5df43a464420c9fe68ba83937dlgao                        if DecDefaultValue == None:
78052302d4dee589a5df43a464420c9fe68ba83937dlgao                            DecMatch = True
78152302d4dee589a5df43a464420c9fe68ba83937dlgao                        else:
78252302d4dee589a5df43a464420c9fe68ba83937dlgao                            DecDefaultValueNumber = int(DecDefaultValue.strip(), 0)
78352302d4dee589a5df43a464420c9fe68ba83937dlgao                            DecMatch = (DecDefaultValueNumber == PcdValueNumber)
78452302d4dee589a5df43a464420c9fe68ba83937dlgao
78552302d4dee589a5df43a464420c9fe68ba83937dlgao                        if InfDefaultValue == None:
78652302d4dee589a5df43a464420c9fe68ba83937dlgao                            InfMatch = True
78752302d4dee589a5df43a464420c9fe68ba83937dlgao                        else:
78852302d4dee589a5df43a464420c9fe68ba83937dlgao                            InfDefaultValueNumber = int(InfDefaultValue.strip(), 0)
78952302d4dee589a5df43a464420c9fe68ba83937dlgao                            InfMatch = (InfDefaultValueNumber == PcdValueNumber)
79052302d4dee589a5df43a464420c9fe68ba83937dlgao
79152302d4dee589a5df43a464420c9fe68ba83937dlgao                        if DscDefaultValue == None:
79252302d4dee589a5df43a464420c9fe68ba83937dlgao                            DscMatch = True
79352302d4dee589a5df43a464420c9fe68ba83937dlgao                        else:
79452302d4dee589a5df43a464420c9fe68ba83937dlgao                            DscDefaultValueNumber = int(DscDefaultValue.strip(), 0)
79552302d4dee589a5df43a464420c9fe68ba83937dlgao                            DscMatch = (DscDefaultValueNumber == PcdValueNumber)
79652302d4dee589a5df43a464420c9fe68ba83937dlgao                    else:
79752302d4dee589a5df43a464420c9fe68ba83937dlgao                        if DecDefaultValue == None:
79852302d4dee589a5df43a464420c9fe68ba83937dlgao                            DecMatch = True
79952302d4dee589a5df43a464420c9fe68ba83937dlgao                        else:
800d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao                            DecMatch = (DecDefaultValue.strip() == PcdValue.strip())
80152302d4dee589a5df43a464420c9fe68ba83937dlgao
80252302d4dee589a5df43a464420c9fe68ba83937dlgao                        if InfDefaultValue == None:
80352302d4dee589a5df43a464420c9fe68ba83937dlgao                            InfMatch = True
80452302d4dee589a5df43a464420c9fe68ba83937dlgao                        else:
805d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao                            InfMatch = (InfDefaultValue.strip() == PcdValue.strip())
80652302d4dee589a5df43a464420c9fe68ba83937dlgao
80752302d4dee589a5df43a464420c9fe68ba83937dlgao                        if DscDefaultValue == None:
80852302d4dee589a5df43a464420c9fe68ba83937dlgao                            DscMatch = True
80952302d4dee589a5df43a464420c9fe68ba83937dlgao                        else:
810d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao                            DscMatch = (DscDefaultValue.strip() == PcdValue.strip())
81152302d4dee589a5df43a464420c9fe68ba83937dlgao
81252302d4dee589a5df43a464420c9fe68ba83937dlgao                    #
81352302d4dee589a5df43a464420c9fe68ba83937dlgao                    # Report PCD item according to their override relationship
81452302d4dee589a5df43a464420c9fe68ba83937dlgao                    #
81552302d4dee589a5df43a464420c9fe68ba83937dlgao                    if DecMatch and InfMatch:
81647fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu                        FileWrite(File, '    %-*s: %6s %10s = %-22s' % (self.MaxLen, Pcd.TokenCName, TypeName, '(' + Pcd.DatumType + ')', PcdValue.strip()))
81752302d4dee589a5df43a464420c9fe68ba83937dlgao                    else:
81852302d4dee589a5df43a464420c9fe68ba83937dlgao                        if DscMatch:
81952302d4dee589a5df43a464420c9fe68ba83937dlgao                            if (Pcd.TokenCName, Key) in self.FdfPcdSet:
82047fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu                                FileWrite(File, ' *F %-*s: %6s %10s = %-22s' % (self.MaxLen, Pcd.TokenCName, TypeName, '(' + Pcd.DatumType + ')', PcdValue.strip()))
82152302d4dee589a5df43a464420c9fe68ba83937dlgao                            else:
82247fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu                                FileWrite(File, ' *P %-*s: %6s %10s = %-22s' % (self.MaxLen, Pcd.TokenCName, TypeName, '(' + Pcd.DatumType + ')', PcdValue.strip()))
82352302d4dee589a5df43a464420c9fe68ba83937dlgao                        else:
82447fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu                            FileWrite(File, ' *M %-*s: %6s %10s = %-22s' % (self.MaxLen, Pcd.TokenCName, TypeName, '(' + Pcd.DatumType + ')', PcdValue.strip()))
82547fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu
82652302d4dee589a5df43a464420c9fe68ba83937dlgao                    if TypeName in ('DYNHII', 'DEXHII', 'DYNVPD', 'DEXVPD'):
82752302d4dee589a5df43a464420c9fe68ba83937dlgao                        for SkuInfo in Pcd.SkuInfoList.values():
82852302d4dee589a5df43a464420c9fe68ba83937dlgao                            if TypeName in ('DYNHII', 'DEXHII'):
82947fea6afd74af76c7e2a2b03d319b7ac035ac26aYonghong Zhu                                FileWrite(File, '%*s: %s: %s' % (self.MaxLen + 4, SkuInfo.VariableGuid, SkuInfo.VariableName, SkuInfo.VariableOffset))
83052302d4dee589a5df43a464420c9fe68ba83937dlgao                            else:
83152302d4dee589a5df43a464420c9fe68ba83937dlgao                                FileWrite(File, '%*s' % (self.MaxLen + 4, SkuInfo.VpdOffset))
83252302d4dee589a5df43a464420c9fe68ba83937dlgao
83352302d4dee589a5df43a464420c9fe68ba83937dlgao                    if not DscMatch and DscDefaultValue != None:
834d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao                        FileWrite(File, '    %*s = %s' % (self.MaxLen + 19, 'DSC DEFAULT', DscDefaultValue.strip()))
83552302d4dee589a5df43a464420c9fe68ba83937dlgao
83652302d4dee589a5df43a464420c9fe68ba83937dlgao                    if not InfMatch and InfDefaultValue != None:
837d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao                        FileWrite(File, '    %*s = %s' % (self.MaxLen + 19, 'INF DEFAULT', InfDefaultValue.strip()))
83852302d4dee589a5df43a464420c9fe68ba83937dlgao
83952302d4dee589a5df43a464420c9fe68ba83937dlgao                    if not DecMatch and DecDefaultValue != None:
840d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao                        FileWrite(File, '    %*s = %s' % (self.MaxLen + 19, 'DEC DEFAULT', DecDefaultValue.strip()))
84152302d4dee589a5df43a464420c9fe68ba83937dlgao
84252302d4dee589a5df43a464420c9fe68ba83937dlgao                    if ModulePcdSet == None:
84352302d4dee589a5df43a464420c9fe68ba83937dlgao                        ModuleOverride = self.ModulePcdOverride.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName), {})
84452302d4dee589a5df43a464420c9fe68ba83937dlgao                        for ModulePath in ModuleOverride:
84552302d4dee589a5df43a464420c9fe68ba83937dlgao                            ModuleDefault = ModuleOverride[ModulePath]
84652302d4dee589a5df43a464420c9fe68ba83937dlgao                            if Pcd.DatumType in ('UINT8', 'UINT16', 'UINT32', 'UINT64'):
84752302d4dee589a5df43a464420c9fe68ba83937dlgao                                ModulePcdDefaultValueNumber = int(ModuleDefault.strip(), 0)
84852302d4dee589a5df43a464420c9fe68ba83937dlgao                                Match = (ModulePcdDefaultValueNumber == PcdValueNumber)
84952302d4dee589a5df43a464420c9fe68ba83937dlgao                            else:
850d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao                                Match = (ModuleDefault.strip() == PcdValue.strip())
85152302d4dee589a5df43a464420c9fe68ba83937dlgao                            if Match:
85252302d4dee589a5df43a464420c9fe68ba83937dlgao                                continue
853d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao                            FileWrite(File, ' *M %-*s = %s' % (self.MaxLen + 19, ModulePath, ModuleDefault.strip()))
85452302d4dee589a5df43a464420c9fe68ba83937dlgao
85552302d4dee589a5df43a464420c9fe68ba83937dlgao        if ModulePcdSet == None:
85652302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, gSectionEnd)
85752302d4dee589a5df43a464420c9fe68ba83937dlgao        else:
85852302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, gSubSectionEnd)
85952302d4dee589a5df43a464420c9fe68ba83937dlgao
86052302d4dee589a5df43a464420c9fe68ba83937dlgao
86152302d4dee589a5df43a464420c9fe68ba83937dlgao
86252302d4dee589a5df43a464420c9fe68ba83937dlgao##
86352302d4dee589a5df43a464420c9fe68ba83937dlgao# Reports platform and module Prediction information
86452302d4dee589a5df43a464420c9fe68ba83937dlgao#
86552302d4dee589a5df43a464420c9fe68ba83937dlgao# This class reports the platform execution order prediction section and
86652302d4dee589a5df43a464420c9fe68ba83937dlgao# module load fixed address prediction subsection in the build report file.
86752302d4dee589a5df43a464420c9fe68ba83937dlgao#
86852302d4dee589a5df43a464420c9fe68ba83937dlgaoclass PredictionReport(object):
86952302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
87052302d4dee589a5df43a464420c9fe68ba83937dlgao    # Constructor function for class PredictionReport
87152302d4dee589a5df43a464420c9fe68ba83937dlgao    #
87252302d4dee589a5df43a464420c9fe68ba83937dlgao    # This constructor function generates PredictionReport object for the platform.
87352302d4dee589a5df43a464420c9fe68ba83937dlgao    #
87452302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self:           The object pointer
87552302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param Wa              Workspace context information
87652302d4dee589a5df43a464420c9fe68ba83937dlgao    #
87752302d4dee589a5df43a464420c9fe68ba83937dlgao    def __init__(self, Wa):
87852302d4dee589a5df43a464420c9fe68ba83937dlgao        self._MapFileName = os.path.join(Wa.BuildDir, Wa.Name + ".map")
87952302d4dee589a5df43a464420c9fe68ba83937dlgao        self._MapFileParsed = False
88052302d4dee589a5df43a464420c9fe68ba83937dlgao        self._EotToolInvoked = False
88152302d4dee589a5df43a464420c9fe68ba83937dlgao        self._FvDir = Wa.FvDir
88252302d4dee589a5df43a464420c9fe68ba83937dlgao        self._EotDir = Wa.BuildDir
88352302d4dee589a5df43a464420c9fe68ba83937dlgao        self._FfsEntryPoint = {}
88452302d4dee589a5df43a464420c9fe68ba83937dlgao        self._GuidMap = {}
88552302d4dee589a5df43a464420c9fe68ba83937dlgao        self._SourceList = []
88652302d4dee589a5df43a464420c9fe68ba83937dlgao        self.FixedMapDict = {}
88752302d4dee589a5df43a464420c9fe68ba83937dlgao        self.ItemList = []
88852302d4dee589a5df43a464420c9fe68ba83937dlgao        self.MaxLen = 0
88952302d4dee589a5df43a464420c9fe68ba83937dlgao
89052302d4dee589a5df43a464420c9fe68ba83937dlgao        #
89152302d4dee589a5df43a464420c9fe68ba83937dlgao        # Collect all platform reference source files and GUID C Name
89252302d4dee589a5df43a464420c9fe68ba83937dlgao        #
89352302d4dee589a5df43a464420c9fe68ba83937dlgao        for Pa in Wa.AutoGenObjectList:
89452302d4dee589a5df43a464420c9fe68ba83937dlgao            for Module in Pa.LibraryAutoGenList + Pa.ModuleAutoGenList:
89552302d4dee589a5df43a464420c9fe68ba83937dlgao                #
89640d841f6a8f84e75409178e19e69b95e01bada0flgao                # BASE typed modules are EFI agnostic, so we need not scan
89740d841f6a8f84e75409178e19e69b95e01bada0flgao                # their source code to find PPI/Protocol produce or consume
89840d841f6a8f84e75409178e19e69b95e01bada0flgao                # information.
89940d841f6a8f84e75409178e19e69b95e01bada0flgao                #
90040d841f6a8f84e75409178e19e69b95e01bada0flgao                if Module.ModuleType == "BASE":
90140d841f6a8f84e75409178e19e69b95e01bada0flgao                    continue
90240d841f6a8f84e75409178e19e69b95e01bada0flgao                #
90352302d4dee589a5df43a464420c9fe68ba83937dlgao                # Add module referenced source files
90452302d4dee589a5df43a464420c9fe68ba83937dlgao                #
90552302d4dee589a5df43a464420c9fe68ba83937dlgao                self._SourceList.append(str(Module))
90652302d4dee589a5df43a464420c9fe68ba83937dlgao                IncludeList = {}
90752302d4dee589a5df43a464420c9fe68ba83937dlgao                for Source in Module.SourceFileList:
90852302d4dee589a5df43a464420c9fe68ba83937dlgao                    if os.path.splitext(str(Source))[1].lower() == ".c":
90952302d4dee589a5df43a464420c9fe68ba83937dlgao                        self._SourceList.append("  " + str(Source))
91052302d4dee589a5df43a464420c9fe68ba83937dlgao                        FindIncludeFiles(Source.Path, Module.IncludePathList, IncludeList)
91152302d4dee589a5df43a464420c9fe68ba83937dlgao                for IncludeFile in IncludeList.values():
91252302d4dee589a5df43a464420c9fe68ba83937dlgao                    self._SourceList.append("  " + IncludeFile)
91352302d4dee589a5df43a464420c9fe68ba83937dlgao
91452302d4dee589a5df43a464420c9fe68ba83937dlgao                for Guid in Module.PpiList:
91552302d4dee589a5df43a464420c9fe68ba83937dlgao                    self._GuidMap[Guid] = GuidStructureStringToGuidString(Module.PpiList[Guid])
91652302d4dee589a5df43a464420c9fe68ba83937dlgao                for Guid in Module.ProtocolList:
91752302d4dee589a5df43a464420c9fe68ba83937dlgao                    self._GuidMap[Guid] = GuidStructureStringToGuidString(Module.ProtocolList[Guid])
91852302d4dee589a5df43a464420c9fe68ba83937dlgao                for Guid in Module.GuidList:
91952302d4dee589a5df43a464420c9fe68ba83937dlgao                    self._GuidMap[Guid] = GuidStructureStringToGuidString(Module.GuidList[Guid])
92052302d4dee589a5df43a464420c9fe68ba83937dlgao
92152302d4dee589a5df43a464420c9fe68ba83937dlgao                if Module.Guid and not Module.IsLibrary:
92252302d4dee589a5df43a464420c9fe68ba83937dlgao                    EntryPoint = " ".join(Module.Module.ModuleEntryPointList)
92352302d4dee589a5df43a464420c9fe68ba83937dlgao                    if int(str(Module.AutoGenVersion), 0) >= 0x00010005:
92452302d4dee589a5df43a464420c9fe68ba83937dlgao                        RealEntryPoint = "_ModuleEntryPoint"
92552302d4dee589a5df43a464420c9fe68ba83937dlgao                    else:
92652302d4dee589a5df43a464420c9fe68ba83937dlgao                        RealEntryPoint = EntryPoint
92752302d4dee589a5df43a464420c9fe68ba83937dlgao                        if EntryPoint == "_ModuleEntryPoint":
92852302d4dee589a5df43a464420c9fe68ba83937dlgao                            CCFlags = Module.BuildOption.get("CC", {}).get("FLAGS", "")
92952302d4dee589a5df43a464420c9fe68ba83937dlgao                            Match = gGlueLibEntryPoint.search(CCFlags)
93052302d4dee589a5df43a464420c9fe68ba83937dlgao                            if Match:
93152302d4dee589a5df43a464420c9fe68ba83937dlgao                                EntryPoint = Match.group(1)
93252302d4dee589a5df43a464420c9fe68ba83937dlgao
93352302d4dee589a5df43a464420c9fe68ba83937dlgao                    self._FfsEntryPoint[Module.Guid.upper()] = (EntryPoint, RealEntryPoint)
93452302d4dee589a5df43a464420c9fe68ba83937dlgao
93552302d4dee589a5df43a464420c9fe68ba83937dlgao
93652302d4dee589a5df43a464420c9fe68ba83937dlgao        #
93752302d4dee589a5df43a464420c9fe68ba83937dlgao        # Collect platform firmware volume list as the input of EOT.
93852302d4dee589a5df43a464420c9fe68ba83937dlgao        #
93952302d4dee589a5df43a464420c9fe68ba83937dlgao        self._FvList = []
94052302d4dee589a5df43a464420c9fe68ba83937dlgao        if Wa.FdfProfile:
94152302d4dee589a5df43a464420c9fe68ba83937dlgao            for Fd in Wa.FdfProfile.FdDict:
94252302d4dee589a5df43a464420c9fe68ba83937dlgao                for FdRegion in Wa.FdfProfile.FdDict[Fd].RegionList:
94352302d4dee589a5df43a464420c9fe68ba83937dlgao                    if FdRegion.RegionType != "FV":
94452302d4dee589a5df43a464420c9fe68ba83937dlgao                        continue
94552302d4dee589a5df43a464420c9fe68ba83937dlgao                    for FvName in FdRegion.RegionDataList:
94652302d4dee589a5df43a464420c9fe68ba83937dlgao                        if FvName in self._FvList:
94752302d4dee589a5df43a464420c9fe68ba83937dlgao                            continue
94852302d4dee589a5df43a464420c9fe68ba83937dlgao                        self._FvList.append(FvName)
94952302d4dee589a5df43a464420c9fe68ba83937dlgao                        for Ffs in Wa.FdfProfile.FvDict[FvName.upper()].FfsList:
95052302d4dee589a5df43a464420c9fe68ba83937dlgao                            for Section in Ffs.SectionList:
95152302d4dee589a5df43a464420c9fe68ba83937dlgao                                try:
95252302d4dee589a5df43a464420c9fe68ba83937dlgao                                    for FvSection in Section.SectionList:
95352302d4dee589a5df43a464420c9fe68ba83937dlgao                                        if FvSection.FvName in self._FvList:
95452302d4dee589a5df43a464420c9fe68ba83937dlgao                                            continue
95552302d4dee589a5df43a464420c9fe68ba83937dlgao                                        self._FvList.append(FvSection.FvName)
95652302d4dee589a5df43a464420c9fe68ba83937dlgao                                except AttributeError:
95752302d4dee589a5df43a464420c9fe68ba83937dlgao                                    pass
95852302d4dee589a5df43a464420c9fe68ba83937dlgao
95952302d4dee589a5df43a464420c9fe68ba83937dlgao
96052302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
96152302d4dee589a5df43a464420c9fe68ba83937dlgao    # Parse platform fixed address map files
96252302d4dee589a5df43a464420c9fe68ba83937dlgao    #
96352302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function parses the platform final fixed address map file to get
96452302d4dee589a5df43a464420c9fe68ba83937dlgao    # the database of predicted fixed address for module image base, entry point
96552302d4dee589a5df43a464420c9fe68ba83937dlgao    # etc.
96652302d4dee589a5df43a464420c9fe68ba83937dlgao    #
96752302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self:           The object pointer
96852302d4dee589a5df43a464420c9fe68ba83937dlgao    #
96952302d4dee589a5df43a464420c9fe68ba83937dlgao    def _ParseMapFile(self):
97052302d4dee589a5df43a464420c9fe68ba83937dlgao        if self._MapFileParsed:
97152302d4dee589a5df43a464420c9fe68ba83937dlgao            return
97252302d4dee589a5df43a464420c9fe68ba83937dlgao        self._MapFileParsed = True
97352302d4dee589a5df43a464420c9fe68ba83937dlgao        if os.path.isfile(self._MapFileName):
97452302d4dee589a5df43a464420c9fe68ba83937dlgao            try:
97552302d4dee589a5df43a464420c9fe68ba83937dlgao                FileContents = open(self._MapFileName).read()
97652302d4dee589a5df43a464420c9fe68ba83937dlgao                for Match in gMapFileItemPattern.finditer(FileContents):
97752302d4dee589a5df43a464420c9fe68ba83937dlgao                    AddressType = Match.group(1)
97852302d4dee589a5df43a464420c9fe68ba83937dlgao                    BaseAddress = Match.group(2)
97952302d4dee589a5df43a464420c9fe68ba83937dlgao                    EntryPoint = Match.group(3)
98052302d4dee589a5df43a464420c9fe68ba83937dlgao                    Guid = Match.group(4).upper()
98152302d4dee589a5df43a464420c9fe68ba83937dlgao                    List = self.FixedMapDict.setdefault(Guid, [])
98252302d4dee589a5df43a464420c9fe68ba83937dlgao                    List.append((AddressType, BaseAddress, "*I"))
98352302d4dee589a5df43a464420c9fe68ba83937dlgao                    List.append((AddressType, EntryPoint, "*E"))
98452302d4dee589a5df43a464420c9fe68ba83937dlgao            except:
98552302d4dee589a5df43a464420c9fe68ba83937dlgao                EdkLogger.warn(None, "Cannot open file to read", self._MapFileName)
98652302d4dee589a5df43a464420c9fe68ba83937dlgao
98752302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
98852302d4dee589a5df43a464420c9fe68ba83937dlgao    # Invokes EOT tool to get the predicted the execution order.
98952302d4dee589a5df43a464420c9fe68ba83937dlgao    #
99052302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function invokes EOT tool to calculate the predicted dispatch order
99152302d4dee589a5df43a464420c9fe68ba83937dlgao    #
99252302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self:           The object pointer
99352302d4dee589a5df43a464420c9fe68ba83937dlgao    #
99452302d4dee589a5df43a464420c9fe68ba83937dlgao    def _InvokeEotTool(self):
99552302d4dee589a5df43a464420c9fe68ba83937dlgao        if self._EotToolInvoked:
99652302d4dee589a5df43a464420c9fe68ba83937dlgao            return
99752302d4dee589a5df43a464420c9fe68ba83937dlgao
99852302d4dee589a5df43a464420c9fe68ba83937dlgao        self._EotToolInvoked = True
99952302d4dee589a5df43a464420c9fe68ba83937dlgao        FvFileList = []
100052302d4dee589a5df43a464420c9fe68ba83937dlgao        for FvName in self._FvList:
100152302d4dee589a5df43a464420c9fe68ba83937dlgao            FvFile = os.path.join(self._FvDir, FvName + ".Fv")
100252302d4dee589a5df43a464420c9fe68ba83937dlgao            if os.path.isfile(FvFile):
100352302d4dee589a5df43a464420c9fe68ba83937dlgao                FvFileList.append(FvFile)
100452302d4dee589a5df43a464420c9fe68ba83937dlgao
100552302d4dee589a5df43a464420c9fe68ba83937dlgao        if len(FvFileList) == 0:
100652302d4dee589a5df43a464420c9fe68ba83937dlgao            return
100752302d4dee589a5df43a464420c9fe68ba83937dlgao        #
100852302d4dee589a5df43a464420c9fe68ba83937dlgao        # Write source file list and GUID file list to an intermediate file
100952302d4dee589a5df43a464420c9fe68ba83937dlgao        # as the input for EOT tool and dispatch List as the output file
101052302d4dee589a5df43a464420c9fe68ba83937dlgao        # from EOT tool.
101152302d4dee589a5df43a464420c9fe68ba83937dlgao        #
101252302d4dee589a5df43a464420c9fe68ba83937dlgao        SourceList = os.path.join(self._EotDir, "SourceFile.txt")
101352302d4dee589a5df43a464420c9fe68ba83937dlgao        GuidList = os.path.join(self._EotDir, "GuidList.txt")
101452302d4dee589a5df43a464420c9fe68ba83937dlgao        DispatchList = os.path.join(self._EotDir, "Dispatch.txt")
101552302d4dee589a5df43a464420c9fe68ba83937dlgao
101652302d4dee589a5df43a464420c9fe68ba83937dlgao        TempFile = open(SourceList, "w+")
101752302d4dee589a5df43a464420c9fe68ba83937dlgao        for Item in self._SourceList:
101852302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(TempFile, Item)
101952302d4dee589a5df43a464420c9fe68ba83937dlgao        TempFile.close()
102052302d4dee589a5df43a464420c9fe68ba83937dlgao        TempFile = open(GuidList, "w+")
102152302d4dee589a5df43a464420c9fe68ba83937dlgao        for Key in self._GuidMap:
102252302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(TempFile, "%s %s" % (Key, self._GuidMap[Key]))
102352302d4dee589a5df43a464420c9fe68ba83937dlgao        TempFile.close()
102452302d4dee589a5df43a464420c9fe68ba83937dlgao
102552302d4dee589a5df43a464420c9fe68ba83937dlgao        try:
102652302d4dee589a5df43a464420c9fe68ba83937dlgao            from Eot.Eot import Eot
102740d841f6a8f84e75409178e19e69b95e01bada0flgao
102852302d4dee589a5df43a464420c9fe68ba83937dlgao            #
102940d841f6a8f84e75409178e19e69b95e01bada0flgao            # Invoke EOT tool and echo its runtime performance
103052302d4dee589a5df43a464420c9fe68ba83937dlgao            #
103140d841f6a8f84e75409178e19e69b95e01bada0flgao            EotStartTime = time.time()
103252302d4dee589a5df43a464420c9fe68ba83937dlgao            Eot(CommandLineOption=False, SourceFileList=SourceList, GuidList=GuidList,
103352302d4dee589a5df43a464420c9fe68ba83937dlgao                FvFileList=' '.join(FvFileList), Dispatch=DispatchList, IsInit=True)
103440d841f6a8f84e75409178e19e69b95e01bada0flgao            EotEndTime = time.time()
103540d841f6a8f84e75409178e19e69b95e01bada0flgao            EotDuration = time.strftime("%H:%M:%S", time.gmtime(int(round(EotEndTime - EotStartTime))))
103640d841f6a8f84e75409178e19e69b95e01bada0flgao            EdkLogger.quiet("EOT run time: %s\n" % EotDuration)
103740d841f6a8f84e75409178e19e69b95e01bada0flgao
103852302d4dee589a5df43a464420c9fe68ba83937dlgao            #
103952302d4dee589a5df43a464420c9fe68ba83937dlgao            # Parse the output of EOT tool
104052302d4dee589a5df43a464420c9fe68ba83937dlgao            #
104152302d4dee589a5df43a464420c9fe68ba83937dlgao            for Line in open(DispatchList):
104252302d4dee589a5df43a464420c9fe68ba83937dlgao                if len(Line.split()) < 4:
104352302d4dee589a5df43a464420c9fe68ba83937dlgao                    continue
104452302d4dee589a5df43a464420c9fe68ba83937dlgao                (Guid, Phase, FfsName, FilePath) = Line.split()
104552302d4dee589a5df43a464420c9fe68ba83937dlgao                Symbol = self._FfsEntryPoint.get(Guid, [FfsName, ""])[0]
104652302d4dee589a5df43a464420c9fe68ba83937dlgao                if len(Symbol) > self.MaxLen:
104752302d4dee589a5df43a464420c9fe68ba83937dlgao                    self.MaxLen = len(Symbol)
104852302d4dee589a5df43a464420c9fe68ba83937dlgao                self.ItemList.append((Phase, Symbol, FilePath))
104952302d4dee589a5df43a464420c9fe68ba83937dlgao        except:
105052302d4dee589a5df43a464420c9fe68ba83937dlgao            EdkLogger.quiet("(Python %s on %s\n%s)" % (platform.python_version(), sys.platform, traceback.format_exc()))
105152302d4dee589a5df43a464420c9fe68ba83937dlgao            EdkLogger.warn(None, "Failed to generate execution order prediction report, for some error occurred in executing EOT.")
105252302d4dee589a5df43a464420c9fe68ba83937dlgao
105352302d4dee589a5df43a464420c9fe68ba83937dlgao
105452302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
105552302d4dee589a5df43a464420c9fe68ba83937dlgao    # Generate platform execution order report
105652302d4dee589a5df43a464420c9fe68ba83937dlgao    #
105752302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function generates the predicted module execution order.
105852302d4dee589a5df43a464420c9fe68ba83937dlgao    #
105952302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
106052302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param File            The file object for report
106152302d4dee589a5df43a464420c9fe68ba83937dlgao    #
106252302d4dee589a5df43a464420c9fe68ba83937dlgao    def _GenerateExecutionOrderReport(self, File):
106352302d4dee589a5df43a464420c9fe68ba83937dlgao        self._InvokeEotTool()
106452302d4dee589a5df43a464420c9fe68ba83937dlgao        if len(self.ItemList) == 0:
106552302d4dee589a5df43a464420c9fe68ba83937dlgao            return
106652302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSectionStart)
106752302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Execution Order Prediction")
106852302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "*P PEI phase")
106952302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "*D DXE phase")
107052302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "*E Module INF entry point name")
107152302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "*N Module notification function name")
107252302d4dee589a5df43a464420c9fe68ba83937dlgao
107352302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Type %-*s %s" % (self.MaxLen, "Symbol", "Module INF Path"))
107452302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSectionSep)
107552302d4dee589a5df43a464420c9fe68ba83937dlgao        for Item in self.ItemList:
107652302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "*%sE  %-*s %s" % (Item[0], self.MaxLen, Item[1], Item[2]))
107752302d4dee589a5df43a464420c9fe68ba83937dlgao
107852302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSectionStart)
107952302d4dee589a5df43a464420c9fe68ba83937dlgao
108052302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
108152302d4dee589a5df43a464420c9fe68ba83937dlgao    # Generate Fixed Address report.
108252302d4dee589a5df43a464420c9fe68ba83937dlgao    #
108352302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function generate the predicted fixed address report for a module
108452302d4dee589a5df43a464420c9fe68ba83937dlgao    # specified by Guid.
108552302d4dee589a5df43a464420c9fe68ba83937dlgao    #
108652302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
108752302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param File            The file object for report
108852302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param Guid            The module Guid value.
108952302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param NotifyList      The list of all notify function in a module
109052302d4dee589a5df43a464420c9fe68ba83937dlgao    #
109152302d4dee589a5df43a464420c9fe68ba83937dlgao    def _GenerateFixedAddressReport(self, File, Guid, NotifyList):
109252302d4dee589a5df43a464420c9fe68ba83937dlgao        self._ParseMapFile()
109352302d4dee589a5df43a464420c9fe68ba83937dlgao        FixedAddressList = self.FixedMapDict.get(Guid)
109452302d4dee589a5df43a464420c9fe68ba83937dlgao        if not FixedAddressList:
109552302d4dee589a5df43a464420c9fe68ba83937dlgao            return
109652302d4dee589a5df43a464420c9fe68ba83937dlgao
109752302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSubSectionStart)
109852302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Fixed Address Prediction")
109952302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "*I  Image Loading Address")
110052302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "*E  Entry Point Address")
110152302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "*N  Notification Function Address")
110252302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "*F  Flash Address")
110352302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "*M  Memory Address")
110452302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "*S  SMM RAM Offset")
110552302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "TOM Top of Memory")
110652302d4dee589a5df43a464420c9fe68ba83937dlgao
110752302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Type Address           Name")
110852302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSubSectionSep)
110952302d4dee589a5df43a464420c9fe68ba83937dlgao        for Item in FixedAddressList:
111052302d4dee589a5df43a464420c9fe68ba83937dlgao            Type = Item[0]
111152302d4dee589a5df43a464420c9fe68ba83937dlgao            Value = Item[1]
111252302d4dee589a5df43a464420c9fe68ba83937dlgao            Symbol = Item[2]
111352302d4dee589a5df43a464420c9fe68ba83937dlgao            if Symbol == "*I":
111452302d4dee589a5df43a464420c9fe68ba83937dlgao                Name = "(Image Base)"
111552302d4dee589a5df43a464420c9fe68ba83937dlgao            elif Symbol == "*E":
111652302d4dee589a5df43a464420c9fe68ba83937dlgao                Name = self._FfsEntryPoint.get(Guid, ["", "_ModuleEntryPoint"])[1]
111752302d4dee589a5df43a464420c9fe68ba83937dlgao            elif Symbol in NotifyList:
111852302d4dee589a5df43a464420c9fe68ba83937dlgao                Name = Symbol
111952302d4dee589a5df43a464420c9fe68ba83937dlgao                Symbol = "*N"
112052302d4dee589a5df43a464420c9fe68ba83937dlgao            else:
112152302d4dee589a5df43a464420c9fe68ba83937dlgao                continue
112252302d4dee589a5df43a464420c9fe68ba83937dlgao
112352302d4dee589a5df43a464420c9fe68ba83937dlgao            if "Flash" in Type:
112452302d4dee589a5df43a464420c9fe68ba83937dlgao                Symbol += "F"
112552302d4dee589a5df43a464420c9fe68ba83937dlgao            elif "Memory" in Type:
112652302d4dee589a5df43a464420c9fe68ba83937dlgao                Symbol += "M"
112752302d4dee589a5df43a464420c9fe68ba83937dlgao            else:
112852302d4dee589a5df43a464420c9fe68ba83937dlgao                Symbol += "S"
112952302d4dee589a5df43a464420c9fe68ba83937dlgao
113052302d4dee589a5df43a464420c9fe68ba83937dlgao            if Value[0] == "-":
113152302d4dee589a5df43a464420c9fe68ba83937dlgao                Value = "TOM" + Value
113252302d4dee589a5df43a464420c9fe68ba83937dlgao
113352302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "%s  %-16s  %s" % (Symbol, Value, Name))
113452302d4dee589a5df43a464420c9fe68ba83937dlgao
113552302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
113652302d4dee589a5df43a464420c9fe68ba83937dlgao    # Generate report for the prediction part
113752302d4dee589a5df43a464420c9fe68ba83937dlgao    #
113852302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function generate the predicted fixed address report for a module or
113952302d4dee589a5df43a464420c9fe68ba83937dlgao    # predicted module execution order for a platform.
114052302d4dee589a5df43a464420c9fe68ba83937dlgao    # If the input Guid is None, then, it generates the predicted module execution order;
114152302d4dee589a5df43a464420c9fe68ba83937dlgao    # otherwise it generated the module fixed loading address for the module specified by
114252302d4dee589a5df43a464420c9fe68ba83937dlgao    # Guid.
114352302d4dee589a5df43a464420c9fe68ba83937dlgao    #
114452302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
114552302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param File            The file object for report
114652302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param Guid            The module Guid value.
114752302d4dee589a5df43a464420c9fe68ba83937dlgao    #
114852302d4dee589a5df43a464420c9fe68ba83937dlgao    def GenerateReport(self, File, Guid):
114952302d4dee589a5df43a464420c9fe68ba83937dlgao        if Guid:
115052302d4dee589a5df43a464420c9fe68ba83937dlgao            self._GenerateFixedAddressReport(File, Guid.upper(), [])
115152302d4dee589a5df43a464420c9fe68ba83937dlgao        else:
115252302d4dee589a5df43a464420c9fe68ba83937dlgao            self._GenerateExecutionOrderReport(File)
115352302d4dee589a5df43a464420c9fe68ba83937dlgao
115452302d4dee589a5df43a464420c9fe68ba83937dlgao##
115552302d4dee589a5df43a464420c9fe68ba83937dlgao# Reports FD region information
115652302d4dee589a5df43a464420c9fe68ba83937dlgao#
115752302d4dee589a5df43a464420c9fe68ba83937dlgao# This class reports the FD subsection in the build report file.
115852302d4dee589a5df43a464420c9fe68ba83937dlgao# It collects region information of platform flash device.
115952302d4dee589a5df43a464420c9fe68ba83937dlgao# If the region is a firmware volume, it lists the set of modules
116052302d4dee589a5df43a464420c9fe68ba83937dlgao# and its space information; otherwise, it only lists its region name,
116152302d4dee589a5df43a464420c9fe68ba83937dlgao# base address and size in its sub-section header.
116252302d4dee589a5df43a464420c9fe68ba83937dlgao# If there are nesting FVs, the nested FVs will list immediate after
116352302d4dee589a5df43a464420c9fe68ba83937dlgao# this FD region subsection
116452302d4dee589a5df43a464420c9fe68ba83937dlgao#
116552302d4dee589a5df43a464420c9fe68ba83937dlgaoclass FdRegionReport(object):
116652302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
116752302d4dee589a5df43a464420c9fe68ba83937dlgao    # Discover all the nested FV name list.
116852302d4dee589a5df43a464420c9fe68ba83937dlgao    #
116952302d4dee589a5df43a464420c9fe68ba83937dlgao    # This is an internal worker function to discover the all the nested FV information
117052302d4dee589a5df43a464420c9fe68ba83937dlgao    # in the parent firmware volume. It uses deep first search algorithm recursively to
117152302d4dee589a5df43a464420c9fe68ba83937dlgao    # find all the FV list name and append them to the list.
117252302d4dee589a5df43a464420c9fe68ba83937dlgao    #
117352302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
117452302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param FvName          The name of current firmware file system
117552302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param Wa              Workspace context information
117652302d4dee589a5df43a464420c9fe68ba83937dlgao    #
117752302d4dee589a5df43a464420c9fe68ba83937dlgao    def _DiscoverNestedFvList(self, FvName, Wa):
117852302d4dee589a5df43a464420c9fe68ba83937dlgao        for Ffs in Wa.FdfProfile.FvDict[FvName.upper()].FfsList:
117952302d4dee589a5df43a464420c9fe68ba83937dlgao            for Section in Ffs.SectionList:
118052302d4dee589a5df43a464420c9fe68ba83937dlgao                try:
118152302d4dee589a5df43a464420c9fe68ba83937dlgao                    for FvSection in Section.SectionList:
118252302d4dee589a5df43a464420c9fe68ba83937dlgao                        if FvSection.FvName in self.FvList:
118352302d4dee589a5df43a464420c9fe68ba83937dlgao                            continue
118452302d4dee589a5df43a464420c9fe68ba83937dlgao                        self._GuidsDb[Ffs.NameGuid.upper()] = FvSection.FvName
118552302d4dee589a5df43a464420c9fe68ba83937dlgao                        self.FvList.append(FvSection.FvName)
118652302d4dee589a5df43a464420c9fe68ba83937dlgao                        self.FvInfo[FvSection.FvName] = ("Nested FV", 0, 0)
118752302d4dee589a5df43a464420c9fe68ba83937dlgao                        self._DiscoverNestedFvList(FvSection.FvName, Wa)
118852302d4dee589a5df43a464420c9fe68ba83937dlgao                except AttributeError:
118952302d4dee589a5df43a464420c9fe68ba83937dlgao                    pass
119052302d4dee589a5df43a464420c9fe68ba83937dlgao
119152302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
119252302d4dee589a5df43a464420c9fe68ba83937dlgao    # Constructor function for class FdRegionReport
119352302d4dee589a5df43a464420c9fe68ba83937dlgao    #
119452302d4dee589a5df43a464420c9fe68ba83937dlgao    # This constructor function generates FdRegionReport object for a specified FdRegion.
119552302d4dee589a5df43a464420c9fe68ba83937dlgao    # If the FdRegion is a firmware volume, it will recursively find all its nested Firmware
119652302d4dee589a5df43a464420c9fe68ba83937dlgao    # volume list. This function also collects GUID map in order to dump module identification
119752302d4dee589a5df43a464420c9fe68ba83937dlgao    # in the final report.
119852302d4dee589a5df43a464420c9fe68ba83937dlgao    #
119952302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self:           The object pointer
120052302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param FdRegion        The current FdRegion object
120152302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param Wa              Workspace context information
120252302d4dee589a5df43a464420c9fe68ba83937dlgao    #
120352302d4dee589a5df43a464420c9fe68ba83937dlgao    def __init__(self, FdRegion, Wa):
120452302d4dee589a5df43a464420c9fe68ba83937dlgao        self.Type = FdRegion.RegionType
120552302d4dee589a5df43a464420c9fe68ba83937dlgao        self.BaseAddress = FdRegion.Offset
120652302d4dee589a5df43a464420c9fe68ba83937dlgao        self.Size = FdRegion.Size
120752302d4dee589a5df43a464420c9fe68ba83937dlgao        self.FvList = []
120852302d4dee589a5df43a464420c9fe68ba83937dlgao        self.FvInfo = {}
120952302d4dee589a5df43a464420c9fe68ba83937dlgao        self._GuidsDb = {}
121052302d4dee589a5df43a464420c9fe68ba83937dlgao        self._FvDir = Wa.FvDir
121152302d4dee589a5df43a464420c9fe68ba83937dlgao
121252302d4dee589a5df43a464420c9fe68ba83937dlgao        #
121352302d4dee589a5df43a464420c9fe68ba83937dlgao        # If the input FdRegion is not a firmware volume,
121452302d4dee589a5df43a464420c9fe68ba83937dlgao        # we are done.
121552302d4dee589a5df43a464420c9fe68ba83937dlgao        #
121652302d4dee589a5df43a464420c9fe68ba83937dlgao        if self.Type != "FV":
121752302d4dee589a5df43a464420c9fe68ba83937dlgao            return
121852302d4dee589a5df43a464420c9fe68ba83937dlgao
121952302d4dee589a5df43a464420c9fe68ba83937dlgao        #
122052302d4dee589a5df43a464420c9fe68ba83937dlgao        # Find all nested FVs in the FdRegion
122152302d4dee589a5df43a464420c9fe68ba83937dlgao        #
122252302d4dee589a5df43a464420c9fe68ba83937dlgao        for FvName in FdRegion.RegionDataList:
122352302d4dee589a5df43a464420c9fe68ba83937dlgao            if FvName in self.FvList:
122452302d4dee589a5df43a464420c9fe68ba83937dlgao                continue
122552302d4dee589a5df43a464420c9fe68ba83937dlgao            self.FvList.append(FvName)
122652302d4dee589a5df43a464420c9fe68ba83937dlgao            self.FvInfo[FvName] = ("Fd Region", self.BaseAddress, self.Size)
122752302d4dee589a5df43a464420c9fe68ba83937dlgao            self._DiscoverNestedFvList(FvName, Wa)
122852302d4dee589a5df43a464420c9fe68ba83937dlgao
122952302d4dee589a5df43a464420c9fe68ba83937dlgao        PlatformPcds = {}
123052302d4dee589a5df43a464420c9fe68ba83937dlgao        #
123152302d4dee589a5df43a464420c9fe68ba83937dlgao        # Collect PCDs declared in DEC files.
12320d2711a69397d2971079121df4326d84736c181elgao        #
12330d2711a69397d2971079121df4326d84736c181elgao        for Pa in Wa.AutoGenObjectList:
12340d2711a69397d2971079121df4326d84736c181elgao            for Package in Pa.PackageList:
12350d2711a69397d2971079121df4326d84736c181elgao                for (TokenCName, TokenSpaceGuidCName, DecType) in Package.Pcds:
12360d2711a69397d2971079121df4326d84736c181elgao                    DecDefaultValue = Package.Pcds[TokenCName, TokenSpaceGuidCName, DecType].DefaultValue
12370d2711a69397d2971079121df4326d84736c181elgao                    PlatformPcds[(TokenCName, TokenSpaceGuidCName)] = DecDefaultValue
123852302d4dee589a5df43a464420c9fe68ba83937dlgao        #
1239af9785a9ed61daea52b47f0bf448f1f228beee1eYonghong Zhu        # Collect PCDs defined in DSC file
124052302d4dee589a5df43a464420c9fe68ba83937dlgao        #
1241af9785a9ed61daea52b47f0bf448f1f228beee1eYonghong Zhu        for arch in Wa.ArchList:
1242af9785a9ed61daea52b47f0bf448f1f228beee1eYonghong Zhu            Platform = Wa.BuildDatabase[Wa.MetaFile, arch]
1243af9785a9ed61daea52b47f0bf448f1f228beee1eYonghong Zhu            for (TokenCName, TokenSpaceGuidCName) in Platform.Pcds:
1244af9785a9ed61daea52b47f0bf448f1f228beee1eYonghong Zhu                DscDefaultValue = Platform.Pcds[(TokenCName, TokenSpaceGuidCName)].DefaultValue
1245af9785a9ed61daea52b47f0bf448f1f228beee1eYonghong Zhu                PlatformPcds[(TokenCName, TokenSpaceGuidCName)] = DscDefaultValue
124652302d4dee589a5df43a464420c9fe68ba83937dlgao
124752302d4dee589a5df43a464420c9fe68ba83937dlgao        #
124852302d4dee589a5df43a464420c9fe68ba83937dlgao        # Add PEI and DXE a priori files GUIDs defined in PI specification.
124952302d4dee589a5df43a464420c9fe68ba83937dlgao        #
125052302d4dee589a5df43a464420c9fe68ba83937dlgao        self._GuidsDb["1B45CC0A-156A-428A-AF62-49864DA0E6E6"] = "PEI Apriori"
125152302d4dee589a5df43a464420c9fe68ba83937dlgao        self._GuidsDb["FC510EE7-FFDC-11D4-BD41-0080C73C8881"] = "DXE Apriori"
125252302d4dee589a5df43a464420c9fe68ba83937dlgao        #
125352302d4dee589a5df43a464420c9fe68ba83937dlgao        # Add ACPI table storage file
125452302d4dee589a5df43a464420c9fe68ba83937dlgao        #
125552302d4dee589a5df43a464420c9fe68ba83937dlgao        self._GuidsDb["7E374E25-8E01-4FEE-87F2-390C23C606CD"] = "ACPI table storage"
125652302d4dee589a5df43a464420c9fe68ba83937dlgao
125752302d4dee589a5df43a464420c9fe68ba83937dlgao        for Pa in Wa.AutoGenObjectList:
125852302d4dee589a5df43a464420c9fe68ba83937dlgao            for ModuleKey in Pa.Platform.Modules:
125952302d4dee589a5df43a464420c9fe68ba83937dlgao                M = Pa.Platform.Modules[ModuleKey].M
126005cc51ad5894c8904d0fe5cdcf3f4d0a07dab85dLi YangX                InfPath = mws.join(Wa.WorkspaceDir, M.MetaFile.File)
126152302d4dee589a5df43a464420c9fe68ba83937dlgao                self._GuidsDb[M.Guid.upper()] = "%s (%s)" % (M.Module.BaseName, InfPath)
126252302d4dee589a5df43a464420c9fe68ba83937dlgao
126352302d4dee589a5df43a464420c9fe68ba83937dlgao        #
126452302d4dee589a5df43a464420c9fe68ba83937dlgao        # Collect the GUID map in the FV firmware volume
126552302d4dee589a5df43a464420c9fe68ba83937dlgao        #
126652302d4dee589a5df43a464420c9fe68ba83937dlgao        for FvName in self.FvList:
126752302d4dee589a5df43a464420c9fe68ba83937dlgao            for Ffs in Wa.FdfProfile.FvDict[FvName.upper()].FfsList:
126852302d4dee589a5df43a464420c9fe68ba83937dlgao                try:
126952302d4dee589a5df43a464420c9fe68ba83937dlgao                    #
127052302d4dee589a5df43a464420c9fe68ba83937dlgao                    # collect GUID map for binary EFI file in FDF file.
127152302d4dee589a5df43a464420c9fe68ba83937dlgao                    #
127252302d4dee589a5df43a464420c9fe68ba83937dlgao                    Guid = Ffs.NameGuid.upper()
127352302d4dee589a5df43a464420c9fe68ba83937dlgao                    Match = gPcdGuidPattern.match(Ffs.NameGuid)
127452302d4dee589a5df43a464420c9fe68ba83937dlgao                    if Match:
127552302d4dee589a5df43a464420c9fe68ba83937dlgao                        PcdTokenspace = Match.group(1)
127652302d4dee589a5df43a464420c9fe68ba83937dlgao                        PcdToken = Match.group(2)
127752302d4dee589a5df43a464420c9fe68ba83937dlgao                        if (PcdToken, PcdTokenspace) in PlatformPcds:
127852302d4dee589a5df43a464420c9fe68ba83937dlgao                            GuidValue = PlatformPcds[(PcdToken, PcdTokenspace)]
127952302d4dee589a5df43a464420c9fe68ba83937dlgao                            Guid = GuidStructureByteArrayToGuidString(GuidValue).upper()
128052302d4dee589a5df43a464420c9fe68ba83937dlgao                    for Section in Ffs.SectionList:
128152302d4dee589a5df43a464420c9fe68ba83937dlgao                        try:
128205cc51ad5894c8904d0fe5cdcf3f4d0a07dab85dLi YangX                            ModuleSectFile = mws.join(Wa.WorkspaceDir, Section.SectFileName)
128352302d4dee589a5df43a464420c9fe68ba83937dlgao                            self._GuidsDb[Guid] = ModuleSectFile
128452302d4dee589a5df43a464420c9fe68ba83937dlgao                        except AttributeError:
128552302d4dee589a5df43a464420c9fe68ba83937dlgao                            pass
128652302d4dee589a5df43a464420c9fe68ba83937dlgao                except AttributeError:
128752302d4dee589a5df43a464420c9fe68ba83937dlgao                    pass
128852302d4dee589a5df43a464420c9fe68ba83937dlgao
128952302d4dee589a5df43a464420c9fe68ba83937dlgao
129052302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
129152302d4dee589a5df43a464420c9fe68ba83937dlgao    # Internal worker function to generate report for the FD region
129252302d4dee589a5df43a464420c9fe68ba83937dlgao    #
129352302d4dee589a5df43a464420c9fe68ba83937dlgao    # This internal worker function to generate report for the FD region.
129452302d4dee589a5df43a464420c9fe68ba83937dlgao    # It the type is firmware volume, it lists offset and module identification.
129552302d4dee589a5df43a464420c9fe68ba83937dlgao    #
129652302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
129752302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param File            The file object for report
129852302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param Title           The title for the FD subsection
129952302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param BaseAddress     The base address for the FD region
130052302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param Size            The size of the FD region
130152302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param FvName          The FV name if the FD region is a firmware volume
130252302d4dee589a5df43a464420c9fe68ba83937dlgao    #
130352302d4dee589a5df43a464420c9fe68ba83937dlgao    def _GenerateReport(self, File, Title, Type, BaseAddress, Size=0, FvName=None):
130452302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSubSectionStart)
130552302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, Title)
130652302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Type:               %s" % Type)
130752302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Base Address:       0x%X" % BaseAddress)
130852302d4dee589a5df43a464420c9fe68ba83937dlgao
130952302d4dee589a5df43a464420c9fe68ba83937dlgao        if self.Type == "FV":
131052302d4dee589a5df43a464420c9fe68ba83937dlgao            FvTotalSize = 0
131152302d4dee589a5df43a464420c9fe68ba83937dlgao            FvTakenSize = 0
131252302d4dee589a5df43a464420c9fe68ba83937dlgao            FvFreeSize  = 0
1313b36d134faf4305247830522b8e2bb255e98c5699lgao            FvReportFileName = os.path.join(self._FvDir, FvName + ".Fv.txt")
131452302d4dee589a5df43a464420c9fe68ba83937dlgao            try:
131552302d4dee589a5df43a464420c9fe68ba83937dlgao                #
131652302d4dee589a5df43a464420c9fe68ba83937dlgao                # Collect size info in the firmware volume.
131752302d4dee589a5df43a464420c9fe68ba83937dlgao                #
131852302d4dee589a5df43a464420c9fe68ba83937dlgao                FvReport = open(FvReportFileName).read()
131952302d4dee589a5df43a464420c9fe68ba83937dlgao                Match = gFvTotalSizePattern.search(FvReport)
132052302d4dee589a5df43a464420c9fe68ba83937dlgao                if Match:
132152302d4dee589a5df43a464420c9fe68ba83937dlgao                    FvTotalSize = int(Match.group(1), 16)
132252302d4dee589a5df43a464420c9fe68ba83937dlgao                Match = gFvTakenSizePattern.search(FvReport)
132352302d4dee589a5df43a464420c9fe68ba83937dlgao                if Match:
132452302d4dee589a5df43a464420c9fe68ba83937dlgao                    FvTakenSize = int(Match.group(1), 16)
132552302d4dee589a5df43a464420c9fe68ba83937dlgao                FvFreeSize = FvTotalSize - FvTakenSize
132652302d4dee589a5df43a464420c9fe68ba83937dlgao                #
132752302d4dee589a5df43a464420c9fe68ba83937dlgao                # Write size information to the report file.
132852302d4dee589a5df43a464420c9fe68ba83937dlgao                #
132952302d4dee589a5df43a464420c9fe68ba83937dlgao                FileWrite(File, "Size:               0x%X (%.0fK)" % (FvTotalSize, FvTotalSize / 1024.0))
133052302d4dee589a5df43a464420c9fe68ba83937dlgao                FileWrite(File, "Fv Name:            %s (%.1f%% Full)" % (FvName, FvTakenSize * 100.0 / FvTotalSize))
133152302d4dee589a5df43a464420c9fe68ba83937dlgao                FileWrite(File, "Occupied Size:      0x%X (%.0fK)" % (FvTakenSize, FvTakenSize / 1024.0))
133252302d4dee589a5df43a464420c9fe68ba83937dlgao                FileWrite(File, "Free Size:          0x%X (%.0fK)" % (FvFreeSize, FvFreeSize / 1024.0))
133352302d4dee589a5df43a464420c9fe68ba83937dlgao                FileWrite(File, "Offset     Module")
133452302d4dee589a5df43a464420c9fe68ba83937dlgao                FileWrite(File, gSubSectionSep)
133552302d4dee589a5df43a464420c9fe68ba83937dlgao                #
133652302d4dee589a5df43a464420c9fe68ba83937dlgao                # Write module offset and module identification to the report file.
133752302d4dee589a5df43a464420c9fe68ba83937dlgao                #
133852302d4dee589a5df43a464420c9fe68ba83937dlgao                OffsetInfo = {}
133952302d4dee589a5df43a464420c9fe68ba83937dlgao                for Match in gOffsetGuidPattern.finditer(FvReport):
134052302d4dee589a5df43a464420c9fe68ba83937dlgao                    Guid = Match.group(2).upper()
134152302d4dee589a5df43a464420c9fe68ba83937dlgao                    OffsetInfo[Match.group(1)] = self._GuidsDb.get(Guid, Guid)
134252302d4dee589a5df43a464420c9fe68ba83937dlgao                OffsetList = OffsetInfo.keys()
134352302d4dee589a5df43a464420c9fe68ba83937dlgao                OffsetList.sort()
134452302d4dee589a5df43a464420c9fe68ba83937dlgao                for Offset in OffsetList:
134552302d4dee589a5df43a464420c9fe68ba83937dlgao                    FileWrite (File, "%s %s" % (Offset, OffsetInfo[Offset]))
134652302d4dee589a5df43a464420c9fe68ba83937dlgao            except IOError:
134752302d4dee589a5df43a464420c9fe68ba83937dlgao                EdkLogger.warn(None, "Fail to read report file", FvReportFileName)
134852302d4dee589a5df43a464420c9fe68ba83937dlgao        else:
134952302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, "Size:               0x%X (%.0fK)" % (Size, Size / 1024.0))
135052302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSubSectionEnd)
135152302d4dee589a5df43a464420c9fe68ba83937dlgao
135252302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
135352302d4dee589a5df43a464420c9fe68ba83937dlgao    # Generate report for the FD region
135452302d4dee589a5df43a464420c9fe68ba83937dlgao    #
135552302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function generates report for the FD region.
135652302d4dee589a5df43a464420c9fe68ba83937dlgao    #
135752302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
135852302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param File            The file object for report
135952302d4dee589a5df43a464420c9fe68ba83937dlgao    #
136052302d4dee589a5df43a464420c9fe68ba83937dlgao    def GenerateReport(self, File):
136152302d4dee589a5df43a464420c9fe68ba83937dlgao        if (len(self.FvList) > 0):
136252302d4dee589a5df43a464420c9fe68ba83937dlgao            for FvItem in self.FvList:
136352302d4dee589a5df43a464420c9fe68ba83937dlgao                Info = self.FvInfo[FvItem]
136452302d4dee589a5df43a464420c9fe68ba83937dlgao                self._GenerateReport(File, Info[0], "FV", Info[1], Info[2], FvItem)
136552302d4dee589a5df43a464420c9fe68ba83937dlgao        else:
136652302d4dee589a5df43a464420c9fe68ba83937dlgao            self._GenerateReport(File, "FD Region", self.Type, self.BaseAddress, self.Size)
136752302d4dee589a5df43a464420c9fe68ba83937dlgao
136852302d4dee589a5df43a464420c9fe68ba83937dlgao##
136952302d4dee589a5df43a464420c9fe68ba83937dlgao# Reports FD information
137052302d4dee589a5df43a464420c9fe68ba83937dlgao#
137152302d4dee589a5df43a464420c9fe68ba83937dlgao# This class reports the FD section in the build report file.
137252302d4dee589a5df43a464420c9fe68ba83937dlgao# It collects flash device information for a platform.
137352302d4dee589a5df43a464420c9fe68ba83937dlgao#
137452302d4dee589a5df43a464420c9fe68ba83937dlgaoclass FdReport(object):
137552302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
137652302d4dee589a5df43a464420c9fe68ba83937dlgao    # Constructor function for class FdReport
137752302d4dee589a5df43a464420c9fe68ba83937dlgao    #
137852302d4dee589a5df43a464420c9fe68ba83937dlgao    # This constructor function generates FdReport object for a specified
137952302d4dee589a5df43a464420c9fe68ba83937dlgao    # firmware device.
138052302d4dee589a5df43a464420c9fe68ba83937dlgao    #
138152302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
138252302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param Fd              The current Firmware device object
138352302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param Wa              Workspace context information
138452302d4dee589a5df43a464420c9fe68ba83937dlgao    #
138552302d4dee589a5df43a464420c9fe68ba83937dlgao    def __init__(self, Fd, Wa):
138652302d4dee589a5df43a464420c9fe68ba83937dlgao        self.FdName = Fd.FdUiName
138752302d4dee589a5df43a464420c9fe68ba83937dlgao        self.BaseAddress = Fd.BaseAddress
138852302d4dee589a5df43a464420c9fe68ba83937dlgao        self.Size = Fd.Size
138952302d4dee589a5df43a464420c9fe68ba83937dlgao        self.FdRegionList = [FdRegionReport(FdRegion, Wa) for FdRegion in Fd.RegionList]
1390fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu        self.FvPath = os.path.join(Wa.BuildDir, "FV")
1391fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu        self.VpdFilePath = os.path.join(self.FvPath, "%s.map" % Wa.Platform.VpdToolGuid)
1392043928da6a7c9c5427c12ca49bf625fc6f052526Yonghong Zhu        self.VPDBaseAddress = 0
1393043928da6a7c9c5427c12ca49bf625fc6f052526Yonghong Zhu        self.VPDSize = 0
1394fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu        self.VPDInfoList = []
1395fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu        for index, FdRegion in enumerate(Fd.RegionList):
1396043928da6a7c9c5427c12ca49bf625fc6f052526Yonghong Zhu            if str(FdRegion.RegionType) is 'FILE' and Wa.Platform.VpdToolGuid in str(FdRegion.RegionDataList):
1397fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                self.VPDBaseAddress = self.FdRegionList[index].BaseAddress
1398fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                self.VPDSize = self.FdRegionList[index].Size
1399fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                break
1400fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu
1401fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu        if os.path.isfile(self.VpdFilePath):
1402fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu            fd = open(self.VpdFilePath, "r")
1403fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu            Lines = fd.readlines()
1404fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu            for Line in Lines:
1405fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                Line = Line.strip()
1406fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                if len(Line) == 0 or Line.startswith("#"):
1407fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                    continue
1408fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                try:
1409fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                    PcdName, SkuId, Offset, Size, Value = Line.split("#")[0].split("|")
1410fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                    PcdName, SkuId, Offset, Size, Value = PcdName.strip(), SkuId.strip(), Offset.strip(), Size.strip(), Value.strip()
1411fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                    Offset = '0x%08X' % (int(Offset, 16) + self.VPDBaseAddress)
1412fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                    self.VPDInfoList.append("%s | %s | %s | %s | %s" % (PcdName, SkuId, Offset, Size, Value))
1413fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                except:
1414fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                    EdkLogger.error("BuildReport", CODE_ERROR, "Fail to parse VPD information file %s" % self.VpdFilePath)
1415fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu            fd.close()
141652302d4dee589a5df43a464420c9fe68ba83937dlgao
141752302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
141852302d4dee589a5df43a464420c9fe68ba83937dlgao    # Generate report for the firmware device.
141952302d4dee589a5df43a464420c9fe68ba83937dlgao    #
142052302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function generates report for the firmware device.
142152302d4dee589a5df43a464420c9fe68ba83937dlgao    #
142252302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
142352302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param File            The file object for report
142452302d4dee589a5df43a464420c9fe68ba83937dlgao    #
142552302d4dee589a5df43a464420c9fe68ba83937dlgao    def GenerateReport(self, File):
142652302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSectionStart)
142752302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Firmware Device (FD)")
142852302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "FD Name:            %s" % self.FdName)
142952302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Base Address:       %s" % self.BaseAddress)
143052302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Size:               0x%X (%.0fK)" % (self.Size, self.Size / 1024.0))
143152302d4dee589a5df43a464420c9fe68ba83937dlgao        if len(self.FdRegionList) > 0:
143252302d4dee589a5df43a464420c9fe68ba83937dlgao            FileWrite(File, gSectionSep)
143352302d4dee589a5df43a464420c9fe68ba83937dlgao            for FdRegionItem in self.FdRegionList:
143452302d4dee589a5df43a464420c9fe68ba83937dlgao                FdRegionItem.GenerateReport(File)
143552302d4dee589a5df43a464420c9fe68ba83937dlgao
1436fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu        if len(self.VPDInfoList) > 0:
1437fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu            FileWrite(File, gSubSectionStart)
1438fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu            FileWrite(File, "FD VPD Region")
1439fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu            FileWrite(File, "Base Address:       0x%X" % self.VPDBaseAddress)
1440fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu            FileWrite(File, "Size:               0x%X (%.0fK)" % (self.VPDSize, self.VPDSize / 1024.0))
1441fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu            FileWrite(File, gSubSectionSep)
1442fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu            for item in self.VPDInfoList:
1443fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu                FileWrite(File, item)
1444fb3d22793e916e4fc8439abc72c1c1a964abf7d0Yonghong Zhu            FileWrite(File, gSubSectionEnd)
144552302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, gSectionEnd)
144652302d4dee589a5df43a464420c9fe68ba83937dlgao
144752302d4dee589a5df43a464420c9fe68ba83937dlgao
144852302d4dee589a5df43a464420c9fe68ba83937dlgao
144952302d4dee589a5df43a464420c9fe68ba83937dlgao##
145052302d4dee589a5df43a464420c9fe68ba83937dlgao# Reports platform information
145152302d4dee589a5df43a464420c9fe68ba83937dlgao#
145252302d4dee589a5df43a464420c9fe68ba83937dlgao# This class reports the whole platform information
145352302d4dee589a5df43a464420c9fe68ba83937dlgao#
145452302d4dee589a5df43a464420c9fe68ba83937dlgaoclass PlatformReport(object):
145552302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
145652302d4dee589a5df43a464420c9fe68ba83937dlgao    # Constructor function for class PlatformReport
145752302d4dee589a5df43a464420c9fe68ba83937dlgao    #
145852302d4dee589a5df43a464420c9fe68ba83937dlgao    # This constructor function generates PlatformReport object a platform build.
145952302d4dee589a5df43a464420c9fe68ba83937dlgao    # It generates report for platform summary, flash, global PCDs and detailed
146052302d4dee589a5df43a464420c9fe68ba83937dlgao    # module information for modules involved in platform build.
146152302d4dee589a5df43a464420c9fe68ba83937dlgao    #
146252302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
146352302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param Wa              Workspace context information
1464d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao    # @param MaList          The list of modules in the platform build
146552302d4dee589a5df43a464420c9fe68ba83937dlgao    #
1466d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao    def __init__(self, Wa, MaList, ReportType):
146752302d4dee589a5df43a464420c9fe68ba83937dlgao        self._WorkspaceDir = Wa.WorkspaceDir
146852302d4dee589a5df43a464420c9fe68ba83937dlgao        self.PlatformName = Wa.Name
146952302d4dee589a5df43a464420c9fe68ba83937dlgao        self.PlatformDscPath = Wa.Platform
147052302d4dee589a5df43a464420c9fe68ba83937dlgao        self.Architectures = " ".join(Wa.ArchList)
147152302d4dee589a5df43a464420c9fe68ba83937dlgao        self.ToolChain = Wa.ToolChain
147252302d4dee589a5df43a464420c9fe68ba83937dlgao        self.Target = Wa.BuildTarget
147352302d4dee589a5df43a464420c9fe68ba83937dlgao        self.OutputPath = os.path.join(Wa.WorkspaceDir, Wa.OutputDir)
147452302d4dee589a5df43a464420c9fe68ba83937dlgao        self.BuildEnvironment = platform.platform()
147552302d4dee589a5df43a464420c9fe68ba83937dlgao
147652302d4dee589a5df43a464420c9fe68ba83937dlgao        self.PcdReport = None
147752302d4dee589a5df43a464420c9fe68ba83937dlgao        if "PCD" in ReportType:
147852302d4dee589a5df43a464420c9fe68ba83937dlgao            self.PcdReport = PcdReport(Wa)
147952302d4dee589a5df43a464420c9fe68ba83937dlgao
148052302d4dee589a5df43a464420c9fe68ba83937dlgao        self.FdReportList = []
1481d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao        if "FLASH" in ReportType and Wa.FdfProfile and MaList == None:
148252302d4dee589a5df43a464420c9fe68ba83937dlgao            for Fd in Wa.FdfProfile.FdDict:
148352302d4dee589a5df43a464420c9fe68ba83937dlgao                self.FdReportList.append(FdReport(Wa.FdfProfile.FdDict[Fd], Wa))
148452302d4dee589a5df43a464420c9fe68ba83937dlgao
148552302d4dee589a5df43a464420c9fe68ba83937dlgao        self.PredictionReport = None
148652302d4dee589a5df43a464420c9fe68ba83937dlgao        if "FIXED_ADDRESS" in ReportType or "EXECUTION_ORDER" in ReportType:
148752302d4dee589a5df43a464420c9fe68ba83937dlgao            self.PredictionReport = PredictionReport(Wa)
148852302d4dee589a5df43a464420c9fe68ba83937dlgao
1489e56468c072e0d53834787f4ad0e292b33cc6be08qhuang        self.DepexParser = None
1490e56468c072e0d53834787f4ad0e292b33cc6be08qhuang        if "DEPEX" in ReportType:
1491e56468c072e0d53834787f4ad0e292b33cc6be08qhuang            self.DepexParser = DepexParser(Wa)
1492e56468c072e0d53834787f4ad0e292b33cc6be08qhuang
149352302d4dee589a5df43a464420c9fe68ba83937dlgao        self.ModuleReportList = []
1494d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao        if MaList != None:
1495636f2be673b2f43518167d8fddae56b714f19314lgao            self._IsModuleBuild = True
1496d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao            for Ma in MaList:
1497d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao                self.ModuleReportList.append(ModuleReport(Ma, ReportType))
1498d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao        else:
1499636f2be673b2f43518167d8fddae56b714f19314lgao            self._IsModuleBuild = False
1500d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao            for Pa in Wa.AutoGenObjectList:
1501d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao                for ModuleKey in Pa.Platform.Modules:
1502d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao                    self.ModuleReportList.append(ModuleReport(Pa.Platform.Modules[ModuleKey].M, ReportType))
150352302d4dee589a5df43a464420c9fe68ba83937dlgao
150452302d4dee589a5df43a464420c9fe68ba83937dlgao
150552302d4dee589a5df43a464420c9fe68ba83937dlgao
150652302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
150752302d4dee589a5df43a464420c9fe68ba83937dlgao    # Generate report for the whole platform.
150852302d4dee589a5df43a464420c9fe68ba83937dlgao    #
150952302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function generates report for platform information.
151052302d4dee589a5df43a464420c9fe68ba83937dlgao    # It comprises of platform summary, global PCD, flash and
151152302d4dee589a5df43a464420c9fe68ba83937dlgao    # module list sections.
151252302d4dee589a5df43a464420c9fe68ba83937dlgao    #
151352302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
151452302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param File            The file object for report
151552302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param BuildDuration   The total time to build the modules
151652302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param ReportType      The kind of report items in the final report file
151752302d4dee589a5df43a464420c9fe68ba83937dlgao    #
151852302d4dee589a5df43a464420c9fe68ba83937dlgao    def GenerateReport(self, File, BuildDuration, ReportType):
151952302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Platform Summary")
152052302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Platform Name:        %s" % self.PlatformName)
152152302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Platform DSC Path:    %s" % self.PlatformDscPath)
152252302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Architectures:        %s" % self.Architectures)
152352302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Tool Chain:           %s" % self.ToolChain)
152452302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Target:               %s" % self.Target)
152552302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Output Path:          %s" % self.OutputPath)
152652302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Build Environment:    %s" % self.BuildEnvironment)
152752302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Build Duration:       %s" % BuildDuration)
152852302d4dee589a5df43a464420c9fe68ba83937dlgao        FileWrite(File, "Report Content:       %s" % ", ".join(ReportType))
152952302d4dee589a5df43a464420c9fe68ba83937dlgao
1530636f2be673b2f43518167d8fddae56b714f19314lgao        if not self._IsModuleBuild:
1531636f2be673b2f43518167d8fddae56b714f19314lgao            if "PCD" in ReportType:
1532636f2be673b2f43518167d8fddae56b714f19314lgao                self.PcdReport.GenerateReport(File, None)
1533636f2be673b2f43518167d8fddae56b714f19314lgao
1534636f2be673b2f43518167d8fddae56b714f19314lgao            if "FLASH" in ReportType:
1535636f2be673b2f43518167d8fddae56b714f19314lgao                for FdReportListItem in self.FdReportList:
1536636f2be673b2f43518167d8fddae56b714f19314lgao                    FdReportListItem.GenerateReport(File)
153752302d4dee589a5df43a464420c9fe68ba83937dlgao
153852302d4dee589a5df43a464420c9fe68ba83937dlgao        for ModuleReportItem in self.ModuleReportList:
1539e56468c072e0d53834787f4ad0e292b33cc6be08qhuang            ModuleReportItem.GenerateReport(File, self.PcdReport, self.PredictionReport, self.DepexParser, ReportType)
154052302d4dee589a5df43a464420c9fe68ba83937dlgao
1541636f2be673b2f43518167d8fddae56b714f19314lgao        if not self._IsModuleBuild:
1542636f2be673b2f43518167d8fddae56b714f19314lgao            if "EXECUTION_ORDER" in ReportType:
1543636f2be673b2f43518167d8fddae56b714f19314lgao                self.PredictionReport.GenerateReport(File, None)
154452302d4dee589a5df43a464420c9fe68ba83937dlgao
154552302d4dee589a5df43a464420c9fe68ba83937dlgao## BuildReport class
154652302d4dee589a5df43a464420c9fe68ba83937dlgao#
154752302d4dee589a5df43a464420c9fe68ba83937dlgao#  This base class contain the routines to collect data and then
154852302d4dee589a5df43a464420c9fe68ba83937dlgao#  applies certain format to the output report
154952302d4dee589a5df43a464420c9fe68ba83937dlgao#
155052302d4dee589a5df43a464420c9fe68ba83937dlgaoclass BuildReport(object):
155152302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
155252302d4dee589a5df43a464420c9fe68ba83937dlgao    # Constructor function for class BuildReport
155352302d4dee589a5df43a464420c9fe68ba83937dlgao    #
155452302d4dee589a5df43a464420c9fe68ba83937dlgao    # This constructor function generates BuildReport object a platform build.
155552302d4dee589a5df43a464420c9fe68ba83937dlgao    # It generates report for platform summary, flash, global PCDs and detailed
155652302d4dee589a5df43a464420c9fe68ba83937dlgao    # module information for modules involved in platform build.
155752302d4dee589a5df43a464420c9fe68ba83937dlgao    #
155852302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
155952302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param ReportFile      The file name to save report file
156052302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param ReportType      The kind of report items in the final report file
156152302d4dee589a5df43a464420c9fe68ba83937dlgao    #
156252302d4dee589a5df43a464420c9fe68ba83937dlgao    def __init__(self, ReportFile, ReportType):
156352302d4dee589a5df43a464420c9fe68ba83937dlgao        self.ReportFile = ReportFile
156452302d4dee589a5df43a464420c9fe68ba83937dlgao        if ReportFile:
156552302d4dee589a5df43a464420c9fe68ba83937dlgao            self.ReportList = []
156652302d4dee589a5df43a464420c9fe68ba83937dlgao            self.ReportType = []
156752302d4dee589a5df43a464420c9fe68ba83937dlgao            if ReportType:
156852302d4dee589a5df43a464420c9fe68ba83937dlgao                for ReportTypeItem in ReportType:
156952302d4dee589a5df43a464420c9fe68ba83937dlgao                    if ReportTypeItem not in self.ReportType:
157052302d4dee589a5df43a464420c9fe68ba83937dlgao                        self.ReportType.append(ReportTypeItem)
157152302d4dee589a5df43a464420c9fe68ba83937dlgao            else:
157252302d4dee589a5df43a464420c9fe68ba83937dlgao                self.ReportType = ["PCD", "LIBRARY", "BUILD_FLAGS", "DEPEX", "FLASH", "FIXED_ADDRESS"]
157352302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
157452302d4dee589a5df43a464420c9fe68ba83937dlgao    # Adds platform report to the list
157552302d4dee589a5df43a464420c9fe68ba83937dlgao    #
157652302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function adds a platform report to the final report list.
157752302d4dee589a5df43a464420c9fe68ba83937dlgao    #
157852302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
157952302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param Wa              Workspace context information
1580d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao    # @param MaList          The list of modules in the platform build
158152302d4dee589a5df43a464420c9fe68ba83937dlgao    #
1582d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao    def AddPlatformReport(self, Wa, MaList=None):
158352302d4dee589a5df43a464420c9fe68ba83937dlgao        if self.ReportFile:
1584d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao            self.ReportList.append((Wa, MaList))
158552302d4dee589a5df43a464420c9fe68ba83937dlgao
158652302d4dee589a5df43a464420c9fe68ba83937dlgao    ##
158752302d4dee589a5df43a464420c9fe68ba83937dlgao    # Generates the final report.
158852302d4dee589a5df43a464420c9fe68ba83937dlgao    #
158952302d4dee589a5df43a464420c9fe68ba83937dlgao    # This function generates platform build report. It invokes GenerateReport()
159052302d4dee589a5df43a464420c9fe68ba83937dlgao    # method for every platform report in the list.
159152302d4dee589a5df43a464420c9fe68ba83937dlgao    #
159252302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param self            The object pointer
159352302d4dee589a5df43a464420c9fe68ba83937dlgao    # @param BuildDuration   The total time to build the modules
159452302d4dee589a5df43a464420c9fe68ba83937dlgao    #
159552302d4dee589a5df43a464420c9fe68ba83937dlgao    def GenerateReport(self, BuildDuration):
159652302d4dee589a5df43a464420c9fe68ba83937dlgao        if self.ReportFile:
159752302d4dee589a5df43a464420c9fe68ba83937dlgao            try:
159840d841f6a8f84e75409178e19e69b95e01bada0flgao                File = StringIO('')
1599d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao                for (Wa, MaList) in self.ReportList:
1600d5d56f1bc5e7bcebd08ad55e940fb907ea0af365lgao                    PlatformReport(Wa, MaList, self.ReportType).GenerateReport(File, BuildDuration, self.ReportType)
160164b2609fcff9d6412eea4c74c8e74bed33dc3235lgao                Content = FileLinesSplit(File.getvalue(), gLineMaxLength)
160264b2609fcff9d6412eea4c74c8e74bed33dc3235lgao                SaveFileOnChange(self.ReportFile, Content, True)
160340d841f6a8f84e75409178e19e69b95e01bada0flgao                EdkLogger.quiet("Build report can be found at %s" % os.path.abspath(self.ReportFile))
160452302d4dee589a5df43a464420c9fe68ba83937dlgao            except IOError:
160552302d4dee589a5df43a464420c9fe68ba83937dlgao                EdkLogger.error(None, FILE_WRITE_FAILURE, ExtraData=self.ReportFile)
160652302d4dee589a5df43a464420c9fe68ba83937dlgao            except:
160752302d4dee589a5df43a464420c9fe68ba83937dlgao                EdkLogger.error("BuildReport", CODE_ERROR, "Unknown fatal error when generating build report", ExtraData=self.ReportFile, RaiseError=False)
160852302d4dee589a5df43a464420c9fe68ba83937dlgao                EdkLogger.quiet("(Python %s on %s\n%s)" % (platform.python_version(), sys.platform, traceback.format_exc()))
160952302d4dee589a5df43a464420c9fe68ba83937dlgao            File.close()
1610636f2be673b2f43518167d8fddae56b714f19314lgao
161152302d4dee589a5df43a464420c9fe68ba83937dlgao# This acts like the main() function for the script, unless it is 'import'ed into another script.
161252302d4dee589a5df43a464420c9fe68ba83937dlgaoif __name__ == '__main__':
161352302d4dee589a5df43a464420c9fe68ba83937dlgao    pass
161452302d4dee589a5df43a464420c9fe68ba83937dlgao
1615