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/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 +++++++++++++++++ 4 files changed, 214 insertions(+) create mode 100644 src/vendorcode/google/chromeos/fmap.c create mode 100644 src/vendorcode/google/chromeos/fmap.h (limited to 'src/vendorcode') 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