[U-Boot] [PATCH v2 00/20] x86: Create fully relocatable U-Boot image

Version 2 adds an additional patch to fix a breakage which I did not pick up after rebasing against master

Commit 55e97429d1e6cf0976711e4e0f29ea924b7e5917 removed the definition from /arch/i386/include/asm/u-boot.h but not its usage in do_bdinfo()
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- common/cmd_bdinfo.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index 6b611b1..1326c8f 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -385,7 +385,6 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) bd_t *bd = gd->bd; char buf[32];
- print_num ("env_t", (ulong)bd->bi_env); print_num ("boot_params", (ulong)bd->bi_boot_params); print_num ("bi_memstart", bd->bi_memstart); print_num ("bi_memsize", bd->bi_memsize);

Relocation is not board-specific for the x86 architectrure, so CONFIG_RELOC_FIXUP_WORKS can be defined globally in the config.h
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/include/asm/config.h | 2 ++ include/configs/eNET.h | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/i386/include/asm/config.h b/arch/i386/include/asm/config.h index 049c44e..1952de7 100644 --- a/arch/i386/include/asm/config.h +++ b/arch/i386/include/asm/config.h @@ -21,4 +21,6 @@ #ifndef _ASM_CONFIG_H_ #define _ASM_CONFIG_H_
+#define CONFIG_RELOC_FIXUP_WORKS + #endif diff --git a/include/configs/eNET.h b/include/configs/eNET.h index da2a97d..fc7c1c6 100644 --- a/include/configs/eNET.h +++ b/include/configs/eNET.h @@ -29,8 +29,6 @@ #ifndef __CONFIG_H #define __CONFIG_H
-#define CONFIG_RELOC_FIXUP_WORKS - /* * Stuff still to be dealt with - */

Use TEXT_BASE rather than a hard-coded base address on x86 linker scripts. This will allow any board to define its base link address without having to modify the linker script
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- board/eNET/u-boot.lds | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/board/eNET/u-boot.lds b/board/eNET/u-boot.lds index 7b0ffaa..d78d75f 100644 --- a/board/eNET/u-boot.lds +++ b/board/eNET/u-boot.lds @@ -27,7 +27,7 @@ ENTRY(_start)
SECTIONS { - . = 0x06000000; /* Location of bootcode in flash */ + . = TEXT_BASE; /* Location of bootcode in flash */ _i386boot_text_start = .; .text : { *(.text); }
@@ -98,12 +98,12 @@ SECTIONS * The fff0 offset of resetvec is important, however. */ . = 0xfffffe00; - .start32 : AT (0x0603fe00) { *(.start32); } + .start32 : AT (TEXT_BASE + 0x3fe00) { *(.start32); }
. = 0xf800; - .start16 : AT (0x0603f800) { *(.start16); } + .start16 : AT (TEXT_BASE + 0x3f800) { *(.start16); }
. = 0xfff0; - .resetvec : AT (0x0603fff0) { *(.resetvec); } + .resetvec : AT (TEXT_BASE + 0x3fff0) { *(.resetvec); } _i386boot_end = (LOADADDR(.resetvec) + SIZEOF(.resetvec) ); }

The header of recent Linux Kernels includes the size of the image, and therefore is not needed to be passed to zboot. Still process the third parameter (size of image) in the event that an older kernel is being loaded
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/lib/zimage.c | 18 +++++++++++++----- 1 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/arch/i386/lib/zimage.c b/arch/i386/lib/zimage.c index 89fe015..0c42072 100644 --- a/arch/i386/lib/zimage.c +++ b/arch/i386/lib/zimage.c @@ -248,7 +248,8 @@ void boot_zimage(void *setup_base) int do_zboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { void *base_ptr; - void *bzImage_addr; + void *bzImage_addr = NULL; + char *s; ulong bzImage_size = 0;
disable_interrupts(); @@ -256,10 +257,17 @@ int do_zboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* Setup board for maximum PC/AT Compatibility */ setup_pcat_compatibility();
- /* argv[1] holds the address of the bzImage */ - bzImage_addr = (void *)simple_strtoul(argv[1], NULL, 16); + if (argc >= 2) + /* argv[1] holds the address of the bzImage */ + s = argv[1]; + else + s = getenv("fileaddr"); + + if (s) + bzImage_addr = (void *)simple_strtoul(s, NULL, 16);
- if (argc == 3) + if (argc >= 3) + /* argv[2] holds the size of the bzImage */ bzImage_size = simple_strtoul(argv[2], NULL, 16);
/* Lets look for*/ @@ -282,7 +290,7 @@ int do_zboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) }
U_BOOT_CMD( - zboot, 3, 0, do_zboot, + zboot, 2, 0, do_zboot, "Boot bzImage", "" );

Follow the discussion of Charles Manning and Mike Frysinger. Using gc_sections helps reduce image size.
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/config.mk | 3 +++ board/eNET/u-boot.lds | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/arch/i386/config.mk b/arch/i386/config.mk index 4b990e0..0e80a1ae 100644 --- a/arch/i386/config.mk +++ b/arch/i386/config.mk @@ -26,3 +26,6 @@ CROSS_COMPILE ?= i386-linux- STANDALONE_LOAD_ADDR = 0x40000
PLATFORM_CPPFLAGS += -DCONFIG_I386 -D__I386__ + +LDFLAGS += --cref --gc-sections +PLATFORM_RELFLAGS += -ffunction-sections diff --git a/board/eNET/u-boot.lds b/board/eNET/u-boot.lds index d78d75f..7b211a8 100644 --- a/board/eNET/u-boot.lds +++ b/board/eNET/u-boot.lds @@ -77,13 +77,13 @@ SECTIONS _i386boot_bss_size = SIZEOF(.bss);
/* 16bit realmode trampoline code */ - .realmode 0x7c0 : AT ( LOADADDR(.rel.dyn) + SIZEOF(.rel.dyn) ) { *(.realmode) } + .realmode 0x7c0 : AT ( LOADADDR(.rel.dyn) + SIZEOF(.rel.dyn) ) { KEEP(*(.realmode)) }
_i386boot_realmode = LOADADDR(.realmode); _i386boot_realmode_size = SIZEOF(.realmode);
/* 16bit BIOS emulation code (just enough to boot Linux) */ - .bios 0 : AT ( LOADADDR(.realmode) + SIZEOF(.realmode) ) { *(.bios) } + .bios 0 : AT ( LOADADDR(.realmode) + SIZEOF(.realmode) ) { KEEP(*(.bios)) }
_i386boot_bios = LOADADDR(.bios); _i386boot_bios_size = SIZEOF(.bios); @@ -98,12 +98,12 @@ SECTIONS * The fff0 offset of resetvec is important, however. */ . = 0xfffffe00; - .start32 : AT (TEXT_BASE + 0x3fe00) { *(.start32); } + .start32 : AT (TEXT_BASE + 0x3fe00) { KEEP(*(.start32)); }
. = 0xf800; - .start16 : AT (TEXT_BASE + 0x3f800) { *(.start16); } + .start16 : AT (TEXT_BASE + 0x3f800) { KEEP(*(.start16)); }
. = 0xfff0; - .resetvec : AT (TEXT_BASE + 0x3fff0) { *(.resetvec); } + .resetvec : AT (TEXT_BASE + 0x3fff0) { KEEP(*(.resetvec)); } _i386boot_end = (LOADADDR(.resetvec) + SIZEOF(.resetvec) ); }

Linux has C macros and code to load the GTD after switching to Protected Mode. Using these greatly simplifies the assembler code
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/cpu/cpu.c | 57 +++++++++++++++++++++++++++++ arch/i386/cpu/start.S | 96 ------------------------------------------------- 2 files changed, 57 insertions(+), 96 deletions(-)
diff --git a/arch/i386/cpu/cpu.c b/arch/i386/cpu/cpu.c index bd6aced..ae40384 100644 --- a/arch/i386/cpu/cpu.c +++ b/arch/i386/cpu/cpu.c @@ -37,6 +37,61 @@ #include <command.h> #include <asm/interrupt.h>
+/* Constructor for a conventional segment GDT (or LDT) entry */ +/* This is a macro so it can be used in initializers */ +#define GDT_ENTRY(flags, base, limit) \ + ((((base) & 0xff000000ULL) << (56-24)) | \ + (((flags) & 0x0000f0ffULL) << 40) | \ + (((limit) & 0x000f0000ULL) << (48-16)) | \ + (((base) & 0x00ffffffULL) << 16) | \ + (((limit) & 0x0000ffffULL))) + +/* Simple and small GDT entries for booting only */ + +#define GDT_ENTRY_32BIT_CS 2 +#define GDT_ENTRY_32BIT_DS (GDT_ENTRY_32BIT_CS + 1) +#define GDT_ENTRY_16BIT_CS (GDT_ENTRY_32BIT_DS + 1) +#define GDT_ENTRY_16BIT_DS (GDT_ENTRY_16BIT_CS + 1) + +/* + * Set up the GDT + */ + +struct gdt_ptr { + u16 len; + u32 ptr; +} __attribute__((packed)); + +static void reload_gdt(void) +{ + /* There are machines which are known to not boot with the GDT + being 8-byte unaligned. Intel recommends 16 byte alignment. */ + static const u64 boot_gdt[] __attribute__((aligned(16))) = { + /* CS: code, read/execute, 4 GB, base 0 */ + [GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff), + /* DS: data, read/write, 4 GB, base 0 */ + [GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff), + /* 16-bit CS: code, read/execute, 64 kB, base 0 */ + [GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x109b, 0, 0x0ffff), + /* 16-bit DS: data, read/write, 64 kB, base 0 */ + [GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x1093, 0, 0x0ffff), + }; + static struct gdt_ptr gdt; + + gdt.len = sizeof(boot_gdt)-1; + gdt.ptr = (u32)&boot_gdt; + + asm volatile("lgdtl %0\n" \ + "movl $((2+1)*8), %%ecx\n" \ + "movl %%ecx, %%ds\n" \ + "movl %%ecx, %%es\n" \ + "movl %%ecx, %%fs\n" \ + "movl %%ecx, %%gs\n" \ + "movl %%ecx, %%ss" \ + : : "m" (gdt) : "ecx"); +} + + int cpu_init_f(void) { /* initialize FPU, reset EM, set MP and NE */ @@ -51,6 +106,8 @@ int cpu_init_f(void)
int cpu_init_r(void) { + reload_gdt(); + /* Initialize core interrupt and exception functionality of CPU */ cpu_init_interrupts (); return 0; diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index 7def8de..3cea04b 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -100,53 +100,6 @@ mem_init_ret: jmp get_mem_size get_mem_size_ret:
- /* - * We are now in 'Flat Protected Mode' and we know how much memory - * the board has. The (temporary) Global Descriptor Table is not - * in a 'Safe' place (it is either in Flash which can be erased or - * reprogrammed or in a fail-safe boot-strap image which could be - * over-written). - * - * Move the final gdt to a safe place (top of RAM) and load it. - * This is not a trivial excercise - the lgdt instruction does not - * have a register operand (memory only) and we may well be - * running from Flash, so self modifying code will not work here. - * To overcome this, we copy a stub into upper memory along with - * the GDT. - */ - - /* Reduce upper memory limit by (Stub + GDT Pointer + GDT) */ - subl $(end_gdt_setup - start_gdt_setup), %eax - - /* Copy the GDT and Stub */ - movl $start_gdt_setup, %esi - movl %eax, %edi - movl $(end_gdt_setup - start_gdt_setup), %ecx - shrl $2, %ecx - cld - rep movsl - - /* write the lgdt 'parameter' */ - subl $(jmp_instr - start_gdt_setup - 4), %ebp - addl %eax, %ebp - movl $(gdt_ptr - start_gdt_setup), %ebx - addl %eax, %ebx - movl %ebx, (%ebp) - - /* write the gdt address into the pointer */ - movl $(gdt_addr - start_gdt_setup), %ebp - addl %eax, %ebp - movl $(gdt - start_gdt_setup), %ebx - addl %eax, %ebx - movl %ebx, (%ebp) - - /* Save the return address */ - movl $load_gdt_ret, %ebp - - /* Load the new (safe) Global Descriptor Table */ - jmp *%eax - -load_gdt_ret: /* Check we have enough memory for stack */ movl $CONFIG_SYS_STACK_SIZE, %ecx cmpl %ecx, %eax @@ -221,52 +174,3 @@ die: hlt blank_idt_ptr: .word 0 /* limit */ .long 0 /* base */ - -.align 4 -start_gdt_setup: - lgdt gdt_ptr -jmp_instr: - jmp *%ebp - -.align 4 -gdt_ptr: - .word 0x30 /* limit (48 bytes = 6 GDT entries) */ -gdt_addr: - .long gdt /* base */ - - /* The GDT table ... - * - * Selector Type - * 0x00 NULL - * 0x08 Unused - * 0x10 32bit code - * 0x18 32bit data/stack - * 0x20 16bit code - * 0x28 16bit data/stack - */ - -.align 4 -gdt: - .word 0, 0, 0, 0 /* NULL */ - .word 0, 0, 0, 0 /* unused */ - - .word 0xFFFF /* 4Gb - (0x100000*0x1000 = 4Gb) */ - .word 0 /* base address = 0 */ - .word 0x9B00 /* code read/exec */ - .word 0x00CF /* granularity = 4096, 386 (+5th nibble of limit) */ - - .word 0xFFFF /* 4Gb - (0x100000*0x1000 = 4Gb) */ - .word 0x0 /* base address = 0 */ - .word 0x9300 /* data read/write */ - .word 0x00CF /* granularity = 4096, 386 (+5th nibble of limit) */ - - .word 0xFFFF /* 64kb */ - .word 0 /* base address = 0 */ - .word 0x9b00 /* data read/write */ - .word 0x0010 /* granularity = 1 (+5th nibble of limit) */ - - .word 0xFFFF /* 64kb */ - .word 0 /* base address = 0 */ - .word 0x9300 /* data read/write */ - .word 0x0010 /* granularity = 1 (+5th nibble of limit) */ -end_gdt_setup:

Perform some basic code cleanups of the x86 files
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/cpu/sc520/sc520.c | 54 ++-- arch/i386/cpu/sc520/sc520_asm.S | 642 +++++++++++++++++++-------------------- arch/i386/cpu/start.S | 30 +- arch/i386/cpu/start16.S | 9 +- 4 files changed, 362 insertions(+), 373 deletions(-)
diff --git a/arch/i386/cpu/sc520/sc520.c b/arch/i386/cpu/sc520/sc520.c index 519bfd8..7acd471 100644 --- a/arch/i386/cpu/sc520/sc520.c +++ b/arch/i386/cpu/sc520/sc520.c @@ -41,7 +41,8 @@ volatile sc520_mmcr_t *sc520_mmcr = (sc520_mmcr_t *)0xfffef000;
void init_sc520(void) { - /* Set the UARTxCTL register at it's slower, + /* + * Set the UARTxCTL register at it's slower, * baud clock giving us a 1.8432 MHz reference */ writeb(0x07, &sc520_mmcr->uart1ctl); @@ -50,25 +51,30 @@ void init_sc520(void) /* first set the timer pin mapping */ writeb(0x72, &sc520_mmcr->clksel); /* no clock frequency selected, use 1.1892MHz */
- /* enable PCI bus arbitrer */ - writeb(0x02, &sc520_mmcr->sysarbctl); /* enable concurrent mode */ + /* enable PCI bus arbiter (concurrent mode) */ + writeb(0x02, &sc520_mmcr->sysarbctl);
- writeb(0x1f, &sc520_mmcr->sysarbmenb); /* enable external grants */ - writeb(0x04, &sc520_mmcr->hbctl); /* enable posted-writes */ + /* enable external grants */ + writeb(0x1f, &sc520_mmcr->sysarbmenb); + + /* enable posted-writes */ + writeb(0x04, &sc520_mmcr->hbctl);
if (CONFIG_SYS_SC520_HIGH_SPEED) { - writeb(0x02, &sc520_mmcr->cpuctl); /* set it to 133 MHz and write back */ + /* set it to 133 MHz and write back */ + writeb(0x02, &sc520_mmcr->cpuctl); gd->cpu_clk = 133000000; printf("## CPU Speed set to 133MHz\n"); } else { - writeb(0x01, &sc520_mmcr->cpuctl); /* set it to 100 MHz and write back */ + /* set it to 100 MHz and write back */ + writeb(0x01, &sc520_mmcr->cpuctl); printf("## CPU Speed set to 100MHz\n"); gd->cpu_clk = 100000000; }
/* wait at least one millisecond */ - asm("movl $0x2000,%%ecx\n" + asm("movl $0x2000, %%ecx\n" "0: pushl %%ecx\n" "popl %%ecx\n" "loop 0b\n": : : "ecx"); @@ -107,15 +113,15 @@ unsigned long init_sc520_dram(void)
/* set SDRAM speed here */
- refresh_rate/=78; - if (refresh_rate<=1) { - val = 0; /* 7.8us */ - } else if (refresh_rate==2) { - val = 1; /* 15.6us */ - } else if (refresh_rate==3 || refresh_rate==4) { - val = 2; /* 31.2us */ + refresh_rate /= 78; + if (refresh_rate <= 1) { + val = 0; /* 7.8us */ + } else if (refresh_rate == 2) { + val = 1; /* 15.6us */ + } else if (refresh_rate == 3 || refresh_rate == 4) { + val = 2; /* 31.2us */ } else { - val = 3; /* 62.4us */ + val = 3; /* 62.4us */ }
tmp = (readb(&sc520_mmcr->drcctl) & 0xcf) | (val<<4); @@ -124,9 +130,9 @@ unsigned long init_sc520_dram(void) val = readb(&sc520_mmcr->drctmctl) & 0xf0;
if (cas_precharge_delay==3) { - val |= 0x04; /* 3T */ + val |= 0x04; /* 3T */ } else if (cas_precharge_delay==4) { - val |= 0x08; /* 4T */ + val |= 0x08; /* 4T */ } else if (cas_precharge_delay>4) { val |= 0x0c; } @@ -139,8 +145,10 @@ unsigned long init_sc520_dram(void) writeb(val, &c520_mmcr->drctmctl); #endif
- /* We read-back the configuration of the dram - * controller that the assembly code wrote */ + /* + * We read-back the configuration of the dram + * controller that the assembly code wrote + */ dram_ctrl = readl(&sc520_mmcr->drcbendadr);
bd->bi_dram[0].start = 0; @@ -148,7 +156,6 @@ unsigned long init_sc520_dram(void) /* bank 0 enabled */ dram_present = bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22; bd->bi_dram[0].size = bd->bi_dram[1].start; - } else { bd->bi_dram[0].size = 0; bd->bi_dram[1].start = bd->bi_dram[0].start; @@ -179,11 +186,6 @@ unsigned long init_sc520_dram(void) } else { bd->bi_dram[3].size = 0; } - - -#if 0 - printf("Configured %d bytes of dram\n", dram_present); -#endif gd->ram_size = dram_present;
return dram_present; diff --git a/arch/i386/cpu/sc520/sc520_asm.S b/arch/i386/cpu/sc520/sc520_asm.S index fff56c0..7c2de31 100644 --- a/arch/i386/cpu/sc520/sc520_asm.S +++ b/arch/i386/cpu/sc520/sc520_asm.S @@ -172,366 +172,349 @@ .equ ROW11_DATA, 0x07070707 /* 11 row data/also bank switch (MASK) */ .equ ROW10_DATA, 0xaaaaaaaa /* 10 row data/also bank switch (MASK) */
- - /* - * initialize dram controller registers - */ .globl mem_init mem_init: - xorw %ax,%ax - movl $DBCTL, %edi - movb %al, (%edi) /* disable write buffer */ - - movl $ECCCTL, %edi - movb %al, (%edi) /* disable ECC */ - - movl $DRCTMCTL, %edi - movb $0x1E,%al /* Set SDRAM timing for slowest */ - movb %al, (%edi) - - /* - * setup loop to do 4 external banks starting with bank 3 - */ - movl $0xff000000,%eax /* enable last bank and setup */ - movl $DRCBENDADR, %edi /* ending address register */ - movl %eax, (%edi) - - movl $DRCCFG, %edi /* setup */ - movw $0xbbbb,%ax /* dram config register for */ - movw %ax, (%edi) - - /* - * issue a NOP to all DRAMs - */ - movl $DRCCTL, %edi /* setup DRAM control register with */ - movb $0x1,%al /* Disable refresh,disable write buffer */ - movb %al, (%edi) - movl $CACHELINESZ, %esi /* just a dummy address to write for */ - movw %ax, (%esi) - /* - * delay for 100 usec? 200? - * ******this is a cludge for now ************* - */ - movw $100,%cx + /* initialize dram controller registers */ + xorw %ax, %ax + movl $DBCTL, %edi + movb %al, (%edi) /* disable write buffer */ + + movl $ECCCTL, %edi + movb %al, (%edi) /* disable ECC */ + + movl $DRCTMCTL, %edi + movb $0x1e, %al /* Set SDRAM timing for slowest */ + movb %al, (%edi) + + /* setup loop to do 4 external banks starting with bank 3 */ + movl $0xff000000, %eax /* enable last bank and setup */ + movl $DRCBENDADR, %edi /* ending address register */ + movl %eax, (%edi) + + movl $DRCCFG, %edi /* setup */ + movw $0xbbbb, %ax /* dram config register for */ + movw %ax, (%edi) + + /* issue a NOP to all DRAMs */ + movl $DRCCTL, %edi /* setup DRAM control register with */ + movb $0x01, %al /* Disable refresh,disable write buffer */ + movb %al, (%edi) + movl $CACHELINESZ, %esi /* just a dummy address to write for */ + movw %ax, (%esi) + + /* delay for 100 usec? */ + movw $100, %cx sizdelay: - loop sizdelay /* we need 100 usec here */ - /***********************************************/ + loop sizdelay
- /* - * issue all banks precharge - */ - movb $0x2,%al /* All banks precharge */ - movb %al, (%edi) - movw %ax, (%esi) + /* issue all banks precharge */ + movb $0x02, %al + movb %al, (%edi) + movw %ax, (%esi)
- /* - * issue 2 auto refreshes to all banks - */ - movb $0x4,%al /* Auto refresh cmd */ - movb %al, (%edi) - movw $2,%cx + /* issue 2 auto refreshes to all banks */ + movb $0x04, %al /* Auto refresh cmd */ + movb %al, (%edi) + movw $0x02, %cx refresh1: - movw %ax, (%esi) - loop refresh1 - - /* - * issue LOAD MODE REGISTER command - */ - movb $0x3,%al /* Load mode register cmd */ - movb %al, (%edi) - movw %ax, (%esi) - - /* - * issue 8 more auto refreshes to all banks - */ - movb $0x4,%al /* Auto refresh cmd */ - movb %al, (%edi) - movw $8,%cx + movw %ax, (%esi) + loop refresh1 + + /* issue LOAD MODE REGISTER command */ + movb $0x03, %al /* Load mode register cmd */ + movb %al, (%edi) + movw %ax, (%esi) + + /* issue 8 more auto refreshes to all banks */ + movb $0x04, %al /* Auto refresh cmd */ + movb %al, (%edi) + movw $0x0008, %cx refresh2: - movw %ax, (%esi) - loop refresh2 + movw %ax, (%esi) + loop refresh2
- /* - * set control register to NORMAL mode - */ - movb $0x0,%al /* Normal mode value */ - movb %al, (%edi) + /* set control register to NORMAL mode */ + movb $0x00, %al /* Normal mode value */ + movb %al, (%edi)
- /* - * size dram starting with external bank 3 moving to external bank 0 - */ - movl $0x3,%ecx /* start with external bank 3 */ + /* + * size dram starting with external bank 3 + * moving to external bank 0 + */ + movl $0x3, %ecx /* start with external bank 3 */
nextbank:
- /* - * write col 11 wrap adr - */ - movl $COL11_ADR, %esi /* set address to max col (11) wrap addr */ - movl $COL11_DATA, %eax /* pattern for max supported columns(11) */ - movl %eax, (%esi) /* write max col pattern at max col adr */ - movl (%esi), %ebx /* optional read */ - cmpl %ebx,%eax /* to verify write */ - jnz bad_ram /* this ram is bad */ - /* - * write col 10 wrap adr - */ + /* write col 11 wrap adr */ + movl $COL11_ADR, %esi /* set address to max col (11) wrap addr */ + movl $COL11_DATA, %eax /* pattern for max supported columns(11) */ + movl %eax, (%esi) /* write max col pattern at max col adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx, %eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + + /* write col 10 wrap adr */ + movl $COL10_ADR, %esi /* set address to 10 col wrap address */ + movl $COL10_DATA, %eax /* pattern for 10 col wrap */ + movl %eax, (%esi) /* write 10 col pattern @ 10 col wrap adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx, %eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + + /* write col 9 wrap adr */ + movl $COL09_ADR, %esi /* set address to 9 col wrap address */ + movl $COL09_DATA, %eax /* pattern for 9 col wrap */ + movl %eax, (%esi) /* write 9 col pattern @ 9 col wrap adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx, %eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + + /* write col 8 wrap adr */ + movl $COL08_ADR, %esi /* set address to min(8) col wrap address */ + movl $COL08_DATA, %eax /* pattern for min (8) col wrap */ + movl %eax, (%esi) /* write min col pattern @ min col adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx, %eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + + /* write row 14 wrap adr */ + movl $ROW14_ADR, %esi /* set address to max row (14) wrap addr */ + movl $ROW14_DATA, %eax /* pattern for max supported rows(14) */ + movl %eax, (%esi) /* write max row pattern at max row adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx, %eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + + /* write row 13 wrap adr */ + movl $ROW13_ADR, %esi /* set address to 13 row wrap address */ + movl $ROW13_DATA, %eax /* pattern for 13 row wrap */ + movl %eax, (%esi) /* write 13 row pattern @ 13 row wrap adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx, %eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + + /* write row 12 wrap adr */ + movl $ROW12_ADR, %esi /* set address to 12 row wrap address */ + movl $ROW12_DATA, %eax /* pattern for 12 row wrap */ + movl %eax, (%esi) /* write 12 row pattern @ 12 row wrap adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx, %eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + + /* write row 11 wrap adr */ + movl $ROW11_ADR, %edi /* set address to 11 row wrap address */ + movl $ROW11_DATA, %eax /* pattern for 11 row wrap */ + movl %eax, (%edi) /* write 11 row pattern @ 11 row wrap adr */ + movl (%edi), %ebx /* optional read */ + cmpl %ebx, %eax /* to verify write */ + jnz bad_ram /* this ram is bad */
- movl $COL10_ADR, %esi /* set address to 10 col wrap address */ - movl $COL10_DATA, %eax /* pattern for 10 col wrap */ - movl %eax, (%esi) /* write 10 col pattern @ 10 col wrap adr */ - movl (%esi), %ebx /* optional read */ - cmpl %ebx,%eax /* to verify write */ - jnz bad_ram /* this ram is bad */ - /* - * write col 9 wrap adr - */ - movl $COL09_ADR, %esi /* set address to 9 col wrap address */ - movl $COL09_DATA, %eax /* pattern for 9 col wrap */ - movl %eax, (%esi) /* write 9 col pattern @ 9 col wrap adr */ - movl (%esi), %ebx /* optional read */ - cmpl %ebx,%eax /* to verify write */ - jnz bad_ram /* this ram is bad */ - /* - * write col 8 wrap adr - */ - movl $COL08_ADR, %esi /* set address to min(8) col wrap address */ - movl $COL08_DATA, %eax /* pattern for min (8) col wrap */ - movl %eax, (%esi) /* write min col pattern @ min col adr */ - movl (%esi), %ebx /* optional read */ - cmpl %ebx,%eax /* to verify write */ - jnz bad_ram /* this ram is bad */ - /* - * write row 14 wrap adr - */ - movl $ROW14_ADR, %esi /* set address to max row (14) wrap addr */ - movl $ROW14_DATA, %eax /* pattern for max supported rows(14) */ - movl %eax, (%esi) /* write max row pattern at max row adr */ - movl (%esi), %ebx /* optional read */ - cmpl %ebx,%eax /* to verify write */ - jnz bad_ram /* this ram is bad */ - /* - * write row 13 wrap adr - */ - movl $ROW13_ADR, %esi /* set address to 13 row wrap address */ - movl $ROW13_DATA, %eax /* pattern for 13 row wrap */ - movl %eax, (%esi) /* write 13 row pattern @ 13 row wrap adr */ - movl (%esi), %ebx /* optional read */ - cmpl %ebx,%eax /* to verify write */ - jnz bad_ram /* this ram is bad */ - /* - * write row 12 wrap adr - */ - movl $ROW12_ADR, %esi /* set address to 12 row wrap address */ - movl $ROW12_DATA, %eax /* pattern for 12 row wrap */ - movl %eax, (%esi) /* write 12 row pattern @ 12 row wrap adr */ - movl (%esi), %ebx /* optional read */ - cmpl %ebx,%eax /* to verify write */ - jnz bad_ram /* this ram is bad */ - /* - * write row 11 wrap adr - */ - movl $ROW11_ADR, %edi /* set address to 11 row wrap address */ - movl $ROW11_DATA, %eax /* pattern for 11 row wrap */ - movl %eax, (%edi) /* write 11 row pattern @ 11 row wrap adr */ - movl (%edi), %ebx /* optional read */ - cmpl %ebx,%eax /* to verify write */ - jnz bad_ram /* this ram is bad */ - /* - * write row 10 wrap adr --- this write is really to determine number of banks - */ - movl $ROW10_ADR, %edi /* set address to 10 row wrap address */ - movl $ROW10_DATA, %eax /* pattern for 10 row wrap (AA) */ - movl %eax, (%edi) /* write 10 row pattern @ 10 row wrap adr */ - movl (%edi), %ebx /* optional read */ - cmpl %ebx,%eax /* to verify write */ - jnz bad_ram /* this ram is bad */ - /* - * read data @ row 12 wrap adr to determine * banks, - * and read data @ row 14 wrap adr to determine * rows. - * if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM. - * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4 - * if data @ row 12 wrap == 11 or 12, we have 4 banks, - */ - xorw %di,%di /* value for 2 banks in DI */ - movl (%esi), %ebx /* read from 12 row wrap to check banks - * (esi is setup from the write to row 12 wrap) */ - cmpl %ebx,%eax /* check for AA pattern (eax holds the aa pattern) */ - jz only2 /* if pattern == AA, we only have 2 banks */ + /* + * write row 10 wrap adr --- this write is really to determine + * number of banks + */ + movl $ROW10_ADR, %edi /* set address to 10 row wrap address */ + movl $ROW10_DATA, %eax /* pattern for 10 row wrap (AA) */ + movl %eax, (%edi) /* write 10 row pattern @ 10 row wrap adr */ + movl (%edi), %ebx /* optional read */ + cmpl %ebx, %eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + + /* + * read data @ row 12 wrap adr to determine * banks, + * and read data @ row 14 wrap adr to determine * rows. + * if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM. + * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4 + * if data @ row 12 wrap == 11 or 12, we have 4 banks, + */ + xorw %di, %di /* value for 2 banks in DI */ + movl (%esi), %ebx /* read from 12 row wrap to check banks */ + /* (esi is setup from the write to row 12 wrap) */ + cmpl %ebx, %eax /* check for AA pattern (eax holds the aa pattern) */ + jz only2 /* if pattern == AA, we only have 2 banks */
/* 4 banks */
- movw $8,%di /* value for 4 banks in DI (BNK_CNT bit) */ - cmpl $ROW11_DATA, %ebx /* only other legitimate values are 11 */ - jz only2 - cmpl $ROW12_DATA, %ebx /* and 12 */ - jnz bad_ram /* its bad if not 11 or 12! */ + movw $0x008, %di /* value for 4 banks in DI (BNK_CNT bit) */ + cmpl $ROW11_DATA, %ebx /* only other legitimate values are 11 */ + jz only2 + cmpl $ROW12_DATA, %ebx /* and 12 */ + jnz bad_ram /* its bad if not 11 or 12! */
/* fall through */ only2: /* * validate row mask */ - movl $ROW14_ADR, %esi /* set address back to max row wrap addr */ - movl (%esi), %eax /* read actual number of rows @ row14 adr */ + movl $ROW14_ADR, %esi /* set address back to max row wrap addr */ + movl (%esi), %eax /* read actual number of rows @ row14 adr */
- cmpl $ROW11_DATA, %eax /* row must be greater than 11 pattern */ - jb bad_ram + cmpl $ROW11_DATA, %eax /* row must be greater than 11 pattern */ + jb bad_ram
- cmpl $ROW14_DATA, %eax /* and row must be less than 14 pattern */ - ja bad_ram + cmpl $ROW14_DATA, %eax /* and row must be less than 14 pattern */ + ja bad_ram + + cmpb %ah, %al /* verify all 4 bytes of dword same */ + jnz bad_ram + movl %eax, %ebx + shrl $16, %ebx + cmpw %bx, %ax + jnz bad_ram + + /* + * read col 11 wrap adr for real column data value + */ + movl $COL11_ADR, %esi /* set address to max col (11) wrap addr */ + movl (%esi), %eax /* read real col number at max col adr */ + + /* + * validate column data + */ + cmpl $COL08_DATA, %eax /* col must be greater than 8 pattern */ + jb bad_ram + + cmpl $COL11_DATA, %eax /* and row must be less than 11 pattern */ + ja bad_ram + + subl $COL08_DATA, %eax /* normalize column data to zero */ + jc bad_ram + cmpb %ah, %al /* verify all 4 bytes of dword equal */ + jnz bad_ram + movl %eax, %edx + shrl $16, %edx + cmpw %dx, %ax + jnz bad_ram + + /* + * merge bank and col data together + */ + addw %di, %dx /* merge of bank and col info in dl */ + + /* + * fix ending addr mask based upon col info + */ + movb $0x03, %al + subb %dh, %al /* dh contains the overflow from the bank/col merge */ + movb %bl, %dh /* bl contains the row mask (aa, 07, 0f, 1f or 3f) */ + xchgw %cx, %ax /* cx = ax = 3 or 2 depending on 2 or 4 bank device */ + shrb %cl, %dh + incb %dh /* ending addr is 1 greater than real end */ + xchgw %cx, %ax /* cx is bank number again */
- cmpb %ah,%al /* verify all 4 bytes of dword same */ - jnz bad_ram - movl %eax,%ebx - shrl $16,%ebx - cmpw %bx,%ax - jnz bad_ram - /* - * read col 11 wrap adr for real column data value - */ - movl $COL11_ADR, %esi /* set address to max col (11) wrap addr */ - movl (%esi), %eax /* read real col number at max col adr */ - /* - * validate column data - */ - cmpl $COL08_DATA, %eax /* col must be greater than 8 pattern */ - jb bad_ram - - cmpl $COL11_DATA, %eax /* and row must be less than 11 pattern */ - ja bad_ram - - subl $COL08_DATA, %eax /* normalize column data to zero */ - jc bad_ram - cmpb %ah,%al /* verify all 4 bytes of dword equal */ - jnz bad_ram - movl %eax,%edx - shrl $16,%edx - cmpw %dx,%ax - jnz bad_ram - /* - * merge bank and col data together - */ - addw %di,%dx /* merge of bank and col info in dl */ - /* - * fix ending addr mask based upon col info - */ - movb $3,%al - subb %dh,%al /* dh contains the overflow from the bank/col merge */ - movb %bl,%dh /* bl contains the row mask (aa, 07, 0f, 1f or 3f) */ - xchgw %cx,%ax /* cx = ax = 3 or 2 depending on 2 or 4 bank device */ - shrb %cl,%dh /* */ - incb %dh /* ending addr is 1 greater than real end */ - xchgw %cx,%ax /* cx is bank number again */ - /* - * issue all banks precharge - */ bad_reint: - movl $DRCCTL, %esi /* setup DRAM control register with */ - movb $0x2,%al /* All banks precharge */ - movb %al, (%esi) - movl $CACHELINESZ, %esi /* address to init read buffer */ - movw %ax, (%esi) + /* + * issue all banks precharge + */ + movl $DRCCTL, %esi /* setup DRAM control register with */ + movb $0x02, %al /* All banks precharge */ + movb %al, (%esi) + movl $CACHELINESZ, %esi /* address to init read buffer */ + movw %ax, (%esi)
- /* - * update ENDING ADDRESS REGISTER - */ - movl $DRCBENDADR, %edi /* DRAM ending address register */ - movl %ecx,%ebx + /* + * update ENDING ADDRESS REGISTER + */ + movl $DRCBENDADR, %edi /* DRAM ending address register */ + movl %ecx, %ebx addl %ebx, %edi - movb %dh, (%edi) - /* - * update CONFIG REGISTER - */ - xorb %dh,%dh - movw $0x00f,%bx - movw %cx,%ax - shlw $2,%ax - xchgw %cx,%ax - shlw %cl,%dx - shlw %cl,%bx - notw %bx - xchgw %cx,%ax - movl $DRCCFG, %edi - mov (%edi), %ax - andw %bx,%ax - orw %dx,%ax - movw %ax, (%edi) - jcxz cleanup - - decw %cx - movl %ecx,%ebx - movl $DRCBENDADR, %edi /* DRAM ending address register */ - movb $0xff,%al + movb %dh, (%edi) + + /* + * update CONFIG REGISTER + */ + xorb %dh, %dh + movw $0x000f, %bx + movw %cx, %ax + shlw $2, %ax + xchgw %cx, %ax + shlw %cl, %dx + shlw %cl, %bx + notw %bx + xchgw %cx, %ax + movl $DRCCFG, %edi + movw (%edi), %ax + andw %bx, %ax + orw %dx, %ax + movw %ax, (%edi) + jcxz cleanup + + decw %cx + movl %ecx, %ebx + movl $DRCBENDADR, %edi /* DRAM ending address register */ + movb $0xff, %al addl %ebx, %edi - movb %al, (%edi) - /* - * set control register to NORMAL mode - */ - movl $DRCCTL, %esi /* setup DRAM control register with */ - movb $0x0,%al /* Normal mode value */ - movb %al, (%esi) - movl $CACHELINESZ, %esi /* address to init read buffer */ - movw %ax, (%esi) - jmp nextbank + movb %al, (%edi) + + /* + * set control register to NORMAL mode + */ + movl $DRCCTL, %esi /* setup DRAM control register with */ + movb $0x00, %al /* Normal mode value */ + movb %al, (%esi) + movl $CACHELINESZ, %esi /* address to init read buffer */ + movw %ax, (%esi) + jmp nextbank
cleanup: - movl $DRCBENDADR, %edi /* DRAM ending address register */ - movw $4,%cx - xorw %ax,%ax + movl $DRCBENDADR, %edi /* DRAM ending address register */ + movw $0x04, %cx + xorw %ax, %ax cleanuplp: - movb (%edi), %al - orb %al,%al - jz emptybank + movb (%edi), %al + orb %al, %al + jz emptybank
- addb %ah,%al - jns nottoomuch + addb %ah, %al + jns nottoomuch
- movb $0x7f,%al + movb $0x7f, %al nottoomuch: - movb %al,%ah - orb $0x80,%al - movb %al, (%edi) + movb %al, %ah + orb $0x80, %al + movb %al, (%edi) emptybank: - incl %edi - loop cleanuplp + incl %edi + loop cleanuplp
#if defined CONFIG_SYS_SDRAM_DRCTMCTL /* just have your hardware desinger _GIVE_ you what you need here! */ - movl $DRCTMCTL, %edi - movb $CONFIG_SYS_SDRAM_DRCTMCTL,%al - movb %al, (%edi) + movl $DRCTMCTL, %edi + movb $CONFIG_SYS_SDRAM_DRCTMCTL, %al + movb %al, (%edi) #else #if defined(CONFIG_SYS_SDRAM_CAS_LATENCY_2T) || defined(CONFIG_SYS_SDRAM_CAS_LATENCY_3T) - /* set the CAS latency now since it is hard to do - * when we run from the RAM */ - movl $DRCTMCTL, %edi /* DRAM timing register */ - movb (%edi), %al + /* + * Set the CAS latency now since it is hard to do + * when we run from the RAM + */ + movl $DRCTMCTL, %edi /* DRAM timing register */ + movb (%edi), %al #ifdef CONFIG_SYS_SDRAM_CAS_LATENCY_2T - andb $0xef, %al + andb $0xef, %al #endif #ifdef CONFIG_SYS_SDRAM_CAS_LATENCY_3T - orb $0x10, %al + orb $0x10, %al #endif - movb %al, (%edi) + movb %al, (%edi) #endif #endif - movl $DRCCTL, %edi /* DRAM Control register */ - movb $0x3,%al /* Load mode register cmd */ - movb %al, (%edi) - movw %ax, (%esi) + movl $DRCCTL, %edi /* DRAM Control register */ + movb $0x03, %al /* Load mode register cmd */ + movb %al, (%edi) + movw %ax, (%esi)
- movl $DRCCTL, %edi /* DRAM Control register */ - movb $0x18,%al /* Enable refresh and NORMAL mode */ - movb %al, (%edi) + movl $DRCCTL, %edi /* DRAM Control register */ + movb $0x18, %al /* Enable refresh and NORMAL mode */ + movb %al, (%edi)
- jmp dram_done + jmp dram_done
bad_ram: - xorl %edx,%edx - xorl %edi,%edi - jmp bad_reint + xorl %edx, %edx + xorl %edi, %edi + jmp bad_reint
dram_done:
@@ -551,17 +534,17 @@ init_ecc: movl %ebx, %ebp
/* A nominal memory test: just a byte at each address line */ - movl %eax, %ecx - shrl $0x1, %ecx + movl %eax, %ecx + shrl $0x1, %ecx movl $0x1, %edi memtest0: movb $0xa5, (%edi) - cmpb $0xa5, (%edi) + cmpb $0xa5, (%edi) jne out - shrl $1, %ecx - andl %ecx,%ecx + shrl $0x1, %ecx + andl %ecx, %ecx jz set_ecc - shll $1, %edi + shll $0x1, %edi jmp memtest0
set_ecc: @@ -570,21 +553,24 @@ set_ecc: xorl %esi, %esi xorl %edi, %edi xorl %eax, %eax - shrl $2, %ecx + shrl $0x2, %ecx cld rep stosl - /* enable read, write buffers */ - movb $0x11, %al - movl $DBCTL, %edi - movb %al, (%edi) - /* enable NMI mapping for ECC */ - movl $ECCINT, %edi - mov $0x10, %al - movb %al, (%edi) - /* Turn on ECC */ - movl $ECCCTL, %edi - mov $0x05, %al - movb %al, (%edi) + + /* enable read, write buffers */ + movb $0x11, %al + movl $DBCTL, %edi + movb %al, (%edi) + + /* enable NMI mapping for ECC */ + movl $ECCINT, %edi + movb $0x10, %al + movb %al, (%edi) + + /* Turn on ECC */ + movl $ECCCTL, %edi + movb $0x05, %al + movb %al,(%edi) #endif
out: @@ -596,7 +582,7 @@ out: */ .globl get_mem_size get_mem_size: - movl $DRCBENDADR, %edi /* DRAM ending address register */ + movl $DRCBENDADR, %edi /* DRAM ending address register */
bank0: movl (%edi), %eax movl %eax, %ecx diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index 3cea04b..f67a1b7 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -45,7 +45,7 @@ _i386boot_start:
/* Turn of cache (this might require a 486-class CPU) */ movl %cr0, %eax - orl $0x60000000,%eax + orl $0x60000000, %eax movl %eax, %cr0 wbinvd
@@ -54,13 +54,13 @@ _i386boot_start: _start: /* This is the 32-bit cold-reset entry point */
- movl $0x18,%eax /* Load our segement registes, the + movl $0x18, %eax /* Load our segement registes, the * gdt have already been loaded by start16.S */ - movw %ax,%fs - movw %ax,%ds - movw %ax,%gs - movw %ax,%es - movw %ax,%ss + movw %ax, %fs + movw %ax, %ds + movw %ax, %gs + movw %ax, %es + movw %ax, %ss
/* Clear the interupt vectors */ lidt blank_idt_ptr @@ -79,7 +79,7 @@ _start: * to store the return address */
/* Early platform init (setup gpio, etc ) */ - mov $early_board_init_ret, %ebp + mov $early_board_init_ret, %ebp jmp early_board_init early_board_init_ret:
@@ -92,12 +92,12 @@ early_board_init_ret:
/* size memory */ mov $mem_init_ret, %ebp - jmp mem_init + jmp mem_init mem_init_ret:
/* fetch memory size (into %eax) */ mov $get_mem_size_ret, %ebp - jmp get_mem_size + jmp get_mem_size get_mem_size_ret:
/* Check we have enough memory for stack */ @@ -113,7 +113,7 @@ get_mem_size_ret: jmp die mem_ok: /* Set stack pointer to upper memory limit*/ - movl %eax, %esp + movl %eax, %esp
/* indicate progress */ movw $0x02, %ax @@ -150,12 +150,12 @@ stack_ok: wbinvd
/* Get upper memory limit */ - movl %esp, %ecx - subl $CONFIG_SYS_STACK_SIZE, %ecx + movl %esp, %ecx + subl $CONFIG_SYS_STACK_SIZE, %ecx
/* Create a Stack Frame */ - pushl %ebp - movl %esp, %ebp + pushl %ebp + movl %esp, %ebp
/* stack_limit parameter */ pushl %ecx diff --git a/arch/i386/cpu/start16.S b/arch/i386/cpu/start16.S index ebe5835..2a5cca9 100644 --- a/arch/i386/cpu/start16.S +++ b/arch/i386/cpu/start16.S @@ -31,7 +31,8 @@ .code16 .globl start16 start16: - /* First we let the BSP do some early initialization + /* + * First we let the BSP do some early initialization * this code have to map the flash to its final position */ mov $board_init16_ret, %bp @@ -40,7 +41,7 @@ board_init16_ret:
/* Turn of cache (this might require a 486-class CPU) */ movl %cr0, %eax - orl $0x60000000,%eax + orl $0x60000000, %eax movl %eax, %cr0 wbinvd
@@ -50,7 +51,7 @@ o32 cs lgdt gdt_ptr
/* Now, we enter protected mode */ movl %cr0, %eax - orl $1,%eax + orl $1, %eax movl %eax, %cr0
/* Flush the prefetch queue */ @@ -61,7 +62,7 @@ ff:
/* Finally jump to the 32bit initialization code */ movw $code32start, %ax - movw %ax,%bp + movw %ax, %bp o32 cs ljmp *(%bp)
/* 48-bit far pointer */

Change to: - reparam=3 - no-from-pointer - no-stack-protector - preferred-stack-boundary=2 - no-top-level-reorder
These options make the code a little smaller and faster
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/config.mk | 8 ++++++++ arch/i386/cpu/interrupts.c | 7 +------ arch/i386/cpu/start.S | 12 +++--------- arch/i386/include/asm/interrupt.h | 2 -- 4 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/arch/i386/config.mk b/arch/i386/config.mk index 0e80a1ae..8743f1a 100644 --- a/arch/i386/config.mk +++ b/arch/i386/config.mk @@ -25,6 +25,14 @@ CROSS_COMPILE ?= i386-linux-
STANDALONE_LOAD_ADDR = 0x40000
+PLATFORM_CPPFLAGS += -fno-strict-aliasing +PLATFORM_CPPFLAGS += -Wstrict-prototypes +PLATFORM_CPPFLAGS += -mregparm=3 +PLATFORM_CPPFLAGS += -fomit-frame-pointer +PLATFORM_CPPFLAGS += $(call cc-option, -ffreestanding) +PLATFORM_CPPFLAGS += $(call cc-option, -fno-toplevel-reorder, $(call cc-option, -fno-unit-at-a-time)) +PLATFORM_CPPFLAGS += $(call cc-option, -fno-stack-protector) +PLATFORM_CPPFLAGS += $(call cc-option, -mpreferred-stack-boundary=2) PLATFORM_CPPFLAGS += -DCONFIG_I386 -D__I386__
LDFLAGS += --cref --gc-sections diff --git a/arch/i386/cpu/interrupts.c b/arch/i386/cpu/interrupts.c index 51023f3..47a7a29 100644 --- a/arch/i386/cpu/interrupts.c +++ b/arch/i386/cpu/interrupts.c @@ -225,7 +225,7 @@ int disable_interrupts(void) }
/* IRQ Low-Level Service Routine */ -__isr__ irq_llsr(struct pt_regs *regs) +void irq_llsr(struct pt_regs *regs) { /* * For detailed description of each exception, refer to: @@ -370,12 +370,7 @@ asm(".globl irq_common_entry\n" \ "pushl %ecx\n" \ "pushl %ebx\n" \ "mov %esp, %eax\n" \ - "pushl %ebp\n" \ - "movl %esp,%ebp\n" \ - "pushl %eax\n" \ "call irq_llsr\n" \ - "popl %eax\n" \ - "leave\n"\ "popl %ebx\n" \ "popl %ecx\n" \ "popl %edx\n" \ diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index f67a1b7..90dfd5d 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -149,16 +149,10 @@ stack_ok:
wbinvd
- /* Get upper memory limit */ - movl %esp, %ecx - subl $CONFIG_SYS_STACK_SIZE, %ecx + /* Set the upper memory limit parameter */ + movl %esp, %eax + subl $CONFIG_SYS_STACK_SIZE, %eax
- /* 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 */ diff --git a/arch/i386/include/asm/interrupt.h b/arch/i386/include/asm/interrupt.h index 07426fe..99ae843 100644 --- a/arch/i386/include/asm/interrupt.h +++ b/arch/i386/include/asm/interrupt.h @@ -41,6 +41,4 @@ void specific_eoi(int irq);
extern char exception_stack[];
-#define __isr__ void __attribute__ ((regparm(0))) - #endif

Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/cpu/interrupts.c | 23 +++++++++++++++++++---- arch/i386/include/asm/interrupt.h | 2 ++ arch/i386/include/asm/ptrace.h | 24 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/arch/i386/cpu/interrupts.c b/arch/i386/cpu/interrupts.c index 47a7a29..e4d0868 100644 --- a/arch/i386/cpu/interrupts.c +++ b/arch/i386/cpu/interrupts.c @@ -104,7 +104,7 @@ static inline unsigned long get_debugreg(int regno) return val; }
-void dump_regs(struct pt_regs *regs) +void dump_regs(struct irq_regs *regs) { unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; unsigned long d0, d1, d2, d3, d6, d7; @@ -225,7 +225,7 @@ int disable_interrupts(void) }
/* IRQ Low-Level Service Routine */ -void irq_llsr(struct pt_regs *regs) +void irq_llsr(struct irq_regs *regs) { /* * For detailed description of each exception, refer to: @@ -234,7 +234,7 @@ void irq_llsr(struct pt_regs *regs) * Order Number: 253665-029US, November 2008 * Table 6-1. Exceptions and Interrupts */ - switch (regs->orig_eax) { + switch (regs->irq_id) { case 0x00: printf("Divide Error (Division by zero)\n"); dump_regs(regs); @@ -340,7 +340,7 @@ void irq_llsr(struct pt_regs *regs)
default: /* Hardware or User IRQ */ - do_irq(regs->orig_eax); + do_irq(regs->irq_id); } }
@@ -352,17 +352,30 @@ void irq_llsr(struct pt_regs *regs) * Interrupt entries are now very small (a push and a jump) but they are * now slower (all registers pushed on stack which provides complete * crash dumps in the low level handlers + * + * Interrupt Entry Point: + * - Interrupt has caused eflags, CS and EIP to be pushed + * - Interrupt Vector Handler has pushed orig_eax + * - pt_regs.esp needs to be adjusted by 40 bytes: + * 12 bytes pushed by CPU (EFLAGSF, CS, EIP) + * 4 bytes pushed by vector handler (irq_id) + * 24 bytes pushed before SP (SS, GS, FS, ES, DS, EAX) + * NOTE: Only longs are pushed on/popped off the stack! */ asm(".globl irq_common_entry\n" \ ".hidden irq_common_entry\n" \ ".type irq_common_entry, @function\n" \ "irq_common_entry:\n" \ "cld\n" \ + "pushl %ss\n" \ "pushl %gs\n" \ "pushl %fs\n" \ "pushl %es\n" \ "pushl %ds\n" \ "pushl %eax\n" \ + "movl %esp, %eax\n" \ + "addl $40, %eax\n" \ + "pushl %eax\n" \ "pushl %ebp\n" \ "pushl %edi\n" \ "pushl %esi\n" \ @@ -378,10 +391,12 @@ asm(".globl irq_common_entry\n" \ "popl %edi\n" \ "popl %ebp\n" \ "popl %eax\n" \ + "popl %eax\n" \ "popl %ds\n" \ "popl %es\n" \ "popl %fs\n" \ "popl %gs\n" \ + "popl %ss\n" \ "add $4, %esp\n" \ "iret\n" \ DECLARE_INTERRUPT(0) \ diff --git a/arch/i386/include/asm/interrupt.h b/arch/i386/include/asm/interrupt.h index 99ae843..d32ef8b 100644 --- a/arch/i386/include/asm/interrupt.h +++ b/arch/i386/include/asm/interrupt.h @@ -27,6 +27,8 @@ #ifndef __ASM_INTERRUPT_H_ #define __ASM_INTERRUPT_H_ 1
+#include <asm/types.h> + /* arch/i386/cpu/interrupts.c */ void set_vector(u8 intnum, void *routine);
diff --git a/arch/i386/include/asm/ptrace.h b/arch/i386/include/asm/ptrace.h index 750e40d..a727dbf 100644 --- a/arch/i386/include/asm/ptrace.h +++ b/arch/i386/include/asm/ptrace.h @@ -1,6 +1,8 @@ #ifndef _I386_PTRACE_H #define _I386_PTRACE_H
+#include <asm/types.h> + #define EBX 0 #define ECX 1 #define EDX 2 @@ -43,6 +45,28 @@ struct pt_regs { int xss; } __attribute__ ((packed));
+struct irq_regs { + /* Pushed by irq_common_entry */ + long ebx; + long ecx; + long edx; + long esi; + long edi; + long ebp; + long esp; + long eax; + long xds; + long xes; + long xfs; + long xgs; + long xss; + /* Pushed by vector handler (irq_<num>) */ + long irq_id; + /* Pushed by cpu in response to interrupt */ + long eip; + long xcs; + long eflags; +} __attribute__ ((packed));
/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ #define PTRACE_GETREGS 12

Progress indication is not relocation friendly so remove it in preperation for full relocatability support
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/cpu/start.S | 44 ++------------------------------------------ board/eNET/eNET_start.S | 12 ------------ 2 files changed, 2 insertions(+), 54 deletions(-)
diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index 90dfd5d..cb47ce7 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -83,13 +83,6 @@ _start: jmp early_board_init early_board_init_ret:
- /* The __port80 entry-point should be usabe by now */ - /* so we try to indicate progress */ - movw $0x01, %ax - movl $.progress0, %ebp - jmp show_boot_progress_asm -.progress0: - /* size memory */ mov $mem_init_ret, %ebp jmp mem_init @@ -103,24 +96,11 @@ get_mem_size_ret: /* Check we have enough memory for stack */ movl $CONFIG_SYS_STACK_SIZE, %ecx cmpl %ecx, %eax - jae mem_ok - - /* indicate (lack of) progress */ - movw $0x81, %ax - movl $.progress0a, %ebp - jmp show_boot_progress_asm -.progress0a: - jmp die + jb die mem_ok: /* Set stack pointer to upper memory limit*/ movl %eax, %esp
- /* indicate progress */ - movw $0x02, %ax - movl $.progress1, %ebp - jmp show_boot_progress_asm -.progress1: - /* Test the stack */ pushl $0 popl %eax @@ -129,23 +109,7 @@ mem_ok: push $0x55aa55aa popl %ebx cmpl $0x55aa55aa, %ebx - je stack_ok - -no_stack: - /* indicate (lack of) progress */ - movw $0x82, %ax - movl $.progress1a, %ebp - jmp show_boot_progress_asm -.progress1a: - jmp die - - -stack_ok: - /* indicate progress */ - movw $0x03, %ax - movl $.progress2, %ebp - jmp show_boot_progress_asm -.progress2: + jne die
wbinvd
@@ -157,10 +121,6 @@ stack_ok:
/* indicate (lack of) progress */ movw $0x85, %ax - movl $.progress4a, %ebp - jmp show_boot_progress_asm -.progress4a: - die: hlt jmp die hlt diff --git a/board/eNET/eNET_start.S b/board/eNET/eNET_start.S index 1b07d62..6659549 100644 --- a/board/eNET/eNET_start.S +++ b/board/eNET/eNET_start.S @@ -29,18 +29,6 @@ early_board_init: /* No 32-bit board specific initialisation */ jmp *%ebp /* return to caller */
-.globl show_boot_progress_asm -show_boot_progress_asm: - - movb %al, %dl /* Create Working Copy */ - andb $0x80, %dl /* Mask in only Error bit */ - shrb $0x02, %dl /* Shift Error bit to Error LED */ - andb $0x0f, %al /* Mask out 'Error' bit */ - orb %dl, %al /* Mask in ERR LED */ - movw $LED_LATCH_ADDRESS, %dx - outb %al, %dx - jmp *%ebp /* return to caller */ - .globl cpu_halt_asm cpu_halt_asm: movb $0x0f, %al

To allow for 'load anywhere' images, the %ebp return pointer 'hack' must be removed, so we cannot have two 'calls' to get_mem_size
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/cpu/sc520/sc520_asm.S | 17 +++-------------- arch/i386/cpu/start.S | 11 +++++++++++ 2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/arch/i386/cpu/sc520/sc520_asm.S b/arch/i386/cpu/sc520/sc520_asm.S index 7c2de31..e0d3102 100644 --- a/arch/i386/cpu/sc520/sc520_asm.S +++ b/arch/i386/cpu/sc520/sc520_asm.S @@ -517,22 +517,11 @@ bad_ram: jmp bad_reint
dram_done: + jmp *%ebp
#if CONFIG_SYS_SDRAM_ECC_ENABLE - /* - * We are in the middle of an existing 'call' - Need to store the - * existing return address before making another 'call' - */ - movl %ebp, %ebx - - /* Get the memory size */ - movl $init_ecc, %ebp - jmpl get_mem_size - +.globl init_ecc init_ecc: - /* Restore the orignal return address */ - movl %ebx, %ebp - /* A nominal memory test: just a byte at each address line */ movl %eax, %ecx shrl $0x1, %ecx @@ -571,10 +560,10 @@ set_ecc: movl $ECCCTL, %edi movb $0x05, %al movb %al,(%edi) -#endif
out: jmp *%ebp +#endif
/* * Read and decode the sc520 DRCBENDADR MMCR and return the number of diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index cb47ce7..819274f 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -93,6 +93,17 @@ mem_init_ret: jmp get_mem_size get_mem_size_ret:
+#if CONFIG_SYS_SDRAM_ECC_ENABLE + /* Skip ECC initialization if not starting from cold-reset */ + movl %ebx, %ecx + andl $GD_FLG_COLD_BOOT, %ecx + jz init_ecc_ret + mov $init_ecc_ret, %ebp + jmp init_ecc + +init_ecc_ret: +#endif + /* Check we have enough memory for stack */ movl $CONFIG_SYS_STACK_SIZE, %ecx cmpl %ecx, %eax

Using %ebp as a return pointer prevents creating 'load anywhere' images
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/cpu/sc520/sc520_asm.S | 6 +++--- arch/i386/cpu/start.S | 12 ++++++------ arch/i386/cpu/start16.S | 2 +- board/eNET/eNET_start.S | 2 +- board/eNET/eNET_start16.S | 3 +-- 5 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/arch/i386/cpu/sc520/sc520_asm.S b/arch/i386/cpu/sc520/sc520_asm.S index e0d3102..a18e2c3 100644 --- a/arch/i386/cpu/sc520/sc520_asm.S +++ b/arch/i386/cpu/sc520/sc520_asm.S @@ -517,7 +517,7 @@ bad_ram: jmp bad_reint
dram_done: - jmp *%ebp + jmp mem_init_ret
#if CONFIG_SYS_SDRAM_ECC_ENABLE .globl init_ecc @@ -562,7 +562,7 @@ set_ecc: movb %al,(%edi)
out: - jmp *%ebp + jmp init_ecc_ret #endif
/* @@ -607,4 +607,4 @@ bank3: movl (%edi), %eax
done: movl %ebx, %eax - jmp *%ebp + jmp get_mem_size_ret diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index 819274f..551965f 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -1,7 +1,7 @@ /* * U-boot - i386 Startup Code * - * Copyright (c) 2002 Omicron Ceti AB, Daniel Engström denaiel@omicron.se + * Copyright (c) 2002 Omicron Ceti AB, Daniel Engstrᅵm denaiel@omicron.se * * See file CREDITS for list of people who contributed to this * project. @@ -79,18 +79,18 @@ _start: * to store the return address */
/* Early platform init (setup gpio, etc ) */ - mov $early_board_init_ret, %ebp jmp early_board_init +.globl early_board_init_ret early_board_init_ret:
/* size memory */ - mov $mem_init_ret, %ebp jmp mem_init +.globl mem_init_ret mem_init_ret:
/* fetch memory size (into %eax) */ - mov $get_mem_size_ret, %ebp jmp get_mem_size +.globl get_mem_size_ret get_mem_size_ret:
#if CONFIG_SYS_SDRAM_ECC_ENABLE @@ -98,9 +98,9 @@ get_mem_size_ret: movl %ebx, %ecx andl $GD_FLG_COLD_BOOT, %ecx jz init_ecc_ret - mov $init_ecc_ret, %ebp jmp init_ecc
+.globl init_ecc_ret init_ecc_ret: #endif
@@ -116,7 +116,7 @@ mem_ok: pushl $0 popl %eax cmpl $0, %eax - jne no_stack + jne die push $0x55aa55aa popl %ebx cmpl $0x55aa55aa, %ebx diff --git a/arch/i386/cpu/start16.S b/arch/i386/cpu/start16.S index 2a5cca9..0de4d09 100644 --- a/arch/i386/cpu/start16.S +++ b/arch/i386/cpu/start16.S @@ -35,8 +35,8 @@ start16: * First we let the BSP do some early initialization * this code have to map the flash to its final position */ - mov $board_init16_ret, %bp jmp board_init16 +.globl board_init16_ret board_init16_ret:
/* Turn of cache (this might require a 486-class CPU) */ diff --git a/board/eNET/eNET_start.S b/board/eNET/eNET_start.S index 6659549..137fe41 100644 --- a/board/eNET/eNET_start.S +++ b/board/eNET/eNET_start.S @@ -27,7 +27,7 @@ .globl early_board_init early_board_init: /* No 32-bit board specific initialisation */ - jmp *%ebp /* return to caller */ + jmp early_board_init_ret
.globl cpu_halt_asm cpu_halt_asm: diff --git a/board/eNET/eNET_start16.S b/board/eNET/eNET_start16.S index af2c132..06cfd55 100644 --- a/board/eNET/eNET_start16.S +++ b/board/eNET/eNET_start16.S @@ -65,8 +65,7 @@ board_init16: movl $0x000000cb, %eax outl %eax, %dx
- /* the return address is stored in bp */ - jmp *%bp + jmp board_init16_ret
.section .bios, "ax" .code16

%ebx will hold low-level boot flags and must be preserved
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/cpu/sc520/sc520_asm.S | 15 ++++++++++----- arch/i386/cpu/start.S | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/arch/i386/cpu/sc520/sc520_asm.S b/arch/i386/cpu/sc520/sc520_asm.S index a18e2c3..63c14b7 100644 --- a/arch/i386/cpu/sc520/sc520_asm.S +++ b/arch/i386/cpu/sc520/sc520_asm.S @@ -174,6 +174,9 @@
.globl mem_init mem_init: + /* Preserve Boot Flags */ + movl %ebx, %ebp + /* initialize dram controller registers */ xorw %ax, %ax movl $DBCTL, %edi @@ -517,6 +520,8 @@ bad_ram: jmp bad_reint
dram_done: + /* Restore Boot Flags */ + movl %ebx, %ebp jmp mem_init_ret
#if CONFIG_SYS_SDRAM_ECC_ENABLE @@ -579,7 +584,7 @@ bank0: movl (%edi), %eax jz bank1 andl $0x0000007f, %eax shll $22, %eax - movl %eax, %ebx + movl %eax, %edx
bank1: movl (%edi), %eax movl %eax, %ecx @@ -587,7 +592,7 @@ bank1: movl (%edi), %eax jz bank2 andl $0x00007f00, %eax shll $14, %eax - movl %eax, %ebx + movl %eax, %edx
bank2: movl (%edi), %eax movl %eax, %ecx @@ -595,7 +600,7 @@ bank2: movl (%edi), %eax jz bank3 andl $0x007f0000, %eax shll $6, %eax - movl %eax, %ebx + movl %eax, %edx
bank3: movl (%edi), %eax movl %eax, %ecx @@ -603,8 +608,8 @@ bank3: movl (%edi), %eax jz done andl $0x7f000000, %eax shrl $2, %eax - movl %eax, %ebx + movl %eax, %edx
done: - movl %ebx, %eax + movl %edx, %eax jmp get_mem_size_ret diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index 551965f..63f7334 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -118,8 +118,8 @@ mem_ok: cmpl $0, %eax jne die push $0x55aa55aa - popl %ebx - cmpl $0x55aa55aa, %ebx + popl %ecx + cmpl $0x55aa55aa, %ecx jne die
wbinvd

By using another register, reduce code size by one instruction
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/cpu/start.S | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index 63f7334..66ff4f3 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -114,8 +114,8 @@ mem_ok:
/* Test the stack */ pushl $0 - popl %eax - cmpl $0, %eax + popl %ecx + cmpl $0, %ecx jne die push $0x55aa55aa popl %ecx @@ -125,7 +125,6 @@ mem_ok: wbinvd
/* Set the upper memory limit parameter */ - movl %esp, %eax subl $CONFIG_SYS_STACK_SIZE, %eax
call board_init_f /* Enter, U-boot! */

By reserving space for the Global Data immediately below the stack during assembly level initialisation, the C declaration of the static global data can be removed, along with the 'RAM Bootstrap' function. This results in cleaner code, and the ability to pass boot-up flags from assembler into C
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/cpu/start.S | 8 ++++++ arch/i386/include/asm/global_data.h | 24 ++++++++++++++++++- arch/i386/lib/board.c | 42 +++++----------------------------- 3 files changed, 37 insertions(+), 37 deletions(-)
diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index 66ff4f3..cff4637 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -25,6 +25,7 @@
#include <config.h> #include <version.h> +#include <asm/global_data.h>
.section .text @@ -127,6 +128,13 @@ mem_ok: /* Set the upper memory limit parameter */ subl $CONFIG_SYS_STACK_SIZE, %eax
+ /* Reserve space for global data */ + subl $(GD_SIZE * 4), %eax + + /* %eax points to the global data structure */ + movl %esp, (GD_RAM_SIZE * 4)(%eax) + movl %ebx, (GD_FLAGS * 4)(%eax) + call board_init_f /* Enter, U-boot! */
/* indicate (lack of) progress */ diff --git a/arch/i386/include/asm/global_data.h b/arch/i386/include/asm/global_data.h index 3a9adc9..456f606 100644 --- a/arch/i386/include/asm/global_data.h +++ b/arch/i386/include/asm/global_data.h @@ -33,6 +33,8 @@ * Keep it *SMALL* and remember to set CONFIG_SYS_GBL_DATA_SIZE > sizeof(gd_t) */
+#ifndef __ASSEMBLY__ + typedef struct { bd_t *bd; unsigned long flags; @@ -49,6 +51,26 @@ typedef struct { char env_buf[32]; /* buffer for getenv() before reloc. */ } gd_t;
+extern gd_t *gd; + +#endif + +/* Word Offsets into Global Data - MUST match struct gd_t */ +#define GD_BD 0 +#define GD_FLAGS 1 +#define GD_BAUDRATE 2 +#define GD_HAVE_CONSOLE 3 +#define GD_RELOC_OFF 4 +#define GD_ENV_ADDR 5 +#define GD_ENV_VALID 6 +#define GD_CPU_CLK 7 +#define GD_BUS_CLK 8 +#define GD_RAM_SIZE 9 +#define GD_RESET_STATUS 10 +#define GD_JT 11 + +#define GD_SIZE 12 + /* * Global Data Flags */ @@ -61,8 +83,6 @@ typedef struct { #define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */ #define GD_FLG_ENV_READY 0x00080 /* Environment imported into hash table */
-extern gd_t *gd; - #define DECLARE_GLOBAL_DATA_PTR
#endif /* __ASM_GBL_DATA_H */ diff --git a/arch/i386/lib/board.c b/arch/i386/lib/board.c index 5002203..00976a5 100644 --- a/arch/i386/lib/board.c +++ b/arch/i386/lib/board.c @@ -54,8 +54,6 @@ extern ulong _i386boot_rel_dyn_end; extern ulong _i386boot_bss_start; extern ulong _i386boot_bss_size;
-void ram_bootstrap (void *, ulong); - const char version_string[] = U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")";
@@ -164,13 +162,12 @@ init_fnc_t *init_sequence[] = { NULL, };
-static gd_t gd_data; gd_t *gd;
/* * Load U-Boot into RAM, initialize BSS, perform relocation adjustments */ -void board_init_f (ulong stack_limit) +void board_init_f (ulong gdp) { void *text_start = &_i386boot_text_start; void *u_boot_cmd_end = &__u_boot_cmd_end; @@ -184,12 +181,9 @@ void board_init_f (ulong stack_limit) ulong rel_offset; Elf32_Rel *re;
- void (*start_func)(void *, ulong); - uboot_size = (ulong)u_boot_cmd_end - (ulong)text_start; - dest_addr = (void *)stack_limit - (uboot_size + (ulong)bss_size); + dest_addr = (void *)gdp - (uboot_size + (ulong)bss_size); rel_offset = text_start - dest_addr; - start_func = ram_bootstrap - rel_offset;
/* First stage CPU initialization */ if (cpu_init_f() != 0) @@ -213,38 +207,16 @@ void board_init_f (ulong stack_limit) *(ulong *)(re->r_offset - rel_offset) -= (Elf32_Addr)rel_offset; }
+ ((gd_t *)gdp)->reloc_off = rel_offset; + ((gd_t *)gdp)->flags |= GD_FLG_RELOC; + /* Enter the relocated U-Boot! */ - start_func(dest_addr, rel_offset); + (board_init_r - rel_offset)((gd_t *)gdp, (ulong)dest_addr); + /* NOTREACHED - board_init_f() does not return */ while(1); }
-/* - * We cannot initialize gd_data in board_init_f() because we would be - * attempting to write to flash (I have even tried using manual relocation - * adjustments on pointers but it just won't work) and board_init_r() does - * not have enough arguments to allow us to pass the relocation offset - * straight up. This bootstrap function (which runs in RAM) is used to - * setup gd_data in order to pass the relocation offset to the rest of - * U-Boot. - * - * TODO: The compiler optimization barrier is intended to stop GCC from - * optimizing this function into board_init_f(). It seems to work without - * it, but I've left it in to be sure. I think also that the barrier in - * board_init_r() is no longer needed, but left it in 'just in case' - */ -void ram_bootstrap (void *dest_addr, ulong rel_offset) -{ - /* compiler optimization barrier needed for GCC >= 3.4 */ - __asm__ __volatile__("": : :"memory"); - - /* tell others: relocation done */ - gd_data.reloc_off = rel_offset; - gd_data.flags |= GD_FLG_RELOC; - - board_init_r(&gd_data, (ulong)dest_addr); -} - void board_init_r(gd_t *id, ulong dest_addr) { char *s;

Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/cpu/start.S | 19 ++++++------------- arch/i386/cpu/start16.S | 7 ++++--- arch/i386/include/asm/global_data.h | 3 +++ 3 files changed, 13 insertions(+), 16 deletions(-)
diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index cff4637..8fdcd81 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -51,7 +51,7 @@ _i386boot_start: wbinvd
/* Tell 32-bit code it is being entered from an in-RAM copy */ - movw $0x0000, %bx + movw $GD_FLG_WARM_BOOT, %bx _start: /* This is the 32-bit cold-reset entry point */
@@ -66,18 +66,10 @@ _start: /* Clear the interupt vectors */ lidt blank_idt_ptr
- /* - * Skip low-level board and memory initialization if not starting - * from cold-reset. This allows us to do a fail safe boot-strap - * into a new build of U-Boot from a known-good boot flash - */ - movw $0x0001, %ax - cmpw %ax, %bx - jne mem_init_ret - - /* We call a few functions in the board support package - * since we have no stack yet we'll have to use %ebp - * to store the return address */ + /* Skip low-level initialization if not starting from cold-reset */ + movl %ebx, %ecx + andl $GD_FLG_COLD_BOOT, %ecx + jz skip_mem_init
/* Early platform init (setup gpio, etc ) */ jmp early_board_init @@ -89,6 +81,7 @@ early_board_init_ret: .globl mem_init_ret mem_init_ret:
+skip_mem_init: /* fetch memory size (into %eax) */ jmp get_mem_size .globl get_mem_size_ret diff --git a/arch/i386/cpu/start16.S b/arch/i386/cpu/start16.S index 0de4d09..0a5823d 100644 --- a/arch/i386/cpu/start16.S +++ b/arch/i386/cpu/start16.S @@ -22,6 +22,7 @@ * MA 02111-1307 USA */
+#include <asm/global_data.h>
#define BOOT_SEG 0xffff0000 /* linear segment of boot code */ #define a32 .byte 0x67; @@ -31,6 +32,9 @@ .code16 .globl start16 start16: + /* Set the Cold Boot / Hard Reset flag */ + movl $GD_FLG_COLD_BOOT, %ebx + /* * First we let the BSP do some early initialization * this code have to map the flash to its final position @@ -57,9 +61,6 @@ o32 cs lgdt gdt_ptr /* Flush the prefetch queue */ jmp ff ff: - /* Tell 32-bit code it is being entered from hard-reset */ - movw $0x0001, %bx - /* Finally jump to the 32bit initialization code */ movw $code32start, %ax movw %ax, %bp diff --git a/arch/i386/include/asm/global_data.h b/arch/i386/include/asm/global_data.h index 456f606..a15c598 100644 --- a/arch/i386/include/asm/global_data.h +++ b/arch/i386/include/asm/global_data.h @@ -82,6 +82,9 @@ extern gd_t *gd; #define GD_FLG_LOGINIT 0x00020 /* Log Buffer has been initialized */ #define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */ #define GD_FLG_ENV_READY 0x00080 /* Environment imported into hash table */ +#define GD_FLG_COLD_BOOT 0x00100 /* Cold Boot */ +#define GD_FLG_WARM_BOOT 0x00200 /* Warm Boot */ +
#define DECLARE_GLOBAL_DATA_PTR

Create more generic names for the symbols exported from the linker script
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/lib/bios_setup.c | 14 +++++++------- arch/i386/lib/board.c | 20 ++++++++++---------- arch/i386/lib/realmode.c | 14 +++++++------- board/eNET/u-boot.lds | 21 +++++++++------------ 4 files changed, 33 insertions(+), 36 deletions(-)
diff --git a/arch/i386/lib/bios_setup.c b/arch/i386/lib/bios_setup.c index a92b77e..75407c1 100644 --- a/arch/i386/lib/bios_setup.c +++ b/arch/i386/lib/bios_setup.c @@ -45,8 +45,8 @@ DECLARE_GLOBAL_DATA_PTR; #define BIOS_BASE ((char*)0xf0000) #define BIOS_CS 0xf000
-extern ulong _i386boot_bios; -extern ulong _i386boot_bios_size; +extern ulong __bios_start; +extern ulong __bios_size;
/* these are defined in a 16bit segment and needs * to be accessed with the RELOC_16_xxxx() macros below @@ -141,8 +141,8 @@ static void setvector(int vector, u16 segment, void *handler)
int bios_setup(void) { - ulong i386boot_bios = (ulong)&_i386boot_bios + gd->reloc_off; - ulong i386boot_bios_size = (ulong)&_i386boot_bios_size; + ulong bios_start = (ulong)&__bios_start + gd->reloc_off; + ulong bios_size = (ulong)&__bios_size;
static int done=0; int vector; @@ -154,13 +154,13 @@ int bios_setup(void) } done = 1;
- if (i386boot_bios_size > 65536) { + if (bios_size > 65536) { printf("BIOS too large (%ld bytes, max is 65536)\n", - i386boot_bios_size); + bios_size); return -1; }
- memcpy(BIOS_BASE, (void*)i386boot_bios, i386boot_bios_size); + memcpy(BIOS_BASE, (void*)bios_start, bios_size);
/* clear bda */ memset(BIOS_DATA, 0, BIOS_DATA_SIZE); diff --git a/arch/i386/lib/board.c b/arch/i386/lib/board.c index 00976a5..e7a363d 100644 --- a/arch/i386/lib/board.c +++ b/arch/i386/lib/board.c @@ -48,11 +48,11 @@ DECLARE_GLOBAL_DATA_PTR;
/* 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; +extern ulong __text_start; +extern ulong __rel_dyn_start; +extern ulong __rel_dyn_end; +extern ulong __bss_start; +extern ulong __bss_size;
const char version_string[] = U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")"; @@ -169,12 +169,12 @@ gd_t *gd; */ void board_init_f (ulong gdp) { - void *text_start = &_i386boot_text_start; + void *text_start = &__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; - ulong bss_size = (ulong)&_i386boot_bss_size; + Elf32_Rel *rel_dyn_start = (Elf32_Rel *)&__rel_dyn_start; + Elf32_Rel *rel_dyn_end = (Elf32_Rel *)&__rel_dyn_end; + void *bss_start = &__bss_start; + ulong bss_size = (ulong)&__bss_size;
ulong uboot_size; void *dest_addr; diff --git a/arch/i386/lib/realmode.c b/arch/i386/lib/realmode.c index b3f5123..60fe181 100644 --- a/arch/i386/lib/realmode.c +++ b/arch/i386/lib/realmode.c @@ -31,23 +31,23 @@ #define REALMODE_MAILBOX ((char*)0xe00)
-extern ulong _i386boot_realmode; -extern ulong _i386boot_realmode_size; +extern ulong __realmode_start; +extern ulong __realmode_size; extern char realmode_enter;
int realmode_setup(void) { - ulong i386boot_realmode = (ulong)&_i386boot_realmode + gd->reloc_off; - ulong i386boot_realmode_size = (ulong)&_i386boot_realmode_size; + ulong realmode_start = (ulong)&__realmode_start + gd->reloc_off; + ulong realmode_size = (ulong)&__realmode_size;
/* copy the realmode switch code */ - if (i386boot_realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) { + if (realmode_size > (REALMODE_MAILBOX-REALMODE_BASE)) { printf("realmode switch too large (%ld bytes, max is %d)\n", - i386boot_realmode_size, (REALMODE_MAILBOX-REALMODE_BASE)); + realmode_size, (REALMODE_MAILBOX-REALMODE_BASE)); return -1; }
- memcpy(REALMODE_BASE, (void*)i386boot_realmode, i386boot_realmode_size); + memcpy(REALMODE_BASE, (void*)realmode_start, realmode_size); asm("wbinvd\n");
return 0; diff --git a/board/eNET/u-boot.lds b/board/eNET/u-boot.lds index 7b211a8..ef5d941 100644 --- a/board/eNET/u-boot.lds +++ b/board/eNET/u-boot.lds @@ -28,13 +28,12 @@ ENTRY(_start) SECTIONS { . = TEXT_BASE; /* Location of bootcode in flash */ - _i386boot_text_start = .; + __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) } @@ -65,28 +64,27 @@ SECTIONS .u_boot_cmd : { *(.u_boot_cmd) } . = ALIGN(4); __u_boot_cmd_end = .; - _i386boot_cmd_start = LOADADDR(.u_boot_cmd);
- _i386boot_rel_dyn_start = .; + __rel_dyn_start = .; .rel.dyn : { *(.rel.dyn) } - _i386boot_rel_dyn_end = .; + __rel_dyn_end = .;
. = ALIGN(4); - _i386boot_bss_start = ABSOLUTE(.); + __bss_start = ABSOLUTE(.); .bss (NOLOAD) : { *(.bss) } - _i386boot_bss_size = SIZEOF(.bss); + __bss_size = SIZEOF(.bss);
/* 16bit realmode trampoline code */ .realmode 0x7c0 : AT ( LOADADDR(.rel.dyn) + SIZEOF(.rel.dyn) ) { KEEP(*(.realmode)) }
- _i386boot_realmode = LOADADDR(.realmode); - _i386boot_realmode_size = SIZEOF(.realmode); + __realmode_start = LOADADDR(.realmode); + __realmode_size = SIZEOF(.realmode);
/* 16bit BIOS emulation code (just enough to boot Linux) */ .bios 0 : AT ( LOADADDR(.realmode) + SIZEOF(.realmode) ) { KEEP(*(.bios)) }
- _i386boot_bios = LOADADDR(.bios); - _i386boot_bios_size = SIZEOF(.bios); + __bios_start = LOADADDR(.bios); + __bios_size = SIZEOF(.bios);
/* The load addresses below assumes that the flash * will be mapped so that 0x387f0000 == 0xffff0000 @@ -105,5 +103,4 @@ SECTIONS
. = 0xfff0; .resetvec : AT (TEXT_BASE + 0x3fff0) { KEEP(*(.resetvec)); } - _i386boot_end = (LOADADDR(.resetvec) + SIZEOF(.resetvec) ); }

Tidy up the linker script and discard some sections to save space
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/lib/board.c | 5 +++-- board/eNET/u-boot.lds | 39 ++++++++++++++++++--------------------- 2 files changed, 21 insertions(+), 23 deletions(-)
diff --git a/arch/i386/lib/board.c b/arch/i386/lib/board.c index e7a363d..3e89ef4 100644 --- a/arch/i386/lib/board.c +++ b/arch/i386/lib/board.c @@ -49,6 +49,7 @@ DECLARE_GLOBAL_DATA_PTR;
/* Exports from the Linker Script */ extern ulong __text_start; +extern ulong __data_end; extern ulong __rel_dyn_start; extern ulong __rel_dyn_end; extern ulong __bss_start; @@ -170,7 +171,7 @@ gd_t *gd; void board_init_f (ulong gdp) { void *text_start = &__text_start; - void *u_boot_cmd_end = &__u_boot_cmd_end; + void *data_end = &__data_end; Elf32_Rel *rel_dyn_start = (Elf32_Rel *)&__rel_dyn_start; Elf32_Rel *rel_dyn_end = (Elf32_Rel *)&__rel_dyn_end; void *bss_start = &__bss_start; @@ -181,7 +182,7 @@ void board_init_f (ulong gdp) ulong rel_offset; Elf32_Rel *re;
- uboot_size = (ulong)u_boot_cmd_end - (ulong)text_start; + uboot_size = (ulong)data_end - (ulong)text_start; dest_addr = (void *)gdp - (uboot_size + (ulong)bss_size); rel_offset = text_start - dest_addr;
diff --git a/board/eNET/u-boot.lds b/board/eNET/u-boot.lds index ef5d941..3c52010 100644 --- a/board/eNET/u-boot.lds +++ b/board/eNET/u-boot.lds @@ -29,50 +29,47 @@ SECTIONS { . = TEXT_BASE; /* Location of bootcode in flash */ __text_start = .; - .text : { *(.text); } + .text : { *(.text*); }
. = ALIGN(4); - .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } - - . = ALIGN(4); - - .data : { *(.data) } + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } . = ALIGN(4); + __u_boot_cmd_end = .;
- .interp : { *(.interp) } . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
- .dynsym : { *(.dynsym) } . = ALIGN(4); + .data : { *(.data*) }
- .dynstr : { *(.dynstr) } . = ALIGN(4); + .dynsym : { *(.dynsym*) }
- .hash : { *(.hash) } . = ALIGN(4); + .hash : { *(.hash*) }
- .got : { *(.got) } . = ALIGN(4); + .got : { *(.got*) }
- .got.plt : { *(.got.plt) } . = ALIGN(4); + __data_end = .;
- .dynamic (NOLOAD) : { *(.dynamic) } . = ALIGN(4); + __bss_start = ABSOLUTE(.); + .bss (NOLOAD) : { *(.bss) } + __bss_size = SIZEOF(.bss);
- __u_boot_cmd_start = .; - .u_boot_cmd : { *(.u_boot_cmd) } . = ALIGN(4); - __u_boot_cmd_end = .; - __rel_dyn_start = .; .rel.dyn : { *(.rel.dyn) } __rel_dyn_end = .;
- . = ALIGN(4); - __bss_start = ABSOLUTE(.); - .bss (NOLOAD) : { *(.bss) } - __bss_size = SIZEOF(.bss); + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) }
/* 16bit realmode trampoline code */ .realmode 0x7c0 : AT ( LOADADDR(.rel.dyn) + SIZEOF(.rel.dyn) ) { KEEP(*(.realmode)) }

Provides a small speed increase and prepares for fully relocatable image. Downside is the TEXT_BASE, bss, load address etc must ALL be aligned on a a 4-byte boundary which is not such a terrible restriction as everything is already 4-byte aligned anyway
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/lib/board.c | 47 +++++++++++++++++++++++++++++++---------------- board/eNET/u-boot.lds | 3 ++- 2 files changed, 33 insertions(+), 17 deletions(-)
diff --git a/arch/i386/lib/board.c b/arch/i386/lib/board.c index 3e89ef4..9c2f77f 100644 --- a/arch/i386/lib/board.c +++ b/arch/i386/lib/board.c @@ -53,7 +53,7 @@ extern ulong __data_end; extern ulong __rel_dyn_start; extern ulong __rel_dyn_end; extern ulong __bss_start; -extern ulong __bss_size; +extern ulong __bss_end;
const char version_string[] = U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")"; @@ -172,18 +172,22 @@ void board_init_f (ulong gdp) { void *text_start = &__text_start; void *data_end = &__data_end; - Elf32_Rel *rel_dyn_start = (Elf32_Rel *)&__rel_dyn_start; - Elf32_Rel *rel_dyn_end = (Elf32_Rel *)&__rel_dyn_end; + void *rel_dyn_start = &__rel_dyn_start; + void *rel_dyn_end = &__rel_dyn_end; void *bss_start = &__bss_start; - ulong bss_size = (ulong)&__bss_size; + void *bss_end = &__bss_end; + + ulong *dst_addr; + ulong *src_addr; + ulong *end_addr;
- ulong uboot_size; void *dest_addr; ulong rel_offset; - Elf32_Rel *re; + Elf32_Rel *re_src; + Elf32_Rel *re_end;
- uboot_size = (ulong)data_end - (ulong)text_start; - dest_addr = (void *)gdp - (uboot_size + (ulong)bss_size); + /* Calculate destination RAM Address and relocation offset */ + dest_addr = (void *)gdp - (bss_end - text_start); rel_offset = text_start - dest_addr;
/* First stage CPU initialization */ @@ -195,18 +199,29 @@ void board_init_f (ulong gdp) hang();
/* Copy U-Boot into RAM */ - memcpy(dest_addr, text_start, uboot_size); + dst_addr = (ulong *)dest_addr; + src_addr = (ulong *)text_start; + end_addr = (ulong *)data_end; + + while (src_addr < end_addr) + *dst_addr++ = *src_addr++;
/* Clear BSS */ - memset(bss_start - rel_offset, 0, bss_size); + dst_addr = (ulong *)(bss_start - rel_offset); + end_addr = (ulong *)(bss_end - rel_offset); + + while (dst_addr < end_addr) + *dst_addr++ = 0x00000000;
/* 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; - } + re_src = (Elf32_Rel *)rel_dyn_start; + re_end = (Elf32_Rel *)rel_dyn_end; + + do { + if (re_src->r_offset >= TEXT_BASE) + if (*(Elf32_Addr *)(re_src->r_offset - rel_offset) >= TEXT_BASE) + *(Elf32_Addr *)(re_src->r_offset - rel_offset) -= rel_offset; + } while (re_src++ < re_end);
((gd_t *)gdp)->reloc_off = rel_offset; ((gd_t *)gdp)->flags |= GD_FLG_RELOC; diff --git a/board/eNET/u-boot.lds b/board/eNET/u-boot.lds index 3c52010..b414079 100644 --- a/board/eNET/u-boot.lds +++ b/board/eNET/u-boot.lds @@ -58,7 +58,8 @@ SECTIONS . = ALIGN(4); __bss_start = ABSOLUTE(.); .bss (NOLOAD) : { *(.bss) } - __bss_size = SIZEOF(.bss); + . = ALIGN(4); + __bss_end = ABSOLUTE(.);
. = ALIGN(4); __rel_dyn_start = .;

u-boot.bin can be loaded at any 4-byte aligned memory location and directly 'jumped' to using the 'go' command using the load address as the start address. Doing so performs a 'warm boot' which skips memory initialisation and other low-level initialisations, relocates U-Boot to upper memory and starts U-Boot in RAM as per normal 'cold boot'
Signed-off-by: Graeme Russ graeme.russ@gmail.com --- arch/i386/cpu/start.S | 6 ++++++ arch/i386/include/asm/global_data.h | 28 +++++++++++++++------------- arch/i386/lib/board.c | 25 ++++++++++++++----------- 3 files changed, 35 insertions(+), 24 deletions(-)
diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index 8fdcd81..829468f 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -118,6 +118,11 @@ mem_ok:
wbinvd
+ /* Determine our load offset */ + call 1f +1: popl %ecx + subl $1b, %ecx + /* Set the upper memory limit parameter */ subl $CONFIG_SYS_STACK_SIZE, %eax
@@ -127,6 +132,7 @@ mem_ok: /* %eax points to the global data structure */ movl %esp, (GD_RAM_SIZE * 4)(%eax) movl %ebx, (GD_FLAGS * 4)(%eax) + movl %ecx, (GD_LOAD_OFF * 4)(%eax)
call board_init_f /* Enter, U-boot! */
diff --git a/arch/i386/include/asm/global_data.h b/arch/i386/include/asm/global_data.h index a15c598..5971123 100644 --- a/arch/i386/include/asm/global_data.h +++ b/arch/i386/include/asm/global_data.h @@ -41,6 +41,7 @@ typedef struct { unsigned long baudrate; unsigned long have_console; /* serial_init() was called */ unsigned long reloc_off; /* Relocation Offset */ + unsigned long load_off; /* Load Offset */ unsigned long env_addr; /* Address of Environment struct */ unsigned long env_valid; /* Checksum of Environment valid? */ unsigned long cpu_clk; /* CPU clock in Hz! */ @@ -56,20 +57,21 @@ extern gd_t *gd; #endif
/* Word Offsets into Global Data - MUST match struct gd_t */ -#define GD_BD 0 -#define GD_FLAGS 1 -#define GD_BAUDRATE 2 -#define GD_HAVE_CONSOLE 3 -#define GD_RELOC_OFF 4 -#define GD_ENV_ADDR 5 -#define GD_ENV_VALID 6 -#define GD_CPU_CLK 7 -#define GD_BUS_CLK 8 -#define GD_RAM_SIZE 9 -#define GD_RESET_STATUS 10 -#define GD_JT 11 +#define GD_BD 0 +#define GD_FLAGS 1 +#define GD_BAUDRATE 2 +#define GD_HAVE_CONSOLE 3 +#define GD_RELOC_OFF 4 +#define GD_LOAD_OFF 5 +#define GD_ENV_ADDR 6 +#define GD_ENV_VALID 7 +#define GD_CPU_CLK 8 +#define GD_BUS_CLK 9 +#define GD_RAM_SIZE 10 +#define GD_RESET_STATUS 11 +#define GD_JT 12
-#define GD_SIZE 12 +#define GD_SIZE 13
/* * Global Data Flags diff --git a/arch/i386/lib/board.c b/arch/i386/lib/board.c index 9c2f77f..1129918 100644 --- a/arch/i386/lib/board.c +++ b/arch/i386/lib/board.c @@ -190,18 +190,21 @@ void board_init_f (ulong gdp) dest_addr = (void *)gdp - (bss_end - text_start); rel_offset = text_start - dest_addr;
- /* First stage CPU initialization */ - if (cpu_init_f() != 0) - hang(); - - /* First stage Board initialization */ - if (board_early_init_f() != 0) - hang(); + /* Perform low-level initialization only when cold booted */ + if (((gd_t *)gdp)->flags & GD_FLG_COLD_BOOT) { + /* 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 */ dst_addr = (ulong *)dest_addr; - src_addr = (ulong *)text_start; - end_addr = (ulong *)data_end; + src_addr = (ulong *)(text_start + ((gd_t *)gdp)->load_off); + end_addr = (ulong *)(data_end + ((gd_t *)gdp)->load_off);
while (src_addr < end_addr) *dst_addr++ = *src_addr++; @@ -214,8 +217,8 @@ void board_init_f (ulong gdp) *dst_addr++ = 0x00000000;
/* Perform relocation adjustments */ - re_src = (Elf32_Rel *)rel_dyn_start; - re_end = (Elf32_Rel *)rel_dyn_end; + re_src = (Elf32_Rel *)(rel_dyn_start + ((gd_t *)gdp)->load_off); + re_end = (Elf32_Rel *)(rel_dyn_end + ((gd_t *)gdp)->load_off);
do { if (re_src->r_offset >= TEXT_BASE)
participants (1)
-
Graeme Russ