1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <boot_device.h>
7 #include <commonlib/bsd/cbfs_private.h>
8 #include <commonlib/bsd/compression.h>
9 #include <commonlib/list.h>
10 #include <console/console.h>
13 #include <metadata_hash.h>
14 #include <security/tpm/tspi/crtm.h>
15 #include <security/vboot/vboot_common.h>
16 #include <security/vboot/misc.h>
21 #include <timestamp.h>
23 #if ENV_X86 && (ENV_POSTCAR || ENV_SMM)
24 struct mem_pool cbfs_cache
= MEM_POOL_INIT(NULL
, 0, 0);
25 #elif CONFIG(POSTRAM_CBFS_CACHE_IN_BSS) && ENV_RAMSTAGE
26 static u8 cache_buffer
[CONFIG_RAMSTAGE_CBFS_CACHE_SIZE
];
27 struct mem_pool cbfs_cache
=
28 MEM_POOL_INIT(cache_buffer
, sizeof(cache_buffer
), CONFIG_CBFS_CACHE_ALIGN
);
30 struct mem_pool cbfs_cache
=
31 MEM_POOL_INIT(_cbfs_cache
, REGION_SIZE(cbfs_cache
), CONFIG_CBFS_CACHE_ALIGN
);
34 static void switch_to_postram_cache(int unused
)
36 if (_preram_cbfs_cache
!= _postram_cbfs_cache
)
37 mem_pool_init(&cbfs_cache
, _postram_cbfs_cache
, REGION_SIZE(postram_cbfs_cache
),
38 CONFIG_CBFS_CACHE_ALIGN
);
40 CBMEM_CREATION_HOOK(switch_to_postram_cache
);
42 enum cb_err
_cbfs_boot_lookup(const char *name
, bool force_ro
,
43 union cbfs_mdata
*mdata
, struct region_device
*rdev
)
45 const struct cbfs_boot_device
*cbd
= cbfs_get_boot_device(force_ro
);
50 enum cb_err err
= CB_CBFS_CACHE_FULL
;
51 if (!CONFIG(NO_CBFS_MCACHE
) && !ENV_SMM
&& cbd
->mcache_size
)
52 err
= cbfs_mcache_lookup(cbd
->mcache
, cbd
->mcache_size
,
53 name
, mdata
, &data_offset
);
54 if (err
== CB_CBFS_CACHE_FULL
) {
55 struct vb2_hash
*metadata_hash
= NULL
;
56 if (CONFIG(TOCTOU_SAFETY
)) {
57 if (ENV_SMM
) /* Cannot provide TOCTOU safety for SMM */
59 if (!cbd
->mcache_size
)
60 die("Cannot access CBFS TOCTOU-safely in " ENV_STRING
" before CBMEM init!\n");
61 /* We can only reach this for the RW CBFS -- an mcache overflow in the
62 RO CBFS would have been caught when building the mcache in cbfs_get
63 boot_device(). (Note that TOCTOU_SAFETY implies !NO_CBFS_MCACHE.) */
64 assert(cbd
== vboot_get_cbfs_boot_device());
66 || vb2api_get_metadata_hash(vboot_get_context(), &metadata_hash
)
68 die("Failed to get RW metadata hash");
70 err
= cbfs_lookup(&cbd
->rdev
, name
, mdata
, &data_offset
, metadata_hash
);
73 if (CONFIG(VBOOT_ENABLE_CBFS_FALLBACK
) && !force_ro
&& err
== CB_CBFS_NOT_FOUND
) {
74 printk(BIOS_INFO
, "CBFS: Fall back to RO region for %s\n", name
);
75 return _cbfs_boot_lookup(name
, true, mdata
, rdev
);
78 if (err
== CB_CBFS_NOT_FOUND
)
79 printk(BIOS_WARNING
, "CBFS: '%s' not found.\n", name
);
80 else if (err
== CB_CBFS_HASH_MISMATCH
)
81 printk(BIOS_ERR
, "CBFS ERROR: metadata hash mismatch!\n");
83 printk(BIOS_ERR
, "CBFS ERROR: error %d when looking up '%s'\n",
88 if (rdev_chain(rdev
, &cbd
->rdev
, data_offset
, be32toh(mdata
->h
.len
)))
94 void cbfs_unmap(void *mapping
)
97 * This is save to call with mappings that weren't allocated in the cache (e.g. x86
98 * direct mappings) -- mem_pool_free() just does nothing for addresses it doesn't
99 * recognize. This hardcodes the assumption that if platforms implement an rdev_mmap()
100 * that requires a free() for the boot_device, they need to implement it via the
101 * cbfs_cache mem_pool.
103 mem_pool_free(&cbfs_cache
, mapping
);
106 static inline bool fsps_env(void)
108 /* FSP-S is assumed to be loaded in ramstage. */
114 static inline bool fspm_env(void)
116 /* FSP-M is assumed to be loaded in romstage. */
122 static inline bool cbfs_lz4_enabled(void)
124 if (fsps_env() && CONFIG(FSP_COMPRESS_FSP_S_LZ4
))
126 if (fspm_env() && CONFIG(FSP_COMPRESS_FSP_M_LZ4
))
129 if ((ENV_BOOTBLOCK
|| ENV_SEPARATE_VERSTAGE
) && !CONFIG(COMPRESS_PRERAM_STAGES
))
138 static inline bool cbfs_lzma_enabled(void)
140 if (fsps_env() && CONFIG(FSP_COMPRESS_FSP_S_LZMA
))
142 if (fspm_env() && CONFIG(FSP_COMPRESS_FSP_M_LZMA
))
145 /* Payload loader (ramstage) always needs LZMA. */
146 if (ENV_PAYLOAD_LOADER
)
148 /* Only other use of LZMA is ramstage compression. */
149 if (!CONFIG(COMPRESS_RAMSTAGE_LZMA
))
151 /* If there is a postcar, it loads the ramstage. */
152 if (CONFIG(POSTCAR_STAGE
))
154 /* If there is no postcar but a separate romstage, it loads the ramstage. */
155 if (CONFIG(SEPARATE_ROMSTAGE
))
156 return ENV_SEPARATE_ROMSTAGE
;
157 /* Otherwise, the combined bootblock+romstage loads the ramstage. */
158 return ENV_BOOTBLOCK
;
161 static bool cbfs_file_hash_mismatch(const void *buffer
, size_t size
,
162 const union cbfs_mdata
*mdata
, bool skip_verification
)
164 /* Avoid linking hash functions when verification and measurement are disabled. */
165 if (!CONFIG(CBFS_VERIFICATION
) && !CONFIG(TPM_MEASURED_BOOT
))
168 const struct vb2_hash
*hash
= NULL
;
170 if (CONFIG(CBFS_VERIFICATION
) && !skip_verification
) {
171 hash
= cbfs_file_hash(mdata
);
173 ERROR("'%s' does not have a file hash!\n", mdata
->h
.filename
);
177 vb2_error_t rv
= vb2_hash_verify(vboot_hwcrypto_allowed(), buffer
, size
, hash
);
178 if (rv
!= VB2_SUCCESS
) {
179 ERROR("'%s' file hash mismatch!\n", mdata
->h
.filename
);
180 if (CONFIG(VBOOT_CBFS_INTEGRATION
) && !vboot_recovery_mode_enabled()
181 && vboot_logic_executed())
182 vboot_fail_and_reboot(vboot_get_context(), VB2_RECOVERY_FW_BODY
,
188 if (CONFIG(TPM_MEASURED_BOOT
) && !ENV_SMM
) {
189 struct vb2_hash calculated_hash
;
191 /* No need to re-hash file if we already have it from verification. */
192 if (!hash
|| hash
->algo
!= TPM_MEASURE_ALGO
) {
193 if (vb2_hash_calculate(vboot_hwcrypto_allowed(), buffer
, size
,
194 TPM_MEASURE_ALGO
, &calculated_hash
))
197 hash
= &calculated_hash
;
201 tspi_cbfs_measurement(mdata
->h
.filename
, be32toh(mdata
->h
.type
), hash
))
202 ERROR("failed to measure '%s' into TPM log\n", mdata
->h
.filename
);
203 /* We intentionally continue to boot on measurement errors. */
209 static size_t cbfs_load_and_decompress(const struct region_device
*rdev
, void *buffer
,
210 size_t buffer_size
, uint32_t compression
,
211 const union cbfs_mdata
*mdata
, bool skip_verification
)
213 size_t in_size
= region_device_sz(rdev
);
217 DEBUG("Decompressing %zu bytes from '%s' to %p with algo %d\n",
218 in_size
, mdata
->h
.filename
, buffer
, compression
);
220 if (CONFIG(CBFS_VERIFICATION
) && !CONFIG(CBFS_ALLOW_UNVERIFIED_DECOMPRESSION
) &&
221 skip_verification
&& compression
!= CBFS_COMPRESS_NONE
) {
222 ERROR("Refusing to decompress unverified file '%s' with algo %d\n",
223 mdata
->h
.filename
, compression
);
227 switch (compression
) {
228 case CBFS_COMPRESS_NONE
:
229 if (buffer_size
< in_size
)
231 if (rdev_readat(rdev
, buffer
, 0, in_size
) != in_size
)
233 if (cbfs_file_hash_mismatch(buffer
, in_size
, mdata
, skip_verification
))
237 case CBFS_COMPRESS_LZ4
:
238 if (!cbfs_lz4_enabled())
241 /* cbfs_prog_stage_load() takes care of in-place LZ4 decompression by
242 setting up the rdev to be in memory. */
243 map
= rdev_mmap_full(rdev
);
247 if (!cbfs_file_hash_mismatch(map
, in_size
, mdata
, skip_verification
)) {
248 timestamp_add_now(TS_ULZ4F_START
);
249 out_size
= ulz4fn(map
, in_size
, buffer
, buffer_size
);
250 timestamp_add_now(TS_ULZ4F_END
);
253 rdev_munmap(rdev
, map
);
257 case CBFS_COMPRESS_LZMA
:
258 if (!cbfs_lzma_enabled())
260 map
= rdev_mmap_full(rdev
);
264 if (!cbfs_file_hash_mismatch(map
, in_size
, mdata
, skip_verification
)) {
265 /* Note: timestamp not useful for memory-mapped media (x86) */
266 timestamp_add_now(TS_ULZMA_START
);
267 out_size
= ulzman(map
, in_size
, buffer
, buffer_size
);
268 timestamp_add_now(TS_ULZMA_END
);
271 rdev_munmap(rdev
, map
);
280 struct cbfs_preload_context
{
281 struct region_device rdev
;
282 struct thread_handle handle
;
283 struct list_node list_node
;
288 static struct list_node cbfs_preload_context_list
;
290 static struct cbfs_preload_context
*alloc_cbfs_preload_context(size_t additional
)
292 struct cbfs_preload_context
*context
;
293 size_t size
= sizeof(*context
) + additional
;
295 context
= mem_pool_alloc(&cbfs_cache
, size
);
300 memset(context
, 0, size
);
305 static void append_cbfs_preload_context(struct cbfs_preload_context
*context
)
307 list_append(&context
->list_node
, &cbfs_preload_context_list
);
310 static void free_cbfs_preload_context(struct cbfs_preload_context
*context
)
312 list_remove(&context
->list_node
);
314 mem_pool_free(&cbfs_cache
, context
);
317 static enum cb_err
cbfs_preload_thread_entry(void *arg
)
319 struct cbfs_preload_context
*context
= arg
;
321 if (rdev_read_full(&context
->rdev
, context
->buffer
) < 0) {
322 ERROR("%s(name='%s') readat failed\n", __func__
, context
->name
);
329 void cbfs_preload(const char *name
)
331 struct region_device rdev
;
332 union cbfs_mdata mdata
;
333 struct cbfs_preload_context
*context
;
334 bool force_ro
= false;
337 if (!CONFIG(CBFS_PRELOAD
))
340 /* We don't want to cross the vboot boundary */
341 if (ENV_SEPARATE_ROMSTAGE
&& CONFIG(VBOOT_STARTS_IN_ROMSTAGE
))
344 DEBUG("%s(name='%s')\n", __func__
, name
);
346 if (_cbfs_boot_lookup(name
, force_ro
, &mdata
, &rdev
))
349 size
= region_device_sz(&rdev
);
351 context
= alloc_cbfs_preload_context(strlen(name
) + 1);
353 ERROR("%s(name='%s') failed to allocate preload context\n", __func__
, name
);
357 context
->buffer
= mem_pool_alloc(&cbfs_cache
, size
);
358 if (context
->buffer
== NULL
) {
359 ERROR("%s(name='%s') failed to allocate %zu bytes for preload buffer\n",
360 __func__
, name
, size
);
364 context
->rdev
= rdev
;
365 strcpy(context
->name
, name
);
367 append_cbfs_preload_context(context
);
369 if (thread_run(&context
->handle
, cbfs_preload_thread_entry
, context
) == 0)
372 ERROR("%s(name='%s') failed to start preload thread\n", __func__
, name
);
373 mem_pool_free(&cbfs_cache
, context
->buffer
);
376 free_cbfs_preload_context(context
);
379 static struct cbfs_preload_context
*find_cbfs_preload_context(const char *name
)
381 struct cbfs_preload_context
*context
;
383 list_for_each(context
, cbfs_preload_context_list
, list_node
) {
384 if (strcmp(context
->name
, name
) == 0)
391 static enum cb_err
get_preload_rdev(struct region_device
*rdev
, const char *name
)
394 struct cbfs_preload_context
*context
;
396 if (!CONFIG(CBFS_PRELOAD
) || !ENV_SUPPORTS_COOP
)
399 context
= find_cbfs_preload_context(name
);
403 err
= thread_join(&context
->handle
);
404 if (err
!= CB_SUCCESS
) {
405 ERROR("%s(name='%s') Preload thread failed: %u\n", __func__
, name
, err
);
410 if (rdev_chain_mem(rdev
, context
->buffer
, region_device_sz(&context
->rdev
)) != 0) {
411 ERROR("%s(name='%s') chaining failed\n", __func__
, name
);
419 DEBUG("%s(name='%s') preload successful\n", __func__
, name
);
422 free_cbfs_preload_context(context
);
427 static void *do_alloc(union cbfs_mdata
*mdata
, struct region_device
*rdev
,
428 cbfs_allocator_t allocator
, void *arg
, size_t *size_out
,
429 bool skip_verification
)
431 size_t size
= region_device_sz(rdev
);
434 uint32_t compression
= CBFS_COMPRESS_NONE
;
435 const struct cbfs_file_attr_compression
*cattr
= cbfs_find_attr(mdata
,
436 CBFS_FILE_ATTR_TAG_COMPRESSION
, sizeof(*cattr
));
438 compression
= be32toh(cattr
->compression
);
439 size
= be32toh(cattr
->decompressed_size
);
445 /* allocator == NULL means do a cbfs_map() */
447 loc
= allocator(arg
, size
, mdata
);
448 } else if (compression
== CBFS_COMPRESS_NONE
) {
449 void *mapping
= rdev_mmap_full(rdev
);
452 if (cbfs_file_hash_mismatch(mapping
, size
, mdata
, skip_verification
)) {
453 rdev_munmap(rdev
, mapping
);
457 } else if (!cbfs_cache
.size
) {
458 /* In order to use the cbfs_cache you need to add a CBFS_CACHE to your
460 ERROR("Cannot map compressed file %s without cbfs_cache\n", mdata
->h
.filename
);
463 loc
= mem_pool_alloc(&cbfs_cache
, size
);
467 ERROR("'%s' allocation failure\n", mdata
->h
.filename
);
471 size
= cbfs_load_and_decompress(rdev
, loc
, size
, compression
, mdata
, skip_verification
);
478 void *_cbfs_alloc(const char *name
, cbfs_allocator_t allocator
, void *arg
,
479 size_t *size_out
, bool force_ro
, enum cbfs_type
*type
)
481 struct region_device rdev
;
482 bool preload_successful
= false;
483 union cbfs_mdata mdata
;
485 DEBUG("%s(name='%s', alloc=%p(%p), force_ro=%s, type=%d)\n", __func__
, name
, allocator
,
486 arg
, force_ro
? "true" : "false", type
? *type
: -1);
488 if (_cbfs_boot_lookup(name
, force_ro
, &mdata
, &rdev
))
492 const enum cbfs_type real_type
= be32toh(mdata
.h
.type
);
493 if (*type
== CBFS_TYPE_QUERY
)
495 else if (*type
!= real_type
) {
496 ERROR("'%s' type mismatch (is %u, expected %u)\n",
497 mdata
.h
.filename
, real_type
, *type
);
502 /* Update the rdev with the preload content */
503 if (!force_ro
&& get_preload_rdev(&rdev
, name
) == CB_SUCCESS
)
504 preload_successful
= true;
506 void *ret
= do_alloc(&mdata
, &rdev
, allocator
, arg
, size_out
, false);
508 /* When using cbfs_preload we need to free the preload buffer after populating the
509 * destination buffer. We know we must have a mem_rdev here, so extra mmap is fine. */
510 if (preload_successful
)
511 cbfs_unmap(rdev_mmap_full(&rdev
));
516 void *_cbfs_unverified_area_alloc(const char *area
, const char *name
,
517 cbfs_allocator_t allocator
, void *arg
, size_t *size_out
)
519 struct region_device area_rdev
, file_rdev
;
520 union cbfs_mdata mdata
;
523 DEBUG("%s(area='%s', name='%s', alloc=%p(%p))\n", __func__
, area
, name
, allocator
, arg
);
525 if (fmap_locate_area_as_rdev(area
, &area_rdev
))
528 if (cbfs_lookup(&area_rdev
, name
, &mdata
, &data_offset
, NULL
)) {
529 ERROR("'%s' not found in '%s'\n", name
, area
);
533 if (rdev_chain(&file_rdev
, &area_rdev
, data_offset
, be32toh(mdata
.h
.len
)))
536 return do_alloc(&mdata
, &file_rdev
, allocator
, arg
, size_out
, true);
539 void *_cbfs_default_allocator(void *arg
, size_t size
, const union cbfs_mdata
*unused
)
541 struct _cbfs_default_allocator_arg
*darg
= arg
;
542 if (size
> darg
->buf_size
)
547 void *_cbfs_cbmem_allocator(void *arg
, size_t size
, const union cbfs_mdata
*unused
)
549 return cbmem_add((uintptr_t)arg
, size
);
552 enum cb_err
cbfs_prog_stage_load(struct prog
*pstage
)
554 union cbfs_mdata mdata
;
555 struct region_device rdev
;
558 prog_locate_hook(pstage
);
560 if ((err
= _cbfs_boot_lookup(prog_name(pstage
), false, &mdata
, &rdev
)))
563 assert(be32toh(mdata
.h
.type
) == CBFS_TYPE_STAGE
);
564 pstage
->cbfs_type
= CBFS_TYPE_STAGE
;
566 enum cbfs_compression compression
= CBFS_COMPRESS_NONE
;
567 const struct cbfs_file_attr_compression
*cattr
= cbfs_find_attr(&mdata
,
568 CBFS_FILE_ATTR_TAG_COMPRESSION
, sizeof(*cattr
));
570 compression
= be32toh(cattr
->compression
);
572 const struct cbfs_file_attr_stageheader
*sattr
= cbfs_find_attr(&mdata
,
573 CBFS_FILE_ATTR_TAG_STAGEHEADER
, sizeof(*sattr
));
576 prog_set_area(pstage
, (void *)(uintptr_t)be64toh(sattr
->loadaddr
),
577 be32toh(sattr
->memlen
));
578 prog_set_entry(pstage
, prog_start(pstage
) +
579 be32toh(sattr
->entry_offset
), NULL
);
581 /* Hacky way to not load programs over read only media. The stages
582 * that would hit this path initialize themselves. */
583 if ((ENV_BOOTBLOCK
|| ENV_SEPARATE_VERSTAGE
) &&
584 !CONFIG(NO_XIP_EARLY_STAGES
) && CONFIG(BOOT_DEVICE_MEMORY_MAPPED
)) {
585 void *mapping
= rdev_mmap_full(&rdev
);
586 rdev_munmap(&rdev
, mapping
);
587 if (cbfs_file_hash_mismatch(mapping
, region_device_sz(&rdev
), &mdata
, false))
588 return CB_CBFS_HASH_MISMATCH
;
589 if (mapping
== prog_start(pstage
))
593 /* LZ4 stages can be decompressed in-place to save mapping scratch space. Load the
594 compressed data to the end of the buffer and point &rdev to that memory location. */
595 if (cbfs_lz4_enabled() && compression
== CBFS_COMPRESS_LZ4
) {
596 size_t in_size
= region_device_sz(&rdev
);
597 void *compr_start
= prog_start(pstage
) + prog_size(pstage
) - in_size
;
598 if (rdev_readat(&rdev
, compr_start
, 0, in_size
) != in_size
)
600 rdev_chain_mem(&rdev
, compr_start
, in_size
);
603 size_t fsize
= cbfs_load_and_decompress(&rdev
, prog_start(pstage
), prog_size(pstage
),
604 compression
, &mdata
, false);
608 /* Clear area not covered by file. */
609 memset(prog_start(pstage
) + fsize
, 0, prog_size(pstage
) - fsize
);
611 prog_segment_loaded((uintptr_t)prog_start(pstage
), prog_size(pstage
),
617 void cbfs_boot_device_find_mcache(struct cbfs_boot_device
*cbd
, uint32_t id
)
619 if (CONFIG(NO_CBFS_MCACHE
) || ENV_SMM
)
622 if (cbd
->mcache_size
)
625 const struct cbmem_entry
*entry
;
627 (entry
= cbmem_entry_find(id
))) {
628 cbd
->mcache
= cbmem_entry_start(entry
);
629 cbd
->mcache_size
= cbmem_entry_size(entry
);
630 } else if (ENV_ROMSTAGE_OR_BEFORE
) {
631 u8
*boundary
= _ecbfs_mcache
- REGION_SIZE(cbfs_mcache
) *
632 CONFIG_CBFS_MCACHE_RW_PERCENTAGE
/ 100;
633 boundary
= (u8
*)ALIGN_DOWN((uintptr_t)boundary
, CBFS_MCACHE_ALIGNMENT
);
634 if (id
== CBMEM_ID_CBFS_RO_MCACHE
) {
635 cbd
->mcache
= _cbfs_mcache
;
636 cbd
->mcache_size
= boundary
- _cbfs_mcache
;
637 } else if (id
== CBMEM_ID_CBFS_RW_MCACHE
) {
638 cbd
->mcache
= boundary
;
639 cbd
->mcache_size
= _ecbfs_mcache
- boundary
;
644 enum cb_err
cbfs_init_boot_device(const struct cbfs_boot_device
*cbd
,
645 struct vb2_hash
*mdata_hash
)
647 /* If we have an mcache, mcache_build() will also check mdata hash. */
648 if (!CONFIG(NO_CBFS_MCACHE
) && !ENV_SMM
&& cbd
->mcache_size
> 0)
649 return cbfs_mcache_build(&cbd
->rdev
, cbd
->mcache
, cbd
->mcache_size
, mdata_hash
);
651 /* No mcache and no verification means we have nothing special to do. */
652 if (!CONFIG(CBFS_VERIFICATION
) || !mdata_hash
)
655 /* Verification only: use cbfs_walk() without a walker() function to just run through
656 the CBFS once, will return NOT_FOUND by default. */
657 enum cb_err err
= cbfs_walk(&cbd
->rdev
, NULL
, NULL
, mdata_hash
, 0);
658 if (err
== CB_CBFS_NOT_FOUND
)
663 const struct cbfs_boot_device
*cbfs_get_boot_device(bool force_ro
)
665 static struct cbfs_boot_device ro
;
667 /* Ensure we always init RO mcache, even if the first file is from the RW CBFS.
668 Otherwise it may not be available when needed in later stages. */
669 if (ENV_INITIAL_STAGE
&& !force_ro
&& !region_device_sz(&ro
.rdev
))
670 cbfs_get_boot_device(true);
673 const struct cbfs_boot_device
*rw
= vboot_get_cbfs_boot_device();
674 /* This will return NULL if vboot isn't enabled, didn't run yet or decided to
675 boot into recovery mode. */
680 /* In rare cases post-RAM stages may run this before cbmem_initialize(), so we can't
681 lock in the result of find_mcache() on the first try and should keep trying every
682 time until an mcache is found. */
683 cbfs_boot_device_find_mcache(&ro
, CBMEM_ID_CBFS_RO_MCACHE
);
685 if (region_device_sz(&ro
.rdev
))
688 if (fmap_locate_area_as_rdev("COREBOOT", &ro
.rdev
))
689 die("Cannot locate primary CBFS");
691 if (ENV_INITIAL_STAGE
) {
692 enum cb_err err
= cbfs_init_boot_device(&ro
, metadata_hash_get());
693 if (err
== CB_CBFS_HASH_MISMATCH
)
694 die("RO CBFS metadata hash verification failure");
695 else if (CONFIG(TOCTOU_SAFETY
) && err
== CB_CBFS_CACHE_FULL
)
696 die("RO mcache overflow breaks TOCTOU safety!\n");
697 else if (err
&& err
!= CB_CBFS_CACHE_FULL
)
698 die("RO CBFS initialization error: %d", err
);
704 #if !CONFIG(NO_CBFS_MCACHE)
705 static void mcache_to_cbmem(const struct cbfs_boot_device
*cbd
, u32 cbmem_id
)
710 size_t real_size
= cbfs_mcache_real_size(cbd
->mcache
, cbd
->mcache_size
);
711 void *cbmem_mcache
= cbmem_add(cbmem_id
, real_size
);
713 printk(BIOS_ERR
, "Cannot allocate CBMEM mcache %#x (%#zx bytes)!\n",
714 cbmem_id
, real_size
);
717 memcpy(cbmem_mcache
, cbd
->mcache
, real_size
);
720 static void cbfs_mcache_migrate(int unused
)
722 mcache_to_cbmem(vboot_get_cbfs_boot_device(), CBMEM_ID_CBFS_RW_MCACHE
);
723 mcache_to_cbmem(cbfs_get_boot_device(true), CBMEM_ID_CBFS_RO_MCACHE
);
725 CBMEM_CREATION_HOOK(cbfs_mcache_migrate
);