Try to automatically fit sections into open spaces in the fixed area.
authorKevin O'Connor <kevin@koconnor.net>
Sat, 17 Jan 2009 20:17:34 +0000 (15:17 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Sat, 17 Jan 2009 20:17:34 +0000 (15:17 -0500)
Enhance layoutrom.py script to find and locate sections into fixed area.
Have layoutrom.py create output file instead of using redirect from make.
Don't use freespace2 for bios tables in f segment - freespace in fixed
    area is now automatically filled.
Change checkrom script to test final_code16_end instead of _start -
    this improves catching of alignment errors.
Don't align gdt to 8 bytes - it causes whole section to be aligned,
    which causes entry point to be misaligned.
Explicitly reserve space for variables in fixed area so that the space
    for them is not auto-filled.

Makefile
src/memmap.c
src/rombios.lds.S
src/rombios16.lds.S
src/romlayout.S
tools/checkrom.py
tools/layoutrom.py

index 424dd0bb5dee1120a894a3938b9cd9e7da4aed24..f69ed834856cfe74cc7fb2cb898a47a65e013387 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -107,7 +107,7 @@ $(OUT)rom32.o: $(OUT)ccode32.o $(OUT)rombios32.lds
 
 $(OUT)romlayout.lds: $(OUT)romlayout16.o
        @echo "  Building layout information $@"
-       $(Q)$(OBJDUMP) -h $< | ./tools/layoutrom.py $@
+       $(Q)$(OBJDUMP) -h $< | ./tools/layoutrom.py $@
 
 $(OUT)rombios16.lds: $(OUT)romlayout.lds
 
index 372ec5284eec18c42995ceffb66ef5bd63956402..01b00d89af6f617cb35b7d58b26ae1c8b19710db 100644 (file)
@@ -123,7 +123,7 @@ add_e820(u64 start, u64 size, u32 type)
 }
 
 // Symbols defined in romlayout.S
-extern char freespace2_start, freespace2_end;
+extern char freespace1_start, freespace1_end;
 
 u32 bios_table_cur_addr, bios_table_end_addr;
 
@@ -131,8 +131,8 @@ u32 bios_table_cur_addr, bios_table_end_addr;
 void
 memmap_setup()
 {
-    bios_table_cur_addr = (u32)&freespace2_start;
-    bios_table_end_addr = (u32)&freespace2_end;
+    bios_table_cur_addr = (u32)&freespace1_start;
+    bios_table_end_addr = (u32)&freespace1_end;
     dprintf(1, "bios_table_addr: 0x%08x end=0x%08x\n",
             bios_table_cur_addr, bios_table_end_addr);
 
@@ -155,8 +155,8 @@ memmap_finalize()
 
     dprintf(1, "final bios_table_addr: 0x%08x (used %d%%)\n"
             , bios_table_cur_addr
-            , (100 * (bios_table_cur_addr - (u32)&freespace2_start)
-               / ((u32)&freespace2_end - (u32)&freespace2_start)));
+            , (100 * (bios_table_cur_addr - (u32)&freespace1_start)
+               / ((u32)&freespace1_end - (u32)&freespace1_start)));
     if (bios_table_cur_addr > bios_table_end_addr)
         BX_PANIC("bios_table_end_addr overflow!\n");
 }
index c17d0f059db966d4db0685d90eef2a61d36f20f6..61a04c4623fc4d8aa2774cf1d54c6a517f020724 100644 (file)
@@ -15,8 +15,8 @@ SECTIONS
                 *(.text)
 
                 . = code16_start ;
-                final_code16_start = . ;
                 *(.text16)
+                final_code16_end = . ;
                 }
         /DISCARD/ : { *(.discard*) }
 }
index 074d5f1d5c754b6274325c4875df0cdc3e6be866..61de42163e6db0bd7e034e5efb0f2b7e74161fee 100644 (file)
@@ -11,6 +11,7 @@ OUTPUT_ARCH("i386")
 SECTIONS
 {
         . = ( _code32_code32_end - BUILD_BIOS_ADDR ) ;
+        . = ALIGN(16) ;
         code16_start = . ;
         .text16 : {
 
index 4db9dfeeda732384b8c4ec6310c53302b408d106..e8cc9b4c84d50a8b1e5b000cd9797747d7aea633 100644 (file)
@@ -487,7 +487,7 @@ rombios32_gdt_48:
         .word (rombios32_gdt_end - rombios32_gdt)
         .long (BUILD_BIOS_ADDR + rombios32_gdt)
 
-        .balign 8
+        //.balign 8
         .type rombios32_gdt, @object
 rombios32_gdt:
         .word 0, 0, 0, 0
@@ -520,6 +520,7 @@ entry_13_official:
         .type __fdpt, @object
 __fdpt:
         // XXX - Fixed Disk Parameter Table
+        .space 16
 
         ORG 0xe6f2
         .global entry_19_official
@@ -534,6 +535,7 @@ entry_19_official:
         .type __brgt, @object
 __brgt:
         // XXX - Baud Rate Generator Table
+        .space 16
 
         ORG 0xe739
         IRQ_ENTRY_ARG 14
@@ -571,11 +573,7 @@ __int1d:
         // XXX - INT 1D - SYSTEM DATA - VIDEO PARAMETER TABLES
         .space 0x58
 
-        .global freespace2_start, freespace2_end
-freespace2_start:
-
         ORG 0xf841
-freespace2_end:
         .global entry_12_official
 entry_12_official:
         jmp entry_12
@@ -626,6 +624,7 @@ entry_18:
         ORG 0xfef3
 __initvector:
         // XXX - Initial Interrupt Vector Offsets Loaded by POST
+        .space 13
 
         ORG 0xff00
         .type __copyright, @object
index 6b5f1e9f26d34df5a8ed88d6e65d2a9f397f9e66..d03c794c98722785d7508376006b727f7afef075 100755 (executable)
@@ -17,24 +17,22 @@ def main():
         except:
             pass
 
-    c16s = syms['code16_start'] + 0xf0000
-    c32s = syms['final_code16_start']
-    if c16s != c32s:
+    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)" % (
-            c32s, c16s)
+            c16e, f16e)
         sys.exit(1)
 
     sizefree = syms['freespace1_end'] - syms['freespace1_start']
     size16 = syms['code16_end'] - syms['code16_start'] - sizefree
     size32 = syms['code32_end'] - syms['code32_start']
     totalc = size16+size32
-    tablefree = syms['freespace2_end'] - syms['freespace2_start']
     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 "BIOS table space:  %d" % tablefree
 
 if __name__ == '__main__':
     main()
index f1fe0e105823221e406cc462d912fc1c4aaa40a9..592893b63c651a6b93ce95e137d9328d86e6d13c 100755 (executable)
 import sys
 
 def main():
-    # Read in section names and sizes
+    # Get output name
+    outname = sys.argv[1]
 
-    # sections = [(idx, name, size, align), ...]
+    # Read in section names and sizes
+    # sections = [(size, align, name), ...]
     sections = []
     for line in sys.stdin.readlines():
         try:
             idx, name, size, vma, lma, fileoff, align = line.split()
             if align[:3] != '2**':
                 continue
-            sections.append((
-                int(idx), name, int(size, 16), int(align[3:])))
+            sections.append((int(size, 16), 2**int(align[3:]), name))
         except:
             pass
 
-    # fixedsections = [(addr, sectioninfo), ...]
-    fixedsections = []
+    doLayout(sections, outname)
+
+def alignpos(pos, alignbytes):
+    mask = alignbytes - 1
+    return (pos + mask) & ~mask
+
+def doLayout(sections, outname):
     textsections = []
     rodatasections = []
     datasections = []
+    # fixedsections = [(addr, sectioninfo, extasectionslist), ...]
+    fixedsections = []
+    # canrelocate = [(sectioninfo, list), ...]
+    canrelocate = []
 
     # Find desired sections.
     for section in sections:
-        name = section[1]
+        size, align, name = section
         if name[:11] == '.fixedaddr.':
             addr = int(name[11:], 16)
-            fixedsections.append((addr, section))
+            fixedsections.append((addr, section, []))
+            if align != 1:
+                print "Error: Fixed section %s has non-zero alignment (%d)" % (
+                    name, align)
+                sys.exit(1)
         if name[:6] == '.text.':
             textsections.append(section)
+            canrelocate.append((section, textsections))
         if name[:17] == '.rodata.__func__.' or name == '.rodata.str1.1':
             rodatasections.append(section)
+            #canrelocate.append((section, rodatasections))
         if name[:8] == '.data16.':
             datasections.append(section)
+            #canrelocate.append((section, datasections))
+
+    # Find freespace in fixed address area
+    fixedsections.sort()
+    # fixedAddr = [(freespace, sectioninfo), ...]
+    fixedAddr = []
+    for i in range(len(fixedsections)):
+        fixedsectioninfo = fixedsections[i]
+        addr, section, extrasectionslist = fixedsectioninfo
+        if i == len(fixedsections) - 1:
+            nextaddr = 0x10000
+        else:
+            nextaddr = fixedsections[i+1][0]
+        avail = nextaddr - addr - section[0]
+        fixedAddr.append((avail, fixedsectioninfo))
+
+    # Attempt to fit other sections into fixed area
+    fixedAddr.sort()
+    canrelocate.sort()
+    for freespace, fixedsectioninfo in fixedAddr:
+        fixedaddr, fixedsection, extrasections = fixedsectioninfo
+        addpos = fixedaddr + fixedsection[0]
+        nextfixedaddr = addpos + freespace
+#        print "Filling section %x uses %d, next=%x, available=%d" % (
+#            fixedaddr, fixedsection[0], nextfixedaddr, freespace)
+        while 1:
+            canfit = None
+            for fixedaddrinfo in canrelocate:
+                fitsection, inlist = fixedaddrinfo
+                fitnextaddr = alignpos(addpos, fitsection[1]) + fitsection[0]
+#                print "Test %s - %x vs %x" % (
+#                    fitsection[2], fitnextaddr, nextfixedaddr)
+                if fitnextaddr > nextfixedaddr:
+                    # Can't fit.
+                    break
+                canfit = (fitnextaddr, fixedaddrinfo)
+            if canfit is None:
+                break
+            # Found a section that can fit.
+            fitnextaddr, fixedaddrinfo = canfit
+            canrelocate.remove(fixedaddrinfo)
+            fitsection, inlist = fixedaddrinfo
+            inlist.remove(fitsection)
+            extrasections.append(fitsection)
+            addpos = fitnextaddr
+#            print "    Adding %s (size %d align %d)" % (
+#                fitsection[2], fitsection[0], fitsection[1])
 
     # Write regular sections
+    output = open(outname, 'wb')
     for section in textsections:
-        name = section[1]
-        sys.stdout.write("*(%s)\n" % (name,))
-    sys.stdout.write("code16_rodata = . ;\n")
+        name = section[2]
+        output.write("*(%s)\n" % (name,))
+    output.write("code16_rodata = . ;\n")
     for section in rodatasections:
-        name = section[1]
-        sys.stdout.write("*(%s)\n" % (name,))
+        name = section[2]
+        output.write("*(%s)\n" % (name,))
     for section in datasections:
-        name = section[1]
-        sys.stdout.write("*(%s)\n" % (name,))
+        name = section[2]
+        output.write("*(%s)\n" % (name,))
 
     # Write fixed sections
-    sys.stdout.write("freespace1_start = . ;\n")
+    output.write("freespace1_start = . ;\n")
     first = 1
-    for addr, section in fixedsections:
-        name = section[1]
-        sys.stdout.write(". = ( 0x%x - code16_start ) ;\n" % (addr,))
+    for addr, section, extrasections in fixedsections:
+        name = section[2]
+        output.write(". = ( 0x%x - code16_start ) ;\n" % (addr,))
         if first:
             first = 0
-            sys.stdout.write("freespace1_end = . ;\n")
-        sys.stdout.write("*(%s)\n" % (name,))
+            output.write("freespace1_end = . ;\n")
+        output.write("*(%s)\n" % (name,))
+        for extrasection in extrasections:
+            name = extrasection[2]
+            output.write("*(%s)\n" % (name,))
 
 if __name__ == '__main__':
     main()