#!/usr/bin/python
import sys, struct

class FV(object):
	def __init__(self, data):
		hdr = data[:0x38]
		self.rsvd, self.guid, self.size, self.magic, self.attributes, self.hdrlen, self.checksum, self.rsvd2, self.revision = struct.unpack("<16s16sQ4sIHH3sB", hdr)
		if self.magic != '_FVH':
			raise ValueError("bad magic %s"%repr(self.magic))
		data = data[:self.size]
		self.data = data[self.hdrlen:]
		self.blocks = []
		bdata = data[0x38:self.hdrlen]
		while len(bdata):
			bl = bdata[:8]
			numb, blen = struct.unpack("<II",bl)
			if (numb, blen) == (0,0):
				break
			self.blocks.append((numb, blen))
			bdata = bdata[8:]
	def showinfo(self, ts=''):
		print ts+"Reserved boot zone:", ' '.join('%02x'%ord(c) for c in self.rsvd)
		print ts+"GUID:", ' '.join('%02x'%ord(c) for c in self.guid)
		print ts+"Size: 0x%x (data 0x%x)"%(self.size,len(self.data))
		print ts+"Attributes: 0x%08x"%self.attributes
		print ts+"Revision: %d"%self.revision
		print ts+"Blocks:"
		for numb, blen in self.blocks:
			print ts+" %d: len 0x%x"%(numb,blen)

if __name__ == "__main__":
	f = open(sys.argv[1],"rb")
	
	d = f.read()
	
	for start in range(32,len(d),16):
		if d[start+8:start+12] == '_FVH':
			start -= 32
			print "Firmware Volume at %08x"%start
			fv = FV(d[start:])
			fv.showinfo(' ')
			fn = "fv-%08x.bin"%start
			print "Dumping to %s"%fn
			fout = open(fn,"wb")
			fout.write(fv.data)
			fout.close()

