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 and with a dynamic code offset (determined by get_global_offset()). Add BIOS32 structure and code. Add code for 32bit PCI BIOS code.
This commit is contained in:
parent
eda2c83bfa
commit
871e0a0c14
39
Makefile
39
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 $@"
|
||||
|
|
|
@ -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); \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -189,6 +189,7 @@ post()
|
|||
smm_init();
|
||||
|
||||
// Setup interfaces that option roms may need
|
||||
bios32_setup();
|
||||
pmm_setup();
|
||||
pnp_setup();
|
||||
kbd_setup();
|
||||
|
|
|
@ -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 = . ;
|
||||
}
|
||||
|
|
|
@ -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*) }
|
||||
}
|
|
@ -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:
|
||||
|
|
30
src/types.h
30
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,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()
|
||||
#else
|
||||
#elif MODESEGMENT == 1
|
||||
# define VISIBLE16
|
||||
# define VISIBLE32FLAT __VISIBLE
|
||||
# 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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, alt, pri)
|
||||
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, 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()
|
||||
|
|
Loading…
Reference in New Issue