IntelFsp2Pkg/Tools: Add FSP rebasing function into SplitFspBin tool
[mirror_edk2.git] / IntelFsp2Pkg / Tools / SplitFspBin.py
1 ## @ FspTool.py
2 #
3 # Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
4 # This program and the accompanying materials are licensed and made available under
5 # the terms and conditions of the BSD License that accompanies this distribution.
6 # The full text of the license may be found at
7 # http://opensource.org/licenses/bsd-license.php.
8 #
9 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 #
12 ##
13
14 import os
15 import sys
16 import uuid
17 import copy
18 import struct
19 import argparse
20 from ctypes import *
21
22 """
23 This utility supports some operations for Intel FSP 2.0 image.
24 It supports:
25 - Display FSP 2.0 information header
26 - Split FSP 2.0 image into individual FSP-T/M/S/O component
27 - Rebase FSP 2.0 components to a different base address
28 - Generate FSP mapping C header file
29 """
30
31 CopyRightHeaderFile = """/*
32 *
33 * Automatically generated file; DO NOT EDIT.
34 * FSP mapping file
35 *
36 */
37 """
38
39 class c_uint24(Structure):
40 """Little-Endian 24-bit Unsigned Integer"""
41 _pack_ = 1
42 _fields_ = [('Data', (c_uint8 * 3))]
43
44 def __init__(self, val=0):
45 self.set_value(val)
46
47 def __str__(self, indent=0):
48 return '0x%.6x' % self.value
49
50 def __int__(self):
51 return self.get_value()
52
53 def set_value(self, val):
54 self.Data[0:3] = Val2Bytes(val, 3)
55
56 def get_value(self):
57 return Bytes2Val(self.Data[0:3])
58
59 value = property(get_value, set_value)
60
61 class EFI_FIRMWARE_VOLUME_HEADER(Structure):
62 _fields_ = [
63 ('ZeroVector', ARRAY(c_uint8, 16)),
64 ('FileSystemGuid', ARRAY(c_uint8, 16)),
65 ('FvLength', c_uint64),
66 ('Signature', ARRAY(c_char, 4)),
67 ('Attributes', c_uint32),
68 ('HeaderLength', c_uint16),
69 ('Checksum', c_uint16),
70 ('ExtHeaderOffset', c_uint16),
71 ('Reserved', c_uint8),
72 ('Revision', c_uint8)
73 ]
74
75 class EFI_FIRMWARE_VOLUME_EXT_HEADER(Structure):
76 _fields_ = [
77 ('FvName', ARRAY(c_uint8, 16)),
78 ('ExtHeaderSize', c_uint32)
79 ]
80
81 class EFI_FFS_INTEGRITY_CHECK(Structure):
82 _fields_ = [
83 ('Header', c_uint8),
84 ('File', c_uint8)
85 ]
86
87 class EFI_FFS_FILE_HEADER(Structure):
88 _fields_ = [
89 ('Name', ARRAY(c_uint8, 16)),
90 ('IntegrityCheck', EFI_FFS_INTEGRITY_CHECK),
91 ('Type', c_uint8),
92 ('Attributes', c_uint8),
93 ('Size', c_uint24),
94 ('State', c_uint8)
95 ]
96
97 class EFI_COMMON_SECTION_HEADER(Structure):
98 _fields_ = [
99 ('Size', c_uint24),
100 ('Type', c_uint8)
101 ]
102
103 class FSP_COMMON_HEADER(Structure):
104 _fields_ = [
105 ('Signature', ARRAY(c_char, 4)),
106 ('HeaderLength', c_uint32)
107 ]
108
109 class FSP_INFORMATION_HEADER(Structure):
110 _fields_ = [
111 ('Signature', ARRAY(c_char, 4)),
112 ('HeaderLength', c_uint32),
113 ('Reserved1', c_uint16),
114 ('SpecVersion', c_uint8),
115 ('HeaderRevision', c_uint8),
116 ('ImageRevision', c_uint32),
117 ('ImageId', ARRAY(c_char, 8)),
118 ('ImageSize', c_uint32),
119 ('ImageBase', c_uint32),
120 ('ImageAttribute', c_uint16),
121 ('ComponentAttribute', c_uint16),
122 ('CfgRegionOffset', c_uint32),
123 ('CfgRegionSize', c_uint32),
124 ('Reserved2', c_uint32),
125 ('TempRamInitEntryOffset', c_uint32),
126 ('Reserved3', c_uint32),
127 ('NotifyPhaseEntryOffset', c_uint32),
128 ('FspMemoryInitEntryOffset', c_uint32),
129 ('TempRamExitEntryOffset', c_uint32),
130 ('FspSiliconInitEntryOffset', c_uint32)
131 ]
132
133 class FSP_PATCH_TABLE(Structure):
134 _fields_ = [
135 ('Signature', ARRAY(c_char, 4)),
136 ('HeaderLength', c_uint16),
137 ('HeaderRevision', c_uint8),
138 ('Reserved', c_uint8),
139 ('PatchEntryNum', c_uint32)
140 ]
141
142 class EFI_IMAGE_DATA_DIRECTORY(Structure):
143 _fields_ = [
144 ('VirtualAddress', c_uint32),
145 ('Size', c_uint32)
146 ]
147
148 class EFI_TE_IMAGE_HEADER(Structure):
149 _fields_ = [
150 ('Signature', ARRAY(c_char, 2)),
151 ('Machine', c_uint16),
152 ('NumberOfSections', c_uint8),
153 ('Subsystem', c_uint8),
154 ('StrippedSize', c_uint16),
155 ('AddressOfEntryPoint', c_uint32),
156 ('BaseOfCode', c_uint32),
157 ('ImageBase', c_uint64),
158 ('DataDirectoryBaseReloc', EFI_IMAGE_DATA_DIRECTORY),
159 ('DataDirectoryDebug', EFI_IMAGE_DATA_DIRECTORY)
160 ]
161
162 class PE_RELOC_BLOCK_HEADER(Structure):
163 _fields_ = [
164 ('PageRVA', c_uint32),
165 ('BlockSize', c_uint32)
166 ]
167
168 class EFI_FV_FILETYPE:
169 ALL = 0x00
170 RAW = 0x01
171 FREEFORM = 0x02
172 SECURITY_CORE = 0x03
173 PEI_CORE = 0x04
174 DXE_CORE = 0x05
175 PEIM = 0x06
176 DRIVER = 0x07
177 COMBINED_PEIM_DRIVER = 0x08
178 APPLICATION = 0x09
179 SMM = 0x0a
180 FIRMWARE_VOLUME_IMAGE = 0x0b
181 COMBINED_SMM_DXE = 0x0c
182 SMM_CORE = 0x0d
183 OEM_MIN = 0xc0
184 OEM_MAX = 0xdf
185 DEBUG_MIN = 0xe0
186 DEBUG_MAX = 0xef
187 FFS_MIN = 0xf0
188 FFS_MAX = 0xff
189 FFS_PAD = 0xf0
190
191 class EFI_SECTION_TYPE:
192 """Enumeration of all valid firmware file section types."""
193 ALL = 0x00
194 COMPRESSION = 0x01
195 GUID_DEFINED = 0x02
196 DISPOSABLE = 0x03
197 PE32 = 0x10
198 PIC = 0x11
199 TE = 0x12
200 DXE_DEPEX = 0x13
201 VERSION = 0x14
202 USER_INTERFACE = 0x15
203 COMPATIBILITY16 = 0x16
204 FIRMWARE_VOLUME_IMAGE = 0x17
205 FREEFORM_SUBTYPE_GUID = 0x18
206 RAW = 0x19
207 PEI_DEPEX = 0x1b
208 SMM_DEPEX = 0x1c
209
210 def AlignPtr (offset, alignment = 8):
211 return (offset + alignment - 1) & ~(alignment - 1)
212
213 def Bytes2Val (bytes):
214 return reduce(lambda x,y: (x<<8)|y, bytes[::-1] )
215
216 def Val2Bytes (value, blen):
217 return [(value>>(i*8) & 0xff) for i in range(blen)]
218
219 def OutputStruct (obj, indent = 0, plen = 0):
220 if indent:
221 body = ''
222 else:
223 body = (' ' * indent + '<%s>:\n') % obj.__class__.__name__
224
225 if plen == 0:
226 plen = sizeof(obj)
227
228 max_key_len = 26
229 pstr = (' ' * (indent + 1) + '{0:<%d} = {1}\n') % max_key_len
230
231 for field in obj._fields_:
232 key = field[0]
233 val = getattr(obj, key)
234 rep = ''
235 if not isinstance(val, c_uint24) and isinstance(val, Structure):
236 body += pstr.format(key, val.__class__.__name__)
237 body += OutputStruct (val, indent + 1)
238 plen -= sizeof(val)
239 else:
240 if type(val) is str:
241 rep = "0x%X ('%s')" % (Bytes2Val(bytearray(val)), val)
242 elif type(val) in (int, long):
243 rep = '0x%X' % val
244 elif isinstance(val, c_uint24):
245 rep = '0x%X' % val.get_value()
246 elif 'c_ubyte_Array' in str(type(val)):
247 if sizeof(val) == 16:
248 rep = str(uuid.UUID(bytes = str(bytearray(val)))).upper()
249 else:
250 res = ['0x%02X'%i for i in bytearray(val)]
251 rep = '[%s]' % (','.join(res))
252 else:
253 rep = str(val)
254 plen -= sizeof(field[1])
255 body += pstr.format(key, rep)
256 if plen <= 0:
257 break
258 return body
259
260 class Section:
261 def __init__(self, offset, secdata):
262 self.SecHdr = EFI_COMMON_SECTION_HEADER.from_buffer (secdata, 0)
263 self.SecData = secdata[0:int(self.SecHdr.Size)]
264 self.Offset = offset
265
266 class FirmwareFile:
267 def __init__(self, offset, filedata):
268 self.FfsHdr = EFI_FFS_FILE_HEADER.from_buffer (filedata, 0)
269 self.FfsData = filedata[0:int(self.FfsHdr.Size)]
270 self.Offset = offset
271 self.SecList = []
272
273 def ParseFfs(self):
274 ffssize = len(self.FfsData)
275 offset = sizeof(self.FfsHdr)
276 if self.FfsHdr.Name != '\xff' * 16:
277 while offset < ffssize:
278 sechdr = EFI_COMMON_SECTION_HEADER.from_buffer (self.FfsData, offset)
279 sec = Section (offset, self.FfsData[offset:offset + int(sechdr.Size)])
280 self.SecList.append(sec)
281 offset += int(sechdr.Size)
282 offset = AlignPtr(offset, 4)
283
284 class FirmwareVolume:
285 def __init__(self, offset, fvdata):
286 self.FvHdr = EFI_FIRMWARE_VOLUME_HEADER.from_buffer (fvdata, 0)
287 self.FvData = fvdata[0 : self.FvHdr.FvLength]
288 self.Offset = offset
289 if self.FvHdr.ExtHeaderOffset > 0:
290 self.FvExtHdr = EFI_FIRMWARE_VOLUME_EXT_HEADER.from_buffer (self.FvData, self.FvHdr.ExtHeaderOffset)
291 else:
292 self.FvExtHdr = None
293 self.FfsList = []
294
295 def ParseFv(self):
296 fvsize = len(self.FvData)
297 if self.FvExtHdr:
298 offset = self.FvHdr.ExtHeaderOffset + self.FvExtHdr.ExtHeaderSize
299 else:
300 offset = self.FvHdr.HeaderLength
301 offset = AlignPtr(offset)
302 while offset < fvsize:
303 ffshdr = EFI_FFS_FILE_HEADER.from_buffer (self.FvData, offset)
304 if (ffshdr.Name == '\xff' * 16) and (int(ffshdr.Size) == 0xFFFFFF):
305 offset = fvsize
306 else:
307 ffs = FirmwareFile (offset, self.FvData[offset:offset + int(ffshdr.Size)])
308 ffs.ParseFfs()
309 self.FfsList.append(ffs)
310 offset += int(ffshdr.Size)
311 offset = AlignPtr(offset)
312
313 class FspImage:
314 def __init__(self, offset, fih, fihoff, patch):
315 self.Fih = fih
316 self.FihOffset = fihoff
317 self.Offset = offset
318 self.FvIdxList = []
319 self.Type = "XTMSXXXXOXXXXXXX"[(fih.ComponentAttribute >> 12) & 0x0F]
320 self.PatchList = patch
321 self.PatchList.append(fihoff + 0x1C)
322
323 def AppendFv(self, FvIdx):
324 self.FvIdxList.append(FvIdx)
325
326 def Patch(self, delta, fdbin):
327 count = 0
328 applied = 0
329 for idx, patch in enumerate(self.PatchList):
330 ptype = (patch>>24) & 0x0F
331 if ptype not in [0x00, 0x0F]:
332 raise Exception('ERROR: Invalid patch type %d !' % ptype)
333 if patch & 0x80000000:
334 patch = self.Fih.ImageSize - (0x1000000 - (patch & 0xFFFFFF))
335 else:
336 patch = patch & 0xFFFFFF
337 if (patch < self.Fih.ImageSize) and (patch + sizeof(c_uint32) <= self.Fih.ImageSize):
338 offset = patch + self.Offset
339 value = Bytes2Val(fdbin[offset:offset+sizeof(c_uint32)])
340 value += delta
341 fdbin[offset:offset+sizeof(c_uint32)] = Val2Bytes(value, sizeof(c_uint32))
342 applied += 1
343 count += 1
344 # Don't count the FSP base address patch entry appended at the end
345 if count != 0:
346 count -= 1
347 applied -= 1
348 return (count, applied)
349
350 class FirmwareDevice:
351 def __init__(self, offset, fdfile):
352 self.FvList = []
353 self.FspList = []
354 self.FdFile = fdfile
355 self.Offset = 0
356 hfsp = open (self.FdFile, 'rb')
357 self.FdData = bytearray(hfsp.read())
358 hfsp.close()
359
360 def ParseFd(self):
361 offset = 0
362 fdsize = len(self.FdData)
363 self.FvList = []
364 while offset < fdsize:
365 fvh = EFI_FIRMWARE_VOLUME_HEADER.from_buffer (self.FdData, offset)
366 if '_FVH' != fvh.Signature:
367 raise Exception("ERROR: Invalid FV header !")
368 fv = FirmwareVolume (offset, self.FdData[offset:offset + fvh.FvLength])
369 fv.ParseFv ()
370 self.FvList.append(fv)
371 offset += fv.FvHdr.FvLength
372
373 def CheckFsp (self):
374 if len(self.FspList) == 0:
375 return
376
377 fih = None
378 for fsp in self.FspList:
379 if fsp.Fih.HeaderRevision < 3:
380 raise Exception("ERROR: FSP 1.x is not supported by this tool !")
381 if not fih:
382 fih = fsp.Fih
383 else:
384 newfih = fsp.Fih
385 if (newfih.ImageId != fih.ImageId) or (newfih.ImageRevision != fih.ImageRevision):
386 raise Exception("ERROR: Inconsistent FSP ImageId or ImageRevision detected !")
387
388 def ParseFsp(self):
389 flen = 0
390 for idx, fv in enumerate(self.FvList):
391 # Check if this FV contains FSP header
392 if flen == 0:
393 if len(fv.FfsList) == 0:
394 continue
395 ffs = fv.FfsList[0]
396 if len(ffs.SecList) == 0:
397 continue
398 sec = ffs.SecList[0]
399 if sec.SecHdr.Type != EFI_SECTION_TYPE.RAW:
400 continue
401 fihoffset = ffs.Offset + sec.Offset + sizeof(sec.SecHdr)
402 fspoffset = fv.Offset
403 offset = fspoffset + fihoffset
404 fih = FSP_INFORMATION_HEADER.from_buffer (self.FdData, offset)
405 if 'FSPH' != fih.Signature:
406 continue
407
408 offset += fih.HeaderLength
409 offset = AlignPtr(offset, 4)
410 plist = []
411 while True:
412 fch = FSP_COMMON_HEADER.from_buffer (self.FdData, offset)
413 if 'FSPP' != fch.Signature:
414 offset += fch.HeaderLength
415 offset = AlignPtr(offset, 4)
416 else:
417 fspp = FSP_PATCH_TABLE.from_buffer (self.FdData, offset)
418 offset += sizeof(fspp)
419 pdata = (c_uint32 * fspp.PatchEntryNum).from_buffer(self.FdData, offset)
420 plist = list(pdata)
421 break
422
423 fsp = FspImage (fspoffset, fih, fihoffset, plist)
424 fsp.AppendFv (idx)
425 self.FspList.append(fsp)
426 flen = fsp.Fih.ImageSize - fv.FvHdr.FvLength
427 else:
428 fsp.AppendFv (idx)
429 flen -= fv.FvHdr.FvLength
430 if flen < 0:
431 raise Exception("ERROR: Incorrect FV size in image !")
432 self.CheckFsp ()
433
434 class TeImage:
435 def __init__(self, offset, tedata):
436 self.Offset = offset
437 self.TeHdr = EFI_TE_IMAGE_HEADER.from_buffer (tedata, 0)
438 self.TeData = tedata
439 self.RelocList = []
440
441 def ParseReloc(self):
442 rsize = self.TeHdr.DataDirectoryBaseReloc.Size
443 roffset = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + self.TeHdr.DataDirectoryBaseReloc.VirtualAddress
444 alignment = 4
445 offset = roffset
446 while offset < roffset + rsize:
447 offset = AlignPtr(offset, 4)
448 blkhdr = PE_RELOC_BLOCK_HEADER.from_buffer(self.TeData, offset)
449 offset += sizeof(blkhdr)
450 # Read relocation type,offset pairs
451 rlen = blkhdr.BlockSize - sizeof(PE_RELOC_BLOCK_HEADER)
452 rnum = rlen/sizeof(c_uint16)
453 rdata = (c_uint16 * rnum).from_buffer(self.TeData, offset)
454 for each in rdata:
455 roff = each & 0xfff
456 rtype = each >> 12
457 if rtype == 0: # IMAGE_REL_BASED.ABSOLUTE:
458 continue
459 if rtype != 3: # IMAGE_REL_BASED_HIGHLOW
460 raise Exception("ERROR: Unsupported relocation type %d!" % rtype)
461 # Calculate the offset of the relocation
462 aoff = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + blkhdr.PageRVA + roff
463 self.RelocList.append((rtype, aoff))
464 offset += sizeof(rdata)
465
466 def Rebase(self, delta, fdbin):
467 count = 0
468 if delta == 0:
469 return count
470
471 for (rtype, roff) in self.RelocList:
472 if rtype == 0x03: # HIGHLOW
473 offset = roff + self.Offset
474 value = Bytes2Val(fdbin[offset:offset+sizeof(c_uint32)])
475 value += delta
476 fdbin[offset:offset+sizeof(c_uint32)] = Val2Bytes(value, sizeof(c_uint32))
477 count += 1
478 else:
479 raise Exception('ERROR: Unknown relocation type %d !' % rtype)
480
481 tehdr = self.TeHdr
482 tehdr.ImageBase += delta
483 offset = self.Offset
484 fdbin[offset:offset+sizeof(tehdr)] = bytearray(tehdr)
485
486 return count
487
488 def ShowFspInfo (fspfile):
489 fd = FirmwareDevice(0, fspfile)
490 fd.ParseFd ()
491 fd.ParseFsp ()
492
493 print ("\nFound the following %d Firmware Volumes in FSP binary:" % (len(fd.FvList)))
494 for idx, fv in enumerate(fd.FvList):
495 name = fv.FvExtHdr.FvName
496 if not name:
497 name = '\xff' * 16
498 else:
499 name = str(bytearray(name))
500 guid = uuid.UUID(bytes = name)
501 print ("FV%d:" % idx)
502 print (" GUID : %s" % str(guid).upper())
503 print (" Offset : 0x%08X" % fv.Offset)
504 print (" Length : 0x%08X" % fv.FvHdr.FvLength)
505 print ("\n")
506
507 for fsp in fd.FspList:
508 fvlist = map(lambda x : 'FV%d' % x, fsp.FvIdxList)
509 print ("FSP_%s contains %s" % (fsp.Type, ','.join(fvlist)))
510 print ("%s" % (OutputStruct(fsp.Fih, 0, fsp.Fih.HeaderLength)))
511
512 def GenFspHdr (fspfile, outdir, hfile):
513 fd = FirmwareDevice(0, fspfile)
514 fd.ParseFd ()
515 fd.ParseFsp ()
516
517 if not hfile:
518 hfile = os.path.splitext(os.path.basename(fspfile))[0] + '.h'
519 fspname, ext = os.path.splitext(os.path.basename(hfile))
520 filename = os.path.join(outdir, fspname + ext)
521 hfsp = open(filename, 'w')
522 hfsp.write ('%s\n\n' % CopyRightHeaderFile)
523
524 firstfv = True
525 for fsp in fd.FspList:
526 fih = fsp.Fih
527 if firstfv:
528 hfsp.write("#define FSP_IMAGE_ID 0x%016X /* '%s' */\n" % (Bytes2Val(bytearray(fih.ImageId)), fih.ImageId))
529 hfsp.write("#define FSP_IMAGE_REV 0x%08X \n\n" % fih.ImageRevision)
530 firstfv = False
531 fv = fd.FvList[fsp.FvIdxList[0]]
532 hfsp.write ('#define FSP%s_BASE 0x%08X\n' % (fsp.Type, fih.ImageBase))
533 hfsp.write ('#define FSP%s_OFFSET 0x%08X\n' % (fsp.Type, fv.Offset))
534 hfsp.write ('#define FSP%s_LENGTH 0x%08X\n\n' % (fsp.Type, fih.ImageSize))
535
536 hfsp.close()
537
538 def SplitFspBin (fspfile, outdir, nametemplate):
539 fd = FirmwareDevice(0, fspfile)
540 fd.ParseFd ()
541 fd.ParseFsp ()
542
543 for fsp in fd.FspList:
544 ftype = fsp.Type
545 if not nametemplate:
546 nametemplate = fspfile
547 fspname, ext = os.path.splitext(os.path.basename(nametemplate))
548 filename = os.path.join(outdir, fspname + '_' + fsp.Type + ext)
549 hfsp = open(filename, 'wb')
550 print ("Ceate FSP component file '%s'" % filename)
551 for fvidx in fsp.FvIdxList:
552 fv = fd.FvList[fvidx]
553 hfsp.write(fv.FvData)
554 hfsp.close()
555
556 def RebaseFspBin (FspBinary, FspComponent, FspBase, OutputDir, OutputFile):
557 fd = FirmwareDevice(0, FspBinary)
558 fd.ParseFd ()
559 fd.ParseFsp ()
560
561 numcomp = len(FspComponent)
562 baselist = FspBase
563 if numcomp != len(baselist):
564 print "ERROR: Required number of base does not match number of FSP component !"
565 return
566
567 newfspbin = fd.FdData[:]
568
569 for idx, fspcomp in enumerate(FspComponent):
570
571 found = False
572 for fsp in fd.FspList:
573 ftype = fsp.Type.lower()
574 if ftype == fspcomp:
575 found = True
576 break
577
578 if not found:
579 print "ERROR: Could not find FSP_%c component to rebase !" % fspcomp.upper()
580 return
581
582 fspbase = baselist[idx]
583 if fspbase.startswith('0x'):
584 newbase = int(fspbase, 16)
585 else:
586 newbase = int(fspbase)
587 oldbase = fsp.Fih.ImageBase
588 delta = newbase - oldbase
589 print "Rebase FSP-%c from 0x%08X to 0x%08X:" % (ftype.upper(),oldbase,newbase)
590
591 telist = []
592 for fvidx in fsp.FvIdxList:
593 fv = fd.FvList[fvidx]
594 for ffs in fv.FfsList:
595 for sec in ffs.SecList:
596 if sec.SecHdr.Type == EFI_SECTION_TYPE.TE: # TE
597 offset = fd.Offset + fv.Offset + ffs.Offset + sec.Offset + sizeof(sec.SecHdr)
598 telist.append ((offset, len(sec.SecData) - sizeof(sec.SecHdr)))
599 elif sec.SecHdr.Type == EFI_SECTION_TYPE.PE32: # PE
600 raise Exception("ERROR: PE32 Section is not supported !")
601
602 fcount = 0
603 tecount = 0
604 for (teoffset, telen) in telist:
605 tehdr = EFI_TE_IMAGE_HEADER.from_buffer (fd.FdData, teoffset)
606 if 'VZ' != tehdr.Signature:
607 raise Exception("ERROR: Invalid TE header !")
608 te = TeImage(teoffset, fd.FdData[teoffset:teoffset + telen])
609 te.ParseReloc()
610 tecount += te.Rebase(delta, newfspbin)
611 fcount += 1
612 print " Patched %d entries in %d TE images." % (tecount, fcount)
613
614 (count, applied) = fsp.Patch(delta, newfspbin)
615 print " Patched %d entries using FSP patch table." % applied
616 if count != applied:
617 print " %d invalid entries are ignored !" % (count - applied)
618
619 if OutputFile == '':
620 filename = os.path.basename(FspBinary)
621 base, ext = os.path.splitext(filename)
622 OutputFile = base + "_%08X" % newbase + ext
623
624 fspname, ext = os.path.splitext(os.path.basename(OutputFile))
625 filename = os.path.join(OutputDir, fspname + ext)
626 fd = open(filename, "wb")
627 fd.write(newfspbin)
628 fd.close()
629
630 def main ():
631 parser = argparse.ArgumentParser()
632 subparsers = parser.add_subparsers(title='commands')
633
634 parser_rebase = subparsers.add_parser('rebase', help='rebase a FSP into a new base address')
635 parser_rebase.set_defaults(which='rebase')
636 parser_rebase.add_argument('-f', '--fspbin' , dest='FspBinary', type=str, help='FSP binary file path', required = True)
637 parser_rebase.add_argument('-c', '--fspcomp', choices=['t','m','s','o'], nargs='+', dest='FspComponent', type=str, help='FSP component to rebase', default = "['t']", required = True)
638 parser_rebase.add_argument('-b', '--newbase', dest='FspBase', nargs='+', type=str, help='Rebased FSP binary file name', default = '', required = True)
639 parser_rebase.add_argument('-o', '--outdir' , dest='OutputDir', type=str, help='Output directory path', default = '.')
640 parser_rebase.add_argument('-n', '--outfile', dest='OutputFile', type=str, help='Rebased FSP binary file name', default = '')
641
642 parser_split = subparsers.add_parser('split', help='split a FSP into multiple components')
643 parser_split.set_defaults(which='split')
644 parser_split.add_argument('-f', '--fspbin' , dest='FspBinary', type=str, help='FSP binary file path', required = True)
645 parser_split.add_argument('-o', '--outdir' , dest='OutputDir', type=str, help='Output directory path', default = '.')
646 parser_split.add_argument('-n', '--nametpl', dest='NameTemplate', type=str, help='Output name template', default = '')
647
648 parser_genhdr = subparsers.add_parser('genhdr', help='generate a header file for FSP binary')
649 parser_genhdr.set_defaults(which='genhdr')
650 parser_genhdr.add_argument('-f', '--fspbin' , dest='FspBinary', type=str, help='FSP binary file path', required = True)
651 parser_genhdr.add_argument('-o', '--outdir' , dest='OutputDir', type=str, help='Output directory path', default = '.')
652 parser_genhdr.add_argument('-n', '--hfile', dest='HFileName', type=str, help='Output header file name', default = '')
653
654 parser_info = subparsers.add_parser('info', help='display FSP information')
655 parser_info.set_defaults(which='info')
656 parser_info.add_argument('-f', '--fspbin' , dest='FspBinary', type=str, help='FSP binary file path', required = True)
657
658 args = parser.parse_args()
659 if args.which in ['rebase', 'split', 'genhdr', 'info']:
660 if not os.path.exists(args.FspBinary):
661 raise Exception ("ERROR: Could not locate FSP binary file '%s' !" % args.FspBinary)
662 if hasattr(args, 'OutputDir') and not os.path.exists(args.OutputDir):
663 raise Exception ("ERROR: Invalid output directory '%s' !" % args.OutputDir)
664
665 if args.which == 'rebase':
666 RebaseFspBin (args.FspBinary, args.FspComponent, args.FspBase, args.OutputDir, args.OutputFile)
667 elif args.which == 'split':
668 SplitFspBin (args.FspBinary, args.OutputDir, args.NameTemplate)
669 elif args.which == 'genhdr':
670 GenFspHdr (args.FspBinary, args.OutputDir, args.HFileName)
671 elif args.which == 'info':
672 ShowFspInfo (args.FspBinary)
673 else:
674 pass
675
676 return 0
677
678 if __name__ == '__main__':
679 sys.exit(main())