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

def hexdump(s,sep=" "):
	return sep.join(map(lambda x: "%02x"%ord(x),s))

def ascii(s):
	s2 = ""
	for c in s:
		if ord(c)<0x20 or ord(c)>0x7e:
			s2 += "."
		else:
			s2 += c
	return s2

def pad(s,c,l):
	if len(s)<l:
		s += c * (l-len(s))
	return s

def chexdump(s,ts=""):
	for i in range(0,len(s),16):
		print ts+"%08x  %s  %s  |%s|"%(i,pad(hexdump(s[i:i+8],' ')," ",23),pad(hexdump(s[i+8:i+16],' ')," ",23),pad(ascii(s[i:i+16])," ",16))

def addup(s):
	if len(s) & 1:
		s = s + "\x00"
	sum = 0
	while len(s):
		sum += struct.unpack("<H",s[:2])[0]
		s = s[2:]
	return sum &0xFFFF

class VAR(object):
	GLOBAL_VARIABLE = "\x61\xdf\xe4\x8b\xca\x93\xd2\x11\xaa\x0d\x00\xe0\x98\x03\x2b\x8c"
	def __init__(self, data):
		hdr = data[:0x22]
		self.magic, self.iter, self.attributes, self.nsize, self.dsize, self.guid, self.checksum = struct.unpack("<HHIII16sH", hdr)
		if self.magic != 0x55aa:
			raise ValueError("bad magic 0x%x"%self.magic)
		self.bname = data[0x22:0x22+self.nsize]
		self.name = ''.join(data[0x22:0x22+self.nsize:2])
		self.name = self.name.split("\x00")[0]
		self.value = data[0x22+self.nsize:0x22+self.nsize+self.dsize]
		self.rest = data[0x22+self.nsize+self.dsize:]
		cdata = data[:0x20] + "\x00\x00" + data[0x22:]
		fdata = "\xaa\x55\x7f\x00" + cdata[4:0x22+self.nsize+self.dsize]
		self.ccsum = (-addup(fdata)) & 0xFFFF
		if self.ccsum != self.checksum:
			raise ValueError("Checksum error")
	def showinfo(self, ts=''):
		print ts+"Variable %s"%repr(self.name)
		print ts+" Attributes: 0x%08x"%self.attributes
		print ts+" Iteration: 0x%02x"%self.iter
		if self.guid == self.GLOBAL_VARIABLE:
			print ts+" VendorGUID: EFI_GLOBAL_VARIABLE (%s)"%' '.join('%02x'%ord(c) for c in self.guid)
		else:
			print ts+" VendorGUID: %s"%' '.join('%02x'%ord(c) for c in self.guid)
		print ts+" Checksum: 0x%02x"%self.checksum
		print ts+"  calc 0x%04x"%self.ccsum
		print ts+" Value (0x%x bytes):"%(len(self.value))
		chexdump(self.value, ts+"  ")

f = open(sys.argv[1],"rb")

d = f.read()

hdr = d[:16]

if hdr[:4] != '$VSS':
	raise ValueError("Bad header")

size, unk = struct.unpack("II",hdr[4:12])

vdb = d[16:size]

vdbt = {}

while vdb[:2] == "\xaa\x55":
	v = VAR(vdb)
	vdb = v.rest
	if v.name not in vdbt or vdbt[v.name].iter <= v.iter:
		vdbt[v.name] = v
	v.showinfo()

#for k in sorted(vdbt):
	#vdbt[k].showinfo()

