Merge git://git.denx.de/u-boot-x86

This commit is contained in:
Tom Rini 2015-10-21 20:47:40 -04:00
commit 858dbdf841
207 changed files with 1726 additions and 752 deletions

View File

@ -1288,6 +1288,7 @@ define filechk_timestamp.h
LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_DATE "%b %d %C%y"'; \
LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_TIME "%T"'; \
LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_TZ "%z"'; \
LC_ALL=C $${DATE} -u -d "$${SOURCE_DATE}" +'#define U_BOOT_DMI_DATE "%m/%d/%Y"'; \
else \
return 42; \
fi; \
@ -1295,6 +1296,7 @@ define filechk_timestamp.h
LC_ALL=C date +'#define U_BOOT_DATE "%b %d %C%y"'; \
LC_ALL=C date +'#define U_BOOT_TIME "%T"'; \
LC_ALL=C date +'#define U_BOOT_TZ "%z"'; \
LC_ALL=C date +'#define U_BOOT_DMI_DATE "%m/%d/%Y"'; \
fi)
endef

12
README
View File

@ -796,18 +796,10 @@ The following options need to be configured:
- vxWorks boot parameters:
bootvx constructs a valid bootline using the following
environments variables: bootfile, ipaddr, serverip, hostname.
environments variables: bootdev, bootfile, ipaddr, netmask,
serverip, gatewayip, hostname, othbootargs.
It loads the vxWorks image pointed bootfile.
CONFIG_SYS_VXWORKS_BOOT_DEVICE - The vxworks device name
CONFIG_SYS_VXWORKS_MAC_PTR - Ethernet 6 byte MA -address
CONFIG_SYS_VXWORKS_SERVERNAME - Name of the server
CONFIG_SYS_VXWORKS_BOOT_ADDR - Address of boot parameters
CONFIG_SYS_VXWORKS_ADD_PARAMS
Add it at the end of the bootline. E.g "u=username pw=secret"
Note: If a "bootargs" environment is defined, it will overwride
the defaults discussed just above.

View File

@ -239,6 +239,14 @@ config FSP_SYS_MALLOC_F_LEN
help
Additional size of malloc() pool before relocation.
config ENABLE_MRC_CACHE
bool "Enable MRC cache"
depends on !EFI && !SYS_COREBOOT
help
Enable this feature to cause MRC data to be cached in NV storage
to be used for speeding up boot time on future reboots and/or
power cycles.
config SMP
bool "Enable Symmetric Multiprocessing"
default n
@ -358,6 +366,17 @@ config GENERATE_ACPI_TABLE
by the operating system. It defines platform-independent interfaces
for configuration and power management monitoring.
config GENERATE_SMBIOS_TABLE
bool "Generate an SMBIOS (System Management BIOS) table"
default y
help
The System Management BIOS (SMBIOS) specification addresses how
motherboard and system vendors present management information about
their products in a standard format by extending the BIOS interface
on Intel architecture systems.
Check http://www.dmtf.org/standards/smbios for details.
endmenu
config MAX_PIRQ_LINKS

View File

@ -8,6 +8,7 @@
#include <mmc.h>
#include <pci_ids.h>
#include <asm/irq.h>
#include <asm/mrccache.h>
#include <asm/post.h>
static struct pci_device_id mmc_supported[] = {
@ -43,6 +44,30 @@ int arch_misc_init(void)
if (!ll_boot_init())
return 0;
#ifdef CONFIG_ENABLE_MRC_CACHE
/*
* We intend not to check any return value here, as even MRC cache
* is not saved successfully, it is not a severe error that will
* prevent system from continuing to boot.
*/
mrccache_save();
#endif
return pirq_init();
}
int reserve_arch(void)
{
#ifdef CONFIG_ENABLE_MRC_CACHE
return mrccache_reserve();
#else
return 0;
#endif
}
#endif
void reset_cpu(ulong addr)
{
/* cold reset */
x86_full_reset();
}

View File

@ -142,7 +142,12 @@ void arch_setup_gd(gd_t *new_gd)
gdt_addr = new_gd->arch.gdt;
/* CS: code, read/execute, 4 GB, base 0 */
/*
* CS: code, read/execute, 4 GB, base 0
*
* Some OS (like VxWorks) requires GDT entry 1 to be the 32-bit CS
*/
gdt_addr[X86_GDT_ENTRY_UNUSED] = GDT_ENTRY(0xc09b, 0, 0xfffff);
gdt_addr[X86_GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff);
/* DS: data, read/write, 4 GB, base 0 */

View File

@ -14,7 +14,6 @@ obj-y += lpc.o
obj-y += me_status.o
obj-y += model_206ax.o
obj-y += microcode_intel.o
obj-y += mrccache.o
obj-y += northbridge.o
obj-y += pch.o
obj-y += pci.o

View File

@ -55,38 +55,6 @@ void bd82x6x_pci_init(pci_dev_t dev)
x86_pci_write_config16(dev, SECSTS, reg16);
}
#define PCI_BRIDGE_UPDATE_COMMAND
void bd82x6x_pci_dev_enable_resources(pci_dev_t dev)
{
uint16_t command;
command = x86_pci_read_config16(dev, PCI_COMMAND);
command |= PCI_COMMAND_IO;
#ifdef PCI_BRIDGE_UPDATE_COMMAND
/*
* If we write to PCI_COMMAND, on some systems this will cause the
* ROM and APICs to become invisible.
*/
debug("%x cmd <- %02x\n", dev, command);
x86_pci_write_config16(dev, PCI_COMMAND, command);
#else
printf("%s cmd <- %02x (NOT WRITTEN!)\n", dev_path(dev), command);
#endif
}
void bd82x6x_pci_bus_enable_resources(pci_dev_t dev)
{
uint16_t ctrl;
ctrl = x86_pci_read_config16(dev, PCI_BRIDGE_CONTROL);
ctrl |= PCI_COMMAND_IO;
ctrl |= PCI_BRIDGE_CTL_VGA;
debug("%x bridge ctrl <- %04x\n", dev, ctrl);
x86_pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl);
bd82x6x_pci_dev_enable_resources(dev);
}
static int bd82x6x_probe(struct udevice *dev)
{
const void *blob = gd->fdt_blob;

View File

@ -188,7 +188,7 @@ car_uninit:
wrmsr
/* Disable the no-eviction run state */
movl NOEVICTMOD_MSR, %ecx
movl $NOEVICTMOD_MSR, %ecx
rdmsr
andl $~2, %eax
wrmsr

View File

@ -340,3 +340,10 @@ int print_cpuinfo(void)
return 0;
}
void board_debug_uart_init(void)
{
/* This enables the debug UART */
pci_x86_write_config(NULL, PCH_LPC_DEV, LPC_EN, COMA_LPC_EN,
PCI_SIZE_16);
}

View File

@ -21,10 +21,10 @@
#include <asm/processor.h>
#include <asm/gpio.h>
#include <asm/global_data.h>
#include <asm/mrccache.h>
#include <asm/mtrr.h>
#include <asm/pci.h>
#include <asm/arch/me.h>
#include <asm/arch/mrccache.h>
#include <asm/arch/pei_data.h>
#include <asm/arch/pch.h>
#include <asm/post.h>
@ -89,51 +89,15 @@ void dram_init_banksize(void)
}
}
static int get_mrc_entry(struct udevice **devp, struct fmap_entry *entry)
{
const void *blob = gd->fdt_blob;
int node, spi_node, mrc_node;
int upto;
int ret;
/* Find the flash chip within the SPI controller node */
upto = 0;
spi_node = fdtdec_next_alias(blob, "spi", COMPAT_INTEL_ICH_SPI, &upto);
if (spi_node < 0)
return -ENOENT;
node = fdt_first_subnode(blob, spi_node);
if (node < 0)
return -ECHILD;
/* Find the place where we put the MRC cache */
mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache");
if (mrc_node < 0)
return -EPERM;
if (fdtdec_read_fmap_entry(blob, mrc_node, "rm-mrc-cache", entry))
return -EINVAL;
if (devp) {
debug("getting sf\n");
ret = uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node,
devp);
debug("ret = %d\n", ret);
if (ret)
return ret;
}
return 0;
}
static int read_seed_from_cmos(struct pei_data *pei_data)
{
u16 c1, c2, checksum, seed_checksum;
struct udevice *dev;
int rcode = 0;
int ret = 0;
rcode = uclass_get_device(UCLASS_RTC, 0, &dev);
if (rcode) {
debug("Cannot find RTC: err=%d\n", rcode);
ret = uclass_get_device(UCLASS_RTC, 0, &dev);
if (ret) {
debug("Cannot find RTC: err=%d\n", ret);
return -ENODEV;
}
@ -143,11 +107,18 @@ static int read_seed_from_cmos(struct pei_data *pei_data)
* the flash too much. So we store these in CMOS and the large MRC
* data in SPI flash.
*/
rtc_read32(dev, CMOS_OFFSET_MRC_SEED, &pei_data->scrambler_seed);
ret = rtc_read32(dev, CMOS_OFFSET_MRC_SEED, &pei_data->scrambler_seed);
if (!ret) {
ret = rtc_read32(dev, CMOS_OFFSET_MRC_SEED_S3,
&pei_data->scrambler_seed_s3);
}
if (ret) {
debug("Failed to read from RTC %s\n", dev->name);
return ret;
}
debug("Read scrambler seed 0x%08x from CMOS 0x%02x\n",
pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED);
rtc_read32(dev, CMOS_OFFSET_MRC_SEED_S3, &pei_data->scrambler_seed_s3);
debug("Read S3 scrambler seed 0x%08x from CMOS 0x%02x\n",
pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3);
@ -174,27 +145,21 @@ static int read_seed_from_cmos(struct pei_data *pei_data)
static int prepare_mrc_cache(struct pei_data *pei_data)
{
struct mrc_data_container *mrc_cache;
struct fmap_entry entry;
struct mrc_region entry;
int ret;
ret = read_seed_from_cmos(pei_data);
if (ret)
return ret;
ret = get_mrc_entry(NULL, &entry);
ret = mrccache_get_region(NULL, &entry);
if (ret)
return ret;
mrc_cache = mrccache_find_current(&entry);
if (!mrc_cache)
return -ENOENT;
/*
* TODO(sjg@chromium.org): Skip this for now as it causes boot
* problems
*/
if (0) {
pei_data->mrc_input = mrc_cache->data;
pei_data->mrc_input_len = mrc_cache->data_size;
}
pei_data->mrc_input = mrc_cache->data;
pei_data->mrc_input_len = mrc_cache->data_size;
debug("%s: at %p, size %x checksum %04x\n", __func__,
pei_data->mrc_input, pei_data->mrc_input_len,
mrc_cache->checksum);
@ -202,41 +167,15 @@ static int prepare_mrc_cache(struct pei_data *pei_data)
return 0;
}
static int build_mrc_data(struct mrc_data_container **datap)
{
struct mrc_data_container *data;
int orig_len;
int output_len;
orig_len = gd->arch.mrc_output_len;
output_len = ALIGN(orig_len, 16);
data = malloc(output_len + sizeof(*data));
if (!data)
return -ENOMEM;
data->signature = MRC_DATA_SIGNATURE;
data->data_size = output_len;
data->reserved = 0;
memcpy(data->data, gd->arch.mrc_output, orig_len);
/* Zero the unused space in aligned buffer. */
if (output_len > orig_len)
memset(data->data + orig_len, 0, output_len - orig_len);
data->checksum = compute_ip_checksum(data->data, output_len);
*datap = data;
return 0;
}
static int write_seeds_to_cmos(struct pei_data *pei_data)
{
u16 c1, c2, checksum;
struct udevice *dev;
int rcode = 0;
int ret = 0;
rcode = uclass_get_device(UCLASS_RTC, 0, &dev);
if (rcode) {
debug("Cannot find RTC: err=%d\n", rcode);
ret = uclass_get_device(UCLASS_RTC, 0, &dev);
if (ret) {
debug("Cannot find RTC: err=%d\n", ret);
return -ENODEV;
}
@ -262,42 +201,12 @@ static int write_seeds_to_cmos(struct pei_data *pei_data)
return 0;
}
static int sdram_save_mrc_data(void)
{
struct mrc_data_container *data;
struct fmap_entry entry;
struct udevice *sf;
int ret;
if (!gd->arch.mrc_output_len)
return 0;
debug("Saving %d bytes of MRC output data to SPI flash\n",
gd->arch.mrc_output_len);
ret = get_mrc_entry(&sf, &entry);
if (ret)
goto err_entry;
ret = build_mrc_data(&data);
if (ret)
goto err_data;
ret = mrccache_update(sf, &entry, data);
if (!ret)
debug("Saved MRC data with checksum %04x\n", data->checksum);
free(data);
err_data:
err_entry:
if (ret)
debug("%s: Failed: %d\n", __func__, ret);
return ret;
}
/* Use this hook to save our SDRAM parameters */
int misc_init_r(void)
{
int ret;
ret = sdram_save_mrc_data();
ret = mrccache_save();
if (ret)
printf("Unable to save MRC data: %d\n", ret);
@ -421,9 +330,11 @@ int sdram_initialise(struct pei_data *pei_data)
if (data) {
int rv;
int (*func)(struct pei_data *);
ulong start;
debug("Calling MRC at %p\n", data);
post_code(POST_PRE_MRC);
start = get_timer(0);
func = (int (*)(struct pei_data *))data;
rv = func(pei_data);
post_code(POST_MRC);
@ -441,6 +352,7 @@ int sdram_initialise(struct pei_data *pei_data)
printf("Nonzero MRC return value.\n");
return -EFAULT;
}
debug("MRC execution time %lu ms\n", get_timer(start));
} else {
printf("UEFI PEI System Agent not found.\n");
return -ENOSYS;
@ -455,7 +367,7 @@ int sdram_initialise(struct pei_data *pei_data)
debug("System Agent Version %d.%d.%d Build %d\n",
version >> 24 , (version >> 16) & 0xff,
(version >> 8) & 0xff, version & 0xff);
debug("MCR output data length %#x at %p\n", pei_data->mrc_output_len,
debug("MRC output data length %#x at %p\n", pei_data->mrc_output_len,
pei_data->mrc_output);
/*
@ -476,7 +388,7 @@ int sdram_initialise(struct pei_data *pei_data)
if (pei_data->boot_mode != PEI_BOOT_RESUME) {
/*
* This will be copied to SDRAM in reserve_arch(), then written
* to SPI flash in sdram_save_mrc_data()
* to SPI flash in mrccache_save()
*/
gd->arch.mrc_output = (char *)pei_data->mrc_output;
gd->arch.mrc_output_len = pei_data->mrc_output_len;
@ -490,19 +402,7 @@ int sdram_initialise(struct pei_data *pei_data)
int reserve_arch(void)
{
u16 checksum;
checksum = compute_ip_checksum(gd->arch.mrc_output,
gd->arch.mrc_output_len);
debug("Saving %d bytes for MRC output data, checksum %04x\n",
gd->arch.mrc_output_len, checksum);
gd->start_addr_sp -= gd->arch.mrc_output_len;
memcpy((void *)gd->start_addr_sp, gd->arch.mrc_output,
gd->arch.mrc_output_len);
gd->arch.mrc_output = (char *)gd->start_addr_sp;
gd->start_addr_sp &= ~0xf;
return 0;
return mrccache_reserve();
}
static int copy_spd(struct pei_data *peid)
@ -827,7 +727,7 @@ int dram_init(void)
int ret;
debug("Boot mode %d\n", gd->arch.pei_boot_mode);
debug("mcr_input %p\n", pei_data.mrc_input);
debug("mrc_input %p\n", pei_data.mrc_input);
pei_data.boot_mode = gd->arch.pei_boot_mode;
ret = copy_spd(&pei_data);
if (!ret)

View File

@ -7,6 +7,8 @@
#include <common.h>
#include <errno.h>
#include <fdtdec.h>
#include <malloc.h>
#include <asm/mrccache.h>
#include <asm/mtrr.h>
#include <asm/post.h>
#include <asm/arch/mrc.h>
@ -15,6 +17,29 @@
DECLARE_GLOBAL_DATA_PTR;
static __maybe_unused int prepare_mrc_cache(struct mrc_params *mrc_params)
{
struct mrc_data_container *cache;
struct mrc_region entry;
int ret;
ret = mrccache_get_region(NULL, &entry);
if (ret)
return ret;
cache = mrccache_find_current(&entry);
if (!cache)
return -ENOENT;
debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__,
cache->data, cache->data_size, cache->checksum);
/* copy mrc cache to the mrc_params */
memcpy(&mrc_params->timings, cache->data, cache->data_size);
return 0;
}
static int mrc_configure_params(struct mrc_params *mrc_params)
{
const void *blob = gd->fdt_blob;
@ -27,14 +52,15 @@ static int mrc_configure_params(struct mrc_params *mrc_params)
return -EINVAL;
}
/*
* TODO:
*
* We need support fast boot (MRC cache) in the future.
*
* Set boot mode to cold boot for now
*/
#ifdef CONFIG_ENABLE_MRC_CACHE
mrc_params->boot_mode = prepare_mrc_cache(mrc_params);
if (mrc_params->boot_mode)
mrc_params->boot_mode = BM_COLD;
else
mrc_params->boot_mode = BM_FAST;
#else
mrc_params->boot_mode = BM_COLD;
#endif
/*
* TODO:
@ -98,6 +124,9 @@ static int mrc_configure_params(struct mrc_params *mrc_params)
int dram_init(void)
{
struct mrc_params mrc_params;
#ifdef CONFIG_ENABLE_MRC_CACHE
char *cache;
#endif
int ret;
memset(&mrc_params, 0, sizeof(struct mrc_params));
@ -121,6 +150,15 @@ int dram_init(void)
(~(gd->ram_size - 1)) | MTRR_PHYS_MASK_VALID);
enable_caches();
#ifdef CONFIG_ENABLE_MRC_CACHE
cache = malloc(sizeof(struct mrc_timings));
if (cache) {
memcpy(cache, &mrc_params.timings, sizeof(struct mrc_timings));
gd->arch.mrc_output = cache;
gd->arch.mrc_output_len = sizeof(struct mrc_timings);
}
#endif
return 0;
}

View File

@ -8,6 +8,7 @@
#include <mmc.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mrccache.h>
#include <asm/mtrr.h>
#include <asm/pci.h>
#include <asm/post.h>
@ -368,6 +369,15 @@ void cpu_irq_init(void)
int arch_misc_init(void)
{
#ifdef CONFIG_ENABLE_MRC_CACHE
/*
* We intend not to check any return value here, as even MRC cache
* is not saved successfully, it is not a severe error that will
* prevent system from continuing to boot.
*/
mrccache_save();
#endif
return pirq_init();
}
@ -390,3 +400,12 @@ void board_final_cleanup(void)
return;
}
int reserve_arch(void)
{
#ifdef CONFIG_ENABLE_MRC_CACHE
return mrccache_reserve();
#else
return 0;
#endif
}

View File

@ -42,4 +42,12 @@ config CPU_ADDR_BITS
int
default 32
config DISABLE_IGD
bool "Disable Integrated Graphics Device (IGD)"
help
Disable the Integrated Graphics Device (IGD) so that it does not
show in the PCI configuration space as a VGA disaplay controller.
This gives a chance for U-Boot to run PCI/PCIe based graphics
card's VGA BIOS and use that card for the graphics console.
endif

View File

@ -23,6 +23,16 @@ static void unprotect_spi_flash(void)
x86_pci_write_config32(TNC_LPC, 0xd8, bc);
}
static void __maybe_unused disable_igd(void)
{
u32 gc;
gc = x86_pci_read_config32(TNC_IGD, IGD_GC);
gc &= ~GMS_MASK;
gc |= VGA_DISABLE;
x86_pci_write_config32(TNC_IGD, IGD_GC, gc);
}
int arch_cpu_init(void)
{
int ret;
@ -39,6 +49,15 @@ int arch_cpu_init(void)
return 0;
}
int arch_early_init_r(void)
{
#ifdef CONFIG_DISABLE_IGD
disable_igd();
#endif
return 0;
}
void cpu_irq_init(void)
{
struct tnc_rcba *rcba;

View File

@ -190,8 +190,8 @@ load_msr:
/* c_handler(cpu_num) */
movl %esi, %eax /* cpu_num */
mov c_handler, %eax
call *%eax
mov c_handler, %esi
call *%esi
.align 4
.globl sipi_params

View File

@ -126,14 +126,9 @@ car_init_ret:
call board_init_f_mem
mov %eax, %esp
/*
* Debug UART is available here although it may not be plumbed out
* to pins depending on the board. To use it:
*
* call debug_uart_init
* mov $'a', %eax
* call printch
*/
#ifdef CONFIG_DEBUG_UART
call debug_uart_init
#endif
/* Get address of global_data */
mov %fs:0, %edx

View File

@ -6,7 +6,8 @@ dtb-y += bayleybay.dtb \
galileo.dtb \
minnowmax.dtb \
qemu-x86_i440fx.dtb \
qemu-x86_q35.dtb
qemu-x86_q35.dtb \
broadwell_som-6896.dtb
targets += $(dtb-y)

View File

@ -68,9 +68,15 @@
#size-cells = <0>;
compatible = "intel,ich-spi";
spi-flash@0 {
#address-cells = <1>;
#size-cells = <1>;
reg = <0>;
compatible = "winbond,w25q64dw", "spi-flash";
memory-map = <0xff800000 0x00800000>;
rw-mrc-cache {
label = "rw-mrc-cache";
reg = <0x006e0000 0x00010000>;
};
};
};

View File

@ -0,0 +1,43 @@
/dts-v1/;
/include/ "skeleton.dtsi"
/include/ "serial.dtsi"
/include/ "rtc.dtsi"
/ {
model = "Advantech SOM-6896";
compatible = "advantech,som-6896", "intel,broadwell";
aliases {
spi0 = "/spi";
};
config {
silent_console = <0>;
};
chosen {
stdout-path = "/serial";
};
pci {
compatible = "pci-x86";
#address-cells = <3>;
#size-cells = <2>;
u-boot,dm-pre-reloc;
ranges = <0x02000000 0x0 0xe0000000 0xe0000000 0 0x10000000
0x42000000 0x0 0xd0000000 0xd0000000 0 0x10000000
0x01000000 0x0 0x2000 0x2000 0 0xe000>;
};
spi {
#address-cells = <1>;
#size-cells = <0>;
compatible = "intel,ich-spi";
spi-flash@0 {
reg = <0>;
compatible = "winbond,w25q128", "spi-flash";
memory-map = <0xff000000 0x01000000>;
};
};
};

View File

@ -208,8 +208,6 @@
rw-mrc-cache {
label = "rw-mrc-cache";
reg = <0x003e0000 0x00010000>;
type = "wiped";
wipe-value = [ff];
};
};
};

View File

@ -64,10 +64,7 @@
memory-map = <0xff800000 0x00800000>;
rw-mrc-cache {
label = "rw-mrc-cache";
/* Alignment: 4k (for updating) */
reg = <0x003e0000 0x00010000>;
type = "wiped";
wipe-value = [ff];
};
};
};

View File

@ -132,6 +132,10 @@
reg = <0>;
compatible = "winbond,w25q64", "spi-flash";
memory-map = <0xff800000 0x00800000>;
rw-mrc-cache {
label = "rw-mrc-cache";
reg = <0x00010000 0x00010000>;
};
};
};

View File

@ -273,9 +273,15 @@
#size-cells = <0>;
compatible = "intel,ich-spi";
spi-flash@0 {
#address-cells = <1>;
#size-cells = <1>;
reg = <0>;
compatible = "stmicro,n25q064a", "spi-flash";
memory-map = <0xff800000 0x00800000>;
rw-mrc-cache {
label = "rw-mrc-cache";
reg = <0x006f0000 0x00010000>;
};
};
};

View File

@ -1,51 +0,0 @@
/*
* Copyright (c) 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _ASM_ARCH_MRCCACHE_H
#define _ASM_ARCH_MRCCACHE_H
#define MRC_DATA_ALIGN 0x1000
#define MRC_DATA_SIGNATURE (('M' << 0) | ('R' << 8) | ('C' << 16) | \
('D'<<24))
__packed struct mrc_data_container {
u32 signature; /* "MRCD" */
u32 data_size; /* Size of the 'data' field */
u32 checksum; /* IP style checksum */
u32 reserved; /* For header alignment */
u8 data[0]; /* Variable size, platform/run time dependent */
};
struct fmap_entry;
struct udevice;
/**
* mrccache_find_current() - find the latest MRC cache record
*
* This searches the MRC cache region looking for the latest record to use
* for setting up SDRAM
*
* @entry: Information about the position and size of the MRC cache
* @return pointer to latest record, or NULL if none
*/
struct mrc_data_container *mrccache_find_current(struct fmap_entry *entry);
/**
* mrccache_update() - update the MRC cache with a new record
*
* This writes a new record to the end of the MRC cache. If the new record is
* the same as the latest record then the write is skipped
*
* @sf: SPI flash to write to
* @entry: Position and size of MRC cache in SPI flash
* @cur: Record to write
* @return 0 if updated, -EEXIST if the record is the same as the latest
* record, other error if SPI write failed
*/
int mrccache_update(struct udevice *sf, struct fmap_entry *entry,
struct mrc_data_container *cur);
#endif

View File

@ -7,6 +7,11 @@
#ifndef _X86_ARCH_TNC_H_
#define _X86_ARCH_TNC_H_
/* IGD Control Register */
#define IGD_GC 0x50
#define VGA_DISABLE 0x00020000
#define GMS_MASK 0x00700000
/* Memory BAR Enable */
#define MEM_BAR_EN 0x00000001

View File

@ -23,4 +23,7 @@ struct e820entry {
#endif /* __ASSEMBLY__ */
/* Implementation defined function to install an e820 map */
unsigned install_e820_map(unsigned max_entries, struct e820entry *);
#endif /* _ASM_X86_E820_H */

View File

@ -0,0 +1,107 @@
/*
* Copyright (C) 2014 Google, Inc
* Copyright (C) 2015 Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _ASM_MRCCACHE_H
#define _ASM_MRCCACHE_H
#define MRC_DATA_ALIGN 0x1000
#define MRC_DATA_SIGNATURE (('M' << 0) | ('R' << 8) | \
('C' << 16) | ('D'<<24))
#define MRC_DATA_HEADER_SIZE 32
struct __packed mrc_data_container {
u32 signature; /* "MRCD" */
u32 data_size; /* Size of the 'data' field */
u32 checksum; /* IP style checksum */
u32 reserved; /* For header alignment */
u8 data[0]; /* Variable size, platform/run time dependent */
};
struct mrc_region {
u32 base;
u32 offset;
u32 length;
};
struct udevice;
/**
* mrccache_find_current() - find the latest MRC cache record
*
* This searches the MRC cache region looking for the latest record to use
* for setting up SDRAM
*
* @entry: Position and size of MRC cache in SPI flash
* @return pointer to latest record, or NULL if none
*/
struct mrc_data_container *mrccache_find_current(struct mrc_region *entry);
/**
* mrccache_update() - update the MRC cache with a new record
*
* This writes a new record to the end of the MRC cache region. If the new
* record is the same as the latest record then the write is skipped
*
* @sf: SPI flash to write to
* @entry: Position and size of MRC cache in SPI flash
* @cur: Record to write
* @return 0 if updated, -EEXIST if the record is the same as the latest
* record, -EINVAL if the record is not valid, other error if SPI write failed
*/
int mrccache_update(struct udevice *sf, struct mrc_region *entry,
struct mrc_data_container *cur);
/**
* mrccache_reserve() - reserve MRC data on the stack
*
* This copies MRC data pointed by gd->arch.mrc_output to a new place on the
* stack with length gd->arch.mrc_output_len, and updates gd->arch.mrc_output
* to point to the new place once the migration is done.
*
* This routine should be called by reserve_arch() before U-Boot is relocated
* when MRC cache is enabled.
*
* @return 0 always
*/
int mrccache_reserve(void);
/**
* mrccache_get_region() - get MRC region on the SPI flash
*
* This gets MRC region whose offset and size are described in the device tree
* as a subnode to the SPI flash. If a non-NULL device pointer is supplied,
* this also probes the SPI flash device and returns its device pointer for
* the caller to use later.
*
* Be careful when calling this routine with a non-NULL device pointer:
* - driver model initialization must be complete
* - calling in the pre-relocation phase may bring some side effects during
* the SPI flash device probe (eg: for SPI controllers on a PCI bus, it
* triggers PCI bus enumeration during which insufficient memory issue
* might be exposed and it causes subsequent SPI flash probe fails).
*
* @devp: Returns pointer to the SPI flash device
* @entry: Position and size of MRC cache in SPI flash
* @return 0 if success, -ENOENT if SPI flash node does not exist in the
* device tree, -EPERM if MRC region subnode does not exist in the device
* tree, -EINVAL if MRC region properties format is incorrect, other error
* if SPI flash probe failed.
*/
int mrccache_get_region(struct udevice **devp, struct mrc_region *entry);
/**
* mrccache_save() - save MRC data to the SPI flash
*
* This saves MRC data stored previously by gd->arch.mrc_output to a proper
* place within the MRC region on the SPI flash.
*
* @return 0 if saved to SPI flash successfully, other error if failed
*/
int mrccache_save(void);
#endif /* _ASM_MRCCACHE_H */

View File

@ -0,0 +1,236 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* Adapted from coreboot src/include/smbios.h
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _SMBIOS_H_
#define _SMBIOS_H_
/* SMBIOS spec version implemented */
#define SMBIOS_MAJOR_VER 3
#define SMBIOS_MINOR_VER 0
/* SMBIOS structure types */
enum {
SMBIOS_BIOS_INFORMATION = 0,
SMBIOS_SYSTEM_INFORMATION = 1,
SMBIOS_BOARD_INFORMATION = 2,
SMBIOS_SYSTEM_ENCLOSURE = 3,
SMBIOS_PROCESSOR_INFORMATION = 4,
SMBIOS_CACHE_INFORMATION = 7,
SMBIOS_SYSTEM_SLOTS = 9,
SMBIOS_PHYS_MEMORY_ARRAY = 16,
SMBIOS_MEMORY_DEVICE = 17,
SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS = 19,
SMBIOS_SYSTEM_BOOT_INFORMATION = 32,
SMBIOS_END_OF_TABLE = 127
};
#define SMBIOS_INTERMEDIATE_OFFSET 16
#define SMBIOS_STRUCT_EOS_BYTES 2
struct __packed smbios_entry {
u8 anchor[4];
u8 checksum;
u8 length;
u8 major_ver;
u8 minor_ver;
u16 max_struct_size;
u8 entry_point_rev;
u8 formatted_area[5];
u8 intermediate_anchor[5];
u8 intermediate_checksum;
u16 struct_table_length;
u32 struct_table_address;
u16 struct_count;
u8 bcd_rev;
};
/* BIOS characteristics */
#define BIOS_CHARACTERISTICS_PCI_SUPPORTED (1 << 7)
#define BIOS_CHARACTERISTICS_UPGRADEABLE (1 << 11)
#define BIOS_CHARACTERISTICS_SELECTABLE_BOOT (1 << 16)
#define BIOS_CHARACTERISTICS_EXT1_ACPI (1 << 0)
#define BIOS_CHARACTERISTICS_EXT2_TARGET (1 << 2)
struct __packed smbios_type0 {
u8 type;
u8 length;
u16 handle;
u8 vendor;
u8 bios_ver;
u16 bios_start_segment;
u8 bios_release_date;
u8 bios_rom_size;
u64 bios_characteristics;
u8 bios_characteristics_ext1;
u8 bios_characteristics_ext2;
u8 bios_major_release;
u8 bios_minor_release;
u8 ec_major_release;
u8 ec_minor_release;
char eos[SMBIOS_STRUCT_EOS_BYTES];
};
struct __packed smbios_type1 {
u8 type;
u8 length;
u16 handle;
u8 manufacturer;
u8 product_name;
u8 version;
u8 serial_number;
u8 uuid[16];
u8 wakeup_type;
u8 sku_number;
u8 family;
char eos[SMBIOS_STRUCT_EOS_BYTES];
};
#define SMBIOS_BOARD_FEATURE_HOSTING (1 << 0)
#define SMBIOS_BOARD_MOTHERBOARD 10
struct __packed smbios_type2 {
u8 type;
u8 length;
u16 handle;
u8 manufacturer;
u8 product_name;
u8 version;
u8 serial_number;
u8 asset_tag_number;
u8 feature_flags;
u8 chassis_location;
u16 chassis_handle;
u8 board_type;
char eos[SMBIOS_STRUCT_EOS_BYTES];
};
#define SMBIOS_ENCLOSURE_DESKTOP 3
#define SMBIOS_STATE_SAFE 3
#define SMBIOS_SECURITY_NONE 3
struct __packed smbios_type3 {
u8 type;
u8 length;
u16 handle;
u8 manufacturer;
u8 chassis_type;
u8 version;
u8 serial_number;
u8 asset_tag_number;
u8 bootup_state;
u8 power_supply_state;
u8 thermal_state;
u8 security_status;
u32 oem_defined;
u8 height;
u8 number_of_power_cords;
u8 element_count;
u8 element_record_length;
char eos[SMBIOS_STRUCT_EOS_BYTES];
};
#define SMBIOS_PROCESSOR_TYPE_CENTRAL 3
#define SMBIOS_PROCESSOR_STATUS_ENABLED 1
#define SMBIOS_PROCESSOR_UPGRADE_NONE 6
struct __packed smbios_type4 {
u8 type;
u8 length;
u16 handle;
u8 socket_designation;
u8 processor_type;
u8 processor_family;
u8 processor_manufacturer;
u32 processor_id[2];
u8 processor_version;
u8 voltage;
u16 external_clock;
u16 max_speed;
u16 current_speed;
u8 status;
u8 processor_upgrade;
u16 l1_cache_handle;
u16 l2_cache_handle;
u16 l3_cache_handle;
u8 serial_number;
u8 asset_tag;
u8 part_number;
u8 core_count;
u8 core_enabled;
u8 thread_count;
u16 processor_characteristics;
u16 processor_family2;
u16 core_count2;
u16 core_enabled2;
u16 thread_count2;
char eos[SMBIOS_STRUCT_EOS_BYTES];
};
struct __packed smbios_type32 {
u8 type;
u8 length;
u16 handle;
u8 reserved[6];
u8 boot_status;
u8 eos[SMBIOS_STRUCT_EOS_BYTES];
};
struct __packed smbios_type127 {
u8 type;
u8 length;
u16 handle;
u8 eos[SMBIOS_STRUCT_EOS_BYTES];
};
struct __packed smbios_header {
u8 type;
u8 length;
u16 handle;
};
/**
* fill_smbios_header() - Fill the header of an SMBIOS table
*
* This fills the header of an SMBIOS table structure.
*
* @table: start address of the structure
* @type: the type of structure
* @length: the length of the formatted area of the structure
* @handle: the structure's handle, a unique 16-bit number
*/
static inline void fill_smbios_header(void *table, int type,
int length, int handle)
{
struct smbios_header *header = table;
header->type = type;
header->length = length - SMBIOS_STRUCT_EOS_BYTES;
header->handle = handle;
}
/**
* Function prototype to write a specific type of SMBIOS structure
*
* @addr: start address to write the structure
* @handle: the structure's handle, a unique 16-bit number
* @return: size of the structure
*/
typedef int (*smbios_write_type)(u32 *addr, int handle);
/**
* write_smbios_table() - Write SMBIOS table
*
* This writes SMBIOS table at a given address.
*
* @addr: start address to write SMBIOS table
* @return: end address of SMBIOS table
*/
u32 write_smbios_table(u32 addr);
#endif /* _SMBIOS_H_ */

View File

@ -31,9 +31,6 @@
#define BZIMAGE_LOAD_ADDR 0x100000
#define ZIMAGE_LOAD_ADDR 0x10000
/* Implementation defined function to install an e820 map. */
unsigned install_e820_map(unsigned max_entries, struct e820entry *);
struct boot_params *load_zimage(char *image, unsigned long kernel_size,
ulong *load_addressp);
int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,

View File

@ -10,13 +10,14 @@ obj-y += bios_asm.o
obj-y += bios_interrupts.o
obj-$(CONFIG_CMD_BOOTM) += bootm.o
obj-y += cmd_boot.o
obj-$(CONFIG_HAVE_FSP) += cmd_hob.o
obj-$(CONFIG_EFI) += efi/
obj-y += e820.o
obj-y += gcc.o
obj-y += init_helpers.o
obj-y += interrupts.o
obj-y += lpc-uclass.o
obj-y += mpspec.o
obj-$(CONFIG_ENABLE_MRC_CACHE) += mrccache.o
obj-y += cmd_mtrr.o
obj-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o
obj-$(CONFIG_SYS_PCAT_TIMER) += pcat_timer.o
@ -29,6 +30,7 @@ obj-y += relocate.o
obj-y += physmem.o
obj-$(CONFIG_X86_RAMTEST) += ramtest.o
obj-y += sfi.o
obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
obj-y += string.o
obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi_table.o
obj-y += tables.o

View File

@ -1,65 +0,0 @@
/*
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <command.h>
#include <linux/compiler.h>
#include <asm/fsp/fsp_support.h>
DECLARE_GLOBAL_DATA_PTR;
static char *hob_type[] = {
"reserved",
"Hand-off",
"Memory Allocation",
"Resource Descriptor",
"GUID Extension",
"Firmware Volume",
"CPU",
"Memory Pool",
"reserved",
"Firmware Volume 2",
"Load PEIM Unused",
"UEFI Capsule",
};
int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
const struct hob_header *hdr;
uint type;
char *desc;
int i = 0;
hdr = gd->arch.hob_list;
printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr);
printf("No. | Address | Type | Length in Bytes\n");
printf("----|----------|---------------------|----------------\n");
while (!end_of_hob(hdr)) {
printf("%-3d | %08x | ", i, (unsigned int)hdr);
type = hdr->type;
if (type == HOB_TYPE_UNUSED)
desc = "*Unused*";
else if (type == HOB_TYPE_EOH)
desc = "*END OF HOB*";
else if (type >= 0 && type <= ARRAY_SIZE(hob_type))
desc = hob_type[type];
else
desc = "*Invalid Type*";
printf("%-19s | %-15d\n", desc, hdr->len);
hdr = get_next_hob(hdr);
i++;
}
return 0;
}
U_BOOT_CMD(
hob, 1, 1, do_hob,
"print Firmware Support Package (FSP) Hand-Off Block information",
""
);

37
arch/x86/lib/e820.c Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/e820.h>
DECLARE_GLOBAL_DATA_PTR;
/*
* Install a default e820 table with 4 entries as follows:
*
* 0x000000-0x0a0000 Useable RAM
* 0x0a0000-0x100000 Reserved for ISA
* 0x100000-gd->ram_size Useable RAM
* CONFIG_PCIE_ECAM_BASE PCIe ECAM
*/
__weak unsigned install_e820_map(unsigned max_entries,
struct e820entry *entries)
{
entries[0].addr = 0;
entries[0].size = ISA_START_ADDRESS;
entries[0].type = E820_RAM;
entries[1].addr = ISA_START_ADDRESS;
entries[1].size = ISA_END_ADDRESS - ISA_START_ADDRESS;
entries[1].type = E820_RESERVED;
entries[2].addr = ISA_END_ADDRESS;
entries[2].size = gd->ram_size - ISA_END_ADDRESS;
entries[2].type = E820_RAM;
entries[3].addr = CONFIG_PCIE_ECAM_BASE;
entries[3].size = CONFIG_PCIE_ECAM_SIZE;
entries[3].type = E820_RESERVED;
return 4;
}

View File

@ -4,6 +4,7 @@
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += cmd_fsp.o
obj-y += fsp_car.o
obj-y += fsp_common.o
obj-y += fsp_dram.o

132
arch/x86/lib/fsp/cmd_fsp.c Normal file
View File

@ -0,0 +1,132 @@
/*
* Copyright (C) 2014-2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <command.h>
#include <asm/fsp/fsp_support.h>
DECLARE_GLOBAL_DATA_PTR;
static char *hob_type[] = {
"reserved",
"Hand-off",
"Mem Alloc",
"Res Desc",
"GUID Ext",
"FV",
"CPU",
"Mem Pool",
"reserved",
"FV2",
"Load PEIM",
"Capsule",
};
static int do_hdr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
struct fsp_header *hdr = find_fsp_header();
u32 img_addr = hdr->img_base;
char *sign = (char *)&hdr->sign;
int i;
printf("FSP : binary 0x%08x, header 0x%08x\n",
CONFIG_FSP_ADDR, (int)hdr);
printf("Header : sign ");
for (i = 0; i < sizeof(hdr->sign); i++)
printf("%c", *sign++);
printf(", size %d, rev %d\n", hdr->hdr_len, hdr->hdr_rev);
printf("Image : rev %d.%d, id ",
(hdr->img_rev >> 8) & 0xff, hdr->img_rev & 0xff);
for (i = 0; i < ARRAY_SIZE(hdr->img_id); i++)
printf("%c", hdr->img_id[i]);
printf(", addr 0x%08x, size %d\n", img_addr, hdr->img_size);
printf("VPD : addr 0x%08x, size %d\n",
hdr->cfg_region_off + img_addr, hdr->cfg_region_size);
printf("\nNumber of APIs Supported : %d\n", hdr->api_num);
printf("\tTempRamInit : 0x%08x\n", hdr->fsp_tempram_init + img_addr);
printf("\tFspInit : 0x%08x\n", hdr->fsp_init + img_addr);
printf("\tFspNotify : 0x%08x\n", hdr->fsp_notify + img_addr);
return 0;
}
static int do_hob(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
const struct hob_header *hdr;
uint type;
char *desc;
int i = 0;
hdr = gd->arch.hob_list;
printf("HOB list address: 0x%08x\n\n", (unsigned int)hdr);
printf("# | Address | Type | Len | ");
printf("%42s\n", "GUID");
printf("---|----------|-----------|------|-");
printf("------------------------------------------\n");
while (!end_of_hob(hdr)) {
printf("%-2d | %08x | ", i, (unsigned int)hdr);
type = hdr->type;
if (type == HOB_TYPE_UNUSED)
desc = "*Unused*";
else if (type == HOB_TYPE_EOH)
desc = "*EOH*";
else if (type >= 0 && type <= ARRAY_SIZE(hob_type))
desc = hob_type[type];
else
desc = "*Invalid*";
printf("%-9s | %-4d | ", desc, hdr->len);
if (type == HOB_TYPE_MEM_ALLOC || type == HOB_TYPE_RES_DESC ||
type == HOB_TYPE_GUID_EXT) {
struct efi_guid *guid = (struct efi_guid *)(hdr + 1);
int j;
printf("%08x-%04x-%04x", guid->data1,
guid->data2, guid->data3);
for (j = 0; j < ARRAY_SIZE(guid->data4); j++)
printf("-%02x", guid->data4[j]);
} else {
printf("%42s", "Not Available");
}
printf("\n");
hdr = get_next_hob(hdr);
i++;
}
return 0;
}
static cmd_tbl_t fsp_commands[] = {
U_BOOT_CMD_MKENT(hdr, 0, 1, do_hdr, "", ""),
U_BOOT_CMD_MKENT(hob, 0, 1, do_hob, "", ""),
};
static int do_fsp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
cmd_tbl_t *fsp_cmd;
int ret;
if (argc < 2)
return CMD_RET_USAGE;
fsp_cmd = find_cmd_tbl(argv[1], fsp_commands, ARRAY_SIZE(fsp_commands));
argc -= 2;
argv += 2;
if (!fsp_cmd || argc > fsp_cmd->maxargs)
return CMD_RET_USAGE;
ret = fsp_cmd->cmd(fsp_cmd, flag, argc, argv);
return cmd_process_error(fsp_cmd, ret);
}
U_BOOT_CMD(
fsp, 2, 1, do_fsp,
"Show Intel Firmware Support Package (FSP) related information",
"hdr - Print FSP header information\n"
"fsp hob - Print FSP Hand-Off Block (HOB) information"
);

View File

@ -7,6 +7,7 @@
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <asm/mrccache.h>
#include <asm/post.h>
#include <asm/processor.h>
#include <asm/fsp/fsp_support.h>
@ -54,15 +55,42 @@ void board_final_cleanup(void)
return;
}
static __maybe_unused void *fsp_prepare_mrc_cache(void)
{
struct mrc_data_container *cache;
struct mrc_region entry;
int ret;
ret = mrccache_get_region(NULL, &entry);
if (ret)
return NULL;
cache = mrccache_find_current(&entry);
if (!cache)
return NULL;
debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__,
cache->data, cache->data_size, cache->checksum);
return cache->data;
}
int x86_fsp_init(void)
{
void *nvs;
if (!gd->arch.hob_list) {
#ifdef CONFIG_ENABLE_MRC_CACHE
nvs = fsp_prepare_mrc_cache();
#else
nvs = NULL;
#endif
/*
* The first time we enter here, call fsp_init().
* Note the execution does not return to this function,
* instead it jumps to fsp_continue().
*/
fsp_init(CONFIG_FSP_TEMP_RAM_ADDR, BOOT_FULL_CONFIG, NULL);
fsp_init(CONFIG_FSP_TEMP_RAM_ADDR, BOOT_FULL_CONFIG, nvs);
} else {
/*
* The second time we enter here, adjust the size of malloc()

View File

@ -7,6 +7,7 @@
#include <common.h>
#include <asm/fsp/fsp_support.h>
#include <asm/e820.h>
#include <asm/mrccache.h>
#include <asm/post.h>
DECLARE_GLOBAL_DATA_PTR;
@ -32,6 +33,11 @@ int dram_init(void)
gd->ram_size = ram_size;
post_code(POST_DRAM);
#ifdef CONFIG_ENABLE_MRC_CACHE
gd->arch.mrc_output = fsp_get_nvs_data(gd->arch.hob_list,
&gd->arch.mrc_output_len);
#endif
return 0;
}

View File

@ -1,32 +1,37 @@
/*
* From Coreboot src/southbridge/intel/bd82x6x/mrccache.c
* From coreboot src/southbridge/intel/bd82x6x/mrccache.c
*
* Copyright (C) 2014 Google Inc.
* Copyright (C) 2015 Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <net.h>
#include <spi.h>
#include <spi_flash.h>
#include <asm/arch/mrccache.h>
#include <asm/arch/sandybridge.h>
#include <asm/mrccache.h>
DECLARE_GLOBAL_DATA_PTR;
static struct mrc_data_container *next_mrc_block(
struct mrc_data_container *mrc_cache)
struct mrc_data_container *cache)
{
/* MRC data blocks are aligned within the region */
u32 mrc_size = sizeof(*mrc_cache) + mrc_cache->data_size;
u32 mrc_size = sizeof(*cache) + cache->data_size;
u8 *region_ptr = (u8 *)cache;
if (mrc_size & (MRC_DATA_ALIGN - 1UL)) {
mrc_size &= ~(MRC_DATA_ALIGN - 1UL);
mrc_size += MRC_DATA_ALIGN;
}
u8 *region_ptr = (u8 *)mrc_cache;
region_ptr += mrc_size;
return (struct mrc_data_container *)region_ptr;
}
@ -35,17 +40,13 @@ static int is_mrc_cache(struct mrc_data_container *cache)
return cache && (cache->signature == MRC_DATA_SIGNATURE);
}
/*
* Find the largest index block in the MRC cache. Return NULL if none is
* found.
*/
struct mrc_data_container *mrccache_find_current(struct fmap_entry *entry)
struct mrc_data_container *mrccache_find_current(struct mrc_region *entry)
{
struct mrc_data_container *cache, *next;
ulong base_addr, end_addr;
uint id;
base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
base_addr = entry->base + entry->offset;
end_addr = base_addr + entry->length;
cache = NULL;
@ -84,12 +85,12 @@ struct mrc_data_container *mrccache_find_current(struct fmap_entry *entry)
*
* @return next cache entry if found, NULL if we got to the end
*/
static struct mrc_data_container *find_next_mrc_cache(struct fmap_entry *entry,
static struct mrc_data_container *find_next_mrc_cache(struct mrc_region *entry,
struct mrc_data_container *cache)
{
ulong base_addr, end_addr;
base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
base_addr = entry->base + entry->offset;
end_addr = base_addr + entry->length;
cache = next_mrc_block(cache);
@ -105,7 +106,7 @@ static struct mrc_data_container *find_next_mrc_cache(struct fmap_entry *entry,
return cache;
}
int mrccache_update(struct udevice *sf, struct fmap_entry *entry,
int mrccache_update(struct udevice *sf, struct mrc_region *entry,
struct mrc_data_container *cur)
{
struct mrc_data_container *cache;
@ -113,8 +114,11 @@ int mrccache_update(struct udevice *sf, struct fmap_entry *entry,
ulong base_addr;
int ret;
if (!is_mrc_cache(cur))
return -EINVAL;
/* Find the last used block */
base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
base_addr = entry->base + entry->offset;
debug("Updating MRC cache data\n");
cache = mrccache_find_current(entry);
if (cache && (cache->data_size == cur->data_size) &&
@ -155,3 +159,95 @@ int mrccache_update(struct udevice *sf, struct fmap_entry *entry,
return 0;
}
int mrccache_reserve(void)
{
struct mrc_data_container *cache;
u16 checksum;
if (!gd->arch.mrc_output_len)
return 0;
/* adjust stack pointer to store pure cache data plus the header */
gd->start_addr_sp -= (gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE);
cache = (struct mrc_data_container *)gd->start_addr_sp;
cache->signature = MRC_DATA_SIGNATURE;
cache->data_size = gd->arch.mrc_output_len;
checksum = compute_ip_checksum(gd->arch.mrc_output, cache->data_size);
debug("Saving %d bytes for MRC output data, checksum %04x\n",
cache->data_size, checksum);
cache->checksum = checksum;
cache->reserved = 0;
memcpy(cache->data, gd->arch.mrc_output, cache->data_size);
/* gd->arch.mrc_output now points to the container */
gd->arch.mrc_output = (char *)cache;
gd->start_addr_sp &= ~0xf;
return 0;
}
int mrccache_get_region(struct udevice **devp, struct mrc_region *entry)
{
const void *blob = gd->fdt_blob;
int node, mrc_node;
u32 reg[2];
int ret;
/* Find the flash chip within the SPI controller node */
node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
if (node < 0)
return -ENOENT;
if (fdtdec_get_int_array(blob, node, "memory-map", reg, 2))
return -FDT_ERR_NOTFOUND;
entry->base = reg[0];
/* Find the place where we put the MRC cache */
mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache");
if (mrc_node < 0)
return -EPERM;
if (fdtdec_get_int_array(blob, mrc_node, "reg", reg, 2))
return -FDT_ERR_NOTFOUND;
entry->offset = reg[0];
entry->length = reg[1];
if (devp) {
ret = uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node,
devp);
debug("ret = %d\n", ret);
if (ret)
return ret;
}
return 0;
}
int mrccache_save(void)
{
struct mrc_data_container *data;
struct mrc_region entry;
struct udevice *sf;
int ret;
if (!gd->arch.mrc_output_len)
return 0;
debug("Saving %d bytes of MRC output data to SPI flash\n",
gd->arch.mrc_output_len);
ret = mrccache_get_region(&sf, &entry);
if (ret)
goto err_entry;
data = (struct mrc_data_container *)gd->arch.mrc_output;
ret = mrccache_update(sf, &entry, data);
if (!ret)
debug("Saved MRC data with checksum %04x\n", data->checksum);
err_entry:
if (ret)
debug("%s: Failed: %d\n", __func__, ret);
return ret;
}

269
arch/x86/lib/smbios.c Normal file
View File

@ -0,0 +1,269 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* Adapted from coreboot src/arch/x86/smbios.c
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <version.h>
#include <asm/cpu.h>
#include <asm/smbios.h>
#include <asm/tables.h>
DECLARE_GLOBAL_DATA_PTR;
/**
* smbios_add_string() - add a string to the string area
*
* This adds a string to the string area which is appended directly after
* the formatted portion of an SMBIOS structure.
*
* @start: string area start address
* @str: string to add
* @return: string number in the string area
*/
static int smbios_add_string(char *start, const char *str)
{
int i = 1;
char *p = start;
for (;;) {
if (!*p) {
strcpy(p, str);
p += strlen(str);
*p++ = '\0';
*p++ = '\0';
return i;
}
if (!strcmp(p, str))
return i;
p += strlen(p) + 1;
i++;
}
}
/**
* smbios_string_table_len() - compute the string area size
*
* This computes the size of the string area including the string terminator.
*
* @start: string area start address
* @return: string area size
*/
static int smbios_string_table_len(char *start)
{
char *p = start;
int i, len = 0;
while (*p) {
i = strlen(p) + 1;
p += i;
len += i;
}
return len + 1;
}
static int smbios_write_type0(u32 *current, int handle)
{
struct smbios_type0 *t = (struct smbios_type0 *)*current;
int len = sizeof(struct smbios_type0);
memset(t, 0, sizeof(struct smbios_type0));
fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle);
t->vendor = smbios_add_string(t->eos, "U-Boot");
t->bios_ver = smbios_add_string(t->eos, PLAIN_VERSION);
t->bios_release_date = smbios_add_string(t->eos, U_BOOT_DMI_DATE);
t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1;
t->bios_characteristics = BIOS_CHARACTERISTICS_PCI_SUPPORTED |
BIOS_CHARACTERISTICS_SELECTABLE_BOOT |
BIOS_CHARACTERISTICS_UPGRADEABLE;
#ifdef CONFIG_GENERATE_ACPI_TABLE
t->bios_characteristics_ext1 = BIOS_CHARACTERISTICS_EXT1_ACPI;
#endif
t->bios_characteristics_ext2 = BIOS_CHARACTERISTICS_EXT2_TARGET;
t->bios_major_release = 0xff;
t->bios_minor_release = 0xff;
t->ec_major_release = 0xff;
t->ec_minor_release = 0xff;
len = t->length + smbios_string_table_len(t->eos);
*current += len;
return len;
}
static int smbios_write_type1(u32 *current, int handle)
{
struct smbios_type1 *t = (struct smbios_type1 *)*current;
int len = sizeof(struct smbios_type1);
memset(t, 0, sizeof(struct smbios_type1));
fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle);
t->manufacturer = smbios_add_string(t->eos, CONFIG_SYS_VENDOR);
t->product_name = smbios_add_string(t->eos, CONFIG_SYS_BOARD);
len = t->length + smbios_string_table_len(t->eos);
*current += len;
return len;
}
static int smbios_write_type2(u32 *current, int handle)
{
struct smbios_type2 *t = (struct smbios_type2 *)*current;
int len = sizeof(struct smbios_type2);
memset(t, 0, sizeof(struct smbios_type2));
fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle);
t->manufacturer = smbios_add_string(t->eos, CONFIG_SYS_VENDOR);
t->product_name = smbios_add_string(t->eos, CONFIG_SYS_BOARD);
t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING;
t->board_type = SMBIOS_BOARD_MOTHERBOARD;
len = t->length + smbios_string_table_len(t->eos);
*current += len;
return len;
}
static int smbios_write_type3(u32 *current, int handle)
{
struct smbios_type3 *t = (struct smbios_type3 *)*current;
int len = sizeof(struct smbios_type3);
memset(t, 0, sizeof(struct smbios_type3));
fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle);
t->manufacturer = smbios_add_string(t->eos, CONFIG_SYS_VENDOR);
t->chassis_type = SMBIOS_ENCLOSURE_DESKTOP;
t->bootup_state = SMBIOS_STATE_SAFE;
t->power_supply_state = SMBIOS_STATE_SAFE;
t->thermal_state = SMBIOS_STATE_SAFE;
t->security_status = SMBIOS_SECURITY_NONE;
len = t->length + smbios_string_table_len(t->eos);
*current += len;
return len;
}
static int smbios_write_type4(u32 *current, int handle)
{
struct smbios_type4 *t = (struct smbios_type4 *)*current;
int len = sizeof(struct smbios_type4);
const char *vendor;
char *name;
char processor_name[CPU_MAX_NAME_LEN];
struct cpuid_result res;
memset(t, 0, sizeof(struct smbios_type4));
fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle);
t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
t->processor_family = gd->arch.x86;
vendor = cpu_vendor_name(gd->arch.x86_vendor);
t->processor_manufacturer = smbios_add_string(t->eos, vendor);
res = cpuid(1);
t->processor_id[0] = res.eax;
t->processor_id[1] = res.edx;
name = cpu_get_name(processor_name);
t->processor_version = smbios_add_string(t->eos, name);
t->status = SMBIOS_PROCESSOR_STATUS_ENABLED;
t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE;
t->l1_cache_handle = 0xffff;
t->l2_cache_handle = 0xffff;
t->l3_cache_handle = 0xffff;
t->processor_family2 = t->processor_family;
len = t->length + smbios_string_table_len(t->eos);
*current += len;
return len;
}
static int smbios_write_type32(u32 *current, int handle)
{
struct smbios_type32 *t = (struct smbios_type32 *)*current;
int len = sizeof(struct smbios_type32);
memset(t, 0, sizeof(struct smbios_type32));
fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle);
*current += len;
return len;
}
static int smbios_write_type127(u32 *current, int handle)
{
struct smbios_type127 *t = (struct smbios_type127 *)*current;
int len = sizeof(struct smbios_type127);
memset(t, 0, sizeof(struct smbios_type127));
fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle);
*current += len;
return len;
}
static smbios_write_type smbios_write_funcs[] = {
smbios_write_type0,
smbios_write_type1,
smbios_write_type2,
smbios_write_type3,
smbios_write_type4,
smbios_write_type32,
smbios_write_type127
};
u32 write_smbios_table(u32 addr)
{
struct smbios_entry *se;
u32 tables;
int len = 0;
int max_struct_size = 0;
int handle = 0;
char *istart;
int isize;
int i;
/* 16 byte align the table address */
addr = ALIGN(addr, 16);
se = (struct smbios_entry *)addr;
memset(se, 0, sizeof(struct smbios_entry));
addr += sizeof(struct smbios_entry);
addr = ALIGN(addr, 16);
tables = addr;
/* populate minimum required tables */
for (i = 0; i < ARRAY_SIZE(smbios_write_funcs); i++) {
int tmp = smbios_write_funcs[i](&addr, handle++);
max_struct_size = max(max_struct_size, tmp);
len += tmp;
}
memcpy(se->anchor, "_SM_", 4);
se->length = sizeof(struct smbios_entry);
se->major_ver = SMBIOS_MAJOR_VER;
se->minor_ver = SMBIOS_MINOR_VER;
se->max_struct_size = max_struct_size;
memcpy(se->intermediate_anchor, "_DMI_", 5);
se->struct_table_length = len;
se->struct_table_address = tables;
se->struct_count = handle;
/* calculate checksums */
istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
se->intermediate_checksum = table_compute_checksum(istart, isize);
se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
return addr;
}

View File

@ -7,6 +7,7 @@
#include <common.h>
#include <asm/sfi.h>
#include <asm/mpspec.h>
#include <asm/smbios.h>
#include <asm/tables.h>
#include <asm/acpi_table.h>
@ -56,4 +57,8 @@ void write_tables(void)
rom_table_end = write_acpi_tables(rom_table_end);
rom_table_end = ALIGN(rom_table_end, 1024);
#endif
#ifdef CONFIG_GENERATE_SMBIOS_TABLE
rom_table_end = write_smbios_table(rom_table_end);
rom_table_end = ALIGN(rom_table_end, 1024);
#endif
}

View File

@ -42,32 +42,6 @@ DECLARE_GLOBAL_DATA_PTR;
#define COMMAND_LINE_SIZE 2048
/*
* Install a default e820 table with 3 entries as follows:
*
* 0x000000-0x0a0000 Useable RAM
* 0x0a0000-0x100000 Reserved for ISA
* 0x100000-gd->ram_size Useable RAM
*/
__weak unsigned install_e820_map(unsigned max_entries,
struct e820entry *entries)
{
entries[0].addr = 0;
entries[0].size = ISA_START_ADDRESS;
entries[0].type = E820_RAM;
entries[1].addr = ISA_START_ADDRESS;
entries[1].size = ISA_END_ADDRESS - ISA_START_ADDRESS;
entries[1].type = E820_RESERVED;
entries[2].addr = ISA_END_ADDRESS;
entries[2].size = gd->ram_size - ISA_END_ADDRESS;
entries[2].type = E820_RAM;
entries[3].addr = CONFIG_PCIE_ECAM_BASE;
entries[3].size = CONFIG_PCIE_ECAM_SIZE;
entries[3].type = E820_RESERVED;
return 4;
}
static void build_command_line(char *command_line, int auto_boot)
{
char *env_command_line;

View File

@ -148,6 +148,12 @@ config CMD_BOOTM
help
Boot an application image from the memory.
config CMD_ELF
bool "bootelf, bootvx"
default y
help
Boot an ELF/vxWorks image from the memory.
config CMD_GO
bool "go"
default y

View File

@ -14,23 +14,98 @@
*/
#include <common.h>
#include <bootm.h>
#include <command.h>
#include <linux/ctype.h>
#include <net.h>
#include <elf.h>
#include <net.h>
#include <vxworks.h>
#if defined(CONFIG_WALNUT) || defined(CONFIG_SYS_VXWORKS_MAC_PTR)
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_X86
#include <asm/e820.h>
#include <linux/linkage.h>
#endif
static unsigned long load_elf_image_phdr(unsigned long addr);
static unsigned long load_elf_image_shdr(unsigned long addr);
/*
* A very simple elf loader, assumes the image is valid, returns the
* entry point address.
*/
static unsigned long load_elf_image_phdr(unsigned long addr)
{
Elf32_Ehdr *ehdr; /* Elf header structure pointer */
Elf32_Phdr *phdr; /* Program header structure pointer */
int i;
ehdr = (Elf32_Ehdr *)addr;
phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff);
/* Load each program header */
for (i = 0; i < ehdr->e_phnum; ++i) {
void *dst = (void *)(uintptr_t)phdr->p_paddr;
void *src = (void *)addr + phdr->p_offset;
debug("Loading phdr %i to 0x%p (%i bytes)\n",
i, dst, phdr->p_filesz);
if (phdr->p_filesz)
memcpy(dst, src, phdr->p_filesz);
if (phdr->p_filesz != phdr->p_memsz)
memset(dst + phdr->p_filesz, 0x00,
phdr->p_memsz - phdr->p_filesz);
flush_cache((unsigned long)dst, phdr->p_filesz);
++phdr;
}
return ehdr->e_entry;
}
static unsigned long load_elf_image_shdr(unsigned long addr)
{
Elf32_Ehdr *ehdr; /* Elf header structure pointer */
Elf32_Shdr *shdr; /* Section header structure pointer */
unsigned char *strtab = 0; /* String table pointer */
unsigned char *image; /* Binary image pointer */
int i; /* Loop counter */
ehdr = (Elf32_Ehdr *)addr;
/* Find the section header string table for output info */
shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
(ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
if (shdr->sh_type == SHT_STRTAB)
strtab = (unsigned char *)(addr + shdr->sh_offset);
/* Load each appropriate section */
for (i = 0; i < ehdr->e_shnum; ++i) {
shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
(i * sizeof(Elf32_Shdr)));
if (!(shdr->sh_flags & SHF_ALLOC) ||
shdr->sh_addr == 0 || shdr->sh_size == 0) {
continue;
}
if (strtab) {
debug("%sing %s @ 0x%08lx (%ld bytes)\n",
(shdr->sh_type == SHT_NOBITS) ? "Clear" : "Load",
&strtab[shdr->sh_name],
(unsigned long)shdr->sh_addr,
(long)shdr->sh_size);
}
if (shdr->sh_type == SHT_NOBITS) {
memset((void *)(uintptr_t)shdr->sh_addr, 0,
shdr->sh_size);
} else {
image = (unsigned char *)addr + shdr->sh_offset;
memcpy((void *)(uintptr_t)shdr->sh_addr,
(const void *)image, shdr->sh_size);
}
flush_cache(shdr->sh_addr, shdr->sh_size);
}
return ehdr->e_entry;
}
/* Allow ports to override the default behavior */
static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
int argc, char * const argv[])
int argc, char * const argv[])
{
unsigned long ret;
@ -54,18 +129,16 @@ static unsigned long do_bootelf_exec(ulong (*entry)(int, char * const[]),
return ret;
}
/* ======================================================================
/*
* Determine if a valid ELF image exists at the given memory location.
* First looks at the ELF header magic field, the makes sure that it is
* executable and makes sure that it is for a PowerPC.
* ====================================================================== */
* First look at the ELF header magic field, then make sure that it is
* executable.
*/
int valid_elf_image(unsigned long addr)
{
Elf32_Ehdr *ehdr; /* Elf header structure pointer */
Elf32_Ehdr *ehdr; /* Elf header structure pointer */
/* -------------------------------------------------- */
ehdr = (Elf32_Ehdr *) addr;
ehdr = (Elf32_Ehdr *)addr;
if (!IS_ELF(*ehdr)) {
printf("## No elf image at address 0x%08lx\n", addr);
@ -77,27 +150,17 @@ int valid_elf_image(unsigned long addr)
return 0;
}
#if 0
if (ehdr->e_machine != EM_PPC) {
printf("## Not a PowerPC elf image at address 0x%08lx\n", addr);
return 0;
}
#endif
return 1;
}
/* ======================================================================
* Interpreter command to boot an arbitrary ELF image from memory.
* ====================================================================== */
/* Interpreter command to boot an arbitrary ELF image from memory */
int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
unsigned long addr; /* Address of the ELF image */
unsigned long rc; /* Return value from user code */
unsigned long addr; /* Address of the ELF image */
unsigned long rc; /* Return value from user code */
char *sload, *saddr;
const char *ep = getenv("autostart");
/* -------------------------------------------------- */
int rcode = 0;
sload = saddr = NULL;
@ -138,28 +201,32 @@ int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
rcode = 1;
printf("## Application terminated, rc = 0x%lx\n", rc);
return rcode;
}
/* ======================================================================
/*
* Interpreter command to boot VxWorks from a memory image. The image can
* be either an ELF image or a raw binary. Will attempt to setup the
* bootline and other parameters correctly.
* ====================================================================== */
*/
int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
unsigned long addr; /* Address of image */
unsigned long bootaddr; /* Address to put the bootline */
char *bootline; /* Text of the bootline */
char *tmp; /* Temporary char pointer */
char build_buf[128]; /* Buffer for building the bootline */
unsigned long addr; /* Address of image */
unsigned long bootaddr; /* Address to put the bootline */
char *bootline; /* Text of the bootline */
char *tmp; /* Temporary char pointer */
char build_buf[128]; /* Buffer for building the bootline */
int ptr = 0;
#ifdef CONFIG_X86
struct e820info *info;
struct e820entry *data;
#endif
/* ---------------------------------------------------
*
/*
* Check the loadaddr variable.
* If we don't know where the image is then we're done.
*/
if (argc < 2)
addr = load_addr;
else
@ -167,7 +234,8 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#if defined(CONFIG_CMD_NET)
/*
* Check to see if we need to tftp the image ourselves before starting
* Check to see if we need to tftp the image ourselves
* before starting
*/
if ((argc == 2) && (strcmp(argv[1], "tftp") == 0)) {
if (net_loop(TFTPGET) <= 0)
@ -177,18 +245,18 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
#endif
/* This should equate
* to NV_RAM_ADRS + NV_BOOT_OFFSET + NV_ENET_OFFSET
/*
* This should equate to
* NV_RAM_ADRS + NV_BOOT_OFFSET + NV_ENET_OFFSET
* from the VxWorks BSP header files.
* This will vary from board to board
*/
#if defined(CONFIG_WALNUT)
tmp = (char *) CONFIG_SYS_NVRAM_BASE_ADDR + 0x500;
tmp = (char *)CONFIG_SYS_NVRAM_BASE_ADDR + 0x500;
eth_getenv_enetaddr("ethaddr", (uchar *)build_buf);
memcpy(tmp, &build_buf[3], 3);
#elif defined(CONFIG_SYS_VXWORKS_MAC_PTR)
tmp = (char *) CONFIG_SYS_VXWORKS_MAC_PTR;
tmp = (char *)CONFIG_SYS_VXWORKS_MAC_PTR;
eth_getenv_enetaddr("ethaddr", (uchar *)build_buf);
memcpy(tmp, build_buf, 6);
#else
@ -197,169 +265,135 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
/*
* Use bootaddr to find the location in memory that VxWorks
* will look for the bootline string. The default value for
* PowerPC is LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET which
* defaults to 0x4200
* will look for the bootline string. The default value is
* (LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET) as defined by
* VxWorks BSP. For example, on PowerPC it defaults to 0x4200.
*/
tmp = getenv("bootaddr");
if (!tmp)
bootaddr = CONFIG_SYS_VXWORKS_BOOT_ADDR;
else
if (!tmp) {
printf("## VxWorks bootline address not specified\n");
} else {
bootaddr = simple_strtoul(tmp, NULL, 16);
/*
* Check to see if the bootline is defined in the 'bootargs'
* parameter. If it is not defined, we may be able to
* construct the info
*/
bootline = getenv("bootargs");
if (bootline) {
memcpy((void *)bootaddr, bootline,
max(strlen(bootline), (size_t)255));
flush_cache(bootaddr, max(strlen(bootline), (size_t)255));
} else {
sprintf(build_buf, CONFIG_SYS_VXWORKS_BOOT_DEVICE);
tmp = getenv("bootfile");
if (tmp)
sprintf(&build_buf[strlen(build_buf)],
"%s:%s ", CONFIG_SYS_VXWORKS_SERVERNAME, tmp);
else
sprintf(&build_buf[strlen(build_buf)],
"%s:file ", CONFIG_SYS_VXWORKS_SERVERNAME);
/*
* Check to see if the bootline is defined in the 'bootargs'
* parameter. If it is not defined, we may be able to
* construct the info.
*/
bootline = getenv("bootargs");
if (bootline) {
memcpy((void *)bootaddr, bootline,
max(strlen(bootline), (size_t)255));
flush_cache(bootaddr, max(strlen(bootline),
(size_t)255));
} else {
tmp = getenv("bootdev");
if (tmp)
ptr = sprintf(build_buf, tmp);
else
printf("## VxWorks boot device not specified\n");
tmp = getenv("ipaddr");
if (tmp)
sprintf(&build_buf[strlen(build_buf)], "e=%s ", tmp);
tmp = getenv("bootfile");
if (tmp)
ptr += sprintf(build_buf + ptr,
"host:%s ", tmp);
else
ptr += sprintf(build_buf + ptr,
"host:vxWorks ");
tmp = getenv("serverip");
if (tmp)
sprintf(&build_buf[strlen(build_buf)], "h=%s ", tmp);
/*
* The following parameters are only needed if 'bootdev'
* is an ethernet device, otherwise they are optional.
*/
tmp = getenv("ipaddr");
if (tmp) {
ptr += sprintf(build_buf + ptr, "e=%s", tmp);
tmp = getenv("netmask");
if (tmp) {
u32 mask = getenv_ip("netmask").s_addr;
ptr += sprintf(build_buf + ptr,
":%08x ", ntohl(mask));
} else {
ptr += sprintf(build_buf + ptr, " ");
}
}
tmp = getenv("hostname");
if (tmp)
sprintf(&build_buf[strlen(build_buf)], "tn=%s ", tmp);
tmp = getenv("serverip");
if (tmp)
ptr += sprintf(build_buf + ptr, "h=%s ", tmp);
#ifdef CONFIG_SYS_VXWORKS_ADD_PARAMS
sprintf(&build_buf[strlen(build_buf)],
CONFIG_SYS_VXWORKS_ADD_PARAMS);
#endif
tmp = getenv("gatewayip");
if (tmp)
ptr += sprintf(build_buf + ptr, "g=%s ", tmp);
memcpy((void *)bootaddr, build_buf,
max(strlen(build_buf), (size_t)255));
flush_cache(bootaddr, max(strlen(build_buf), (size_t)255));
tmp = getenv("hostname");
if (tmp)
ptr += sprintf(build_buf + ptr, "tn=%s ", tmp);
tmp = getenv("othbootargs");
if (tmp)
ptr += sprintf(build_buf + ptr, tmp);
memcpy((void *)bootaddr, build_buf,
max(strlen(build_buf), (size_t)255));
flush_cache(bootaddr, max(strlen(build_buf),
(size_t)255));
}
printf("## Using bootline (@ 0x%lx): %s\n", bootaddr,
(char *)bootaddr);
}
#ifdef CONFIG_X86
/*
* Since E820 information is critical to the kernel, if we don't
* specify these in the environments, use a default one.
*/
tmp = getenv("e820data");
if (tmp)
data = (struct e820entry *)simple_strtoul(tmp, NULL, 16);
else
data = (struct e820entry *)VXWORKS_E820_DATA_ADDR;
tmp = getenv("e820info");
if (tmp)
info = (struct e820info *)simple_strtoul(tmp, NULL, 16);
else
info = (struct e820info *)VXWORKS_E820_INFO_ADDR;
memset(info, 0, sizeof(struct e820info));
info->sign = E820_SIGNATURE;
info->entries = install_e820_map(E820MAX, data);
info->addr = (info->entries - 1) * sizeof(struct e820entry) +
VXWORKS_E820_DATA_ADDR;
#endif
/*
* If the data at the load address is an elf image, then
* treat it like an elf image. Otherwise, assume that it is a
* binary image
* binary image.
*/
if (valid_elf_image(addr)) {
if (valid_elf_image(addr))
addr = load_elf_image_shdr(addr);
} else {
else
puts("## Not an ELF image, assuming binary\n");
/* leave addr as load_addr */
}
printf("## Using bootline (@ 0x%lx): %s\n", bootaddr,
(char *) bootaddr);
printf("## Starting vxWorks at 0x%08lx ...\n", addr);
dcache_disable();
((void (*)(int)) addr) (0);
#ifdef CONFIG_X86
/* VxWorks on x86 uses stack to pass parameters */
((asmlinkage void (*)(int))addr)(0);
#else
((void (*)(int))addr)(0);
#endif
puts("## vxWorks terminated\n");
return 1;
}
/* ======================================================================
* A very simple elf loader, assumes the image is valid, returns the
* entry point address.
* ====================================================================== */
static unsigned long load_elf_image_phdr(unsigned long addr)
{
Elf32_Ehdr *ehdr; /* Elf header structure pointer */
Elf32_Phdr *phdr; /* Program header structure pointer */
int i;
ehdr = (Elf32_Ehdr *) addr;
phdr = (Elf32_Phdr *) (addr + ehdr->e_phoff);
/* Load each program header */
for (i = 0; i < ehdr->e_phnum; ++i) {
void *dst = (void *)(uintptr_t) phdr->p_paddr;
void *src = (void *) addr + phdr->p_offset;
debug("Loading phdr %i to 0x%p (%i bytes)\n",
i, dst, phdr->p_filesz);
if (phdr->p_filesz)
memcpy(dst, src, phdr->p_filesz);
if (phdr->p_filesz != phdr->p_memsz)
memset(dst + phdr->p_filesz, 0x00,
phdr->p_memsz - phdr->p_filesz);
flush_cache((unsigned long)dst, phdr->p_filesz);
++phdr;
}
return ehdr->e_entry;
}
static unsigned long load_elf_image_shdr(unsigned long addr)
{
Elf32_Ehdr *ehdr; /* Elf header structure pointer */
Elf32_Shdr *shdr; /* Section header structure pointer */
unsigned char *strtab = 0; /* String table pointer */
unsigned char *image; /* Binary image pointer */
int i; /* Loop counter */
/* -------------------------------------------------- */
ehdr = (Elf32_Ehdr *) addr;
/* Find the section header string table for output info */
shdr = (Elf32_Shdr *) (addr + ehdr->e_shoff +
(ehdr->e_shstrndx * sizeof(Elf32_Shdr)));
if (shdr->sh_type == SHT_STRTAB)
strtab = (unsigned char *) (addr + shdr->sh_offset);
/* Load each appropriate section */
for (i = 0; i < ehdr->e_shnum; ++i) {
shdr = (Elf32_Shdr *) (addr + ehdr->e_shoff +
(i * sizeof(Elf32_Shdr)));
if (!(shdr->sh_flags & SHF_ALLOC)
|| shdr->sh_addr == 0 || shdr->sh_size == 0) {
continue;
}
if (strtab) {
debug("%sing %s @ 0x%08lx (%ld bytes)\n",
(shdr->sh_type == SHT_NOBITS) ?
"Clear" : "Load",
&strtab[shdr->sh_name],
(unsigned long) shdr->sh_addr,
(long) shdr->sh_size);
}
if (shdr->sh_type == SHT_NOBITS) {
memset((void *)(uintptr_t) shdr->sh_addr, 0,
shdr->sh_size);
} else {
image = (unsigned char *) addr + shdr->sh_offset;
memcpy((void *)(uintptr_t) shdr->sh_addr,
(const void *) image,
shdr->sh_size);
}
flush_cache(shdr->sh_addr, shdr->sh_size);
}
return ehdr->e_entry;
}
/* ====================================================================== */
U_BOOT_CMD(
bootelf, 3, 0, do_bootelf,
bootelf, 3, 0, do_bootelf,
"Boot from an ELF image in memory",
"[-p|-s] [address]\n"
"\t- load ELF image at [address] via program headers (-p)\n"
@ -367,7 +401,7 @@ U_BOOT_CMD(
);
U_BOOT_CMD(
bootvx, 2, 0, do_bootvx,
bootvx, 2, 0, do_bootvx,
"Boot vxWorks from an ELF image",
" [address] - load address of vxWorks ELF image."
);

View File

@ -19,10 +19,13 @@ void *malloc_simple(size_t bytes)
void *ptr;
new_ptr = gd->malloc_ptr + bytes;
debug("%s: size=%zx, ptr=%lx, limit=%lx\n", __func__, bytes, new_ptr,
gd->malloc_limit);
if (new_ptr > gd->malloc_limit)
return NULL;
ptr = map_sysmem(gd->malloc_base + gd->malloc_ptr, bytes);
gd->malloc_ptr = ALIGN(new_ptr, sizeof(new_ptr));
return ptr;
}
@ -37,6 +40,7 @@ void *memalign_simple(size_t align, size_t bytes)
return NULL;
ptr = map_sysmem(addr, bytes);
gd->malloc_ptr = ALIGN(new_ptr, sizeof(new_ptr));
return ptr;
}

View File

@ -5,6 +5,7 @@ CONFIG_AUTOBOOT_KEYED=y
CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
CONFIG_AUTOBOOT_DELAY_STR="d"
CONFIG_AUTOBOOT_STOP_STR=" "
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_XIMG is not set
# CONFIG_CMD_FPGA is not set
# CONFIG_CMD_SOURCE is not set

View File

@ -5,6 +5,7 @@ CONFIG_AUTOBOOT_KEYED=y
CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
CONFIG_AUTOBOOT_DELAY_STR="d"
CONFIG_AUTOBOOT_STOP_STR=" "
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_XIMG is not set
# CONFIG_CMD_FPGA is not set
# CONFIG_CMD_SETEXPR is not set

View File

@ -5,6 +5,7 @@ CONFIG_AUTOBOOT_KEYED=y
CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
CONFIG_AUTOBOOT_DELAY_STR="d"
CONFIG_AUTOBOOT_STOP_STR=" "
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_XIMG is not set
# CONFIG_CMD_FPGA is not set
# CONFIG_CMD_SOURCE is not set

View File

@ -3,6 +3,7 @@ CONFIG_VENDOR_INTEL=y
CONFIG_DEFAULT_DEVICE_TREE="bayleybay"
CONFIG_TARGET_BAYLEYBAY=y
CONFIG_HAVE_INTEL_ME=y
CONFIG_ENABLE_MRC_CACHE=y
CONFIG_SMP=y
CONFIG_HAVE_VGA_BIOS=y
CONFIG_VGA_BIOS_ADDR=0xfffa0000

View File

@ -4,6 +4,7 @@ CONFIG_VENDOR_GOOGLE=y
CONFIG_DEFAULT_DEVICE_TREE="chromebook_link"
CONFIG_TARGET_CHROMEBOOK_LINK=y
CONFIG_HAVE_MRC=y
CONFIG_ENABLE_MRC_CACHE=y
CONFIG_HAVE_VGA_BIOS=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
@ -21,6 +22,10 @@ CONFIG_CROS_EC_LPC=y
CONFIG_SPI_FLASH=y
CONFIG_DM_PCI=y
CONFIG_DM_RTC=y
CONFIG_DEBUG_UART=y
CONFIG_DEBUG_UART_BASE=0x3f8
CONFIG_DEBUG_UART_CLOCK=1843200
CONFIG_DEBUG_UART_BOARD_INIT=y
CONFIG_DM_TPM=y
CONFIG_TPM_TIS_LPC=y
CONFIG_VIDEO_VESA=y

View File

@ -3,6 +3,7 @@ CONFIG_VENDOR_GOOGLE=y
CONFIG_DEFAULT_DEVICE_TREE="chromebox_panther"
CONFIG_TARGET_CHROMEBOX_PANTHER=y
CONFIG_HAVE_MRC=y
CONFIG_ENABLE_MRC_CACHE=y
CONFIG_HAVE_VGA_BIOS=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set

View File

@ -3,6 +3,7 @@ CONFIG_TARGET_DBAU1X00=y
CONFIG_SYS_EXTRA_OPTIONS="DBAU1000"
CONFIG_SYS_PROMPT="DbAu1xx0 # "
# CONFIG_CMD_BDI is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_RUN is not set
# CONFIG_CMD_SAVEENV is not set
# CONFIG_CMD_LOADB is not set

View File

@ -3,6 +3,7 @@ CONFIG_TARGET_DBAU1X00=y
CONFIG_DBAU1100=y
CONFIG_SYS_PROMPT="DbAu1xx0 # "
# CONFIG_CMD_BDI is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_RUN is not set
# CONFIG_CMD_SAVEENV is not set
# CONFIG_CMD_LOADB is not set

View File

@ -3,6 +3,7 @@ CONFIG_TARGET_DBAU1X00=y
CONFIG_DBAU1500=y
CONFIG_SYS_PROMPT="DbAu1xx0 # "
# CONFIG_CMD_BDI is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_RUN is not set
# CONFIG_CMD_SAVEENV is not set
# CONFIG_CMD_LOADB is not set

View File

@ -3,6 +3,7 @@ CONFIG_TARGET_DBAU1X00=y
CONFIG_DBAU1550=y
CONFIG_SYS_PROMPT="DbAu1xx0 # "
# CONFIG_CMD_BDI is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_RUN is not set
# CONFIG_CMD_SAVEENV is not set
# CONFIG_CMD_FPGA is not set

View File

@ -4,6 +4,7 @@ CONFIG_DBAU1550=y
CONFIG_SYS_LITTLE_ENDIAN=y
CONFIG_SYS_PROMPT="DbAu1xx0 # "
# CONFIG_CMD_BDI is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_RUN is not set
# CONFIG_CMD_SAVEENV is not set
# CONFIG_CMD_FPGA is not set

View File

@ -3,4 +3,5 @@ CONFIG_4xx=y
CONFIG_TARGET_DLVISION_10G=y
CONFIG_AUTOBOOT_KEYED=y
CONFIG_AUTOBOOT_STOP_STR=" "
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_NFS is not set

View File

@ -1,4 +1,5 @@
CONFIG_PPC=y
CONFIG_4xx=y
CONFIG_TARGET_DLVISION=y
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_NFS is not set

View File

@ -2,6 +2,7 @@ CONFIG_X86=y
CONFIG_VENDOR_INTEL=y
CONFIG_DEFAULT_DEVICE_TREE="galileo"
CONFIG_TARGET_GALILEO=y
CONFIG_ENABLE_MRC_CACHE=y
CONFIG_GENERATE_PIRQ_TABLE=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set

View File

@ -1,4 +1,5 @@
CONFIG_SPARC=y
CONFIG_TARGET_GR_CPCI_AX2000=y
CONFIG_SYS_TEXT_BASE=0x00000000
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_SETEXPR is not set

View File

@ -1,4 +1,5 @@
CONFIG_SPARC=y
CONFIG_TARGET_GR_EP2S60=y
CONFIG_SYS_TEXT_BASE=0x00000000
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_SETEXPR is not set

View File

@ -1,4 +1,5 @@
CONFIG_SPARC=y
CONFIG_TARGET_GR_XC3S_1500=y
CONFIG_SYS_TEXT_BASE=0x00000000
# CONFIG_CMD_ELF is not sets
# CONFIG_CMD_SETEXPR is not set

View File

@ -5,5 +5,6 @@ CONFIG_AUTOBOOT_KEYED=y
CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
CONFIG_AUTOBOOT_DELAY_STR="d"
CONFIG_AUTOBOOT_STOP_STR=" "
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_FPGA is not set
# CONFIG_CMD_SETEXPR is not set

View File

@ -2,6 +2,7 @@ CONFIG_SPARC=y
CONFIG_TARGET_GRSIM=y
CONFIG_SYS_TEXT_BASE=0x00000000
# CONFIG_CMD_BOOTD is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_IMI is not set
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_EDITENV is not set

View File

@ -2,6 +2,7 @@ CONFIG_SPARC=y
CONFIG_TARGET_GRSIM_LEON2=y
CONFIG_SYS_TEXT_BASE=0x00000000
# CONFIG_CMD_BOOTD is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_IMI is not set
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_EDITENV is not set

View File

@ -3,4 +3,5 @@ CONFIG_4xx=y
CONFIG_TARGET_IO=y
CONFIG_AUTOBOOT_KEYED=y
CONFIG_AUTOBOOT_STOP_STR=" "
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_NFS is not set

View File

@ -3,4 +3,5 @@ CONFIG_4xx=y
CONFIG_TARGET_IOCON=y
CONFIG_AUTOBOOT_KEYED=y
CONFIG_AUTOBOOT_STOP_STR=" "
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_NFS is not set

View File

@ -3,6 +3,7 @@ CONFIG_VENDOR_INTEL=y
CONFIG_DEFAULT_DEVICE_TREE="minnowmax"
CONFIG_TARGET_MINNOWMAX=y
CONFIG_HAVE_INTEL_ME=y
CONFIG_ENABLE_MRC_CACHE=y
CONFIG_SMP=y
CONFIG_HAVE_VGA_BIOS=y
CONFIG_GENERATE_PIRQ_TABLE=y

View File

@ -1,4 +1,5 @@
CONFIG_PPC=y
CONFIG_4xx=y
CONFIG_TARGET_NEO=y
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_NFS is not set

View File

@ -3,6 +3,7 @@ CONFIG_TARGET_PB1X00=y
CONFIG_SYS_EXTRA_OPTIONS="PB1000"
CONFIG_SYS_PROMPT="Pb1x00 # "
# CONFIG_CMD_BDI is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_RUN is not set
# CONFIG_CMD_SAVEENV is not set
# CONFIG_CMD_LOADB is not set

View File

@ -3,6 +3,7 @@ CONFIG_DEFAULT_DEVICE_TREE="sandbox"
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_FIT_SIGNATURE=y
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_SETEXPR is not set

View File

@ -6,6 +6,7 @@ CONFIG_VCT_SMALL_IMAGE=y
CONFIG_SYS_PROMPT="$ "
# CONFIG_CMD_BDI is not set
# CONFIG_CMD_CONSOLE is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_CRC32 is not set
# CONFIG_CMD_LOADB is not set

View File

@ -5,6 +5,7 @@ CONFIG_VCT_SMALL_IMAGE=y
CONFIG_SYS_PROMPT="$ "
# CONFIG_CMD_BDI is not set
# CONFIG_CMD_CONSOLE is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_CRC32 is not set
# CONFIG_CMD_LOADB is not set
# CONFIG_CMD_LOADS is not set

View File

@ -6,6 +6,7 @@ CONFIG_VCT_SMALL_IMAGE=y
CONFIG_SYS_PROMPT="$ "
# CONFIG_CMD_BDI is not set
# CONFIG_CMD_CONSOLE is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_CRC32 is not set
# CONFIG_CMD_LOADB is not set

View File

@ -5,6 +5,7 @@ CONFIG_VCT_SMALL_IMAGE=y
CONFIG_SYS_PROMPT="$ "
# CONFIG_CMD_BDI is not set
# CONFIG_CMD_CONSOLE is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_CRC32 is not set
# CONFIG_CMD_LOADB is not set
# CONFIG_CMD_LOADS is not set

View File

@ -6,6 +6,7 @@ CONFIG_VCT_SMALL_IMAGE=y
CONFIG_SYS_PROMPT="$ "
# CONFIG_CMD_BDI is not set
# CONFIG_CMD_CONSOLE is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_CRC32 is not set
# CONFIG_CMD_LOADB is not set

View File

@ -5,6 +5,7 @@ CONFIG_VCT_SMALL_IMAGE=y
CONFIG_SYS_PROMPT="$ "
# CONFIG_CMD_BDI is not set
# CONFIG_CMD_CONSOLE is not set
# CONFIG_CMD_ELF is not set
# CONFIG_CMD_CRC32 is not set
# CONFIG_CMD_LOADB is not set
# CONFIG_CMD_LOADS is not set

View File

@ -1,19 +1,85 @@
From VxWorks 6.9+ (not include 6.9), VxWorks starts adopting device tree as its hardware
decription mechansim (for PowerPC and ARM), thus requiring boot interface changes.
#
# Copyright (C) 2013, Miao Yan <miao.yan@windriver.com>
# Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
#
# SPDX-License-Identifier: GPL-2.0+
#
VxWorks Support
===============
This document describes the information about U-Boot loading VxWorks kernel.
Status
------
U-Boot supports loading VxWorks kernels via 'bootvx' and 'bootm' commands.
For booting old kernels (6.9.x) on PowerPC and ARM, and all kernel versions
on other architectures, 'bootvx' shall be used. For booting VxWorks 7 kernels
on PowerPC and ARM, 'bootm' shall be used.
64-bit x86 kernel cannot be loaded as of today.
VxWork 7 on PowerPC and ARM
---------------------------
From VxWorks 7, VxWorks starts adopting device tree as its hardware decription
mechansim (for PowerPC and ARM), thus requiring boot interface changes.
This section will describe the new interface.
For PowerPC, the calling convention of the new VxWorks entry point conforms to the ePAPR standard,
which is shown below (see ePAPR for more details):
For PowerPC, the calling convention of the new VxWorks entry point conforms to
the ePAPR standard, which is shown below (see ePAPR for more details):
void (*kernel_entry)(fdt_addr,
0, 0, EPAPR_MAGIC, boot_IMA, 0, 0)
void (*kernel_entry)(fdt_addr, 0, 0, EPAPR_MAGIC, boot_IMA, 0, 0)
For ARM, the calling convention is show below:
void (*kernel_entry)(void *fdt_addr)
When booting new VxWorks kernel (uImage format), the parameters passed to bootm is like below:
When booting new VxWorks kernel (uImage format), the parameters passed to bootm
is like below:
bootm <kernel image address> - <device tree address>
The do_bootvx command still works as it was for older VxWorks kernels.
VxWorks bootline
----------------
When using 'bootvx', the kernel bootline must be prepared by U-Boot at a
board-specific address before loading VxWorks. U-Boot supplies its address
via "bootaddr" environment variable. To check where the bootline should be
for a specific board, go to the VxWorks BSP for that board, and look for a
parameter called BOOT_LINE_ADRS. Assign its value to "bootaddr". A typical
value for "bootaddr" is 0x101200.
If a "bootargs" variable is defined, its content will be copied to the memory
location pointed by "bootaddr" as the kernel bootline. If "bootargs" is not
there, command 'bootvx' can construct a valid bootline using the following
environments variables: bootdev, bootfile, ipaddr, netmask, serverip,
gatewayip, hostname, othbootargs.
When using 'bootm', just define "bootargs" in the environment and U-Boot will
handle bootline fix up for the kernel dtb automatically.
Serial console
--------------
It's very common that VxWorks BSPs configure a different baud rate for the
serial console from what is being used by U-Boot. For example, VxWorks tends
to use 9600 as the default baud rate on all x86 BSPs while U-Boot uses 115200.
Please configure both U-Boot and VxWorks to use the same baud rate, or it may
look like VxWorks hangs somewhere as nothing outputs on the serial console.
x86-specific information
------------------------
Before loading an x86 kernel, two additional environment variables need to be
provided. They are "e820data" and "e820info", which represent the address of
E820 table and E820 information (defined by VxWorks) in system memory.
Check VxWorks kernel configuration to look for BIOS_E820_DATA_START and
BIOS_E820_INFO_START, and assign their values to "e820data" and "e820info"
accordingly. If neither of these two are supplied, U-Boot assumes a default
location at 0x4000 for "e820data" and 0x4a00 for "e820info". Typical values
for "e820data" and "e820info" are 0x104000 and 0x104a00. But there is one
exception on Intel Galileo, where "e820data" and "e820info" should be left
unset, which assume the default location for VxWorks.
Note since currently U-Boot does not support ACPI yet, VxWorks kernel must
be configured to use MP table and virtual wire interrupt mode. This requires
INCLUDE_MPTABLE_BOOT_OP and INCLUDE_VIRTUAL_WIRE_MODE to be included in a
VxWorks kernel configuration.

View File

@ -25,6 +25,8 @@ targets and all Intel boards support running U-Boot 'bare metal'.
As for loading an OS, U-Boot supports directly booting a 32-bit or 64-bit
Linux kernel as part of a FIT image. It also supports a compressed zImage.
U-Boot supports loading an x86 VxWorks kernel. Please check README.vxworks
for more details.
Build Instructions for U-Boot as coreboot payload
-------------------------------------------------
@ -188,6 +190,7 @@ Offset Description Controlling config
000000 descriptor.bin Hard-coded to 0 in ifdtool
001000 me.bin Set by the descriptor
500000 <spare>
6f0000 MRC cache CONFIG_ENABLE_MRC_CACHE
700000 u-boot-dtb.bin CONFIG_SYS_TEXT_BASE
790000 vga.bin CONFIG_VGA_BIOS_ADDR
7c0000 fsp.bin CONFIG_FSP_ADDR
@ -330,9 +333,8 @@ In keeping with the U-Boot philosophy of providing functions to check and
adjust internal settings, there are several x86-specific commands that may be
useful:
hob - Display information about Firmware Support Package (FSP) Hand-off
Block. This is only available on platforms which use FSP, mostly
Atom.
fsp - Display information about Intel Firmware Support Package (FSP).
This is only available on platforms which use FSP, mostly Atom.
iod - Display I/O memory
iow - Write I/O memory
mtrr - List and set the Memory Type Range Registers (MTRR). These are used to
@ -762,7 +764,6 @@ TODO List
- Audio
- Chrome OS verified boot
- SMI and ACPI support, to provide platform info and facilities to Linux
- Desktop Management Interface (DMI) [15] support
References
----------
@ -780,4 +781,3 @@ References
[12] http://events.linuxfoundation.org/sites/events/files/slides/chromeos_and_diy_vboot_0.pdf
[13] http://events.linuxfoundation.org/sites/events/files/slides/elce-2014.pdf
[14] doc/device-tree-bindings/misc/intel,irq-router.txt
[15] http://en.wikipedia.org/wiki/Desktop_Management_Interface

View File

@ -85,30 +85,7 @@ static int pci_get_bus_max(void)
int pci_last_busno(void)
{
struct pci_controller *hose;
struct udevice *bus;
struct uclass *uc;
int ret;
debug("pci_last_busno\n");
ret = uclass_get(UCLASS_PCI, &uc);
if (ret || list_empty(&uc->dev_head))
return -1;
/* Probe the last bus */
bus = list_entry(uc->dev_head.prev, struct udevice, uclass_node);
debug("bus = %p, %s\n", bus, bus->name);
assert(bus);
ret = device_probe(bus);
if (ret)
return ret;
/* If that bus has bridges, we may have new buses now. Get the last */
bus = list_entry(uc->dev_head.prev, struct udevice, uclass_node);
hose = dev_get_uclass_priv(bus);
debug("bus = %s, hose = %p\n", bus->name, hose);
return hose->last_busno;
return pci_get_bus_max();
}
int pci_get_ff(enum pci_size_t size)
@ -387,9 +364,23 @@ int dm_pci_read_config32(struct udevice *dev, int offset, u32 *valuep)
return 0;
}
static void set_vga_bridge_bits(struct udevice *dev)
{
struct udevice *parent = dev->parent;
u16 bc;
while (parent->seq != 0) {
dm_pci_read_config16(parent, PCI_BRIDGE_CONTROL, &bc);
bc |= PCI_BRIDGE_CTL_VGA;
dm_pci_write_config16(parent, PCI_BRIDGE_CONTROL, bc);
parent = parent->parent;
}
}
int pci_auto_config_devices(struct udevice *bus)
{
struct pci_controller *hose = bus->uclass_priv;
struct pci_child_platdata *pplat;
unsigned int sub_bus;
struct udevice *dev;
int ret;
@ -401,10 +392,18 @@ int pci_auto_config_devices(struct udevice *bus)
!ret && dev;
ret = device_find_next_child(&dev)) {
unsigned int max_bus;
int ret;
debug("%s: device %s\n", __func__, dev->name);
max_bus = pciauto_config_device(hose, pci_get_bdf(dev));
ret = pciauto_config_device(hose, pci_get_bdf(dev));
if (ret < 0)
return ret;
max_bus = ret;
sub_bus = max(sub_bus, max_bus);
pplat = dev_get_parent_platdata(dev);
if (pplat->class == (PCI_CLASS_DISPLAY_VGA << 8))
set_vga_bridge_bits(dev);
}
debug("%s: done\n", __func__);
@ -434,7 +433,7 @@ int dm_pci_hose_probe_bus(struct pci_controller *hose, pci_dev_t bdf)
ret = device_probe(bus);
if (ret) {
debug("%s: Cannot probe bus bus %s: %d\n", __func__, bus->name,
debug("%s: Cannot probe bus %s: %d\n", __func__, bus->name,
ret);
return ret;
}
@ -474,10 +473,17 @@ static bool pci_match_one_id(const struct pci_device_id *id,
* pci_find_and_bind_driver() - Find and bind the right PCI driver
*
* This only looks at certain fields in the descriptor.
*
* @parent: Parent bus
* @find_id: Specification of the driver to find
* @bdf: Bus/device/function addreess - see PCI_BDF()
* @devp: Returns a pointer to the device created
* @return 0 if OK, -EPERM if the device is not needed before relocation and
* therefore was not created, other -ve value on error
*/
static int pci_find_and_bind_driver(struct udevice *parent,
struct pci_device_id *find_id, pci_dev_t bdf,
struct udevice **devp)
struct pci_device_id *find_id,
pci_dev_t bdf, struct udevice **devp)
{
struct pci_driver_entry *start, *entry;
const char *drv;
@ -513,7 +519,7 @@ static int pci_find_and_bind_driver(struct udevice *parent,
*/
if (!(gd->flags & GD_FLG_RELOC) &&
!(drv->flags & DM_FLAG_PRE_RELOC))
return 0;
return -EPERM;
/*
* We could pass the descriptor to the driver as
@ -541,7 +547,7 @@ static int pci_find_and_bind_driver(struct udevice *parent,
* limited (ie: using Cache As RAM).
*/
if (!(gd->flags & GD_FLG_RELOC) && !bridge)
return 0;
return -EPERM;
/* Bind a generic driver so that the device can be used */
sprintf(name, "pci_%x:%x.%x", parent->seq, PCI_DEV(bdf),
@ -553,7 +559,7 @@ static int pci_find_and_bind_driver(struct udevice *parent,
ret = device_bind_driver(parent, drv, str, devp);
if (ret) {
debug("%s: Failed to bind generic driver: %d", __func__, ret);
debug("%s: Failed to bind generic driver: %d\n", __func__, ret);
return ret;
}
debug("%s: No match found: bound generic driver instead\n", __func__);
@ -629,17 +635,17 @@ int pci_bind_bus_devices(struct udevice *bus)
ret = pci_find_and_bind_driver(bus, &find_id, bdf,
&dev);
}
if (ret)
if (ret == -EPERM)
continue;
else if (ret)
return ret;
/* Update the platform data */
if (dev) {
pplat = dev_get_parent_platdata(dev);
pplat->devfn = PCI_MASK_BUS(bdf);
pplat->vendor = vendor;
pplat->device = device;
pplat->class = class;
}
pplat = dev_get_parent_platdata(dev);
pplat->devfn = PCI_MASK_BUS(bdf);
pplat->vendor = vendor;
pplat->device = device;
pplat->class = class;
}
return 0;
@ -777,6 +783,8 @@ static int pci_uclass_post_probe(struct udevice *bus)
#ifdef CONFIG_PCI_PNP
ret = pci_auto_config_devices(bus);
if (ret < 0)
return ret;
#endif
#if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
@ -793,11 +801,14 @@ static int pci_uclass_post_probe(struct udevice *bus)
* Note we only call this 1) after U-Boot is relocated, and 2)
* root bus has finished probing.
*/
if ((gd->flags & GD_FLG_RELOC) && (bus->seq == 0))
if ((gd->flags & GD_FLG_RELOC) && (bus->seq == 0)) {
ret = fsp_init_phase_pci();
if (ret)
return ret;
}
#endif
return ret < 0 ? ret : 0;
return 0;
}
static int pci_uclass_child_post_bind(struct udevice *dev)

View File

@ -89,6 +89,7 @@ void pciauto_setup_device(struct pci_controller *hose,
struct pci_region *bar_res;
int found_mem64 = 0;
#endif
u16 class;
pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | PCI_COMMAND_MASTER;
@ -206,6 +207,11 @@ void pciauto_setup_device(struct pci_controller *hose,
}
#endif
/* PCI_COMMAND_IO must be set for VGA device */
pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class);
if (class == PCI_CLASS_DISPLAY_VGA)
cmdstat |= PCI_COMMAND_IO;
pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat);
pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE,
CONFIG_SYS_PCI_CACHE_LINE_SIZE);

View File

@ -192,7 +192,7 @@ static void mc146818_init(void)
/* Clear any pending interrupts */
mc146818_read8(RTC_CONFIG_C);
}
#endif
#endif /* CONFIG_CMD_DATE */
#ifdef CONFIG_DM_RTC
@ -225,7 +225,7 @@ static int rtc_mc146818_write8(struct udevice *dev, unsigned int reg, int val)
return 0;
}
static int rtc_mc146818_bind(struct udevice *dev)
static int rtc_mc146818_probe(struct udevice *dev)
{
mc146818_init();
@ -249,7 +249,7 @@ U_BOOT_DRIVER(rtc_mc146818) = {
.name = "rtc_mc146818",
.id = UCLASS_RTC,
.of_match = rtc_mc146818_ids,
.bind = rtc_mc146818_bind,
.probe = rtc_mc146818_probe,
.ops = &rtc_mc146818_ops,
};

View File

@ -68,7 +68,7 @@ int rtc_read32(struct udevice *dev, unsigned int reg, u32 *valuep)
for (i = 0; i < sizeof(value); i++) {
ret = rtc_read8(dev, reg + i);
if (ret)
if (ret < 0)
return ret;
value |= ret << (i << 3);
}

View File

@ -109,6 +109,27 @@ config DEBUG_UART_SHIFT
value. Use this value to specify the shift to use, where 0=byte
registers, 2=32-bit word registers, etc.
config DEBUG_UART_BOARD_INIT
bool "Enable board-specific debug UART init"
depends on DEBUG_UART
help
Some boards need to set things up before the debug UART can be used.
On these boards a call to debug_uart_init() is insufficient. When
this option is enabled, the function board_debug_uart_init() will
be called when debug_uart_init() is called. You can put any code
here that is needed to set up the UART ready for use, such as set
pin multiplexing or enable clocks.
config DEBUG_UART_ANNOUNCE
bool "Show a message when the debug UART starts up"
depends on DEBUG_UART
help
Enable this option to show a message when the debug UART is ready
for use. You will see a message like "<debug_uart> " as soon as
U-Boot has the UART ready for use (i.e. your code calls
debug_uart_init()). This can be useful just as a check that
everything is working.
config ROCKCHIP_SERIAL
bool "Rockchip on-chip UART support"
depends on ARCH_ROCKCHIP && DM_SERIAL

View File

@ -257,7 +257,7 @@ int NS16550_tstc(NS16550_t com_port)
(1 << CONFIG_DEBUG_UART_SHIFT), \
CONFIG_DEBUG_UART_SHIFT)
void debug_uart_init(void)
static inline void _debug_uart_init(void)
{
struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE;
int baud_divisor;

View File

@ -107,7 +107,7 @@ static int serial_efi_pending(struct udevice *dev, bool input)
* There is nothing to init here since the EFI console is already running by
* the time we enter U-Boot.
*/
void debug_uart_init(void)
static inline void _debug_uart_init(void)
{
}

View File

@ -207,7 +207,7 @@ U_BOOT_DRIVER(serial_s5p) = {
#include <debug_uart.h>
void debug_uart_init(void)
static inline void _debug_uart_init(void)
{
struct s5p_uart *uart = (struct s5p_uart *)CONFIG_DEBUG_UART_BASE;

View File

@ -133,7 +133,8 @@ static int get_ich_version(uint16_t device_id)
(device_id >= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN &&
device_id <= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX) ||
device_id == PCI_DEVICE_ID_INTEL_VALLEYVIEW_LPC ||
device_id == PCI_DEVICE_ID_INTEL_LYNXPOINT_LPC)
device_id == PCI_DEVICE_ID_INTEL_LYNXPOINT_LPC ||
device_id == PCI_DEVICE_ID_INTEL_WILDCATPOINT_LPC)
return 9;
return 0;

View File

@ -34,7 +34,7 @@ void *video_hw_init(void)
}
if (vbe_get_video_info(gdev)) {
dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0);
if (dev == -1) {
if (dev < 0) {
printf("no card detected\n");
return NULL;
}

View File

@ -29,7 +29,6 @@
#define CONFIG_CMD_DOC /* Disk-On-Chip Support */
#define CONFIG_CMD_DTT /* Digital Therm and Thermostat */
#define CONFIG_CMD_EEPROM /* EEPROM read/write support */
#define CONFIG_CMD_ELF /* ELF (VxWorks) load/boot cmd */
#define CONFIG_CMD_EXT2 /* EXT2 Support */
#define CONFIG_CMD_FAT /* FAT support */
#define CONFIG_CMD_FDC /* Floppy Disk Support */

View File

@ -49,7 +49,6 @@
#define CONFIG_CMD_BOOTZ
#endif
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_ELF
#define CONFIG_CMD_EXT2
#define CONFIG_CMD_EXT4
#define CONFIG_CMD_FAT

View File

@ -756,7 +756,6 @@ unsigned long get_board_ddr_clk(void);
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_EEPROM
#define CONFIG_CMD_ELF
#define CONFIG_CMD_ERRATA
#define CONFIG_CMD_GREPENV
#define CONFIG_CMD_IRQ

View File

@ -342,7 +342,6 @@ extern unsigned long get_sdram_size(void);
*/
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_ERRATA
#define CONFIG_CMD_ELF
#define CONFIG_CMD_EXT2
#define CONFIG_CMD_FAT
#define CONFIG_CMD_IRQ

View File

@ -580,7 +580,6 @@ combinations. this should be removed later
*/
#define CONFIG_CMD_DATE
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_ELF
#define CONFIG_CMD_ERRATA
#define CONFIG_CMD_I2C
#define CONFIG_CMD_IRQ

View File

@ -494,7 +494,6 @@
* Command line configuration.
*/
#define CONFIG_CMD_ERRATA
#define CONFIG_CMD_ELF
#define CONFIG_CMD_IRQ
#define CONFIG_CMD_MII
#define CONFIG_CMD_PING

View File

@ -55,7 +55,6 @@
*/
#define CONFIG_CMD_PCI
#define CONFIG_CMD_IRQ
#define CONFIG_CMD_ELF
#define CONFIG_CMD_I2C
#define CONFIG_CMD_BSP
#define CONFIG_CMD_EEPROM

View File

@ -72,7 +72,6 @@
#define CONFIG_CMD_IRQ
#define CONFIG_CMD_IDE
#define CONFIG_CMD_FAT
#define CONFIG_CMD_ELF
#define CONFIG_CMD_DATE
#define CONFIG_CMD_I2C
#define CONFIG_CMD_MII

View File

@ -23,7 +23,6 @@
/* Command line configuration */
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_ELF
#undef CONFIG_CMD_I2C
#define CONFIG_CMD_MII
#define CONFIG_CMD_PING

View File

@ -39,7 +39,6 @@
/* Command line configuration */
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_ELF
#define CONFIG_CMD_I2C
#define CONFIG_CMD_JFFS2
#define CONFIG_CMD_REGINFO

View File

@ -37,7 +37,6 @@
/* Command line configuration */
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DHCP
#define CONFIG_CMD_ELF
#define CONFIG_CMD_I2C
#define CONFIG_CMD_MII
#define CONFIG_CMD_PCI

View File

@ -59,7 +59,6 @@
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_MII
#define CONFIG_CMD_PING
#define CONFIG_CMD_ELF
#define CONFIG_BOOTDELAY 5

View File

@ -58,7 +58,6 @@
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_PING
#define CONFIG_CMD_MII
#define CONFIG_CMD_ELF
#define CONFIG_CMD_I2C
#define CONFIG_CMD_DHCP

Some files were not shown because too many files have changed in this diff Show More