Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 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 |
Kevin O'Connor | 4b39b82 | 2008-05-08 21:47:33 -0400 | [diff] [blame] | 10 | import os |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 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' |
Kevin O'Connor | 59fead6 | 2008-05-10 15:49:20 -0400 | [diff] [blame] | 16 | OUT='out/bios.bin' |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 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) |
Kevin O'Connor | bdce35f | 2008-02-26 21:33:14 -0500 | [diff] [blame] | 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) |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 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 | |
Kevin O'Connor | bdce35f | 2008-02-26 21:33:14 -0500 | [diff] [blame] | 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 | |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 77 | # Write output rom |
| 78 | f = open(OUT, 'wb') |
| 79 | f.write(outrom) |
| 80 | f.close() |
| 81 | |
Kevin O'Connor | 4b39b82 | 2008-05-08 21:47:33 -0400 | [diff] [blame] | 82 | # Build elf file with 32bit entry point |
| 83 | os.system( |
Kevin O'Connor | 59fead6 | 2008-05-10 15:49:20 -0400 | [diff] [blame] | 84 | "ld -melf_i386 -e %s -Ttext 0xf0000 -b binary %s -o %s" % ( |
| 85 | int(o32['OFFSET_post32'], 16), OUT, OUT+".elf")) |
Kevin O'Connor | 4b39b82 | 2008-05-08 21:47:33 -0400 | [diff] [blame] | 86 | |
Kevin O'Connor | f076a3e | 2008-02-25 22:25:15 -0500 | [diff] [blame] | 87 | if __name__ == '__main__': |
| 88 | main() |