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 <reinauer@google.com>
Reviewed-on: http://review.coreboot.org/1701
Reviewed-by: Marc Jones <marcj303@gmail.com>
Tested-by: build bot (Jenkins)
This commit is contained in:
Stefan Reinauer 2012-08-09 13:44:38 -07:00 committed by Stefan Reinauer
parent a60ca36c42
commit 357bb2daf0
6 changed files with 230 additions and 15 deletions

View File

@ -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

View File

@ -28,6 +28,9 @@
#include "sandybridge.h"
#include <spi.h>
#include <spi_flash.h>
#if CONFIG_CHROMEOS
#include <vendorcode/google/chromeos/fmap.h>
#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;
}

View File

@ -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

View File

@ -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

View File

@ -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 <stdint.h>
#include <stddef.h>
#include <string.h>
#include <console/console.h>
#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;
}

View File

@ -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 <stdint.h>
#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__*/