1## @file 2# process FFS generation from FILE statement 3# 4# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR> 5# 6# SPDX-License-Identifier: BSD-2-Clause-Patent 7# 8 9## 10# Import Modules 11# 12from __future__ import absolute_import 13from io import BytesIO 14from struct import pack 15from CommonDataClass.FdfClass import FileStatementClassObject 16from Common import EdkLogger 17from Common.BuildToolError import GENFDS_ERROR 18from Common.Misc import GuidStructureByteArrayToGuidString, SaveFileOnChange 19import Common.LongFilePathOs as os 20from .GuidSection import GuidSection 21from .FvImageSection import FvImageSection 22from .Ffs import FdfFvFileTypeToFileType 23from .GenFdsGlobalVariable import GenFdsGlobalVariable 24import shutil 25 26## generate FFS from FILE 27# 28# 29class FileStatement (FileStatementClassObject): 30 ## The constructor 31 # 32 # @param self The object pointer 33 # 34 def __init__(self): 35 FileStatementClassObject.__init__(self) 36 self.CurrentLineNum = None 37 self.CurrentLineContent = None 38 self.FileName = None 39 self.InfFileName = None 40 self.SubAlignment = None 41 42 ## GenFfs() method 43 # 44 # Generate FFS 45 # 46 # @param self The object pointer 47 # @param Dict dictionary contains macro and value pair 48 # @param FvChildAddr Array of the inside FvImage base address 49 # @param FvParentAddr Parent Fv base address 50 # @retval string Generated FFS file name 51 # 52 def GenFfs(self, Dict = None, FvChildAddr=[], FvParentAddr=None, IsMakefile=False, FvName=None): 53 54 if self.NameGuid and self.NameGuid.startswith('PCD('): 55 PcdValue = GenFdsGlobalVariable.GetPcdValue(self.NameGuid) 56 if len(PcdValue) == 0: 57 EdkLogger.error("GenFds", GENFDS_ERROR, '%s NOT defined.' \ 58 % (self.NameGuid)) 59 if PcdValue.startswith('{'): 60 PcdValue = GuidStructureByteArrayToGuidString(PcdValue) 61 RegistryGuidStr = PcdValue 62 if len(RegistryGuidStr) == 0: 63 EdkLogger.error("GenFds", GENFDS_ERROR, 'GUID value for %s in wrong format.' \ 64 % (self.NameGuid)) 65 self.NameGuid = RegistryGuidStr 66 67 Str = self.NameGuid 68 if FvName: 69 Str += FvName 70 OutputDir = os.path.join(GenFdsGlobalVariable.FfsDir, Str) 71 if os.path.exists(OutputDir): 72 shutil.rmtree(OutputDir) 73 if not os.path.exists(OutputDir): 74 os.makedirs(OutputDir) 75 76 if Dict is None: 77 Dict = {} 78 79 Dict.update(self.DefineVarDict) 80 SectionAlignments = None 81 if self.FvName: 82 Buffer = BytesIO() 83 if self.FvName.upper() not in GenFdsGlobalVariable.FdfParser.Profile.FvDict: 84 EdkLogger.error("GenFds", GENFDS_ERROR, "FV (%s) is NOT described in FDF file!" % (self.FvName)) 85 Fv = GenFdsGlobalVariable.FdfParser.Profile.FvDict.get(self.FvName.upper()) 86 FileName = Fv.AddToBuffer(Buffer) 87 SectionFiles = [FileName] 88 89 elif self.FdName: 90 if self.FdName.upper() not in GenFdsGlobalVariable.FdfParser.Profile.FdDict: 91 EdkLogger.error("GenFds", GENFDS_ERROR, "FD (%s) is NOT described in FDF file!" % (self.FdName)) 92 Fd = GenFdsGlobalVariable.FdfParser.Profile.FdDict.get(self.FdName.upper()) 93 FileName = Fd.GenFd() 94 SectionFiles = [FileName] 95 96 elif self.FileName: 97 if hasattr(self, 'FvFileType') and self.FvFileType == 'RAW': 98 if isinstance(self.FileName, list) and isinstance(self.SubAlignment, list) and len(self.FileName) == len(self.SubAlignment): 99 FileContent = BytesIO() 100 MaxAlignIndex = 0 101 MaxAlignValue = 1 102 for Index, File in enumerate(self.FileName): 103 try: 104 f = open(File, 'rb') 105 except: 106 GenFdsGlobalVariable.ErrorLogger("Error opening RAW file %s." % (File)) 107 Content = f.read() 108 f.close() 109 AlignValue = 1 110 if self.SubAlignment[Index]: 111 AlignValue = GenFdsGlobalVariable.GetAlignment(self.SubAlignment[Index]) 112 if AlignValue > MaxAlignValue: 113 MaxAlignIndex = Index 114 MaxAlignValue = AlignValue 115 FileContent.write(Content) 116 if len(FileContent.getvalue()) % AlignValue != 0: 117 Size = AlignValue - len(FileContent.getvalue()) % AlignValue 118 for i in range(0, Size): 119 FileContent.write(pack('B', 0xFF)) 120 121 if FileContent.getvalue() != b'': 122 OutputRAWFile = os.path.join(GenFdsGlobalVariable.FfsDir, self.NameGuid, self.NameGuid + '.raw') 123 SaveFileOnChange(OutputRAWFile, FileContent.getvalue(), True) 124 self.FileName = OutputRAWFile 125 self.SubAlignment = self.SubAlignment[MaxAlignIndex] 126 127 if self.Alignment and self.SubAlignment: 128 if GenFdsGlobalVariable.GetAlignment (self.Alignment) < GenFdsGlobalVariable.GetAlignment (self.SubAlignment): 129 self.Alignment = self.SubAlignment 130 elif self.SubAlignment: 131 self.Alignment = self.SubAlignment 132 133 self.FileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(self.FileName) 134 #Replace $(SAPCE) with real space 135 self.FileName = self.FileName.replace('$(SPACE)', ' ') 136 SectionFiles = [GenFdsGlobalVariable.MacroExtend(self.FileName, Dict)] 137 138 else: 139 SectionFiles = [] 140 Index = 0 141 SectionAlignments = [] 142 for section in self.SectionList: 143 Index = Index + 1 144 SecIndex = '%d' %Index 145 # process the inside FvImage from FvSection or GuidSection 146 if FvChildAddr != []: 147 if isinstance(section, FvImageSection): 148 section.FvAddr = FvChildAddr.pop(0) 149 elif isinstance(section, GuidSection): 150 section.FvAddr = FvChildAddr 151 if FvParentAddr and isinstance(section, GuidSection): 152 section.FvParentAddr = FvParentAddr 153 154 if self.KeepReloc == False: 155 section.KeepReloc = False 156 sectList, align = section.GenSection(OutputDir, self.NameGuid, SecIndex, self.KeyStringList, None, Dict) 157 if sectList != []: 158 for sect in sectList: 159 SectionFiles.append(sect) 160 SectionAlignments.append(align) 161 162 # 163 # Prepare the parameter 164 # 165 FfsFileOutput = os.path.join(OutputDir, self.NameGuid + '.ffs') 166 GenFdsGlobalVariable.GenerateFfs(FfsFileOutput, SectionFiles, 167 FdfFvFileTypeToFileType.get(self.FvFileType), 168 self.NameGuid, 169 Fixed=self.Fixed, 170 CheckSum=self.CheckSum, 171 Align=self.Alignment, 172 SectionAlign=SectionAlignments 173 ) 174 175 return FfsFileOutput 176