summaryrefslogtreecommitdiff
path: root/arch/x86/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/lib')
-rw-r--r--arch/x86/lib/Makefile7
-rw-r--r--arch/x86/lib/bdinfo.c5
-rw-r--r--arch/x86/lib/bios.c4
-rw-r--r--arch/x86/lib/bootm.c2
-rw-r--r--arch/x86/lib/mrccache.c6
-rw-r--r--arch/x86/lib/spl.c68
-rw-r--r--arch/x86/lib/tables.c46
-rw-r--r--arch/x86/lib/zimage.c93
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 = &reg_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 = &params->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 = &params->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);