Version 0.1.2
[people/mcb30/legacybios.git] / tools / buildrom.py
1 #!/usr/bin/env python
2 # Script to merge a rom32.bin file into a rom16.bin file.
3 #
4 # Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
5 #
6 # This file may be distributed under the terms of the GNU GPLv3 license.
7
8 import sys
9 import struct
10
11 ROM16='out/rom16.bin'
12 ROM32='out/rom32.bin'
13 OFFSETS16='out/rom16.offset.auto.h'
14 OFFSETS32='out/rom32.offset.auto.h'
15 OUT='out/rom.bin'
16
17 def align(v, a):
18     return (v + a - 1) // a * a
19
20 def scanconfig(file):
21     f = open(file, 'rb')
22     opts = {}
23     for l in f.readlines():
24         parts = l.split()
25         if len(parts) != 3:
26             continue
27         if parts[0] != '#define':
28             continue
29         opts[parts[1]] = parts[2]
30     return opts
31
32 def alteraddr(data, offset, ptr):
33     rel = struct.pack("<i", ptr)
34     return data[:offset] + rel + data[offset+4:]
35
36
37 def main():
38     # Read in files
39     f = open(ROM16, 'rb')
40     data16 = f.read()
41     f = open(ROM32, 'rb')
42     data32 = f.read()
43
44     if len(data16) != 65536:
45         print "16bit code is not 65536 bytes long"
46         sys.exit(1)
47
48     # Get config options
49     o16 = scanconfig(OFFSETS16)
50     o32 = scanconfig(OFFSETS32)
51
52     # Inject 32bit code
53     spos = align(int(o16['OFFSET_bios16c_end'], 16), 16)
54     epos = int(o16['OFFSET_post16'], 16)
55     size32 = len(data32)
56     freespace = epos - spos
57     if size32 > freespace:
58         print "32bit code too large (%d vs %d)" % (size32, freespace)
59         sys.exit(1)
60     outrom = data16[:spos] + data32 + data16[spos+size32:]
61
62     # Fixup initial jump to 32 bit code
63     jmppos = int(o16['OFFSET_set_entry32'], 16)
64     start32 = int(o32['OFFSET__start'], 16)
65     outrom = alteraddr(outrom, jmppos+2, start32)
66
67     # Write output rom
68     f = open(OUT, 'wb')
69     f.write(outrom)
70     f.close()
71
72 if __name__ == '__main__':
73     main()