diff options
Diffstat (limited to 'arch/x86/lib')
-rw-r--r-- | arch/x86/lib/Makefile | 4 | ||||
-rw-r--r-- | arch/x86/lib/cmd_hob.c | 65 | ||||
-rw-r--r-- | arch/x86/lib/e820.c | 37 | ||||
-rw-r--r-- | arch/x86/lib/fsp/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/lib/fsp/cmd_fsp.c | 132 | ||||
-rw-r--r-- | arch/x86/lib/fsp/fsp_common.c | 30 | ||||
-rw-r--r-- | arch/x86/lib/fsp/fsp_dram.c | 6 | ||||
-rw-r--r-- | arch/x86/lib/mrccache.c | 253 | ||||
-rw-r--r-- | arch/x86/lib/smbios.c | 269 | ||||
-rw-r--r-- | arch/x86/lib/tables.c | 5 | ||||
-rw-r--r-- | arch/x86/lib/zimage.c | 26 |
11 files changed, 735 insertions, 93 deletions
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 6ecd6dbd9d..2f82a21aff 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -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 diff --git a/arch/x86/lib/cmd_hob.c b/arch/x86/lib/cmd_hob.c deleted file mode 100644 index 915746a4f9..0000000000 --- a/arch/x86/lib/cmd_hob.c +++ /dev/null @@ -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", - "" -); diff --git a/arch/x86/lib/e820.c b/arch/x86/lib/e820.c new file mode 100644 index 0000000000..5babfde268 --- /dev/null +++ b/arch/x86/lib/e820.c @@ -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; +} diff --git a/arch/x86/lib/fsp/Makefile b/arch/x86/lib/fsp/Makefile index 5b12c12d7a..3ea4880a30 100644 --- a/arch/x86/lib/fsp/Makefile +++ b/arch/x86/lib/fsp/Makefile @@ -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 diff --git a/arch/x86/lib/fsp/cmd_fsp.c b/arch/x86/lib/fsp/cmd_fsp.c new file mode 100644 index 0000000000..4959edf11b --- /dev/null +++ b/arch/x86/lib/fsp/cmd_fsp.c @@ -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" +); diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c index 658f32d583..c78df94b80 100644 --- a/arch/x86/lib/fsp/fsp_common.c +++ b/arch/x86/lib/fsp/fsp_common.c @@ -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() diff --git a/arch/x86/lib/fsp/fsp_dram.c b/arch/x86/lib/fsp/fsp_dram.c index e51ca96eb7..fcfe693ce5 100644 --- a/arch/x86/lib/fsp/fsp_dram.c +++ b/arch/x86/lib/fsp/fsp_dram.c @@ -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; } diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c new file mode 100644 index 0000000000..53a1259d09 --- /dev/null +++ b/arch/x86/lib/mrccache.c @@ -0,0 +1,253 @@ +/* + * 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/mrccache.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct mrc_data_container *next_mrc_block( + struct mrc_data_container *cache) +{ + /* MRC data blocks are aligned within the region */ + 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; + } + + region_ptr += mrc_size; + + return (struct mrc_data_container *)region_ptr; +} + +static int is_mrc_cache(struct mrc_data_container *cache) +{ + return cache && (cache->signature == MRC_DATA_SIGNATURE); +} + +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 = entry->base + entry->offset; + end_addr = base_addr + entry->length; + cache = NULL; + + /* Search for the last filled entry in the region */ + for (id = 0, next = (struct mrc_data_container *)base_addr; + is_mrc_cache(next); + id++) { + cache = next; + next = next_mrc_block(next); + if ((ulong)next >= end_addr) + break; + } + + if (id-- == 0) { + debug("%s: No valid MRC cache found.\n", __func__); + return NULL; + } + + /* Verify checksum */ + if (cache->checksum != compute_ip_checksum(cache->data, + cache->data_size)) { + printf("%s: MRC cache checksum mismatch\n", __func__); + return NULL; + } + + debug("%s: picked entry %u from cache block\n", __func__, id); + + return cache; +} + +/** + * find_next_mrc_cache() - get next cache entry + * + * @entry: MRC cache flash area + * @cache: Entry to start from + * + * @return next cache entry if found, NULL if we got to the end + */ +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 = entry->base + entry->offset; + end_addr = base_addr + entry->length; + + cache = next_mrc_block(cache); + if ((ulong)cache >= end_addr) { + /* Crossed the boundary */ + cache = NULL; + debug("%s: no available entries found\n", __func__); + } else { + debug("%s: picked next entry from cache block at %p\n", + __func__, cache); + } + + return cache; +} + +int mrccache_update(struct udevice *sf, struct mrc_region *entry, + struct mrc_data_container *cur) +{ + struct mrc_data_container *cache; + ulong offset; + ulong base_addr; + int ret; + + if (!is_mrc_cache(cur)) + return -EINVAL; + + /* Find the last used block */ + 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) && + (!memcmp(cache, cur, cache->data_size + sizeof(*cur)))) { + debug("MRC data in flash is up to date. No update\n"); + return -EEXIST; + } + + /* Move to the next block, which will be the first unused block */ + if (cache) + cache = find_next_mrc_cache(entry, cache); + + /* + * If we have got to the end, erase the entire mrc-cache area and start + * again at block 0. + */ + if (!cache) { + debug("Erasing the MRC cache region of %x bytes at %x\n", + entry->length, entry->offset); + + ret = spi_flash_erase_dm(sf, entry->offset, entry->length); + if (ret) { + debug("Failed to erase flash region\n"); + return ret; + } + cache = (struct mrc_data_container *)base_addr; + } + + /* Write the data out */ + offset = (ulong)cache - base_addr + entry->offset; + debug("Write MRC cache update to flash at %lx\n", offset); + ret = spi_flash_write_dm(sf, offset, cur->data_size + sizeof(*cur), + cur); + if (ret) { + debug("Failed to write to SPI flash\n"); + return ret; + } + + 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; +} diff --git a/arch/x86/lib/smbios.c b/arch/x86/lib/smbios.c new file mode 100644 index 0000000000..441fca99f1 --- /dev/null +++ b/arch/x86/lib/smbios.c @@ -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; +} diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index f15b2e2855..14b15cf389 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -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 } diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index a1ec57e8d3..1b33c77139 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -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; |