This patch series adds support for 32bit PCI BIOS calls to SeaBIOS.
Currently, the SeaBIOS binary is composed of two big chunks of data - the 16bit code (irq handlers) and the 32bit "flat mode" code (post and boot). This patch adds a third chunk for 32bit segmented code. This new code chunk uses explicit segment memory accesses like the 16bit code does, but is compiled in 32bit mode.
I ran into one unexpected complication with this support - the PCI BIOS functions need to support position independent code, as the code and data segment base can vary. Unfortunately, using GCC's -fpic option doesn't work, because that also implies building a GOT/PLT which isn't desired and conflicts with segment accesses. To work around the issue, I reserve %ebx in the 32bit segmented code as a base offset and make sure all global variable accesses are relative to it.
There are three patches - much of it is just renames to support the new code chunk.
-Kevin
Introduce MODESEGMENT define; rename VISIBLE32 to VISIBLE32FLAT.
Prepare for support of segmented 32bit code. Add new MODESEGMENT definition, and clarify existing 32bit mode defs.
diff --git a/Makefile b/Makefile index 45f176e..26c9461 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ SRCBOTH=misc.c pmm.c stacks.c output.c util.c block.c floppy.c ata.c mouse.c \ pnpbios.c pirtable.c vgahooks.c ramdisk.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 -SRC32=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.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
@@ -34,8 +34,8 @@ 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 -CFLAGS16INC = $(COMMONCFLAGS) -DMODE16=1 -fno-defer-pop \ +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,) \ $(call cc-option,$(CC),--param large-stack-frame=4,) @@ -112,36 +112,36 @@ $(OUT)asm-offsets.h: $(OUT)asm-offsets.s
$(OUT)ccode.16.s: ; $(call whole-compile, $(CFLAGS16) -S, $(addprefix src/, $(SRC16)),$@)
-$(OUT)ccode32.o: ; $(call whole-compile, $(CFLAGS), $(addprefix src/, $(SRC32)),$@) +$(OUT)ccode32flat.o: ; $(call whole-compile, $(CFLAGS), $(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)romlayout32.lds $(OUT)code32.o: $(OUT)ccode32.o $(OUT)code16.o tools/layoutrom.py +$(OUT)romlayout16.lds $(OUT)romlayout32flat.lds $(OUT)code32flat.o: $(OUT)ccode32flat.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)$(LD) -melf_i386 -r $(OUT)ccode32.o $(OUT)version.o -o $(OUT)code32.o - $(Q)$(OBJDUMP) -thr $(OUT)code32.o > $(OUT)code32.o.objdump + $(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)code16.o > $(OUT)code16.o.objdump - $(Q)./tools/layoutrom.py $(OUT)code16.o.objdump $(OUT)code32.o.objdump $(OUT)romlayout16.lds $(OUT)romlayout32.lds + $(Q)./tools/layoutrom.py $(OUT)code16.o.objdump $(OUT)code32flat.o.objdump $(OUT)romlayout16.lds $(OUT)romlayout32flat.lds
-$(OUT)rom16.o: $(OUT)code16.o $(OUT)rom32.o $(OUT)romlayout16.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)rom32.o: $(OUT)code32.o $(OUT)romlayout32.lds +$(OUT)rom32flat.o: $(OUT)code32flat.o $(OUT)romlayout32flat.lds @echo " Linking (no relocs) $@" - $(Q)$(LD) -r -T $(OUT)romlayout32.lds $< -o $@ + $(Q)$(LD) -r -T $(OUT)romlayout32flat.lds $< -o $@
-$(OUT)rom.o: $(OUT)rom16.o $(OUT)rom32.o $(OUT)rombios16.lds $(OUT)rombios.lds +$(OUT)rom.o: $(OUT)rom16.o $(OUT)rom32flat.o $(OUT)rombios16.lds $(OUT)rombios.lds @echo " Linking $@" - $(Q)$(LD) -T $(OUT)rombios16.lds $(OUT)rom16.o -R $(OUT)rom32.o -o $(OUT)rom16.reloc.o + $(Q)$(LD) -T $(OUT)rombios16.lds $(OUT)rom16.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)rom32.o -R $(OUT)rom16.moved.o -o $@ + $(Q)$(LD) -T $(OUT)rombios.lds $(OUT)rom16.final.o $(OUT)rom32flat.o -R $(OUT)rom16.moved.o -o $@
$(OUT)bios.bin.elf $(OUT)bios.bin: $(OUT)rom.o tools/checkrom.py @echo " Prepping $@" diff --git a/src/biosvar.h b/src/biosvar.h index aeebf0f..6a789e4 100644 --- a/src/biosvar.h +++ b/src/biosvar.h @@ -238,7 +238,7 @@ static inline u16 get_ebda_seg() { static inline struct extended_bios_data_area_s * get_ebda_ptr() { - ASSERT32(); + ASSERT32FLAT(); return MAKE_FLATPTR(get_ebda_seg(), 0); } #define GET_EBDA2(eseg, var) \ @@ -267,10 +267,10 @@ static inline u16 get_global_seg() { #define GET_GLOBAL(var) \ GET_VAR(GLOBAL_SEGREG, (var)) #define SET_GLOBAL(var, val) do { \ - ASSERT32(); \ + ASSERT32FLAT(); \ (var) = (val); \ } while (0) -#if MODE16 +#if MODESEGMENT #define ADJUST_GLOBAL_PTR(var) (var) #else #define ADJUST_GLOBAL_PTR(var) ((typeof(var))((void*)var - BUILD_BIOS_ADDR)) diff --git a/src/block.c b/src/block.c index 1fbfada..3fb5e91 100644 --- a/src/block.c +++ b/src/block.c @@ -283,7 +283,7 @@ map_floppy_drive(struct drive_s *drive_g) void describe_drive(struct drive_s *drive_g) { - ASSERT32(); + ASSERT32FLAT(); u8 type = GET_GLOBAL(drive_g->type); switch (type) { case DTYPE_FLOPPY: diff --git a/src/boot.c b/src/boot.c index 05de715..c427c00 100644 --- a/src/boot.c +++ b/src/boot.c @@ -486,7 +486,7 @@ do_boot(u16 seq_nr) }
// Boot Failure recovery: try the next device. -void VISIBLE32 +void VISIBLE32FLAT handle_18() { debug_serial_setup(); @@ -498,7 +498,7 @@ handle_18() }
// INT 19h Boot Load Service Entry Point -void VISIBLE32 +void VISIBLE32FLAT handle_19() { debug_serial_setup(); diff --git a/src/farptr.h b/src/farptr.h index acc9d59..3cc4170 100644 --- a/src/farptr.h +++ b/src/farptr.h @@ -122,9 +122,9 @@ extern void __force_link_error__unknown_type(); #define MAKE_FLATPTR(seg,off) ((void*)(((u32)(seg)<<4)+(u32)(off)))
-#if MODE16 == 1 +#if MODESEGMENT == 1
-// Definitions when in 16 bit mode. +// Definitions when using segmented mode. #define GET_FARVAR(seg, var) __GET_FARVAR((seg), (var)) #define SET_FARVAR(seg, var, val) __SET_FARVAR((seg), (var), (val)) #define GET_VAR(seg, var) __GET_VAR(seg, (var)) @@ -159,13 +159,9 @@ static inline void outsl_fl(u16 port, void *ptr_fl, u16 count) { outsl(port, (u32*)FLATPTR_TO_OFFSET(ptr_fl), count); }
-extern void __force_link_error__only_in_32bit() __attribute__ ((noreturn)); -#define ASSERT16() do { } while (0) -#define ASSERT32() __force_link_error__only_in_32bit() - #else
-// In 32-bit mode there is no need to mess with the segments. +// In 32-bit flat mode there is no need to mess with the segments. #define GET_FARVAR(seg, var) \ (*((typeof(&(var)))MAKE_FLATPTR((seg), &(var)))) #define SET_FARVAR(seg, var, val) \ @@ -184,10 +180,6 @@ extern void __force_link_error__only_in_32bit() __attribute__ ((noreturn)); #define outsw_fl(port, ptr_fl, count) outsw(port, ptr_fl, count) #define outsl_fl(port, ptr_fl, count) outsl(port, ptr_fl, count)
-extern void __force_link_error__only_in_16bit() __attribute__ ((noreturn)); -#define ASSERT16() __force_link_error__only_in_16bit() -#define ASSERT32() do { } while (0) - #endif
// Definition for common 16bit segment/offset pointers. diff --git a/src/output.c b/src/output.c index e49010d..3b0e0e7 100644 --- a/src/output.c +++ b/src/output.c @@ -84,10 +84,10 @@ putc_debug(struct putcinfo *action, char c) debug_serial(c); }
-// In 16bit mode just need a dummy variable (putc_debug is always used -// anyway), and in 32bit mode need a pointer to the 32bit instance of -// putc_debug(). -#if MODE16 +// 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 static struct putcinfo debuginfo VAR16; #else static struct putcinfo debuginfo = { putc_debug }; @@ -132,8 +132,8 @@ static struct putcinfo screeninfo = { putc_screen }; static void putc(struct putcinfo *action, char c) { - if (MODE16) { - // Only debugging output supported in 16bit mode. + if (MODESEGMENT) { + // Only debugging output supported in segmented mode. putc_debug(action, c); return; } @@ -325,7 +325,7 @@ panic(const char *fmt, ...) void __dprintf(const char *fmt, ...) { - if (!MODE16 && CONFIG_THREADS && CONFIG_DEBUG_LEVEL >= DEBUG_thread + if (!MODESEGMENT && CONFIG_THREADS && CONFIG_DEBUG_LEVEL >= DEBUG_thread && *fmt != '\' && *fmt != '/') { struct thread_info *cur = getCurThread(); if (cur != &MainThread) { @@ -347,7 +347,7 @@ __dprintf(const char *fmt, ...) void printf(const char *fmt, ...) { - ASSERT32(); + ASSERT32FLAT(); va_list args; va_start(args, fmt); bvprintf(&screeninfo, fmt, args); @@ -382,7 +382,7 @@ putc_str(struct putcinfo *info, char c) int snprintf(char *str, size_t size, const char *fmt, ...) { - ASSERT32(); + ASSERT32FLAT(); if (!size) return 0; struct snprintfinfo sinfo = { { putc_str }, str, str + size }; diff --git a/src/pmm.c b/src/pmm.c index 48a882a..a72167b 100644 --- a/src/pmm.c +++ b/src/pmm.c @@ -11,7 +11,7 @@ #include "biosvar.h" // GET_BDA
-#if MODE16 +#if MODESEGMENT // The 16bit pmm entry points runs in "big real" mode, and can // therefore read/write to the 32bit malloc variables. #define GET_PMMVAR(var) GET_FARVAR(0, (var)) @@ -26,11 +26,11 @@ struct zone_s { u32 top, bottom, cur; };
-struct zone_s ZoneLow VAR32VISIBLE, ZoneHigh VAR32VISIBLE; -struct zone_s ZoneFSeg VAR32VISIBLE; -struct zone_s ZoneTmpLow VAR32VISIBLE, ZoneTmpHigh VAR32VISIBLE; +struct zone_s ZoneLow VAR32FLATVISIBLE, ZoneHigh VAR32FLATVISIBLE; +struct zone_s ZoneFSeg VAR32FLATVISIBLE; +struct zone_s ZoneTmpLow VAR32FLATVISIBLE, ZoneTmpHigh VAR32FLATVISIBLE;
-struct zone_s *Zones[] VAR32VISIBLE = { +struct zone_s *Zones[] VAR32FLATVISIBLE = { &ZoneTmpLow, &ZoneLow, &ZoneFSeg, &ZoneTmpHigh, &ZoneHigh };
@@ -49,7 +49,7 @@ relocate_ebda(u32 newebda, u32 oldebda, u8 ebda_size) return -1;
// Do copy - if (MODE16) + if (MODESEGMENT) memcpy_far(FLATPTR_TO_SEG(newebda) , (void*)FLATPTR_TO_OFFSET(newebda) , FLATPTR_TO_SEG(oldebda) @@ -172,7 +172,7 @@ struct pmmalloc_s { struct pmmalloc_s *next; };
-struct pmmalloc_s *PMMAllocs VAR32VISIBLE; +struct pmmalloc_s *PMMAllocs VAR32FLATVISIBLE;
// Allocate memory from the given zone and track it as a PMM allocation void * @@ -279,7 +279,7 @@ pmm_find(u32 handle) void malloc_setup() { - ASSERT32(); + ASSERT32FLAT(); dprintf(3, "malloc setup\n");
PMMAllocs = NULL; diff --git a/src/post.c b/src/post.c index f087a27..2f14aa7 100644 --- a/src/post.c +++ b/src/post.c @@ -234,7 +234,7 @@ post() }
// 32-bit entry point. -void VISIBLE32 +void VISIBLE32FLAT _start() { init_dma(); diff --git a/src/resume.c b/src/resume.c index 097bb6f..59bb901 100644 --- a/src/resume.c +++ b/src/resume.c @@ -93,8 +93,8 @@ handle_resume(u8 status) panic("Unimplemented shutdown status: %02x\n", status); }
-#if MODE16==0 -void VISIBLE32 +#if MODESEGMENT == 0 +void VISIBLE32FLAT s3_resume() { if (!CONFIG_S3_RESUME) diff --git a/src/smm.c b/src/smm.c index 31e56d8..be2291b 100644 --- a/src/smm.c +++ b/src/smm.c @@ -11,7 +11,7 @@ #include "ioport.h" // outb #include "pci_ids.h" // PCI_VENDOR_ID_INTEL
-ASM32( +ASM32FLAT( ".global smm_relocation_start\n" ".global smm_relocation_end\n" ".global smm_code_start\n" diff --git a/src/smp.c b/src/smp.c index 00cf64b..913d3a2 100644 --- a/src/smp.c +++ b/src/smp.c @@ -8,7 +8,6 @@ #include "util.h" // dprintf #include "config.h" // CONFIG_* #include "cmos.h" // CMOS_BIOS_SMP_COUNT -#include "farptr.h" // ASSERT32 #include "paravirt.h"
#define APIC_ICR_LOW ((u8*)BUILD_APIC_ADDR + 0x300) @@ -70,7 +69,7 @@ ASM16( void smp_probe(void) { - ASSERT32(); + ASSERT32FLAT(); u32 eax, ebx, ecx, cpuid_features; cpuid(1, &eax, &ebx, &ecx, &cpuid_features); if (! (cpuid_features & CPUID_APIC)) { diff --git a/src/stacks.c b/src/stacks.c index 56d17a1..0ddb9a8 100644 --- a/src/stacks.c +++ b/src/stacks.c @@ -168,7 +168,7 @@ switch_next(struct thread_info *cur) void yield() { - if (MODE16 || !CONFIG_THREADS) { + if (MODESEGMENT || !CONFIG_THREADS) { // Just directly check irqs. check_irqs(); return; @@ -198,7 +198,7 @@ __end_thread(struct thread_info *old) void run_thread(void (*func)(void*), void *data) { - ASSERT32(); + ASSERT32FLAT(); if (! CONFIG_THREADS) goto fail; struct thread_info *thread; @@ -241,7 +241,7 @@ fail: void wait_threads() { - ASSERT32(); + ASSERT32FLAT(); if (! CONFIG_THREADS) return; while (MainThread.next != &MainThread) @@ -278,9 +278,9 @@ finish_preempt() }
extern void yield_preempt(); -#if !MODE16 +#if MODESEGMENT == 0 // Try to execute 32bit threads. -void VISIBLE32 +void VISIBLE32FLAT yield_preempt() { PreemptCount++; diff --git a/src/types.h b/src/types.h index 8b9fbb1..b9786e2 100644 --- a/src/types.h +++ b/src/types.h @@ -38,8 +38,8 @@ union u64_u32_u { #if MODE16 == 1 // Notes a function as externally visible in the 16bit code chunk. # define VISIBLE16 __VISIBLE -// Notes a function as externally visible in the 32bit code chunk. -# define VISIBLE32 +// Notes a function as externally visible in the 32bit flat code chunk. +# define VISIBLE32FLAT // 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. @@ -49,21 +49,28 @@ union u64_u32_u { // Designate a variable at a specific 16bit address # define VAR16FIXED(addr) __aligned(1) __VISIBLE __section(".fixedaddr." __stringify(addr)) // Designate a 32bit variable also available in 16bit "big real" mode. -# define VAR32VISIBLE __section(".discard.var32." UNIQSEC) __VISIBLE __weak +# define VAR32FLATVISIBLE __section(".discard.var32flat." UNIQSEC) __VISIBLE __weak // Designate top-level assembler as 16bit only. # define ASM16(code) __ASM(code) -// Designate top-level assembler as 32bit only. -# define ASM32(code) +// 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() #else # define VISIBLE16 -# define VISIBLE32 __VISIBLE +# define VISIBLE32FLAT __VISIBLE # define VAR16 __section(".discard.var16." UNIQSEC) # define VAR16VISIBLE VAR16 __VISIBLE __weak # define VAR16EXPORT VAR16VISIBLE # define VAR16FIXED(addr) VAR16VISIBLE -# define VAR32VISIBLE __VISIBLE +# define VAR32FLATVISIBLE __VISIBLE # define ASM16(code) -# define ASM32(code) __ASM(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
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) diff --git a/src/util.c b/src/util.c index f5ae0e1..552f944 100644 --- a/src/util.c +++ b/src/util.c @@ -18,7 +18,7 @@ inline void call16(struct bregs *callregs) { - if (!MODE16 && getesp() > BUILD_STACK_ADDR) + if (!MODESEGMENT && getesp() > BUILD_STACK_ADDR) panic("call16 with invalid stack\n"); asm volatile( #if MODE16 == 1 @@ -36,7 +36,7 @@ call16(struct bregs *callregs) inline void call16big(struct bregs *callregs) { - ASSERT32(); + ASSERT32FLAT(); if (getesp() > BUILD_STACK_ADDR) panic("call16 with invalid stack\n"); asm volatile( @@ -49,7 +49,7 @@ call16big(struct bregs *callregs) inline void __call16_int(struct bregs *callregs, u16 offset) { - if (MODE16) + if (MODESEGMENT) callregs->code.seg = GET_SEG(CS); else callregs->code.seg = SEG_BIOS; @@ -197,7 +197,7 @@ memcpy_far(u16 d_seg, void *d_far, u16 s_seg, const void *s_far, size_t len) void * #undef memcpy memcpy(void *d1, const void *s1, size_t len) -#if MODE16 == 0 +#if MODESEGMENT == 0 #define memcpy __builtin_memcpy #endif { diff --git a/src/util.h b/src/util.h index 24e39d1..7d95cbe 100644 --- a/src/util.h +++ b/src/util.h @@ -176,7 +176,7 @@ void *memset(void *s, int c, size_t n); inline void memcpy_far(u16 d_seg, void *d_far , u16 s_seg, const void *s_far, size_t len); void *memcpy(void *d1, const void *s1, size_t len); -#if MODE16 == 0 +#if MODESEGMENT == 0 #define memcpy __builtin_memcpy #endif void iomemcpy(void *d, const void *s, u32 len);
Add support for 32bit PCI BIOS entry.
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:%ebx. Add BIOS32 structure and code. Add code for 32bit PCI BIOS code.
diff --git a/Makefile b/Makefile index 26c9461..a5fd63d 100644 --- 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 +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 $@" diff --git a/src/biosvar.h b/src/biosvar.h index 6a789e4..eb34286 100644 --- a/src/biosvar.h +++ b/src/biosvar.h @@ -260,12 +260,21 @@ 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 +// %ebx with the base code offset. +#define GLOBAL_SEGREG GS +#define GLOBAL_OFFSET __CodeOffset +#else #define GLOBAL_SEGREG CS +#define GLOBAL_OFFSET 0 +#endif static inline u16 get_global_seg() { return GET_SEG(GLOBAL_SEGREG); } #define GET_GLOBAL(var) \ - GET_VAR(GLOBAL_SEGREG, (var)) + GET_VAR(GLOBAL_SEGREG, *(typeof(&(var)))((void*)&(var) + GLOBAL_OFFSET)) #define SET_GLOBAL(var, val) do { \ ASSERT32FLAT(); \ (var) = (val); \ diff --git a/src/config.h b/src/config.h index cf5678d..1450bf7 100644 --- a/src/config.h +++ b/src/config.h @@ -192,6 +192,7 @@ #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 diff --git a/src/optionroms.c b/src/optionroms.c index 0be6852..31bb98b 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -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 diff --git a/src/output.c b/src/output.c index 3b0e0e7..2e7175e 100644 --- a/src/output.c +++ b/src/output.c @@ -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 diff --git a/src/pcibios.c b/src/pcibios.c index 6fb7d9e..91b7655 100644 --- a/src/pcibios.c +++ b/src/pcibios.c @@ -12,6 +12,10 @@ #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,7 @@ 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) + GLOBAL_OFFSET , pirsize);
// XXX - bochs bios sets bx to (1 << 9) | (1 << 11) @@ -192,3 +195,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)); +} diff --git a/src/pmm.c b/src/pmm.c index d05cc6f..dab8fb3 100644 --- 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; diff --git a/src/post.c b/src/post.c index 2f14aa7..db9d8f7 100644 --- a/src/post.c +++ b/src/post.c @@ -189,6 +189,7 @@ post() smm_init();
// Setup interfaces that option roms may need + bios32_setup(); pmm_setup(); pnp_setup(); kbd_setup(); diff --git a/src/rombios.lds.S b/src/rombios.lds.S index 6f6040b..20cbebe 100644 --- a/src/rombios.lds.S +++ b/src/rombios.lds.S @@ -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/romlayout.S b/src/romlayout.S index b651a2b..afdefed 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -374,6 +374,64 @@ 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 + calll 1f // Setup %ebx to be code base +1: popl %ebx + subl $1b, %ebx + 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: diff --git a/src/types.h b/src/types.h index b9786e2..cc64cba 100644 --- a/src/types.h +++ b/src/types.h @@ -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,35 @@ 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 +register u32 __CodeOffset asm ("ebx") __VISIBLE; +# 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 diff --git a/src/util.h b/src/util.h index 7d95cbe..7117fa5 100644 --- a/src/util.h +++ b/src/util.h @@ -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(); diff --git a/tools/checkrom.py b/tools/checkrom.py index 6f7b3ba..5c9600f 100755 --- a/tools/checkrom.py +++ b/tools/checkrom.py @@ -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 diff --git a/tools/layoutrom.py b/tools/layoutrom.py index 85bdc7d..3113407 100755 --- a/tools/layoutrom.py +++ b/tools/layoutrom.py @@ -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()