]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Eot/FvImage.py
FatPkg/EnhancedFatDxe: Ensure traverse of subtasks is delete-safe
[mirror_edk2.git] / BaseTools / Source / Python / Eot / FvImage.py
CommitLineData
f51461c8
LG
1## @file\r
2# Parse FV image\r
3#\r
1be2ed90 4# Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>\r
f51461c8
LG
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
1be2ed90 16import Common.LongFilePathOs as os\r
f51461c8
LG
17import re\r
18import sys\r
19import uuid\r
20import struct\r
21import codecs\r
22import copy\r
23\r
24from UserDict import IterableUserDict\r
25from cStringIO import StringIO\r
26from array import array\r
1be2ed90 27from Common.LongFilePathSupport import OpenLongFilePath as open\r
f51461c8
LG
28from CommonDataClass import *\r
29from Common.Misc import sdict, GuidStructureStringToGuidString\r
30\r
31import Common.EdkLogger as EdkLogger\r
32\r
33import EotGlobalData\r
34\r
35# Global definiton\r
36gFfsPrintTitle = "%-36s %-21s %8s %8s %8s %-4s %-36s" % ("GUID", "TYPE", "OFFSET", "SIZE", "FREE", "ALIGN", "NAME")\r
37gFfsPrintFormat = "%36s %-21s %8X %8X %8X %4s %-36s"\r
38gGuidStringFormat = "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"\r
39gPeiAprioriFileNameGuid = '1b45cc0a-156a-428a-af62-49864da0e6e6'\r
40gAprioriGuid = 'fc510ee7-ffdc-11d4-bd41-0080c73c8881'\r
41gIndention = -4\r
42\r
43## Image() class\r
44#\r
45# A class for Image\r
46#\r
47class 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
4231a819 55 if ID is None:\r
f51461c8
LG
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
121class 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
f51461c8
LG
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
4231a819 210 if Db is None:\r
f51461c8
LG
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
4231a819 238 if FfsSecCoreGuid is not None:\r
f51461c8
LG
239 self.OrderedFfsDict[FfsSecCoreGuid] = self.UnDispatchedFfsDict.pop(FfsSecCoreGuid)\r
240 self.LoadPpi(Db, FfsSecCoreGuid)\r
241\r
242 # Parse PEI first\r
4231a819 243 if FfsPeiCoreGuid is not None:\r
f51461c8
LG
244 self.OrderedFfsDict[FfsPeiCoreGuid] = self.UnDispatchedFfsDict.pop(FfsPeiCoreGuid)\r
245 self.LoadPpi(Db, FfsPeiCoreGuid)\r
4231a819 246 if FfsPeiPrioriGuid is not None:\r
f51461c8
LG
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
4231a819 265 if FfsDxeCoreGuid is not None:\r
f51461c8
LG
266 self.OrderedFfsDict[FfsDxeCoreGuid] = self.UnDispatchedFfsDict.pop(FfsDxeCoreGuid)\r
267 self.LoadProtocol(Db, FfsDxeCoreGuid)\r
4231a819 268 if FfsDxePrioriGuid is not None:\r
f51461c8
LG
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
f51461c8
LG
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
4231a819 365 if FileDepex is not None:\r
f51461c8
LG
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
4231a819 453 if LastFfsObj is not None:\r
f51461c8
LG
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
4231a819 462 if LastFfsObj is not None:\r
f51461c8
LG
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
498class 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
4231a819 509 if UncompressedLength is not None:\r
f51461c8 510 m.UncompressedLength = UncompressedLength\r
4231a819 511 if CompressionType is not None:\r
f51461c8 512 m.CompressionType = CompressionType\r
4231a819 513 if CompressedData is not None:\r
f51461c8
LG
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
575class 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
4231a819 589 if SectionDefinitionGuid is not None:\r
f51461c8 590 m.SectionDefinitionGuid = SectionDefinitionGuid\r
4231a819 591 if DataOffset is not None:\r
f51461c8 592 m.DataOffset = DataOffset\r
4231a819 593 if Attributes is not None:\r
f51461c8 594 m.Attributes = Attributes\r
4231a819 595 if Data is not None:\r
f51461c8
LG
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
698class 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
4231a819 773 if CurrentData is None:\r
f51461c8
LG
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
783class 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
808class 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
4231a819 849 if Type is not None:\r
f51461c8 850 m.Type = Type\r
4231a819 851 if Size is not None:\r
f51461c8
LG
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
936class 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
947class 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
401d1343
SV
981 0x0E : "MM_STANDALONE",\r
982 0x0F : "MM_CORE_STANDALONE",\r
f51461c8
LG
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
1117class 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
1188class 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
1208class 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
1238class 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
4231a819 1265 if MappingTitle.match(Line) is not None:\r
f51461c8
LG
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
1288class 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
1319def 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
1388def 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
1400if __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