[U-Boot] [PATCH 00/10] i386 Relocation

This patch series implements full relocation support for the i386 port of U-Boot.
The first 5 patches came about due to my toolchain upgrade (to gcc 4.4.1 and binutils 2.19) (patch 4 id really just a quick tidy-up)
Patch 6 is a standalone bug-fix to resolve a start-up race condition
Patch 7 sets up the i386 interupt handling to be relocation friendly
Patches 8 and 9 are a relocation setup patch - no functionality change
By the end of patch 9, the i386 port is still non-relocatable
Patch 10 is the actual Relocation Patch itself
Relocation is achieved by utilising the -pie ld command line option and minimal boot-up processing of the resulting .rel.dyn section. By not using gcc's -fpie flag, the overhead of .got and the call/pop in each function entry is avoided - This prevents bloat of .text and .got and avoids the performance penalty of GOT lookups
This relocation scheme is possibly usable on many other arches
Many thanks to Joakim Tjernlund and Bill Campbell for their invaluable assistance and references.
Size analysis: Non-Reloc Reloc ------------------------------------- .text 0x00011970 0x00011850 .plt 0x00000000 .rodata 0x00005bae 0x00005b49 .data 0x00000a5c 0x00000a3c .interp 0x00000013 .dynsym 0x000000f0 .dynstr 0x00000113 .hash 0x00000050 .got 0x00000000 0x00000000 .got.plt 0x0000000c .dynamic 0x00000080 .u_boot_cmd 0x000003c0 0x000003c0 .rel.dyn 0x00004190 .bss 0x00001a34 0x00001a34 .realmode 0x00000166 0x00000166 .bios 0x0000053e 0x0000053e .start16 0x000000bc 0x000000bc .resetvec 0x00000010 0x00000010 ===================================== 0x0001a4de 0x0001e7bb
~17kB increase in binary image size (of which ~16kb is .rel.dyn which is not copied to RAM). Post processing of .rel.dyn could reduce the overhead by a further ~8kB - Speed improvement would be negligble and the only saving would be in image size, not RAM utilisation.

Warning introduced by GCC 4.4.1
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- board/eNET/config.mk | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/board/eNET/config.mk b/board/eNET/config.mk index a763841..058026d 100644 --- a/board/eNET/config.mk +++ b/board/eNET/config.mk @@ -22,3 +22,4 @@ #
TEXT_BASE = 0x38040000 +CFLAGS_dlmalloc.o += -Wa,--no-warn -fno-strict-aliasing

Brings i386 malloc init in line with other arches
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- common/dlmalloc.c | 6 ------ include/configs/eNET.h | 2 +- include/configs/sc520_cdp.h | 2 +- include/configs/sc520_spunk.h | 2 +- lib_i386/board.c | 15 +++++++-------- 5 files changed, 10 insertions(+), 17 deletions(-)
diff --git a/common/dlmalloc.c b/common/dlmalloc.c index ca088a1..735b344 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -1522,11 +1522,6 @@ void *sbrk(ptrdiff_t increment) return (void *)old; }
-#ifndef CONFIG_X86 -/* - * x86 boards use a slightly different init sequence thus they implement - * their own version of mem_malloc_init() - */ void mem_malloc_init(ulong start, ulong size) { mem_malloc_start = start; @@ -1535,7 +1530,6 @@ void mem_malloc_init(ulong start, ulong size)
memset((void *)mem_malloc_start, 0, size); } -#endif
/* field-extraction macros */
diff --git a/include/configs/eNET.h b/include/configs/eNET.h index 243a554..54c34fa 100644 --- a/include/configs/eNET.h +++ b/include/configs/eNET.h @@ -61,7 +61,7 @@ /* * Size of malloc() pool */ -#define CONFIG_MALLOC_SIZE (CONFIG_SYS_ENV_SIZE + 128*1024) +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128*1024)
#define CONFIG_BAUDRATE 9600
diff --git a/include/configs/sc520_cdp.h b/include/configs/sc520_cdp.h index 214a9af..2f1dae7 100644 --- a/include/configs/sc520_cdp.h +++ b/include/configs/sc520_cdp.h @@ -65,7 +65,7 @@ /* * Size of malloc() pool */ -#define CONFIG_MALLOC_SIZE (CONFIG_ENV_SIZE + 128*1024) +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128*1024)
#define CONFIG_BAUDRATE 9600
diff --git a/include/configs/sc520_spunk.h b/include/configs/sc520_spunk.h index f3fc960..cf5633c 100644 --- a/include/configs/sc520_spunk.h +++ b/include/configs/sc520_spunk.h @@ -63,7 +63,7 @@ /* * Size of malloc() pool */ -#define CONFIG_MALLOC_SIZE (CONFIG_ENV_SIZE + 128*1024) +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128*1024)
#define CONFIG_BAUDRATE 9600 diff --git a/lib_i386/board.c b/lib_i386/board.c index 12ca20f..ebd7047 100644 --- a/lib_i386/board.c +++ b/lib_i386/board.c @@ -77,17 +77,16 @@ ulong i386boot_bios_size = (ulong)&_i386boot_bios_size; /* size of BIOS const char version_string[] = U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")";
-static int mem_malloc_init(void) +static int heap_init(void) { /* start malloc area right after the stack */ - mem_malloc_start = i386boot_bss_start + - i386boot_bss_size + CONFIG_SYS_STACK_SIZE; - mem_malloc_start = (mem_malloc_start+3)&~3; + ulong start = i386boot_bss_start + i386boot_bss_size + + CONFIG_SYS_STACK_SIZE;
- /* Use all available RAM for malloc() */ - mem_malloc_end = gd->ram_size; + /* 4-byte aligned */ + start = (start+3)&~3;
- mem_malloc_brk = mem_malloc_start; + mem_malloc_init(start, CONFIG_SYS_MALLOC_LEN);
return 0; } @@ -184,7 +183,7 @@ init_fnc_t *init_sequence[] = { cpu_init, /* basic cpu dependent setup */ board_init, /* basic board dependent setup */ dram_init, /* configure available RAM banks */ - mem_malloc_init, /* dependant on dram_init */ + heap_init, /* dependant on dram_init */ interrupt_init, /* set up exceptions */ timer_init, serial_init,

Signed-off-by: Graeme Russ graeme.russ@gmail.com --- board/eNET/config.mk | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/board/eNET/config.mk b/board/eNET/config.mk index 058026d..c9703ea 100644 --- a/board/eNET/config.mk +++ b/board/eNET/config.mk @@ -23,3 +23,4 @@
TEXT_BASE = 0x38040000 CFLAGS_dlmalloc.o += -Wa,--no-warn -fno-strict-aliasing +PLATFORM_CPPFLAGS += -fno-dwarf2-cfi-asm

Signed-off-by: Graeme Russ graeme.russ@gmail.com --- lib_i386/Makefile | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib_i386/Makefile b/lib_i386/Makefile index bb9b330..9838506 100644 --- a/lib_i386/Makefile +++ b/lib_i386/Makefile @@ -32,16 +32,16 @@ SOBJS-y += realmode_switch.o COBJS-y += bios_setup.o COBJS-y += board.o COBJS-y += bootm.o +COBJS-y += interrupts.o +COBJS-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o +COBJS-$(CONFIG_SYS_GENERIC_TIMER) += pcat_timer.o COBJS-$(CONFIG_PCI) += pci.o COBJS-$(CONFIG_PCI) += pci_type1.o COBJS-y += realmode.o +COBJS-y += timer.o COBJS-y += video_bios.o COBJS-y += video.o COBJS-y += zimage.o -COBJS-y += interrupts.o -COBJS-y += timer.o -COBJS-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o -COBJS-$(CONFIG_SYS_GENERIC_TIMER) += pcat_timer.o
SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))

Signed-off-by: Graeme Russ graeme.russ@gmail.com --- include/configs/eNET.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/configs/eNET.h b/include/configs/eNET.h index 54c34fa..0a86550 100644 --- a/include/configs/eNET.h +++ b/include/configs/eNET.h @@ -234,8 +234,8 @@ #ifndef __ASSEMBLER__ extern unsigned long ip;
-#define PRINTIP asm ("call next_line\n" \ - "next_line:\n" \ +#define PRINTIP asm ("call 0\n" \ + "0:\n" \ "pop %%eax\n" \ "movl %%eax, %0\n" \ :"=r"(ip) \

Signed-off-by: Graeme Russ graeme.russ@gmail.com --- cpu/i386/sc520/sc520_timer.c | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/cpu/i386/sc520/sc520_timer.c b/cpu/i386/sc520/sc520_timer.c index 23de14b..25c9a24 100644 --- a/cpu/i386/sc520/sc520_timer.c +++ b/cpu/i386/sc520/sc520_timer.c @@ -35,6 +35,12 @@ void sc520_timer_isr(void)
int timer_init(void) { + /* Register the SC520 specific timer interrupt handler */ + register_timer_isr (sc520_timer_isr); + + /* Install interrupt handler for GP Timer 1 */ + irq_install_handler (0, timer_isr, NULL); + /* Map GP Timer 1 to Master PIC IR0 */ sc520_mmcr->gp_tmr_int_map[1] = 0x01;
@@ -54,11 +60,6 @@ int timer_init(void) sc520_mmcr->gptmr1maxcmpa = 100; sc520_mmcr->gptmr1ctl = 0xe009;
- /* Register the SC520 specific timer interrupt handler */ - register_timer_isr (sc520_timer_isr); - - /* Install interrupt handler for GP Timer 1 */ - irq_install_handler (0, timer_isr, NULL); unmask_irq (0);
/* Clear the GP Timer 1 status register to get the show rolling*/

In preperation for full relocation
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- cpu/i386/Makefile | 2 +- cpu/i386/cpu.c | 1 - cpu/i386/exceptions.c | 229 --------------------- cpu/i386/interrupts.c | 431 ++++++++++++++++++++++++++++++++++++++-- include/asm-i386/interrupt.h | 27 --- include/asm-i386/u-boot-i386.h | 3 - lib_i386/interrupts.c | 4 +- lib_i386/pcat_interrupts.c | 33 --- 8 files changed, 420 insertions(+), 310 deletions(-) delete mode 100644 cpu/i386/exceptions.c
diff --git a/cpu/i386/Makefile b/cpu/i386/Makefile index e98bd3d..c658c6e 100644 --- a/cpu/i386/Makefile +++ b/cpu/i386/Makefile @@ -29,7 +29,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).a
START = start.o start16.o resetvec.o -COBJS = serial.o interrupts.o exceptions.o cpu.o +COBJS = serial.o interrupts.o cpu.o
SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/cpu/i386/cpu.c b/cpu/i386/cpu.c index d91e33b..8baf37d 100644 --- a/cpu/i386/cpu.c +++ b/cpu/i386/cpu.c @@ -48,7 +48,6 @@ int cpu_init(void)
/* Initialize core interrupt and exception functionality of CPU */ cpu_init_interrupts (); - cpu_init_exceptions ();
return 0; } diff --git a/cpu/i386/exceptions.c b/cpu/i386/exceptions.c deleted file mode 100644 index bc3d434..0000000 --- a/cpu/i386/exceptions.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * (C) Copyright 2002 - * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/interrupt.h> - -asm (".globl exp_return\n" - "exp_return:\n" - " addl $12, %esp\n" - " pop %esp\n" - " popa\n" - " iret\n"); - -char exception_stack[4096]; - -/* - * For detailed description of each exception, refer to: - * Intel® 64 and IA-32 Architectures Software Developer's Manual - * Volume 1: Basic Architecture - * Order Number: 253665-029US, November 2008 - * Table 6-1. Exceptions and Interrupts - */ -DECLARE_EXCEPTION(0, divide_error_entry); -DECLARE_EXCEPTION(1, debug_entry); -DECLARE_EXCEPTION(2, nmi_interrupt_entry); -DECLARE_EXCEPTION(3, breakpoint_entry); -DECLARE_EXCEPTION(4, overflow_entry); -DECLARE_EXCEPTION(5, bound_range_exceeded_entry); -DECLARE_EXCEPTION(6, invalid_opcode_entry); -DECLARE_EXCEPTION(7, device_not_available_entry); -DECLARE_EXCEPTION(8, double_fault_entry); -DECLARE_EXCEPTION(9, coprocessor_segment_overrun_entry); -DECLARE_EXCEPTION(10, invalid_tss_entry); -DECLARE_EXCEPTION(11, segment_not_present_entry); -DECLARE_EXCEPTION(12, stack_segment_fault_entry); -DECLARE_EXCEPTION(13, general_protection_entry); -DECLARE_EXCEPTION(14, page_fault_entry); -DECLARE_EXCEPTION(15, reserved_exception_entry); -DECLARE_EXCEPTION(16, floating_point_error_entry); -DECLARE_EXCEPTION(17, alignment_check_entry); -DECLARE_EXCEPTION(18, machine_check_entry); -DECLARE_EXCEPTION(19, simd_floating_point_exception_entry); -DECLARE_EXCEPTION(20, reserved_exception_entry); -DECLARE_EXCEPTION(21, reserved_exception_entry); -DECLARE_EXCEPTION(22, reserved_exception_entry); -DECLARE_EXCEPTION(23, reserved_exception_entry); -DECLARE_EXCEPTION(24, reserved_exception_entry); -DECLARE_EXCEPTION(25, reserved_exception_entry); -DECLARE_EXCEPTION(26, reserved_exception_entry); -DECLARE_EXCEPTION(27, reserved_exception_entry); -DECLARE_EXCEPTION(28, reserved_exception_entry); -DECLARE_EXCEPTION(29, reserved_exception_entry); -DECLARE_EXCEPTION(30, reserved_exception_entry); -DECLARE_EXCEPTION(31, reserved_exception_entry); - -__isr__ reserved_exception_entry(int cause, int ip, int seg) -{ - printf("Reserved Exception %d at %04x:%08x\n", cause, seg, ip); -} - -__isr__ divide_error_entry(int cause, int ip, int seg) -{ - printf("Divide Error (Division by zero) at %04x:%08x\n", seg, ip); - while(1); -} - -__isr__ debug_entry(int cause, int ip, int seg) -{ - printf("Debug Interrupt (Single step) at %04x:%08x\n", seg, ip); -} - -__isr__ nmi_interrupt_entry(int cause, int ip, int seg) -{ - printf("NMI Interrupt at %04x:%08x\n", seg, ip); -} - -__isr__ breakpoint_entry(int cause, int ip, int seg) -{ - printf("Breakpoint at %04x:%08x\n", seg, ip); -} - -__isr__ overflow_entry(int cause, int ip, int seg) -{ - printf("Overflow at %04x:%08x\n", seg, ip); - while(1); -} - -__isr__ bound_range_exceeded_entry(int cause, int ip, int seg) -{ - printf("BOUND Range Exceeded at %04x:%08x\n", seg, ip); - while(1); -} - -__isr__ invalid_opcode_entry(int cause, int ip, int seg) -{ - printf("Invalid Opcode (UnDefined Opcode) at %04x:%08x\n", seg, ip); - while(1); -} - -__isr__ device_not_available_entry(int cause, int ip, int seg) -{ - printf("Device Not Available (No Math Coprocessor) at %04x:%08x\n", seg, ip); - while(1); -} - -__isr__ double_fault_entry(int cause, int ip, int seg) -{ - printf("Double fault at %04x:%08x\n", seg, ip); - while(1); -} - -__isr__ coprocessor_segment_overrun_entry(int cause, int ip, int seg) -{ - printf("Co-processor segment overrun at %04x:%08x\n", seg, ip); - while(1); -} - -__isr__ invalid_tss_entry(int cause, int ip, int seg) -{ - printf("Invalid TSS at %04x:%08x\n", seg, ip); -} - -__isr__ segment_not_present_entry(int cause, int ip, int seg) -{ - printf("Segment Not Present at %04x:%08x\n", seg, ip); - while(1); -} - -__isr__ stack_segment_fault_entry(int cause, int ip, int seg) -{ - printf("Stack Segment Fault at %04x:%08x\n", seg, ip); - while(1); -} - -__isr__ general_protection_entry(int cause, int ip, int seg) -{ - printf("General Protection at %04x:%08x\n", seg, ip); -} - -__isr__ page_fault_entry(int cause, int ip, int seg) -{ - printf("Page fault at %04x:%08x\n", seg, ip); - while(1); -} - -__isr__ floating_point_error_entry(int cause, int ip, int seg) -{ - printf("Floating-Point Error (Math Fault) at %04x:%08x\n", seg, ip); -} - -__isr__ alignment_check_entry(int cause, int ip, int seg) -{ - printf("Alignment check at %04x:%08x\n", seg, ip); -} - -__isr__ machine_check_entry(int cause, int ip, int seg) -{ - printf("Machine Check at %04x:%08x\n", seg, ip); -} - -__isr__ simd_floating_point_exception_entry(int cause, int ip, int seg) -{ - printf("SIMD Floating-Point Exception at %04x:%08x\n", seg, ip); -} - -int cpu_init_exceptions(void) -{ - /* Just in case... */ - disable_interrupts(); - - /* Setup exceptions */ - set_vector(0x00, exp_0); - set_vector(0x01, exp_1); - set_vector(0x02, exp_2); - set_vector(0x03, exp_3); - set_vector(0x04, exp_4); - set_vector(0x05, exp_5); - set_vector(0x06, exp_6); - set_vector(0x07, exp_7); - set_vector(0x08, exp_8); - set_vector(0x09, exp_9); - set_vector(0x0a, exp_10); - set_vector(0x0b, exp_11); - set_vector(0x0c, exp_12); - set_vector(0x0d, exp_13); - set_vector(0x0e, exp_14); - set_vector(0x0f, exp_15); - set_vector(0x10, exp_16); - set_vector(0x11, exp_17); - set_vector(0x12, exp_18); - set_vector(0x13, exp_19); - set_vector(0x14, exp_20); - set_vector(0x15, exp_21); - set_vector(0x16, exp_22); - set_vector(0x17, exp_23); - set_vector(0x18, exp_24); - set_vector(0x19, exp_25); - set_vector(0x1a, exp_26); - set_vector(0x1b, exp_27); - set_vector(0x1c, exp_28); - set_vector(0x1d, exp_29); - set_vector(0x1e, exp_30); - set_vector(0x1f, exp_31); - - /* It is now safe to enable interrupts */ - enable_interrupts(); - - return 0; -} diff --git a/cpu/i386/interrupts.c b/cpu/i386/interrupts.c index 063ea42..d80cfb1 100644 --- a/cpu/i386/interrupts.c +++ b/cpu/i386/interrupts.c @@ -1,4 +1,7 @@ /* + * (C) Copyright 2008 + * Graeme Russ, graeme.russ@gmail.com. + * * (C) Copyright 2002 * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. * @@ -24,6 +27,14 @@ #include <common.h> #include <asm/interrupt.h>
+#define DECLARE_INTERRUPT(x) \ + ".globl irq_"#x"\n" \ + "irq_"#x":\n" \ + "pushl %ebp\n" \ + "movl %esp,%ebp\n" \ + "pusha\n" \ + "pushl $"#x"\n" \ + "jmp irq_common_entry\n"
struct idt_entry { u16 base_low; @@ -33,23 +44,20 @@ struct idt_entry { u16 base_high; } __attribute__ ((packed));
+struct desc_ptr { + unsigned short size; + unsigned long address; + unsigned short segment; +} __attribute__((packed));
struct idt_entry idt[256];
+struct desc_ptr idt_ptr;
-asm (".globl irq_return\n" - "irq_return:\n" - " addl $4, %esp\n" - " popa\n" - " iret\n"); - -void __attribute__ ((regparm(0))) default_isr(void); -asm ("default_isr: iret\n"); - -asm ("idt_ptr:\n" - ".word 0x800\n" /* size of the table 8*256 bytes */ - ".long idt\n" /* offset */ - ".word 0x18\n");/* data segment */ +static inline void load_idt(const struct desc_ptr *dtr) +{ + asm volatile("cs lidt %0"::"m" (*dtr)); +}
void set_vector(u8 intnum, void *routine) { @@ -57,11 +65,16 @@ void set_vector(u8 intnum, void *routine) idt[intnum].base_low = (u16)((u32)(routine + gd->reloc_off) & 0xffff); }
+void irq_0(void); +void irq_1(void);
int cpu_init_interrupts(void) { int i;
+ int irq_entry_size = irq_1 - irq_0; + void *irq_entry = (void *)irq_0; + /* Just in case... */ disable_interrupts();
@@ -70,10 +83,15 @@ int cpu_init_interrupts(void) idt[i].access = 0x8e; idt[i].res = 0; idt[i].selector = 0x10; - set_vector(i, default_isr); + set_vector(i, irq_entry); + irq_entry += irq_entry_size; }
- asm ("cs lidt idt_ptr\n"); + idt_ptr.size = 256 * 8; + idt_ptr.address = (unsigned long) idt; + idt_ptr.segment = 0x18; + + load_idt(&idt_ptr);
/* It is now safe to enable interrupts */ enable_interrupts(); @@ -81,6 +99,12 @@ int cpu_init_interrupts(void) return 0; }
+void __do_irq(int irq) +{ + printf("Unhandled IRQ : %d\n", irq); +} +void do_irq(int irq) __attribute__((weak, alias("__do_irq"))); + void enable_interrupts(void) { asm("sti\n"); @@ -94,3 +118,380 @@ int disable_interrupts(void)
return (flags&0x200); /* IE flags is bit 9 */ } + +/* IRQ Low-Level Service Routine */ +__isr__ irq_llsr(int ip, int seg, int irq) +{ + /* + * For detailed description of each exception, refer to: + * Intel® 64 and IA-32 Architectures Software Developer's Manual + * Volume 1: Basic Architecture + * Order Number: 253665-029US, November 2008 + * Table 6-1. Exceptions and Interrupts + */ + switch (irq) { + case 0x00: + printf("Divide Error (Division by zero) at %04x:%08x\n", seg, ip); + while(1); + break; + case 0x01: + printf("Debug Interrupt (Single step) at %04x:%08x\n", seg, ip); + break; + case 0x02: + printf("NMI Interrupt at %04x:%08x\n", seg, ip); + break; + case 0x03: + printf("Breakpoint at %04x:%08x\n", seg, ip); + break; + case 0x04: + printf("Overflow at %04x:%08x\n", seg, ip); + while(1); + break; + case 0x05: + printf("BOUND Range Exceeded at %04x:%08x\n", seg, ip); + while(1); + break; + case 0x06: + printf("Invalid Opcode (UnDefined Opcode) at %04x:%08x\n", seg, ip); + while(1); + break; + case 0x07: + printf("Device Not Available (No Math Coprocessor) at %04x:%08x\n", seg, ip); + while(1); + break; + case 0x08: + printf("Double fault at %04x:%08x\n", seg, ip); + while(1); + break; + case 0x09: + printf("Co-processor segment overrun at %04x:%08x\n", seg, ip); + while(1); + break; + case 0x0a: + printf("Invalid TSS at %04x:%08x\n", seg, ip); + break; + case 0x0b: + printf("Segment Not Present at %04x:%08x\n", seg, ip); + while(1); + break; + case 0x0c: + printf("Stack Segment Fault at %04x:%08x\n", seg, ip); + while(1); + break; + case 0x0d: + printf("General Protection at %04x:%08x\n", seg, ip); + break; + case 0x0e: + printf("Page fault at %04x:%08x\n", seg, ip); + while(1); + break; + case 0x0f: + printf("Floating-Point Error (Math Fault) at %04x:%08x\n", seg, ip); + break; + case 0x10: + printf("Alignment check at %04x:%08x\n", seg, ip); + break; + case 0x11: + printf("Machine Check at %04x:%08x\n", seg, ip); + break; + case 0x12: + printf("SIMD Floating-Point Exception at %04x:%08x\n", seg, ip); + break; + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + printf("Reserved Exception %d at %04x:%08x\n", irq, seg, ip); + break; + + default: + /* Hardware or User IRQ */ + do_irq(irq); + } +} + +/* + * OK - This looks really horrible, but it serves a purpose - It helps create + * fully relocatable code. + * - The call to irq_llsr will be a relative jump + * - The IRQ entries will be guaranteed to be in order + * It's a bit annoying that we need to waste 3 bytes per interrupt entry + * (total of 768 code bytes), but we MUST create a Stack Frame and this is + * the easiest way I could do it. Maybe it can be made better later. + */ +asm(".globl irq_common_entry\n" \ + "irq_common_entry:\n" \ + "pushl $0\n" \ + "pushl $0\n" \ + "call irq_llsr\n" \ + "popl %eax\n" \ + "popl %eax\n" \ + "popl %eax\n" \ + "popa\n" \ + "leave\n"\ + "iret\n" \ + DECLARE_INTERRUPT(0) \ + DECLARE_INTERRUPT(1) \ + DECLARE_INTERRUPT(2) \ + DECLARE_INTERRUPT(3) \ + DECLARE_INTERRUPT(4) \ + DECLARE_INTERRUPT(5) \ + DECLARE_INTERRUPT(6) \ + DECLARE_INTERRUPT(7) \ + DECLARE_INTERRUPT(8) \ + DECLARE_INTERRUPT(9) \ + DECLARE_INTERRUPT(10) \ + DECLARE_INTERRUPT(11) \ + DECLARE_INTERRUPT(12) \ + DECLARE_INTERRUPT(13) \ + DECLARE_INTERRUPT(14) \ + DECLARE_INTERRUPT(15) \ + DECLARE_INTERRUPT(16) \ + DECLARE_INTERRUPT(17) \ + DECLARE_INTERRUPT(18) \ + DECLARE_INTERRUPT(19) \ + DECLARE_INTERRUPT(20) \ + DECLARE_INTERRUPT(21) \ + DECLARE_INTERRUPT(22) \ + DECLARE_INTERRUPT(23) \ + DECLARE_INTERRUPT(24) \ + DECLARE_INTERRUPT(25) \ + DECLARE_INTERRUPT(26) \ + DECLARE_INTERRUPT(27) \ + DECLARE_INTERRUPT(28) \ + DECLARE_INTERRUPT(29) \ + DECLARE_INTERRUPT(30) \ + DECLARE_INTERRUPT(31) \ + DECLARE_INTERRUPT(32) \ + DECLARE_INTERRUPT(33) \ + DECLARE_INTERRUPT(34) \ + DECLARE_INTERRUPT(35) \ + DECLARE_INTERRUPT(36) \ + DECLARE_INTERRUPT(37) \ + DECLARE_INTERRUPT(38) \ + DECLARE_INTERRUPT(39) \ + DECLARE_INTERRUPT(40) \ + DECLARE_INTERRUPT(41) \ + DECLARE_INTERRUPT(42) \ + DECLARE_INTERRUPT(43) \ + DECLARE_INTERRUPT(44) \ + DECLARE_INTERRUPT(45) \ + DECLARE_INTERRUPT(46) \ + DECLARE_INTERRUPT(47) \ + DECLARE_INTERRUPT(48) \ + DECLARE_INTERRUPT(49) \ + DECLARE_INTERRUPT(50) \ + DECLARE_INTERRUPT(51) \ + DECLARE_INTERRUPT(52) \ + DECLARE_INTERRUPT(53) \ + DECLARE_INTERRUPT(54) \ + DECLARE_INTERRUPT(55) \ + DECLARE_INTERRUPT(56) \ + DECLARE_INTERRUPT(57) \ + DECLARE_INTERRUPT(58) \ + DECLARE_INTERRUPT(59) \ + DECLARE_INTERRUPT(60) \ + DECLARE_INTERRUPT(61) \ + DECLARE_INTERRUPT(62) \ + DECLARE_INTERRUPT(63) \ + DECLARE_INTERRUPT(64) \ + DECLARE_INTERRUPT(65) \ + DECLARE_INTERRUPT(66) \ + DECLARE_INTERRUPT(67) \ + DECLARE_INTERRUPT(68) \ + DECLARE_INTERRUPT(69) \ + DECLARE_INTERRUPT(70) \ + DECLARE_INTERRUPT(71) \ + DECLARE_INTERRUPT(72) \ + DECLARE_INTERRUPT(73) \ + DECLARE_INTERRUPT(74) \ + DECLARE_INTERRUPT(75) \ + DECLARE_INTERRUPT(76) \ + DECLARE_INTERRUPT(77) \ + DECLARE_INTERRUPT(78) \ + DECLARE_INTERRUPT(79) \ + DECLARE_INTERRUPT(80) \ + DECLARE_INTERRUPT(81) \ + DECLARE_INTERRUPT(82) \ + DECLARE_INTERRUPT(83) \ + DECLARE_INTERRUPT(84) \ + DECLARE_INTERRUPT(85) \ + DECLARE_INTERRUPT(86) \ + DECLARE_INTERRUPT(87) \ + DECLARE_INTERRUPT(88) \ + DECLARE_INTERRUPT(89) \ + DECLARE_INTERRUPT(90) \ + DECLARE_INTERRUPT(91) \ + DECLARE_INTERRUPT(92) \ + DECLARE_INTERRUPT(93) \ + DECLARE_INTERRUPT(94) \ + DECLARE_INTERRUPT(95) \ + DECLARE_INTERRUPT(97) \ + DECLARE_INTERRUPT(96) \ + DECLARE_INTERRUPT(98) \ + DECLARE_INTERRUPT(99) \ + DECLARE_INTERRUPT(100) \ + DECLARE_INTERRUPT(101) \ + DECLARE_INTERRUPT(102) \ + DECLARE_INTERRUPT(103) \ + DECLARE_INTERRUPT(104) \ + DECLARE_INTERRUPT(105) \ + DECLARE_INTERRUPT(106) \ + DECLARE_INTERRUPT(107) \ + DECLARE_INTERRUPT(108) \ + DECLARE_INTERRUPT(109) \ + DECLARE_INTERRUPT(110) \ + DECLARE_INTERRUPT(111) \ + DECLARE_INTERRUPT(112) \ + DECLARE_INTERRUPT(113) \ + DECLARE_INTERRUPT(114) \ + DECLARE_INTERRUPT(115) \ + DECLARE_INTERRUPT(116) \ + DECLARE_INTERRUPT(117) \ + DECLARE_INTERRUPT(118) \ + DECLARE_INTERRUPT(119) \ + DECLARE_INTERRUPT(120) \ + DECLARE_INTERRUPT(121) \ + DECLARE_INTERRUPT(122) \ + DECLARE_INTERRUPT(123) \ + DECLARE_INTERRUPT(124) \ + DECLARE_INTERRUPT(125) \ + DECLARE_INTERRUPT(126) \ + DECLARE_INTERRUPT(127) \ + DECLARE_INTERRUPT(128) \ + DECLARE_INTERRUPT(129) \ + DECLARE_INTERRUPT(130) \ + DECLARE_INTERRUPT(131) \ + DECLARE_INTERRUPT(132) \ + DECLARE_INTERRUPT(133) \ + DECLARE_INTERRUPT(134) \ + DECLARE_INTERRUPT(135) \ + DECLARE_INTERRUPT(136) \ + DECLARE_INTERRUPT(137) \ + DECLARE_INTERRUPT(138) \ + DECLARE_INTERRUPT(139) \ + DECLARE_INTERRUPT(140) \ + DECLARE_INTERRUPT(141) \ + DECLARE_INTERRUPT(142) \ + DECLARE_INTERRUPT(143) \ + DECLARE_INTERRUPT(144) \ + DECLARE_INTERRUPT(145) \ + DECLARE_INTERRUPT(146) \ + DECLARE_INTERRUPT(147) \ + DECLARE_INTERRUPT(148) \ + DECLARE_INTERRUPT(149) \ + DECLARE_INTERRUPT(150) \ + DECLARE_INTERRUPT(151) \ + DECLARE_INTERRUPT(152) \ + DECLARE_INTERRUPT(153) \ + DECLARE_INTERRUPT(154) \ + DECLARE_INTERRUPT(155) \ + DECLARE_INTERRUPT(156) \ + DECLARE_INTERRUPT(157) \ + DECLARE_INTERRUPT(158) \ + DECLARE_INTERRUPT(159) \ + DECLARE_INTERRUPT(160) \ + DECLARE_INTERRUPT(161) \ + DECLARE_INTERRUPT(162) \ + DECLARE_INTERRUPT(163) \ + DECLARE_INTERRUPT(164) \ + DECLARE_INTERRUPT(165) \ + DECLARE_INTERRUPT(166) \ + DECLARE_INTERRUPT(167) \ + DECLARE_INTERRUPT(168) \ + DECLARE_INTERRUPT(169) \ + DECLARE_INTERRUPT(170) \ + DECLARE_INTERRUPT(171) \ + DECLARE_INTERRUPT(172) \ + DECLARE_INTERRUPT(173) \ + DECLARE_INTERRUPT(174) \ + DECLARE_INTERRUPT(175) \ + DECLARE_INTERRUPT(176) \ + DECLARE_INTERRUPT(177) \ + DECLARE_INTERRUPT(178) \ + DECLARE_INTERRUPT(179) \ + DECLARE_INTERRUPT(180) \ + DECLARE_INTERRUPT(181) \ + DECLARE_INTERRUPT(182) \ + DECLARE_INTERRUPT(183) \ + DECLARE_INTERRUPT(184) \ + DECLARE_INTERRUPT(185) \ + DECLARE_INTERRUPT(186) \ + DECLARE_INTERRUPT(187) \ + DECLARE_INTERRUPT(188) \ + DECLARE_INTERRUPT(189) \ + DECLARE_INTERRUPT(190) \ + DECLARE_INTERRUPT(191) \ + DECLARE_INTERRUPT(192) \ + DECLARE_INTERRUPT(193) \ + DECLARE_INTERRUPT(194) \ + DECLARE_INTERRUPT(195) \ + DECLARE_INTERRUPT(196) \ + DECLARE_INTERRUPT(197) \ + DECLARE_INTERRUPT(198) \ + DECLARE_INTERRUPT(199) \ + DECLARE_INTERRUPT(200) \ + DECLARE_INTERRUPT(201) \ + DECLARE_INTERRUPT(202) \ + DECLARE_INTERRUPT(203) \ + DECLARE_INTERRUPT(204) \ + DECLARE_INTERRUPT(205) \ + DECLARE_INTERRUPT(206) \ + DECLARE_INTERRUPT(207) \ + DECLARE_INTERRUPT(208) \ + DECLARE_INTERRUPT(209) \ + DECLARE_INTERRUPT(210) \ + DECLARE_INTERRUPT(211) \ + DECLARE_INTERRUPT(212) \ + DECLARE_INTERRUPT(213) \ + DECLARE_INTERRUPT(214) \ + DECLARE_INTERRUPT(215) \ + DECLARE_INTERRUPT(216) \ + DECLARE_INTERRUPT(217) \ + DECLARE_INTERRUPT(218) \ + DECLARE_INTERRUPT(219) \ + DECLARE_INTERRUPT(220) \ + DECLARE_INTERRUPT(221) \ + DECLARE_INTERRUPT(222) \ + DECLARE_INTERRUPT(223) \ + DECLARE_INTERRUPT(224) \ + DECLARE_INTERRUPT(225) \ + DECLARE_INTERRUPT(226) \ + DECLARE_INTERRUPT(227) \ + DECLARE_INTERRUPT(228) \ + DECLARE_INTERRUPT(229) \ + DECLARE_INTERRUPT(230) \ + DECLARE_INTERRUPT(231) \ + DECLARE_INTERRUPT(232) \ + DECLARE_INTERRUPT(233) \ + DECLARE_INTERRUPT(234) \ + DECLARE_INTERRUPT(235) \ + DECLARE_INTERRUPT(236) \ + DECLARE_INTERRUPT(237) \ + DECLARE_INTERRUPT(238) \ + DECLARE_INTERRUPT(239) \ + DECLARE_INTERRUPT(240) \ + DECLARE_INTERRUPT(241) \ + DECLARE_INTERRUPT(242) \ + DECLARE_INTERRUPT(243) \ + DECLARE_INTERRUPT(244) \ + DECLARE_INTERRUPT(245) \ + DECLARE_INTERRUPT(246) \ + DECLARE_INTERRUPT(247) \ + DECLARE_INTERRUPT(248) \ + DECLARE_INTERRUPT(249) \ + DECLARE_INTERRUPT(250) \ + DECLARE_INTERRUPT(251) \ + DECLARE_INTERRUPT(252) \ + DECLARE_INTERRUPT(253) \ + DECLARE_INTERRUPT(254) \ + DECLARE_INTERRUPT(255)); diff --git a/include/asm-i386/interrupt.h b/include/asm-i386/interrupt.h index 7f408cb..3e2674a 100644 --- a/include/asm-i386/interrupt.h +++ b/include/asm-i386/interrupt.h @@ -43,31 +43,4 @@ extern char exception_stack[];
#define __isr__ void __attribute__ ((regparm(0)))
-#define DECLARE_INTERRUPT(x) \ - asm(".globl irq_"#x"\n" \ - "irq_"#x":\n" \ - "pusha \n" \ - "pushl $"#x"\n" \ - "pushl $irq_return\n" \ - "jmp do_irq\n"); \ - __isr__ irq_##x(void) - -#define DECLARE_EXCEPTION(x, f) \ - asm(".globl exp_"#x"\n" \ - "exp_"#x":\n" \ - "pusha \n" \ - "movl %esp, %ebx\n" \ - "movl $exception_stack, %eax\n" \ - "movl %eax, %esp \n" \ - "pushl %ebx\n" \ - "movl 32(%esp), %ebx\n" \ - "xorl %edx, %edx\n" \ - "movw 36(%esp), %dx\n" \ - "pushl %edx\n" \ - "pushl %ebx\n" \ - "pushl $"#x"\n" \ - "pushl $exp_return\n" \ - "jmp "#f"\n"); \ - __isr__ exp_##x(void) - #endif diff --git a/include/asm-i386/u-boot-i386.h b/include/asm-i386/u-boot-i386.h index 3921e01..dfec307 100644 --- a/include/asm-i386/u-boot-i386.h +++ b/include/asm-i386/u-boot-i386.h @@ -55,9 +55,6 @@ int timer_init(void); /* cpu/.../interrupts.c */ int cpu_init_interrupts(void);
-/* cpu/.../exceptions.c */ -int cpu_init_exceptions(void); - /* board/.../... */ int board_init(void); int dram_init(void); diff --git a/lib_i386/interrupts.c b/lib_i386/interrupts.c index 3f3613a..efbad72 100644 --- a/lib_i386/interrupts.c +++ b/lib_i386/interrupts.c @@ -109,8 +109,10 @@ void irq_free_handler(int irq) return; }
-__isr__ do_irq(int irq) +void do_irq(int hw_irq) { + int irq = hw_irq - 0x20; + if (irq < 0 || irq >= CONFIG_SYS_NUM_IRQS) { printf("do_irq: bad irq number %d\n", irq); return; diff --git a/lib_i386/pcat_interrupts.c b/lib_i386/pcat_interrupts.c index f01298e..67e6e97 100644 --- a/lib_i386/pcat_interrupts.c +++ b/lib_i386/pcat_interrupts.c @@ -40,45 +40,12 @@ #error "CONFIG_SYS_NUM_IRQS must equal 16 if CONFIG_SYS_NUM_IRQS is defined" #endif
-DECLARE_INTERRUPT(0); -DECLARE_INTERRUPT(1); -DECLARE_INTERRUPT(3); -DECLARE_INTERRUPT(4); -DECLARE_INTERRUPT(5); -DECLARE_INTERRUPT(6); -DECLARE_INTERRUPT(7); -DECLARE_INTERRUPT(8); -DECLARE_INTERRUPT(9); -DECLARE_INTERRUPT(10); -DECLARE_INTERRUPT(11); -DECLARE_INTERRUPT(12); -DECLARE_INTERRUPT(13); -DECLARE_INTERRUPT(14); -DECLARE_INTERRUPT(15); - int interrupt_init(void) { u8 i;
disable_interrupts();
- /* Setup interrupts */ - set_vector(0x20, irq_0); - set_vector(0x21, irq_1); - set_vector(0x23, irq_3); - set_vector(0x24, irq_4); - set_vector(0x25, irq_5); - set_vector(0x26, irq_6); - set_vector(0x27, irq_7); - set_vector(0x28, irq_8); - set_vector(0x29, irq_9); - set_vector(0x2a, irq_10); - set_vector(0x2b, irq_11); - set_vector(0x2c, irq_12); - set_vector(0x2d, irq_13); - set_vector(0x2e, irq_14); - set_vector(0x2f, irq_15); - /* Mask all interrupts */ outb(0xff, MASTER_PIC + IMR); outb(0xff, SLAVE_PIC + IMR);

In preperation for full relocation
Signed-off-by: Graeme Russ graeme.russ@gmail.com
cpu/i386/Makefile | 2 +- cpu/i386/cpu.c | 1 - cpu/i386/exceptions.c | 229 --------------------- cpu/i386/interrupts.c | 431 ++++++++++++++++++++++++++++++++++++++-- include/asm-i386/interrupt.h | 27 --- include/asm-i386/u-boot-i386.h | 3 - lib_i386/interrupts.c | 4 +- lib_i386/pcat_interrupts.c | 33 --- 8 files changed, 420 insertions(+), 310 deletions(-) delete mode 100644 cpu/i386/exceptions.c
Don't know much about x86, but should not these new asm symbools be .hidden and .type <fun>, @function ?
+#define DECLARE_INTERRUPT(x) \
- ".globl irq_"#x"\n" \
- "irq_"#x":\n" \
- "pushl %ebp\n" \
- "movl %esp,%ebp\n" \
- "pusha\n" \
- "pushl $"#x"\n" \
- "jmp irq_common_entry\n"
+asm(".globl irq_common_entry\n" \
- "irq_common_entry:\n" \
- "pushl $0\n" \
- "pushl $0\n" \
- "call irq_llsr\n" \
- "popl %eax\n" \
- "popl %eax\n" \

On Wed, Oct 21, 2009 at 1:35 AM, Joakim Tjernlund joakim.tjernlund@transmode.se wrote:
In preperation for full relocation
Signed-off-by: Graeme Russ graeme.russ@gmail.com
cpu/i386/Makefile | 2 +- cpu/i386/cpu.c | 1 - cpu/i386/exceptions.c | 229 --------------------- cpu/i386/interrupts.c | 431 ++++++++++++++++++++++++++++++++++++++-- include/asm-i386/interrupt.h | 27 --- include/asm-i386/u-boot-i386.h | 3 - lib_i386/interrupts.c | 4 +- lib_i386/pcat_interrupts.c | 33 --- 8 files changed, 420 insertions(+), 310 deletions(-) delete mode 100644 cpu/i386/exceptions.c
Don't know much about x86, but should not these new asm symbools be .hidden and .type <fun>, @function ?
Yes
+#define DECLARE_INTERRUPT(x) \
- ".globl irq_"#x"\n" \
- "irq_"#x":\n" \
- "pushl %ebp\n" \
- "movl %esp,%ebp\n" \
- "pusha\n" \
- "pushl $"#x"\n" \
- "jmp irq_common_entry\n"
Done in patch 8
+asm(".globl irq_common_entry\n" \
- "irq_common_entry:\n" \
- "pushl $0\n" \
- "pushl $0\n" \
- "call irq_llsr\n" \
- "popl %eax\n" \
- "popl %eax\n" \
I missed this one - I will respin patch 8 after any further comments have been made
Regards,
Graeme

Graeme Russ graeme.russ@gmail.com wrote on 20/10/2009 23:44:14:
On Wed, Oct 21, 2009 at 1:35 AM, Joakim Tjernlund joakim.tjernlund@transmode.se wrote:
In preperation for full relocation
Signed-off-by: Graeme Russ graeme.russ@gmail.com
cpu/i386/Makefile | 2 +- cpu/i386/cpu.c | 1 - cpu/i386/exceptions.c | 229 --------------------- cpu/i386/interrupts.c | 431 ++++++++++++++++++++++++++++++++++++++-- include/asm-i386/interrupt.h | 27 --- include/asm-i386/u-boot-i386.h | 3 - lib_i386/interrupts.c | 4 +- lib_i386/pcat_interrupts.c | 33 --- 8 files changed, 420 insertions(+), 310 deletions(-) delete mode 100644 cpu/i386/exceptions.c
Don't know much about x86, but should not these new asm symbools be .hidden and .type <fun>, @function ?
Yes
+#define DECLARE_INTERRUPT(x) \
- ".globl irq_"#x"\n" \
- "irq_"#x":\n" \
- "pushl %ebp\n" \
- "movl %esp,%ebp\n" \
- "pusha\n" \
- "pushl $"#x"\n" \
- "jmp irq_common_entry\n"
Done in patch 8
Ah, sorry for the noise.
+asm(".globl irq_common_entry\n" \
- "irq_common_entry:\n" \
- "pushl $0\n" \
- "pushl $0\n" \
- "call irq_llsr\n" \
- "popl %eax\n" \
- "popl %eax\n" \
I missed this one - I will respin patch 8 after any further comments have been made
OK, at least something good came from this mail.
Jocke

Hides global symbols in inline asm to reduce size of dynamic symbol table
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- board/eNET/eNET_start16.S | 2 + cpu/i386/cpu.c | 2 + cpu/i386/interrupts.c | 2 + lib_i386/bios.S | 70 +++++++++++++++++++++++++++++++++++++++++++++ lib_i386/bios_pci.S | 2 + 5 files changed, 78 insertions(+), 0 deletions(-)
diff --git a/board/eNET/eNET_start16.S b/board/eNET/eNET_start16.S index 48e4d83..af2c132 100644 --- a/board/eNET/eNET_start16.S +++ b/board/eNET/eNET_start16.S @@ -71,6 +71,8 @@ board_init16: .section .bios, "ax" .code16 .globl realmode_reset +.hidden realmode_reset +.type realmode_reset, @function realmode_reset: /* Alias MMCR to 0xdf000 */ movw $0xfffc, %dx diff --git a/cpu/i386/cpu.c b/cpu/i386/cpu.c index 8baf37d..4b68105 100644 --- a/cpu/i386/cpu.c +++ b/cpu/i386/cpu.c @@ -73,6 +73,8 @@ void __attribute__ ((regparm(0))) generate_gpf(void);
/* segment 0x70 is an arbitrary segment which does not exist */ asm(".globl generate_gpf\n" + ".hidden generate_gpf\n" + ".type generate_gpf, @function\n" "generate_gpf:\n" "ljmp $0x70, $0x47114711\n");
diff --git a/cpu/i386/interrupts.c b/cpu/i386/interrupts.c index d80cfb1..6d699e2 100644 --- a/cpu/i386/interrupts.c +++ b/cpu/i386/interrupts.c @@ -29,6 +29,8 @@
#define DECLARE_INTERRUPT(x) \ ".globl irq_"#x"\n" \ + ".hidden irq_"#x"\n" \ + ".type irq_"#x", @function\n" \ "irq_"#x":\n" \ "pushl %ebp\n" \ "movl %esp,%ebp\n" \ diff --git a/lib_i386/bios.S b/lib_i386/bios.S index d6ca3e3..48f1b81 100644 --- a/lib_i386/bios.S +++ b/lib_i386/bios.S @@ -50,134 +50,200 @@ jmp realmode_reset
.globl rm_int00 +.hidden rm_int00 +.type rm_int00, @function rm_int00: pushw $0 jmp any_interrupt16 .globl rm_int01 +.hidden rm_int01 +.type rm_int01, @function rm_int01: pushw $1 jmp any_interrupt16 .globl rm_int02 +.hidden rm_int02 +.type rm_int02, @function rm_int02: pushw $2 jmp any_interrupt16 .globl rm_int03 +.hidden rm_int03 +.type rm_int03, @function rm_int03: pushw $3 jmp any_interrupt16 .globl rm_int04 +.hidden rm_int04 +.type rm_int04, @function rm_int04: pushw $4 jmp any_interrupt16 .globl rm_int05 +.hidden rm_int05 +.type rm_int05, @function rm_int05: pushw $5 jmp any_interrupt16 .globl rm_int06 +.hidden rm_int06 +.type rm_int06, @function rm_int06: pushw $6 jmp any_interrupt16 .globl rm_int07 +.hidden rm_int07 +.type rm_int07, @function rm_int07: pushw $7 jmp any_interrupt16 .globl rm_int08 +.hidden rm_int08 +.type rm_int08, @function rm_int08: pushw $8 jmp any_interrupt16 .globl rm_int09 +.hidden rm_int09 +.type rm_int09, @function rm_int09: pushw $9 jmp any_interrupt16 .globl rm_int0a +.hidden rm_int0a +.type rm_int0a, @function rm_int0a: pushw $10 jmp any_interrupt16 .globl rm_int0b +.hidden rm_int0b +.type rm_int0b, @function rm_int0b: pushw $11 jmp any_interrupt16 .globl rm_int0c +.hidden rm_int0c +.type rm_int0c, @function rm_int0c: pushw $12 jmp any_interrupt16 .globl rm_int0d +.hidden rm_int0d +.type rm_int0d, @function rm_int0d: pushw $13 jmp any_interrupt16 .globl rm_int0e +.hidden rm_int0e +.type rm_int0e, @function rm_int0e: pushw $14 jmp any_interrupt16 .globl rm_int0f +.hidden rm_int0f +.type rm_int0f, @function rm_int0f: pushw $15 jmp any_interrupt16 .globl rm_int10 +.hidden rm_int10 +.type rm_int10, @function rm_int10: pushw $16 jmp any_interrupt16 .globl rm_int11 +.hidden rm_int11 +.type rm_int11, @function rm_int11: pushw $17 jmp any_interrupt16 .globl rm_int12 +.hidden rm_int12 +.type rm_int12, @function rm_int12: pushw $18 jmp any_interrupt16 .globl rm_int13 +.hidden rm_int13 +.type rm_int13, @function rm_int13: pushw $19 jmp any_interrupt16 .globl rm_int14 +.hidden rm_int14 +.type rm_int14, @function rm_int14: pushw $20 jmp any_interrupt16 .globl rm_int15 +.hidden rm_int15 +.type rm_int15, @function rm_int15: pushw $21 jmp any_interrupt16 .globl rm_int16 +.hidden rm_int16 +.type rm_int16, @function rm_int16: pushw $22 jmp any_interrupt16 .globl rm_int17 +.hidden rm_int17 +.type rm_int17, @function rm_int17: pushw $23 jmp any_interrupt16 .globl rm_int18 +.hidden rm_int18 +.type rm_int18, @function rm_int18: pushw $24 jmp any_interrupt16 .globl rm_int19 +.hidden rm_int19 +.type rm_int19, @function rm_int19: pushw $25 jmp any_interrupt16 .globl rm_int1a +.hidden rm_int1a +.type rm_int1a, @function rm_int1a: pushw $26 jmp any_interrupt16 .globl rm_int1b +.hidden rm_int1b +.type rm_int1b, @function rm_int1b: pushw $27 jmp any_interrupt16 .globl rm_int1c +.hidden rm_int1c +.type rm_int1c, @function rm_int1c: pushw $28 jmp any_interrupt16 .globl rm_int1d +.hidden rm_int1d +.type rm_int1d, @function rm_int1d: pushw $29 jmp any_interrupt16 .globl rm_int1e +.hidden rm_int1e +.type rm_int1e, @function rm_int1e: pushw $30 jmp any_interrupt16 .globl rm_int1f +.hidden rm_int1f +.type rm_int1f, @function rm_int1f: pushw $31 jmp any_interrupt16 .globl rm_def_int +.hidden rm_def_int +.type rm_def_int, @function rm_def_int: iret
@@ -454,9 +520,13 @@ Lfunc_b1h:
.globl ram_in_64kb_chunks +.hidden ram_in_64kb_chunks +.type ram_in_64kb_chunks, @function ram_in_64kb_chunks: .word 0
.globl bios_equipment +.hidden bios_equipment +.type bios_equipment, @function bios_equipment: .word 0 diff --git a/lib_i386/bios_pci.S b/lib_i386/bios_pci.S index 67fd00b..9e412e5 100644 --- a/lib_i386/bios_pci.S +++ b/lib_i386/bios_pci.S @@ -34,6 +34,8 @@ .section .bios, "ax" .code16 .globl realmode_pci_bios_call_entry +.hidden realmode_pci_bios_call_entry +.type realmode_pci_bios_call_entry, @function realmode_pci_bios_call_entry: MAKE_BIOS_STACK call realmode_pci_bios

Signed-off-by: Graeme Russ graeme.russ@gmail.com --- include/asm-i386/u-boot-i386.h | 6 ------ lib_i386/bios_setup.c | 6 ++++++ lib_i386/board.c | 11 ----------- lib_i386/realmode.c | 5 +++++ 4 files changed, 11 insertions(+), 17 deletions(-)
diff --git a/include/asm-i386/u-boot-i386.h b/include/asm-i386/u-boot-i386.h index dfec307..1e8def7 100644 --- a/include/asm-i386/u-boot-i386.h +++ b/include/asm-i386/u-boot-i386.h @@ -35,12 +35,6 @@ extern ulong i386boot_bss_size; /* bss size */ extern ulong i386boot_stack_end; /* first usable RAM address after bss and stack */ extern ulong i386boot_ram_end; /* end of ram */
-extern ulong i386boot_realmode; /* start of realmode entry code */ -extern ulong i386boot_realmode_size;/* size of realmode entry code */ -extern ulong i386boot_bios; /* start of BIOS emulation code */ -extern ulong i386boot_bios_size; /* size of BIOS emulation code */ - - /* cpu/.../cpu.c */ int cpu_init(void);
diff --git a/lib_i386/bios_setup.c b/lib_i386/bios_setup.c index 33c842c..6491e52 100644 --- a/lib_i386/bios_setup.c +++ b/lib_i386/bios_setup.c @@ -45,6 +45,9 @@ DECLARE_GLOBAL_DATA_PTR; #define BIOS_BASE ((char*)0xf0000) #define BIOS_CS 0xf000
+extern ulong _i386boot_bios; +extern ulong _i386boot_bios_size; + /* these are defined in a 16bit segment and needs * to be accessed with the RELOC_16_xxxx() macros below */ @@ -138,6 +141,9 @@ static void setvector(int vector, u16 segment, void *handler)
int bios_setup(void) { + ulong i386boot_bios = (ulong)&_i386boot_bios; + ulong i386boot_bios_size = (ulong)&_i386boot_bios_size; + static int done=0; int vector; #ifdef CONFIG_PCI diff --git a/lib_i386/board.c b/lib_i386/board.c index ebd7047..44fa0e3 100644 --- a/lib_i386/board.c +++ b/lib_i386/board.c @@ -53,11 +53,6 @@ extern long _i386boot_romdata_size; extern long _i386boot_bss_start; extern long _i386boot_bss_size;
-extern long _i386boot_realmode; -extern long _i386boot_realmode_size; -extern long _i386boot_bios; -extern long _i386boot_bios_size; - /* The symbols defined by the linker script becomes pointers * which is somewhat inconveient ... */ ulong i386boot_start = (ulong)&_i386boot_start; /* code start (in flash) defined in start.S */ @@ -68,12 +63,6 @@ ulong i386boot_romdata_size = (ulong)&_i386boot_romdata_size; /* size of data ulong i386boot_bss_start = (ulong)&_i386boot_bss_start; /* bss start */ ulong i386boot_bss_size = (ulong)&_i386boot_bss_size; /* bss size */
-ulong i386boot_realmode = (ulong)&_i386boot_realmode; /* start of realmode entry code */ -ulong i386boot_realmode_size = (ulong)&_i386boot_realmode_size; /* size of realmode entry code */ -ulong i386boot_bios = (ulong)&_i386boot_bios; /* start of BIOS emulation code */ -ulong i386boot_bios_size = (ulong)&_i386boot_bios_size; /* size of BIOS emulation code */ - - const char version_string[] = U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")";
diff --git a/lib_i386/realmode.c b/lib_i386/realmode.c index 6cf2738..3c3c1fc 100644 --- a/lib_i386/realmode.c +++ b/lib_i386/realmode.c @@ -31,10 +31,15 @@ #define REALMODE_MAILBOX ((char*)0xe00)
+extern ulong _i386boot_realmode; +extern ulong _i386boot_realmode_size; extern char realmode_enter;
int realmode_setup(void) { + ulong i386boot_realmode = (ulong)&_i386boot_realmode; + ulong i386boot_realmode_size = (ulong)&_i386boot_realmode_size; + /* copy the realmode switch code */ if (i386boot_realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) { printf("realmode switch too large (%ld bytes, max is %d)\n",

Signed-off-by: Graeme Russ graeme.russ@gmail.com --- board/eNET/config.mk | 2 + board/eNET/eNET.c | 17 +++-- board/eNET/u-boot.lds | 34 +++++++-- cpu/i386/cpu.c | 12 ++- cpu/i386/interrupts.c | 4 +- cpu/i386/start.S | 132 ++++------------------------------ include/asm-i386/u-boot-i386.h | 14 +--- lib_i386/board.c | 155 +++++++++++++++++++++++----------------- lib_i386/interrupts.c | 4 +- lib_i386/timer.c | 2 +- 10 files changed, 159 insertions(+), 217 deletions(-)
diff --git a/board/eNET/config.mk b/board/eNET/config.mk index c9703ea..5c64804 100644 --- a/board/eNET/config.mk +++ b/board/eNET/config.mk @@ -23,4 +23,6 @@
TEXT_BASE = 0x38040000 CFLAGS_dlmalloc.o += -Wa,--no-warn -fno-strict-aliasing +PLATFORM_RELFLAGS += -fvisibility=hidden PLATFORM_CPPFLAGS += -fno-dwarf2-cfi-asm +PLATFORM_LDFLAGS += -pic --emit-relocs -Bsymbolic -Bsymbolic-functions diff --git a/board/eNET/eNET.c b/board/eNET/eNET.c index 29cf295..baf7c95 100644 --- a/board/eNET/eNET.c +++ b/board/eNET/eNET.c @@ -47,7 +47,6 @@ void init_sc520_enet (void) { /* Set CPU Speed to 100MHz */ sc520_mmcr->cpuctl = 0x01; - gd->cpu_clk = 100000000;
/* wait at least one millisecond */ asm("movl $0x2000,%%ecx\n" @@ -67,7 +66,7 @@ void init_sc520_enet (void) /* * Miscellaneous platform dependent initializations */ -int board_init(void) +int board_early_init_f(void) { init_sc520_enet();
@@ -117,12 +116,20 @@ int board_init(void) sc520_mmcr->sysarbctl = 0x06; sc520_mmcr->sysarbmenb = 0x0003;
- /* Crystal is 33.000MHz */ - gd->bus_clk = 33000000; - return 0; }
+int board_early_init_r(void) +{ + /* CPU Speed to 100MHz */ + gd->cpu_clk = 100000000; + + /* Crystal is 33.000MHz */ + gd->bus_clk = 33000000; + + return 0; +} + int dram_init(void) { init_sc520_dram(); diff --git a/board/eNET/u-boot.lds b/board/eNET/u-boot.lds index 4ea424d..8f9885b 100644 --- a/board/eNET/u-boot.lds +++ b/board/eNET/u-boot.lds @@ -28,28 +28,48 @@ ENTRY(_start) SECTIONS { . = 0x38040000; /* Location of bootcode in flash */ + _i386boot_text_start = .; .text : { *(.text); }
. = ALIGN(4); .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
_i386boot_text_size = SIZEOF(.text) + SIZEOF(.rodata); + . = ALIGN(4); + + .data : { *(.data) } + . = ALIGN(4); + + .interp : { *(.interp) } + . = ALIGN(4); + + .dynsym : { *(.dynsym) } + . = ALIGN(4);
- . = 0x03FF0000; /* Ram data segment to use */ - _i386boot_romdata_dest = ABSOLUTE(.); - .data : AT ( LOADADDR(.rodata) + SIZEOF(.rodata) ) { *(.data) } - _i386boot_romdata_start = LOADADDR(.data); + .dynstr : { *(.dynstr) } + . = ALIGN(4); + + .hash : { *(.hash) } + . = ALIGN(4);
+ .got : { *(.got) } . = ALIGN(4); - .got : AT ( LOADADDR(.data) + SIZEOF(.data) ) { *(.got) }
+ .got.plt : { *(.got.plt) } . = ALIGN(4); + + .dynamic (NOLOAD) : { *(.dynamic) } + . = ALIGN(4); + __u_boot_cmd_start = .; .u_boot_cmd : { *(.u_boot_cmd) } + . = ALIGN(4); __u_boot_cmd_end = .; _i386boot_cmd_start = LOADADDR(.u_boot_cmd);
- _i386boot_romdata_size = SIZEOF(.data) + SIZEOF(.got) + SIZEOF(.u_boot_cmd); + _i386boot_rel_dyn_start = .; + .rel.dyn : { *(.rel.dyn) } + _i386boot_rel_dyn_end = .;
. = ALIGN(4); _i386boot_bss_start = ABSOLUTE(.); @@ -57,7 +77,7 @@ SECTIONS _i386boot_bss_size = SIZEOF(.bss);
/* 16bit realmode trampoline code */ - .realmode 0x7c0 : AT ( LOADADDR(.got) + SIZEOF(.got) + SIZEOF(.u_boot_cmd)) { *(.realmode) } + .realmode 0x7c0 : AT ( LOADADDR(.rel.dyn) + SIZEOF(.rel.dyn) ) { *(.realmode) }
_i386boot_realmode = LOADADDR(.realmode); _i386boot_realmode_size = SIZEOF(.realmode); diff --git a/cpu/i386/cpu.c b/cpu/i386/cpu.c index 4b68105..e9c0739 100644 --- a/cpu/i386/cpu.c +++ b/cpu/i386/cpu.c @@ -37,7 +37,7 @@ #include <command.h> #include <asm/interrupt.h>
-int cpu_init(void) +int cpu_init_f(void) { /* initialize FPU, reset EM, set MP and NE */ asm ("fninit\n" \ @@ -46,12 +46,16 @@ int cpu_init(void) "orl $0x22, %eax\n" \ "movl %eax, %cr0\n" );
- /* Initialize core interrupt and exception functionality of CPU */ - cpu_init_interrupts (); - return 0; }
+int cpu_init_r(void) +{ + /* Initialize core interrupt and exception functionality of CPU */ + cpu_init_interrupts (); + return 0; +} + int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { printf ("resetting ...\n"); diff --git a/cpu/i386/interrupts.c b/cpu/i386/interrupts.c index 6d699e2..f3b9e63 100644 --- a/cpu/i386/interrupts.c +++ b/cpu/i386/interrupts.c @@ -63,8 +63,8 @@ static inline void load_idt(const struct desc_ptr *dtr)
void set_vector(u8 intnum, void *routine) { - idt[intnum].base_high = (u16)((u32)(routine + gd->reloc_off) >> 16); - idt[intnum].base_low = (u16)((u32)(routine + gd->reloc_off) & 0xffff); + idt[intnum].base_high = (u16)((u32)(routine) >> 16); + idt[intnum].base_low = (u16)((u32)(routine) & 0xffff); }
void irq_0(void); diff --git a/cpu/i386/start.S b/cpu/i386/start.S index 59089ef..25d32e6 100644 --- a/cpu/i386/start.S +++ b/cpu/i386/start.S @@ -63,11 +63,8 @@ early_board_init_ret: jmp mem_init mem_init_ret:
- /* check ammount of configured memory - * (we need atleast bss start+bss size+stack size) */ - movl $_i386boot_bss_start, %ecx /* BSS start */ - addl $_i386boot_bss_size, %ecx /* BSS size */ - addl $CONFIG_SYS_STACK_SIZE, %ecx + /* Check we have enough memory for stack */ + movl $CONFIG_SYS_STACK_SIZE, %ecx cmpl %ecx, %eax jae mem_ok
@@ -78,6 +75,8 @@ mem_init_ret: .progress0a: jmp die mem_ok: + /* Set stack pointer to upper memory limit*/ + movl %eax, %esp
/* indicate progress */ movw $0x02, %ax @@ -85,12 +84,7 @@ mem_ok: jmp show_boot_progress_asm .progress1:
- /* create a stack after the bss */ - movl $_i386boot_bss_start, %eax - addl $_i386boot_bss_size, %eax - addl $CONFIG_SYS_STACK_SIZE, %eax - movl %eax, %esp - + /* Test the stack */ pushl $0 popl %eax cmpl $0, %eax @@ -116,115 +110,19 @@ stack_ok: jmp show_boot_progress_asm .progress2:
- /* copy data section to ram, size must be 4-byte aligned */ - movl $_i386boot_romdata_dest, %edi /* destination address */ - movl $_i386boot_romdata_start, %esi /* source address */ - movl $_i386boot_romdata_size, %ecx /* number of bytes to copy */ - movl %ecx, %eax - andl $3, %eax - jnz data_fail - - shrl $2, %ecx /* copy 4 byte each time */ - cld - cmpl $0, %ecx - je data_ok -data_segment: - movsl - loop data_segment - jmp data_ok -data_fail: - /* indicate (lack of) progress */ - movw $0x83, %ax - movl $.progress2a, %ebp - jmp show_boot_progress_asm -.progress2a: - jmp die - -data_ok: - - /* indicate progress */ - movw $0x04, %ax - movl $.progress3, %ebp - jmp show_boot_progress_asm -.progress3: - - /* clear bss section in ram, size must be 4-byte aligned */ - movl $_i386boot_bss_start, %edi /* MK_CHG BSS start */ - movl $_i386boot_bss_size, %ecx /* BSS size */ - movl %ecx, %eax - andl $3, %eax - jnz bss_fail - shrl $2, %ecx /* clear 4 byte each time */ - cld - cmpl $0, %ecx - je bss_ok -bss: - movl $0, (%edi) - add $4, %edi - loop bss - jmp bss_ok - -bss_fail: - /* indicate (lack of) progress */ - movw $0x84, %ax - movl $.progress3a, %ebp - jmp show_boot_progress_asm -.progress3a: - jmp die - -bss_ok: -#ifndef CONFIG_SKIP_RELOCATE_UBOOT - /* indicate progress */ - movw $0x06, %ax - movl $.progress6, %ebp - jmp show_boot_progress_asm -.progress6: - - /* copy text section to ram, size must be 4-byte aligned */ - movl $CONFIG_SYS_BL_START_RAM, %edi /* destination address */ - movl $TEXT_BASE, %esi /* source address */ - movl $_i386boot_text_size, %ecx /* number of bytes to copy */ - movl %ecx, %eax - andl $3, %eax - jz text_copy /* Already 4-byte aligned */ - subl $4, %eax /* Add extra bytes to size */ - addl %eax, %ecx -text_copy: - shrl $2, %ecx /* copy 4 byte each time */ - cld - cmpl $0, %ecx - je text_ok -text_segment: - movsl - loop text_segment - jmp text_ok -text_fail: - /* indicate (lack of) progress */ - movw $0x86, %ax - movl $.progress5a, %ebp - jmp show_boot_progress_asm -.progress5a: - jmp die - -text_ok: -#endif wbinvd
+ /* Get upper memory limit */ + movl %esp, %ecx + subl $CONFIG_SYS_STACK_SIZE, %ecx
- /* indicate progress */ - movw $0x05, %ax - movl $.progress4, %ebp - jmp show_boot_progress_asm -.progress4: - -#ifndef CONFIG_SKIP_RELOCATE_UBOOT - /* Jump to the RAM copy of start_i386boot */ - movl $start_i386boot, %ebp - addl $(CONFIG_SYS_BL_START_RAM - TEXT_BASE), %ebp - call *%ebp /* Enter, U-boot! */ -#else - call start_i386boot /* Enter, U-boot! */ -#endif + /* Create a Stack Frame */ + pushl %ebp + movl %esp, %ebp + + /* stack_limit parameter */ + pushl %ecx + call board_init_f /* Enter, U-boot! */
/* indicate (lack of) progress */ movw $0x85, %ax diff --git a/include/asm-i386/u-boot-i386.h b/include/asm-i386/u-boot-i386.h index 1e8def7..7c99c8c 100644 --- a/include/asm-i386/u-boot-i386.h +++ b/include/asm-i386/u-boot-i386.h @@ -24,19 +24,9 @@ #ifndef _U_BOOT_I386_H_ #define _U_BOOT_I386_H_ 1
-/* for the following variables, see start.S */ -extern ulong i386boot_start; /* code start (in flash) */ -extern ulong i386boot_end; /* code end (in flash) */ -extern ulong i386boot_romdata_start;/* datasegment in flash (also code+rodata end) */ -extern ulong i386boot_romdata_dest; /* data location segment in ram */ -extern ulong i386boot_romdata_size; /* size of data segment */ -extern ulong i386boot_bss_start; /* bss start */ -extern ulong i386boot_bss_size; /* bss size */ -extern ulong i386boot_stack_end; /* first usable RAM address after bss and stack */ -extern ulong i386boot_ram_end; /* end of ram */ - /* cpu/.../cpu.c */ -int cpu_init(void); +int cpu_init_r(void); +int cpu_init_f(void);
/* cpu/.../timer.c */ void timer_isr(void *); diff --git a/lib_i386/board.c b/lib_i386/board.c index 44fa0e3..c16c391 100644 --- a/lib_i386/board.c +++ b/lib_i386/board.c @@ -38,6 +38,7 @@ #include <net.h> #include <ide.h> #include <asm/u-boot-i386.h> +#include <elf.h>
#ifdef CONFIG_BITBANGMII #include <miiphy.h> @@ -45,41 +46,16 @@
DECLARE_GLOBAL_DATA_PTR;
-extern long _i386boot_start; -extern long _i386boot_end; -extern long _i386boot_romdata_start; -extern long _i386boot_romdata_dest; -extern long _i386boot_romdata_size; -extern long _i386boot_bss_start; -extern long _i386boot_bss_size; - -/* The symbols defined by the linker script becomes pointers - * which is somewhat inconveient ... */ -ulong i386boot_start = (ulong)&_i386boot_start; /* code start (in flash) defined in start.S */ -ulong i386boot_end = (ulong)&_i386boot_end; /* code end (in flash) */ -ulong i386boot_romdata_start = (ulong)&_i386boot_romdata_start; /* datasegment in flash (also code+rodata end) */ -ulong i386boot_romdata_dest = (ulong)&_i386boot_romdata_dest; /* data location segment in ram */ -ulong i386boot_romdata_size = (ulong)&_i386boot_romdata_size; /* size of data segment */ -ulong i386boot_bss_start = (ulong)&_i386boot_bss_start; /* bss start */ -ulong i386boot_bss_size = (ulong)&_i386boot_bss_size; /* bss size */ - +/* Exports from the Linker Script */ +extern ulong _i386boot_text_start; +extern ulong _i386boot_rel_dyn_start; +extern ulong _i386boot_rel_dyn_end; +extern ulong _i386boot_bss_start; +extern ulong _i386boot_bss_size; +void ram_bootstrap (void *); const char version_string[] = U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")";
-static int heap_init(void) -{ - /* start malloc area right after the stack */ - ulong start = i386boot_bss_start + i386boot_bss_size + - CONFIG_SYS_STACK_SIZE; - - /* 4-byte aligned */ - start = (start+3)&~3; - - mem_malloc_init(start, CONFIG_SYS_MALLOC_LEN); - - return 0; -} - /************************************************************************ * Init Utilities * ************************************************************************ @@ -103,6 +79,7 @@ static int display_banner (void) {
printf ("\n\n%s\n\n", version_string); +/* printf ("U-Boot code: %08lX -> %08lX data: %08lX -> %08lX\n" " BSS: %08lX -> %08lX stack: %08lX -> %08lX\n", i386boot_start, i386boot_romdata_start-1, @@ -111,6 +88,7 @@ static int display_banner (void) i386boot_bss_start+i386boot_bss_size, i386boot_bss_start+i386boot_bss_size+CONFIG_SYS_STACK_SIZE-1);
+*/
return (0); } @@ -142,7 +120,6 @@ static void display_flash_config (ulong size) print_size (size, "\n"); }
- /* * Breath some life into the board... * @@ -154,6 +131,7 @@ static void display_flash_config (ulong size) * can relocate the monitor code to RAM. */
+ /* * All attempts to come up with a "common" initialization sequence * that works for all boards and architectures failed: some of the @@ -169,13 +147,12 @@ static void display_flash_config (ulong size) typedef int (init_fnc_t) (void);
init_fnc_t *init_sequence[] = { - cpu_init, /* basic cpu dependent setup */ - board_init, /* basic board dependent setup */ + serial_init, + cpu_init_r, /* basic cpu dependent setup */ + board_early_init_r, /* basic board dependent setup */ dram_init, /* configure available RAM banks */ - heap_init, /* dependant on dram_init */ interrupt_init, /* set up exceptions */ timer_init, - serial_init, env_init, /* initialize environment */ init_baudrate, /* initialze baudrate settings */ serial_init, /* serial communications setup */ @@ -187,21 +164,86 @@ init_fnc_t *init_sequence[] = {
gd_t *gd;
-void start_i386boot (void) +/* + * Load U-Boot into RAM, initialize BSS, perform relocation adjustments + */ +void board_init_f (ulong stack_limit) +{ + void *text_start = &_i386boot_text_start; + void *u_boot_cmd_end = &__u_boot_cmd_end; + Elf32_Rel *rel_dyn_start = (Elf32_Rel *)&_i386boot_rel_dyn_start; + Elf32_Rel *rel_dyn_end = (Elf32_Rel *)&_i386boot_rel_dyn_end; + void *bss_start = &_i386boot_bss_start; + void *bss_size = &_i386boot_bss_size; + + size_t uboot_size; + void *ram_start; + ulong rel_offset; + Elf32_Rel *re; + + void (*start_func)(void *); + + /* compiler optimization barrier needed for GCC >= 3.4 */ + __asm__ __volatile__("": : :"memory"); + + uboot_size = (size_t)u_boot_cmd_end - (size_t)text_start; + ram_start = (void *)stack_limit - (uboot_size + (ulong)bss_size); + rel_offset = text_start - ram_start; + start_func = ram_bootstrap - rel_offset; + + /* First stage CPU initialization */ + if (cpu_init_f() != 0) + hang(); + + /* First stage Board initialization */ + if (board_early_init_f() != 0) + hang(); + + /* Copy U-Boot into RAM */ + memcpy(ram_start, text_start, (size_t)uboot_size); + + /* Clear BSS */ + memset(bss_start - rel_offset, 0, (size_t)bss_size); + + /* Perform relocation adjustments */ + for (re = rel_dyn_start; re < rel_dyn_end; re++) + { + if (re->r_offset >= TEXT_BASE) + if (*(ulong *)re->r_offset >= TEXT_BASE) + *(ulong *)(re->r_offset - rel_offset) -= (Elf32_Addr)rel_offset; + } + + start_func(ram_start); + + /* NOTREACHED - relocate_code() does not return */ + while(1); +} + +/* + * All attempts to jump straight from board_init_f() to board_init_r() + * have failed, hence this special 'bootstrap' function. + */ +void ram_bootstrap (void *ram_start) +{ + static gd_t gd_data; + + /* compiler optimization barrier needed for GCC >= 3.4 */ + __asm__ __volatile__("": : :"memory"); + + board_init_r(&gd_data, (ulong)ram_start); +} + +void board_init_r(gd_t *id, ulong ram_start) { char *s; int i; ulong size; - static gd_t gd_data; static bd_t bd_data; init_fnc_t **init_fnc_ptr;
-#ifndef CONFIG_SKIP_RELOCATE_UBOOT - cmd_tbl_t *p; -#endif show_boot_progress(0x21);
- gd = &gd_data; + gd = id; /* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory");
@@ -212,10 +254,9 @@ void start_i386boot (void)
gd->baudrate = CONFIG_BAUDRATE;
-#ifndef CONFIG_SKIP_RELOCATE_UBOOT - /* Need to set relocation offset here for interrupt initialization */ - gd->reloc_off = CONFIG_SYS_BL_START_RAM - TEXT_BASE; -#endif + mem_malloc_init((((ulong)ram_start - CONFIG_SYS_MALLOC_LEN)+3)&~3, + CONFIG_SYS_MALLOC_LEN); + for (init_fnc_ptr = init_sequence, i=0; *init_fnc_ptr; ++init_fnc_ptr, i++) { show_boot_progress(0xa130|i);
@@ -225,26 +266,6 @@ void start_i386boot (void) } show_boot_progress(0x23);
-#ifndef CONFIG_SKIP_RELOCATE_UBOOT - for (p = &__u_boot_cmd_start; p != &__u_boot_cmd_end; p++) { - ulong addr; - addr = (ulong) (p->cmd) + gd->reloc_off; - p->cmd = (int (*)(struct cmd_tbl_s *, int, int, char *[]))addr; - addr = (ulong)(p->name) + gd->reloc_off; - p->name = (char *)addr; - - if (p->usage != NULL) { - addr = (ulong)(p->usage) + gd->reloc_off; - p->usage = (char *)addr; - } - #ifdef CONFIG_SYS_LONGHELP - if (p->help != NULL) { - addr = (ulong)(p->help) + gd->reloc_off; - p->help = (char *)addr; - } - #endif - } -#endif /* configure available FLASH banks */ size = flash_init(); display_flash_config(size); diff --git a/lib_i386/interrupts.c b/lib_i386/interrupts.c index efbad72..51def59 100644 --- a/lib_i386/interrupts.c +++ b/lib_i386/interrupts.c @@ -70,12 +70,12 @@ void irq_install_handler(int irq, interrupt_handler_t *handler, void *arg)
if (irq_handlers[irq].handler != NULL) printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n", - (ulong) handler + gd->reloc_off, + (ulong) handler, (ulong) irq_handlers[irq].handler);
status = disable_interrupts ();
- irq_handlers[irq].handler = handler + gd->reloc_off; + irq_handlers[irq].handler = handler; irq_handlers[irq].arg = arg; irq_handlers[irq].count = 0;
diff --git a/lib_i386/timer.c b/lib_i386/timer.c index 58a0212..5cb1f54 100644 --- a/lib_i386/timer.c +++ b/lib_i386/timer.c @@ -51,7 +51,7 @@ int register_timer_isr (timer_fnc_t *isr_func) if (new_func == NULL) return 1;
- new_func->isr_func = isr_func + gd->reloc_off; + new_func->isr_func = isr_func; new_func->next = NULL;
/*

Dear Graeme Russ,
In message 1256038799-21100-1-git-send-email-graeme.russ@gmail.com you wrote:
This patch series implements full relocation support for the i386 port of U-Boot.
The first 5 patches came about due to my toolchain upgrade (to gcc 4.4.1 and binutils 2.19) (patch 4 id really just a quick tidy-up)
Patch 6 is a standalone bug-fix to resolve a start-up race condition
Patch 7 sets up the i386 interupt handling to be relocation friendly
Patches 8 and 9 are a relocation setup patch - no functionality change
By the end of patch 9, the i386 port is still non-relocatable
Patch 10 is the actual Relocation Patch itself
You wrote you were going to respin at least patch 8, but I did not see any new postings yet. I assume I should therefor wait for a reposting (of a rebased version) of this patch series?
Best regards,
Wolfgang Denk
participants (3)
-
Graeme Russ
-
Joakim Tjernlund
-
Wolfgang Denk