1## @ PatchBinFv.py 2# 3# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR> 4# SPDX-License-Identifier: BSD-2-Clause-Patent 5# 6## 7 8import os 9import re 10import sys 11import time 12import shutil 13import struct 14import binascii 15from ctypes import * 16 17class FileChecker: 18 def __init__(self): 19 self.SyncSectionList = ["PatchPcd"] 20 self.FvName = "" 21 self.target = "" 22 self.sourceRoot = "" 23 self.reportFile = "" 24 self.InfPcdList = [] 25 26 def GetSectionName(self, line): 27 splitLine = line[1:-1].split(".") 28 return splitLine[0] 29 30 def IsSyncSection(self, line): 31 name = self.GetSectionName(line) 32 for sectionName in self.SyncSectionList: 33 if (cmp (sectionName, name) == 0) : 34 return True 35 return False 36 37 def PrintPcdList(self, pcdList): 38 for pcd in pcdList: 39 print "PCD: " + pcd[0] + "|" + pcd[1] + "|" + pcd[2] + " <== " + pcd[3] + "(" + pcd[4] + ")" 40 41 def GetInfFileGuid(self, fileName): 42 guid = "" 43 try : 44 file = open(fileName) 45 except Exception: 46 print "fail to open " + fileName 47 return 48 try: 49 while 1: 50 line = file.readline() 51 if not line: 52 break 53 54 newline = line[:-1] 55 56 if cmp (line[:11], " FILE_GUID") == 0: 57 splitLine = line.split("=") 58 templine = splitLine[1] 59 guid = templine[1:1+36] 60 finally: 61 file.close() 62 return guid 63 64 def ParseInfFile(self, fileName): 65 SyncToDest = False 66 try : 67 file = open(fileName) 68 except Exception: 69 print "fail to open " + fileName 70 return 71 try: 72 while 1: 73 line = file.readline() 74 if not line: 75 break 76 77 newline = line[:-1] 78 79 if cmp (line[0], "#") == 0: 80 continue 81 82 83 if cmp (line[0], "[") == 0: 84 SyncToDest = self.IsSyncSection(line) 85 PatchOffset = False 86 87 if (cmp (self.GetSectionName(line), "PatchPcd") == 0) : 88 PatchOffset = True 89 continue 90 91 if SyncToDest == True : 92 line = line.strip() 93 if (cmp (line, "") == 0) : 94 continue 95 if (cmp (line[0], "#") == 0) : 96 continue 97 98 splitLine = line.split(" ") 99 line = splitLine[0] 100 101 splitLine = line.split("|") 102 103 self.InfPcdList.append([splitLine[0], splitLine[1], splitLine[2], "", ""]) 104 105 finally: 106 file.close() 107 return 108 109 def ProcessFvInf(self, fvName): 110 sourceFileName = os.path.join(self.sourceRoot,fvName,self.target,fvName+".inf") 111 print "\nprocessing - " + sourceFileName 112 fileGuid = self.GetInfFileGuid (sourceFileName) 113 print "FV NAME GUID - " + fileGuid 114 115 self.InfPcdList = [] 116 self.ParseInfFile(sourceFileName) 117 118 self.InfPcdList.sort() 119 120 #self.PrintPcdList(self.InfPcdList) 121 122 try : 123 file = open(self.reportFile) 124 except Exception: 125 print "fail to open " + self.reportFile 126 return 127 try: 128 for pcd in self.InfPcdList: 129 file.seek(0) 130 print "checking - " + pcd[0] 131 ValuePair = self.GetPcdFromReport (file, pcd[0]) 132 pcd[3] = ValuePair[0] 133 pcd[4] = ValuePair[1] 134 finally: 135 file.close() 136 137 self.PrintPcdList(self.InfPcdList) 138 139 def PatchFv(self, fvName): 140 sourceFileName = os.path.join(self.sourceRoot,fvName,self.target,fvName+".Fv") 141 print "patching - " + sourceFileName 142 143 try : 144 file = open(sourceFileName, "rb") 145 except Exception: 146 print "fail to open " + sourceFileName 147 return 148 try: 149 buffer = file.read() 150 data = bytearray(buffer) 151 file.close() 152 153 for pcd in self.InfPcdList: 154 offset = int(pcd[2], 16) 155 if (cmp (pcd[4], "BOOLEAN") == 0) or (cmp (pcd[4], "UINT8") == 0): 156 b = struct.pack("B", int(pcd[3],16)) 157 print " [" + hex(offset) + "] " + binascii.hexlify(data[offset:offset+1]) + " <= " + binascii.hexlify(b) 158 data[offset:offset+1] = b 159 elif (cmp (pcd[4], "UINT16") == 0): 160 h = struct.pack("H", int(pcd[3],16)) 161 print " [" + hex(offset) + "] " + binascii.hexlify(data[offset:offset+2]) + " <= " + binascii.hexlify(h) 162 data[offset:offset+2] = h 163 elif (cmp (pcd[4], "UINT32") == 0): 164 l = struct.pack("I", int(pcd[3],16)) 165 print " [" + hex(offset) + "] " + binascii.hexlify(data[offset:offset+4]) + " <= " + binascii.hexlify(l) 166 data[offset:offset+4] = l 167 elif (cmp (pcd[4], "UINT64") == 0): 168 q = struct.pack("Q", int(pcd[3],16)) 169 print " [" + hex(offset) + "] " + binascii.hexlify(data[offset:offset+8]) + " <= " + binascii.hexlify(q) 170 data[offset:offset+8] = q 171 file = open(sourceFileName, "wb") 172 file.write(data) 173 finally: 174 file.close() 175 176 def GetPcdFromReport(self, file, pcd): 177 FoundPkg = False 178 pcdSplit = pcd.split(".") 179 TargetPkg = pcdSplit[0] 180 TargetPcd = pcdSplit[1] 181 while 1: 182 line = file.readline() 183 if not line: 184 break 185 186 newline = line[:-1] 187 188 if (cmp (newline, TargetPkg) == 0): 189 FoundPkg = True 190 continue 191 192 if (cmp (newline, "") == 0) or ((cmp (newline[0], " ") != 0) and (cmp (newline[0], "0") != 0)): 193 FoundPkg = False 194 195 if (FoundPkg == True) : 196 newline = newline.strip() 197 splitLine = newline.split(" ", 2) 198 if (cmp (splitLine[0], "*F") == 0) or (cmp (splitLine[0], "*P") == 0): 199 if (cmp (splitLine[1], TargetPcd) == 0): 200 print "found - " + TargetPkg + "." + TargetPcd 201 202 splitLine = splitLine[2].strip()[1:].strip().split(" ", 1) 203 if (cmp (splitLine[0], "FIXED") == 0) or (cmp (splitLine[0], "PATCH") == 0): 204 SplitLine = splitLine[1].strip()[1:].split(")", 1) 205 Type = SplitLine[0] 206 Value = SplitLine[1].strip()[1:].strip().split()[0] 207 print " Type - (" + Type + "), Value - (" + Value + ")" 208 return [Value, Type] 209 return ["", ""] 210 211def main(): 212 global FileChecker 213 214 fileChecker = FileChecker() 215 216 if (len(sys.argv) != 5) : 217 print "usage: PatchBinFv <Target> <SourceRoot> <ReportFile> <FvName>" 218 return 0 219 220 fileChecker.target = sys.argv[1] 221 fileChecker.sourceRoot = sys.argv[2] 222 fileChecker.reportFile = sys.argv[3] 223 fileChecker.FvName = sys.argv[4] 224 225 fileChecker.ProcessFvInf (fileChecker.FvName) 226 fileChecker.PatchFv (fileChecker.FvName) 227 228if __name__ == '__main__': 229 sys.exit(main()) 230