]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/efibinary.py
3 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials are licensed and made available
6 # under the terms and conditions of the BSD License which accompanies this
7 # distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 return logging
.getLogger('EFI Binary File')
24 class EFIBinaryError(Exception):
25 def __init__(self
, message
):
26 Exception.__init
__(self
)
27 self
._message
= message
33 EFI_FV_HEADER_SIZE
= 0x48
38 def Load(self
, fd
, size
):
40 while (index
+ self
.EFI_FV_HEADER_SIZE
< size
):
44 index
+= fv
.GetHeader().GetFvLength()
45 index
= align(index
, 8)
52 FILE_SYSTEM_GUID
= uuid
.UUID('{8c8ce578-8a3d-4f1c-9935-896185c32dd3}')
54 def __init__(self
, parent
=None):
58 self
._blockentries
= []
61 # following field is for FV in FD
64 self
._raw
= array
.array('B')
67 self
._offset
= fd
.tell()
68 self
._filename
= fd
.name
71 self
._fvheader
= EfiFirmwareVolumeHeader
.Read(fd
)
72 #self._fvheader.Dump()
74 self
._size
= self
._fvheader
.GetFvLength()
76 if self
._fvheader
.GetFileSystemGuid() != self
.FILE_SYSTEM_GUID
:
78 self
._raw
.fromfile(fd
, self
.GetHeader().GetFvLength())
82 blockentry
= BlockMapEntry
.Read(fd
)
83 self
._blockentries
.append(blockentry
)
84 while (blockentry
.GetNumberBlocks() != 0 and blockentry
.GetLength() != 0):
85 self
._blockentries
.append(blockentry
)
86 blockentry
= BlockMapEntry
.Read(fd
)
89 if self
._fvheader
.GetSize() + (len(self
._blockentries
)) * 8 != \
90 self
._fvheader
.GetHeaderLength():
91 raise EFIBinaryError("Volume Header length not consistent with block map!")
93 index
= align(fd
.tell(), 8)
95 while ((index
+ EfiFfs
.FFS_HEADER_SIZE
) < self
._size
):
96 ffs
= EfiFfs
.Read(fd
, self
)
97 if not isValidGuid(ffs
.GetNameGuid()):
101 index
= align(fd
.tell(), 8)
103 fd
.seek(self
._offset
)
104 self
._raw
.fromfile(fd
, self
.GetHeader().GetFvLength())
110 return self
._fvheader
112 def GetBlockEntries(self
):
113 return self
._blockentries
115 def GetHeaderRawData(self
):
117 ret
+= self
._fvheader
.GetRawData()
118 for block
in self
._blockentries
:
119 ret
+= block
.GetRawData()
125 def GetRawData(self
):
126 return self
._raw
.tolist()
128 class BinaryItem(object):
129 def __init__(self
, parent
=None):
131 self
._arr
= array
.array('B')
132 self
._parent
= parent
135 def Read(cls
, fd
, parent
=None):
144 """should be implemented by inherited class"""
146 def fromfile(self
, fd
):
147 self
._arr
.fromfile(fd
, self
.GetSize())
152 class EfiFirmwareVolumeHeader(BinaryItem
):
156 def GetSigunature(self
):
157 list = self
._arr
.tolist()
159 for x
in list[40:44]:
163 def GetAttribute(self
):
164 return list2int(self
._arr
.tolist()[44:48])
166 def GetErasePolarity(self
):
167 list = self
.GetAttrStrings()
168 if 'EFI_FVB2_ERASE_POLARITY' in list:
172 def GetAttrStrings(self
):
174 value
= self
.GetAttribute()
175 if (value
& 0x01) != 0:
176 list.append('EFI_FVB2_READ_DISABLED_CAP')
177 if (value
& 0x02) != 0:
178 list.append('EFI_FVB2_READ_ENABLED_CAP')
179 if (value
& 0x04) != 0:
180 list.append('EFI_FVB2_READ_STATUS')
181 if (value
& 0x08) != 0:
182 list.append('EFI_FVB2_WRITE_DISABLED_CAP')
183 if (value
& 0x10) != 0:
184 list.append('EFI_FVB2_WRITE_ENABLED_CAP')
185 if (value
& 0x20) != 0:
186 list.append('EFI_FVB2_WRITE_STATUS')
187 if (value
& 0x40) != 0:
188 list.append('EFI_FVB2_LOCK_CAP')
189 if (value
& 0x80) != 0:
190 list.append('EFI_FVB2_LOCK_STATUS')
191 if (value
& 0x200) != 0:
192 list.append('EFI_FVB2_STICKY_WRITE')
193 if (value
& 0x400) != 0:
194 list.append('EFI_FVB2_MEMORY_MAPPED')
195 if (value
& 0x800) != 0:
196 list.append('EFI_FVB2_ERASE_POLARITY')
197 if (value
& 0x1000) != 0:
198 list.append('EFI_FVB2_READ_LOCK_CAP')
199 if (value
& 0x00002000) != 0:
200 list.append('EFI_FVB2_READ_LOCK_STATUS')
201 if (value
& 0x00004000) != 0:
202 list.append('EFI_FVB2_WRITE_LOCK_CAP')
203 if (value
& 0x00008000) != 0:
204 list.append('EFI_FVB2_WRITE_LOCK_STATUS')
207 list.append('EFI_FVB2_ALIGNMENT_1')
208 if (value
& 0x001F0000) == 0x00010000:
209 list.append('EFI_FVB2_ALIGNMENT_2')
210 if (value
& 0x001F0000) == 0x00020000:
211 list.append('EFI_FVB2_ALIGNMENT_4')
212 if (value
& 0x001F0000) == 0x00030000:
213 list.append('EFI_FVB2_ALIGNMENT_8')
214 if (value
& 0x001F0000) == 0x00040000:
215 list.append('EFI_FVB2_ALIGNMENT_16')
216 if (value
& 0x001F0000) == 0x00050000:
217 list.append('EFI_FVB2_ALIGNMENT_32')
218 if (value
& 0x001F0000) == 0x00060000:
219 list.append('EFI_FVB2_ALIGNMENT_64')
220 if (value
& 0x001F0000) == 0x00070000:
221 list.append('EFI_FVB2_ALIGNMENT_128')
222 if (value
& 0x001F0000) == 0x00080000:
223 list.append('EFI_FVB2_ALIGNMENT_256')
224 if (value
& 0x001F0000) == 0x00090000:
225 list.append('EFI_FVB2_ALIGNMENT_512')
226 if (value
& 0x001F0000) == 0x000A0000:
227 list.append('EFI_FVB2_ALIGNMENT_1K')
228 if (value
& 0x001F0000) == 0x000B0000:
229 list.append('EFI_FVB2_ALIGNMENT_2K')
230 if (value
& 0x001F0000) == 0x000C0000:
231 list.append('EFI_FVB2_ALIGNMENT_4K')
232 if (value
& 0x001F0000) == 0x000D0000:
233 list.append('EFI_FVB2_ALIGNMENT_8K')
234 if (value
& 0x001F0000) == 0x000E0000:
235 list.append('EFI_FVB2_ALIGNMENT_16K')
236 if (value
& 0x001F0000) == 0x000F0000:
237 list.append('EFI_FVB2_ALIGNMENT_32K')
238 if (value
& 0x001F0000) == 0x00100000:
239 list.append('EFI_FVB2_ALIGNMENT_64K')
240 if (value
& 0x001F0000) == 0x00110000:
241 list.append('EFI_FVB2_ALIGNMENT_128K')
242 if (value
& 0x001F0000) == 0x00120000:
243 list.append('EFI_FVB2_ALIGNMENT_256K')
244 if (value
& 0x001F0000) == 0x00130000:
245 list.append('EFI_FVB2_ALIGNMENT_512K')
249 def GetHeaderLength(self
):
250 return list2int(self
._arr
.tolist()[48:50])
253 print 'Signature: %s' % self
.GetSigunature()
254 print 'Attribute: 0x%X' % self
.GetAttribute()
255 print 'Header Length: 0x%X' % self
.GetHeaderLength()
256 print 'File system Guid: ', self
.GetFileSystemGuid()
257 print 'Revision: 0x%X' % self
.GetRevision()
258 print 'FvLength: 0x%X' % self
.GetFvLength()
260 def GetFileSystemGuid(self
):
261 list = self
._arr
.tolist()
262 return list2guid(list[16:32])
264 def GetRevision(self
):
265 list = self
._arr
.tolist()
268 def GetFvLength(self
):
269 list = self
._arr
.tolist()
270 return list2int(list[32:40])
272 def GetRawData(self
):
273 return self
._arr
.tolist()
275 class BlockMapEntry(BinaryItem
):
279 def GetNumberBlocks(self
):
280 list = self
._arr
.tolist()
281 return list2int(list[0:4])
284 list = self
._arr
.tolist()
285 return list2int(list[4:8])
287 def GetRawData(self
):
288 return self
._arr
.tolist()
291 return '[BlockEntry] Number = 0x%X, length=0x%X' % (self
.GetNumberBlocks(), self
.GetLength())
293 class EfiFfs(object):
296 def __init__(self
, parent
=None):
299 # following field is for FFS in FV file.
300 self
._parent
= parent
305 self
._offset
= align(fd
.tell(), 8)
307 self
._header
= EfiFfsHeader
.Read(fd
, self
)
309 if not isValidGuid(self
.GetNameGuid()):
313 fileend
= self
._offset
+ self
.GetSize()
314 while (index
+ EfiSection
.EFI_SECTION_HEADER_SIZE
< fileend
):
315 section
= EfiSection(self
)
317 if section
.GetSize() == 0 and section
.GetHeader().GetType() == 0:
319 self
._sections
.append(section
)
322 # rebase file pointer to next ffs file
323 index
= self
._offset
+ self
._header
.GetFfsSize()
324 index
= align(index
, 8)
331 return self
._header
.GetFfsSize()
334 def Read(cls
, fd
, parent
=None):
339 def GetNameGuid(self
):
340 return self
._header
.GetNameGuid()
342 def DumpContent(self
):
343 list = self
._content
.tolist()
348 line
.append('0x%X' % int(item
))
354 line
.append('0x%X' % int(item
))
363 def GetSections(self
):
364 return self
._sections
366 class EfiFfsHeader(BinaryItem
):
367 ffs_state_map
= {0x01:'EFI_FILE_HEADER_CONSTRUCTION',
368 0x02:'EFI_FILE_HEADER_VALID',
369 0x04:'EFI_FILE_DATA_VALID',
370 0x08:'EFI_FILE_MARKED_FOR_UPDATE',
371 0x10:'EFI_FILE_DELETED',
372 0x20:'EFI_FILE_HEADER_INVALID'}
377 def GetNameGuid(self
):
378 list = self
._arr
.tolist()
379 return list2guid(list[0:16])
382 list = self
._arr
.tolist()
386 def GetTypeString(self
):
387 value
= self
.GetType()
389 return 'EFI_FV_FILETYPE_RAW'
391 return 'EFI_FV_FILETYPE_FREEFORM'
393 return 'EFI_FV_FILETYPE_SECURITY_CORE'
395 return 'EFI_FV_FILETYPE_PEI_CORE'
397 return 'EFI_FV_FILETYPE_DXE_CORE'
399 return 'EFI_FV_FILETYPE_PEIM'
401 return 'EFI_FV_FILETYPE_DRIVER'
403 return 'EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER'
405 return 'EFI_FV_FILETYPE_APPLICATION'
407 return 'EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE'
409 return 'EFI_FV_FILETYPE_OEM_MIN'
411 return 'EFI_FV_FILETYPE_OEM_MAX'
413 return 'EFI_FV_FILETYPE_DEBUG_MIN'
415 return 'EFI_FV_FILETYPE_DEBUG_MAX'
417 return 'EFI_FV_FILETYPE_FFS_PAD'
419 return 'EFI_FV_FILETYPE_FFS_MAX'
420 return 'Unknown FFS Type'
422 def GetAttributes(self
):
423 list = self
._arr
.tolist()
426 def GetFfsSize(self
):
427 list = self
._arr
.tolist()
428 return list2int(list[20:23])
431 list = self
._arr
.tolist()
432 state
= int(list[23])
433 polarity
= self
.GetParent().GetParent().GetHeader().GetErasePolarity()
435 state
= (~state
) & 0xFF
437 while (HighestBit
!= 0) and (HighestBit
& state
) == 0:
438 HighestBit
= HighestBit
>> 1
441 def GetStateString(self
):
442 state
= self
.GetState()
443 if state
in self
.ffs_state_map
.keys():
444 return self
.ffs_state_map
[state
]
445 return 'Unknown Ffs State'
448 print "FFS name: ", self
.GetNameGuid()
449 print "FFS type: ", self
.GetType()
450 print "FFS attr: 0x%X" % self
.GetAttributes()
451 print "FFS size: 0x%X" % self
.GetFfsSize()
452 print "FFS state: 0x%X" % self
.GetState()
454 def GetRawData(self
):
455 return self
._arr
.tolist()
458 class EfiSection(object):
459 EFI_SECTION_HEADER_SIZE
= 4
461 def __init__(self
, parent
=None):
463 self
._parent
= parent
465 self
._contents
= array
.array('B')
468 self
._offset
= align(fd
.tell(), 4)
470 self
._header
= EfiSectionHeader
.Read(fd
, self
)
472 if self
._header
.GetTypeString() == "EFI_SECTION_PE32":
473 pefile
= pe
.PEFile(self
)
474 pefile
.Load(fd
, self
.GetContentSize())
476 fd
.seek(self
._offset
)
477 self
._contents
.fromfile(fd
, self
.GetContentSize())
479 # rebase file pointer to next section
480 index
= self
._offset
+ self
.GetSize()
481 index
= align(index
, 4)
484 def GetContentSize(self
):
485 return self
.GetSize() - self
.EFI_SECTION_HEADER_SIZE
487 def GetContent(self
):
488 return self
._contents
.tolist()
491 return self
._header
.GetSectionSize()
496 def GetSectionOffset(self
):
497 return self
._offset
+ self
.EFI_SECTION_HEADER_SIZE
499 class EfiSectionHeader(BinaryItem
):
500 section_type_map
= {0x01: 'EFI_SECTION_COMPRESSION',
501 0x02: 'EFI_SECTION_GUID_DEFINED',
502 0x10: 'EFI_SECTION_PE32',
503 0x11: 'EFI_SECTION_PIC',
504 0x12: 'EFI_SECTION_TE',
505 0x13: 'EFI_SECTION_DXE_DEPEX',
506 0x14: 'EFI_SECTION_VERSION',
507 0x15: 'EFI_SECTION_USER_INTERFACE',
508 0x16: 'EFI_SECTION_COMPATIBILITY16',
509 0x17: 'EFI_SECTION_FIRMWARE_VOLUME_IMAGE',
510 0x18: 'EFI_SECTION_FREEFORM_SUBTYPE_GUID',
511 0x19: 'EFI_SECTION_RAW',
512 0x1B: 'EFI_SECTION_PEI_DEPEX'}
516 def GetSectionSize(self
):
517 list = self
._arr
.tolist()
518 return list2int(list[0:3])
521 list = self
._arr
.tolist()
524 def GetTypeString(self
):
525 type = self
.GetType()
526 if type not in self
.section_type_map
.keys():
527 return 'Unknown Section Type'
528 return self
.section_type_map
[type]
531 print 'size = 0x%X' % self
.GetSectionSize()
532 print 'type = 0x%X' % self
.GetType()
536 rMapEntry
= re
.compile('^(\w+)[ \(\w\)]* \(BaseAddress=([0-9a-fA-F]+), EntryPoint=([0-9a-fA-F]+), GUID=([0-9a-fA-F\-]+)')
537 class EfiFvMapFile(object):
539 self
._mapentries
= {}
541 def Load(self
, path
):
542 if not os
.path
.exists(path
):
546 file = open(path
, 'r')
547 lines
= file.readlines()
555 ret
= rMapEntry
.match(line
)
557 name
= ret
.groups()[0]
558 baseaddr
= int(ret
.groups()[1], 16)
559 entry
= int(ret
.groups()[2], 16)
560 guidstr
= '{' + ret
.groups()[3] + '}'
561 guid
= uuid
.UUID(guidstr
)
562 self
._mapentries
[guid
] = EfiFvMapFileEntry(name
, baseaddr
, entry
, guid
)
565 def GetEntry(self
, guid
):
566 if guid
in self
._mapentries
.keys():
567 return self
._mapentries
[guid
]
570 class EfiFvMapFileEntry(object):
571 def __init__(self
, name
, baseaddr
, entry
, guid
):
573 self
._baseaddr
= baseaddr
580 def GetBaseAddress(self
):
581 return self
._baseaddr
583 def GetEntryPoint(self
):
587 val1
= list2int(list[0:4])
588 val2
= list2int(list[4:6])
589 val3
= list2int(list[6:8])
591 for item
in list[8:16]:
592 val4
= (val4
<< 8) |
int(item
)
594 val
= val1
<< 12 * 8 | val2
<< 10 * 8 | val3
<< 8 * 8 | val4
595 guid
= uuid
.UUID(int=val
)
600 for index
in range(len(list) - 1, -1, -1):
601 val
= (val
<< 8) |
int(list[index
])
604 def align(value
, alignment
):
605 return (value
+ ((alignment
- value
) & (alignment
- 1)))
607 gInvalidGuid
= uuid
.UUID(int=0xffffffffffffffffffffffffffffffff)
608 def isValidGuid(guid
):
609 if guid
== gInvalidGuid
: