tree: drop last paragraph of GPL copyright header
[coreboot.git] / src / northbridge / intel / haswell / mrccache.c
blob713993078259030df90e0006a3a4d0e7566490e4
1 /*
2 * This file is part of the coreboot project.
4 * Copyright (C) 2012 Google Inc.
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.
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.
16 #include <stdint.h>
17 #include <string.h>
18 #include <bootstate.h>
19 #include <console/console.h>
20 #include <cbfs.h>
21 #include <fmap.h>
22 #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>
30 /* convert a pointer to flash area into the offset inside the flash */
31 static inline u32 to_flash_offset(struct spi_flash *flash, void *p) {
32 return ((u32)p + flash->size);
35 static struct mrc_data_container *next_mrc_block(
36 struct mrc_data_container *mrc_cache)
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;
45 u8 *region_ptr = (u8*)mrc_cache;
46 region_ptr += mrc_size;
47 return (struct mrc_data_container *)region_ptr;
50 static int is_mrc_cache(struct mrc_data_container *mrc_cache)
52 return (!!mrc_cache) && (mrc_cache->mrc_signature == MRC_DATA_SIGNATURE);
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
61 static u32 get_mrc_cache_region(struct mrc_data_container **mrc_region_ptr)
63 size_t region_size = 0;
64 *mrc_region_ptr = NULL;
66 if (IS_ENABLED(CONFIG_CHROMEOS)) {
67 struct region_device rdev;
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);
73 } else {
74 *mrc_region_ptr = cbfs_boot_map_with_leak("mrc.cache",
75 CBFS_TYPE_MRC_CACHE,
76 &region_size);
78 return region_size;
82 * Find the largest index block in the MRC cache. Return NULL if non is
83 * found.
85 static struct mrc_data_container *find_current_mrc_cache_local
86 (struct mrc_data_container *mrc_cache, u32 region_size)
88 u32 region_end;
89 u32 entry_id = 0;
90 struct mrc_data_container *mrc_next = mrc_cache;
92 region_end = (u32) mrc_cache + region_size;
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;
105 if (entry_id == 0) {
106 printk(BIOS_ERR, "%s: No valid MRC cache found.\n", __func__);
107 return NULL;
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;
118 printk(BIOS_DEBUG, "%s: picked entry %u from cache block\n", __func__,
119 entry_id - 1);
121 return mrc_cache;
124 /* SPI code needs malloc/free.
125 * Also unknown if writing flash from XIP-flash code is a good idea
128 /* find the first empty block in the MRC cache area.
129 * If there's none, return NULL.
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
135 static 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)
140 u32 region_end = (u32) mrc_cache_base + region_size;
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);
154 return mrc_cache;
157 static void update_mrc_cache(void *unused)
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;
164 if (!current) {
165 printk(BIOS_ERR, "No MRC cache in cbmem. Can't update flash.\n");
166 return;
168 if (current->mrc_data_size == -1) {
169 printk(BIOS_ERR, "MRC cache data in cbmem invalid.\n");
170 return;
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;
181 * we need to:
183 // 0. compare MRC data to last mrc-cache block (exit if same)
184 cache = find_current_mrc_cache_local(cache_base, cache_size);
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;
193 // 1. use spi_flash_probe() to find the flash, then
194 spi_init();
195 struct spi_flash *flash = spi_flash_probe(0, 0);
196 if (!flash) {
197 printk(BIOS_DEBUG, "Could not find SPI device\n");
198 return;
201 // 2. look up the first unused block
202 if (cache)
203 cache = find_next_mrc_cache(cache_base, cache, cache_size);
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.
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);
215 flash->erase(flash, to_flash_offset(flash, cache_base), cache_size);
217 /* we will start at the beginning again */
218 cache = cache_base;
220 // 4. write mrc data with flash->write()
221 printk(BIOS_DEBUG, "Finally: write MRC cache update to flash at %p\n",
222 cache);
223 flash->write(flash, to_flash_offset(flash, cache),
224 current->mrc_data_size + sizeof(*current), current);
227 BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY, update_mrc_cache, NULL);
229 struct mrc_data_container *find_current_mrc_cache(void)
231 struct mrc_data_container *cache_base;
232 u32 cache_size;
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;
242 * we need to:
244 // 0. compare MRC data to last mrc-cache block (exit if same)
245 return find_current_mrc_cache_local(cache_base, cache_size);