## @file | |
# process GUIDed section generation | |
# | |
# Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR> | |
# | |
# This program and the accompanying materials | |
# are licensed and made available under the terms and conditions of the BSD License | |
# which accompanies this distribution. The full text of the license may be found at | |
# http://opensource.org/licenses/bsd-license.php | |
# | |
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
# | |
## | |
# Import Modules | |
# | |
import Section | |
import subprocess | |
from Ffs import Ffs | |
import Common.LongFilePathOs as os | |
from GenFdsGlobalVariable import GenFdsGlobalVariable | |
from CommonDataClass.FdfClass import GuidSectionClassObject | |
from Common import ToolDefClassObject | |
import sys | |
from Common import EdkLogger | |
from Common.BuildToolError import * | |
from FvImageSection import FvImageSection | |
from Common.LongFilePathSupport import OpenLongFilePath as open | |
## generate GUIDed section | |
# | |
# | |
class GuidSection(GuidSectionClassObject) : | |
## The constructor | |
# | |
# @param self The object pointer | |
# | |
def __init__(self): | |
GuidSectionClassObject.__init__(self) | |
## GenSection() method | |
# | |
# Generate GUIDed section | |
# | |
# @param self The object pointer | |
# @param OutputPath Where to place output file | |
# @param ModuleName Which module this section belongs to | |
# @param SecNum Index of section | |
# @param KeyStringList Filter for inputs of section generation | |
# @param FfsInf FfsInfStatement object that contains this section data | |
# @param Dict dictionary contains macro and its value | |
# @retval tuple (Generated file name, section alignment) | |
# | |
def GenSection(self, OutputPath, ModuleName, SecNum, KeyStringList, FfsInf=None, Dict={}): | |
# | |
# Generate all section | |
# | |
self.KeyStringList = KeyStringList | |
self.CurrentArchList = GenFdsGlobalVariable.ArchList | |
if FfsInf != None: | |
self.Alignment = FfsInf.__ExtendMacro__(self.Alignment) | |
self.NameGuid = FfsInf.__ExtendMacro__(self.NameGuid) | |
self.SectionType = FfsInf.__ExtendMacro__(self.SectionType) | |
self.CurrentArchList = [FfsInf.CurrentArch] | |
SectFile = tuple() | |
SectAlign = [] | |
Index = 0 | |
MaxAlign = None | |
if self.FvAddr != []: | |
FvAddrIsSet = True | |
else: | |
FvAddrIsSet = False | |
if self.ProcessRequired in ("TRUE", "1"): | |
if self.FvAddr != []: | |
#no use FvAddr when the image is processed. | |
self.FvAddr = [] | |
if self.FvParentAddr != None: | |
#no use Parent Addr when the image is processed. | |
self.FvParentAddr = None | |
for Sect in self.SectionList: | |
Index = Index + 1 | |
SecIndex = '%s.%d' % (SecNum, Index) | |
# set base address for inside FvImage | |
if isinstance(Sect, FvImageSection): | |
if self.FvAddr != []: | |
Sect.FvAddr = self.FvAddr.pop(0) | |
self.IncludeFvSection = True | |
elif isinstance(Sect, GuidSection): | |
Sect.FvAddr = self.FvAddr | |
Sect.FvParentAddr = self.FvParentAddr | |
ReturnSectList, align = Sect.GenSection(OutputPath, ModuleName, SecIndex, KeyStringList, FfsInf, Dict) | |
if isinstance(Sect, GuidSection): | |
if Sect.IncludeFvSection: | |
self.IncludeFvSection = Sect.IncludeFvSection | |
if align != None: | |
if MaxAlign == None: | |
MaxAlign = align | |
if GenFdsGlobalVariable.GetAlignment (align) > GenFdsGlobalVariable.GetAlignment (MaxAlign): | |
MaxAlign = align | |
if ReturnSectList != []: | |
if align == None: | |
align = "1" | |
for file in ReturnSectList: | |
SectFile += (file,) | |
SectAlign.append(align) | |
if MaxAlign != None: | |
if self.Alignment == None: | |
self.Alignment = MaxAlign | |
else: | |
if GenFdsGlobalVariable.GetAlignment (MaxAlign) > GenFdsGlobalVariable.GetAlignment (self.Alignment): | |
self.Alignment = MaxAlign | |
OutputFile = OutputPath + \ | |
os.sep + \ | |
ModuleName + \ | |
'SEC' + \ | |
SecNum + \ | |
Ffs.SectionSuffix['GUIDED'] | |
OutputFile = os.path.normpath(OutputFile) | |
ExternalTool = None | |
ExternalOption = None | |
if self.NameGuid != None: | |
ExternalTool, ExternalOption = self.__FindExtendTool__() | |
# | |
# If not have GUID , call default | |
# GENCRC32 section | |
# | |
if self.NameGuid == None : | |
GenFdsGlobalVariable.VerboseLogger("Use GenSection function Generate CRC32 Section") | |
GenFdsGlobalVariable.GenerateSection(OutputFile, SectFile, Section.Section.SectionType[self.SectionType], InputAlign=SectAlign) | |
OutputFileList = [] | |
OutputFileList.append(OutputFile) | |
return OutputFileList, self.Alignment | |
#or GUID not in External Tool List | |
elif ExternalTool == None: | |
EdkLogger.error("GenFds", GENFDS_ERROR, "No tool found with GUID %s" % self.NameGuid) | |
else: | |
DummyFile = OutputFile + ".dummy" | |
# | |
# Call GenSection with DUMMY section type. | |
# | |
GenFdsGlobalVariable.GenerateSection(DummyFile, SectFile, InputAlign=SectAlign) | |
# | |
# Use external tool process the Output | |
# | |
TempFile = OutputPath + \ | |
os.sep + \ | |
ModuleName + \ | |
'SEC' + \ | |
SecNum + \ | |
'.tmp' | |
TempFile = os.path.normpath(TempFile) | |
# | |
# Remove temp file if its time stamp is older than dummy file | |
# Just in case the external tool fails at this time but succeeded before | |
# Error should be reported if the external tool does not generate a new output based on new input | |
# | |
if os.path.exists(TempFile) and os.path.exists(DummyFile) and os.path.getmtime(TempFile) < os.path.getmtime(DummyFile): | |
os.remove(TempFile) | |
FirstCall = False | |
CmdOption = '-e' | |
if ExternalOption != None: | |
CmdOption = CmdOption + ' ' + ExternalOption | |
if self.ProcessRequired not in ("TRUE", "1") and self.IncludeFvSection and not FvAddrIsSet and self.FvParentAddr != None: | |
#FirstCall is only set for the encapsulated flash FV image without process required attribute. | |
FirstCall = True | |
# | |
# Call external tool | |
# | |
ReturnValue = [1] | |
if FirstCall: | |
#first try to call the guided tool with -z option and CmdOption for the no process required guided tool. | |
GenFdsGlobalVariable.GuidTool(TempFile, [DummyFile], ExternalTool, '-z' + ' ' + CmdOption, ReturnValue) | |
# | |
# when no call or first call failed, ReturnValue are not 1. | |
# Call the guided tool with CmdOption | |
# | |
if ReturnValue[0] != 0: | |
FirstCall = False | |
ReturnValue[0] = 0 | |
GenFdsGlobalVariable.GuidTool(TempFile, [DummyFile], ExternalTool, CmdOption) | |
# | |
# There is external tool which does not follow standard rule which return nonzero if tool fails | |
# The output file has to be checked | |
# | |
if not os.path.exists(TempFile): | |
EdkLogger.error("GenFds", COMMAND_FAILURE, 'Fail to call %s, no output file was generated' % ExternalTool) | |
FileHandleIn = open(DummyFile, 'rb') | |
FileHandleIn.seek(0, 2) | |
InputFileSize = FileHandleIn.tell() | |
FileHandleOut = open(TempFile, 'rb') | |
FileHandleOut.seek(0, 2) | |
TempFileSize = FileHandleOut.tell() | |
Attribute = [] | |
HeaderLength = None | |
if self.ExtraHeaderSize != -1: | |
HeaderLength = str(self.ExtraHeaderSize) | |
if self.ProcessRequired == "NONE" and HeaderLength == None: | |
if TempFileSize > InputFileSize: | |
FileHandleIn.seek(0) | |
BufferIn = FileHandleIn.read() | |
FileHandleOut.seek(0) | |
BufferOut = FileHandleOut.read() | |
if BufferIn == BufferOut[TempFileSize - InputFileSize:]: | |
HeaderLength = str(TempFileSize - InputFileSize) | |
#auto sec guided attribute with process required | |
if HeaderLength == None: | |
Attribute.append('PROCESSING_REQUIRED') | |
FileHandleIn.close() | |
FileHandleOut.close() | |
if FirstCall and 'PROCESSING_REQUIRED' in Attribute: | |
# Guided data by -z option on first call is the process required data. Call the guided tool with the real option. | |
GenFdsGlobalVariable.GuidTool(TempFile, [DummyFile], ExternalTool, CmdOption) | |
# | |
# Call Gensection Add Section Header | |
# | |
if self.ProcessRequired in ("TRUE", "1"): | |
if 'PROCESSING_REQUIRED' not in Attribute: | |
Attribute.append('PROCESSING_REQUIRED') | |
if self.AuthStatusValid in ("TRUE", "1"): | |
Attribute.append('AUTH_STATUS_VALID') | |
GenFdsGlobalVariable.GenerateSection(OutputFile, [TempFile], Section.Section.SectionType['GUIDED'], | |
Guid=self.NameGuid, GuidAttr=Attribute, GuidHdrLen=HeaderLength) | |
OutputFileList = [] | |
OutputFileList.append(OutputFile) | |
if 'PROCESSING_REQUIRED' in Attribute: | |
# reset guided section alignment to none for the processed required guided data | |
self.Alignment = None | |
self.IncludeFvSection = False | |
self.ProcessRequired = "TRUE" | |
return OutputFileList, self.Alignment | |
## __FindExtendTool() | |
# | |
# Find location of tools to process section data | |
# | |
# @param self The object pointer | |
# | |
def __FindExtendTool__(self): | |
# if user not specify filter, try to deduce it from global data. | |
if self.KeyStringList == None or self.KeyStringList == []: | |
Target = GenFdsGlobalVariable.TargetName | |
ToolChain = GenFdsGlobalVariable.ToolChainTag | |
ToolDb = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDatabase | |
if ToolChain not in ToolDb['TOOL_CHAIN_TAG']: | |
EdkLogger.error("GenFds", GENFDS_ERROR, "Can not find external tool because tool tag %s is not defined in tools_def.txt!" % ToolChain) | |
self.KeyStringList = [Target + '_' + ToolChain + '_' + self.CurrentArchList[0]] | |
for Arch in self.CurrentArchList: | |
if Target + '_' + ToolChain + '_' + Arch not in self.KeyStringList: | |
self.KeyStringList.append(Target + '_' + ToolChain + '_' + Arch) | |
if GenFdsGlobalVariable.GuidToolDefinition: | |
if self.NameGuid in GenFdsGlobalVariable.GuidToolDefinition.keys(): | |
return GenFdsGlobalVariable.GuidToolDefinition[self.NameGuid] | |
ToolDefinition = ToolDefClassObject.ToolDefDict(GenFdsGlobalVariable.ConfDir).ToolsDefTxtDictionary | |
ToolPathTmp = None | |
ToolOption = None | |
for ToolDef in ToolDefinition.items(): | |
if self.NameGuid == ToolDef[1]: | |
KeyList = ToolDef[0].split('_') | |
Key = KeyList[0] + \ | |
'_' + \ | |
KeyList[1] + \ | |
'_' + \ | |
KeyList[2] | |
if Key in self.KeyStringList and KeyList[4] == 'GUID': | |
ToolPath = ToolDefinition.get(Key + \ | |
'_' + \ | |
KeyList[3] + \ | |
'_' + \ | |
'PATH') | |
ToolOption = ToolDefinition.get(Key + \ | |
'_' + \ | |
KeyList[3] + \ | |
'_' + \ | |
'FLAGS') | |
if ToolPathTmp == None: | |
ToolPathTmp = ToolPath | |
else: | |
if ToolPathTmp != ToolPath: | |
EdkLogger.error("GenFds", GENFDS_ERROR, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp, ToolPath)) | |
GenFdsGlobalVariable.GuidToolDefinition[self.NameGuid] = (ToolPathTmp, ToolOption) | |
return ToolPathTmp, ToolOption | |