Fixup bios.bin.elf building on other versions of ld.
[seabios.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 import os
11
12 ROM16='out/rom16.bin'
13 ROM32='out/rom32.bin'
14 OFFSETS16='out/rom16.offset.auto.h'
15 OFFSETS32='out/rom32.offset.auto.h'
16 OUT='out/bios.bin'
17
18 def align(v, a):
19     return (v + a - 1) // a * a
20
21 def scanconfig(file):
22     f = open(file, 'rb')
23     opts = {}
24     for l in f.readlines():
25         parts = l.split()
26         if len(parts) != 3:
27             continue
28         if parts[0] != '#define':
29             continue
30         opts[parts[1]] = parts[2]
31     return opts
32
33 def alteraddr(data, offset, ptr):
34     rel = struct.pack("<i", ptr)
35     return data[:offset] + rel + data[offset+4:]
36
37
38 def main():
39     # Read in files
40     f = open(ROM16, 'rb')
41     data16 = f.read()
42     f = open(ROM32, 'rb')
43     data32 = f.read()
44
45     if len(data16) != 65536:
46         print "16bit code is not 65536 bytes long"
47         sys.exit(1)
48
49     # Get config options
50     o16 = scanconfig(OFFSETS16)
51     o32 = scanconfig(OFFSETS32)
52
53     # Inject 32bit code
54     spos = align(int(o16['OFFSET_bios16c_end'], 16), 16)
55     epos = int(o16['OFFSET_post16'], 16)
56     size32 = len(data32)
57     freespace = epos - spos
58     if size32 > freespace:
59         print "32bit code too large (%d vs %d)" % (size32, freespace)
60         sys.exit(1)
61     if data16[spos:spos+size32] != '\0'*size32:
62         print "Non zero data in 16bit freespace (%d to %d)" % (
63             spos, spos+size32)
64         sys.exit(1)
65     outrom = data16[:spos] + data32 + data16[spos+size32:]
66
67     # Fixup initial jump to 32 bit code
68     jmppos = int(o16['OFFSET_set_entry32'], 16)
69     start32 = int(o32['OFFSET__start'], 16)
70     outrom = alteraddr(outrom, jmppos+2, start32)
71
72     print "Writing output rom %s" % OUT
73     print " 16bit C-code size: %d" % spos
74     print " 32bit C-code size: %d" % size32
75     print " Total C-code size: %d" % (spos+size32)
76
77     # Write output rom
78     f = open(OUT, 'wb')
79     f.write(outrom)
80     f.close()
81
82     # Build elf file with 32bit entry point
83     os.system(
84         "ld -melf_i386 -e %s -Tdata 0xf0000 -b binary %s -o %s" % (
85             int(o32['OFFSET_post32'], 16), OUT, OUT+".elf"))
86
87 if __name__ == '__main__':
88     main()