coreboot-v3/arch/x86/stage1.c
<<
>>
Prefs
   1/*
   2 * This file is part of the coreboot project.
   3 *
   4 * Copyright (C) 2007 Stefan Reinauer <stepan@coresystems.de>
   5 * Copyright (C) 2007 Advanced Micro Devices, Inc.
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  19 */
  20
  21#include <types.h>
  22#include <io.h>
  23#include <console.h>
  24#include <cpu.h>
  25#include <globalvars.h>
  26#include <lar.h>
  27#include <string.h>
  28#include <tables.h>
  29#include <lib.h>
  30#include <mc146818rtc.h>
  31#include <cpu.h>
  32#include <multiboot.h>
  33#include <stage1.h>
  34
  35#ifdef CONFIG_PAYLOAD_ELF_LOADER
  36/* ah, well, what a mess! This is a hard code. FIX ME but how? 
  37 * By getting rid of ELF ...
  38 */
  39#define UNCOMPRESS_AREA (0x400000)
  40#endif /* CONFIG_PAYLOAD_ELF_LOADER */
  41
  42/* these prototypes should go into headers */
  43void uart_init(void);
  44void die(const char *msg);
  45void hardware_stage1(void);
  46void disable_car(void);
  47void mainboard_pre_payload(void);
  48
  49static void enable_rom(void)
  50{
  51        // nothing here yet
  52        post_code(POST_STAGE1_ENABLE_ROM);
  53}
  54
  55void init_archive(struct mem_file *archive)
  56{
  57        // FIXME this should be defined in the VPD area
  58        // but NOT IN THE CODE.
  59
  60        /* The len field starts behind the reset vector on x86.
  61         * The start is not correct for all platforms. sc520 will
  62         * need some hands on here.
  63         */
  64        archive->len = *(u32 *)0xfffffff4;
  65        archive->start =(void *)(0UL-archive->len);
  66
  67        // FIXME check integrity
  68
  69}
  70
  71/*
  72 * The name is slightly misleading because this is the initial stack pointer,
  73 * not the address of the first element on the stack.
  74 * NOTE: This function is very processor specific.
  75 */
  76void *bottom_of_stack(void)
  77{
  78        u32 onstack = (u32)&onstack;
  79
  80        /* Check whether the variable onstack is inside the CAR stack area.
  81         * If it is, assume we're still in CAR or the stack has not moved.
  82         * Otherwise return initial %esp for the RAM-based stack location.
  83         */
  84        if ((onstack >= CAR_STACK_BASE - CAR_STACK_SIZE) &&
  85            (onstack < CAR_STACK_BASE))
  86                return (void *)CAR_STACK_BASE;
  87        /* OK, so current %esp is not inside the CAR stack area. */
  88        return (void *)RAM_STACK_BASE;
  89}
  90
  91struct global_vars *global_vars(void)
  92{
  93        return *(struct global_vars **)(bottom_of_stack() - sizeof(struct global_vars *));
  94}
  95
  96void global_vars_init(struct global_vars *globvars)
  97{
  98        memset(globvars, 0, sizeof(struct global_vars));
  99        *(struct global_vars **)(bottom_of_stack() - sizeof(struct global_vars *)) = globvars;
 100#ifdef CONFIG_CONSOLE_BUFFER
 101        /* Initialize the printk buffer. */
 102        printk_buffer_init();
 103#endif
 104        console_loglevel_init();
 105
 106}
 107
 108#ifdef CONFIG_CHECK_STACK_USAGE
 109/* STACKFILL_BYTE could be a special value like 0x6b. Just make sure the stage0
 110 * code fills the complete CAR area with it. And the stack switching needs to
 111 * overwrite the unused parts of the stack with STACKFILL_BYTE as well.
 112 */
 113#define STACKFILL_BYTE 0x0
 114void check_stack()
 115{
 116        unsigned long stacksize, i;
 117        char *lowestaddr;
 118        if (global_vars()->ram_available)
 119                stacksize = RAM_STACK_SIZE;
 120        else
 121                stacksize = CAR_STACK_SIZE;
 122        lowestaddr = bottom_of_stack() - stacksize;
 123        for (i = 0; i < stacksize; i++)
 124                if (lowestaddr[i] != STACKFILL_BYTE)
 125                        break;
 126        global_vars()->loweststack = lowestaddr + i;
 127}
 128#endif
 129
 130void dump_mem_range(int msg_level, unsigned char *buf, int size)
 131{
 132        int i;
 133        printk(msg_level, "dumping memrange %p size %i:\n", buf, size);
 134        for (i = 0; i < size; i++) {
 135                printk(msg_level, "%02x ", buf[i]);
 136                if (i % 16 == 15)
 137                        printk(msg_level, "\n");
 138        }
 139        return;
 140}
 141
 142/** cycles
 143 * provide 64-bit high precision counter 
 144 * @returns Time in 64 bits
 145 */
 146u64 cycles(void)
 147{
 148        u64 ret;
 149        asm volatile ("rdtsc" : "=A" (ret));
 150        return ret;
 151}
 152
 153#ifdef CONFIG_PAYLOAD_ELF_LOADER
 154/* until we get rid of elf */
 155int legacy(struct mem_file *archive, char *name, void *where, struct lb_memory *mem)
 156{
 157        int ret;
 158        int elfboot_mem(struct lb_memory *mem, void *where, int size);
 159        ret = copy_file(archive, name, where);
 160        if (ret) {
 161                printk(BIOS_ERR, "'%s' found, but could not load it.\n", name);
 162        }
 163
 164        ret =  elfboot_mem(mem, where, archive->reallen);
 165
 166        printk(BIOS_ERR, "elfboot_mem returns %d\n", ret);
 167        return -1;
 168}
 169#endif /* CONFIG_PAYLOAD_ELF_LOADER */
 170
 171
 172static int run_address_multiboot(void *f, struct multiboot_info *mbi)
 173{
 174        int ret, dummy;
 175        __asm__ __volatile__ ("call *%4" : "=a" (ret), "=c" (dummy) : "a" (MB_MAGIC2), "b" (mbi), "c" (f) : "edx", "memory");
 176        return ret;
 177}
 178
 179/**
 180 * This function is called from assembler code with its argument on the
 181 * stack. Force the compiler to generate always correct code for this case.
 182 * We have cache as ram running and can start executing code in C.
 183 * @param bist Built In Self Test, which is used to indicate status of self test.
 184 * bist is defined by the CPU hardware and is present in EAX on first instruction of coreboot. 
 185 * Its value is implementation defined.
 186 * @param init_detected This (optionally set) value is used on some platforms (e.g. k8) to indicate
 187 * that we are restarting after some sort of reconfiguration. Note that we could use it on geode but 
 188 * do not at present. 
 189 */
 190void __attribute__((stdcall, regparm(0))) stage1_phase1(u32 bist, u32 init_detected, u32 cpu)
 191{
 192        struct global_vars globvars;
 193        int ret;
 194        struct mem_file archive;
 195
 196        post_code(POST_STAGE1_MAIN);
 197
 198        /* Only the BSP/BSC should do the following mainboard and global vars setup.
 199         */
 200        if (cpu == 0) {
 201                /* Initialize global variables before we can think of using them.
 202                 */
 203                global_vars_init(&globvars);
 204                globvars.init_detected = init_detected;
 205
 206                hardware_stage1();
 207
 208                uart_init();    // initialize serial port
 209
 210                /* Exactly from now on we can use printk to the serial port.
 211                 * Celebrate this by printing a LB banner.
 212                 */
 213                console_init();
 214
 215#ifdef CONFIG_CHECK_STACK_USAGE
 216                printk(BIOS_DEBUG, "Initial lowest stack is %p\n",
 217                        global_vars()->loweststack);
 218#endif
 219
 220                enable_rom();   // enable entire ROM area
 221        }
 222
 223        if (bist != 0) {
 224                printk(BIOS_INFO, "BIST FAILED: %08x on CPU: %08x", bist, cpu);
 225                die("");
 226        }
 227
 228        init_archive(&archive);
 229
 230        // find first initram
 231        if (check_normal_boot_flag()) {
 232                printk(BIOS_DEBUG, "Choosing normal boot.\n");
 233                ret = execute_in_place(&archive, "normal/initram/segment0");
 234        } else {
 235                printk(BIOS_DEBUG, "Choosing fallback boot.\n");
 236                ret = execute_in_place(&archive, "fallback/initram/segment0");
 237                /* Try a normal boot if fallback doesn't exist in the lar.
 238                 * TODO: There are other ways to do this.
 239                 * It could be ifdef or the boot flag could be forced.
 240                 */
 241                if (ret) {
 242                        printk(BIOS_DEBUG, "Fallback failed. Try normal boot\n");
 243                        ret = execute_in_place(&archive, "normal/initram/segment0");
 244                }
 245        }
 246
 247        if (ret)
 248                die("Failed RAM init code\n");
 249
 250        printk(BIOS_DEBUG, "Done RAM init code\n");
 251#ifdef CONFIG_CHECK_STACK_USAGE
 252        printk(BIOS_DEBUG, "After RAM init, lowest stack is %p\n",
 253                global_vars()->loweststack);
 254#endif
 255
 256        /* Switch the stack location from CAR to RAM, rebuild the stack,
 257         * disable CAR and continue at stage1_phase3(). This is all wrapped in
 258         * stage1_phase2() to make the code easier to follow.
 259         * We will NEVER return.
 260         */
 261        stage1_phase2();
 262
 263        /* If we reach this point, something went terribly wrong. */
 264        die("The world is broken.\n");
 265}
 266
 267/**
 268 * This function is called to take care of switching and rebuilding the stack
 269 * so that we can cope with processors which don't support a CAR area at low
 270 * addresses where CAR could be copied to RAM without problems.
 271 * This function handles everything related to switching off CAR and moving
 272 * important data from CAR to RAM.
 273 * 1.  Perform all work which can be done while CAR and RAM are both active.
 274 *     That's mainly moving the printk buffer around.
 275 * 2a. Optionally back up the new stack location (desirable for S3).
 276 * 2b. Optionally rebuild the stack at another location.
 277 * 2c. Switch stack pointer to the new stack if the stack was rebuilt.
 278 * 3.  Disable CAR.
 279 * 4.  Call or jump to stage1_phase3.
 280 * Steps 2a-4 have to be done in asm. That's what the oddly named disable_car()
 281 * function does.
 282 *
 283 * TODO: Some parts of the list above are not yet done, so the code will not
 284 * yet work on C7.
 285 */
 286void stage1_phase2(void)
 287{
 288#ifdef CONFIG_CONSOLE_BUFFER
 289        /* Move the printk buffer to PRINTK_BUF_ADDR_RAM */
 290        printk_buffer_move((void *)PRINTK_BUF_ADDR_RAM, PRINTK_BUF_SIZE_RAM);
 291        printk(BIOS_DEBUG, "Done printk() buffer move\n");
 292#endif
 293        /* Turn off Cache-As-Ram */
 294        disable_car();
 295
 296        /* If we reach this point, something went terribly wrong. */
 297        die("The world is broken.\n");
 298}
 299
 300/**
 301 * This function is the second part of the former stage1_main() after
 302 * switching the stack and disabling CAR.
 303 */
 304void __attribute__((stdcall)) stage1_phase3(void)
 305{
 306        void *entry;
 307        struct mem_file archive;
 308        struct multiboot_info *mbi;
 309
 310#ifdef CONFIG_PAYLOAD_ELF_LOADER
 311        int ret;
 312        struct mem_file result;
 313        int elfboot_mem(struct lb_memory *mem, void *where, int size);
 314
 315        /* Why can't we statically init this hack? */
 316        unsigned char faker[64];
 317        struct lb_memory *mem = (struct lb_memory*) faker;
 318
 319        mem->tag = LB_TAG_MEMORY;
 320        mem->size = 28;
 321        mem->map[0].start.lo = mem->map[0].start.hi = 0;
 322        mem->map[0].size.lo = (32*1024*1024);
 323        mem->map[0].size.hi = 0;
 324        mem->map[0].type = LB_MEM_RAM;
 325#endif /* CONFIG_PAYLOAD_ELF_LOADER */
 326
 327        /* Provide an easy way to check whether RAM is available. */
 328        global_vars()->ram_available = 1;
 329
 330        // location and size of image.
 331        init_archive(&archive);
 332
 333        entry = load_file_segments(&archive, "normal/stage2");
 334        if (entry == (void *)-1)
 335                die("FATAL: Failed loading stage2.");
 336        mbi = (struct multiboot_info*) run_address(entry);
 337        if (! mbi)
 338                die("FATAL: Failed in stage2 code.");
 339
 340        printk(BIOS_DEBUG, "Stage2 code done.\n");
 341
 342#ifdef CONFIG_PAYLOAD_ELF_LOADER
 343        ret = find_file(&archive, "normal/payload", &result);
 344        if (! ret)
 345                legacy(&archive, "normal/payload", (void *)UNCOMPRESS_AREA, mem);
 346#endif /* CONFIG_PAYLOAD_ELF_LOADER */
 347
 348        entry = load_file_segments(&archive, "normal/payload");
 349#ifdef CONFIG_CHECK_STACK_USAGE
 350        printk(BIOS_DEBUG, "Before handoff to payload, lowest stack is %p\n",
 351                global_vars()->loweststack);
 352#endif
 353        if (entry != (void*)-1) {
 354                /* Final coreboot call before handing off to the payload. */
 355                mainboard_pre_payload();
 356                run_address_multiboot(entry, mbi);
 357        } else {
 358                die("FATAL: No usable payload found.\n");
 359        }
 360        die ("FATAL: Last stage returned to coreboot.\n");
 361}
 362
 363
 364
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.