blob: 713993078259030df90e0006a3a4d0e7566490e4 [file] [log] [blame]
Aaron Durbin76c37002012-10-30 09:03:43 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2012 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Aaron Durbin76c37002012-10-30 09:03:43 -050014 */
15
16#include <stdint.h>
17#include <string.h>
Aaron Durbin243aa442013-04-24 17:31:49 -050018#include <bootstate.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050019#include <console/console.h>
20#include <cbfs.h>
Aaron Durbin0424c952015-03-28 23:56:22 -050021#include <fmap.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050022#include <ip_checksum.h>
23#include <device/device.h>
24#include <cbmem.h>
25#include "pei_data.h"
26#include "haswell.h"
27#include <spi-generic.h>
28#include <spi_flash.h>
Aaron Durbin76c37002012-10-30 09:03:43 -050029
Kyösti Mälkki9b29aad2015-01-06 07:08:46 +010030/* convert a pointer to flash area into the offset inside the flash */
31static inline u32 to_flash_offset(struct spi_flash *flash, void *p) {
32 return ((u32)p + flash->size);
33}
34
Aaron Durbin76c37002012-10-30 09:03:43 -050035static struct mrc_data_container *next_mrc_block(
36 struct mrc_data_container *mrc_cache)
37{
38 /* MRC data blocks are aligned within the region */
39 u32 mrc_size = sizeof(*mrc_cache) + mrc_cache->mrc_data_size;
40 if (mrc_size & (MRC_DATA_ALIGN - 1UL)) {
41 mrc_size &= ~(MRC_DATA_ALIGN - 1UL);
42 mrc_size += MRC_DATA_ALIGN;
43 }
44
45 u8 *region_ptr = (u8*)mrc_cache;
46 region_ptr += mrc_size;
47 return (struct mrc_data_container *)region_ptr;
48}
49
50static int is_mrc_cache(struct mrc_data_container *mrc_cache)
51{
52 return (!!mrc_cache) && (mrc_cache->mrc_signature == MRC_DATA_SIGNATURE);
53}
54
55/* Right now, the offsets for the MRC cache area are hard-coded in the
56 * northbridge Kconfig if CONFIG_CHROMEOS is not set. In order to make
57 * this more flexible, there are two of options:
58 * - Have each mainboard Kconfig supply a hard-coded offset
59 * - Use CBFS
60 */
61static u32 get_mrc_cache_region(struct mrc_data_container **mrc_region_ptr)
62{
Aaron Durbin0424c952015-03-28 23:56:22 -050063 size_t region_size = 0;
Patrick Georgi7a625da2015-07-27 23:17:14 +020064 *mrc_region_ptr = NULL;
Aaron Durbin0424c952015-03-28 23:56:22 -050065
66 if (IS_ENABLED(CONFIG_CHROMEOS)) {
67 struct region_device rdev;
68
69 if (fmap_locate_area_as_rdev("RW_MRC_CACHE", &rdev) == 0) {
70 region_size = region_device_sz(&rdev);
71 *mrc_region_ptr = rdev_mmap_full(&rdev);
72 }
73 } else {
Aaron Durbin899d13d2015-05-15 23:39:23 -050074 *mrc_region_ptr = cbfs_boot_map_with_leak("mrc.cache",
Aaron Durbin0424c952015-03-28 23:56:22 -050075 CBFS_TYPE_MRC_CACHE,
76 &region_size);
77 }
Aaron Durbin76c37002012-10-30 09:03:43 -050078 return region_size;
79}
80
81/*
82 * Find the largest index block in the MRC cache. Return NULL if non is
83 * found.
84 */
85static struct mrc_data_container *find_current_mrc_cache_local
86 (struct mrc_data_container *mrc_cache, u32 region_size)
87{
88 u32 region_end;
89 u32 entry_id = 0;
90 struct mrc_data_container *mrc_next = mrc_cache;
91
92 region_end = (u32) mrc_cache + region_size;
93
94 /* Search for the last filled entry in the region */
95 while (is_mrc_cache(mrc_next)) {
96 entry_id++;
97 mrc_cache = mrc_next;
98 mrc_next = next_mrc_block(mrc_next);
99 if ((u32)mrc_next >= region_end) {
100 /* Stay in the MRC data region */
101 break;
102 }
103 }
104
105 if (entry_id == 0) {
106 printk(BIOS_ERR, "%s: No valid MRC cache found.\n", __func__);
107 return NULL;
108 }
109
110 /* Verify checksum */
111 if (mrc_cache->mrc_checksum !=
112 compute_ip_checksum(mrc_cache->mrc_data,
113 mrc_cache->mrc_data_size)) {
114 printk(BIOS_ERR, "%s: MRC cache checksum mismatch\n", __func__);
115 return NULL;
116 }
117
118 printk(BIOS_DEBUG, "%s: picked entry %u from cache block\n", __func__,
119 entry_id - 1);
120
121 return mrc_cache;
122}
123
124/* SPI code needs malloc/free.
125 * Also unknown if writing flash from XIP-flash code is a good idea
126 */
Aaron Durbin4d3de7e2015-09-02 17:34:04 -0500127
Aaron Durbin76c37002012-10-30 09:03:43 -0500128/* find the first empty block in the MRC cache area.
129 * If there's none, return NULL.
130 *
131 * @mrc_cache_base - base address of the MRC cache area
132 * @mrc_cache - current entry (for which we need to find next)
133 * @region_size - total size of the MRC cache area
134 */
135static struct mrc_data_container *find_next_mrc_cache
136 (struct mrc_data_container *mrc_cache_base,
137 struct mrc_data_container *mrc_cache,
138 u32 region_size)
139{
140 u32 region_end = (u32) mrc_cache_base + region_size;
141
142 mrc_cache = next_mrc_block(mrc_cache);
143 if ((u32)mrc_cache >= region_end) {
144 /* Crossed the boundary */
145 mrc_cache = NULL;
146 printk(BIOS_DEBUG, "%s: no available entries found\n",
147 __func__);
148 } else {
149 printk(BIOS_DEBUG,
150 "%s: picked next entry from cache block at %p\n",
151 __func__, mrc_cache);
152 }
153
154 return mrc_cache;
155}
156
Aaron Durbin243aa442013-04-24 17:31:49 -0500157static void update_mrc_cache(void *unused)
Aaron Durbin76c37002012-10-30 09:03:43 -0500158{
159 printk(BIOS_DEBUG, "Updating MRC cache data.\n");
160 struct mrc_data_container *current = cbmem_find(CBMEM_ID_MRCDATA);
161 struct mrc_data_container *cache, *cache_base;
162 u32 cache_size;
163
164 if (!current) {
165 printk(BIOS_ERR, "No MRC cache in cbmem. Can't update flash.\n");
166 return;
167 }
168 if (current->mrc_data_size == -1) {
169 printk(BIOS_ERR, "MRC cache data in cbmem invalid.\n");
170 return;
171 }
172
173 cache_size = get_mrc_cache_region(&cache_base);
174 if (cache_base == NULL) {
175 printk(BIOS_ERR, "%s: could not find MRC cache area\n",
176 __func__);
177 return;
178 }
179
180 /*
181 * we need to:
182 */
183 // 0. compare MRC data to last mrc-cache block (exit if same)
184 cache = find_current_mrc_cache_local(cache_base, cache_size);
185
186 if (cache && (cache->mrc_data_size == current->mrc_data_size) &&
187 (memcmp(cache, current, cache->mrc_data_size) == 0)) {
188 printk(BIOS_DEBUG,
189 "MRC data in flash is up to date. No update.\n");
190 return;
191 }
192
193 // 1. use spi_flash_probe() to find the flash, then
194 spi_init();
Gabe Black1e187352014-03-27 20:37:03 -0700195 struct spi_flash *flash = spi_flash_probe(0, 0);
Aaron Durbin76c37002012-10-30 09:03:43 -0500196 if (!flash) {
197 printk(BIOS_DEBUG, "Could not find SPI device\n");
198 return;
199 }
200
201 // 2. look up the first unused block
202 if (cache)
203 cache = find_next_mrc_cache(cache_base, cache, cache_size);
204
205 /*
206 * 3. if no such place exists, erase entire mrc-cache range & use
207 * block 0. First time around the erase is not needed, but this is a
208 * small overhead for simpler code.
209 */
210 if (!cache) {
211 printk(BIOS_DEBUG,
212 "Need to erase the MRC cache region of %d bytes at %p\n",
213 cache_size, cache_base);
214
Vladimir Serbinenkoe51210d2014-01-04 20:58:55 +0100215 flash->erase(flash, to_flash_offset(flash, cache_base), cache_size);
Aaron Durbin76c37002012-10-30 09:03:43 -0500216
217 /* we will start at the beginning again */
218 cache = cache_base;
219 }
220 // 4. write mrc data with flash->write()
221 printk(BIOS_DEBUG, "Finally: write MRC cache update to flash at %p\n",
222 cache);
Vladimir Serbinenkoe51210d2014-01-04 20:58:55 +0100223 flash->write(flash, to_flash_offset(flash, cache),
Aaron Durbin76c37002012-10-30 09:03:43 -0500224 current->mrc_data_size + sizeof(*current), current);
225}
Aaron Durbin243aa442013-04-24 17:31:49 -0500226
Aaron Durbin9ef9d852015-03-16 17:30:09 -0500227BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY, update_mrc_cache, NULL);
Aaron Durbin76c37002012-10-30 09:03:43 -0500228
229struct mrc_data_container *find_current_mrc_cache(void)
230{
231 struct mrc_data_container *cache_base;
232 u32 cache_size;
233
234 cache_size = get_mrc_cache_region(&cache_base);
235 if (cache_base == NULL) {
236 printk(BIOS_ERR, "%s: could not find MRC cache area\n",
237 __func__);
238 return NULL;
239 }
240
241 /*
242 * we need to:
243 */
244 // 0. compare MRC data to last mrc-cache block (exit if same)
245 return find_current_mrc_cache_local(cache_base, cache_size);
246}