From 357bb2daf09090192c09ddde501a7e07337614e1 Mon Sep 17 00:00:00 2001 From: Stefan Reinauer Date: Thu, 9 Aug 2012 13:44:38 -0700 Subject: SandyBridge/IvyBridge: Use flash map to find MRC cache Until now, the MRC cache position and size was hard coded in Kconfig. However, on ChromeOS devices, it should be determined by reading the FMAP. This patch provides a minimalistic FMAP parser (libflashmap was too complex and OS centered) to allow reading the in-ROM flash map and look for sections. This will also be needed on some partner devices where coreboot will have to find the VPD in order to set up the device's mac address correctly. The MRC cache implementation demonstrates how to use the FMAP parser. Change-Id: I34964b72587443a6ca4f27407d778af8728565f8 Signed-off-by: Stefan Reinauer Reviewed-on: http://review.coreboot.org/1701 Reviewed-by: Marc Jones Tested-by: build bot (Jenkins) --- src/northbridge/intel/sandybridge/Kconfig | 13 +-- src/northbridge/intel/sandybridge/mrccache.c | 18 ++-- src/vendorcode/google/chromeos/Kconfig | 7 ++ src/vendorcode/google/chromeos/Makefile.inc | 2 + src/vendorcode/google/chromeos/fmap.c | 126 +++++++++++++++++++++++++++ src/vendorcode/google/chromeos/fmap.h | 79 +++++++++++++++++ 6 files changed, 230 insertions(+), 15 deletions(-) create mode 100644 src/vendorcode/google/chromeos/fmap.c create mode 100644 src/vendorcode/google/chromeos/fmap.h (limited to 'src') diff --git a/src/northbridge/intel/sandybridge/Kconfig b/src/northbridge/intel/sandybridge/Kconfig index 7dfd10d3ba..229589998f 100644 --- a/src/northbridge/intel/sandybridge/Kconfig +++ b/src/northbridge/intel/sandybridge/Kconfig @@ -44,16 +44,14 @@ config MRC_CACHE_BASE config MRC_CACHE_LOCATION hex + depends on !CHROMEOS default 0x1ec000 config MRC_CACHE_SIZE hex + depends on !CHROMEOS default 0x10000 -config MRC_CACHE_ALIGNMENT - hex - default 0x1000 - config DCACHE_RAM_BASE hex default 0xff7f0000 @@ -85,17 +83,14 @@ config MRC_CACHE_BASE config MRC_CACHE_LOCATION hex + depends on !CHROMEOS default 0x370000 config MRC_CACHE_SIZE hex + depends on !CHROMEOS default 0x10000 -config MRC_CACHE_ALIGNMENT - hex - default 0x1000 - - config DCACHE_RAM_BASE hex default 0xff7e0000 diff --git a/src/northbridge/intel/sandybridge/mrccache.c b/src/northbridge/intel/sandybridge/mrccache.c index 00b3bdd362..2a7727c876 100644 --- a/src/northbridge/intel/sandybridge/mrccache.c +++ b/src/northbridge/intel/sandybridge/mrccache.c @@ -28,6 +28,9 @@ #include "sandybridge.h" #include #include +#if CONFIG_CHROMEOS +#include +#endif struct mrc_data_container *next_mrc_block(struct mrc_data_container *mrc_cache) { @@ -49,18 +52,21 @@ int is_mrc_cache(struct mrc_data_container *mrc_cache) } /* Right now, the offsets for the MRC cache area are hard-coded in the - * northbridge Kconfig. In order to make this more flexible, there are - * a number of options: + * northbridge Kconfig if CONFIG_CHROMEOS is not set. In order to make + * this more flexible, there are two of options: * - Have each mainboard Kconfig supply a hard-coded offset - * - For ChromeOS devices: implement native FMAP - * - For non-ChromeOS devices: use CBFS + * - Use CBFS */ u32 get_mrc_cache_region(struct mrc_data_container **mrc_region_ptr) { - - u32 region_size = CONFIG_MRC_CACHE_SIZE; + u32 region_size; +#if CONFIG_CHROMEOS + region_size = find_fmap_entry("RW_MRC_CACHE", (void **)mrc_region_ptr); +#else + region_size = CONFIG_MRC_CACHE_SIZE; *mrc_region_ptr = (struct mrc_data_container *) (CONFIG_MRC_CACHE_BASE + CONFIG_MRC_CACHE_LOCATION); +#endif return region_size; } diff --git a/src/vendorcode/google/chromeos/Kconfig b/src/vendorcode/google/chromeos/Kconfig index 179bbb1f27..ace0c1805f 100644 --- a/src/vendorcode/google/chromeos/Kconfig +++ b/src/vendorcode/google/chromeos/Kconfig @@ -57,4 +57,11 @@ config CHROMEOS_RAMOOPS_RAM_SIZE default 0x00100000 depends on CHROMEOS_RAMOOPS +config FLASHMAP_OFFSET + hex + default 0x00670000 if NORTHBRIDGE_INTEL_SANDYBRIDGE + default 0x005f0000 if NORTHBRIDGE_INTEL_IVYBRIDGE + help + Offset of flash map in firmware image + endmenu diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc index c1b1ccef3e..6e5ea9ba78 100644 --- a/src/vendorcode/google/chromeos/Makefile.inc +++ b/src/vendorcode/google/chromeos/Makefile.inc @@ -23,3 +23,5 @@ romstage-y += vbnv.c ramstage-y += vbnv.c romstage-y += vboot.c ramstage-y += gnvs.c +romstage-y += fmap.c +ramstage-y += fmap.c diff --git a/src/vendorcode/google/chromeos/fmap.c b/src/vendorcode/google/chromeos/fmap.c new file mode 100644 index 0000000000..0871529a75 --- /dev/null +++ b/src/vendorcode/google/chromeos/fmap.c @@ -0,0 +1,126 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 The ChromiumOS Authors. All rights reserved. + * + * 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 + */ + +#include +#include +#include +#include +#include "fmap.h" + +static int fmap_try_find(void *fmap) +{ + if (!memcmp(fmap, FMAP_SIGNATURE, + sizeof(FMAP_SIGNATURE)-1)) + return 1; + return 0; +} + +/* Find FMAP data structure in ROM. + * See http://code.google.com/p/flashmap/ for more information on FMAP. + */ +const struct fmap *fmap_find(void) +{ + const struct fmap *fmap = NULL; + + /* FIXME: Get rid of the hard codes. The "easy" way would be to + * do a binary search, but since ROM accesses are slow, we don't + * want to spend a lot of time looking for the FMAP. An elegant + * solution would be to store a pointer to the FMAP in the CBFS + * master header; that would require some more changes to cbfstool + * and possibly cros_bundle_firmware. + * FIXME: Use CONFIG_ROMSIZE instead of CONFIG_MRC_CACHE_BASE + * (and get rid of CONFIG_MRC_CACHE_BASE), once we are building + * coreboot images with ME firmware etc built in instead of just + * the CBFS part. + */ + if (fmap_try_find((void *)CONFIG_MRC_CACHE_BASE + + CONFIG_FLASHMAP_OFFSET)) + fmap = (const struct fmap *)(CONFIG_MRC_CACHE_BASE + + CONFIG_FLASHMAP_OFFSET); + if (fmap) { + printk(BIOS_DEBUG, "FMAP: Found \"%s\" version %d.%d at %p.\n", + fmap->name, fmap->ver_major, fmap->ver_minor, fmap); + printk(BIOS_DEBUG, "FMAP: base = %llx size = %x #areas = %d\n", + (unsigned long long)fmap->base, fmap->size, + fmap->nareas); + } else + printk(BIOS_DEBUG, "No FMAP found.\n"); + + return fmap; +} + +const struct fmap_area *find_fmap_area(const struct fmap *fmap, + const char name[]) +{ + const struct fmap_area *area = NULL; + + if (fmap) { + int i; + for (i = 0; i < fmap->nareas; i++) { + if (!strcmp((const char *)fmap->areas[i].name, name)) { + area = &fmap->areas[i]; + break; + } + } + } + + if (area) { + printk(BIOS_DEBUG, "FMAP: area %s found\n", name); + printk(BIOS_DEBUG, "FMAP: offset: %x\n", area->offset); + printk(BIOS_DEBUG, "FMAP: size: %d bytes\n", area->size); + } else { + printk(BIOS_DEBUG, "FMAP: area %s not found\n", name); + } + + return area; +} + +int find_fmap_entry(const char name[], void **pointer) +{ +#ifndef __PRE_RAM__ + static +#endif + const struct fmap *fmap = NULL; + const struct fmap_area *area; + void *base = NULL; + + if (!fmap) + fmap = fmap_find(); + + area = find_fmap_area(fmap, name); + + if (!area) + return -1; + + /* Right now cros_bundle_firmware does not write a valid + * base address into the FMAP. Hence, if base is 0, assume + * 4GB-8MB as base address. + */ + if (fmap->base) { + base = (void *)(unsigned long)fmap->base; + } else { + printk(BIOS_WARNING, "FMAP: No valid base address, using" + " 0x%08x\n", CONFIG_MRC_CACHE_BASE); + base = (void *)CONFIG_MRC_CACHE_BASE; + } + + *pointer = base + area->offset; + + return area->size; +} diff --git a/src/vendorcode/google/chromeos/fmap.h b/src/vendorcode/google/chromeos/fmap.h new file mode 100644 index 0000000000..a3d2abd582 --- /dev/null +++ b/src/vendorcode/google/chromeos/fmap.h @@ -0,0 +1,79 @@ +/* + * Copyright 2010, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + */ + +#ifndef FLASHMAP_LIB_FMAP_H__ +#define FLASHMAP_LIB_FMAP_H__ + +#include + +#define FMAP_SIGNATURE "__FMAP__" +#define FMAP_VER_MAJOR 1 /* this header's FMAP minor version */ +#define FMAP_VER_MINOR 1 /* this header's FMAP minor version */ +#define FMAP_STRLEN 32 /* maximum length for strings, */ + /* including null-terminator */ + +enum fmap_flags { + FMAP_AREA_STATIC = 1 << 0, + FMAP_AREA_COMPRESSED = 1 << 1, + FMAP_AREA_RO = 1 << 2, +}; + +/* Mapping of volatile and static regions in firmware binary */ +struct fmap_area { + uint32_t offset; /* offset relative to base */ + uint32_t size; /* size in bytes */ + uint8_t name[FMAP_STRLEN]; /* descriptive name */ + uint16_t flags; /* flags for this area */ +} __attribute__((packed)); + +struct fmap { + uint8_t signature[8]; /* "__FMAP__" (0x5F5F464D41505F5F) */ + uint8_t ver_major; /* major version */ + uint8_t ver_minor; /* minor version */ + uint64_t base; /* address of the firmware binary */ + uint32_t size; /* size of firmware binary in bytes */ + uint8_t name[FMAP_STRLEN]; /* name of this firmware binary */ + uint16_t nareas; /* number of areas described by + fmap_areas[] below */ + struct fmap_area areas[]; +} __attribute__((packed)); + + +/* coreboot specific function prototypes */ +const struct fmap *fmap_find(void); +const struct fmap_area *find_fmap_area(const struct fmap *fmap, + const char name[]); +int find_fmap_entry(const char name[], void **pointer); +#endif /* FLASHMAP_LIB_FMAP_H__*/ -- cgit v1.2.3