coreboot-kgpe-d16/src/lib/coreboot_table.c

602 lines
15 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0-only */
#include <arch/cbconfig.h>
#include <console/console.h>
#include <console/uart.h>
#include <ip_checksum.h>
#include <boot/coreboot_tables.h>
#include <boot/tables.h>
#include <boot_device.h>
#include <string.h>
#include <version.h>
#include <boardid.h>
#include <device/device.h>
#include <fmap.h>
#include <stdlib.h>
#include <cbfs.h>
#include <cbmem.h>
#include <bootmem.h>
#include <bootsplash.h>
drivers/spi: Pass flash parameters from coreboot to payload A payload may want to run erase operations on SPI NOR flash without re-probing the device to get its properties. This patch passes up three properties of flash to achieve that: - The size of the flash device - The sector size, i.e., the granularity of erase - The command used for erase The patch sends the parameters through coreboot and then libpayload. The patch also includes a minor refactoring of the flash erase code. Parameters are sent up for just one flash device. If multiple SPI flash devices are probed, the second one will "win" and its parameters will be sent up to the payload. TEST=Observed parameters to be passed up to depthcharge through libpayload and be used to correctly initialize flash and do an erase. TEST=Winbond and Gigadevices spi flash drivers compile with the changes; others don't, for seemingly unrelated reasons. BRANCH=none BUG=chromium:446377 Change-Id: Ib8be86494b5a3d1cfe1d23d3492e3b5cba5f99c6 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: 988c8c68bbfcdfa69d497ea5f806567bc80f8126 Original-Change-Id: Ie2b3a7f5b6e016d212f4f9bac3fabd80daf2ce72 Original-Signed-off-by: Dan Ehrenberg <dehrenberg@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/239570 Original-Reviewed-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: http://review.coreboot.org/9726 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
2015-01-08 19:29:19 +01:00
#include <spi_flash.h>
#include <security/vboot/misc.h>
#include <security/vboot/vbnv_layout.h>
#if CONFIG(USE_OPTION_TABLE)
#include <option_table.h>
#endif
#if CONFIG(CHROMEOS)
#if CONFIG(HAVE_ACPI_TABLES)
#include <acpi/acpi.h>
#endif
#include <vendorcode/google/chromeos/chromeos.h>
#include <vendorcode/google/chromeos/gnvs.h>
#endif
#if CONFIG(PLATFORM_USES_FSP2_0)
#include <fsp/util.h>
#else
void lb_string_platform_blob_version(struct lb_header *header);
#endif
static struct lb_header *lb_table_init(unsigned long addr)
{
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;
}
static struct lb_record *lb_first_record(struct lb_header *header)
{
struct lb_record *rec;
rec = (void *)(((char *)header) + sizeof(*header));
return rec;
}
static struct lb_record *lb_last_record(struct lb_header *header)
{
struct lb_record *rec;
rec = (void *)(((char *)header) + sizeof(*header)
+ header->table_bytes);
return rec;
}
arm: libpayload: Add cache coherent DMA memory definition and management This patch adds a mechanism to set aside a region of cache-coherent (i.e. usually uncached) virtual memory, which can be used to communicate with DMA devices without automatic cache snooping (common on ARM) without the need of explicit flush/invalidation instructions in the driver code. This works by setting aside said region in the (board-specific) page table setup, as exemplary done in this patch for the Snow and Pit boards. It uses a new mechanism for adding board-specific Coreboot table entries to describe this region in an entry with the LB_DMA tag. Libpayload's memory allocator is enhanced to be able to operate on distinct types/regions of memory. It provides dma_malloc() and dma_memalign() functions for use in drivers, which by default just operate on the same heap as their traditional counterparts. However, if the Coreboot table parsing code finds a CB_DMA section, further requests through the dma_xxx() functions will return memory from the region described therein instead. Change-Id: Ia9c249249e936bbc3eb76e7b4822af2230ffb186 Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/167155 (cherry picked from commit d142ccdcd902a9d6ab4d495fbe6cbe85c61a5f01) Signed-off-by: Isaac Christensen <isaac.christensen@se-eng.com> Reviewed-on: http://review.coreboot.org/6622 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
2013-08-28 00:48:32 +02:00
struct lb_record *lb_new_record(struct lb_header *header)
{
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;
}
static struct lb_memory *lb_memory(struct lb_header *header)
{
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;
}
void lb_add_serial(struct lb_serial *new_serial, void *data)
{
struct lb_header *header = (struct lb_header *)data;
struct lb_serial *serial;
serial = (struct lb_serial *)lb_new_record(header);
serial->tag = LB_TAG_SERIAL;
serial->size = sizeof(*serial);
serial->type = new_serial->type;
serial->baseaddr = new_serial->baseaddr;
serial->baud = new_serial->baud;
serial->regwidth = new_serial->regwidth;
coreboot_tables: Extend serial port description Extend the serial port description to include the input clock frequency and a payload specific value. Without the input frequency it is impossible for the payload to compute the baud-rate divisor without making an assumption about the frequency. This breaks down when the UART is able to support multiple input clock frequencies. Add the UART_PCI_ADDR Kconfig value to specify the unique PCI device being used as the console UART. Specify this value as zero when the UART is not on the PCI bus. Otherwise specify the device using bus, device and function along with setting the valid bit. Currently the only payload to consume these new fields is the EDK-II CorebootPayloadPkg. Testing on Galileo: * Edit the src/mainboard/intel/galileo/Makefile.inc file: * Add "select ADD_FSP_PDAT_FILE" * Add "select ADD_FSP_RAW_BIN" * Add "select ADD_RMU_FILE" * Place the FSP.bin file in the location specified by CONFIG_FSP_FILE * Place the pdat.bin files in the location specified by CONFIG_FSP_PDAT_FILE * Place the rmu.bin file in the location specified by CONFIG_RMU_FILE * Build EDK2 CorebootPayloadPkg/CorebootPayloadPkgIa32.dsc to generate UEFIPAYLOAD.fd * Testing is successful when CorebootPayloadPkg is able to properly initialize the serial port without using built-in values. Change-Id: Id4b4455bbf9583f0d66c315d38c493a81fd852a8 Signed-off-by: Lee Leahy <leroy.p.leahy@intel.com> Reviewed-on: https://review.coreboot.org/14609 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth <martinroth@google.com>
2016-05-04 20:59:19 +02:00
serial->input_hertz = new_serial->input_hertz;
serial->uart_pci_addr = new_serial->uart_pci_addr;
}
void lb_add_console(uint16_t consoletype, void *data)
{
struct lb_header *header = (struct lb_header *)data;
struct lb_console *console;
console = (struct lb_console *)lb_new_record(header);
console->tag = LB_TAG_CONSOLE;
console->size = sizeof(*console);
console->type = consoletype;
}
static void lb_framebuffer(struct lb_header *header)
{
struct lb_framebuffer *framebuffer;
struct lb_framebuffer fb = {0};
if (!CONFIG(LINEAR_FRAMEBUFFER) || fill_lb_framebuffer(&fb))
return;
framebuffer = (struct lb_framebuffer *)lb_new_record(header);
memcpy(framebuffer, &fb, sizeof(*framebuffer));
framebuffer->tag = LB_TAG_FRAMEBUFFER;
framebuffer->size = sizeof(*framebuffer);
if (CONFIG(BOOTSPLASH)) {
uint8_t *fb_ptr = (uint8_t *)(uintptr_t)framebuffer->physical_address;
unsigned int width = framebuffer->x_resolution;
unsigned int height = framebuffer->y_resolution;
unsigned int depth = framebuffer->bits_per_pixel;
set_bootsplash(fb_ptr, width, height, depth);
}
}
void lb_add_gpios(struct lb_gpios *gpios, const struct lb_gpio *gpio_table,
size_t count)
{
size_t table_size = count * sizeof(struct lb_gpio);
memcpy(&gpios->gpios[gpios->count], gpio_table, table_size);
gpios->count += count;
gpios->size += table_size;
}
#if CONFIG(CHROMEOS)
static void lb_gpios(struct lb_header *header)
{
struct lb_gpios *gpios;
struct lb_gpio *g;
gpios = (struct lb_gpios *)lb_new_record(header);
gpios->tag = LB_TAG_GPIO;
gpios->size = sizeof(*gpios);
gpios->count = 0;
fill_lb_gpios(gpios);
printk(BIOS_INFO, "Passing %u GPIOs to payload:\n"
" NAME | PORT | POLARITY | VALUE\n",
gpios->count);
for (g = &gpios->gpios[0]; g < &gpios->gpios[gpios->count]; g++) {
printk(BIOS_INFO, "%16s | ", g->name);
if (g->port == -1)
printk(BIOS_INFO, " undefined | ");
else
printk(BIOS_INFO, "%#.8x | ", g->port);
if (g->polarity == ACTIVE_HIGH)
printk(BIOS_INFO, " high | ");
else
printk(BIOS_INFO, " low | ");
switch (g->value) {
case 0:
printk(BIOS_INFO, " low\n");
break;
case 1:
printk(BIOS_INFO, " high\n");
break;
default:
printk(BIOS_INFO, "undefined\n");
break;
}
}
}
static void lb_vbnv(struct lb_header *header)
{
#if CONFIG(PC80_SYSTEM)
struct lb_range *vbnv;
vbnv = (struct lb_range *)lb_new_record(header);
vbnv->tag = LB_TAG_VBNV;
vbnv->size = sizeof(*vbnv);
vbnv->range_start = CONFIG_VBOOT_VBNV_OFFSET + 14;
vbnv->range_size = VBOOT_VBNV_BLOCK_SIZE;
#endif
}
#endif /* CONFIG_CHROMEOS */
__weak uint32_t board_id(void) { return UNDEFINED_STRAPPING_ID; }
__weak uint32_t ram_code(void) { return UNDEFINED_STRAPPING_ID; }
__weak uint32_t sku_id(void) { return UNDEFINED_STRAPPING_ID; }
static void lb_board_id(struct lb_header *header)
{
struct lb_strapping_id *rec;
uint32_t bid = board_id();
if (bid == UNDEFINED_STRAPPING_ID)
return;
rec = (struct lb_strapping_id *)lb_new_record(header);
rec->tag = LB_TAG_BOARD_ID;
rec->size = sizeof(*rec);
rec->id_code = bid;
printk(BIOS_INFO, "Board ID: %d\n", bid);
}
static void lb_boot_media_params(struct lb_header *header)
{
struct lb_boot_media_params *bmp;
const struct region_device *boot_dev;
struct region_device cbfs_dev;
boot_device_init();
if (cbfs_boot_region_device(&cbfs_dev))
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 = region_device_offset(&cbfs_dev);
bmp->cbfs_size = region_device_sz(&cbfs_dev);
bmp->boot_media_size = region_device_sz(boot_dev);
bmp->fmap_offset = get_fmap_flash_offset();
}
static void lb_ram_code(struct lb_header *header)
{
struct lb_strapping_id *rec;
uint32_t code = ram_code();
if (code == UNDEFINED_STRAPPING_ID)
return;
rec = (struct lb_strapping_id *)lb_new_record(header);
rec->tag = LB_TAG_RAM_CODE;
rec->size = sizeof(*rec);
rec->id_code = code;
printk(BIOS_INFO, "RAM code: %d\n", code);
}
static void lb_sku_id(struct lb_header *header)
{
struct lb_strapping_id *rec;
uint32_t sid = sku_id();
if (sid == UNDEFINED_STRAPPING_ID)
return;
rec = (struct lb_strapping_id *)lb_new_record(header);
rec->tag = LB_TAG_SKU_ID;
rec->size = sizeof(*rec);
rec->id_code = sid;
printk(BIOS_INFO, "SKU ID: %d\n", sid);
}
static void lb_mmc_info(struct lb_header *header)
{
struct lb_mmc_info *rec;
int32_t *ms_cbmem;
ms_cbmem = cbmem_find(CBMEM_ID_MMC_STATUS);
if (!ms_cbmem)
return;
rec = (struct lb_mmc_info *)lb_new_record(header);
rec->tag = LB_TAG_MMC_INFO;
rec->size = sizeof(*rec);
rec->early_cmd1_status = *ms_cbmem;
}
static void add_cbmem_pointers(struct lb_header *header)
{
/*
* 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},
{CBMEM_ID_CONSOLE, LB_TAG_CBMEM_CONSOLE},
{CBMEM_ID_ACPI_GNVS, LB_TAG_ACPI_GNVS},
{CBMEM_ID_VPD, LB_TAG_VPD},
{CBMEM_ID_WIFI_CALIBRATION, LB_TAG_WIFI_CALIBRATION},
{CBMEM_ID_TCPA_LOG, LB_TAG_TCPA_LOG},
{CBMEM_ID_FMAP, LB_TAG_FMAP},
{CBMEM_ID_VBOOT_WORKBUF, LB_TAG_VBOOT_WORKBUF},
};
int i;
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);
if (!cbmem_addr)
continue; /* This section is not present */
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);
cbmem_ref->cbmem_addr = (unsigned long)cbmem_addr;
}
}
static struct lb_mainboard *lb_mainboard(struct lb_header *header)
{
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 = ALIGN_UP(sizeof(*mainboard) +
strlen(mainboard_vendor) + 1 +
strlen(mainboard_part_number) + 1, 8);
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;
}
#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
static void lb_strings(struct lb_header *header)
{
static const struct {
uint32_t tag;
const char *string;
} strings[] = {
{ LB_TAG_VERSION, coreboot_version, },
{ LB_TAG_EXTRA_VERSION, coreboot_extra_version, },
{ LB_TAG_BUILD, coreboot_build, },
{ LB_TAG_COMPILE_TIME, coreboot_compile_time, },
};
unsigned int i;
for (i = 0; i < ARRAY_SIZE(strings); i++) {
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 = ALIGN_UP(sizeof(*rec) + len + 1, 8);
memcpy(rec->string, strings[i].string, len+1);
}
}
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;
}
void __weak lb_board(struct lb_header *header) { /* NOOP */ }
arm: libpayload: Add cache coherent DMA memory definition and management This patch adds a mechanism to set aside a region of cache-coherent (i.e. usually uncached) virtual memory, which can be used to communicate with DMA devices without automatic cache snooping (common on ARM) without the need of explicit flush/invalidation instructions in the driver code. This works by setting aside said region in the (board-specific) page table setup, as exemplary done in this patch for the Snow and Pit boards. It uses a new mechanism for adding board-specific Coreboot table entries to describe this region in an entry with the LB_DMA tag. Libpayload's memory allocator is enhanced to be able to operate on distinct types/regions of memory. It provides dma_malloc() and dma_memalign() functions for use in drivers, which by default just operate on the same heap as their traditional counterparts. However, if the Coreboot table parsing code finds a CB_DMA section, further requests through the dma_xxx() functions will return memory from the region described therein instead. Change-Id: Ia9c249249e936bbc3eb76e7b4822af2230ffb186 Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/167155 (cherry picked from commit d142ccdcd902a9d6ab4d495fbe6cbe85c61a5f01) Signed-off-by: Isaac Christensen <isaac.christensen@se-eng.com> Reviewed-on: http://review.coreboot.org/6622 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
2013-08-28 00:48:32 +02:00
/*
* It's possible that the system is using a SPI flash as the boot device,
* however it is not probing for devices to fill in specifics. In that
* case don't provide any information as the correct information is
* not known.
*/
void __weak lb_spi_flash(struct lb_header *header) { /* NOOP */ }
static struct lb_forward *lb_forward(struct lb_header *header,
struct lb_header *next_header)
{
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);
forward->forward = (uint64_t)(unsigned long)next_header;
return forward;
}
static unsigned long lb_table_fini(struct lb_header *head)
{
struct lb_record *rec, *first_rec;
rec = lb_last_record(head);
if (head->table_entries)
head->table_bytes += rec->size;
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));
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;
}
size_t write_coreboot_forwarding_table(uintptr_t entry, uintptr_t target)
{
struct lb_header *head;
printk(BIOS_DEBUG, "Writing table forward entry at %p\n",
(void *)entry);
head = lb_table_init(entry);
lb_forward(head, (struct lb_header *)target);
return (uintptr_t)lb_table_fini(head) - entry;
}
static uintptr_t write_coreboot_table(uintptr_t rom_table_end)
{
struct lb_header *head;
printk(BIOS_DEBUG, "Writing coreboot table at 0x%08lx\n",
(long)rom_table_end);
head = lb_table_init(rom_table_end);
#if CONFIG(USE_OPTION_TABLE)
{
struct cmos_option_table *option_table =
cbfs_boot_map_with_leak("cmos_layout.bin",
CBFS_COMPONENT_CMOS_LAYOUT, NULL);
if (option_table) {
struct lb_record *rec_dest = lb_new_record(head);
/* Copy the option config table, it's already a
* lb_record...
*/
memcpy(rec_dest, option_table, option_table->size);
/* Create CMOS checksum entry in coreboot table */
lb_cmos_checksum(head);
} else {
printk(BIOS_ERR,
"cmos_layout.bin could not be found!\n");
}
}
#endif
/* Serialize resource map into mem table types (LB_MEM_*) */
bootmem_write_memory_table(lb_memory(head));
/* Record our motherboard */
lb_mainboard(head);
/* Record the serial ports and consoles */
#if CONFIG(CONSOLE_SERIAL)
uart_fill_lb(head);
#endif
#if CONFIG(CONSOLE_USB)
lb_add_console(LB_TAG_CONSOLE_EHCI, head);
#endif
/* Record our various random string information */
lb_strings(head);
if (CONFIG(PLATFORM_USES_FSP2_0))
lb_string_platform_blob_version(head);
lb_record_version_timestamp(head);
/* Record our framebuffer */
lb_framebuffer(head);
#if CONFIG(CHROMEOS)
/* Record our GPIO settings (ChromeOS specific) */
lb_gpios(head);
/* pass along VBNV offsets in CMOS */
lb_vbnv(head);
#endif
/* Add strapping IDs if available */
lb_board_id(head);
lb_ram_code(head);
lb_sku_id(head);
/* Pass mmc early init status */
lb_mmc_info(head);
drivers/spi: Pass flash parameters from coreboot to payload A payload may want to run erase operations on SPI NOR flash without re-probing the device to get its properties. This patch passes up three properties of flash to achieve that: - The size of the flash device - The sector size, i.e., the granularity of erase - The command used for erase The patch sends the parameters through coreboot and then libpayload. The patch also includes a minor refactoring of the flash erase code. Parameters are sent up for just one flash device. If multiple SPI flash devices are probed, the second one will "win" and its parameters will be sent up to the payload. TEST=Observed parameters to be passed up to depthcharge through libpayload and be used to correctly initialize flash and do an erase. TEST=Winbond and Gigadevices spi flash drivers compile with the changes; others don't, for seemingly unrelated reasons. BRANCH=none BUG=chromium:446377 Change-Id: Ib8be86494b5a3d1cfe1d23d3492e3b5cba5f99c6 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: 988c8c68bbfcdfa69d497ea5f806567bc80f8126 Original-Change-Id: Ie2b3a7f5b6e016d212f4f9bac3fabd80daf2ce72 Original-Signed-off-by: Dan Ehrenberg <dehrenberg@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/239570 Original-Reviewed-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: http://review.coreboot.org/9726 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
2015-01-08 19:29:19 +01:00
/* Add SPI flash description if available */
if (CONFIG(BOOT_DEVICE_SPI_FLASH))
lb_spi_flash(head);
drivers/spi: Pass flash parameters from coreboot to payload A payload may want to run erase operations on SPI NOR flash without re-probing the device to get its properties. This patch passes up three properties of flash to achieve that: - The size of the flash device - The sector size, i.e., the granularity of erase - The command used for erase The patch sends the parameters through coreboot and then libpayload. The patch also includes a minor refactoring of the flash erase code. Parameters are sent up for just one flash device. If multiple SPI flash devices are probed, the second one will "win" and its parameters will be sent up to the payload. TEST=Observed parameters to be passed up to depthcharge through libpayload and be used to correctly initialize flash and do an erase. TEST=Winbond and Gigadevices spi flash drivers compile with the changes; others don't, for seemingly unrelated reasons. BRANCH=none BUG=chromium:446377 Change-Id: Ib8be86494b5a3d1cfe1d23d3492e3b5cba5f99c6 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: 988c8c68bbfcdfa69d497ea5f806567bc80f8126 Original-Change-Id: Ie2b3a7f5b6e016d212f4f9bac3fabd80daf2ce72 Original-Signed-off-by: Dan Ehrenberg <dehrenberg@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/239570 Original-Reviewed-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: http://review.coreboot.org/9726 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
2015-01-08 19:29:19 +01:00
add_cbmem_pointers(head);
arm: libpayload: Add cache coherent DMA memory definition and management This patch adds a mechanism to set aside a region of cache-coherent (i.e. usually uncached) virtual memory, which can be used to communicate with DMA devices without automatic cache snooping (common on ARM) without the need of explicit flush/invalidation instructions in the driver code. This works by setting aside said region in the (board-specific) page table setup, as exemplary done in this patch for the Snow and Pit boards. It uses a new mechanism for adding board-specific Coreboot table entries to describe this region in an entry with the LB_DMA tag. Libpayload's memory allocator is enhanced to be able to operate on distinct types/regions of memory. It provides dma_malloc() and dma_memalign() functions for use in drivers, which by default just operate on the same heap as their traditional counterparts. However, if the Coreboot table parsing code finds a CB_DMA section, further requests through the dma_xxx() functions will return memory from the region described therein instead. Change-Id: Ia9c249249e936bbc3eb76e7b4822af2230ffb186 Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/167155 (cherry picked from commit d142ccdcd902a9d6ab4d495fbe6cbe85c61a5f01) Signed-off-by: Isaac Christensen <isaac.christensen@se-eng.com> Reviewed-on: http://review.coreboot.org/6622 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
2013-08-28 00:48:32 +02:00
/* Add board-specific table entries, if any. */
lb_board(head);
#if CONFIG(CHROMEOS_RAMOOPS)
lb_ramoops(head);
#endif
lb_boot_media_params(head);
/* Add architecture records. */
lb_arch_add_records(head);
/* Add all cbmem entries into the coreboot tables. */
cbmem_add_records_to_cbtable(head);
/* Remember where my valid memory ranges are */
return lb_table_fini(head);
}
void *write_tables(void)
{
uintptr_t cbtable_start;
uintptr_t cbtable_end;
size_t cbtable_size;
const size_t max_table_size = COREBOOT_TABLE_SIZE;
cbtable_start = (uintptr_t)cbmem_add(CBMEM_ID_CBTABLE, max_table_size);
if (!cbtable_start) {
printk(BIOS_ERR, "Could not add CBMEM for coreboot table.\n");
return NULL;
}
/* Add architecture specific tables. */
arch_write_tables(cbtable_start);
/* Write the coreboot table. */
cbtable_end = write_coreboot_table(cbtable_start);
cbtable_size = cbtable_end - cbtable_start;
if (cbtable_size > max_table_size) {
printk(BIOS_ERR, "%s: coreboot table didn't fit (%zx/%zx)\n",
__func__, cbtable_size, max_table_size);
}
printk(BIOS_DEBUG, "coreboot table: %zd bytes.\n", cbtable_size);
/* Print CBMEM sections */
cbmem_list();
return (void *)cbtable_start;
}