2009-08-27 13:23:06 +02:00
|
|
|
/*
|
|
|
|
* This file is part of the coreboot project.
|
2010-04-27 08:56:47 +02:00
|
|
|
*
|
2009-08-27 13:23:06 +02:00
|
|
|
* Copyright (C) 2003-2004 Eric Biederman
|
2010-03-29 19:14:28 +02:00
|
|
|
* Copyright (C) 2005-2010 coresystems GmbH
|
2009-08-27 13:23:06 +02:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; version 2 of
|
|
|
|
* the License.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*/
|
|
|
|
|
2003-04-22 21:02:15 +02:00
|
|
|
#include <console/console.h>
|
2014-02-17 20:34:42 +01:00
|
|
|
#include <console/uart.h>
|
2003-04-22 21:02:15 +02:00
|
|
|
#include <ip_checksum.h>
|
2008-01-18 17:16:45 +01:00
|
|
|
#include <boot/coreboot_tables.h>
|
2015-07-14 18:15:51 +02:00
|
|
|
#include <boot_device.h>
|
2003-04-22 21:02:15 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <version.h>
|
2014-07-29 01:03:07 +02:00
|
|
|
#include <boardid.h>
|
2004-10-14 22:54:17 +02:00
|
|
|
#include <device/device.h>
|
2015-07-14 18:15:51 +02:00
|
|
|
#include <fmap.h>
|
2004-10-14 22:54:17 +02:00
|
|
|
#include <stdlib.h>
|
2011-08-16 01:35:10 +02:00
|
|
|
#include <cbfs.h>
|
2011-09-23 18:56:11 +02:00
|
|
|
#include <cbmem.h>
|
2014-02-19 04:55:02 +01:00
|
|
|
#include <bootmem.h>
|
2015-01-08 19:29:19 +01:00
|
|
|
#include <spi_flash.h>
|
2015-09-21 20:11:47 +02:00
|
|
|
#if CONFIG_USE_OPTION_TABLE
|
|
|
|
#include <option_table.h>
|
|
|
|
#endif
|
2012-04-27 00:34:54 +02:00
|
|
|
#if CONFIG_CHROMEOS
|
2014-01-03 15:55:40 +01:00
|
|
|
#if CONFIG_HAVE_ACPI_TABLES
|
2012-04-27 00:34:54 +02:00
|
|
|
#include <arch/acpi.h>
|
2013-03-20 22:08:04 +01:00
|
|
|
#endif
|
2013-03-08 06:15:06 +01:00
|
|
|
#include <vendorcode/google/chromeos/chromeos.h>
|
2012-04-27 00:34:54 +02:00
|
|
|
#include <vendorcode/google/chromeos/gnvs.h>
|
|
|
|
#endif
|
2013-03-26 19:09:39 +01:00
|
|
|
#if CONFIG_ARCH_X86
|
|
|
|
#include <cpu/x86/mtrr.h>
|
|
|
|
#endif
|
2003-04-22 21:02:15 +02:00
|
|
|
|
2009-08-27 13:23:06 +02:00
|
|
|
static struct lb_header *lb_table_init(unsigned long addr)
|
2003-04-22 21:02:15 +02:00
|
|
|
{
|
|
|
|
struct lb_header *header;
|
|
|
|
|
|
|
|
/* 16 byte align the address */
|
|
|
|
addr += 15;
|
|
|
|
addr &= ~15;
|
|
|
|
|
|
|
|
header = (void *)addr;
|
|
|
|
header->signature[0] = 'L';
|
|
|
|
header->signature[1] = 'B';
|
|
|
|
header->signature[2] = 'I';
|
|
|
|
header->signature[3] = 'O';
|
|
|
|
header->header_bytes = sizeof(*header);
|
|
|
|
header->header_checksum = 0;
|
|
|
|
header->table_bytes = 0;
|
|
|
|
header->table_checksum = 0;
|
|
|
|
header->table_entries = 0;
|
|
|
|
return header;
|
|
|
|
}
|
|
|
|
|
2009-08-27 13:23:06 +02:00
|
|
|
static struct lb_record *lb_first_record(struct lb_header *header)
|
2003-04-22 21:02:15 +02:00
|
|
|
{
|
|
|
|
struct lb_record *rec;
|
|
|
|
rec = (void *)(((char *)header) + sizeof(*header));
|
|
|
|
return rec;
|
|
|
|
}
|
|
|
|
|
2009-08-27 13:23:06 +02:00
|
|
|
static struct lb_record *lb_last_record(struct lb_header *header)
|
2003-04-22 21:02:15 +02:00
|
|
|
{
|
|
|
|
struct lb_record *rec;
|
|
|
|
rec = (void *)(((char *)header) + sizeof(*header) + header->table_bytes);
|
|
|
|
return rec;
|
|
|
|
}
|
|
|
|
|
2013-08-28 00:48:32 +02:00
|
|
|
struct lb_record *lb_new_record(struct lb_header *header)
|
2003-04-22 21:02:15 +02:00
|
|
|
{
|
|
|
|
struct lb_record *rec;
|
|
|
|
rec = lb_last_record(header);
|
|
|
|
if (header->table_entries) {
|
|
|
|
header->table_bytes += rec->size;
|
|
|
|
}
|
|
|
|
rec = lb_last_record(header);
|
|
|
|
header->table_entries++;
|
|
|
|
rec->tag = LB_TAG_UNUSED;
|
|
|
|
rec->size = sizeof(*rec);
|
|
|
|
return rec;
|
|
|
|
}
|
|
|
|
|
2009-08-27 13:23:06 +02:00
|
|
|
static struct lb_memory *lb_memory(struct lb_header *header)
|
2003-04-22 21:02:15 +02:00
|
|
|
{
|
|
|
|
struct lb_record *rec;
|
|
|
|
struct lb_memory *mem;
|
|
|
|
rec = lb_new_record(header);
|
|
|
|
mem = (struct lb_memory *)rec;
|
|
|
|
mem->tag = LB_TAG_MEMORY;
|
|
|
|
mem->size = sizeof(*mem);
|
|
|
|
return mem;
|
|
|
|
}
|
|
|
|
|
2014-03-15 00:32:55 +01:00
|
|
|
void lb_add_serial(struct lb_serial *new_serial, void *data)
|
2008-01-25 19:28:18 +01:00
|
|
|
{
|
2014-03-15 00:32:55 +01:00
|
|
|
struct lb_header *header = (struct lb_header *)data;
|
2008-01-25 19:28:18 +01:00
|
|
|
struct lb_serial *serial;
|
2014-03-15 00:32:55 +01:00
|
|
|
|
|
|
|
serial = (struct lb_serial *)lb_new_record(header);
|
2008-01-25 19:28:18 +01:00
|
|
|
serial->tag = LB_TAG_SERIAL;
|
|
|
|
serial->size = sizeof(*serial);
|
2014-03-15 00:32:55 +01:00
|
|
|
serial->type = new_serial->type;
|
|
|
|
serial->baseaddr = new_serial->baseaddr;
|
|
|
|
serial->baud = new_serial->baud;
|
2015-01-10 01:54:19 +01:00
|
|
|
serial->regwidth = new_serial->regwidth;
|
2008-01-25 19:28:18 +01:00
|
|
|
}
|
|
|
|
|
2014-03-15 00:32:55 +01:00
|
|
|
void lb_add_console(uint16_t consoletype, void *data)
|
2008-01-27 15:12:54 +01:00
|
|
|
{
|
2014-03-15 00:32:55 +01:00
|
|
|
struct lb_header *header = (struct lb_header *)data;
|
2008-01-27 15:12:54 +01:00
|
|
|
struct lb_console *console;
|
2009-04-21 22:14:31 +02:00
|
|
|
|
2008-01-27 15:12:54 +01:00
|
|
|
console = (struct lb_console *)lb_new_record(header);
|
|
|
|
console->tag = LB_TAG_CONSOLE;
|
|
|
|
console->size = sizeof(*console);
|
|
|
|
console->type = consoletype;
|
|
|
|
}
|
|
|
|
|
2015-10-02 01:06:47 +02:00
|
|
|
void __attribute__((weak)) lb_framebuffer(struct lb_header *header)
|
2010-02-22 05:33:13 +01:00
|
|
|
{
|
2013-02-26 19:07:40 +01:00
|
|
|
#if CONFIG_FRAMEBUFFER_KEEP_VESA_MODE || CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT
|
2010-02-22 05:33:13 +01:00
|
|
|
void fill_lb_framebuffer(struct lb_framebuffer *framebuffer);
|
oprom: Ensure that mode information is valid before putting it in the tables.
At least when CONFIG_CHROMEOS is turned on, it's possible for
CONFIG_FRAMEBUFFER_KEEP_VESA_MODE to be set but for there not to be any valid
information to put into the framebuffer coreboot table. That means that what's
put in there is junk, probably all zeroes from the uninitialized global
variable the mode information is stored in (mode_info).
When a payload uses libpayload and turns on the coreboot framebuffer console,
that console will attempt to scroll at some point and decrease the cursor's y
coordinate until it is less than the number of rows claimed by the console.
The number of rows is computed by taking the vertical resolution of the
framebuffer and dividing it by the height of the font. Because the mode
information was all zeroes, the coreboot table info is all zeroes, and that
means that the number of rows the console claims is zero. You can't get the
unsigned y coordinate of the cursor to be less than zero, so libpayload gets
stuck in an infinite loop.
The solution this change implements is to add a new function,
vbe_mode_info_valid, which simply returns whether or not mode_info has anything
in it. If not, the framebuffer coreboot table is not created, and libpayload
doesn't get stuck.
Change-Id: I08f3ec628e4453f0cfe9e15c4d8dfd40327f91c9
Signed-off-by: Gabe Black <gabeblack@google.com>
Reviewed-on: http://review.coreboot.org/1758
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
2012-09-30 13:47:48 +02:00
|
|
|
int vbe_mode_info_valid(void);
|
2010-02-22 05:33:13 +01:00
|
|
|
|
oprom: Ensure that mode information is valid before putting it in the tables.
At least when CONFIG_CHROMEOS is turned on, it's possible for
CONFIG_FRAMEBUFFER_KEEP_VESA_MODE to be set but for there not to be any valid
information to put into the framebuffer coreboot table. That means that what's
put in there is junk, probably all zeroes from the uninitialized global
variable the mode information is stored in (mode_info).
When a payload uses libpayload and turns on the coreboot framebuffer console,
that console will attempt to scroll at some point and decrease the cursor's y
coordinate until it is less than the number of rows claimed by the console.
The number of rows is computed by taking the vertical resolution of the
framebuffer and dividing it by the height of the font. Because the mode
information was all zeroes, the coreboot table info is all zeroes, and that
means that the number of rows the console claims is zero. You can't get the
unsigned y coordinate of the cursor to be less than zero, so libpayload gets
stuck in an infinite loop.
The solution this change implements is to add a new function,
vbe_mode_info_valid, which simply returns whether or not mode_info has anything
in it. If not, the framebuffer coreboot table is not created, and libpayload
doesn't get stuck.
Change-Id: I08f3ec628e4453f0cfe9e15c4d8dfd40327f91c9
Signed-off-by: Gabe Black <gabeblack@google.com>
Reviewed-on: http://review.coreboot.org/1758
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
2012-09-30 13:47:48 +02:00
|
|
|
// If there isn't any mode info to put in the table, don't ask for it
|
|
|
|
// to be filled with junk.
|
|
|
|
if (!vbe_mode_info_valid())
|
|
|
|
return;
|
2010-02-22 05:33:13 +01:00
|
|
|
struct lb_framebuffer *framebuffer;
|
|
|
|
framebuffer = (struct lb_framebuffer *)lb_new_record(header);
|
2013-11-23 14:46:34 +01:00
|
|
|
fill_lb_framebuffer(framebuffer);
|
2010-02-22 05:33:13 +01:00
|
|
|
framebuffer->tag = LB_TAG_FRAMEBUFFER;
|
|
|
|
framebuffer->size = sizeof(*framebuffer);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-12-22 02:12:38 +01:00
|
|
|
void fill_lb_gpio(struct lb_gpio *gpio, int num,
|
|
|
|
int polarity, const char *name, int value)
|
|
|
|
{
|
|
|
|
memset(gpio, 0, sizeof(*gpio));
|
|
|
|
gpio->port = num;
|
|
|
|
gpio->polarity = polarity;
|
|
|
|
if (value >= 0)
|
|
|
|
gpio->value = value;
|
|
|
|
strncpy((char *)gpio->name, name, GPIO_MAX_NAME_LENGTH);
|
|
|
|
}
|
|
|
|
|
2014-05-03 12:29:06 +02:00
|
|
|
#if CONFIG_CHROMEOS
|
2012-04-05 21:22:02 +02:00
|
|
|
static void lb_gpios(struct lb_header *header)
|
|
|
|
{
|
|
|
|
struct lb_gpios *gpios;
|
2014-09-23 03:48:41 +02:00
|
|
|
|
2012-04-05 21:22:02 +02:00
|
|
|
gpios = (struct lb_gpios *)lb_new_record(header);
|
|
|
|
gpios->tag = LB_TAG_GPIO;
|
|
|
|
gpios->size = sizeof(*gpios);
|
|
|
|
gpios->count = 0;
|
|
|
|
fill_lb_gpios(gpios);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void lb_vdat(struct lb_header *header)
|
|
|
|
{
|
2014-01-03 15:55:40 +01:00
|
|
|
#if CONFIG_HAVE_ACPI_TABLES
|
2013-08-28 00:38:54 +02:00
|
|
|
struct lb_range *vdat;
|
2012-04-05 21:22:02 +02:00
|
|
|
|
2013-08-28 00:38:54 +02:00
|
|
|
vdat = (struct lb_range *)lb_new_record(header);
|
2012-04-05 21:22:02 +02:00
|
|
|
vdat->tag = LB_TAG_VDAT;
|
|
|
|
vdat->size = sizeof(*vdat);
|
2013-08-28 00:38:54 +02:00
|
|
|
acpi_get_vdat_info(&vdat->range_start, &vdat->range_size);
|
2013-03-20 22:08:04 +01:00
|
|
|
#endif
|
2012-04-05 21:22:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void lb_vbnv(struct lb_header *header)
|
|
|
|
{
|
2013-03-20 22:08:04 +01:00
|
|
|
#if CONFIG_PC80_SYSTEM
|
2013-08-28 00:38:54 +02:00
|
|
|
struct lb_range *vbnv;
|
2012-04-05 21:22:02 +02:00
|
|
|
|
2013-08-28 00:38:54 +02:00
|
|
|
vbnv = (struct lb_range *)lb_new_record(header);
|
2012-04-05 21:22:02 +02:00
|
|
|
vbnv->tag = LB_TAG_VBNV;
|
|
|
|
vbnv->size = sizeof(*vbnv);
|
2013-08-28 00:38:54 +02:00
|
|
|
vbnv->range_start = CONFIG_VBNV_OFFSET + 14;
|
|
|
|
vbnv->range_size = CONFIG_VBNV_SIZE;
|
2013-03-20 22:08:04 +01:00
|
|
|
#endif
|
2012-04-05 21:22:02 +02:00
|
|
|
}
|
2013-03-08 06:15:06 +01:00
|
|
|
|
2015-04-22 17:41:42 +02:00
|
|
|
#if CONFIG_VBOOT_VERIFY_FIRMWARE
|
2013-03-08 06:15:06 +01:00
|
|
|
static void lb_vboot_handoff(struct lb_header *header)
|
|
|
|
{
|
|
|
|
void *addr;
|
|
|
|
uint32_t size;
|
2013-08-28 00:38:54 +02:00
|
|
|
struct lb_range *vbho;
|
2013-03-08 06:15:06 +01:00
|
|
|
|
|
|
|
if (vboot_get_handoff_info(&addr, &size))
|
|
|
|
return;
|
|
|
|
|
2013-08-28 00:38:54 +02:00
|
|
|
vbho = (struct lb_range *)lb_new_record(header);
|
2013-03-08 06:15:06 +01:00
|
|
|
vbho->tag = LB_TAB_VBOOT_HANDOFF;
|
|
|
|
vbho->size = sizeof(*vbho);
|
2013-08-28 00:38:54 +02:00
|
|
|
vbho->range_start = (intptr_t)addr;
|
|
|
|
vbho->range_size = size;
|
2013-03-08 06:15:06 +01:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline void lb_vboot_handoff(struct lb_header *header) {}
|
|
|
|
#endif /* CONFIG_VBOOT_VERIFY_FIRMWARE */
|
|
|
|
#endif /* CONFIG_CHROMEOS */
|
2012-04-05 21:22:02 +02:00
|
|
|
|
2014-07-29 01:03:07 +02:00
|
|
|
static void lb_board_id(struct lb_header *header)
|
|
|
|
{
|
2015-03-27 00:29:00 +01:00
|
|
|
#if CONFIG_BOARD_ID_AUTO || CONFIG_BOARD_ID_MANUAL
|
2014-07-29 01:03:07 +02:00
|
|
|
struct lb_board_id *bid;
|
|
|
|
|
|
|
|
bid = (struct lb_board_id *)lb_new_record(header);
|
|
|
|
|
|
|
|
bid->tag = LB_TAG_BOARD_ID;
|
|
|
|
bid->size = sizeof(*bid);
|
|
|
|
bid->board_id = board_id();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-07-14 18:15:51 +02:00
|
|
|
static void lb_boot_media_params(struct lb_header *header)
|
|
|
|
{
|
|
|
|
struct lb_boot_media_params *bmp;
|
|
|
|
struct cbfs_props props;
|
|
|
|
const struct region_device *boot_dev;
|
|
|
|
struct region_device fmrd;
|
|
|
|
|
|
|
|
boot_device_init();
|
|
|
|
|
|
|
|
if (cbfs_boot_region_properties(&props))
|
|
|
|
return;
|
|
|
|
|
|
|
|
boot_dev = boot_device_ro();
|
|
|
|
if (boot_dev == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
bmp = (struct lb_boot_media_params *)lb_new_record(header);
|
|
|
|
bmp->tag = LB_TAG_BOOT_MEDIA_PARAMS;
|
|
|
|
bmp->size = sizeof(*bmp);
|
|
|
|
|
|
|
|
bmp->cbfs_offset = props.offset;
|
|
|
|
bmp->cbfs_size = props.size;
|
|
|
|
bmp->boot_media_size = region_device_sz(boot_dev);
|
|
|
|
|
|
|
|
bmp->fmap_offset = ~(uint64_t)0;
|
|
|
|
if (find_fmap_directory(&fmrd) == 0) {
|
|
|
|
bmp->fmap_offset = region_device_offset(&fmrd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-04 02:42:09 +01:00
|
|
|
static void lb_ram_code(struct lb_header *header)
|
|
|
|
{
|
|
|
|
#if IS_ENABLED(CONFIG_RAM_CODE_SUPPORT)
|
|
|
|
struct lb_ram_code *code;
|
|
|
|
|
|
|
|
code = (struct lb_ram_code *)lb_new_record(header);
|
|
|
|
|
|
|
|
code->tag = LB_TAG_RAM_CODE;
|
|
|
|
code->size = sizeof(*code);
|
|
|
|
code->ram_code = ram_code();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2011-10-03 23:58:57 +02:00
|
|
|
static void add_cbmem_pointers(struct lb_header *header)
|
2011-09-23 18:56:11 +02:00
|
|
|
{
|
2011-10-03 23:58:57 +02:00
|
|
|
/*
|
|
|
|
* These CBMEM sections' addresses are included in the coreboot table
|
|
|
|
* with the appropriate tags.
|
|
|
|
*/
|
|
|
|
const struct section_id {
|
|
|
|
int cbmem_id;
|
|
|
|
int table_tag;
|
|
|
|
} section_ids[] = {
|
|
|
|
{CBMEM_ID_TIMESTAMP, LB_TAG_TIMESTAMPS},
|
2013-12-12 19:43:21 +01:00
|
|
|
{CBMEM_ID_CONSOLE, LB_TAG_CBMEM_CONSOLE},
|
|
|
|
{CBMEM_ID_ACPI_GNVS, LB_TAG_ACPI_GNVS},
|
2014-10-24 00:15:45 +02:00
|
|
|
{CBMEM_ID_WIFI_CALIBRATION, LB_TAG_WIFI_CALIBRATION}
|
2011-10-03 23:58:57 +02:00
|
|
|
};
|
|
|
|
int i;
|
2011-09-23 18:56:11 +02:00
|
|
|
|
2011-10-03 23:58:57 +02:00
|
|
|
for (i = 0; i < ARRAY_SIZE(section_ids); i++) {
|
|
|
|
const struct section_id *sid = section_ids + i;
|
|
|
|
struct lb_cbmem_ref *cbmem_ref;
|
|
|
|
void *cbmem_addr = cbmem_find(sid->cbmem_id);
|
2011-09-23 18:56:11 +02:00
|
|
|
|
2011-10-03 23:58:57 +02:00
|
|
|
if (!cbmem_addr)
|
|
|
|
continue; /* This section is not present */
|
2011-09-23 18:56:11 +02:00
|
|
|
|
2011-10-03 23:58:57 +02:00
|
|
|
cbmem_ref = (struct lb_cbmem_ref *)lb_new_record(header);
|
|
|
|
if (!cbmem_ref) {
|
|
|
|
printk(BIOS_ERR, "No more room in coreboot table!\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cbmem_ref->tag = sid->table_tag;
|
|
|
|
cbmem_ref->size = sizeof(*cbmem_ref);
|
2013-01-11 19:41:42 +01:00
|
|
|
cbmem_ref->cbmem_addr = (unsigned long)cbmem_addr;
|
2011-10-03 23:58:57 +02:00
|
|
|
}
|
2011-09-23 18:56:11 +02:00
|
|
|
}
|
|
|
|
|
2010-01-30 10:47:18 +01:00
|
|
|
static struct lb_mainboard *lb_mainboard(struct lb_header *header)
|
2003-04-22 21:02:15 +02:00
|
|
|
{
|
|
|
|
struct lb_record *rec;
|
|
|
|
struct lb_mainboard *mainboard;
|
|
|
|
rec = lb_new_record(header);
|
|
|
|
mainboard = (struct lb_mainboard *)rec;
|
|
|
|
mainboard->tag = LB_TAG_MAINBOARD;
|
|
|
|
|
|
|
|
mainboard->size = (sizeof(*mainboard) +
|
2010-04-27 08:56:47 +02:00
|
|
|
strlen(mainboard_vendor) + 1 +
|
2003-04-22 21:02:15 +02:00
|
|
|
strlen(mainboard_part_number) + 1 +
|
|
|
|
3) & ~3;
|
|
|
|
|
|
|
|
mainboard->vendor_idx = 0;
|
|
|
|
mainboard->part_number_idx = strlen(mainboard_vendor) + 1;
|
|
|
|
|
|
|
|
memcpy(mainboard->strings + mainboard->vendor_idx,
|
|
|
|
mainboard_vendor, strlen(mainboard_vendor) + 1);
|
|
|
|
memcpy(mainboard->strings + mainboard->part_number_idx,
|
|
|
|
mainboard_part_number, strlen(mainboard_part_number) + 1);
|
|
|
|
|
|
|
|
return mainboard;
|
|
|
|
}
|
|
|
|
|
2015-09-21 20:11:47 +02:00
|
|
|
#if CONFIG_USE_OPTION_TABLE
|
|
|
|
static struct cmos_checksum *lb_cmos_checksum(struct lb_header *header)
|
|
|
|
{
|
|
|
|
struct lb_record *rec;
|
|
|
|
struct cmos_checksum *cmos_checksum;
|
|
|
|
rec = lb_new_record(header);
|
|
|
|
cmos_checksum = (struct cmos_checksum *)rec;
|
|
|
|
cmos_checksum->tag = LB_TAG_OPTION_CHECKSUM;
|
|
|
|
|
|
|
|
cmos_checksum->size = (sizeof(*cmos_checksum));
|
|
|
|
|
|
|
|
cmos_checksum->range_start = LB_CKS_RANGE_START * 8;
|
|
|
|
cmos_checksum->range_end = ( LB_CKS_RANGE_END * 8 ) + 7;
|
|
|
|
cmos_checksum->location = LB_CKS_LOC * 8;
|
|
|
|
cmos_checksum->type = CHECKSUM_PCBIOS;
|
|
|
|
|
|
|
|
return cmos_checksum;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-08-27 13:23:06 +02:00
|
|
|
static void lb_strings(struct lb_header *header)
|
2003-04-22 21:02:15 +02:00
|
|
|
{
|
|
|
|
static const struct {
|
|
|
|
uint32_t tag;
|
2007-10-24 00:17:45 +02:00
|
|
|
const char *string;
|
2003-04-22 21:02:15 +02:00
|
|
|
} strings[] = {
|
2008-01-18 16:08:58 +01:00
|
|
|
{ LB_TAG_VERSION, coreboot_version, },
|
|
|
|
{ LB_TAG_EXTRA_VERSION, coreboot_extra_version, },
|
|
|
|
{ LB_TAG_BUILD, coreboot_build, },
|
|
|
|
{ LB_TAG_COMPILE_TIME, coreboot_compile_time, },
|
2003-04-22 21:02:15 +02:00
|
|
|
};
|
2003-05-19 21:16:21 +02:00
|
|
|
unsigned int i;
|
2008-10-01 14:52:52 +02:00
|
|
|
for(i = 0; i < ARRAY_SIZE(strings); i++) {
|
2003-04-22 21:02:15 +02:00
|
|
|
struct lb_string *rec;
|
|
|
|
size_t len;
|
|
|
|
rec = (struct lb_string *)lb_new_record(header);
|
|
|
|
len = strlen(strings[i].string);
|
|
|
|
rec->tag = strings[i].tag;
|
|
|
|
rec->size = (sizeof(*rec) + len + 1 + 3) & ~3;
|
|
|
|
memcpy(rec->string, strings[i].string, len+1);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-08-23 01:08:09 +02:00
|
|
|
static void lb_record_version_timestamp(struct lb_header *header)
|
|
|
|
{
|
|
|
|
struct lb_timestamp *rec;
|
|
|
|
rec = (struct lb_timestamp *)lb_new_record(header);
|
|
|
|
rec->tag = LB_TAG_VERSION_TIMESTAMP;
|
|
|
|
rec->size = sizeof(*rec);
|
|
|
|
rec->timestamp = coreboot_version_timestamp;
|
|
|
|
}
|
|
|
|
|
2013-08-28 00:48:32 +02:00
|
|
|
void __attribute__((weak)) lb_board(struct lb_header *header) { /* NOOP */ }
|
|
|
|
|
2009-08-27 13:23:06 +02:00
|
|
|
static struct lb_forward *lb_forward(struct lb_header *header, struct lb_header *next_header)
|
2009-03-17 15:38:48 +01:00
|
|
|
{
|
|
|
|
struct lb_record *rec;
|
|
|
|
struct lb_forward *forward;
|
|
|
|
rec = lb_new_record(header);
|
|
|
|
forward = (struct lb_forward *)rec;
|
|
|
|
forward->tag = LB_TAG_FORWARD;
|
|
|
|
forward->size = sizeof(*forward);
|
2009-04-06 16:00:53 +02:00
|
|
|
forward->forward = (uint64_t)(unsigned long)next_header;
|
2009-03-17 15:38:48 +01:00
|
|
|
return forward;
|
|
|
|
}
|
|
|
|
|
2013-03-23 06:06:36 +01:00
|
|
|
static unsigned long lb_table_fini(struct lb_header *head)
|
2003-04-22 21:02:15 +02:00
|
|
|
{
|
|
|
|
struct lb_record *rec, *first_rec;
|
|
|
|
rec = lb_last_record(head);
|
|
|
|
if (head->table_entries) {
|
|
|
|
head->table_bytes += rec->size;
|
|
|
|
}
|
2009-03-17 15:38:48 +01:00
|
|
|
|
2003-04-22 21:02:15 +02:00
|
|
|
first_rec = lb_first_record(head);
|
|
|
|
head->table_checksum = compute_ip_checksum(first_rec, head->table_bytes);
|
|
|
|
head->header_checksum = 0;
|
|
|
|
head->header_checksum = compute_ip_checksum(head, sizeof(*head));
|
2011-08-16 20:44:35 +02:00
|
|
|
printk(BIOS_DEBUG,
|
|
|
|
"Wrote coreboot table at: %p, 0x%x bytes, checksum %x\n",
|
|
|
|
head, head->table_bytes, head->table_checksum);
|
|
|
|
return (unsigned long)rec + rec->size;
|
2003-04-22 21:02:15 +02:00
|
|
|
}
|
|
|
|
|
2010-04-27 08:56:47 +02:00
|
|
|
unsigned long write_coreboot_table(
|
|
|
|
unsigned long low_table_start, unsigned long low_table_end,
|
2006-07-19 17:32:49 +02:00
|
|
|
unsigned long rom_table_start, unsigned long rom_table_end)
|
2003-04-22 21:02:15 +02:00
|
|
|
{
|
|
|
|
struct lb_header *head;
|
|
|
|
|
2013-03-20 22:08:04 +01:00
|
|
|
if (low_table_start || low_table_end) {
|
|
|
|
printk(BIOS_DEBUG, "Writing table forward entry at 0x%08lx\n",
|
|
|
|
low_table_end);
|
|
|
|
head = lb_table_init(low_table_end);
|
|
|
|
lb_forward(head, (struct lb_header*)rom_table_end);
|
|
|
|
|
2013-03-23 06:06:36 +01:00
|
|
|
low_table_end = (unsigned long) lb_table_fini(head);
|
2013-03-20 22:08:04 +01:00
|
|
|
printk(BIOS_DEBUG, "Table forward entry ends at 0x%08lx.\n",
|
2009-03-17 15:38:48 +01:00
|
|
|
low_table_end);
|
2013-03-20 22:08:04 +01:00
|
|
|
low_table_end = ALIGN(low_table_end, 4096);
|
|
|
|
printk(BIOS_DEBUG, "... aligned to 0x%08lx\n", low_table_end);
|
|
|
|
}
|
2009-03-17 15:38:48 +01:00
|
|
|
|
2013-03-20 22:08:04 +01:00
|
|
|
printk(BIOS_DEBUG, "Writing coreboot table at 0x%08lx\n",
|
|
|
|
rom_table_end);
|
2010-04-27 08:56:47 +02:00
|
|
|
|
2009-03-17 15:38:48 +01:00
|
|
|
head = lb_table_init(rom_table_end);
|
|
|
|
rom_table_end = (unsigned long)head;
|
2010-03-22 12:42:32 +01:00
|
|
|
printk(BIOS_DEBUG, "rom_table_end = 0x%08lx\n", rom_table_end);
|
2013-03-20 22:08:04 +01:00
|
|
|
rom_table_end = ALIGN(rom_table_end, (64 * 1024));
|
|
|
|
printk(BIOS_DEBUG, "... aligned to 0x%08lx\n", rom_table_end);
|
2006-07-19 17:32:49 +02:00
|
|
|
|
2011-08-15 20:26:35 +02:00
|
|
|
#if CONFIG_USE_OPTION_TABLE
|
2007-04-06 14:14:51 +02:00
|
|
|
{
|
2015-05-16 06:39:23 +02:00
|
|
|
struct cmos_option_table *option_table =
|
|
|
|
cbfs_boot_map_with_leak("cmos_layout.bin",
|
2014-01-12 13:45:52 +01:00
|
|
|
CBFS_COMPONENT_CMOS_LAYOUT, NULL);
|
2011-01-18 14:56:36 +01:00
|
|
|
if (option_table) {
|
|
|
|
struct lb_record *rec_dest = lb_new_record(head);
|
|
|
|
/* Copy the option config table, it's already a lb_record... */
|
2011-01-24 22:07:57 +01:00
|
|
|
memcpy(rec_dest, option_table, option_table->size);
|
2015-09-21 20:11:47 +02:00
|
|
|
/* Create cmos checksum entry in coreboot table */
|
|
|
|
lb_cmos_checksum(head);
|
2011-01-18 15:28:45 +01:00
|
|
|
} else {
|
|
|
|
printk(BIOS_ERR, "cmos_layout.bin could not be found!\n");
|
2011-01-18 14:56:36 +01:00
|
|
|
}
|
2004-10-27 10:53:57 +02:00
|
|
|
}
|
2007-04-06 14:14:51 +02:00
|
|
|
#endif
|
2013-03-20 22:08:04 +01:00
|
|
|
|
2014-02-19 04:55:02 +01:00
|
|
|
/* Initialize the memory map at boot time. */
|
|
|
|
bootmem_init();
|
2010-04-27 08:56:47 +02:00
|
|
|
|
2013-03-20 22:08:04 +01:00
|
|
|
if (low_table_start || low_table_end) {
|
2014-02-19 04:55:02 +01:00
|
|
|
uint64_t size = low_table_end - low_table_start;
|
2013-03-20 22:08:04 +01:00
|
|
|
/* Record the mptable and the the lb_table.
|
|
|
|
* (This will be adjusted later) */
|
2014-02-19 04:55:02 +01:00
|
|
|
bootmem_add_range(low_table_start, size, LB_MEM_TABLE);
|
2013-03-20 22:08:04 +01:00
|
|
|
}
|
2004-10-27 10:53:57 +02:00
|
|
|
|
2013-03-13 18:41:44 +01:00
|
|
|
/* Record the pirq table, acpi tables, and maybe the mptable. However,
|
|
|
|
* these only need to be added when the rom_table is sitting below
|
|
|
|
* 1MiB. If it isn't that means high tables are being written.
|
|
|
|
* The code below handles high tables correctly. */
|
2014-02-19 04:55:02 +01:00
|
|
|
if (rom_table_end <= (1 << 20)) {
|
|
|
|
uint64_t size = rom_table_end - rom_table_start;
|
|
|
|
bootmem_add_range(rom_table_start, size, LB_MEM_TABLE);
|
|
|
|
}
|
2009-04-28 14:57:25 +02:00
|
|
|
|
2013-03-23 06:06:36 +01:00
|
|
|
/* No other memory areas can be added after the memory table has been
|
|
|
|
* committed as the entries won't show up in the serialize mem table. */
|
2014-02-25 07:24:22 +01:00
|
|
|
bootmem_write_memory_table(lb_memory(head));
|
2003-04-22 21:02:15 +02:00
|
|
|
|
2008-01-25 19:28:18 +01:00
|
|
|
/* Record our motherboard */
|
2003-04-22 21:02:15 +02:00
|
|
|
lb_mainboard(head);
|
2014-03-15 00:32:55 +01:00
|
|
|
|
|
|
|
/* Record the serial ports and consoles */
|
2014-02-13 16:16:22 +01:00
|
|
|
#if CONFIG_CONSOLE_SERIAL
|
2014-03-15 00:32:55 +01:00
|
|
|
uart_fill_lb(head);
|
|
|
|
#endif
|
|
|
|
#if CONFIG_CONSOLE_USB
|
|
|
|
lb_add_console(LB_TAG_CONSOLE_EHCI, head);
|
|
|
|
#endif
|
|
|
|
|
2003-04-22 21:02:15 +02:00
|
|
|
/* Record our various random string information */
|
|
|
|
lb_strings(head);
|
2014-08-23 01:08:09 +02:00
|
|
|
lb_record_version_timestamp(head);
|
2010-02-22 05:33:13 +01:00
|
|
|
/* Record our framebuffer */
|
|
|
|
lb_framebuffer(head);
|
2003-04-22 21:02:15 +02:00
|
|
|
|
2012-04-05 21:22:02 +02:00
|
|
|
#if CONFIG_CHROMEOS
|
|
|
|
/* Record our GPIO settings (ChromeOS specific) */
|
|
|
|
lb_gpios(head);
|
|
|
|
|
2013-07-10 05:51:14 +02:00
|
|
|
/* pass along the VDAT buffer address */
|
2012-04-05 21:22:02 +02:00
|
|
|
lb_vdat(head);
|
|
|
|
|
|
|
|
/* pass along VBNV offsets in CMOS */
|
|
|
|
lb_vbnv(head);
|
2013-03-08 06:15:06 +01:00
|
|
|
|
|
|
|
/* pass along the vboot_handoff address. */
|
|
|
|
lb_vboot_handoff(head);
|
2012-04-05 21:22:02 +02:00
|
|
|
#endif
|
2014-07-29 01:03:07 +02:00
|
|
|
|
|
|
|
/* Add board ID if available */
|
|
|
|
lb_board_id(head);
|
|
|
|
|
2014-11-04 02:42:09 +01:00
|
|
|
/* Add RAM config if available */
|
|
|
|
lb_ram_code(head);
|
|
|
|
|
2015-01-08 19:29:19 +01:00
|
|
|
#if IS_ENABLED(CONFIG_SPI_FLASH)
|
|
|
|
/* Add SPI flash description if available */
|
|
|
|
lb_spi_flash(head);
|
|
|
|
#endif
|
|
|
|
|
2011-10-03 23:58:57 +02:00
|
|
|
add_cbmem_pointers(head);
|
|
|
|
|
2013-08-28 00:48:32 +02:00
|
|
|
/* Add board-specific table entries, if any. */
|
|
|
|
lb_board(head);
|
|
|
|
|
2014-11-09 02:34:27 +01:00
|
|
|
#if IS_ENABLED(CONFIG_CHROMEOS_RAMOOPS)
|
|
|
|
lb_ramoops(head);
|
|
|
|
#endif
|
|
|
|
|
2015-07-14 18:15:51 +02:00
|
|
|
lb_boot_media_params(head);
|
|
|
|
|
2003-04-22 21:02:15 +02:00
|
|
|
/* Remember where my valid memory ranges are */
|
2013-03-23 06:06:36 +01:00
|
|
|
return lb_table_fini(head);
|
2003-04-22 21:02:15 +02:00
|
|
|
}
|