| 1 | ## @file\r |
| 2 | # Parse FV image\r |
| 3 | #\r |
| 4 | # Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>\r |
| 5 | # This program and the accompanying materials\r |
| 6 | # are licensed and made available under the terms and conditions of the BSD License\r |
| 7 | # which accompanies this distribution. The full text of the license may be found at\r |
| 8 | # http://opensource.org/licenses/bsd-license.php\r |
| 9 | #\r |
| 10 | # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r |
| 11 | # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r |
| 12 | #\r |
| 13 | \r |
| 14 | ## Import Modules\r |
| 15 | #\r |
| 16 | import Common.LongFilePathOs as os\r |
| 17 | import re\r |
| 18 | import sys\r |
| 19 | import uuid\r |
| 20 | import struct\r |
| 21 | import codecs\r |
| 22 | import copy\r |
| 23 | \r |
| 24 | from UserDict import IterableUserDict\r |
| 25 | from cStringIO import StringIO\r |
| 26 | from array import array\r |
| 27 | from Common.LongFilePathSupport import OpenLongFilePath as open\r |
| 28 | from CommonDataClass import *\r |
| 29 | from Common.Misc import sdict, GuidStructureStringToGuidString\r |
| 30 | \r |
| 31 | import Common.EdkLogger as EdkLogger\r |
| 32 | \r |
| 33 | import EotGlobalData\r |
| 34 | \r |
| 35 | # Global definiton\r |
| 36 | gFfsPrintTitle = "%-36s %-21s %8s %8s %8s %-4s %-36s" % ("GUID", "TYPE", "OFFSET", "SIZE", "FREE", "ALIGN", "NAME")\r |
| 37 | gFfsPrintFormat = "%36s %-21s %8X %8X %8X %4s %-36s"\r |
| 38 | gGuidStringFormat = "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"\r |
| 39 | gPeiAprioriFileNameGuid = '1b45cc0a-156a-428a-af62-49864da0e6e6'\r |
| 40 | gAprioriGuid = 'fc510ee7-ffdc-11d4-bd41-0080c73c8881'\r |
| 41 | gIndention = -4\r |
| 42 | \r |
| 43 | ## Image() class\r |
| 44 | #\r |
| 45 | # A class for Image\r |
| 46 | #\r |
| 47 | class Image(array):\r |
| 48 | _HEADER_ = struct.Struct("")\r |
| 49 | _HEADER_SIZE_ = _HEADER_.size\r |
| 50 | \r |
| 51 | def __new__(cls, *args, **kwargs):\r |
| 52 | return array.__new__(cls, 'B')\r |
| 53 | \r |
| 54 | def __init__(m, ID=None):\r |
| 55 | if ID is None:\r |
| 56 | m._ID_ = str(uuid.uuid1()).upper()\r |
| 57 | else:\r |
| 58 | m._ID_ = ID\r |
| 59 | m._BUF_ = None\r |
| 60 | m._LEN_ = None\r |
| 61 | m._OFF_ = None\r |
| 62 | \r |
| 63 | m._SubImages = sdict() # {offset: Image()}\r |
| 64 | \r |
| 65 | array.__init__(m, 'B')\r |
| 66 | \r |
| 67 | def __repr__(m):\r |
| 68 | return m._ID_\r |
| 69 | \r |
| 70 | def __len__(m):\r |
| 71 | Len = array.__len__(m)\r |
| 72 | for Offset in m._SubImages:\r |
| 73 | Len += len(m._SubImages[Offset])\r |
| 74 | return Len\r |
| 75 | \r |
| 76 | def _Unpack(m):\r |
| 77 | m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])\r |
| 78 | return len(m)\r |
| 79 | \r |
| 80 | def _Pack(m, PadByte=0xFF):\r |
| 81 | raise NotImplementedError\r |
| 82 | \r |
| 83 | def frombuffer(m, Buffer, Offset=0, Size=None):\r |
| 84 | m._BUF_ = Buffer\r |
| 85 | m._OFF_ = Offset\r |
| 86 | # we may need the Size information in advance if it's given\r |
| 87 | m._LEN_ = Size\r |
| 88 | m._LEN_ = m._Unpack()\r |
| 89 | \r |
| 90 | def empty(m):\r |
| 91 | del m[0:]\r |
| 92 | \r |
| 93 | def GetField(m, FieldStruct, Offset=0):\r |
| 94 | return FieldStruct.unpack_from(m, Offset)\r |
| 95 | \r |
| 96 | def SetField(m, FieldStruct, Offset, *args):\r |
| 97 | # check if there's enough space\r |
| 98 | Size = FieldStruct.size\r |
| 99 | if Size > len(m):\r |
| 100 | m.extend([0] * (Size - len(m)))\r |
| 101 | FieldStruct.pack_into(m, Offset, *args)\r |
| 102 | \r |
| 103 | def _SetData(m, Data):\r |
| 104 | if len(m) < m._HEADER_SIZE_:\r |
| 105 | m.extend([0] * (m._HEADER_SIZE_ - len(m)))\r |
| 106 | else:\r |
| 107 | del m[m._HEADER_SIZE_:]\r |
| 108 | m.extend(Data)\r |
| 109 | \r |
| 110 | def _GetData(m):\r |
| 111 | if len(m) > m._HEADER_SIZE_:\r |
| 112 | return m[m._HEADER_SIZE_:]\r |
| 113 | return None\r |
| 114 | \r |
| 115 | Data = property(_GetData, _SetData)\r |
| 116 | \r |
| 117 | ## FirmwareVolume() class\r |
| 118 | #\r |
| 119 | # A class for Firmware Volume\r |
| 120 | #\r |
| 121 | class FirmwareVolume(Image):\r |
| 122 | # Read FvLength, Attributes, HeaderLength, Checksum\r |
| 123 | _HEADER_ = struct.Struct("16x 1I2H8B 1Q 4x 1I 1H 1H")\r |
| 124 | _HEADER_SIZE_ = _HEADER_.size\r |
| 125 | \r |
| 126 | _FfsGuid = "8C8CE578-8A3D-4F1C-9935-896185C32DD3"\r |
| 127 | \r |
| 128 | _GUID_ = struct.Struct("16x 1I2H8B")\r |
| 129 | _LENGTH_ = struct.Struct("16x 16x 1Q")\r |
| 130 | _SIG_ = struct.Struct("16x 16x 8x 1I")\r |
| 131 | _ATTR_ = struct.Struct("16x 16x 8x 4x 1I")\r |
| 132 | _HLEN_ = struct.Struct("16x 16x 8x 4x 4x 1H")\r |
| 133 | _CHECKSUM_ = struct.Struct("16x 16x 8x 4x 4x 2x 1H")\r |
| 134 | \r |
| 135 | def __init__(self, Name=''):\r |
| 136 | Image.__init__(self)\r |
| 137 | self.Name = Name\r |
| 138 | self.FfsDict = sdict()\r |
| 139 | self.OrderedFfsDict = sdict()\r |
| 140 | self.UnDispatchedFfsDict = sdict()\r |
| 141 | self.ProtocolList = sdict()\r |
| 142 | \r |
| 143 | def CheckArchProtocol(self):\r |
| 144 | for Item in EotGlobalData.gArchProtocolGuids:\r |
| 145 | if Item.lower() not in EotGlobalData.gProtocolList:\r |
| 146 | \r |
| 147 | return False\r |
| 148 | \r |
| 149 | return True\r |
| 150 | \r |
| 151 | def ParseDepex(self, Depex, Type):\r |
| 152 | List = None\r |
| 153 | if Type == 'Ppi':\r |
| 154 | List = EotGlobalData.gPpiList\r |
| 155 | if Type == 'Protocol':\r |
| 156 | List = EotGlobalData.gProtocolList\r |
| 157 | DepexStack = []\r |
| 158 | DepexList = []\r |
| 159 | DepexString = ''\r |
| 160 | FileDepex = None\r |
| 161 | CouldBeLoaded = True\r |
| 162 | for Index in range(0, len(Depex.Expression)):\r |
| 163 | Item = Depex.Expression[Index]\r |
| 164 | if Item == 0x00:\r |
| 165 | Index = Index + 1\r |
| 166 | Guid = gGuidStringFormat % Depex.Expression[Index]\r |
| 167 | if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:\r |
| 168 | return (True, 'BEFORE %s' % Guid, [Guid, 'BEFORE'])\r |
| 169 | elif Item == 0x01:\r |
| 170 | Index = Index + 1\r |
| 171 | Guid = gGuidStringFormat % Depex.Expression[Index]\r |
| 172 | if Guid in self.OrderedFfsDict and Depex.Expression[Index + 1] == 0x08:\r |
| 173 | return (True, 'AFTER %s' % Guid, [Guid, 'AFTER'])\r |
| 174 | elif Item == 0x02:\r |
| 175 | Index = Index + 1\r |
| 176 | Guid = gGuidStringFormat % Depex.Expression[Index]\r |
| 177 | if Guid.lower() in List:\r |
| 178 | DepexStack.append(True)\r |
| 179 | DepexList.append(Guid)\r |
| 180 | else:\r |
| 181 | DepexStack.append(False)\r |
| 182 | DepexList.append(Guid)\r |
| 183 | continue\r |
| 184 | elif Item == 0x03 or Item == 0x04:\r |
| 185 | DepexStack.append(eval(str(DepexStack.pop()) + ' ' + Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))\r |
| 186 | DepexList.append(str(DepexList.pop()) + ' ' + Depex._OPCODE_STRING_[Item].upper() + ' ' + str(DepexList.pop()))\r |
| 187 | elif Item == 0x05:\r |
| 188 | DepexStack.append(eval(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexStack.pop())))\r |
| 189 | DepexList.append(Depex._OPCODE_STRING_[Item].lower() + ' ' + str(DepexList.pop()))\r |
| 190 | elif Item == 0x06:\r |
| 191 | DepexStack.append(True)\r |
| 192 | DepexList.append('TRUE')\r |
| 193 | DepexString = DepexString + 'TRUE' + ' '\r |
| 194 | elif Item == 0x07:\r |
| 195 | DepexStack.append(False)\r |
| 196 | DepexList.append('False')\r |
| 197 | DepexString = DepexString + 'FALSE' + ' '\r |
| 198 | elif Item == 0x08:\r |
| 199 | if Index != len(Depex.Expression) - 1:\r |
| 200 | CouldBeLoaded = False\r |
| 201 | else:\r |
| 202 | CouldBeLoaded = DepexStack.pop()\r |
| 203 | else:\r |
| 204 | CouldBeLoaded = False\r |
| 205 | if DepexList != []:\r |
| 206 | DepexString = DepexList[0].strip()\r |
| 207 | return (CouldBeLoaded, DepexString, FileDepex)\r |
| 208 | \r |
| 209 | def Dispatch(self, Db = None):\r |
| 210 | if Db is None:\r |
| 211 | return False\r |
| 212 | self.UnDispatchedFfsDict = copy.copy(self.FfsDict)\r |
| 213 | # Find PeiCore, DexCore, PeiPriori, DxePriori first\r |
| 214 | FfsSecCoreGuid = None\r |
| 215 | FfsPeiCoreGuid = None\r |
| 216 | FfsDxeCoreGuid = None\r |
| 217 | FfsPeiPrioriGuid = None\r |
| 218 | FfsDxePrioriGuid = None\r |
| 219 | for FfsID in self.UnDispatchedFfsDict:\r |
| 220 | Ffs = self.UnDispatchedFfsDict[FfsID]\r |
| 221 | if Ffs.Type == 0x03:\r |
| 222 | FfsSecCoreGuid = FfsID\r |
| 223 | continue\r |
| 224 | if Ffs.Type == 0x04:\r |
| 225 | FfsPeiCoreGuid = FfsID\r |
| 226 | continue\r |
| 227 | if Ffs.Type == 0x05:\r |
| 228 | FfsDxeCoreGuid = FfsID\r |
| 229 | continue\r |
| 230 | if Ffs.Guid.lower() == gPeiAprioriFileNameGuid:\r |
| 231 | FfsPeiPrioriGuid = FfsID\r |
| 232 | continue\r |
| 233 | if Ffs.Guid.lower() == gAprioriGuid:\r |
| 234 | FfsDxePrioriGuid = FfsID\r |
| 235 | continue\r |
| 236 | \r |
| 237 | # Parse SEC_CORE first\r |
| 238 | if FfsSecCoreGuid is not None:\r |
| 239 | self.OrderedFfsDict[FfsSecCoreGuid] = self.UnDispatchedFfsDict.pop(FfsSecCoreGuid)\r |
| 240 | self.LoadPpi(Db, FfsSecCoreGuid)\r |
| 241 | \r |
| 242 | # Parse PEI first\r |
| 243 | if FfsPeiCoreGuid is not None:\r |
| 244 | self.OrderedFfsDict[FfsPeiCoreGuid] = self.UnDispatchedFfsDict.pop(FfsPeiCoreGuid)\r |
| 245 | self.LoadPpi(Db, FfsPeiCoreGuid)\r |
| 246 | if FfsPeiPrioriGuid is not None:\r |
| 247 | # Load PEIM described in priori file\r |
| 248 | FfsPeiPriori = self.UnDispatchedFfsDict.pop(FfsPeiPrioriGuid)\r |
| 249 | if len(FfsPeiPriori.Sections) == 1:\r |
| 250 | Section = FfsPeiPriori.Sections.popitem()[1]\r |
| 251 | if Section.Type == 0x19:\r |
| 252 | GuidStruct = struct.Struct('1I2H8B')\r |
| 253 | Start = 4\r |
| 254 | while len(Section) > Start:\r |
| 255 | Guid = GuidStruct.unpack_from(Section[Start : Start + 16])\r |
| 256 | GuidString = gGuidStringFormat % Guid\r |
| 257 | Start = Start + 16\r |
| 258 | if GuidString in self.UnDispatchedFfsDict:\r |
| 259 | self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)\r |
| 260 | self.LoadPpi(Db, GuidString)\r |
| 261 | \r |
| 262 | self.DisPatchPei(Db)\r |
| 263 | \r |
| 264 | # Parse DXE then\r |
| 265 | if FfsDxeCoreGuid is not None:\r |
| 266 | self.OrderedFfsDict[FfsDxeCoreGuid] = self.UnDispatchedFfsDict.pop(FfsDxeCoreGuid)\r |
| 267 | self.LoadProtocol(Db, FfsDxeCoreGuid)\r |
| 268 | if FfsDxePrioriGuid is not None:\r |
| 269 | # Load PEIM described in priori file\r |
| 270 | FfsDxePriori = self.UnDispatchedFfsDict.pop(FfsDxePrioriGuid)\r |
| 271 | if len(FfsDxePriori.Sections) == 1:\r |
| 272 | Section = FfsDxePriori.Sections.popitem()[1]\r |
| 273 | if Section.Type == 0x19:\r |
| 274 | GuidStruct = struct.Struct('1I2H8B')\r |
| 275 | Start = 4\r |
| 276 | while len(Section) > Start:\r |
| 277 | Guid = GuidStruct.unpack_from(Section[Start : Start + 16])\r |
| 278 | GuidString = gGuidStringFormat % Guid\r |
| 279 | Start = Start + 16\r |
| 280 | if GuidString in self.UnDispatchedFfsDict:\r |
| 281 | self.OrderedFfsDict[GuidString] = self.UnDispatchedFfsDict.pop(GuidString)\r |
| 282 | self.LoadProtocol(Db, GuidString)\r |
| 283 | \r |
| 284 | self.DisPatchDxe(Db)\r |
| 285 | \r |
| 286 | def LoadProtocol(self, Db, ModuleGuid):\r |
| 287 | SqlCommand = """select GuidValue from Report\r |
| 288 | where SourceFileFullPath in\r |
| 289 | (select Value1 from Inf where BelongsToFile =\r |
| 290 | (select BelongsToFile from Inf\r |
| 291 | where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)\r |
| 292 | and Model = %s)\r |
| 293 | and ItemType = 'Protocol' and ItemMode = 'Produced'""" \\r |
| 294 | % (ModuleGuid, 5001, 3007)\r |
| 295 | RecordSet = Db.TblReport.Exec(SqlCommand)\r |
| 296 | for Record in RecordSet:\r |
| 297 | SqlCommand = """select Value2 from Inf where BelongsToFile =\r |
| 298 | (select DISTINCT BelongsToFile from Inf\r |
| 299 | where Value1 =\r |
| 300 | (select SourceFileFullPath from Report\r |
| 301 | where GuidValue like '%s' and ItemMode = 'Callback'))\r |
| 302 | and Value1 = 'FILE_GUID'""" % Record[0]\r |
| 303 | CallBackSet = Db.TblReport.Exec(SqlCommand)\r |
| 304 | if CallBackSet != []:\r |
| 305 | EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid\r |
| 306 | else:\r |
| 307 | EotGlobalData.gProtocolList[Record[0].lower()] = ModuleGuid\r |
| 308 | \r |
| 309 | def LoadPpi(self, Db, ModuleGuid):\r |
| 310 | SqlCommand = """select GuidValue from Report\r |
| 311 | where SourceFileFullPath in\r |
| 312 | (select Value1 from Inf where BelongsToFile =\r |
| 313 | (select BelongsToFile from Inf\r |
| 314 | where Value1 = 'FILE_GUID' and Value2 like '%s' and Model = %s)\r |
| 315 | and Model = %s)\r |
| 316 | and ItemType = 'Ppi' and ItemMode = 'Produced'""" \\r |
| 317 | % (ModuleGuid, 5001, 3007)\r |
| 318 | RecordSet = Db.TblReport.Exec(SqlCommand)\r |
| 319 | for Record in RecordSet:\r |
| 320 | EotGlobalData.gPpiList[Record[0].lower()] = ModuleGuid\r |
| 321 | \r |
| 322 | def DisPatchDxe(self, Db):\r |
| 323 | IsInstalled = False\r |
| 324 | ScheduleList = sdict()\r |
| 325 | for FfsID in self.UnDispatchedFfsDict:\r |
| 326 | CouldBeLoaded = False\r |
| 327 | DepexString = ''\r |
| 328 | FileDepex = None\r |
| 329 | Ffs = self.UnDispatchedFfsDict[FfsID]\r |
| 330 | if Ffs.Type == 0x07:\r |
| 331 | # Get Depex\r |
| 332 | IsFoundDepex = False\r |
| 333 | for Section in Ffs.Sections.values():\r |
| 334 | # Find Depex\r |
| 335 | if Section.Type == 0x13:\r |
| 336 | IsFoundDepex = True\r |
| 337 | CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Protocol')\r |
| 338 | break\r |
| 339 | if Section.Type == 0x01:\r |
| 340 | CompressSections = Section._SubImages[4]\r |
| 341 | for CompressSection in CompressSections.Sections:\r |
| 342 | if CompressSection.Type == 0x13:\r |
| 343 | IsFoundDepex = True\r |
| 344 | CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Protocol')\r |
| 345 | break\r |
| 346 | if CompressSection.Type == 0x02:\r |
| 347 | NewSections = CompressSection._SubImages[4]\r |
| 348 | for NewSection in NewSections.Sections:\r |
| 349 | if NewSection.Type == 0x13:\r |
| 350 | IsFoundDepex = True\r |
| 351 | CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Protocol')\r |
| 352 | break\r |
| 353 | \r |
| 354 | # Not find Depex\r |
| 355 | if not IsFoundDepex:\r |
| 356 | CouldBeLoaded = self.CheckArchProtocol()\r |
| 357 | DepexString = ''\r |
| 358 | FileDepex = None\r |
| 359 | \r |
| 360 | # Append New Ffs\r |
| 361 | if CouldBeLoaded:\r |
| 362 | IsInstalled = True\r |
| 363 | NewFfs = self.UnDispatchedFfsDict.pop(FfsID)\r |
| 364 | NewFfs.Depex = DepexString\r |
| 365 | if FileDepex is not None:\r |
| 366 | ScheduleList.insert.insert(FileDepex[1], FfsID, NewFfs, FileDepex[0])\r |
| 367 | else:\r |
| 368 | ScheduleList[FfsID] = NewFfs\r |
| 369 | else:\r |
| 370 | self.UnDispatchedFfsDict[FfsID].Depex = DepexString\r |
| 371 | \r |
| 372 | for FfsID in ScheduleList:\r |
| 373 | NewFfs = ScheduleList.pop(FfsID)\r |
| 374 | FfsName = 'UnKnown'\r |
| 375 | self.OrderedFfsDict[FfsID] = NewFfs\r |
| 376 | self.LoadProtocol(Db, FfsID)\r |
| 377 | \r |
| 378 | SqlCommand = """select Value2 from Inf\r |
| 379 | where BelongsToFile = (select BelongsToFile from Inf where Value1 = 'FILE_GUID' and lower(Value2) = lower('%s') and Model = %s)\r |
| 380 | and Model = %s and Value1='BASE_NAME'""" % (FfsID, 5001, 5001)\r |
| 381 | RecordSet = Db.TblReport.Exec(SqlCommand)\r |
| 382 | if RecordSet != []:\r |
| 383 | FfsName = RecordSet[0][0]\r |
| 384 | \r |
| 385 | if IsInstalled:\r |
| 386 | self.DisPatchDxe(Db)\r |
| 387 | \r |
| 388 | def DisPatchPei(self, Db):\r |
| 389 | IsInstalled = False\r |
| 390 | for FfsID in self.UnDispatchedFfsDict:\r |
| 391 | CouldBeLoaded = True\r |
| 392 | DepexString = ''\r |
| 393 | FileDepex = None\r |
| 394 | Ffs = self.UnDispatchedFfsDict[FfsID]\r |
| 395 | if Ffs.Type == 0x06 or Ffs.Type == 0x08:\r |
| 396 | # Get Depex\r |
| 397 | for Section in Ffs.Sections.values():\r |
| 398 | if Section.Type == 0x1B:\r |
| 399 | CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(Section._SubImages[4], 'Ppi')\r |
| 400 | break\r |
| 401 | \r |
| 402 | if Section.Type == 0x01:\r |
| 403 | CompressSections = Section._SubImages[4]\r |
| 404 | for CompressSection in CompressSections.Sections:\r |
| 405 | if CompressSection.Type == 0x1B:\r |
| 406 | CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(CompressSection._SubImages[4], 'Ppi')\r |
| 407 | break\r |
| 408 | if CompressSection.Type == 0x02:\r |
| 409 | NewSections = CompressSection._SubImages[4]\r |
| 410 | for NewSection in NewSections.Sections:\r |
| 411 | if NewSection.Type == 0x1B:\r |
| 412 | CouldBeLoaded, DepexString, FileDepex = self.ParseDepex(NewSection._SubImages[4], 'Ppi')\r |
| 413 | break\r |
| 414 | \r |
| 415 | # Append New Ffs\r |
| 416 | if CouldBeLoaded:\r |
| 417 | IsInstalled = True\r |
| 418 | NewFfs = self.UnDispatchedFfsDict.pop(FfsID)\r |
| 419 | NewFfs.Depex = DepexString\r |
| 420 | self.OrderedFfsDict[FfsID] = NewFfs\r |
| 421 | self.LoadPpi(Db, FfsID)\r |
| 422 | else:\r |
| 423 | self.UnDispatchedFfsDict[FfsID].Depex = DepexString\r |
| 424 | \r |
| 425 | if IsInstalled:\r |
| 426 | self.DisPatchPei(Db)\r |
| 427 | \r |
| 428 | \r |
| 429 | def __str__(self):\r |
| 430 | global gIndention\r |
| 431 | gIndention += 4\r |
| 432 | FvInfo = '\n' + ' ' * gIndention\r |
| 433 | FvInfo += "[FV:%s] file_system=%s size=%x checksum=%s\n" % (self.Name, self.FileSystemGuid, self.Size, self.Checksum)\r |
| 434 | FfsInfo = "\n".join([str(self.FfsDict[FfsId]) for FfsId in self.FfsDict])\r |
| 435 | gIndention -= 4\r |
| 436 | return FvInfo + FfsInfo\r |
| 437 | \r |
| 438 | def _Unpack(self):\r |
| 439 | Size = self._LENGTH_.unpack_from(self._BUF_, self._OFF_)[0]\r |
| 440 | self.empty()\r |
| 441 | self.extend(self._BUF_[self._OFF_:self._OFF_+Size])\r |
| 442 | \r |
| 443 | # traverse the FFS\r |
| 444 | EndOfFv = Size\r |
| 445 | FfsStartAddress = self.HeaderSize\r |
| 446 | LastFfsObj = None\r |
| 447 | while FfsStartAddress < EndOfFv:\r |
| 448 | FfsObj = Ffs()\r |
| 449 | FfsObj.frombuffer(self, FfsStartAddress)\r |
| 450 | FfsId = repr(FfsObj)\r |
| 451 | if ((self.Attributes & 0x00000800) != 0 and len(FfsObj) == 0xFFFFFF) \\r |
| 452 | or ((self.Attributes & 0x00000800) == 0 and len(FfsObj) == 0):\r |
| 453 | if LastFfsObj is not None:\r |
| 454 | LastFfsObj.FreeSpace = EndOfFv - LastFfsObj._OFF_ - len(LastFfsObj)\r |
| 455 | else:\r |
| 456 | if FfsId in self.FfsDict:\r |
| 457 | EdkLogger.error("FV", 0, "Duplicate GUID in FFS",\r |
| 458 | ExtraData="\t%s @ %s\n\t%s @ %s" \\r |
| 459 | % (FfsObj.Guid, FfsObj.Offset,\r |
| 460 | self.FfsDict[FfsId].Guid, self.FfsDict[FfsId].Offset))\r |
| 461 | self.FfsDict[FfsId] = FfsObj\r |
| 462 | if LastFfsObj is not None:\r |
| 463 | LastFfsObj.FreeSpace = FfsStartAddress - LastFfsObj._OFF_ - len(LastFfsObj)\r |
| 464 | \r |
| 465 | FfsStartAddress += len(FfsObj)\r |
| 466 | #\r |
| 467 | # align to next 8-byte aligned address: A = (A + 8 - 1) & (~(8 - 1))\r |
| 468 | # The next FFS must be at the latest next 8-byte aligned address\r |
| 469 | #\r |
| 470 | FfsStartAddress = (FfsStartAddress + 7) & (~7)\r |
| 471 | LastFfsObj = FfsObj\r |
| 472 | \r |
| 473 | def _GetAttributes(self):\r |
| 474 | return self.GetField(self._ATTR_, 0)[0]\r |
| 475 | \r |
| 476 | def _GetSize(self):\r |
| 477 | return self.GetField(self._LENGTH_, 0)[0]\r |
| 478 | \r |
| 479 | def _GetChecksum(self):\r |
| 480 | return self.GetField(self._CHECKSUM_, 0)[0]\r |
| 481 | \r |
| 482 | def _GetHeaderLength(self):\r |
| 483 | return self.GetField(self._HLEN_, 0)[0]\r |
| 484 | \r |
| 485 | def _GetFileSystemGuid(self):\r |
| 486 | return gGuidStringFormat % self.GetField(self._GUID_, 0)\r |
| 487 | \r |
| 488 | Attributes = property(_GetAttributes)\r |
| 489 | Size = property(_GetSize)\r |
| 490 | Checksum = property(_GetChecksum)\r |
| 491 | HeaderSize = property(_GetHeaderLength)\r |
| 492 | FileSystemGuid = property(_GetFileSystemGuid)\r |
| 493 | \r |
| 494 | ## CompressedImage() class\r |
| 495 | #\r |
| 496 | # A class for Compressed Image\r |
| 497 | #\r |
| 498 | class CompressedImage(Image):\r |
| 499 | # UncompressedLength = 4-byte\r |
| 500 | # CompressionType = 1-byte\r |
| 501 | _HEADER_ = struct.Struct("1I 1B")\r |
| 502 | _HEADER_SIZE_ = _HEADER_.size\r |
| 503 | \r |
| 504 | _ORIG_SIZE_ = struct.Struct("1I")\r |
| 505 | _CMPRS_TYPE_ = struct.Struct("4x 1B")\r |
| 506 | \r |
| 507 | def __init__(m, CompressedData=None, CompressionType=None, UncompressedLength=None):\r |
| 508 | Image.__init__(m)\r |
| 509 | if UncompressedLength is not None:\r |
| 510 | m.UncompressedLength = UncompressedLength\r |
| 511 | if CompressionType is not None:\r |
| 512 | m.CompressionType = CompressionType\r |
| 513 | if CompressedData is not None:\r |
| 514 | m.Data = CompressedData\r |
| 515 | \r |
| 516 | def __str__(m):\r |
| 517 | global gIndention\r |
| 518 | S = "algorithm=%s uncompressed=%x" % (m.CompressionType, m.UncompressedLength)\r |
| 519 | for Sec in m.Sections:\r |
| 520 | S += '\n' + str(Sec)\r |
| 521 | \r |
| 522 | return S\r |
| 523 | \r |
| 524 | def _SetOriginalSize(m, Size):\r |
| 525 | m.SetField(m._ORIG_SIZE_, 0, Size)\r |
| 526 | \r |
| 527 | def _GetOriginalSize(m):\r |
| 528 | return m.GetField(m._ORIG_SIZE_)[0]\r |
| 529 | \r |
| 530 | def _SetCompressionType(m, Type):\r |
| 531 | m.SetField(m._CMPRS_TYPE_, 0, Type)\r |
| 532 | \r |
| 533 | def _GetCompressionType(m):\r |
| 534 | return m.GetField(m._CMPRS_TYPE_)[0]\r |
| 535 | \r |
| 536 | def _GetSections(m):\r |
| 537 | try:\r |
| 538 | import EfiCompressor\r |
| 539 | TmpData = EfiCompressor.FrameworkDecompress(\r |
| 540 | m[m._HEADER_SIZE_:],\r |
| 541 | len(m) - m._HEADER_SIZE_\r |
| 542 | )\r |
| 543 | DecData = array('B')\r |
| 544 | DecData.fromstring(TmpData)\r |
| 545 | except:\r |
| 546 | import EfiCompressor\r |
| 547 | TmpData = EfiCompressor.UefiDecompress(\r |
| 548 | m[m._HEADER_SIZE_:],\r |
| 549 | len(m) - m._HEADER_SIZE_\r |
| 550 | )\r |
| 551 | DecData = array('B')\r |
| 552 | DecData.fromstring(TmpData)\r |
| 553 | \r |
| 554 | SectionList = []\r |
| 555 | Offset = 0\r |
| 556 | while Offset < len(DecData):\r |
| 557 | Sec = Section()\r |
| 558 | try:\r |
| 559 | Sec.frombuffer(DecData, Offset)\r |
| 560 | Offset += Sec.Size\r |
| 561 | # the section is aligned to 4-byte boundary\r |
| 562 | except:\r |
| 563 | break\r |
| 564 | SectionList.append(Sec)\r |
| 565 | return SectionList\r |
| 566 | \r |
| 567 | UncompressedLength = property(_GetOriginalSize, _SetOriginalSize)\r |
| 568 | CompressionType = property(_GetCompressionType, _SetCompressionType)\r |
| 569 | Sections = property(_GetSections)\r |
| 570 | \r |
| 571 | ## GuidDefinedImage() class\r |
| 572 | #\r |
| 573 | # A class for GUID Defined Image\r |
| 574 | #\r |
| 575 | class GuidDefinedImage(Image):\r |
| 576 | _HEADER_ = struct.Struct("1I2H8B 1H 1H")\r |
| 577 | _HEADER_SIZE_ = _HEADER_.size\r |
| 578 | \r |
| 579 | _GUID_ = struct.Struct("1I2H8B")\r |
| 580 | _DATA_OFFSET_ = struct.Struct("16x 1H")\r |
| 581 | _ATTR_ = struct.Struct("18x 1H")\r |
| 582 | \r |
| 583 | CRC32_GUID = "FC1BCDB0-7D31-49AA-936A-A4600D9DD083"\r |
| 584 | TIANO_COMPRESS_GUID = 'A31280AD-481E-41B6-95E8-127F4C984779'\r |
| 585 | LZMA_COMPRESS_GUID = 'EE4E5898-3914-4259-9D6E-DC7BD79403CF'\r |
| 586 | \r |
| 587 | def __init__(m, SectionDefinitionGuid=None, DataOffset=None, Attributes=None, Data=None):\r |
| 588 | Image.__init__(m)\r |
| 589 | if SectionDefinitionGuid is not None:\r |
| 590 | m.SectionDefinitionGuid = SectionDefinitionGuid\r |
| 591 | if DataOffset is not None:\r |
| 592 | m.DataOffset = DataOffset\r |
| 593 | if Attributes is not None:\r |
| 594 | m.Attributes = Attributes\r |
| 595 | if Data is not None:\r |
| 596 | m.Data = Data\r |
| 597 | \r |
| 598 | def __str__(m):\r |
| 599 | S = "guid=%s" % (gGuidStringFormat % m.SectionDefinitionGuid)\r |
| 600 | for Sec in m.Sections:\r |
| 601 | S += "\n" + str(Sec)\r |
| 602 | return S\r |
| 603 | \r |
| 604 | def _Unpack(m):\r |
| 605 | # keep header in this Image object\r |
| 606 | m.empty()\r |
| 607 | m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])\r |
| 608 | return len(m)\r |
| 609 | \r |
| 610 | def _SetAttribute(m, Attribute):\r |
| 611 | m.SetField(m._ATTR_, 0, Attribute)\r |
| 612 | \r |
| 613 | def _GetAttribute(m):\r |
| 614 | return m.GetField(m._ATTR_)[0]\r |
| 615 | \r |
| 616 | def _SetGuid(m, Guid):\r |
| 617 | m.SetField(m._GUID_, 0, Guid)\r |
| 618 | \r |
| 619 | def _GetGuid(m):\r |
| 620 | return m.GetField(m._GUID_)\r |
| 621 | \r |
| 622 | def _SetDataOffset(m, Offset):\r |
| 623 | m.SetField(m._DATA_OFFSET_, 0, Offset)\r |
| 624 | \r |
| 625 | def _GetDataOffset(m):\r |
| 626 | return m.GetField(m._DATA_OFFSET_)[0]\r |
| 627 | \r |
| 628 | def _GetSections(m):\r |
| 629 | SectionList = []\r |
| 630 | Guid = gGuidStringFormat % m.SectionDefinitionGuid\r |
| 631 | if Guid == m.CRC32_GUID:\r |
| 632 | # skip the CRC32 value, we don't do CRC32 verification here\r |
| 633 | Offset = m.DataOffset - 4\r |
| 634 | while Offset < len(m):\r |
| 635 | Sec = Section()\r |
| 636 | try:\r |
| 637 | Sec.frombuffer(m, Offset)\r |
| 638 | Offset += Sec.Size\r |
| 639 | # the section is aligned to 4-byte boundary\r |
| 640 | Offset = (Offset + 3) & (~3)\r |
| 641 | except:\r |
| 642 | break\r |
| 643 | SectionList.append(Sec)\r |
| 644 | elif Guid == m.TIANO_COMPRESS_GUID:\r |
| 645 | try:\r |
| 646 | import EfiCompressor\r |
| 647 | # skip the header\r |
| 648 | Offset = m.DataOffset - 4\r |
| 649 | TmpData = EfiCompressor.FrameworkDecompress(m[Offset:], len(m)-Offset)\r |
| 650 | DecData = array('B')\r |
| 651 | DecData.fromstring(TmpData)\r |
| 652 | Offset = 0\r |
| 653 | while Offset < len(DecData):\r |
| 654 | Sec = Section()\r |
| 655 | try:\r |
| 656 | Sec.frombuffer(DecData, Offset)\r |
| 657 | Offset += Sec.Size\r |
| 658 | # the section is aligned to 4-byte boundary\r |
| 659 | Offset = (Offset + 3) & (~3)\r |
| 660 | except:\r |
| 661 | break\r |
| 662 | SectionList.append(Sec)\r |
| 663 | except:\r |
| 664 | pass\r |
| 665 | elif Guid == m.LZMA_COMPRESS_GUID:\r |
| 666 | try:\r |
| 667 | import LzmaCompressor\r |
| 668 | # skip the header\r |
| 669 | Offset = m.DataOffset - 4\r |
| 670 | TmpData = LzmaCompressor.LzmaDecompress(m[Offset:], len(m)-Offset)\r |
| 671 | DecData = array('B')\r |
| 672 | DecData.fromstring(TmpData)\r |
| 673 | Offset = 0\r |
| 674 | while Offset < len(DecData):\r |
| 675 | Sec = Section()\r |
| 676 | try:\r |
| 677 | Sec.frombuffer(DecData, Offset)\r |
| 678 | Offset += Sec.Size\r |
| 679 | # the section is aligned to 4-byte boundary\r |
| 680 | Offset = (Offset + 3) & (~3)\r |
| 681 | except:\r |
| 682 | break\r |
| 683 | SectionList.append(Sec)\r |
| 684 | except:\r |
| 685 | pass\r |
| 686 | \r |
| 687 | return SectionList\r |
| 688 | \r |
| 689 | Attributes = property(_GetAttribute, _SetAttribute)\r |
| 690 | SectionDefinitionGuid = property(_GetGuid, _SetGuid)\r |
| 691 | DataOffset = property(_GetDataOffset, _SetDataOffset)\r |
| 692 | Sections = property(_GetSections)\r |
| 693 | \r |
| 694 | ## Depex() class\r |
| 695 | #\r |
| 696 | # A class for Depex\r |
| 697 | #\r |
| 698 | class Depex(Image):\r |
| 699 | _HEADER_ = struct.Struct("")\r |
| 700 | _HEADER_SIZE_ = 0\r |
| 701 | \r |
| 702 | _GUID_ = struct.Struct("1I2H8B")\r |
| 703 | _OPCODE_ = struct.Struct("1B")\r |
| 704 | \r |
| 705 | _OPCODE_STRING_ = {\r |
| 706 | 0x00 : "BEFORE",\r |
| 707 | 0x01 : "AFTER",\r |
| 708 | 0x02 : "PUSH",\r |
| 709 | 0x03 : "AND",\r |
| 710 | 0x04 : "OR",\r |
| 711 | 0x05 : "NOT",\r |
| 712 | 0x06 : "TRUE",\r |
| 713 | 0x07 : "FALSE",\r |
| 714 | 0x08 : "END",\r |
| 715 | 0x09 : "SOR"\r |
| 716 | }\r |
| 717 | \r |
| 718 | _NEXT_ = {\r |
| 719 | -1 : _OPCODE_, # first one in depex must be an opcdoe\r |
| 720 | 0x00 : _GUID_, #"BEFORE",\r |
| 721 | 0x01 : _GUID_, #"AFTER",\r |
| 722 | 0x02 : _GUID_, #"PUSH",\r |
| 723 | 0x03 : _OPCODE_, #"AND",\r |
| 724 | 0x04 : _OPCODE_, #"OR",\r |
| 725 | 0x05 : _OPCODE_, #"NOT",\r |
| 726 | 0x06 : _OPCODE_, #"TRUE",\r |
| 727 | 0x07 : _OPCODE_, #"FALSE",\r |
| 728 | 0x08 : None, #"END",\r |
| 729 | 0x09 : _OPCODE_, #"SOR"\r |
| 730 | }\r |
| 731 | \r |
| 732 | def __init__(m):\r |
| 733 | Image.__init__(m)\r |
| 734 | m._ExprList = []\r |
| 735 | \r |
| 736 | def __str__(m):\r |
| 737 | global gIndention\r |
| 738 | gIndention += 4\r |
| 739 | Indention = ' ' * gIndention\r |
| 740 | S = '\n'\r |
| 741 | for T in m.Expression:\r |
| 742 | if T in m._OPCODE_STRING_:\r |
| 743 | S += Indention + m._OPCODE_STRING_[T]\r |
| 744 | if T not in [0x00, 0x01, 0x02]:\r |
| 745 | S += '\n'\r |
| 746 | else:\r |
| 747 | S += ' ' + gGuidStringFormat % T + '\n'\r |
| 748 | gIndention -= 4\r |
| 749 | return S\r |
| 750 | \r |
| 751 | def _Unpack(m):\r |
| 752 | # keep header in this Image object\r |
| 753 | m.empty()\r |
| 754 | m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])\r |
| 755 | return len(m)\r |
| 756 | \r |
| 757 | def _GetExpression(m):\r |
| 758 | if m._ExprList == []:\r |
| 759 | Offset = 0\r |
| 760 | CurrentData = m._OPCODE_\r |
| 761 | while Offset < len(m):\r |
| 762 | Token = CurrentData.unpack_from(m, Offset)\r |
| 763 | Offset += CurrentData.size\r |
| 764 | if len(Token) == 1:\r |
| 765 | Token = Token[0]\r |
| 766 | if Token in m._NEXT_:\r |
| 767 | CurrentData = m._NEXT_[Token]\r |
| 768 | else:\r |
| 769 | CurrentData = m._GUID_\r |
| 770 | else:\r |
| 771 | CurrentData = m._OPCODE_\r |
| 772 | m._ExprList.append(Token)\r |
| 773 | if CurrentData is None:\r |
| 774 | break\r |
| 775 | return m._ExprList\r |
| 776 | \r |
| 777 | Expression = property(_GetExpression)\r |
| 778 | \r |
| 779 | ## Ui() class\r |
| 780 | #\r |
| 781 | # A class for Ui\r |
| 782 | #\r |
| 783 | class Ui(Image):\r |
| 784 | _HEADER_ = struct.Struct("")\r |
| 785 | _HEADER_SIZE_ = 0\r |
| 786 | \r |
| 787 | def __init__(m):\r |
| 788 | Image.__init__(m)\r |
| 789 | \r |
| 790 | def __str__(m):\r |
| 791 | return m.String\r |
| 792 | \r |
| 793 | def _Unpack(m):\r |
| 794 | # keep header in this Image object\r |
| 795 | m.empty()\r |
| 796 | m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._LEN_])\r |
| 797 | return len(m)\r |
| 798 | \r |
| 799 | def _GetUiString(m):\r |
| 800 | return codecs.utf_16_decode(m[0:-2].tostring())[0]\r |
| 801 | \r |
| 802 | String = property(_GetUiString)\r |
| 803 | \r |
| 804 | ## Section() class\r |
| 805 | #\r |
| 806 | # A class for Section\r |
| 807 | #\r |
| 808 | class Section(Image):\r |
| 809 | _TypeName = {\r |
| 810 | 0x00 : "<unknown>",\r |
| 811 | 0x01 : "COMPRESSION",\r |
| 812 | 0x02 : "GUID_DEFINED",\r |
| 813 | 0x10 : "PE32",\r |
| 814 | 0x11 : "PIC",\r |
| 815 | 0x12 : "TE",\r |
| 816 | 0x13 : "DXE_DEPEX",\r |
| 817 | 0x14 : "VERSION",\r |
| 818 | 0x15 : "USER_INTERFACE",\r |
| 819 | 0x16 : "COMPATIBILITY16",\r |
| 820 | 0x17 : "FIRMWARE_VOLUME_IMAGE",\r |
| 821 | 0x18 : "FREEFORM_SUBTYPE_GUID",\r |
| 822 | 0x19 : "RAW",\r |
| 823 | 0x1B : "PEI_DEPEX"\r |
| 824 | }\r |
| 825 | \r |
| 826 | _SectionSubImages = {\r |
| 827 | 0x01 : CompressedImage,\r |
| 828 | 0x02 : GuidDefinedImage,\r |
| 829 | 0x17 : FirmwareVolume,\r |
| 830 | 0x13 : Depex,\r |
| 831 | 0x1B : Depex,\r |
| 832 | 0x15 : Ui\r |
| 833 | }\r |
| 834 | \r |
| 835 | # Size = 3-byte\r |
| 836 | # Type = 1-byte\r |
| 837 | _HEADER_ = struct.Struct("3B 1B")\r |
| 838 | _HEADER_SIZE_ = _HEADER_.size\r |
| 839 | \r |
| 840 | # SubTypeGuid\r |
| 841 | # _FREE_FORM_SUBTYPE_GUID_HEADER_ = struct.Struct("1I2H8B")\r |
| 842 | \r |
| 843 | _SIZE_ = struct.Struct("3B")\r |
| 844 | _TYPE_ = struct.Struct("3x 1B")\r |
| 845 | \r |
| 846 | def __init__(m, Type=None, Size=None):\r |
| 847 | Image.__init__(m)\r |
| 848 | m._Alignment = 1\r |
| 849 | if Type is not None:\r |
| 850 | m.Type = Type\r |
| 851 | if Size is not None:\r |
| 852 | m.Size = Size\r |
| 853 | \r |
| 854 | def __str__(m):\r |
| 855 | global gIndention\r |
| 856 | gIndention += 4\r |
| 857 | SectionInfo = ' ' * gIndention\r |
| 858 | if m.Type in m._TypeName:\r |
| 859 | SectionInfo += "[SECTION:%s] offset=%x size=%x" % (m._TypeName[m.Type], m._OFF_, m.Size)\r |
| 860 | else:\r |
| 861 | SectionInfo += "[SECTION:%x<unknown>] offset=%x size=%x " % (m.Type, m._OFF_, m.Size)\r |
| 862 | for Offset in m._SubImages:\r |
| 863 | SectionInfo += ", " + str(m._SubImages[Offset])\r |
| 864 | gIndention -= 4\r |
| 865 | return SectionInfo\r |
| 866 | \r |
| 867 | def _Unpack(m):\r |
| 868 | m.empty()\r |
| 869 | Type, = m._TYPE_.unpack_from(m._BUF_, m._OFF_)\r |
| 870 | Size1, Size2, Size3 = m._SIZE_.unpack_from(m._BUF_, m._OFF_)\r |
| 871 | Size = Size1 + (Size2 << 8) + (Size3 << 16)\r |
| 872 | \r |
| 873 | if Type not in m._SectionSubImages:\r |
| 874 | # no need to extract sub-image, keep all in this Image object\r |
| 875 | m.extend(m._BUF_[m._OFF_ : m._OFF_ + Size])\r |
| 876 | else:\r |
| 877 | # keep header in this Image object\r |
| 878 | m.extend(m._BUF_[m._OFF_ : m._OFF_ + m._HEADER_SIZE_])\r |
| 879 | #\r |
| 880 | # use new Image object to represent payload, which may be another kind\r |
| 881 | # of image such as PE32\r |
| 882 | #\r |
| 883 | PayloadOffset = m._HEADER_SIZE_\r |
| 884 | PayloadLen = m.Size - m._HEADER_SIZE_\r |
| 885 | Payload = m._SectionSubImages[m.Type]()\r |
| 886 | Payload.frombuffer(m._BUF_, m._OFF_ + m._HEADER_SIZE_, PayloadLen)\r |
| 887 | m._SubImages[PayloadOffset] = Payload\r |
| 888 | \r |
| 889 | return Size\r |
| 890 | \r |
| 891 | def _SetSize(m, Size):\r |
| 892 | Size1 = Size & 0xFF\r |
| 893 | Size2 = (Size & 0xFF00) >> 8\r |
| 894 | Size3 = (Size & 0xFF0000) >> 16\r |
| 895 | m.SetField(m._SIZE_, 0, Size1, Size2, Size3)\r |
| 896 | \r |
| 897 | def _GetSize(m):\r |
| 898 | Size1, Size2, Size3 = m.GetField(m._SIZE_)\r |
| 899 | return Size1 + (Size2 << 8) + (Size3 << 16)\r |
| 900 | \r |
| 901 | def _SetType(m, Type):\r |
| 902 | m.SetField(m._TYPE_, 0, Type)\r |
| 903 | \r |
| 904 | def _GetType(m):\r |
| 905 | return m.GetField(m._TYPE_)[0]\r |
| 906 | \r |
| 907 | def _GetAlignment(m):\r |
| 908 | return m._Alignment\r |
| 909 | \r |
| 910 | def _SetAlignment(m, Alignment):\r |
| 911 | m._Alignment = Alignment\r |
| 912 | AlignmentMask = Alignment - 1\r |
| 913 | # section alignment is actually for payload, so we need to add header size\r |
| 914 | PayloadOffset = m._OFF_ + m._HEADER_SIZE_\r |
| 915 | if (PayloadOffset & (~AlignmentMask)) == 0:\r |
| 916 | return\r |
| 917 | NewOffset = (PayloadOffset + AlignmentMask) & (~AlignmentMask)\r |
| 918 | while (NewOffset - PayloadOffset) < m._HEADER_SIZE_:\r |
| 919 | NewOffset += m._Alignment\r |
| 920 | \r |
| 921 | def tofile(m, f):\r |
| 922 | m.Size = len(m)\r |
| 923 | Image.tofile(m, f)\r |
| 924 | for Offset in m._SubImages:\r |
| 925 | m._SubImages[Offset].tofile(f)\r |
| 926 | \r |
| 927 | Type = property(_GetType, _SetType)\r |
| 928 | Size = property(_GetSize, _SetSize)\r |
| 929 | Alignment = property(_GetAlignment, _SetAlignment)\r |
| 930 | # SubTypeGuid = property(_GetGuid, _SetGuid)\r |
| 931 | \r |
| 932 | ## PadSection() class\r |
| 933 | #\r |
| 934 | # A class for Pad Section\r |
| 935 | #\r |
| 936 | class PadSection(Section):\r |
| 937 | def __init__(m, Size):\r |
| 938 | Section.__init__(m)\r |
| 939 | m.Type = 0x19\r |
| 940 | m.Size = Size\r |
| 941 | m.Data = [0] * (Size - m._HEADER_SIZE_)\r |
| 942 | \r |
| 943 | ## Ffs() class\r |
| 944 | #\r |
| 945 | # A class for Ffs Section\r |
| 946 | #\r |
| 947 | class Ffs(Image):\r |
| 948 | _FfsFormat = "24B%(payload_size)sB"\r |
| 949 | # skip IntegrityCheck\r |
| 950 | _HEADER_ = struct.Struct("1I2H8B 2x 1B 1B 3B 1B")\r |
| 951 | _HEADER_SIZE_ = _HEADER_.size\r |
| 952 | \r |
| 953 | _NAME_ = struct.Struct("1I2H8B")\r |
| 954 | _INT_CHECK_ = struct.Struct("16x 1H")\r |
| 955 | _TYPE_ = struct.Struct("18x 1B")\r |
| 956 | _ATTR_ = struct.Struct("19x 1B")\r |
| 957 | _SIZE_ = struct.Struct("20x 3B")\r |
| 958 | _STATE_ = struct.Struct("23x 1B")\r |
| 959 | \r |
| 960 | VTF_GUID = "1BA0062E-C779-4582-8566-336AE8F78F09"\r |
| 961 | \r |
| 962 | FFS_ATTRIB_FIXED = 0x04\r |
| 963 | FFS_ATTRIB_DATA_ALIGNMENT = 0x38\r |
| 964 | FFS_ATTRIB_CHECKSUM = 0x40\r |
| 965 | \r |
| 966 | _TypeName = {\r |
| 967 | 0x00 : "<unknown>",\r |
| 968 | 0x01 : "RAW",\r |
| 969 | 0x02 : "FREEFORM",\r |
| 970 | 0x03 : "SECURITY_CORE",\r |
| 971 | 0x04 : "PEI_CORE",\r |
| 972 | 0x05 : "DXE_CORE",\r |
| 973 | 0x06 : "PEIM",\r |
| 974 | 0x07 : "DRIVER",\r |
| 975 | 0x08 : "COMBINED_PEIM_DRIVER",\r |
| 976 | 0x09 : "APPLICATION",\r |
| 977 | 0x0A : "SMM",\r |
| 978 | 0x0B : "FIRMWARE_VOLUME_IMAGE",\r |
| 979 | 0x0C : "COMBINED_SMM_DXE",\r |
| 980 | 0x0D : "SMM_CORE",\r |
| 981 | 0x0E : "MM_STANDALONE",\r |
| 982 | 0x0F : "MM_CORE_STANDALONE",\r |
| 983 | 0xc0 : "OEM_MIN",\r |
| 984 | 0xdf : "OEM_MAX",\r |
| 985 | 0xe0 : "DEBUG_MIN",\r |
| 986 | 0xef : "DEBUG_MAX",\r |
| 987 | 0xf0 : "FFS_MIN",\r |
| 988 | 0xff : "FFS_MAX",\r |
| 989 | 0xf0 : "FFS_PAD",\r |
| 990 | }\r |
| 991 | \r |
| 992 | def __init__(self):\r |
| 993 | Image.__init__(self)\r |
| 994 | self.FreeSpace = 0\r |
| 995 | \r |
| 996 | self.Sections = sdict()\r |
| 997 | self.Depex = ''\r |
| 998 | \r |
| 999 | self.__ID__ = None\r |
| 1000 | \r |
| 1001 | def __str__(self):\r |
| 1002 | global gIndention\r |
| 1003 | gIndention += 4\r |
| 1004 | Indention = ' ' * gIndention\r |
| 1005 | FfsInfo = Indention\r |
| 1006 | FfsInfo += "[FFS:%s] offset=%x size=%x guid=%s free_space=%x alignment=%s\n" % \\r |
| 1007 | (Ffs._TypeName[self.Type], self._OFF_, self.Size, self.Guid, self.FreeSpace, self.Alignment)\r |
| 1008 | SectionInfo = '\n'.join([str(self.Sections[Offset]) for Offset in self.Sections])\r |
| 1009 | gIndention -= 4\r |
| 1010 | return FfsInfo + SectionInfo + "\n"\r |
| 1011 | \r |
| 1012 | def __len__(self):\r |
| 1013 | return self.Size\r |
| 1014 | \r |
| 1015 | def __repr__(self):\r |
| 1016 | return self.__ID__\r |
| 1017 | \r |
| 1018 | def _Unpack(self):\r |
| 1019 | Size1, Size2, Size3 = self._SIZE_.unpack_from(self._BUF_, self._OFF_)\r |
| 1020 | Size = Size1 + (Size2 << 8) + (Size3 << 16)\r |
| 1021 | self.empty()\r |
| 1022 | self.extend(self._BUF_[self._OFF_ : self._OFF_ + Size])\r |
| 1023 | \r |
| 1024 | # Pad FFS may use the same GUID. We need to avoid it.\r |
| 1025 | if self.Type == 0xf0:\r |
| 1026 | self.__ID__ = str(uuid.uuid1()).upper()\r |
| 1027 | else:\r |
| 1028 | self.__ID__ = self.Guid\r |
| 1029 | \r |
| 1030 | # Traverse the SECTION. RAW and PAD do not have sections\r |
| 1031 | if self.Type not in [0xf0, 0x01] and Size > 0 and Size < 0xFFFFFF:\r |
| 1032 | EndOfFfs = Size\r |
| 1033 | SectionStartAddress = self._HEADER_SIZE_\r |
| 1034 | while SectionStartAddress < EndOfFfs:\r |
| 1035 | SectionObj = Section()\r |
| 1036 | SectionObj.frombuffer(self, SectionStartAddress)\r |
| 1037 | #f = open(repr(SectionObj), 'wb')\r |
| 1038 | #SectionObj.Size = 0\r |
| 1039 | #SectionObj.tofile(f)\r |
| 1040 | #f.close()\r |
| 1041 | self.Sections[SectionStartAddress] = SectionObj\r |
| 1042 | SectionStartAddress += len(SectionObj)\r |
| 1043 | SectionStartAddress = (SectionStartAddress + 3) & (~3)\r |
| 1044 | \r |
| 1045 | def Pack(self):\r |
| 1046 | pass\r |
| 1047 | \r |
| 1048 | def SetFreeSpace(self, Size):\r |
| 1049 | self.FreeSpace = Size\r |
| 1050 | \r |
| 1051 | def _GetGuid(self):\r |
| 1052 | return gGuidStringFormat % self.Name\r |
| 1053 | \r |
| 1054 | def _SetName(self, Value):\r |
| 1055 | # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11\r |
| 1056 | self.SetField(self._NAME_, 0, Value)\r |
| 1057 | \r |
| 1058 | def _GetName(self):\r |
| 1059 | # Guid1, Guid2, Guid3, Guid4, Guid5, Guid6, Guid7, Guid8, Guid9, Guid10, Guid11\r |
| 1060 | return self.GetField(self._NAME_)\r |
| 1061 | \r |
| 1062 | def _SetSize(m, Size):\r |
| 1063 | Size1 = Size & 0xFF\r |
| 1064 | Size2 = (Size & 0xFF00) >> 8\r |
| 1065 | Size3 = (Size & 0xFF0000) >> 16\r |
| 1066 | m.SetField(m._SIZE_, 0, Size1, Size2, Size3)\r |
| 1067 | \r |
| 1068 | def _GetSize(m):\r |
| 1069 | Size1, Size2, Size3 = m.GetField(m._SIZE_)\r |
| 1070 | return Size1 + (Size2 << 8) + (Size3 << 16)\r |
| 1071 | \r |
| 1072 | def _SetType(m, Type):\r |
| 1073 | m.SetField(m._TYPE_, 0, Type)\r |
| 1074 | \r |
| 1075 | def _GetType(m):\r |
| 1076 | return m.GetField(m._TYPE_)[0]\r |
| 1077 | \r |
| 1078 | def _SetAttributes(self, Value):\r |
| 1079 | self.SetField(m._ATTR_, 0, Value)\r |
| 1080 | \r |
| 1081 | def _GetAttributes(self):\r |
| 1082 | return self.GetField(self._ATTR_)[0]\r |
| 1083 | \r |
| 1084 | def _GetFixed(self):\r |
| 1085 | if (self.Attributes & self.FFS_ATTRIB_FIXED) != 0:\r |
| 1086 | return True\r |
| 1087 | return False\r |
| 1088 | \r |
| 1089 | def _GetCheckSum(self):\r |
| 1090 | if (self.Attributes & self.FFS_ATTRIB_CHECKSUM) != 0:\r |
| 1091 | return True\r |
| 1092 | return False\r |
| 1093 | \r |
| 1094 | def _GetAlignment(self):\r |
| 1095 | return (self.Attributes & self.FFS_ATTRIB_DATA_ALIGNMENT) >> 3\r |
| 1096 | \r |
| 1097 | def _SetState(self, Value):\r |
| 1098 | self.SetField(m._STATE_, 0, Value)\r |
| 1099 | \r |
| 1100 | def _GetState(self):\r |
| 1101 | return self.GetField(m._STATE_)[0]\r |
| 1102 | \r |
| 1103 | Name = property(_GetName, _SetName)\r |
| 1104 | Guid = property(_GetGuid)\r |
| 1105 | Type = property(_GetType, _SetType)\r |
| 1106 | Size = property(_GetSize, _SetSize)\r |
| 1107 | Attributes = property(_GetAttributes, _SetAttributes)\r |
| 1108 | Fixed = property(_GetFixed)\r |
| 1109 | Checksum = property(_GetCheckSum)\r |
| 1110 | Alignment = property(_GetAlignment)\r |
| 1111 | State = property(_GetState, _SetState)\r |
| 1112 | \r |
| 1113 | ## PeImage() class\r |
| 1114 | #\r |
| 1115 | # A class for PE Image\r |
| 1116 | #\r |
| 1117 | class PeImage:\r |
| 1118 | #\r |
| 1119 | # just extract e_lfanew\r |
| 1120 | #\r |
| 1121 | _DosHeaderFormat = "60x 1I"\r |
| 1122 | #\r |
| 1123 | # Machine\r |
| 1124 | # NumberOfSections\r |
| 1125 | # SizeOfOptionalHeader\r |
| 1126 | #\r |
| 1127 | _FileHeaderFormat = "4x 1H 1H 4x 4x 4x 1H 2x"\r |
| 1128 | #\r |
| 1129 | # Magic\r |
| 1130 | # SizeOfImage\r |
| 1131 | # SizeOfHeaders\r |
| 1132 | # CheckSum\r |
| 1133 | # NumberOfRvaAndSizes\r |
| 1134 | #\r |
| 1135 | _OptionalHeader32Format = "1H 54x 1I 1I 1I 24x 1I"\r |
| 1136 | _OptionalHeader64Format = ""\r |
| 1137 | def __init__(self, Buf, Offset, Size):\r |
| 1138 | self.Offset = Offset\r |
| 1139 | self.Size = Size\r |
| 1140 | self.Machine = 0x014c # IA32\r |
| 1141 | self.NumberOfSections = 0\r |
| 1142 | self.SizeOfImage = 0\r |
| 1143 | self.SizeOfOptionalHeader = 0\r |
| 1144 | self.Checksum = 0\r |
| 1145 | self._PeImageBuf = Buf\r |
| 1146 | self._SectionList = []\r |
| 1147 | \r |
| 1148 | self._DosHeader = struct.Struct(PeImage._DosHeaderFormat)\r |
| 1149 | self._FileHeader = struct.Struct(PeImage._FileHeaderFormat)\r |
| 1150 | self._OptionalHeader32 = struct.Struct(PeImage._OptionalHeader32Format)\r |
| 1151 | \r |
| 1152 | self.Buffer = None\r |
| 1153 | \r |
| 1154 | self._Unpack()\r |
| 1155 | \r |
| 1156 | def __str__(self):\r |
| 1157 | pass\r |
| 1158 | \r |
| 1159 | def __len__(self):\r |
| 1160 | return self.Size\r |
| 1161 | \r |
| 1162 | def _Unpack(self):\r |
| 1163 | # from DOS header, get the offset of PE header\r |
| 1164 | FileHeaderOffset, = self._DosHeader.unpack_from(self._PeImageBuf, self.Offset)\r |
| 1165 | if FileHeaderOffset < struct.calcsize(self._DosHeaderFormat):\r |
| 1166 | EdkLogger.error("PE+", 0, "Invalid offset of IMAGE_FILE_HEADER: %s" % FileHeaderOffset)\r |
| 1167 | \r |
| 1168 | # from FILE header, get the optional header size\r |
| 1169 | self.Machine, self.NumberOfSections, self.SizeOfOptionalHeader = \\r |
| 1170 | self._FileHeader.unpack_from(self._PeImageBuf, self.Offset + FileHeaderOffset)\r |
| 1171 | \r |
| 1172 | print "Machine=%x NumberOfSections=%x SizeOfOptionalHeader=%x" % (self.Machine, self.NumberOfSections, self.SizeOfOptionalHeader)\r |
| 1173 | # optional header follows the FILE header\r |
| 1174 | OptionalHeaderOffset = FileHeaderOffset + struct.calcsize(self._FileHeaderFormat)\r |
| 1175 | Magic, self.SizeOfImage, SizeOfHeaders, self.Checksum, NumberOfRvaAndSizes = \\r |
| 1176 | self._OptionalHeader32.unpack_from(self._PeImageBuf, self.Offset + OptionalHeaderOffset)\r |
| 1177 | print "Magic=%x SizeOfImage=%x SizeOfHeaders=%x, Checksum=%x, NumberOfRvaAndSizes=%x" % (Magic, self.SizeOfImage, SizeOfHeaders, self.Checksum, NumberOfRvaAndSizes)\r |
| 1178 | \r |
| 1179 | PeImageSectionTableOffset = OptionalHeaderOffset + self.SizeOfOptionalHeader\r |
| 1180 | PeSections = PeSectionTable(self._PeImageBuf, self.Offset + PeImageSectionTableOffset, self.NumberOfSections)\r |
| 1181 | \r |
| 1182 | print "%x" % PeSections.GetFileAddress(0x3920)\r |
| 1183 | \r |
| 1184 | ## PeSectionTable() class\r |
| 1185 | #\r |
| 1186 | # A class for PE Section Table\r |
| 1187 | #\r |
| 1188 | class PeSectionTable:\r |
| 1189 | def __init__(self, Buf, Offset, NumberOfSections):\r |
| 1190 | self._SectionList = []\r |
| 1191 | \r |
| 1192 | SectionHeaderOffset = Offset\r |
| 1193 | for TableIndex in range(0, NumberOfSections):\r |
| 1194 | SectionHeader = PeSectionHeader(Buf, SectionHeaderOffset)\r |
| 1195 | self._SectionList.append(SectionHeader)\r |
| 1196 | SectionHeaderOffset += len(SectionHeader)\r |
| 1197 | print SectionHeader\r |
| 1198 | \r |
| 1199 | def GetFileAddress(self, Rva):\r |
| 1200 | for PeSection in self._SectionList:\r |
| 1201 | if Rva in PeSection:\r |
| 1202 | return PeSection[Rva]\r |
| 1203 | \r |
| 1204 | ## PeSectionHeader() class\r |
| 1205 | #\r |
| 1206 | # A class for PE Section Header\r |
| 1207 | #\r |
| 1208 | class PeSectionHeader:\r |
| 1209 | #\r |
| 1210 | # VirtualAddress\r |
| 1211 | # SizeOfRawData\r |
| 1212 | # PointerToRawData\r |
| 1213 | #\r |
| 1214 | _HeaderFormat = "12x 1I 1I 1I 16x"\r |
| 1215 | _HeaderLength = struct.calcsize(_HeaderFormat)\r |
| 1216 | \r |
| 1217 | def __init__(self, Buf, Offset):\r |
| 1218 | self.VirtualAddressStart, self.SizeOfRawData, self.PointerToRawData = \\r |
| 1219 | struct.unpack_from(self._HeaderFormat, Buf, Offset)\r |
| 1220 | self.VirtualAddressEnd = self.VirtualAddressStart + self.SizeOfRawData - 1\r |
| 1221 | \r |
| 1222 | def __str__(self):\r |
| 1223 | return "VirtualAddress=%x, SizeOfRawData=%x, PointerToRawData=%x" % (self.VirtualAddressStart, self.SizeOfRawData, self.PointerToRawData)\r |
| 1224 | \r |
| 1225 | def __len__(self):\r |
| 1226 | return self._HeaderLength\r |
| 1227 | \r |
| 1228 | def __contains__(self, Rva):\r |
| 1229 | return Rva >= self.VirtualAddressStart and Rva <= self.VirtualAddressEnd\r |
| 1230 | \r |
| 1231 | def __getitem__(self, Rva):\r |
| 1232 | return Rva - self.VirtualAddressStart + self.PointerToRawData\r |
| 1233 | \r |
| 1234 | ## LinkMap() class\r |
| 1235 | #\r |
| 1236 | # A class for Link Map\r |
| 1237 | #\r |
| 1238 | class LinkMap:\r |
| 1239 | _StartFlag = {\r |
| 1240 | "MSFT" : re.compile("Address +Publics by Value +Rva\+Base +Lib:Object"),\r |
| 1241 | "GCC" : re.compile("^\.(text|bss|data|edata)"),\r |
| 1242 | }\r |
| 1243 | \r |
| 1244 | _MappingFormat = {\r |
| 1245 | "MSFT" : re.compile("([0-9a-f]+):([0-9a-f]+)\s+_+([0-9A-Za-z]+)\s+([0-9a-f]+)\s+"),\r |
| 1246 | "GCC" : re.compile("^(\.\w)?\s+(0x[0-9a-f]+)\s+_+([0-9A-Za-z]+)"),\r |
| 1247 | }\r |
| 1248 | \r |
| 1249 | def __init__(self, MapFile, MapType="MSFT"):\r |
| 1250 | self.File = MapFile\r |
| 1251 | self.MapType = MapType\r |
| 1252 | self._Globals = {} # global:RVA\r |
| 1253 | \r |
| 1254 | self._Parse()\r |
| 1255 | \r |
| 1256 | def _Parse(self):\r |
| 1257 | MapFile = open(self.File, 'r')\r |
| 1258 | MappingTitle = self._StartFlag[self.MapType]\r |
| 1259 | MappingFormat = self._MappingFormat[self.MapType]\r |
| 1260 | MappingStart = False\r |
| 1261 | try:\r |
| 1262 | for Line in MapFile:\r |
| 1263 | Line = Line.strip()\r |
| 1264 | if not MappingStart:\r |
| 1265 | if MappingTitle.match(Line) is not None:\r |
| 1266 | MappingStart = True\r |
| 1267 | continue\r |
| 1268 | ResultList = MappingFormat.findall(Line)\r |
| 1269 | if len(ResultList) == 0 or len(ResultList[0]) != 4:\r |
| 1270 | continue\r |
| 1271 | self._Globals[ResultList[2]] = int(ResultList[3], 16)\r |
| 1272 | EdkLogger.verbose(ResultList[0])\r |
| 1273 | finally:\r |
| 1274 | MapFile.close()\r |
| 1275 | \r |
| 1276 | def __contains__(self, Var):\r |
| 1277 | return Var in self._Globals\r |
| 1278 | \r |
| 1279 | def __getitem__(self, Var):\r |
| 1280 | if Var not in self._Globals:\r |
| 1281 | return None\r |
| 1282 | return self._Globals[Var]\r |
| 1283 | \r |
| 1284 | ## MultipleFv() class\r |
| 1285 | #\r |
| 1286 | # A class for Multiple FV\r |
| 1287 | #\r |
| 1288 | class MultipleFv(FirmwareVolume):\r |
| 1289 | def __init__(self, FvList):\r |
| 1290 | FirmwareVolume.__init__(self)\r |
| 1291 | self.BasicInfo = []\r |
| 1292 | for FvPath in FvList:\r |
| 1293 | FvName = os.path.splitext(os.path.split(FvPath)[1])[0]\r |
| 1294 | Fd = open(FvPath, 'rb')\r |
| 1295 | Buf = array('B')\r |
| 1296 | try:\r |
| 1297 | Buf.fromfile(Fd, os.path.getsize(FvPath))\r |
| 1298 | except EOFError:\r |
| 1299 | pass\r |
| 1300 | \r |
| 1301 | Fv = FirmwareVolume(FvName)\r |
| 1302 | Fv.frombuffer(Buf, 0, len(Buf))\r |
| 1303 | \r |
| 1304 | self.BasicInfo.append([Fv.Name, Fv.FileSystemGuid, Fv.Size])\r |
| 1305 | self.FfsDict.append(Fv.FfsDict)\r |
| 1306 | \r |
| 1307 | # Version and Copyright\r |
| 1308 | __version_number__ = "0.01"\r |
| 1309 | __version__ = "%prog Version " + __version_number__\r |
| 1310 | __copyright__ = "Copyright (c) 2008, Intel Corporation. All rights reserved."\r |
| 1311 | \r |
| 1312 | ## Parse command line options\r |
| 1313 | #\r |
| 1314 | # Using standard Python module optparse to parse command line option of this tool.\r |
| 1315 | #\r |
| 1316 | # @retval Options A optparse.Values object containing the parsed options\r |
| 1317 | # @retval InputFile Path of file to be trimmed\r |
| 1318 | #\r |
| 1319 | def GetOptions():\r |
| 1320 | OptionList = [\r |
| 1321 | make_option("-a", "--arch", dest="Arch",\r |
| 1322 | help="The input file is preprocessed source code, including C or assembly code"),\r |
| 1323 | make_option("-p", "--platform", dest="ActivePlatform",\r |
| 1324 | help="The input file is preprocessed VFR file"),\r |
| 1325 | make_option("-m", "--module", dest="ActiveModule",\r |
| 1326 | help="Convert standard hex format (0xabcd) to MASM format (abcdh)"),\r |
| 1327 | make_option("-f", "--FDF-file", dest="FdfFile",\r |
| 1328 | help="Convert standard hex format (0xabcd) to MASM format (abcdh)"),\r |
| 1329 | make_option("-o", "--output", dest="OutputDirectory",\r |
| 1330 | help="File to store the trimmed content"),\r |
| 1331 | make_option("-t", "--toolchain-tag", dest="ToolChain",\r |
| 1332 | help=""),\r |
| 1333 | make_option("-k", "--msft", dest="MakefileType", action="store_const", const="nmake",\r |
| 1334 | help=""),\r |
| 1335 | make_option("-g", "--gcc", dest="MakefileType", action="store_const", const="gmake",\r |
| 1336 | help=""),\r |
| 1337 | make_option("-v", "--verbose", dest="LogLevel", action="store_const", const=EdkLogger.VERBOSE,\r |
| 1338 | help="Run verbosely"),\r |
| 1339 | make_option("-d", "--debug", dest="LogLevel", type="int",\r |
| 1340 | help="Run with debug information"),\r |
| 1341 | make_option("-q", "--quiet", dest="LogLevel", action="store_const", const=EdkLogger.QUIET,\r |
| 1342 | help="Run quietly"),\r |
| 1343 | make_option("-?", action="help", help="show this help message and exit"),\r |
| 1344 | ]\r |
| 1345 | \r |
| 1346 | # use clearer usage to override default usage message\r |
| 1347 | UsageString = "%prog [-a ARCH] [-p PLATFORM] [-m MODULE] [-t TOOLCHAIN_TAG] [-k] [-g] [-v|-d <debug_level>|-q] [-o <output_directory>] [GenC|GenMake]"\r |
| 1348 | \r |
| 1349 | Parser = OptionParser(description=__copyright__, version=__version__, option_list=OptionList, usage=UsageString)\r |
| 1350 | Parser.set_defaults(Arch=[])\r |
| 1351 | Parser.set_defaults(ActivePlatform=None)\r |
| 1352 | Parser.set_defaults(ActiveModule=None)\r |
| 1353 | Parser.set_defaults(OutputDirectory="build")\r |
| 1354 | Parser.set_defaults(FdfFile=None)\r |
| 1355 | Parser.set_defaults(ToolChain="MYTOOLS")\r |
| 1356 | if sys.platform == "win32":\r |
| 1357 | Parser.set_defaults(MakefileType="nmake")\r |
| 1358 | else:\r |
| 1359 | Parser.set_defaults(MakefileType="gmake")\r |
| 1360 | Parser.set_defaults(LogLevel=EdkLogger.INFO)\r |
| 1361 | \r |
| 1362 | Options, Args = Parser.parse_args()\r |
| 1363 | \r |
| 1364 | # error check\r |
| 1365 | if len(Args) == 0:\r |
| 1366 | Options.Target = "genmake"\r |
| 1367 | sys.argv.append("genmake")\r |
| 1368 | elif len(Args) == 1:\r |
| 1369 | Options.Target = Args[0].lower()\r |
| 1370 | if Options.Target not in ["genc", "genmake"]:\r |
| 1371 | EdkLogger.error("AutoGen", OPTION_NOT_SUPPORTED, "Not supported target",\r |
| 1372 | ExtraData="%s\n\n%s" % (Options.Target, Parser.get_usage()))\r |
| 1373 | else:\r |
| 1374 | EdkLogger.error("AutoGen", OPTION_NOT_SUPPORTED, "Too many targets",\r |
| 1375 | ExtraData=Parser.get_usage())\r |
| 1376 | \r |
| 1377 | return Options\r |
| 1378 | \r |
| 1379 | ## Entrance method\r |
| 1380 | #\r |
| 1381 | # This method mainly dispatch specific methods per the command line options.\r |
| 1382 | # If no error found, return zero value so the caller of this tool can know\r |
| 1383 | # if it's executed successfully or not.\r |
| 1384 | #\r |
| 1385 | # @retval 0 Tool was successful\r |
| 1386 | # @retval 1 Tool failed\r |
| 1387 | #\r |
| 1388 | def Main():\r |
| 1389 | from build import build\r |
| 1390 | try:\r |
| 1391 | Option = GetOptions()\r |
| 1392 | build.main()\r |
| 1393 | except Exception, e:\r |
| 1394 | print e\r |
| 1395 | return 1\r |
| 1396 | \r |
| 1397 | return 0\r |
| 1398 | \r |
| 1399 | # This acts like the main() function for the script, unless it is 'import'ed into another script.\r |
| 1400 | if __name__ == '__main__':\r |
| 1401 | EdkLogger.Initialize()\r |
| 1402 | # sys.exit(Main())\r |
| 1403 | \r |
| 1404 | if len(sys.argv) > 1:\r |
| 1405 | FilePath = sys.argv[1]\r |
| 1406 | if FilePath.lower().endswith(".fv"):\r |
| 1407 | fd = open(FilePath, 'rb')\r |
| 1408 | buf = array('B')\r |
| 1409 | try:\r |
| 1410 | buf.fromfile(fd, os.path.getsize(FilePath))\r |
| 1411 | except EOFError:\r |
| 1412 | pass\r |
| 1413 | \r |
| 1414 | fv = FirmwareVolume("FVRECOVERY")\r |
| 1415 | fv.frombuffer(buf, 0, len(buf))\r |
| 1416 | #fv.Dispatch(None)\r |
| 1417 | print fv\r |
| 1418 | elif FilePath.endswith(".efi"):\r |
| 1419 | fd = open(FilePath, 'rb')\r |
| 1420 | buf = array('B')\r |
| 1421 | Size = os.path.getsize(FilePath)\r |
| 1422 | \r |
| 1423 | try:\r |
| 1424 | buf.fromfile(fd, Size)\r |
| 1425 | except EOFError:\r |
| 1426 | pass\r |
| 1427 | \r |
| 1428 | PeSection = Section(Type=0x10)\r |
| 1429 | PeSection.Data = buf\r |
| 1430 | sf, ext = os.path.splitext(os.path.basename(FilePath))\r |
| 1431 | sf += ".sec"\r |
| 1432 | PeSection.tofile(open(sf, 'wb'))\r |
| 1433 | elif FilePath.endswith(".map"):\r |
| 1434 | mf = LinkMap(FilePath)\r |