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