## @file | |
# process GUIDed section generation | |
# | |
# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR> | |
# Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<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 | |
# | |
from __future__ import absolute_import | |
from . import Section | |
import subprocess | |
from .Ffs import Ffs | |
import Common.LongFilePathOs as os | |
from .GenFdsGlobalVariable import GenFdsGlobalVariable | |
from .GenFdsGlobalVariable import FindExtendTool | |
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 | |
from Common.DataType import * | |
## 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={}, IsMakefile=False): | |
# | |
# Generate all section | |
# | |
self.KeyStringList = KeyStringList | |
self.CurrentArchList = GenFdsGlobalVariable.ArchList | |
if FfsInf is not 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 is not 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, IsMakefile=IsMakefile) | |
if isinstance(Sect, GuidSection): | |
if Sect.IncludeFvSection: | |
self.IncludeFvSection = Sect.IncludeFvSection | |
if align is not None: | |
if MaxAlign is None: | |
MaxAlign = align | |
if GenFdsGlobalVariable.GetAlignment (align) > GenFdsGlobalVariable.GetAlignment (MaxAlign): | |
MaxAlign = align | |
if ReturnSectList != []: | |
if align is None: | |
align = "1" | |
for file in ReturnSectList: | |
SectFile += (file,) | |
SectAlign.append(align) | |
if MaxAlign is not None: | |
if self.Alignment is None: | |
self.Alignment = MaxAlign | |
else: | |
if GenFdsGlobalVariable.GetAlignment (MaxAlign) > GenFdsGlobalVariable.GetAlignment (self.Alignment): | |
self.Alignment = MaxAlign | |
OutputFile = OutputPath + \ | |
os.sep + \ | |
ModuleName + \ | |
SUP_MODULE_SEC + \ | |
SecNum + \ | |
Ffs.SectionSuffix['GUIDED'] | |
OutputFile = os.path.normpath(OutputFile) | |
ExternalTool = None | |
ExternalOption = None | |
if self.NameGuid is not None: | |
ExternalTool, ExternalOption = FindExtendTool(self.KeyStringList, self.CurrentArchList, self.NameGuid) | |
# | |
# If not have GUID , call default | |
# GENCRC32 section | |
# | |
if self.NameGuid is None : | |
GenFdsGlobalVariable.VerboseLogger("Use GenSection function Generate CRC32 Section") | |
GenFdsGlobalVariable.GenerateSection(OutputFile, SectFile, Section.Section.SectionType[self.SectionType], InputAlign=SectAlign, IsMakefile=IsMakefile) | |
OutputFileList = [] | |
OutputFileList.append(OutputFile) | |
return OutputFileList, self.Alignment | |
#or GUID not in External Tool List | |
elif ExternalTool is 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, IsMakefile=IsMakefile) | |
# | |
# Use external tool process the Output | |
# | |
TempFile = OutputPath + \ | |
os.sep + \ | |
ModuleName + \ | |
SUP_MODULE_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 is not None: | |
CmdOption = CmdOption + ' ' + ExternalOption | |
if not GenFdsGlobalVariable.EnableGenfdsMultiThread: | |
if self.ProcessRequired not in ("TRUE", "1") and self.IncludeFvSection and not FvAddrIsSet and self.FvParentAddr is not 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 is 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 is 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) | |
else: | |
#add input file for GenSec get PROCESSING_REQUIRED | |
GenFdsGlobalVariable.GuidTool(TempFile, [DummyFile], ExternalTool, CmdOption, IsMakefile=IsMakefile) | |
Attribute = [] | |
HeaderLength = None | |
if self.ExtraHeaderSize != -1: | |
HeaderLength = str(self.ExtraHeaderSize) | |
if self.AuthStatusValid in ("TRUE", "1"): | |
Attribute.append('AUTH_STATUS_VALID') | |
if self.ProcessRequired == "NONE" and HeaderLength is None: | |
GenFdsGlobalVariable.GenerateSection(OutputFile, [TempFile], Section.Section.SectionType['GUIDED'], | |
Guid=self.NameGuid, GuidAttr=Attribute, | |
GuidHdrLen=HeaderLength, DummyFile=DummyFile, IsMakefile=IsMakefile) | |
else: | |
if self.ProcessRequired in ("TRUE", "1"): | |
if 'PROCESSING_REQUIRED' not in Attribute: | |
Attribute.append('PROCESSING_REQUIRED') | |
GenFdsGlobalVariable.GenerateSection(OutputFile, [TempFile], Section.Section.SectionType['GUIDED'], | |
Guid=self.NameGuid, GuidAttr=Attribute, | |
GuidHdrLen=HeaderLength, IsMakefile=IsMakefile) | |
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" | |
if IsMakefile and self.Alignment is not None and self.Alignment.strip() == '0': | |
self.Alignment = '1' | |
return OutputFileList, self.Alignment | |