diff options
author | Bin Meng <bmeng.cn@gmail.com> | 2016-02-27 22:58:03 -0800 |
---|---|---|
committer | Bin Meng <bmeng.cn@gmail.com> | 2016-03-17 10:27:22 +0800 |
commit | 26f9a9b73aeb59150281a10e76567967cfe0611b (patch) | |
tree | b3f6705813e4e5013d58722c26c646de05923079 /arch | |
parent | ff94c219e95843fe24710c16a66efdfb6ca536a9 (diff) |
x86: Implement functions for writing coreboot table
To prepare generating coreboot table from U-Boot, implement functions
to handle the writing.
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/coreboot_tables.h | 10 | ||||
-rw-r--r-- | arch/x86/lib/Makefile | 1 | ||||
-rw-r--r-- | arch/x86/lib/coreboot_table.c | 136 |
3 files changed, 147 insertions, 0 deletions
diff --git a/arch/x86/include/asm/coreboot_tables.h b/arch/x86/include/asm/coreboot_tables.h index ab4425f78a..15ccf9be6c 100644 --- a/arch/x86/include/asm/coreboot_tables.h +++ b/arch/x86/include/asm/coreboot_tables.h @@ -294,4 +294,14 @@ struct cbmem_entry { #define CBMEM_ID_CONSOLE 0x434f4e53 #define CBMEM_ID_NONE 0x00000000 +/** + * write_coreboot_table() - write coreboot table + * + * This writes coreboot table at a given address. + * + * @addr: start address to write coreboot table + * @cfg_tables: pointer to configuration table memory area + */ +void write_coreboot_table(u32 addr, struct memory_area *cfg_tables); + #endif diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 4fc19365eb..6e0234af5b 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -10,6 +10,7 @@ obj-y += bios_asm.o obj-y += bios_interrupts.o obj-$(CONFIG_CMD_BOOTM) += bootm.o obj-y += cmd_boot.o +obj-y += coreboot_table.o obj-$(CONFIG_EFI) += efi/ obj-y += e820.o obj-y += gcc.o diff --git a/arch/x86/lib/coreboot_table.c b/arch/x86/lib/coreboot_table.c new file mode 100644 index 0000000000..cb45a79857 --- /dev/null +++ b/arch/x86/lib/coreboot_table.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <vbe.h> +#include <asm/coreboot_tables.h> +#include <asm/e820.h> + +/** + * cb_table_init() - initialize a coreboot table header + * + * This fills in the coreboot table header signature and the header bytes. + * Other fields are set to zero. + * + * @cbh: coreboot table header address + */ +static void cb_table_init(struct cb_header *cbh) +{ + memset(cbh, 0, sizeof(struct cb_header)); + memcpy(cbh->signature, "LBIO", 4); + cbh->header_bytes = sizeof(struct cb_header); +} + +/** + * cb_table_add_entry() - add a coreboot table entry + * + * This increases the coreboot table entry size with added table entry length + * and increases entry count by 1. + * + * @cbh: coreboot table header address + * @cbr: to be added table entry address + * @return: pointer to next table entry address + */ +static u32 cb_table_add_entry(struct cb_header *cbh, struct cb_record *cbr) +{ + cbh->table_bytes += cbr->size; + cbh->table_entries++; + + return (u32)cbr + cbr->size; +} + +/** + * cb_table_finalize() - finalize the coreboot table + * + * This calculates the checksum for all coreboot table entries as well as + * the checksum for the coreboot header itself. + * + * @cbh: coreboot table header address + */ +static void cb_table_finalize(struct cb_header *cbh) +{ + struct cb_record *cbr = (struct cb_record *)(cbh + 1); + + cbh->table_checksum = compute_ip_checksum(cbr, cbh->table_bytes); + cbh->header_checksum = compute_ip_checksum(cbh, cbh->header_bytes); +} + +void write_coreboot_table(u32 addr, struct memory_area *cfg_tables) +{ + struct cb_header *cbh = (struct cb_header *)addr; + struct cb_record *cbr; + struct cb_memory *mem; + struct cb_memory_range *map; + struct e820entry e820[32]; + struct cb_framebuffer *fb; + struct vesa_mode_info *vesa; + int i, num; + + cb_table_init(cbh); + cbr = (struct cb_record *)(cbh + 1); + + /* + * Two type of coreboot table entries are generated by us. + * They are 'struct cb_memory' and 'struct cb_framebuffer'. + */ + + /* populate memory map table */ + mem = (struct cb_memory *)cbr; + mem->tag = CB_TAG_MEMORY; + map = mem->map; + + /* first install e820 defined memory maps */ + num = install_e820_map(ARRAY_SIZE(e820), e820); + for (i = 0; i < num; i++) { + map->start.lo = e820[i].addr & 0xffffffff; + map->start.hi = e820[i].addr >> 32; + map->size.lo = e820[i].size & 0xffffffff; + map->size.hi = e820[i].size >> 32; + map->type = e820[i].type; + map++; + } + + /* then install all configuration tables */ + while (cfg_tables->size) { + map->start.lo = cfg_tables->start & 0xffffffff; + map->start.hi = cfg_tables->start >> 32; + map->size.lo = cfg_tables->size & 0xffffffff; + map->size.hi = cfg_tables->size >> 32; + map->type = CB_MEM_TABLE; + map++; + num++; + cfg_tables++; + } + mem->size = num * sizeof(struct cb_memory_range) + + sizeof(struct cb_record); + cbr = (struct cb_record *)cb_table_add_entry(cbh, cbr); + + /* populate framebuffer table if we have sane vesa info */ + vesa = &mode_info.vesa; + if (vesa->x_resolution && vesa->y_resolution) { + fb = (struct cb_framebuffer *)cbr; + fb->tag = CB_TAG_FRAMEBUFFER; + fb->size = sizeof(struct cb_framebuffer); + + fb->x_resolution = vesa->x_resolution; + fb->y_resolution = vesa->y_resolution; + fb->bits_per_pixel = vesa->bits_per_pixel; + fb->bytes_per_line = vesa->bytes_per_scanline; + fb->physical_address = vesa->phys_base_ptr; + fb->red_mask_size = vesa->red_mask_size; + fb->red_mask_pos = vesa->red_mask_pos; + fb->green_mask_size = vesa->green_mask_size; + fb->green_mask_pos = vesa->green_mask_pos; + fb->blue_mask_size = vesa->blue_mask_size; + fb->blue_mask_pos = vesa->blue_mask_pos; + fb->reserved_mask_size = vesa->reserved_mask_size; + fb->reserved_mask_pos = vesa->reserved_mask_pos; + + cbr = (struct cb_record *)cb_table_add_entry(cbh, cbr); + } + + cb_table_finalize(cbh); +} |