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.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
|
|
* MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
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>
|
2003-04-22 21:02:15 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <version.h>
|
2004-10-14 22:54:17 +02:00
|
|
|
#include <device/device.h>
|
|
|
|
#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>
|
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;
|
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;
|
|
|
|
}
|
|
|
|
|
2010-02-22 05:33:13 +01:00
|
|
|
static void lb_framebuffer(struct lb_header *header)
|
|
|
|
{
|
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;
|
|
|
|
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
|
|
|
|
|
|
|
#if CONFIG_VBOOT_VERIFY_FIRMWARE
|
|
|
|
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
|
|
|
|
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},
|
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;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
Extend CBFS to support arbitrary ROM source media.
Summary:
Isolate CBFS underlying I/O to board/arch-specific implementations as
"media stream", to allow loading and booting romstage on non-x86.
CBFS functions now all take a new "media source" parameter; use
CBFS_DEFAULT_MEDIA if you simply want to load from main firmware.
API Changes:
cbfs_find => cbfs_get_file.
cbfs_find_file => cbfs_get_file_content.
cbfs_get_file => cbfs_get_file_content with correct type.
CBFS used to work only on memory-mapped ROM (all x86). For platforms like ARM,
the ROM may come from USB, UART, or SPI -- any serial devices and not available
for memory mapping.
To support these devices (and allowing CBFS to read from multiple source
at the same time), CBFS operations are now virtual-ized into "cbfs_media". To
simplify porting existing code, every media source must support both "reading
into pre-allocated memory (read)" and "read and return an allocated buffer
(map)". For devices without native memory-mapped ROM, "cbfs_simple_buffer*"
provides simple memory mapping simulation.
Every CBFS function now takes a cbfs_media* as parameter. CBFS_DEFAULT_MEDIA
is defined for CBFS functions to automatically initialize a per-board default
media (CBFS will internally calls init_default_cbfs_media). Also revised CBFS
function names relying on memory mapped backend (ex, "cbfs_find" => actually
loads files). Now we only have two getters:
struct cbfs_file *entry = cbfs_get_file(media, name);
void *data = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, name, type);
Test results:
- Verified to work on x86/qemu.
- Compiles on ARM, and follow up commit will provide working SPI driver.
Change-Id: Iac911ded25a6f2feffbf3101a81364625bb07746
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: http://review.coreboot.org/2182
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
2013-01-22 11:57:56 +01:00
|
|
|
struct cmos_option_table *option_table = cbfs_get_file_content(
|
|
|
|
CBFS_DEFAULT_MEDIA, "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);
|
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
|
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);
|
|
|
|
|
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
|
|
|
}
|