Allow rom to grow beyond 64K.

If rom is over 64K then use part of e-segment for 32bit code.
Push 32bit code as high as it can go in the f-segment.
Do version building before layoutrom.py - this way layoutrom knows
    full size of rom.
Make layoutrom.py build the full ld script - remove now unused ld
    scripts that just imported the output of layoutrom.py.
Also, use "objdump" instead of "nm" - reduce toolchain requirements.
Enhance tools/checkrom.py so that it can pad bios.bin to size qemu is
    happy with.
Also, add dependencies to build rules for local tools - if tool
    changes automatically rerun it.
Make sure option roms don't overwrite the 32bit code (should the 32bit
    code be in the e-segment).
Make sure shadow code works even if part of the code is in the
    e-segment.
diff --git a/tools/checkrom.py b/tools/checkrom.py
index 7dc5afc..b1d732a 100755
--- a/tools/checkrom.py
+++ b/tools/checkrom.py
@@ -6,33 +6,56 @@
 # This file may be distributed under the terms of the GNU GPLv3 license.
 
 import sys
+import layoutrom
 
 def main():
-    # Read in symbols (that are valid)
-    syms = {}
-    for line in sys.stdin.readlines():
-        try:
-            addr, type, sym = line.split()
-            syms[sym] = int(addr, 16)
-        except:
-            pass
+    # Get args
+    objinfo, rawfile, outfile = sys.argv[1:]
 
+    # Read in symbols
+    objinfofile = open(objinfo, 'rb')
+    symbols = layoutrom.parseObjDump(objinfofile)[1]
+    syms = {}
+    for name, (addr, section) in symbols.items():
+        syms[name] = addr
+
+    # Read in raw file
+    f = open(rawfile, 'rb')
+    rawdata = f.read()
+    f.close()
+    datasize = len(rawdata)
+    finalsize = 64*1024
+    if datasize > 64*1024:
+        finalsize = 128*1024
+
+    # Sanity checks
     c16e = syms['code16_end'] + 0xf0000
     f16e = syms['final_code16_end']
     if c16e != f16e:
         print "Error!  16bit code moved during linking (0x%x vs 0x%x)" % (
             c16e, f16e)
         sys.exit(1)
+    if datasize > finalsize:
+        print "Error!  Code is too big (0x%x vs 0x%x)" % (
+            datasize, finalsize)
+        sys.exit(1)
 
+    # Print statistics
     sizefree = syms['freespace_end'] - syms['freespace_start']
     size16 = syms['code16_end'] - syms['code16_start']
     size32 = syms['code32_end'] - syms['code32_start']
     totalc = size16+size32
     print "16bit size: %d" % size16
     print "32bit size: %d" % size32
-    print "Total size: %d  Free space: %d  Percent used: %.1f%%" % (
-        totalc, sizefree
-        , (totalc / float(size16+size32+sizefree)) * 100.0)
+    print "Total size: %d  Free space: %d  Percent used: %.1f%% (%dKiB rom)" % (
+        totalc, sizefree + finalsize - datasize
+        , (totalc / float(finalsize)) * 100.0
+        , finalsize / 1024)
+
+    # Write final file
+    f = open(outfile, 'wb')
+    f.write(("\0" * (finalsize - datasize)) + rawdata)
+    f.close()
 
 if __name__ == '__main__':
     main()
diff --git a/tools/layoutrom.py b/tools/layoutrom.py
index 8d557bc..da2940f 100755
--- a/tools/layoutrom.py
+++ b/tools/layoutrom.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# Script to arrange sections to ensure fixed offsets.
+# Script to analyze code and arrange ld sections.
 #
 # Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
 #
@@ -7,18 +7,49 @@
 
 import sys
 
-
+# Align 'pos' to 'alignbytes' offset
 def alignpos(pos, alignbytes):
     mask = alignbytes - 1
     return (pos + mask) & ~mask
 
+# LD script headers/trailers
+COMMONHEADER = """
+/* DO NOT EDIT!  This is an autogenerated file.  See tools/layoutrom.py. */
+OUTPUT_FORMAT("elf32-i386")
+OUTPUT_ARCH("i386")
+SECTIONS
+{
+"""
+COMMONTRAILER = """
+}
+"""
+
 
 ######################################################################
 # 16bit fixed address section fitting
 ######################################################################
 
-MAXPOS = 0x10000
+# Get the maximum start position for a list of sections that end at an
+# address.
+def getSectionsStart(sections, endaddr, minalign=1):
+    totspace = 0
+    for size, align, name in sections:
+        if align > minalign:
+            minalign = align
+        totspace = alignpos(totspace, align) + size
+    return (endaddr - totspace) / minalign * minalign
 
+# Write LD script includes for the given sections
+def outSections(file, sections):
+    for size, align, name in sections:
+        file.write("*(%s)\n" % (name,))
+
+# The 16bit code can't exceed 64K of space.
+MAXPOS = 64*1024
+
+# Layout the 16bit code.  This ensures sections with fixed offset
+# requirements are placed in the correct location.  It also places the
+# 16bit code as high as possible in the f-segment.
 def doLayout16(sections, outname):
     textsections = []
     rodatasections = []
@@ -103,18 +134,6 @@
 #                , fitnextaddr, nextfixedaddr - fitnextaddr)
     firstfixed = fixedsections[0][0]
 
-    # Find overall start position
-    restalign = 0
-    restspace = 0
-    restsections = []
-    for section in textsections + rodatasections + datasections:
-        size, align, name = section
-        if align > restalign:
-            restalign = align
-        restspace = alignpos(restspace, align) + size
-        restsections.append(section)
-    startrest = (firstfixed - restspace) / restalign * restalign
-
     # Report stats
     total = MAXPOS-firstfixed
     slack = total - totalused
@@ -123,20 +142,23 @@
             firstfixed, MAXPOS, total, slack,
             (float(slack) / total) * 100.0))
 
+    # Find overall start position
+    start16 = getSectionsStart(
+        textsections + rodatasections + datasections, firstfixed)
+
     # Write header
     output = open(outname, 'wb')
-    output.write("""
+    output.write(COMMONHEADER + """
         .text16 0x%x : {
                 code16_start = ABSOLUTE(.) ;
                 freespace_end = . ;
-""" % startrest)
+""" % start16)
 
     # Write regular sections
-    for section in restsections:
-        name = section[2]
-        if rodatasections and name == rodatasections[0][2]:
-            output.write("code16_rodata = . ;\n")
-        output.write("*(%s)\n" % (name,))
+    outSections(output, textsections)
+    output.write("code16_rodata = . ;\n")
+    outSections(output, rodatasections)
+    outSections(output, datasections)
 
     # Write fixed sections
     for addr, section, extrasections in fixedsections:
@@ -150,32 +172,66 @@
     output.write("""
                 code16_end = ABSOLUTE(.) ;
         }
-""")
+
+        /* Discard regular data sections to force a link error if
+         * 16bit code attempts to access data not marked with VAR16
+         */
+        /DISCARD/ : { *(.text*) *(.rodata*) *(.data*) *(.bss*) *(COMMON) }
+""" + COMMONTRAILER)
+
+    return start16
 
 
 ######################################################################
 # 32bit section outputting
 ######################################################################
 
-def outsections(file, sections, prefix):
+# Return the subset of sections with a given name prefix
+def getSectionsPrefix(sections, prefix):
     lp = len(prefix)
+    out = []
     for size, align, name in sections:
         if name[:lp] == prefix:
-            file.write("*(%s)\n" % (name,))
+            out.append((size, align, name))
+    return out
 
-def doLayout32(sections, outname):
+# Layout the 32bit code.  This places the code as high as possible.
+def doLayout32(sections, outname, start16):
+    start16 += 0xf0000
+    # Find sections to output
+    textsections = getSectionsPrefix(sections, '.text.')
+    rodatasections = getSectionsPrefix(sections, '.rodata')
+    datasections = getSectionsPrefix(sections, '.data.')
+    bsssections = getSectionsPrefix(sections, '.bss.')
+    start32 = getSectionsStart(
+        textsections + rodatasections + datasections + bsssections, start16, 512)
+
+    # Write sections
     output = open(outname, 'wb')
-    outsections(output, sections, '.text.')
+    output.write(COMMONHEADER + """
+        .text32 0x%x : {
+                code32_start = ABSOLUTE(.) ;
+""" % start32)
+
+    outSections(output, textsections)
     output.write("code32_rodata = . ;\n")
-    outsections(output, sections, '.rodata')
-    outsections(output, sections, '.data.')
-    outsections(output, sections, '.bss.')
+    outSections(output, rodatasections)
+    outSections(output, datasections)
+    outSections(output, bsssections)
+
+    output.write("""
+                freespace_start = . ;
+                code32_end = ABSOLUTE(.) ;
+        }
+""" + COMMONTRAILER)
 
 
 ######################################################################
 # Section garbage collection
 ######################################################################
 
+# Note required section, and recursively set all referenced sections
+# as required.
 def keepsection(name, pri, alt):
     if name in pri[3]:
         # Already kept - nothing to do.
@@ -186,15 +242,18 @@
         return
     # Keep all sections that this section points to
     for symbol in relocs:
-        section = pri[1].get(symbol)
-        if section is not None and section[:9] != '.discard.':
+        addr, section = pri[1].get(symbol, (None, None))
+        if (section is not None and '*' not in section
+            and section[:9] != '.discard.'):
             keepsection(section, pri, alt)
             continue
         # Not in primary sections - it may be a cross 16/32 reference
-        section = alt[1].get(symbol)
-        if section is not None:
+        addr, section = alt[1].get(symbol, (None, None))
+        if section is not None and '*' not in section:
             keepsection(section, alt, pri)
 
+# Determine which sections are actually referenced and need to be
+# placed into the output file.
 def gc(info16, info32):
     # pri = (sections, symbols, relocs, keep sections)
     pri = (info16[0], info16[1], info16[2], [])
@@ -261,8 +320,8 @@
             try:
                 section, off, symbol = line[17:].split()
                 off = int(off, 16)
-                if '*' not in section:
-                    symbols[symbol] = section
+                addr = int(line[:8], 16)
+                symbols[symbol] = addr, section
             except:
                 pass
             continue
@@ -287,8 +346,8 @@
 
     sections16, sections32 = gc(info16, info32)
 
-    doLayout16(sections16, out16)
-    doLayout32(sections32, out32)
+    start16 = doLayout16(sections16, out16)
+    doLayout32(sections32, out32, start16)
 
 if __name__ == '__main__':
     main()