diff options
Diffstat (limited to 'arch/x86/lib')
-rw-r--r-- | arch/x86/lib/Makefile | 7 | ||||
-rw-r--r-- | arch/x86/lib/bdinfo.c | 5 | ||||
-rw-r--r-- | arch/x86/lib/bios.c | 4 | ||||
-rw-r--r-- | arch/x86/lib/bootm.c | 2 | ||||
-rw-r--r-- | arch/x86/lib/mrccache.c | 6 | ||||
-rw-r--r-- | arch/x86/lib/spl.c | 68 | ||||
-rw-r--r-- | arch/x86/lib/tables.c | 46 | ||||
-rw-r--r-- | arch/x86/lib/zimage.c | 93 |
8 files changed, 186 insertions, 45 deletions
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index b0612ae6dd5..90a7618ecfd 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -4,16 +4,17 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-y += bdinfo.o -ifndef CONFIG_X86_64 -ifndef CONFIG_TPL_BUILD + +ifndef CONFIG_$(SPL_TPL_)X86_64 obj-y += bios.o obj-y += bios_asm.o obj-y += bios_interrupts.o endif -endif + ifndef CONFIG_SPL_BUILD obj-$(CONFIG_X86_32BIT_INIT) += string.o endif + ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_BOOTM) += bootm.o endif diff --git a/arch/x86/lib/bdinfo.c b/arch/x86/lib/bdinfo.c index 15390070fe8..124058442c5 100644 --- a/arch/x86/lib/bdinfo.c +++ b/arch/x86/lib/bdinfo.c @@ -22,6 +22,11 @@ void arch_print_bdinfo(void) bdinfo_print_num_l("vendor", gd->arch.x86_vendor); bdinfo_print_str(" name", cpu_vendor_name(gd->arch.x86_vendor)); bdinfo_print_num_l("model", gd->arch.x86_model); + bdinfo_print_num_l("phys_addr in bits", cpu_phys_address_size()); + bdinfo_print_num_l("table start", gd->arch.table_start); + bdinfo_print_num_l("table end", gd->arch.table_end); + bdinfo_print_num_l(" high start", gd->arch.table_start_high); + bdinfo_print_num_l(" high end", gd->arch.table_end_high); if (IS_ENABLED(CONFIG_EFI_STUB)) efi_show_bdinfo(); diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c index 94349ba8073..e29cae78e50 100644 --- a/arch/x86/lib/bios.c +++ b/arch/x86/lib/bios.c @@ -23,7 +23,7 @@ static int (*int_handler[256])(void); /* to have a common register file for interrupt handlers */ -#ifndef CONFIG_BIOSEMU +#if !CONFIG_IS_ENABLED(BIOSEMU) X86EMU_sysEnv _X86EMU_env; #endif @@ -78,7 +78,7 @@ static int int_exception_handler(void) }; struct eregs *regs = ®_info; - debug("Oops, exception %d while executing option rom\n", regs->vector); + log_err("Exception %d while executing option rom\n", regs->vector); cpu_hlt(); return 0; diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index 61cb7bc6116..3196f9ddc2c 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -258,7 +258,7 @@ static ulong get_sp(void) ulong ret; #if CONFIG_IS_ENABLED(X86_64) - ret = gd->start_addr_sp; + asm("mov %%rsp, %0" : "=r"(ret) : ); #else asm("mov %%esp, %0" : "=r"(ret) : ); #endif diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c index 2f6f6880003..6494b8d2634 100644 --- a/arch/x86/lib/mrccache.c +++ b/arch/x86/lib/mrccache.c @@ -6,6 +6,8 @@ * Copyright (C) 2015 Bin Meng <bmeng.cn@gmail.com> */ +#define LOG_CATEGORY UCLASS_RAM + #include <common.h> #include <dm.h> #include <errno.h> @@ -197,8 +199,8 @@ static void mrccache_setup(struct mrc_output *mrc, void *data) cache->signature = MRC_DATA_SIGNATURE; cache->data_size = mrc->len; checksum = compute_ip_checksum(mrc->buf, cache->data_size); - debug("Saving %d bytes for MRC output data, checksum %04x\n", - cache->data_size, checksum); + log_debug("Saving %d bytes for MRC output data, checksum %04x\n", + cache->data_size, checksum); cache->checksum = checksum; cache->reserved = 0; memcpy(cache->data, mrc->buf, cache->data_size); diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index ca1645f9d68..b6812bb8ca2 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -3,6 +3,8 @@ * Copyright (c) 2016 Google, Inc */ +#define LOG_CATEGORY LOGC_BOOT + #include <common.h> #include <cpu_func.h> #include <debug_uart.h> @@ -15,10 +17,12 @@ #include <malloc.h> #include <spl.h> #include <syscon.h> +#include <vesa.h> #include <asm/cpu.h> #include <asm/cpu_common.h> #include <asm/fsp2/fsp_api.h> #include <asm/global_data.h> +#include <asm/mp.h> #include <asm/mrccache.h> #include <asm/mtrr.h> #include <asm/pci.h> @@ -61,6 +65,8 @@ static int set_max_freq(void) static int x86_spl_init(void) { + struct udevice *dev; + #ifndef CONFIG_TPL /* * TODO(sjg@chromium.org): We use this area of RAM for the stack @@ -74,49 +80,64 @@ static int x86_spl_init(void) #endif int ret; - debug("%s starting\n", __func__); + log_debug("x86 spl starting\n"); if (IS_ENABLED(TPL)) ret = x86_cpu_reinit_f(); else ret = x86_cpu_init_f(); ret = spl_init(); if (ret) { - debug("%s: spl_init() failed\n", __func__); + log_debug("spl_init() failed (err=%d)\n", ret); return ret; } ret = arch_cpu_init(); if (ret) { - debug("%s: arch_cpu_init() failed\n", __func__); + log_debug("arch_cpu_init() failed (err=%d)\n", ret); return ret; } #ifndef CONFIG_TPL ret = fsp_setup_pinctrl(NULL, NULL); if (ret) { - debug("%s: fsp_setup_pinctrl() failed\n", __func__); + log_debug("fsp_setup_pinctrl() failed (err=%d)\n", ret); return ret; } #endif - preloader_console_init(); + /* + * spl_board_init() below sets up the console if enabled. If it isn't, + * do it here. We cannot call this twice since it results in a double + * banner and CI tests fail. + */ + if (!IS_ENABLED(CONFIG_SPL_BOARD_INIT)) + preloader_console_init(); #if !defined(CONFIG_TPL) && !CONFIG_IS_ENABLED(CPU) ret = print_cpuinfo(); if (ret) { - debug("%s: print_cpuinfo() failed\n", __func__); + log_debug("print_cpuinfo() failed (err=%d)\n", ret); return ret; } #endif + /* probe the LPC so we get the GPIO_BASE set up correctly */ + ret = uclass_first_device_err(UCLASS_LPC, &dev); + if (ret && ret != -ENODEV) { + log_debug("lpc probe failed\n"); + return ret; + } + ret = dram_init(); if (ret) { - debug("%s: dram_init() failed\n", __func__); + log_debug("dram_init() failed (err=%d)\n", ret); return ret; } + log_debug("mrc\n"); if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) { ret = mrccache_spl_save(); if (ret) - debug("%s: Failed to write to mrccache (err=%d)\n", - __func__, ret); + log_debug("Failed to write to mrccache (err=%d)\n", + ret); } #ifndef CONFIG_SYS_COREBOOT + log_debug("bss\n"); debug("BSS clear from %lx to %lx len %lx\n", (ulong)&__bss_start, (ulong)&__bss_end, (ulong)&__bss_end - (ulong)&__bss_start); memset(&__bss_start, 0, (ulong)&__bss_end - (ulong)&__bss_start); @@ -136,9 +157,29 @@ static int x86_spl_init(void) */ gd->new_gd = (struct global_data *)ptr; memcpy(gd->new_gd, gd, sizeof(*gd)); + + log_debug("logging\n"); + /* + * Make sure logging is disabled when we switch, since the log system + * list head will move + */ + gd->new_gd->flags &= ~GD_FLG_LOG_READY; arch_setup_gd(gd->new_gd); gd->start_addr_sp = (ulong)ptr; + /* start up logging again, with the new list-head location */ + ret = log_init(); + if (ret) { + log_debug("Log setup failed (err=%d)\n", ret); + return ret; + } + + if (_LOG_DEBUG) { + ret = mtrr_list(mtrr_get_var_count(), MP_SELECT_BSP); + if (ret) + printf("mtrr_list failed\n"); + } + /* Cache the SPI flash. Otherwise copying the code to RAM takes ages */ ret = mtrr_add_request(MTRR_TYPE_WRBACK, (1ULL << 32) - CONFIG_XIP_ROM_SIZE, @@ -157,6 +198,7 @@ static int x86_spl_init(void) debug("Failed to set CPU frequency (err=%d)\n", ret); # endif #endif + log_debug("done\n"); return 0; } @@ -250,4 +292,12 @@ void spl_board_init(void) #ifndef CONFIG_TPL preloader_console_init(); #endif + + if (CONFIG_IS_ENABLED(VIDEO)) { + struct udevice *dev; + + /* Set up PCI video in SPL if required */ + uclass_first_device_err(UCLASS_PCI, &dev); + uclass_first_device_err(UCLASS_VIDEO, &dev); + } } diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index ea834a5035f..67bc0a72aeb 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -3,7 +3,7 @@ * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> */ -#define LOG_CATEGORY LOGC_BOARD +#define LOG_CATEGORY LOGC_ACPI #include <common.h> #include <bloblist.h> @@ -54,6 +54,10 @@ static struct table_info table_list[] = { #ifdef CONFIG_GENERATE_MP_TABLE { "mp", write_mp_table, }, #endif + /* + * tables which can go in the bloblist must be last in this list, so + * that the calculation of gd->table_end works properly + */ #ifdef CONFIG_GENERATE_ACPI_TABLE { "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, 0x10000, 0x1000}, #endif @@ -78,33 +82,42 @@ void table_fill_string(char *dest, const char *src, size_t n, char pad) int write_tables(void) { - u32 rom_table_start; - u32 rom_table_end; u32 high_table, table_size; struct memory_area cfg_tables[ARRAY_SIZE(table_list) + 1]; + bool use_high = false; + u32 rom_addr; int i; - rom_table_start = ROM_TABLE_ADDR; + gd->arch.table_start = ROM_TABLE_ADDR; + rom_addr = gd->arch.table_start; - debug("Writing tables to %x:\n", rom_table_start); + debug("Writing tables to %x:\n", rom_addr); for (i = 0; i < ARRAY_SIZE(table_list); i++) { const struct table_info *table = &table_list[i]; int size = table->size ? : CONFIG_ROM_TABLE_SIZE; + u32 rom_table_end; if (IS_ENABLED(CONFIG_BLOBLIST_TABLES) && table->tag) { - rom_table_start = (ulong)bloblist_add(table->tag, size, - table->align); - if (!rom_table_start) + if (!gd->arch.table_end) + gd->arch.table_end = rom_addr; + rom_addr = (ulong)bloblist_add(table->tag, size, + table->align); + if (!rom_addr) return log_msg_ret("bloblist", -ENOBUFS); + + /* the bloblist is always in high memory */ + use_high = true; + if (!gd->arch.table_start_high) + gd->arch.table_start_high = rom_addr; } - rom_table_end = table->write(rom_table_start); + rom_table_end = table->write(rom_addr); if (!rom_table_end) { log_err("Can't create configuration table %d\n", i); return -EINTR; } if (IS_ENABLED(CONFIG_SEABIOS)) { - table_size = rom_table_end - rom_table_start; + table_size = rom_table_end - rom_addr; high_table = (u32)(ulong)high_table_malloc(table_size); if (high_table) { if (!table->write(high_table)) { @@ -123,15 +136,20 @@ int write_tables(void) } debug("- wrote '%s' to %x, end %x\n", table->name, - rom_table_start, rom_table_end); - if (rom_table_end - rom_table_start > size) { + rom_addr, rom_table_end); + if (rom_table_end - rom_addr > size) { log_err("Out of space for configuration tables: need %x, have %x\n", - rom_table_end - rom_table_start, size); + rom_table_end - rom_addr, size); return log_msg_ret("bloblist", -ENOSPC); } - rom_table_start = rom_table_end; + rom_addr = rom_table_end; } + if (use_high) + gd->arch.table_end_high = rom_addr; + else + gd->arch.table_end = rom_addr; + if (IS_ENABLED(CONFIG_SEABIOS)) { /* make sure the last item is zero */ cfg_tables[i].size = 0; diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index e5ea5129c1e..062e3d3e315 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -22,6 +22,7 @@ #include <irq_func.h> #include <log.h> #include <malloc.h> +#include <mapmem.h> #include <acpi/acpi_table.h> #include <asm/io.h> #include <asm/ptrace.h> @@ -180,7 +181,7 @@ static int setup_device_tree(struct setup_header *hdr, const void *fdt_blob) return 0; } -static const char *get_kernel_version(struct boot_params *params, +const char *zimage_get_kernel_version(struct boot_params *params, void *kernel_base) { struct setup_header *hdr = ¶ms->hdr; @@ -188,10 +189,14 @@ static const char *get_kernel_version(struct boot_params *params, const char *s, *end; bootproto = get_boot_protocol(hdr, false); + log_debug("bootproto %x, hdr->setup_sects %x\n", bootproto, + hdr->setup_sects); if (bootproto < 0x0200 || hdr->setup_sects < 15) return NULL; /* sanity-check the kernel version in case it is missing */ + log_debug("hdr->kernel_version %x, str at %p\n", hdr->kernel_version, + kernel_base + hdr->kernel_version + 0x200); for (s = kernel_base + hdr->kernel_version + 0x200, end = s + 0x100; *s; s++) { if (!isprint(*s)) @@ -238,7 +243,7 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size, log_debug("Using boot protocol version %x.%02x\n", (bootproto & 0xff00) >> 8, bootproto & 0xff); - version = get_kernel_version(params, image); + version = zimage_get_kernel_version(params, image); if (version) printf("Linux kernel version %s\n", version); else @@ -442,8 +447,7 @@ static int do_zboot_start(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } -static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) +static int zboot_load(void) { struct boot_params *base_ptr; @@ -460,31 +464,51 @@ static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc, &state.load_address); if (!base_ptr) { puts("## Kernel loading failed ...\n"); - return CMD_RET_FAILURE; + return -EINVAL; } } state.base_ptr = base_ptr; - if (env_set_hex("zbootbase", (ulong)base_ptr) || + + return 0; +} + +static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (zboot_load()) + return CMD_RET_FAILURE; + + if (env_set_hex("zbootbase", map_to_sysmem(state.base_ptr)) || env_set_hex("zbootaddr", state.load_address)) return CMD_RET_FAILURE; return 0; } +static int zboot_setup(void) +{ + struct boot_params *base_ptr = state.base_ptr; + int ret; + + ret = setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET, + 0, state.initrd_addr, state.initrd_size, + (ulong)state.cmdline); + if (ret) + return -EINVAL; + + return 0; +} + static int do_zboot_setup(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct boot_params *base_ptr = state.base_ptr; - int ret; if (!base_ptr) { printf("base is not set: use 'zboot load' first\n"); return CMD_RET_FAILURE; } - ret = setup_zimage(base_ptr, (char *)base_ptr + COMMAND_LINE_OFFSET, - 0, state.initrd_addr, state.initrd_size, - (ulong)state.cmdline); - if (ret) { + if (zboot_setup()) { puts("Setting up boot parameters failed ...\n"); return CMD_RET_FAILURE; } @@ -501,8 +525,7 @@ static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } -static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) +static int zboot_go(void) { struct boot_params *params = state.base_ptr; struct setup_header *hdr = ¶ms->hdr; @@ -522,11 +545,52 @@ static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc, /* we assume that the kernel is in place */ ret = boot_linux_kernel((ulong)state.base_ptr, entry, image_64bit); + + return ret; +} + +static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + + ret = zboot_go(); printf("Kernel returned! (err=%d)\n", ret); return CMD_RET_FAILURE; } +int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size, + ulong base, char *cmdline) +{ + int ret; + + memset(&state, '\0', sizeof(state)); + + if (base) { + state.base_ptr = map_sysmem(base, 0); + state.load_address = addr; + } else { + state.bzimage_addr = addr; + } + state.bzimage_size = size; + state.initrd_addr = initrd; + state.initrd_size = initrd_size; + state.cmdline = cmdline; + + ret = zboot_load(); + if (ret) + return log_msg_ret("ld", ret); + ret = zboot_setup(); + if (ret) + return log_msg_ret("set", ret); + ret = zboot_go(); + if (ret) + return log_msg_ret("set", ret); + + return -EFAULT; +} + static void print_num(const char *name, ulong value) { printf("%-20s: %lx\n", name, value); @@ -668,7 +732,8 @@ void zimage_dump(struct boot_params *base_ptr) print_num("Real mode switch", hdr->realmode_swtch); print_num("Start sys seg", hdr->start_sys_seg); print_num("Kernel version", hdr->kernel_version); - version = get_kernel_version(base_ptr, (void *)state.bzimage_addr); + version = zimage_get_kernel_version(base_ptr, + (void *)state.bzimage_addr); if (version) printf(" @%p: %s\n", version, version); print_num("Type of loader", hdr->type_of_loader); |