#!/usr/bin/env python
-# Script to merge a rom32.bin file into a rom16.bin file.
+# Fill in checksum/size of an option rom, and pad it to proper length.
#
-# Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+# Copyright (C) 2009 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import sys
-import struct
-ROM16='out/rom16.bin'
-ROM32='out/rom32.bin'
-OFFSETS16='out/rom16.offset.auto.h'
-OFFSETS32='out/rom32.offset.auto.h'
-OUT='out/rom.bin'
-
-def align(v, a):
- return (v + a - 1) // a * a
-
-def scanconfig(file):
- f = open(file, 'rb')
- opts = {}
- for l in f.readlines():
- parts = l.split()
- if len(parts) != 3:
- continue
- if parts[0] != '#define':
- continue
- opts[parts[1]] = parts[2]
- return opts
-
-def alteraddr(data, offset, ptr):
- rel = struct.pack("<i", ptr)
- return data[:offset] + rel + data[offset+4:]
+def alignpos(pos, alignbytes):
+ mask = alignbytes - 1
+ return (pos + mask) & ~mask
+def checksum(data):
+ ords = map(ord, data)
+ return sum(ords)
def main():
- # Read in files
- f = open(ROM16, 'rb')
- data16 = f.read()
- f = open(ROM32, 'rb')
- data32 = f.read()
+ inname = sys.argv[1]
+ outname = sys.argv[2]
- if len(data16) != 65536:
- print "16bit code is not 65536 bytes long"
- sys.exit(1)
+ # Read data in
+ f = open(inname, 'rb')
+ data = f.read()
+ count = len(data)
- # Get config options
- o16 = scanconfig(OFFSETS16)
- o32 = scanconfig(OFFSETS32)
+ # Pad to a 512 byte boundary
+ data += "\0" * (alignpos(count, 512) - count)
+ count = len(data)
- # Inject 32bit code
- spos = align(int(o16['OFFSET_bios16c_end'], 16), 16)
- epos = int(o16['OFFSET_post16'], 16)
- size32 = len(data32)
- freespace = epos - spos
- if size32 > freespace:
- print "32bit code too large (%d vs %d)" % (size32, freespace)
- sys.exit(1)
- outrom = data16[:spos] + data32 + data16[spos+size32:]
+ # Check if a pci header is present
+ pcidata = ord(data[24:25]) + (ord(data[25:26]) << 8)
+ if pcidata != 0:
+ data = data[:pcidata + 16] + chr(count/512) + chr(0) + data[pcidata + 18:]
- # Fixup initial jump to 32 bit code
- jmppos = int(o16['OFFSET_set_entry32'], 16)
- start32 = int(o32['OFFSET__start'], 16)
- outrom = alteraddr(outrom, jmppos+2, start32)
+ # Fill in size field; clear checksum field
+ data = data[:2] + chr(count/512) + data[3:6] + "\0" + data[7:]
- # Fixup resume from 16 jump to 32 bit code
- jmppos = int(o16['OFFSET_set_resume32'], 16)
- resume32 = int(o32['OFFSET_call16_resume'], 16)
- outrom = alteraddr(outrom, jmppos+2, resume32)
+ # Checksum rom
+ newsum = (256 - checksum(data)) & 0xff
+ data = data[:6] + chr(newsum) + data[7:]
- # Write output rom
- f = open(OUT, 'wb')
- f.write(outrom)
- f.close()
+ # Write new rom
+ f = open(outname, 'wb')
+ f.write(data)
if __name__ == '__main__':
main()