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