diff --git a/arch/x86/amd/k8/stage1.c b/arch/x86/amd/k8/stage1.c index c729de262f..0bed559dc2 100644 --- a/arch/x86/amd/k8/stage1.c +++ b/arch/x86/amd/k8/stage1.c @@ -26,6 +26,7 @@ #include #include #include +#include /** * Set the MTRR for initial ram access. @@ -73,4 +74,5 @@ void disable_car(void) /* we're now running in ram. Although this will be called again, it does no harm to call it here. */ set_init_ram_access(); banner(BIOS_DEBUG, "disable_car: done"); + stage1_phase3(); } diff --git a/arch/x86/amd/stage0.S b/arch/x86/amd/stage0.S index dc691ec35a..6a8aeb594e 100644 --- a/arch/x86/amd/stage0.S +++ b/arch/x86/amd/stage0.S @@ -341,7 +341,7 @@ CAR_FAM10_ap_out: pushl %ebx /* First parameter: bist */ pushl %eax - call stage1_main + call stage1_phase1 /* We will not go back. */ movb $0xAF, %al /* Should never see this postcode */ diff --git a/arch/x86/geodelx/stage0.S b/arch/x86/geodelx/stage0.S index c3c1d7318f..4f3a230b7e 100644 --- a/arch/x86/geodelx/stage0.S +++ b/arch/x86/geodelx/stage0.S @@ -271,7 +271,7 @@ lout: pushl $0 /* First parameter: bist */ pushl %eax - call stage1_main + call stage1_phase1 /* We will not go back. */ #include "../stage0_common.S" diff --git a/arch/x86/geodelx/stage1.c b/arch/x86/geodelx/stage1.c index 443a7f773d..48e08ba914 100644 --- a/arch/x86/geodelx/stage1.c +++ b/arch/x86/geodelx/stage1.c @@ -24,6 +24,7 @@ #include #include #include +#include static const struct msrinit msr_table[] = { /* Setup access to cache under 1MB. */ @@ -93,4 +94,5 @@ void disable_car(void) banner(BIOS_DEBUG, "Disable_car: done wbinvd"); northbridge_init_early(); banner(BIOS_DEBUG, "disable_car: done"); + stage1_phase3(); } diff --git a/arch/x86/i586/stage0.S b/arch/x86/i586/stage0.S index 6b89749810..668420c6a4 100644 --- a/arch/x86/i586/stage0.S +++ b/arch/x86/i586/stage0.S @@ -339,7 +339,7 @@ lout: pushl $0 /* First parameter: bist */ pushl %eax - call stage1_main + call stage1_phase1 /* We will not go back. */ fixed_mtrr_msr: diff --git a/arch/x86/stage1.c b/arch/x86/stage1.c index 5defdfdce6..ce3d24c135 100644 --- a/arch/x86/stage1.c +++ b/arch/x86/stage1.c @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef CONFIG_PAYLOAD_ELF_LOADER /* ah, well, what a mess! This is a hard code. FIX ME but how? @@ -154,28 +155,12 @@ static int run_address_multiboot(void *f) * that we are restarting after some sort of reconfiguration. Note that we could use it on geode but * do not at present. */ -void __attribute__((stdcall)) stage1_main(u32 bist, u32 init_detected) +void __attribute__((stdcall)) stage1_phase1(u32 bist, u32 init_detected) { struct global_vars globvars; int ret; struct mem_file archive; - void *entry; struct node_core_id me; -#ifdef CONFIG_PAYLOAD_ELF_LOADER - struct mem_file result; - int elfboot_mem(struct lb_memory *mem, void *where, int size); - - /* Why can't we statically init this hack? */ - unsigned char faker[64]; - struct lb_memory *mem = (struct lb_memory*) faker; - - mem->tag = LB_TAG_MEMORY; - mem->size = 28; - mem->map[0].start.lo = mem->map[0].start.hi = 0; - mem->map[0].size.lo = (32*1024*1024); - mem->map[0].size.hi = 0; - mem->map[0].type = LB_MEM_RAM; -#endif /* CONFIG_PAYLOAD_ELF_LOADER */ post_code(POST_STAGE1_MAIN); @@ -234,13 +219,76 @@ void __attribute__((stdcall)) stage1_main(u32 bist, u32 init_detected) printk(BIOS_DEBUG, "Done RAM init code\n"); - /* Turn off Cache-As-Ram */ - disable_car(); + /* Switch the stack location from CAR to RAM, rebuild the stack, + * disable CAR and continue at stage1_phase3(). This is all wrapped in + * stage1_phase2() to make the code easier to follow. + * We will NEVER return. + */ + stage1_phase2(); + /* If we reach this point, something went terribly wrong. */ + die("The world is broken.\n"); +} + +/** + * This function is called to take care of switching and rebuilding the stack + * so that we can cope with processors which don't support a CAR area at low + * addresses where CAR could be copied to RAM without problems. + * This function handles everything related to switching off CAR and moving + * important data from CAR to RAM. + * 1. Perform all work which can be done while CAR and RAM are both active. + * That's mainly moving the printk buffer around. + * 2a. Optionally back up the new stack location (desirable for S3). + * 2b. Optionally rebuild the stack at another location. + * 2c. Switch stack pointer to the new stack if the stack was rebuilt. + * 3. Disable CAR. + * 4. Call or jump to stage1_phase3. + * Steps 2a-4 have to be done in asm. That's what the oddly named disable_car() + * function does. + * + * TODO: Some parts of the list above are not yet done, so the code will not + * yet work on C7. + */ +void stage1_phase2() +{ #ifdef CONFIG_CONSOLE_BUFFER /* Move the printk buffer to PRINTK_BUF_ADDR_RAM */ printk_buffer_move((void *)PRINTK_BUF_ADDR_RAM, PRINTK_BUF_SIZE_RAM); #endif + /* Turn off Cache-As-Ram */ + disable_car(); + + /* If we reach this point, something went terribly wrong. */ + die("The world is broken.\n"); +} + +/** + * This function is the second part of the former stage1_main() after + * switching the stack and disabling CAR. + */ +void __attribute__((stdcall)) stage1_phase3() +{ + void *entry; + int ret; + struct mem_file archive; +#ifdef CONFIG_PAYLOAD_ELF_LOADER + struct mem_file result; + int elfboot_mem(struct lb_memory *mem, void *where, int size); + + /* Why can't we statically init this hack? */ + unsigned char faker[64]; + struct lb_memory *mem = (struct lb_memory*) faker; + + mem->tag = LB_TAG_MEMORY; + mem->size = 28; + mem->map[0].start.lo = mem->map[0].start.hi = 0; + mem->map[0].size.lo = (32*1024*1024); + mem->map[0].size.hi = 0; + mem->map[0].type = LB_MEM_RAM; +#endif /* CONFIG_PAYLOAD_ELF_LOADER */ + + // location and size of image. + init_archive(&archive); entry = load_file_segments(&archive, "normal/stage2"); if (entry == (void *)-1) diff --git a/arch/x86/via/stage0.S b/arch/x86/via/stage0.S index 9a30dfce3e..59f129de39 100644 --- a/arch/x86/via/stage0.S +++ b/arch/x86/via/stage0.S @@ -189,7 +189,7 @@ lout: pushl $0 /* First parameter: bist */ pushl %eax - call stage1_main + call stage1_phase1 /* We will not go back. */ fixed_mtrr_msr: diff --git a/doc/design/newboot.lyx b/doc/design/newboot.lyx index 51921db17c..e113c1c8d1 100644 --- a/doc/design/newboot.lyx +++ b/doc/design/newboot.lyx @@ -759,7 +759,7 @@ Stage 1: C, in arch/{architecture} \end_layout \begin_layout Standard -Initial entry point for stage 1 is arch/{architecture}/stage1.c:stage1_main(). +Initial entry point for stage 1 is arch/{architecture}/stage1.c:stage1_phase1(). \end_layout \begin_layout Standard diff --git a/include/arch/x86/stage1.h b/include/arch/x86/stage1.h new file mode 100644 index 0000000000..034670552f --- /dev/null +++ b/include/arch/x86/stage1.h @@ -0,0 +1,2 @@ +void stage1_phase2(void); +void __attribute__((stdcall)) stage1_phase3(void); diff --git a/mainboard/emulation/qemu-x86/stage1.c b/mainboard/emulation/qemu-x86/stage1.c index 742050872a..0ed9eb7dbe 100644 --- a/mainboard/emulation/qemu-x86/stage1.c +++ b/mainboard/emulation/qemu-x86/stage1.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + /* printk() will not yet output anything. */ /** @@ -34,6 +36,7 @@ void stop_ap(void) void disable_car(void) { + stage1_phase3(); }