Use ld to build final rom; remove custom build utilities.

It's possible to build the final rom with a little LD magic - so use
    that instead of the buildrom.py / defsyms.py method.
Also, rename all occurances of ".globl" to the more clear ".global".
This commit is contained in:
Kevin O'Connor 2008-07-05 20:41:53 -04:00
parent f85fde0cb7
commit 2fda7cbb23
11 changed files with 173 additions and 261 deletions

View File

@ -81,13 +81,6 @@ $(OUT)%.lds: %.lds.S
@echo " Precompiling $<"
$(Q)$(CPP) -P $< -o $@
$(OUT)%.bin: $(OUT)%.o
@echo " Extracting binary $@"
$(Q)objcopy -O binary $< $@
$(OUT)%.offset.auto.h: $(OUT)%.o
@echo " Generating symbol offset header $@"
$(Q)nm $< | ./tools/defsyms.py $@
$(OUT)blob.16.s: ; $(call whole-compile, $(CFLAGS16) -S, $(addprefix src/, $(SRC16)),$@)
@ -96,20 +89,30 @@ $(OUT)romlayout16.o: romlayout.S $(OUT)blob.16.s $(TABLEASM)
@echo " Generating 16bit layout of $@"
$(Q)$(CC) $(CFLAGS16) -c $< -o $@
$(OUT)rom16.o: $(OUT)romlayout16.o $(OUT)rombios16.lds
$(OUT)romlayout32.o: ; $(call whole-compile, $(CFLAGS), $(addprefix src/, $(SRC32)),$@)
$(OUT)rom32.notreloc.o: $(OUT)romlayout32.o $(OUT)rombios32.lds
@echo " Linking (no relocs) $@"
$(Q)ld -r -T $(OUT)rombios32.lds $< -o $@.raw
$(Q)objcopy --prefix-symbols=_code32_ $@.raw $@
$(OUT)rom16.o: $(OUT)romlayout16.o $(OUT)rom32.notreloc.o $(OUT)rombios16.lds
@echo " Linking $@"
$(Q)ld -T $(OUT)rombios16.lds $< -o $@.16
$(Q)objcopy --change-addresses 0xf0000 $@.16 $@
$(Q)ld -T $(OUT)rombios16.lds -R $(OUT)rom32.notreloc.o $< -o $@
$(OUT)romlayout32.o: $(OUT)rom16.offset.auto.h ; $(call whole-compile, $(CFLAGS), $(addprefix src/, $(SRC32)),$@)
$(OUT)rom32.o: $(OUT)romlayout32.o $(OUT)rombios32.lds
$(OUT)rom32.o: $(OUT)rom16.o $(OUT)romlayout32.o $(OUT)rombios32.lds
@echo " Linking $@"
$(Q)ld -T $(OUT)rombios32.lds $< -o $@
$(Q)ld -T $(OUT)rombios32.lds $(OUT)rom16.o $(OUT)romlayout32.o -o $@
$(Q)nm $@ | ./tools/checkrom.py
$(OUT)bios.bin.elf: $(OUT)rom32.o
@echo " Stripping $<"
$(Q)strip $< -o $@
$(OUT)bios.bin: $(OUT)bios.bin.elf
@echo " Extracting binary $@"
$(Q)objcopy -O binary $< $@
$(OUT)bios.bin: $(OUT)rom16.bin $(OUT)rom32.bin $(OUT)rom16.offset.auto.h $(OUT)rom32.offset.auto.h
@echo " Building $@"
$(Q)./tools/buildrom.py
####### Generic rules
clean:

View File

@ -132,8 +132,11 @@ u32 bios_table_cur_addr, bios_table_end_addr;
void
memmap_setup()
{
bios_table_cur_addr = OFFSET_freespace2_start;
bios_table_end_addr = OFFSET_freespace2_end;
// Symbols defined in romlayout.S
extern char freespace2_start, freespace2_end;
bios_table_cur_addr = (u32)&freespace2_start;
bios_table_end_addr = (u32)&freespace2_end;
dprintf(1, "bios_table_addr: 0x%08x end=0x%08x\n",
bios_table_cur_addr, bios_table_end_addr);
}

View File

@ -6,7 +6,6 @@
// This file may be distributed under the terms of the GNU GPLv3 license.
#include "ioport.h" // PORT_*
#include "../out/rom16.offset.auto.h" // OFFSET_*
#include "config.h" // CONFIG_*
#include "cmos.h" // CMOS_*
#include "util.h" // memset
@ -23,12 +22,36 @@
#define ebda ((struct extended_bios_data_area_s *)MAKE_FARPTR(SEG_EBDA, 0))
static void
set_irq(int vector, u32 loc)
set_irq(int vector, void *loc)
{
SET_BDA(ivecs[vector].seg, SEG_BIOS);
SET_BDA(ivecs[vector].offset, loc - BUILD_BIOS_ADDR);
SET_BDA(ivecs[vector].offset, (u32)loc - BUILD_BIOS_ADDR);
}
// Symbols defined in romlayout.S
extern void dummy_iret_handler();
extern void entry_08();
extern void entry_09();
extern void entry_hwirq();
extern void entry_0e();
extern void entry_10();
extern void entry_11();
extern void entry_12();
extern void entry_13();
extern void entry_14();
extern void entry_15();
extern void entry_16();
extern void entry_17();
extern void entry_18();
extern void entry_19();
extern void entry_1a();
extern void entry_1c();
extern void entry_40();
extern void entry_70();
extern void entry_74();
extern void entry_75();
extern void entry_76();
static void
init_bda()
{
@ -39,44 +62,44 @@ init_bda()
int i;
for (i=0; i<256; i++)
set_irq(i, OFFSET_dummy_iret_handler);
set_irq(i, &dummy_iret_handler);
set_irq(0x08, OFFSET_entry_08);
set_irq(0x09, OFFSET_entry_09);
//set_irq(0x0a, OFFSET_entry_hwirq);
//set_irq(0x0b, OFFSET_entry_hwirq);
//set_irq(0x0c, OFFSET_entry_hwirq);
//set_irq(0x0d, OFFSET_entry_hwirq);
set_irq(0x0e, OFFSET_entry_0e);
//set_irq(0x0f, OFFSET_entry_hwirq);
set_irq(0x10, OFFSET_entry_10);
set_irq(0x11, OFFSET_entry_11);
set_irq(0x12, OFFSET_entry_12);
set_irq(0x13, OFFSET_entry_13);
set_irq(0x14, OFFSET_entry_14);
set_irq(0x15, OFFSET_entry_15);
set_irq(0x16, OFFSET_entry_16);
set_irq(0x17, OFFSET_entry_17);
set_irq(0x18, OFFSET_entry_18);
set_irq(0x19, OFFSET_entry_19);
set_irq(0x1a, OFFSET_entry_1a);
set_irq(0x1c, OFFSET_entry_1c);
set_irq(0x40, OFFSET_entry_40);
set_irq(0x70, OFFSET_entry_70);
//set_irq(0x71, OFFSET_entry_hwirq);
//set_irq(0x72, OFFSET_entry_hwirq);
//set_irq(0x73, OFFSET_entry_hwirq);
set_irq(0x74, OFFSET_entry_74);
set_irq(0x75, OFFSET_entry_75);
set_irq(0x76, OFFSET_entry_76);
//set_irq(0x77, OFFSET_entry_hwirq);
set_irq(0x08, &entry_08);
set_irq(0x09, &entry_09);
//set_irq(0x0a, &entry_hwirq);
//set_irq(0x0b, &entry_hwirq);
//set_irq(0x0c, &entry_hwirq);
//set_irq(0x0d, &entry_hwirq);
set_irq(0x0e, &entry_0e);
//set_irq(0x0f, &entry_hwirq);
set_irq(0x10, &entry_10);
set_irq(0x11, &entry_11);
set_irq(0x12, &entry_12);
set_irq(0x13, &entry_13);
set_irq(0x14, &entry_14);
set_irq(0x15, &entry_15);
set_irq(0x16, &entry_16);
set_irq(0x17, &entry_17);
set_irq(0x18, &entry_18);
set_irq(0x19, &entry_19);
set_irq(0x1a, &entry_1a);
set_irq(0x1c, &entry_1c);
set_irq(0x40, &entry_40);
set_irq(0x70, &entry_70);
//set_irq(0x71, &entry_hwirq);
//set_irq(0x72, &entry_hwirq);
//set_irq(0x73, &entry_hwirq);
set_irq(0x74, &entry_74);
set_irq(0x75, &entry_75);
set_irq(0x76, &entry_76);
//set_irq(0x77, &entry_hwirq);
// set vector 0x79 to zero
// this is used by 'gardian angel' protection system
SET_BDA(ivecs[0x79].seg, 0);
SET_BDA(ivecs[0x79].offset, 0);
set_irq(0x1E, OFFSET_diskette_param_table2);
set_irq(0x1E, &diskette_param_table2);
}
static void
@ -187,7 +210,8 @@ callrom(u16 seg, u16 offset)
memset(&br, 0, sizeof(br));
br.es = SEG_BIOS;
// starts 1 past for alignment
br.di = OFFSET_pnp_string - BUILD_BIOS_ADDR + 1;
extern char pnp_string[];
br.di = (u32)pnp_string - BUILD_BIOS_ADDR + 1;
br.cs = seg;
br.ip = offset;
call16(&br);
@ -358,8 +382,8 @@ _start()
interactive_bootmenu();
// Setup bios checksum.
*(u8*)OFFSET_bios_checksum = -checksum((u8*)BUILD_BIOS_ADDR
, BUILD_BIOS_SIZE - 1);
extern char bios_checksum;
bios_checksum = -checksum((u8*)BUILD_BIOS_ADDR, BUILD_BIOS_SIZE - 1);
// Prep for boot process.
make_bios_readonly();
@ -372,14 +396,19 @@ _start()
call16_int(0x19, &br);
}
// Ughh - some older gcc compilers have a bug which causes VISIBLE32
// functions to not be exported as a global variable - force _start
// to be global here.
asm(".global _start");
// Externally visible 32bit entry point.
asm(
".global post32\n"
"post32:\n"
"cli\n"
"cld\n"
"lidtl " __stringify(OFFSET_pmode_IDT_info) "\n"
"lgdtl " __stringify(OFFSET_rombios32_gdt_48) "\n"
"lidtl pmode_IDT_info\n"
"lgdtl rombios32_gdt_48\n"
"movl $" __stringify(BUILD_STACK_ADDR) ", %esp\n"
"ljmp $0x10, $_start\n"
);

View File

@ -1,7 +1,6 @@
// Linker definitions for 16bit code
//
// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2002 MandrakeSoft S.A.
//
// This file may be distributed under the terms of the GNU GPLv3 license.
@ -9,23 +8,15 @@
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH("i386")
ENTRY(post16);
SECTIONS
{
. = 0;
.text : {
.text16 ( _code32_code16_start - BUILD_BIOS_ADDR ) : {
*(.text)
*(.rodata)
*(.rodata.*)
*(.rodata*)
*(.data)
bios16c_end = .;
. = BUILD_START_FIXED;
*(.text.fixed.addr)
}
/DISCARD/ : { *(.stab)
*(.stabstr)
*(.comment)
*(.note)
}
.text16.fixed.addr BUILD_START_FIXED : {
*(.text.fixed.addr)
}
}

View File

@ -1,32 +1,38 @@
// Linker definitions for 32bit code
// Linker definitions for 16 and 32 bit code
//
// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
// Copyright (C) 2002 MandrakeSoft S.A.
//
// This file may be distributed under the terms of the GNU GPLv3 license.
#include "config.h"
#include "../out/rom16.offset.auto.h"
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH("i386")
ENTRY(post32);
SECTIONS
{
. = OFFSET_bios16c_end;
. = ALIGN(16);
_text32_start = . ;
.text : { *(.text) }
.rodata : { *(.rodata) }
.data : { *(.data) }
. = BUILD_BSS_ADDR;
__bss_start = . ;
.bss : { *(.bss) *(COMMON) }
__bss_end = . ;
__call16_from32 = OFFSET___call16_from32;
/DISCARD/ : { *(.stab)
*(.stabstr)
*(.comment)
*(.note)
}
.text BUILD_BIOS_ADDR : {
code32_start = . ;
*(.text)
*(.rodata*)
*(.data)
code32_end = . ;
. = ALIGN(16) ;
code16_start = . ;
*(.text16)
code16_end = . ;
freespace1_start = . ;
. = BUILD_START_FIXED ;
freespace1_end = . ;
*(.text16.fixed.addr)
}
.bss BUILD_BSS_ADDR : {
__bss_start = . ;
*(.bss)
*(COMMON)
__bss_end = . ;
}
}

View File

@ -124,16 +124,11 @@
****************************************************************/
ORG 0xe05b
.globl post16
post16:
// init the stack pointer
RESET_STACK
// Set entry point of rombios32 code - the actual address
// is altered later in the build process.
.globl set_entry32
set_entry32:
pushl $0xf0000000
pushl $_code32__start
cld
@ -184,7 +179,7 @@ transition32:
// Call a 16bit function from 32bit mode.
// %eax = address of struct bregs
// Clobbers: all gp registers, flags, stack registers, cr0, idt/gdt
.globl __call16_from32
.global __call16_from32
__call16_from32:
pushl %eax
@ -232,7 +227,7 @@ __call16_from32:
// Call a 16bit function from 16bit mode with a specified cpu register state
// %eax = address of struct bregs
// Clobbers: all gp registers, es
.globl __call16
.global __call16
__call16:
// Save eax
pushl %eax
@ -283,7 +278,7 @@ __call16:
// APM trampolines
.globl apm16protected_entry
.global apm16protected_entry
apm16protected_entry:
pushfw // save flags
pushl %eax // dummy
@ -293,7 +288,7 @@ apm16protected_entry:
lretw
.code32
.globl apm32protected_entry
.global apm32protected_entry
apm32protected_entry:
pushfw
pushw %cs // Setup for long jump to 16bit mode
@ -328,6 +323,7 @@ apm32protected_entry:
// Set base to f0000 to correspond to beginning of BIOS,
// in case I actually define an IDT later
// Set limit to 0
.global pmode_IDT_info
pmode_IDT_info:
.word 0x0000 // limit 15:00
.long 0xf0000 // base 16:47
@ -341,6 +337,7 @@ rmode_IDT_info:
.word 0x03ff // limit 15:00
.long 0 // base 16:47
.global rombios32_gdt_48
rombios32_gdt_48:
.word 0x30
.word rombios32_gdt
@ -366,7 +363,7 @@ rombios32_gdt:
// Define an entry point for an interrupt (no args passed).
.macro IRQ_ENTRY num
.globl entry_\num
.global entry_\num
entry_\num :
cli // In case something far-calls instead of using "int"
ENTRY handle_\num
@ -375,7 +372,7 @@ rombios32_gdt:
// Define an entry point for an interrupt (can read/modify args).
.macro IRQ_ENTRY_ARG num
.globl entry_\num
.global entry_\num
entry_\num :
cli // In case something far-calls instead of using "int"
ENTRY_ARG handle_\num
@ -415,19 +412,19 @@ rombios32_gdt:
IRQ_ENTRY 75
// int 18/19 are special - they reset the stack and do not return.
.globl entry_19
.global entry_19
entry_19:
RESET_STACK
ENTRY handle_19
.globl entry_18
.global entry_18
entry_18:
RESET_STACK
ENTRY handle_18
// IRQ trampolines
.macro IRQ_TRAMPOLINE num
.globl irq_trampoline_0x\num
.global irq_trampoline_0x\num
irq_trampoline_0x\num :
int $0x\num
lretw
@ -476,7 +473,7 @@ entry_hwirq:
// XXX int 1D
iretw
.globl freespace2_start, freespace2_end
.global freespace2_start, freespace2_end
freespace2_start:
ORG 0xf841
@ -507,7 +504,7 @@ freespace2_end:
.ascii "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team."
ORG 0xff53
.globl dummy_iret_handler
.global dummy_iret_handler
dummy_iret_handler:
iretw
@ -524,7 +521,7 @@ dummy_iret_handler:
ORG 0xfffe
.byte CONFIG_MODEL_ID
.globl bios_checksum
.global bios_checksum
bios_checksum:
.byte 0x00

View File

@ -49,8 +49,8 @@ static inline u8 readb(const void *addr)
}
asm(
".globl smp_ap_boot_code_start\n"
".globl smp_ap_boot_code_end\n"
".global smp_ap_boot_code_start\n"
".global smp_ap_boot_code_end\n"
" .code16\n"
"smp_ap_boot_code_start:\n"

View File

@ -65,16 +65,10 @@ void *memmove(void *d, const void *s, size_t len);
struct bregs;
inline void call16(struct bregs *callregs);
inline void __call16_int(struct bregs *callregs, u16 offset);
#ifdef MODE16
#define call16_int(nr, callregs) do { \
extern void irq_trampoline_ ##nr (); \
__call16_int((callregs), (u32)&irq_trampoline_ ##nr ); \
} while (0)
#else
#include "../out/rom16.offset.auto.h"
#define call16_int(nr, callregs) \
__call16_int((callregs), OFFSET_irq_trampoline_ ##nr - BUILD_BIOS_ADDR)
#endif
// output.c
void debug_serial_setup();

View File

@ -1,89 +0,0 @@
#!/usr/bin/env python
# Script to merge a rom32.bin file into a rom16.bin file.
#
# Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import sys
import struct
import os
ROM16='out/rom16.bin'
ROM32='out/rom32.bin'
OFFSETS16='out/rom16.offset.auto.h'
OFFSETS32='out/rom32.offset.auto.h'
OUT='out/bios.bin'
def align(v, a):
return (v + a - 1) // a * a
def scanconfig(file):
f = open(file, 'rb')
opts = {}
for l in f.readlines():
parts = l.split()
if len(parts) != 3:
continue
if parts[0] != '#define':
continue
opts[parts[1]] = parts[2]
return opts
def alteraddr(data, offset, ptr):
rel = struct.pack("<i", ptr)
return data[:offset] + rel + data[offset+4:]
def main():
# Read in files
f = open(ROM16, 'rb')
data16 = f.read()
f = open(ROM32, 'rb')
data32 = f.read()
if len(data16) != 65536:
print "16bit code is not 65536 bytes long"
sys.exit(1)
# Get config options
o16 = scanconfig(OFFSETS16)
o32 = scanconfig(OFFSETS32)
# Inject 32bit code
spos = align(int(o16['OFFSET_bios16c_end'], 16), 16)
epos = int(o16['OFFSET_post16'], 16)
size32 = len(data32)
freespace = epos - spos
if size32 > freespace:
print "32bit code too large (%d vs %d)" % (size32, freespace)
sys.exit(1)
spos -= 0xf0000
if data16[spos:spos+size32] != '\0'*size32:
print "Non zero data in 16bit freespace (0x%x to 0x%x)" % (
spos, spos+size32)
sys.exit(1)
outrom = data16[:spos] + data32 + data16[spos+size32:]
# Fixup initial jump to 32 bit code
jmppos = int(o16['OFFSET_set_entry32'], 16) - 0xf0000
start32 = int(o32['OFFSET__start'], 16)
outrom = alteraddr(outrom, jmppos+2, start32)
print "Writing output rom %s" % OUT
print " 16bit C-code size: %d" % spos
print " 32bit C-code size: %d" % size32
print " Total C-code size: %d" % (spos+size32)
# Write output rom
f = open(OUT, 'wb')
f.write(outrom)
f.close()
# Build elf file with 32bit entry point
os.system(
"ld -melf_i386 -e %s -Tdata 0xf0000 -b binary %s -o %s" % (
int(o32['OFFSET_post32'], 16), OUT, OUT+".elf"))
if __name__ == '__main__':
main()

33
tools/checkrom.py Executable file
View File

@ -0,0 +1,33 @@
#!/usr/bin/env python
# Script to check a bios image and report info on it.
#
# Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import sys
def main():
# Read in symbols (that are valid)
syms = {}
for line in sys.stdin.readlines():
try:
addr, type, sym = line.split()
syms[sym] = int(addr, 16)
except:
pass
if syms['code16_start'] != syms['_code32_code16_start']:
print "Error! 16bit code moved during linking"
sys.exit(1)
size16 = syms['code16_end'] - syms['code16_start']
size32 = syms['code32_end'] - syms['code32_start']
sizefree = syms['freespace1_end'] - syms['freespace1_start']
print "16bit C-code size: %d" % size16
print "32bit C-code size: %d" % size32
print "Total C-code size: %d" % (size16+size32)
print "Free C-code space: %d" % sizefree
if __name__ == '__main__':
main()

View File

@ -1,55 +0,0 @@
#!/usr/bin/env python
# Simple script to convert the output from 'nm' to a C style header
# file with defined offsets.
#
# Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import sys
import string
def printUsage():
print "Usage:\n %s <output file>" % (sys.argv[0],)
sys.exit(1)
def main():
if len(sys.argv) != 2:
printUsage()
# Find symbols (that are valid)
syms = []
lines = sys.stdin.readlines()
for line in lines:
addr, type, sym = line.split()
if type not in 'Tt':
# Only interested in global symbols in text segment
continue
for c in sym:
if c not in string.letters + string.digits + '_':
break
else:
syms.append((sym, addr))
# Build guard string
guardstr = ''
for c in sys.argv[1]:
if c not in string.letters + string.digits + '_':
guardstr += '_'
else:
guardstr += c
# Generate header
f = open(sys.argv[1], 'wb')
f.write("""
#ifndef __OFFSET_AUTO_H__%s
#define __OFFSET_AUTO_H__%s
// Auto generated file - please see defsyms.py.
// This file contains symbol offsets of a compiled binary.
""" % (guardstr, guardstr))
for sym, addr in syms:
f.write("#define OFFSET_%s 0x%s\n" % (sym, addr))
f.write("""
#endif // __OFFSET_AUTO_H__%s
""" % (guardstr,))
if __name__ == '__main__':
main()