blob: e0d4b7de0130c6f5f973ef9628218afd21ddd22a [file] [log] [blame]
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -05001/*
2 * This file is part of the coreboot project.
3 *
Duncan Lauried8c4f2b2014-04-22 10:46:06 -07004 * Copyright (C) 2014 Google Inc.
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -05005 *
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 Durbin9a7d7bc2013-09-07 00:41:48 -050014 */
15
16#include <string.h>
Aaron Durbin31be2c92016-12-03 22:08:20 -060017#include <boot_device.h>
Aaron Durbin4d3de7e2015-09-02 17:34:04 -050018#include <bootstate.h>
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -050019#include <console/console.h>
20#include <cbmem.h>
Aaron Durbin7d9068f2016-11-04 10:07:14 -050021#include <elog.h>
Aaron Durbin0424c952015-03-28 23:56:22 -050022#include <fmap.h>
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -050023#include <ip_checksum.h>
Aaron Durbin31be2c92016-12-03 22:08:20 -060024#include <region_file.h>
Furquan Shaikh0325dc62016-07-25 13:02:36 -070025#include <vboot/vboot_common.h>
26
Duncan Lauried8c4f2b2014-04-22 10:46:06 -070027#include "mrc_cache.h"
Aaron Durbin4d3de7e2015-09-02 17:34:04 -050028#include "nvm.h"
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -050029
Aaron Durbin31be2c92016-12-03 22:08:20 -060030#define DEFAULT_MRC_CACHE "RW_MRC_CACHE"
31#define VARIABLE_MRC_CACHE "RW_VAR_MRC_CACHE"
32#define RECOVERY_MRC_CACHE "RECOVERY_MRC_CACHE"
33#define UNIFIED_MRC_CACHE "UNIFIED_MRC_CACHE"
34
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -050035#define MRC_DATA_SIGNATURE (('M'<<0)|('R'<<8)|('C'<<16)|('D'<<24))
36
Aaron Durbin31be2c92016-12-03 22:08:20 -060037struct mrc_metadata {
38 uint32_t signature;
39 uint32_t data_size;
40 uint16_t data_checksum;
41 uint16_t header_checksum;
42 uint32_t version;
43} __attribute__((packed));
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -050044
Andrey Petrovef9a9ea2016-11-08 08:30:06 -080045enum result {
Aaron Durbin31be2c92016-12-03 22:08:20 -060046 UPDATE_FAILURE = -1,
Andrey Petrovef9a9ea2016-11-08 08:30:06 -080047 UPDATE_SUCCESS = 0,
48 ALREADY_UPTODATE = 1
49};
50
Aaron Durbin31be2c92016-12-03 22:08:20 -060051#define NORMAL_FLAG (1 << 0)
52#define RECOVERY_FLAG (1 << 1)
53
54struct cache_region {
55 const char *name;
56 uint32_t cbmem_id;
57 int type;
58 int elog_slot;
59 int flags;
60};
61
62static const struct cache_region recovery_training = {
63 .name = RECOVERY_MRC_CACHE,
64 .cbmem_id = CBMEM_ID_MRCDATA,
65 .type = MRC_TRAINING_DATA,
66 .elog_slot = ELOG_MEM_CACHE_UPDATE_SLOT_RECOVERY,
67#if IS_ENABLED(CONFIG_HAS_RECOVERY_MRC_CACHE)
68 .flags = RECOVERY_FLAG,
69#else
70 .flags = 0,
71#endif
72};
73
74static const struct cache_region normal_training = {
75 .name = DEFAULT_MRC_CACHE,
76 .cbmem_id = CBMEM_ID_MRCDATA,
77 .type = MRC_TRAINING_DATA,
78 .elog_slot = ELOG_MEM_CACHE_UPDATE_SLOT_NORMAL,
79 .flags = NORMAL_FLAG | RECOVERY_FLAG,
80};
81
82static const struct cache_region variable_data = {
83 .name = VARIABLE_MRC_CACHE,
84 .cbmem_id = CBMEM_ID_VAR_MRCDATA,
85 .type = MRC_VARIABLE_DATA,
86 .elog_slot = ELOG_MEM_CACHE_UPDATE_SLOT_VARIABLE,
87 .flags = NORMAL_FLAG | RECOVERY_FLAG,
88};
89
90/* Order matters here for priority in matching. */
91static const struct cache_region *cache_regions[] = {
92 &recovery_training,
93 &normal_training,
94 &variable_data,
95};
96
97static int lookup_region_by_name(const char *name, struct region *r)
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -050098{
Aaron Durbin31be2c92016-12-03 22:08:20 -060099 /* This assumes memory mapped boot media just under 4GiB. */
100 const uint32_t pointer_base_32bit = -CONFIG_ROM_SIZE;
Aaron Durbin0424c952015-03-28 23:56:22 -0500101
Aaron Durbin31be2c92016-12-03 22:08:20 -0600102 if (fmap_locate_area(name, r) == 0)
103 return 0;
Aaron Durbin0424c952015-03-28 23:56:22 -0500104
Alexandru Gagniuc810caa92016-04-12 14:52:29 -0700105 /* CHROMEOS builds must get their MRC cache from FMAP. */
Aaron Durbin31be2c92016-12-03 22:08:20 -0600106 if (IS_ENABLED(CONFIG_CHROMEOS)) {
107 printk(BIOS_ERR, "MRC: Chrome OS lookup failure.\n");
108 return -1;
109 }
110
111 if (!IS_ENABLED(CONFIG_BOOT_DEVICE_MEMORY_MAPPED))
Alexandru Gagniuc810caa92016-04-12 14:52:29 -0700112 return -1;
113
Aaron Durbin31be2c92016-12-03 22:08:20 -0600114 /* Base is in the form of a pointer. Make it an offset. */
115 r->offset = CONFIG_MRC_SETTINGS_CACHE_BASE - pointer_base_32bit;
116 r->size = CONFIG_MRC_SETTINGS_CACHE_SIZE;
Alexandru Gagniuc810caa92016-04-12 14:52:29 -0700117
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500118 return 0;
119}
120
Aaron Durbin31be2c92016-12-03 22:08:20 -0600121static const struct cache_region *lookup_region_type(int type)
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700122{
Aaron Durbin31be2c92016-12-03 22:08:20 -0600123 int i;
124 int flags;
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700125
Aaron Durbin31be2c92016-12-03 22:08:20 -0600126 if (vboot_recovery_mode_enabled())
127 flags = RECOVERY_FLAG;
128 else
129 flags = NORMAL_FLAG;
130
131 for (i = 0; i < ARRAY_SIZE(cache_regions); i++) {
132 if (cache_regions[i]->type != type)
133 continue;
134 if ((cache_regions[i]->flags & flags) == flags)
135 return cache_regions[i];
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700136 }
137
Aaron Durbin31be2c92016-12-03 22:08:20 -0600138 return NULL;
139}
140
141int mrc_cache_stash_data(int type, uint32_t version, const void *data,
142 size_t size)
143{
144 const struct cache_region *cr;
145 size_t cbmem_size;
146 struct mrc_metadata *md;
147
148 cr = lookup_region_type(type);
149 if (cr == NULL) {
150 printk(BIOS_ERR, "MRC: failed to add to cbmem for type %d.\n",
151 type);
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700152 return -1;
153 }
154
Aaron Durbin31be2c92016-12-03 22:08:20 -0600155 cbmem_size = sizeof(*md) + size;
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700156
Aaron Durbin31be2c92016-12-03 22:08:20 -0600157 md = cbmem_add(cr->cbmem_id, cbmem_size);
158
159 if (md == NULL) {
160 printk(BIOS_ERR, "MRC: failed to add '%s' to cbmem.\n",
161 cr->name);
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700162 return -1;
163 }
164
Aaron Durbin31be2c92016-12-03 22:08:20 -0600165 memset(md, 0, sizeof(*md));
166 md->signature = MRC_DATA_SIGNATURE;
167 md->data_size = size;
168 md->version = version;
169 md->data_checksum = compute_ip_checksum(data, size);
170 md->header_checksum = compute_ip_checksum(md, sizeof(*md));
171 memcpy(&md[1], data, size);
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700172
173 return 0;
174}
175
Aaron Durbin31be2c92016-12-03 22:08:20 -0600176static const struct cache_region *lookup_region(struct region *r, int type)
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700177{
Aaron Durbin31be2c92016-12-03 22:08:20 -0600178 const struct cache_region *cr;
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700179
Aaron Durbin31be2c92016-12-03 22:08:20 -0600180 cr = lookup_region_type(type);
181
182 if (cr == NULL) {
183 printk(BIOS_ERR, "MRC: failed to locate region type %d.\n",
184 type);
185 return NULL;
186 }
187
188 if (lookup_region_by_name(cr->name, r) < 0)
189 return NULL;
190
191 return cr;
192}
193
194static int mrc_header_valid(struct region_device *rdev, struct mrc_metadata *md)
195{
196 uint16_t checksum;
197 uint16_t checksum_result;
198 size_t size;
199
200 if (rdev_readat(rdev, md, 0, sizeof(*md)) < 0) {
201 printk(BIOS_ERR, "MRC: couldn't read metadata\n");
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700202 return -1;
203 }
204
Aaron Durbin31be2c92016-12-03 22:08:20 -0600205 if (md->signature != MRC_DATA_SIGNATURE) {
206 printk(BIOS_ERR, "MRC: invalid header signature\n");
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700207 return -1;
208 }
209
Aaron Durbin31be2c92016-12-03 22:08:20 -0600210 /* Compute checksum over header with 0 as the value. */
211 checksum = md->header_checksum;
212 md->header_checksum = 0;
213 checksum_result = compute_ip_checksum(md, sizeof(*md));
214
215 if (checksum != checksum_result) {
216 printk(BIOS_ERR, "MRC: header checksum mismatch: %x vs %x\n",
217 checksum, checksum_result);
218 return -1;
219 }
220
221 /* Put back original. */
222 md->header_checksum = checksum;
223
224 /* Re-size the region device according to the metadata as a region_file
225 * does block allocation. */
226 size = sizeof(*md) + md->data_size;
227 if (rdev_chain(rdev, rdev, 0, size) < 0) {
228 printk(BIOS_ERR, "MRC: size exceeds rdev size: %zx vs %zx\n",
229 size, region_device_sz(rdev));
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700230 return -1;
231 }
Duncan Lauried8c4f2b2014-04-22 10:46:06 -0700232
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500233 return 0;
234}
235
Aaron Durbin31be2c92016-12-03 22:08:20 -0600236static int mrc_data_valid(const struct region_device *rdev,
237 const struct mrc_metadata *md)
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500238{
Aaron Durbin31be2c92016-12-03 22:08:20 -0600239 void *data;
240 uint16_t checksum;
241 const size_t md_size = sizeof(*md);
242 const size_t data_size = md->data_size;
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500243
Aaron Durbin31be2c92016-12-03 22:08:20 -0600244 data = rdev_mmap(rdev, md_size, data_size);
245 if (data == NULL) {
246 printk(BIOS_ERR, "MRC: mmap failure on data verification.\n");
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500247 return -1;
248 }
249
Aaron Durbin31be2c92016-12-03 22:08:20 -0600250 checksum = compute_ip_checksum(data, data_size);
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500251
Aaron Durbin31be2c92016-12-03 22:08:20 -0600252 rdev_munmap(rdev, data);
253 if (md->data_checksum != checksum) {
254 printk(BIOS_ERR, "MRC: data checksum mismatch: %x vs %x\n",
255 md->data_checksum, checksum);
256 return -1;
257 }
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500258
259 return 0;
260}
261
Aaron Durbin31be2c92016-12-03 22:08:20 -0600262static int mrc_cache_latest(const char *name,
263 const struct region_device *backing_rdev,
264 struct mrc_metadata *md,
265 struct region_file *cache_file,
266 struct region_device *rdev,
267 bool fail_bad_data)
Andrey Petrovef9a9ea2016-11-08 08:30:06 -0800268{
Aaron Durbin31be2c92016-12-03 22:08:20 -0600269 /* Init and obtain a handle to the file data. */
270 if (region_file_init(cache_file, backing_rdev) < 0) {
271 printk(BIOS_ERR, "MRC: region file invalid in '%s'\n", name);
272 return -1;
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500273 }
274
Aaron Durbin31be2c92016-12-03 22:08:20 -0600275 /* Provide a 0 sized region_device from here on out so the caller
276 * has a valid yet unusable region_device. */
277 rdev_chain(rdev, backing_rdev, 0, 0);
278
279 /* No data to return. */
280 if (region_file_data(cache_file, rdev) < 0) {
281 printk(BIOS_ERR, "MRC: no data in '%s'\n", name);
282 return fail_bad_data ? -1 : 0;
283 }
284
285 /* Validate header and resize region to reflect actual usage on the
286 * saved medium (including metadata and data). */
287 if (mrc_header_valid(rdev, md) < 0) {
288 printk(BIOS_ERR, "MRC: invalid header in '%s'\n", name);
289 return fail_bad_data ? -1 : 0;
290 }
291
292 /* Validate Data */
293 if (mrc_data_valid(rdev, md) < 0) {
294 printk(BIOS_ERR, "MRC: invalid data in '%s'\n", name);
295 return fail_bad_data ? -1 : 0;
296 }
297
298 return 0;
299}
300
301int mrc_cache_get_current(int type, uint32_t version,
302 struct region_device *rdev)
303{
304 const struct cache_region *cr;
305 struct region region;
306 struct region_device read_rdev;
307 struct region_file cache_file;
308 struct mrc_metadata md;
309 size_t data_size;
310 const size_t md_size = sizeof(md);
311 const bool fail_bad_data = true;
312
313 cr = lookup_region(&region, type);
314
315 if (cr == NULL)
316 return -1;
317
318 if (boot_device_ro_subregion(&region, &read_rdev) < 0)
319 return -1;
320
321 if (mrc_cache_latest(cr->name, &read_rdev, &md, &cache_file, rdev,
322 fail_bad_data) < 0)
323 return -1;
324
325 if (version != md.version) {
326 printk(BIOS_INFO, "MRC: version mismatch: %x vs %x\n",
327 md.version, version);
328 return -1;
329 }
330
331 /* Re-size rdev to only contain the data. i.e. remove metadata. */
332 data_size = md.data_size;
333 return rdev_chain(rdev, rdev, md_size, data_size);
334}
335
336static bool mrc_cache_needs_update(const struct region_device *rdev,
337 const struct cbmem_entry *to_be_updated)
338{
339 void *mapping;
340 size_t size = region_device_sz(rdev);
341 bool need_update = false;
342
343 if (cbmem_entry_size(to_be_updated) != size)
344 return true;
345
346 mapping = rdev_mmap_full(rdev);
347
348 if (memcmp(cbmem_entry_start(to_be_updated), mapping, size))
349 need_update = true;
350
351 rdev_munmap(rdev, mapping);
352
353 return need_update;
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500354}
355
Andrey Petrovef9a9ea2016-11-08 08:30:06 -0800356static void log_event_cache_update(uint8_t slot, enum result res)
Aaron Durbin7d9068f2016-11-04 10:07:14 -0500357{
358 const int type = ELOG_TYPE_MEM_CACHE_UPDATE;
359 struct elog_event_mem_cache_update event = {
Andrey Petrovef9a9ea2016-11-08 08:30:06 -0800360 .slot = slot
Aaron Durbin7d9068f2016-11-04 10:07:14 -0500361 };
362
Andrey Petrovef9a9ea2016-11-08 08:30:06 -0800363 /* Filter through interesting events only */
364 switch (res) {
Aaron Durbin31be2c92016-12-03 22:08:20 -0600365 case UPDATE_FAILURE:
Andrey Petrovef9a9ea2016-11-08 08:30:06 -0800366 event.status = ELOG_MEM_CACHE_UPDATE_STATUS_FAIL;
367 break;
368 case UPDATE_SUCCESS:
369 event.status = ELOG_MEM_CACHE_UPDATE_STATUS_SUCCESS;
370 break;
371 default:
372 return;
373 }
374
Aaron Durbin7d9068f2016-11-04 10:07:14 -0500375 if (elog_add_event_raw(type, &event, sizeof(event)) < 0)
376 printk(BIOS_ERR, "Failed to log mem cache update event.\n");
377}
378
Aaron Durbin31be2c92016-12-03 22:08:20 -0600379/* During ramstage this code purposefully uses incoherent transactions between
380 * read and write. The read assumes a memory-mapped boot device that can be used
381 * to quickly locate and compare the up-to-date data. However, when an update
382 * is required it uses the writeable region access to perform the update. */
383static void update_mrc_cache_by_type(int type)
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500384{
Aaron Durbin31be2c92016-12-03 22:08:20 -0600385 const struct cache_region *cr;
386 struct region region;
387 struct region_device read_rdev;
388 struct region_device write_rdev;
389 struct region_file cache_file;
390 struct mrc_metadata md;
391 const struct cbmem_entry *to_be_updated;
392 struct incoherent_rdev backing_irdev;
393 const struct region_device *backing_rdev;
394 struct region_device latest_rdev;
395 const bool fail_bad_data = false;
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500396
Aaron Durbin31be2c92016-12-03 22:08:20 -0600397 cr = lookup_region(&region, type);
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500398
Aaron Durbin31be2c92016-12-03 22:08:20 -0600399 if (cr == NULL)
400 return;
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700401
Aaron Durbin31be2c92016-12-03 22:08:20 -0600402 to_be_updated = cbmem_entry_find(cr->cbmem_id);
403 if (to_be_updated == NULL) {
404 printk(BIOS_ERR, "MRC: No data in cbmem for '%s'.\n",
405 cr->name);
406 return;
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500407 }
408
Aaron Durbin31be2c92016-12-03 22:08:20 -0600409 printk(BIOS_DEBUG, "MRC: Checking cached data update for '%s'.\n",
410 cr->name);
411
412 if (boot_device_ro_subregion(&region, &read_rdev) < 0)
413 return;
414
415 if (boot_device_rw_subregion(&region, &write_rdev) < 0)
416 return;
417
418 backing_rdev = incoherent_rdev_init(&backing_irdev, &region, &read_rdev,
419 &write_rdev);
420
421 if (backing_rdev == NULL)
422 return;
423
424 if (mrc_cache_latest(cr->name, backing_rdev, &md, &cache_file,
425 &latest_rdev, fail_bad_data) < 0)
426 return;
427
428 if (!mrc_cache_needs_update(&latest_rdev, to_be_updated)) {
429 log_event_cache_update(cr->elog_slot, ALREADY_UPTODATE);
430 return;
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500431 }
432
Aaron Durbin31be2c92016-12-03 22:08:20 -0600433 printk(BIOS_DEBUG, "MRC: cache data '%s' needs update.\n", cr->name);
434
435 if (region_file_update_data(&cache_file,
436 cbmem_entry_start(to_be_updated),
437 cbmem_entry_size(to_be_updated)) < 0)
438 log_event_cache_update(cr->elog_slot, UPDATE_FAILURE);
439 else
440 log_event_cache_update(cr->elog_slot, UPDATE_SUCCESS);
441}
442
443/* Protect mrc region with a Protected Range Register */
444static int protect_mrc_cache(const char *name)
445{
446 struct region region;
447
448 if (!IS_ENABLED(CONFIG_MRC_SETTINGS_PROTECT))
449 return 0;
450
451 if (lookup_region_by_name(name, &region) < 0) {
452 printk(BIOS_ERR, "MRC: Could not find region '%s'\n", name);
453 return -1;
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500454 }
455
Aaron Durbin31be2c92016-12-03 22:08:20 -0600456 if (nvm_is_write_protected() <= 0) {
457 printk(BIOS_INFO, "MRC: NOT enabling PRR for '%s'.\n", name);
458 return 0;
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500459 }
460
Aaron Durbin31be2c92016-12-03 22:08:20 -0600461 if (nvm_protect(&region) < 0) {
462 printk(BIOS_ERR, "MRC: ERROR setting PRR for '%s'.\n", name);
463 return -1;
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500464 }
465
Aaron Durbin31be2c92016-12-03 22:08:20 -0600466 printk(BIOS_INFO, "MRC: Enabled Protected Range on '%s'.\n", name);
467 return 0;
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700468}
Aaron Durbin7d9068f2016-11-04 10:07:14 -0500469
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700470static void protect_mrc_region(void)
471{
472 /*
473 * Check if there is a single unified region that encompasses both
474 * RECOVERY_MRC_CACHE and DEFAULT_MRC_CACHE. In that case protect the
475 * entire region using a single PRR.
476 *
477 * If we are not able to protect the entire region, try protecting
478 * individual regions next.
479 */
480 if (protect_mrc_cache(UNIFIED_MRC_CACHE) == 0)
481 return;
482
483 if (IS_ENABLED(CONFIG_HAS_RECOVERY_MRC_CACHE))
484 protect_mrc_cache(RECOVERY_MRC_CACHE);
485
486 protect_mrc_cache(DEFAULT_MRC_CACHE);
487}
488
Aaron Durbind09142c2016-12-14 15:36:56 -0600489static void invalidate_normal_cache(void)
490{
491 struct region_file cache_file;
492 struct region_device rdev;
493 const char *name = DEFAULT_MRC_CACHE;
494 const uint32_t invalid = ~MRC_DATA_SIGNATURE;
495
496 /* Invalidate only on recovery mode with retraining enabled. */
497 if (!vboot_recovery_mode_enabled())
498 return;
499 if (!vboot_recovery_mode_memory_retrain())
500 return;
501
502 if (fmap_locate_area_as_rdev_rw(name, &rdev) < 0) {
503 printk(BIOS_ERR, "MRC: Couldn't find '%s' region. Invalidation failed\n",
504 name);
505 return;
506 }
507
508 if (region_file_init(&cache_file, &rdev) < 0) {
509 printk(BIOS_ERR, "MRC: region file invalid for '%s'. Invalidation failed\n",
510 name);
511 return;
512 }
513
514 /* Push an update that consists of 4 bytes that is smaller than the
515 * MRC metadata as well as an invalid signature. */
516 if (region_file_update_data(&cache_file, &invalid, sizeof(invalid)) < 0)
517 printk(BIOS_ERR, "MRC: invalidation failed for '%s'.\n", name);
518}
519
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700520static void update_mrc_cache(void *unused)
521{
Aaron Durbin31be2c92016-12-03 22:08:20 -0600522 update_mrc_cache_by_type(MRC_TRAINING_DATA);
Andrey Petrovef9a9ea2016-11-08 08:30:06 -0800523
Aaron Durbin31be2c92016-12-03 22:08:20 -0600524 if (IS_ENABLED(CONFIG_MRC_SETTINGS_VARIABLE_DATA))
525 update_mrc_cache_by_type(MRC_VARIABLE_DATA);
Andrey Petrovef9a9ea2016-11-08 08:30:06 -0800526
Aaron Durbind09142c2016-12-14 15:36:56 -0600527 if (IS_ENABLED(CONFIG_MRC_CLEAR_NORMAL_CACHE_ON_RECOVERY_RETRAIN))
528 invalidate_normal_cache();
529
Furquan Shaikhcab1c012016-11-05 23:57:02 -0700530 protect_mrc_region();
Aaron Durbin9a7d7bc2013-09-07 00:41:48 -0500531}
532
Aaron Durbin9ef9d852015-03-16 17:30:09 -0500533BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY, update_mrc_cache, NULL);