Add support for 32bit PCI BIOS entry.
authorKevin O'Connor <kevin@koconnor.net>
Wed, 30 Dec 2009 17:14:53 +0000 (12:14 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Wed, 30 Dec 2009 17:14:53 +0000 (12:14 -0500)
Create a new code blob (code32seg) with support for 32bit functions
    that need to utilize explicit segment accesses.
This code blob uses global variables relative to %gs and with a
    dynamic code offset (determined by get_global_offset()).
Add BIOS32 structure and code.
Add code for 32bit PCI BIOS code.

15 files changed:
Makefile
src/biosvar.h
src/config.h
src/optionroms.c
src/output.c
src/pcibios.c
src/pmm.c
src/post.c
src/rombios.lds.S
src/rombios32seg.lds.S [new file with mode: 0644]
src/romlayout.S
src/types.h
src/util.h
tools/checkrom.py
tools/layoutrom.py

index 26c94615a9fc3399570b7f629a7af439ff662bd1..b71d1a195edeab8bfda4f803ea29600a8dfb12f5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -13,12 +13,13 @@ OUT=out/
 # Source files
 SRCBOTH=misc.c pmm.c stacks.c output.c util.c block.c floppy.c ata.c mouse.c \
         kbd.c pci.c serial.c clock.c pic.c cdrom.c ps2port.c smp.c resume.c \
-        pnpbios.c pirtable.c vgahooks.c ramdisk.c \
+        pnpbios.c pirtable.c vgahooks.c ramdisk.c pcibios.c \
         usb.c usb-uhci.c usb-ohci.c usb-hid.c paravirt.c
-SRC16=$(SRCBOTH) system.c disk.c apm.c pcibios.c font.c
+SRC16=$(SRCBOTH) system.c disk.c apm.c font.c
 SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \
       acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \
       lzmadecode.c
+SRC32SEG=util.c output.c pci.c pcibios.c
 
 cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
               /dev/null 2>&1`"; then echo "$(2)"; else echo "$(3)"; fi ;)
@@ -34,10 +35,12 @@ COMMONCFLAGS += $(call cc-option,$(CC),-nopie,)
 COMMONCFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
 COMMONCFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,)
 
-override CFLAGS = $(COMMONCFLAGS) -g -DMODE16=0 -DMODESEGMENT=0
-CFLAGS16INC = $(COMMONCFLAGS) -DMODE16=1 -DMODESEGMENT=1 -fno-defer-pop \
-              $(call cc-option,$(CC),-fno-jump-tables,-DMANUAL_NO_JUMP_TABLE) \
-              $(call cc-option,$(CC),-fno-tree-switch-conversion,) \
+CFLAGS32FLAT = $(COMMONCFLAGS) -g -DMODE16=0 -DMODESEGMENT=0
+CFLAGSSEG = $(COMMONCFLAGS) -DMODESEGMENT=1 -fno-defer-pop \
+            $(call cc-option,$(CC),-fno-jump-tables,-DMANUAL_NO_JUMP_TABLE) \
+            $(call cc-option,$(CC),-fno-tree-switch-conversion,)
+CFLAGS32SEG = $(CFLAGSSEG) -DMODE16=0 -g
+CFLAGS16INC = $(CFLAGSSEG) -DMODE16=1 \
               $(call cc-option,$(CC),--param large-stack-frame=4,)
 CFLAGS16 = $(CFLAGS16INC) -g
 
@@ -112,36 +115,46 @@ $(OUT)asm-offsets.h: $(OUT)asm-offsets.s
 
 $(OUT)ccode.16.s: ; $(call whole-compile, $(CFLAGS16) -S, $(addprefix src/, $(SRC16)),$@)
 
-$(OUT)ccode32flat.o: ; $(call whole-compile, $(CFLAGS), $(addprefix src/, $(SRC32FLAT)),$@)
+$(OUT)code32seg.o: ; $(call whole-compile, $(CFLAGS32SEG), $(addprefix src/, $(SRC32SEG)),$@)
+
+$(OUT)ccode32flat.o: ; $(call whole-compile, $(CFLAGS32FLAT), $(addprefix src/, $(SRC32FLAT)),$@)
 
 $(OUT)code16.o: romlayout.S $(OUT)ccode.16.s $(OUT)asm-offsets.h
        @echo "  Compiling (16bit) $@"
        $(Q)$(CC) $(CFLAGS16INC) -c -D__ASSEMBLY__ $< -o $@
 
-$(OUT)romlayout16.lds $(OUT)romlayout32flat.lds $(OUT)code32flat.o: $(OUT)ccode32flat.o $(OUT)code16.o tools/layoutrom.py
+$(OUT)romlayout16.lds $(OUT)romlayout32seg.lds $(OUT)romlayout32flat.lds $(OUT)code32flat.o: $(OUT)ccode32flat.o $(OUT)code32seg.o $(OUT)code16.o tools/layoutrom.py
        @echo "  Building ld scripts (version \"$(VERSION)\")"
        $(Q)echo 'const char VERSION[] = "$(VERSION)";' > $(OUT)version.c
-       $(Q)$(CC) $(CFLAGS) -c $(OUT)version.c -o $(OUT)version.o
+       $(Q)$(CC) $(CFLAGS32FLAT) -c $(OUT)version.c -o $(OUT)version.o
        $(Q)$(LD) -melf_i386 -r $(OUT)ccode32flat.o $(OUT)version.o -o $(OUT)code32flat.o
        $(Q)$(OBJDUMP) -thr $(OUT)code32flat.o > $(OUT)code32flat.o.objdump
+       $(Q)$(OBJDUMP) -thr $(OUT)code32seg.o > $(OUT)code32seg.o.objdump
        $(Q)$(OBJDUMP) -thr $(OUT)code16.o > $(OUT)code16.o.objdump
-       $(Q)./tools/layoutrom.py $(OUT)code16.o.objdump $(OUT)code32flat.o.objdump $(OUT)romlayout16.lds $(OUT)romlayout32flat.lds
+       $(Q)./tools/layoutrom.py $(OUT)code16.o.objdump $(OUT)code32seg.o.objdump $(OUT)code32flat.o.objdump $(OUT)romlayout16.lds $(OUT)romlayout32seg.lds $(OUT)romlayout32flat.lds
 
 
 $(OUT)rom16.o: $(OUT)code16.o $(OUT)rom32flat.o $(OUT)romlayout16.lds
        @echo "  Linking (no relocs) $@"
        $(Q)$(LD) -r -T $(OUT)romlayout16.lds $< -o $@
 
+$(OUT)rom32seg.o: $(OUT)code32seg.o $(OUT)romlayout32seg.lds
+       @echo "  Linking (no relocs) $@"
+       $(Q)$(LD) -r -T $(OUT)romlayout32seg.lds $< -o $@
+
 $(OUT)rom32flat.o: $(OUT)code32flat.o $(OUT)romlayout32flat.lds
        @echo "  Linking (no relocs) $@"
        $(Q)$(LD) -r -T $(OUT)romlayout32flat.lds $< -o $@
 
-$(OUT)rom.o: $(OUT)rom16.o $(OUT)rom32flat.o $(OUT)rombios16.lds $(OUT)rombios.lds
+$(OUT)rom.o: $(OUT)rom16.o $(OUT)rom32seg.o $(OUT)rom32flat.o $(OUT)rombios16.lds  $(OUT)rombios32seg.lds $(OUT)rombios.lds
        @echo "  Linking $@"
-       $(Q)$(LD) -T $(OUT)rombios16.lds $(OUT)rom16.o -R $(OUT)rom32flat.o -o $(OUT)rom16.reloc.o
+       $(Q)$(LD) -T $(OUT)rombios16.lds $(OUT)rom16.o -R $(OUT)rom32seg.o -R $(OUT)rom32flat.o -o $(OUT)rom16.reloc.o
        $(Q)$(STRIP) $(OUT)rom16.reloc.o -o $(OUT)rom16.final.o
        $(Q)$(OBJCOPY) --adjust-vma 0xf0000 $(OUT)rom16.o $(OUT)rom16.moved.o
-       $(Q)$(LD) -T $(OUT)rombios.lds $(OUT)rom16.final.o $(OUT)rom32flat.o -R $(OUT)rom16.moved.o -o $@
+       $(Q)$(LD) -T $(OUT)rombios32seg.lds $(OUT)rom32seg.o -R $(OUT)rom16.o -R $(OUT)rom32flat.o -o $(OUT)rom32seg.reloc.o
+       $(Q)$(STRIP) $(OUT)rom32seg.reloc.o -o $(OUT)rom32seg.final.o
+       $(Q)$(OBJCOPY) --adjust-vma 0xf0000 $(OUT)rom32seg.o $(OUT)rom32seg.moved.o
+       $(Q)$(LD) -T $(OUT)rombios.lds $(OUT)rom16.final.o $(OUT)rom32seg.final.o $(OUT)rom32flat.o -R $(OUT)rom16.moved.o -R $(OUT)rom32seg.moved.o -o $@
 
 $(OUT)bios.bin.elf $(OUT)bios.bin: $(OUT)rom.o tools/checkrom.py
        @echo "  Prepping $@"
index 6a789e41a9e216eac664c65765565ec61dcd53b8..db6783e07b2421c5e92d9ca5e719d7e7f1c45a8e 100644 (file)
@@ -260,12 +260,31 @@ get_ebda_ptr()
  * Global variables
  ****************************************************************/
 
+#if MODE16 == 0 && MODESEGMENT == 1
+// In 32bit segmented mode %cs may not be readable and the code may be
+// relocated.  The entry code sets up %gs with a readable segment and
+// the code offset can be determined by get_global_offset().
+#define GLOBAL_SEGREG GS
+static inline u32 __attribute_const get_global_offset(void) {
+    u32 ret;
+    asm("  calll 1f\n"
+        "1:popl %0\n"
+        "  subl $1b, %0"
+        : "=r"(ret));
+    return ret;
+}
+#else
 #define GLOBAL_SEGREG CS
+static inline u32 __attribute_const get_global_offset(void) {
+    return 0;
+}
+#endif
 static inline u16 get_global_seg() {
     return GET_SEG(GLOBAL_SEGREG);
 }
-#define GET_GLOBAL(var)                         \
-    GET_VAR(GLOBAL_SEGREG, (var))
+#define GET_GLOBAL(var)                                                 \
+    GET_VAR(GLOBAL_SEGREG, *(typeof(&(var)))((void*)&(var)              \
+                                             + get_global_offset()))
 #define SET_GLOBAL(var, val) do {               \
         ASSERT32FLAT();                         \
         (var) = (val);                          \
index cf5678d1b525fbf924e022961f8b61a8ab8a9b7c..1450bf7d0c2c368e887a6be78dae041131d8b193 100644 (file)
 #define DEBUG_ISR_hwpic2 5
 #define DEBUG_HDL_pnp 1
 #define DEBUG_HDL_pmm 1
+#define DEBUG_HDL_pcibios32 9
 
 #define DEBUG_unimplemented 2
 #define DEBUG_invalid 3
index 0be68524d290ac87f11b85ebbadc0e3f23ca2027..31bb98be34c338f28841c94ad6e95ecbe25a7a27 100644 (file)
@@ -172,10 +172,10 @@ get_pci_rom(struct rom_header *rom)
 static inline u32
 max_rom()
 {
-    extern u8 code32_start[];
-    if ((u32)code32_start > BUILD_BIOS_ADDR)
+    extern u8 code32flat_start[];
+    if ((u32)code32flat_start > BUILD_BIOS_ADDR)
         return BUILD_BIOS_ADDR;
-    return (u32)code32_start;
+    return (u32)code32flat_start;
 }
 
 // Copy a rom to its permanent location below 1MiB
index 3b0e0e7ccbfbe60be6b52d51a6b0bc431a10d682..2e7175e4f90195b095dde6da3899004ed1a8406c 100644 (file)
@@ -87,8 +87,10 @@ putc_debug(struct putcinfo *action, char c)
 // In segmented mode just need a dummy variable (putc_debug is always
 // used anyway), and in 32bit flat mode need a pointer to the 32bit
 // instance of putc_debug().
-#if MODESEGMENT
+#if MODE16
 static struct putcinfo debuginfo VAR16;
+#elif MODESEGMENT
+static struct putcinfo debuginfo VAR32SEG;
 #else
 static struct putcinfo debuginfo = { putc_debug };
 #endif
index 6fb7d9e180cca003b138e8c3b638c11c4d911f58..2425a65c7f4898ccc1499d0062c157ca341bb911 100644 (file)
 #include "biosvar.h" // GET_EBDA
 #include "pci_regs.h" // PCI_VENDOR_ID
 
+// romlayout.S
+extern void bios32_entry();
+extern void pcibios32_entry();
+
 #define RET_FUNC_NOT_SUPPORTED 0x81
 #define RET_BAD_VENDOR_ID      0x83
 #define RET_DEVICE_NOT_FOUND   0x86
@@ -30,8 +34,7 @@ handle_1ab101(struct bregs *regs)
     regs->bx = 0x0210; // PCI version 2.10
     regs->cl = pci_bdf_to_bus(max - 1);
     regs->edx = 0x20494350; // "PCI "
-    // XXX - bochs bios code sets edi to point to 32bit code - but no
-    // reference to this in spec.
+    regs->edi = (u32)pcibios32_entry + BUILD_BIOS_ADDR;
     set_code_success(regs);
 }
 
@@ -154,7 +157,8 @@ handle_1ab10e(struct bregs *regs)
 
     // Memcpy pir table slots to dest buffer.
     memcpy_far(buf_seg, buf_far
-               , get_global_seg(), pirtable_g->slots
+               , get_global_seg()
+               , (void*)(pirtable_g->slots) + get_global_offset()
                , pirsize);
 
     // XXX - bochs bios sets bx to (1 << 9) | (1 << 11)
@@ -192,3 +196,41 @@ handle_1ab1(struct bregs *regs)
     default:   handle_1ab1XX(regs); break;
     }
 }
+
+
+/****************************************************************
+ * 32bit interface
+ ****************************************************************/
+
+#if MODE16 == 0 && MODESEGMENT == 1
+// Entry point for 32bit pci bios functions.
+void VISIBLE32SEG
+handle_pcibios32(struct bregs *regs)
+{
+    debug_enter(regs, DEBUG_HDL_pcibios32);
+    handle_1ab1(regs);
+}
+#endif
+
+struct bios32_s {
+    u32 signature;
+    u32 entry;
+    u8 version;
+    u8 length;
+    u8 checksum;
+    u8 reserved[5];
+} PACKED;
+
+struct bios32_s BIOS32HEADER __aligned(16) VAR16EXPORT = {
+    .signature = 0x5f32335f, // _32_
+    .length = sizeof(BIOS32HEADER) / 16,
+};
+
+void
+bios32_setup(void)
+{
+    dprintf(3, "init bios32\n");
+
+    BIOS32HEADER.entry = (u32)bios32_entry;
+    BIOS32HEADER.checksum -= checksum(&BIOS32HEADER, sizeof(BIOS32HEADER));
+}
index d05cc6fe54acf970efed762a0ca92950a4c6be5c..dab8fb36b13c48cf09813720e2680bd5af48b077 100644 (file)
--- a/src/pmm.c
+++ b/src/pmm.c
@@ -290,10 +290,11 @@ malloc_setup()
     PMMAllocs = NULL;
 
     // Memory in 0xf0000 area.
-    extern u8 code32_start[];
-    if ((u32)code32_start > BUILD_BIOS_ADDR)
+    extern u8 code32flat_start[];
+    if ((u32)code32flat_start > BUILD_BIOS_ADDR)
         // Clear unused parts of f-segment
-        memset((void*)BUILD_BIOS_ADDR, 0, (u32)code32_start - BUILD_BIOS_ADDR);
+        memset((void*)BUILD_BIOS_ADDR, 0
+               , (u32)code32flat_start - BUILD_BIOS_ADDR);
     memset(BiosTableSpace, 0, CONFIG_MAX_BIOSTABLE);
     ZoneFSeg.bottom = (u32)BiosTableSpace;
     ZoneFSeg.top = ZoneFSeg.cur = ZoneFSeg.bottom + CONFIG_MAX_BIOSTABLE;
index 2f14aa73f07dfdae7b44904fecfd83af96e42d02..db9d8f724077799441f2db1fc190a6df50f019b4 100644 (file)
@@ -189,6 +189,7 @@ post()
     smm_init();
 
     // Setup interfaces that option roms may need
+    bios32_setup();
     pmm_setup();
     pnp_setup();
     kbd_setup();
index 6f6040b552366c317a96ad363ee4020acf566a43..20cbebee3debd08a7c77b8de0b724df8f6178bec 100644 (file)
@@ -11,12 +11,15 @@ OUTPUT_ARCH("i386")
 ENTRY(post32)
 SECTIONS
 {
-        .text code32_start : {
-                *(.text32)
+        .text code32flat_start : {
+                *(.text32flat)
 
-                . = data16_start + BUILD_BIOS_ADDR - code32_start ;
+                . = code32seg_start + BUILD_BIOS_ADDR - code32flat_start ;
+                *(.text32seg)
+
+                . = data16_start + BUILD_BIOS_ADDR - code32flat_start ;
                 *(.data16)
-                . = text16_start + BUILD_BIOS_ADDR - code32_start ;
+                . = text16_start + BUILD_BIOS_ADDR - code32flat_start ;
                 *(.text16)
                 final_text16_end = . ;
                 }
diff --git a/src/rombios32seg.lds.S b/src/rombios32seg.lds.S
new file mode 100644 (file)
index 0000000..9961c50
--- /dev/null
@@ -0,0 +1,15 @@
+// Linker definitions for 32bit segmented code
+//
+// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH("i386")
+SECTIONS
+{
+        .text32seg code32seg_start : {
+                *(.text32seg)
+        }
+        /DISCARD/ : { *(.discard*) }
+}
index b651a2b3cbd6720059bfcbf1d4d280cc62a15b41..43af112793fdc594015ad93e9a86e15bdb735caf 100644 (file)
@@ -374,6 +374,61 @@ apm32protected_entry:
         popfw
         lretl
 
+// PCI-BIOS 32bit entry point
+        DECLFUNC pcibios32_entry
+pcibios32_entry:
+        pushfl
+        pushl %gs               // Backup %gs
+        cli
+        cld
+        pushl %eax              // Save registers (matches struct bregs)
+        pushl %ecx
+        pushl %edx
+        pushl %ebx
+        pushl %ebp
+        pushl %esi
+        pushl %edi
+        pushw %es
+        pushw %ds
+        movl %ds, %eax          // Move %ds to %gs
+        movl %eax, %gs
+        movl %ss, %eax          // Move %ss to %ds
+        movl %eax, %ds
+        movl %esp, %eax         // First arg is pointer to struct bregs
+        calll handle_pcibios32
+        popw %ds                // Restore registers (from struct bregs)
+        popw %es
+        popl %edi
+        popl %esi
+        popl %ebp
+        popl %ebx
+        popl %edx
+        popl %ecx
+        popl %eax
+        popl %gs
+        popfl
+        lretl
+
+// BIOS32 support
+        EXPORTFUNC bios32_entry
+bios32_entry:
+        pushfl
+#if CONFIG_PCIBIOS
+        // Check for PCI-BIOS request
+        cmpl $0x49435024, %eax // $PCI
+        jne 1f
+        movl $BUILD_BIOS_ADDR, %ebx
+        movl $BUILD_BIOS_SIZE, %ecx
+        movl $pcibios32_entry, %edx
+        xorb %al, %al
+        jmp 2f
+#endif
+        // Unknown request
+1:      movb $0x80, %al
+        // Return to caller
+2:      popfl
+        lretl
+
 // 32bit elf entry point
         EXPORTFUNC post32
 post32:
index b9786e2598d5bd2717a9c1b4aaaf05f39c59ad20..cfa47fe89a7fec83445dab92bb9960b297586b19 100644 (file)
@@ -33,6 +33,9 @@ union u64_u32_u {
 
 #define UNIQSEC __FILE__ "." __stringify(__LINE__)
 
+extern void __force_link_error__only_in_32bit_flat() __attribute__ ((noreturn));
+extern void __force_link_error__only_in_16bit() __attribute__ ((noreturn));
+
 #define __ASM(code) asm(".section .text.asm." UNIQSEC "\n\t" code)
 
 #if MODE16 == 1
@@ -40,6 +43,8 @@ union u64_u32_u {
 # define VISIBLE16 __VISIBLE
 // Notes a function as externally visible in the 32bit flat code chunk.
 # define VISIBLE32FLAT
+// Notes a function as externally visible in the 32bit segmented code chunk.
+# define VISIBLE32SEG
 // Designate a variable as (only) visible to 16bit code.
 # define VAR16 __section(".data16." UNIQSEC)
 // Designate a variable as visible to 16bit, 32bit, and assembler code.
@@ -48,6 +53,8 @@ union u64_u32_u {
 # define VAR16EXPORT __section(".data16.export." UNIQSEC) __VISIBLE
 // Designate a variable at a specific 16bit address
 # define VAR16FIXED(addr) __aligned(1) __VISIBLE __section(".fixedaddr." __stringify(addr))
+// Designate a variable as (only) visible to 32bit segmented code.
+# define VAR32SEG __section(".discard.var32seg." UNIQSEC)
 // Designate a 32bit variable also available in 16bit "big real" mode.
 # define VAR32FLATVISIBLE __section(".discard.var32flat." UNIQSEC) __VISIBLE __weak
 // Designate top-level assembler as 16bit only.
@@ -55,20 +62,34 @@ union u64_u32_u {
 // Designate top-level assembler as 32bit flat only.
 # define ASM32FLAT(code)
 // Compile time check for a given mode.
-extern void __force_link_error__only_in_32bit_flat() __attribute__ ((noreturn));
 #define ASSERT16() do { } while (0)
 #define ASSERT32FLAT() __force_link_error__only_in_32bit_flat()
+#elif MODESEGMENT == 1
+# define VISIBLE16
+# define VISIBLE32FLAT
+# define VISIBLE32SEG __VISIBLE
+# define VAR16 __section(".discard.var16." UNIQSEC)
+# define VAR16VISIBLE VAR16 __VISIBLE __weak
+# define VAR16EXPORT VAR16VISIBLE
+# define VAR16FIXED(addr) VAR16VISIBLE
+# define VAR32SEG __section(".data32seg." UNIQSEC)
+# define VAR32FLATVISIBLE __section(".discard.var32flat." UNIQSEC) __VISIBLE __weak
+# define ASM16(code)
+# define ASM32FLAT(code)
+#define ASSERT16() __force_link_error__only_in_16bit()
+#define ASSERT32FLAT() __force_link_error__only_in_32bit_flat()
 #else
 # define VISIBLE16
 # define VISIBLE32FLAT __VISIBLE
+# define VISIBLE32SEG
 # define VAR16 __section(".discard.var16." UNIQSEC)
 # define VAR16VISIBLE VAR16 __VISIBLE __weak
 # define VAR16EXPORT VAR16VISIBLE
 # define VAR16FIXED(addr) VAR16VISIBLE
+# define VAR32SEG __section(".discard.var32seg." UNIQSEC)
 # define VAR32FLATVISIBLE __VISIBLE
 # define ASM16(code)
 # define ASM32FLAT(code) __ASM(code)
-extern void __force_link_error__only_in_16bit() __attribute__ ((noreturn));
 #define ASSERT16() __force_link_error__only_in_16bit()
 #define ASSERT32FLAT() do { } while (0)
 #endif
@@ -100,6 +121,7 @@ extern void __force_link_error__only_in_16bit() __attribute__ ((noreturn));
 
 #define noinline __attribute__((noinline))
 #define __always_inline inline __attribute__((always_inline))
+#define __attribute_const __attribute__((__const__))
 
 #define __stringify_1(x)        #x
 #define __stringify(x)          __stringify_1(x)
index 7d95cbede40735438ea0dbbdf31aa6ef8bbee318..7117fa5efdfb4bc5fce3088e47fc28bc59b629c8 100644 (file)
@@ -268,6 +268,7 @@ void VISIBLE16 handle_1553(struct bregs *regs);
 
 // pcibios.c
 void handle_1ab1(struct bregs *regs);
+void bios32_setup(void);
 
 // shadow.c
 void make_bios_writable();
index 6f7b3ba3fd0690aa4b8ac4a4896560bfcd8e6120..5c9600f13fb48ffe0599cf33b34869ac3879e8c5 100755 (executable)
@@ -39,14 +39,21 @@ def main():
         print "Error!  Code is too big (0x%x vs 0x%x)" % (
             datasize, finalsize)
         sys.exit(1)
+    actualdatasize = f16e - syms['code32flat_start']
+    if datasize != actualdatasize:
+        print "Error!  Unknown extra data (0x%x vs 0x%x)" % (
+            datasize, actualdatasize)
+        sys.exit(1)
 
     # Print statistics
     sizefree = syms['freespace_end'] - syms['freespace_start']
     size16 = syms['text16_end'] - syms['data16_start']
-    size32 = syms['code32_end'] - syms['code32_start']
-    totalc = size16+size32
-    print "16bit size: %d" % size16
-    print "32bit size: %d" % size32
+    size32seg = syms['code32seg_end'] - syms['code32seg_start']
+    size32flat = syms['code32flat_end'] - syms['code32flat_start']
+    totalc = size16+size32seg+size32flat
+    print "16bit size:           %d" % size16
+    print "32bit segmented size: %d" % size32seg
+    print "32bit flat size:      %d" % size32flat
     print "Total size: %d  Free space: %d  Percent used: %.1f%% (%dKiB rom)" % (
         totalc, sizefree + finalsize - datasize
         , (totalc / float(finalsize)) * 100.0
index 85bdc7dfd0bd227e522f73235aecf2738f4bbc9f..3113407880a602c537fd1bba9997c92c14544be7 100755 (executable)
@@ -151,7 +151,6 @@ def doLayout16(sections, outname):
     output.write(COMMONHEADER + """
         data16_start = 0x%x ;
         .data16 data16_start : {
-                freespace_end = . ;
 """ % data16_start)
     outSections(output, datasections)
     output.write("code16_rodata = . ;\n")
@@ -199,23 +198,53 @@ def getSectionsPrefix(sections, prefix):
             out.append((size, align, name))
     return out
 
-# Layout the 32bit code.  This places the code as high as possible.
-def doLayout32(sections, outname, start16):
-    start16 += 0xf0000
+# Layout the 32bit segmented code.  This places the code as high as possible.
+def doLayout32seg(sections, outname, endat):
+    # Find sections to output
+    textsections = getSectionsPrefix(sections, '.text.')
+    rodatasections = (getSectionsPrefix(sections, '.rodata.str1.1')
+                      + getSectionsPrefix(sections, '.rodata.__func__.'))
+    datasections = getSectionsPrefix(sections, '.data32seg.')
+    startat = getSectionsStart(
+        textsections + rodatasections + datasections, endat)
+
+    # Write sections
+    output = open(outname, 'wb')
+    output.write(COMMONHEADER + """
+        code32seg_start = 0x%x ;
+        .text32seg code32seg_start : {
+                freespace_end = . ;
+""" % startat)
+
+    outSections(output, textsections)
+    output.write("code32seg_rodata = . ;\n")
+    outSections(output, rodatasections)
+    outSections(output, datasections)
+
+    output.write("""
+                code32seg_end = ABSOLUTE(.) ;
+        }
+        /DISCARD/ : { *(.text*) *(.rodata*) *(.data*) *(.bss*) *(COMMON) }
+""" + COMMONTRAILER)
+    return startat
+
+# Layout the 32bit flat code.  This places the code as high as possible.
+def doLayout32flat(sections, outname, endat):
+    endat += 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)
+    startat = getSectionsStart(
+        textsections + rodatasections + datasections + bsssections, endat, 512)
 
     # Write sections
     output = open(outname, 'wb')
     output.write(COMMONHEADER + """
-        .text32 0x%x : {
-                code32_start = ABSOLUTE(.) ;
-""" % start32)
+        code32flat_start = 0x%x ;
+        .text32flat code32flat_start : {
+""" % startat)
 
     outSections(output, textsections)
     output.write("code32_rodata = . ;\n")
@@ -225,63 +254,70 @@ def doLayout32(sections, outname, start16):
 
     output.write("""
                 freespace_start = . ;
-                code32_end = ABSOLUTE(.) ;
+                code32flat_end = ABSOLUTE(.) ;
         }
 """ + COMMONTRAILER)
+    return startat
 
 
 ######################################################################
 # Section garbage collection
 ######################################################################
 
+def getSectionsList(info, names):
+    out = []
+    for i in info[0]:
+        size, align, section = i
+        if section not in names:
+#            print "gc", section
+            continue
+        out.append(i)
+    return out
+
 # Note required section, and recursively set all referenced sections
 # as required.
-def keepsection(name, pri, alt):
-    if name in pri[3]:
+def keepsection(name, infos, pos=0):
+    if name in infos[pos][3]:
         # Already kept - nothing to do.
         return
-    pri[3].append(name)
-    relocs = pri[2].get(name)
+    infos[pos][3].append(name)
+    relocs = infos[pos][2].get(name)
     if relocs is None:
         return
     # Keep all sections that this section points to
     for symbol in relocs:
-        addr, section = pri[1].get(symbol, (None, None))
+        addr, section = infos[pos][1].get(symbol, (None, None))
         if (section is not None and '*' not in section
             and section[:9] != '.discard.'):
-            keepsection(section, pri, alt)
+            keepsection(section, infos, pos)
             continue
         # Not in primary sections - it may be a cross 16/32 reference
-        addr, section = alt[1].get(symbol, (None, None))
+        newpos = (pos+1)%3
+        addr, section = infos[newpos][1].get(symbol, (None, None))
+        if section is not None and '*' not in section:
+            keepsection(section, infos, newpos)
+            continue
+        newpos = (pos+2)%3
+        addr, section = infos[(pos+2)%3][1].get(symbol, (None, None))
         if section is not None and '*' not in section:
-            keepsection(section, alt, pri)
+            keepsection(section, infos, newpos)
 
 # 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], [])
-    alt = (info32[0], info32[1], info32[2], [])
+def gc(info16, info32seg, info32flat):
+    # infos = ((sections, symbols, relocs, keep sections), ...)
+    infos = ((info16[0], info16[1], info16[2], []),
+             (info32seg[0], info32seg[1], info32seg[2], []),
+             (info32flat[0], info32flat[1], info32flat[2], []))
     # Start by keeping sections that are globally visible.
     for size, align, section in info16[0]:
         if section[:11] == '.fixedaddr.' or '.export.' in section:
-            keepsection(section, pri, alt)
+            keepsection(section, infos)
     # Return sections found.
-    sections16 = []
-    for info in info16[0]:
-        size, align, section = info
-        if section not in pri[3]:
-#            print "gc16", section
-            continue
-        sections16.append(info)
-    sections32 = []
-    for info in info32[0]:
-        size, align, section = info
-        if section not in alt[3]:
-#            print "gc32", section
-            continue
-        sections32.append(info)
-    return sections16, sections32
+    sections16 = getSectionsList(info16, infos[0][3])
+    sections32seg = getSectionsList(info32seg, infos[1][3])
+    sections32flat = getSectionsList(info32flat, infos[2][3])
+    return sections16, sections32seg, sections32flat
 
 
 ######################################################################
@@ -340,18 +376,21 @@ def parseObjDump(file):
 
 def main():
     # Get output name
-    in16, in32, out16, out32 = sys.argv[1:]
+    in16, in32seg, in32flat, out16, out32seg, out32flat = sys.argv[1:]
 
     infile16 = open(in16, 'rb')
-    infile32 = open(in32, 'rb')
+    infile32seg = open(in32seg, 'rb')
+    infile32flat = open(in32flat, 'rb')
 
     info16 = parseObjDump(infile16)
-    info32 = parseObjDump(infile32)
+    info32seg = parseObjDump(infile32seg)
+    info32flat = parseObjDump(infile32flat)
 
-    sections16, sections32 = gc(info16, info32)
+    sections16, sections32seg, sections32flat = gc(info16, info32seg, info32flat)
 
     start16 = doLayout16(sections16, out16)
-    doLayout32(sections32, out32, start16)
+    start32seg = doLayout32seg(sections32seg, out32seg, start16)
+    doLayout32flat(sections32flat, out32flat, start32seg)
 
 if __name__ == '__main__':
     main()