View difference between Paste ID: f604e244a and
SHOW: | | - or go back to the newest paste.
1-
1+
#!/usr/bin/python
2
3
import sys, struct
4
5
#VSS_OFFSET = 0x00180048
6
#VSS_SIZE = 0x4000 - 0x48
7
VSS_OFFSET = 0x000c0048
8
VSS_SIZE = 0x3f58
9
10
#PATCH_OFFSET = 0x1af
11
PATCH_OFFSET = 0xae
12
PATCH_VALUE = 0x01
13
PATCH_VARIABLE = u"Setup"
14
15
def hexdump(s,sep=" "):
16
	return sep.join(map(lambda x: "%02x"%ord(x),s))
17
18
def ascii(s):
19
	s2 = ""
20
	for c in s:
21
		if ord(c)<0x20 or ord(c)>0x7e:
22
			s2 += "."
23
		else:
24
			s2 += c
25
	return s2
26
27
def pad(s,c,l):
28
	if len(s)<l:
29
		s += c * (l-len(s))
30
	return s
31
32
def chexdump(s,ts=""):
33
	for i in range(0,len(s),16):
34
		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))
35
36
def addup(s):
37
	if len(s) & 1:
38
		s = s + "\x00"
39
	sum = 0
40
	while len(s):
41
		sum += struct.unpack("<H",s[:2])[0]
42
		s = s[2:]
43
	return sum &0xFFFF
44
45
class VAR(object):
46
	GLOBAL_VARIABLE = "\x61\xdf\xe4\x8b\xca\x93\xd2\x11\xaa\x0d\x00\xe0\x98\x03\x2b\x8c"
47
	def __init__(self, data):
48
		hdr = data[:0x20]
49
		self.magic, self.status, self.attributes, self.nsize, self.dsize, self.guid = struct.unpack("<HHIII16s", hdr)
50
		if self.magic != 0x55aa:
51
			raise ValueError("bad magic 0x%x"%self.magic)
52
		self.bname = data[0x20:0x20+self.nsize]
53
		self.name = ''.join(data[0x20:0x20+self.nsize:2])
54
		self.name = self.name.split("\x00")[0]
55
		self.value = data[0x20+self.nsize:0x20+self.nsize+self.dsize]
56
		self.data = data[:0x20+self.nsize+self.dsize]
57
		cdata = data[:0x20] + "\x00\x00" + data[0x20:]
58
		fdata = "\xaa\x55\x7f\x00" + cdata[4:0x20+self.nsize+self.dsize]
59
	def update(self):
60
		self.nsize = len(self.name) * 2 + 2
61
                self.dsize = len(self.value)
62
		self.data = struct.pack("<HHIII16s", self.magic, self.status, self.attributes, self.nsize, self.dsize, self.guid)
63
		self.data += self.name.encode('utf-16le') + "\x00\x00"
64
		self.data += self.value
65
		fdata = "\xaa\x55\x7f\x00" + self.data[4:0x20+self.nsize+self.dsize]
66
                self.data = self.data[:0x20] + self.data[0x20:] 
67
	def showinfo(self, ts=''):
68
		print ts+"Variable %s"%repr(self.name)
69
		print ts+" Attributes: 0x%08x"%self.attributes
70
		print ts+" Status: 0x%02x"%self.status
71
		if self.guid == self.GLOBAL_VARIABLE:
72
			print ts+" VendorGUID: EFI_GLOBAL_VARIABLE (%s)"%' '.join('%02x'%ord(c) for c in self.guid)
73
		else:
74
			print ts+" VendorGUID: %s"%' '.join('%02x'%ord(c) for c in self.guid)
75
		print ts+" Value (0x%x bytes):"%(len(self.value))
76
		chexdump(self.value, ts+"  ")
77
78
print "Loading BIOS..."
79
bin = open(sys.argv[1], "rb").read()
80
81
print "Loading VSS..."
82
vss = bin[VSS_OFFSET:VSS_OFFSET+VSS_SIZE]
83
84
if vss[:4] != "$VSS":
85
	raise ValueError("Invalid VSS signature")
86
87
off = 0x10
88
89
found = False
90
91
while not found and vss[off:off+2] == "\xaa\x55":
92
	var = VAR(vss[off:])
93
	if var.name == PATCH_VARIABLE and var.status == 0x7f:
94
		found = True
95
	else:
96
		off += len(var.data)
97
98
if not found:
99
	#print "Variable not found!"
100
	raise ValueError("Variable not found!")
101
102
print "Old state:"
103
var.showinfo()
104
105
var.value = var.value[:PATCH_OFFSET] + chr(PATCH_VALUE) + var.value[PATCH_OFFSET+1:]
106
var.update()
107
print "Patched state:"
108
var = VAR(var.data)
109
var.showinfo()
110
111
print "Updating VSS..."
112
vss = vss[:off] + var.data + vss[off+len(var.data):]
113
114
print "Updating BIOS..."
115
bin = bin[:VSS_OFFSET] + vss + bin[VSS_OFFSET+VSS_SIZE:]
116
117
print "Writing output..."
118
ofd = open(sys.argv[2], "wb")
119
ofd.write(bin)
120
ofd.close()
121
122
print "Done"