coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
cbfs.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <boot_device.h>
5 #include <cbfs.h>
6 #include <cbmem.h>
9 #include <console/console.h>
10 #include <fmap.h>
11 #include <lib.h>
12 #include <list.h>
13 #include <metadata_hash.h>
14 #include <security/tpm/tspi/crtm.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <symbols.h>
19 #include <thread.h>
20 #include <timestamp.h>
21 
22 #if ENV_STAGE_HAS_DATA_SECTION
23 struct mem_pool cbfs_cache =
24  MEM_POOL_INIT(_cbfs_cache, REGION_SIZE(cbfs_cache), CONFIG_CBFS_CACHE_ALIGN);
25 #else
26 struct mem_pool cbfs_cache = MEM_POOL_INIT(NULL, 0, 0);
27 #endif
28 
29 static void switch_to_postram_cache(int unused)
30 {
31  if (_preram_cbfs_cache != _postram_cbfs_cache)
32  mem_pool_init(&cbfs_cache, _postram_cbfs_cache, REGION_SIZE(postram_cbfs_cache),
33  CONFIG_CBFS_CACHE_ALIGN);
34 }
36 
37 enum cb_err _cbfs_boot_lookup(const char *name, bool force_ro,
38  union cbfs_mdata *mdata, struct region_device *rdev)
39 {
40  const struct cbfs_boot_device *cbd = cbfs_get_boot_device(force_ro);
41  if (!cbd)
42  return CB_ERR;
43 
44  size_t data_offset;
45  enum cb_err err = CB_CBFS_CACHE_FULL;
46  if (!CONFIG(NO_CBFS_MCACHE) && !ENV_SMM && cbd->mcache_size)
47  err = cbfs_mcache_lookup(cbd->mcache, cbd->mcache_size,
48  name, mdata, &data_offset);
49  if (err == CB_CBFS_CACHE_FULL) {
50  struct vb2_hash *metadata_hash = NULL;
51  if (CONFIG(TOCTOU_SAFETY)) {
52  if (ENV_SMM) /* Cannot provide TOCTOU safety for SMM */
53  dead_code();
54  if (!cbd->mcache_size)
55  die("Cannot access CBFS TOCTOU-safely in " ENV_STRING " before CBMEM init!\n");
56  /* We can only reach this for the RW CBFS -- an mcache overflow in the
57  RO CBFS would have been caught when building the mcache in cbfs_get
58  boot_device(). (Note that TOCTOU_SAFETY implies !NO_CBFS_MCACHE.) */
60  die("TODO: set metadata_hash to RW metadata hash here.\n");
61  }
62  err = cbfs_lookup(&cbd->rdev, name, mdata, &data_offset, metadata_hash);
63  }
64 
65  if (CONFIG(VBOOT_ENABLE_CBFS_FALLBACK) && !force_ro && err == CB_CBFS_NOT_FOUND) {
66  printk(BIOS_INFO, "CBFS: Fall back to RO region for %s\n", name);
67  return _cbfs_boot_lookup(name, true, mdata, rdev);
68  }
69  if (err) {
70  if (err == CB_CBFS_NOT_FOUND)
71  printk(BIOS_WARNING, "CBFS: '%s' not found.\n", name);
72  else if (err == CB_CBFS_HASH_MISMATCH)
73  printk(BIOS_ERR, "CBFS ERROR: metadata hash mismatch!\n");
74  else
75  printk(BIOS_ERR, "CBFS ERROR: error %d when looking up '%s'\n",
76  err, name);
77  return err;
78  }
79 
80  if (rdev_chain(rdev, &cbd->rdev, data_offset, be32toh(mdata->h.len)))
81  return CB_ERR;
82 
83  return CB_SUCCESS;
84 }
85 
86 void cbfs_unmap(void *mapping)
87 {
88  /*
89  * This is save to call with mappings that weren't allocated in the cache (e.g. x86
90  * direct mappings) -- mem_pool_free() just does nothing for addresses it doesn't
91  * recognize. This hardcodes the assumption that if platforms implement an rdev_mmap()
92  * that requires a free() for the boot_device, they need to implement it via the
93  * cbfs_cache mem_pool.
94  */
95  mem_pool_free(&cbfs_cache, mapping);
96 }
97 
98 static inline bool fsps_env(void)
99 {
100  /* FSP-S is assumed to be loaded in ramstage. */
101  if (ENV_RAMSTAGE)
102  return true;
103  return false;
104 }
105 
106 static inline bool fspm_env(void)
107 {
108  /* FSP-M is assumed to be loaded in romstage. */
109  if (ENV_ROMSTAGE)
110  return true;
111  return false;
112 }
113 
114 static inline bool cbfs_lz4_enabled(void)
115 {
116  if (fsps_env() && CONFIG(FSP_COMPRESS_FSP_S_LZ4))
117  return true;
118  if (fspm_env() && CONFIG(FSP_COMPRESS_FSP_M_LZ4))
119  return true;
120 
121  if ((ENV_BOOTBLOCK || ENV_SEPARATE_VERSTAGE) && !CONFIG(COMPRESS_PRERAM_STAGES))
122  return false;
123 
124  if (ENV_SMM)
125  return false;
126 
127  return true;
128 }
129 
130 static inline bool cbfs_lzma_enabled(void)
131 {
132  if (fsps_env() && CONFIG(FSP_COMPRESS_FSP_S_LZMA))
133  return true;
134  if (fspm_env() && CONFIG(FSP_COMPRESS_FSP_M_LZMA))
135  return true;
136  /* We assume here romstage and postcar are never compressed. */
138  return false;
139  if (ENV_ROMSTAGE && CONFIG(POSTCAR_STAGE))
140  return false;
141  if ((ENV_ROMSTAGE || ENV_POSTCAR) && !CONFIG(COMPRESS_RAMSTAGE))
142  return false;
143  if (ENV_SMM)
144  return false;
145  return true;
146 }
147 
148 static bool cbfs_file_hash_mismatch(const void *buffer, size_t size,
149  const union cbfs_mdata *mdata, bool skip_verification)
150 {
151  /* Avoid linking hash functions when verification and measurement are disabled. */
152  if (!CONFIG(CBFS_VERIFICATION) && !CONFIG(TPM_MEASURED_BOOT))
153  return false;
154 
155  const struct vb2_hash *hash = NULL;
156 
157  if (CONFIG(CBFS_VERIFICATION) && !skip_verification) {
158  hash = cbfs_file_hash(mdata);
159  if (!hash) {
160  ERROR("'%s' does not have a file hash!\n", mdata->h.filename);
161  return true;
162  }
163  if (vb2_hash_verify(buffer, size, hash) != VB2_SUCCESS) {
164  ERROR("'%s' file hash mismatch!\n", mdata->h.filename);
165  return true;
166  }
167  }
168 
169  if (CONFIG(TPM_MEASURED_BOOT) && !ENV_SMM) {
170  struct vb2_hash calculated_hash;
171 
172  /* No need to re-hash file if we already have it from verification. */
173  if (!hash || hash->algo != TPM_MEASURE_ALGO) {
174  vb2_hash_calculate(buffer, size, TPM_MEASURE_ALGO, &calculated_hash);
175  hash = &calculated_hash;
176  }
177 
178  if (tspi_cbfs_measurement(mdata->h.filename, be32toh(mdata->h.type), hash))
179  ERROR("failed to measure '%s' into TCPA log\n", mdata->h.filename);
180  /* We intentionally continue to boot on measurement errors. */
181  }
182 
183  return false;
184 }
185 
186 static size_t cbfs_load_and_decompress(const struct region_device *rdev, void *buffer,
187  size_t buffer_size, uint32_t compression,
188  const union cbfs_mdata *mdata, bool skip_verification)
189 {
190  size_t in_size = region_device_sz(rdev);
191  size_t out_size = 0;
192  void *map;
193 
194  DEBUG("Decompressing %zu bytes from '%s' to %p with algo %d\n",
195  in_size, mdata->h.filename, buffer, compression);
196 
197  switch (compression) {
198  case CBFS_COMPRESS_NONE:
199  if (buffer_size < in_size)
200  return 0;
201  if (rdev_readat(rdev, buffer, 0, in_size) != in_size)
202  return 0;
203  if (cbfs_file_hash_mismatch(buffer, in_size, mdata, skip_verification))
204  return 0;
205  return in_size;
206 
207  case CBFS_COMPRESS_LZ4:
208  if (!cbfs_lz4_enabled())
209  return 0;
210 
211  /* cbfs_prog_stage_load() takes care of in-place LZ4 decompression by
212  setting up the rdev to be in memory. */
213  map = rdev_mmap_full(rdev);
214  if (map == NULL)
215  return 0;
216 
217  if (!cbfs_file_hash_mismatch(map, in_size, mdata, skip_verification)) {
219  out_size = ulz4fn(map, in_size, buffer, buffer_size);
221  }
222 
223  rdev_munmap(rdev, map);
224 
225  return out_size;
226 
227  case CBFS_COMPRESS_LZMA:
228  if (!cbfs_lzma_enabled())
229  return 0;
230  map = rdev_mmap_full(rdev);
231  if (map == NULL)
232  return 0;
233 
234  if (!cbfs_file_hash_mismatch(map, in_size, mdata, skip_verification)) {
235  /* Note: timestamp not useful for memory-mapped media (x86) */
237  out_size = ulzman(map, in_size, buffer, buffer_size);
239  }
240 
241  rdev_munmap(rdev, map);
242 
243  return out_size;
244 
245  default:
246  return 0;
247  }
248 }
249 
251  struct region_device rdev;
252  struct thread_handle handle;
253  struct list_node list_node;
254  void *buffer;
255  char name[];
256 };
257 
259 
260 static struct cbfs_preload_context *alloc_cbfs_preload_context(size_t additional)
261 {
262  struct cbfs_preload_context *context;
263  size_t size = sizeof(*context) + additional;
264 
265  context = mem_pool_alloc(&cbfs_cache, size);
266 
267  if (!context)
268  return NULL;
269 
270  memset(context, 0, size);
271 
272  return context;
273 }
274 
276 {
278 }
279 
281 {
282  list_remove(&context->list_node);
283 
284  mem_pool_free(&cbfs_cache, context);
285 }
286 
287 static enum cb_err cbfs_preload_thread_entry(void *arg)
288 {
289  struct cbfs_preload_context *context = arg;
290 
291  if (rdev_read_full(&context->rdev, context->buffer) < 0) {
292  ERROR("%s(name='%s') readat failed\n", __func__, context->name);
293  return CB_ERR;
294  }
295 
296  return CB_SUCCESS;
297 }
298 
299 void cbfs_preload(const char *name)
300 {
301  struct region_device rdev;
302  union cbfs_mdata mdata;
303  struct cbfs_preload_context *context;
304  bool force_ro = false;
305  size_t size;
306 
307  if (!CONFIG(CBFS_PRELOAD))
308  dead_code();
309 
310  /* We don't want to cross the vboot boundary */
311  if (ENV_ROMSTAGE && CONFIG(VBOOT_STARTS_IN_ROMSTAGE))
312  return;
313 
314  DEBUG("%s(name='%s')\n", __func__, name);
315 
316  if (_cbfs_boot_lookup(name, force_ro, &mdata, &rdev))
317  return;
318 
319  size = region_device_sz(&rdev);
320 
321  context = alloc_cbfs_preload_context(strlen(name) + 1);
322  if (!context) {
323  ERROR("%s(name='%s') failed to allocate preload context\n", __func__, name);
324  return;
325  }
326 
327  context->buffer = mem_pool_alloc(&cbfs_cache, size);
328  if (context->buffer == NULL) {
329  ERROR("%s(name='%s') failed to allocate %zu bytes for preload buffer\n",
330  __func__, name, size);
331  goto out;
332  }
333 
334  context->rdev = rdev;
335  strcpy(context->name, name);
336 
338 
339  if (thread_run(&context->handle, cbfs_preload_thread_entry, context) == 0)
340  return;
341 
342  ERROR("%s(name='%s') failed to start preload thread\n", __func__, name);
343  mem_pool_free(&cbfs_cache, context->buffer);
344 
345 out:
346  free_cbfs_preload_context(context);
347 }
348 
350 {
351  struct cbfs_preload_context *context;
352 
354  if (strcmp(context->name, name) == 0)
355  return context;
356  }
357 
358  return NULL;
359 }
360 
361 static enum cb_err get_preload_rdev(struct region_device *rdev, const char *name)
362 {
363  enum cb_err err;
364  struct cbfs_preload_context *context;
365 
366  if (!CONFIG(CBFS_PRELOAD) || !ENV_STAGE_SUPPORTS_COOP)
367  return CB_ERR_ARG;
368 
369  context = find_cbfs_preload_context(name);
370  if (!context)
371  return CB_ERR_ARG;
372 
373  err = thread_join(&context->handle);
374  if (err != CB_SUCCESS) {
375  ERROR("%s(name='%s') Preload thread failed: %u\n", __func__, name, err);
376 
377  goto out;
378  }
379 
380  if (rdev_chain_mem(rdev, context->buffer, region_device_sz(&context->rdev)) != 0) {
381  ERROR("%s(name='%s') chaining failed\n", __func__, name);
382 
383  err = CB_ERR;
384  goto out;
385  }
386 
387  err = CB_SUCCESS;
388 
389  DEBUG("%s(name='%s') preload successful\n", __func__, name);
390 
391 out:
392  free_cbfs_preload_context(context);
393 
394  return err;
395 }
396 
397 static void *do_alloc(union cbfs_mdata *mdata, struct region_device *rdev,
398  cbfs_allocator_t allocator, void *arg, size_t *size_out,
399  bool skip_verification)
400 {
401  size_t size = region_device_sz(rdev);
402  void *loc = NULL;
403 
404  uint32_t compression = CBFS_COMPRESS_NONE;
405  const struct cbfs_file_attr_compression *cattr = cbfs_find_attr(mdata,
406  CBFS_FILE_ATTR_TAG_COMPRESSION, sizeof(*cattr));
407  if (cattr) {
408  compression = be32toh(cattr->compression);
409  size = be32toh(cattr->decompressed_size);
410  }
411 
412  if (size_out)
413  *size_out = size;
414 
415  /* allocator == NULL means do a cbfs_map() */
416  if (allocator) {
417  loc = allocator(arg, size, mdata);
418  } else if (compression == CBFS_COMPRESS_NONE) {
419  void *mapping = rdev_mmap_full(rdev);
420  if (!mapping)
421  return NULL;
422  if (cbfs_file_hash_mismatch(mapping, size, mdata, skip_verification)) {
423  rdev_munmap(rdev, mapping);
424  return NULL;
425  }
426  return mapping;
427  } else if (!cbfs_cache.size) {
428  /* In order to use the cbfs_cache you need to add a CBFS_CACHE to your
429  * memlayout. For stages that don't have .data sections (x86 pre-RAM),
430  * it is not possible to add a CBFS_CACHE. */
431  ERROR("Cannot map compressed file %s without cbfs_cache\n", mdata->h.filename);
432  return NULL;
433  } else {
434  loc = mem_pool_alloc(&cbfs_cache, size);
435  }
436 
437  if (!loc) {
438  ERROR("'%s' allocation failure\n", mdata->h.filename);
439  return NULL;
440  }
441 
442  size = cbfs_load_and_decompress(rdev, loc, size, compression, mdata, skip_verification);
443  if (!size)
444  return NULL;
445 
446  return loc;
447 }
448 
449 void *_cbfs_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
450  size_t *size_out, bool force_ro, enum cbfs_type *type)
451 {
452  struct region_device rdev;
453  bool preload_successful = false;
454  union cbfs_mdata mdata;
455 
456  DEBUG("%s(name='%s', alloc=%p(%p), force_ro=%s, type=%d)\n", __func__, name, allocator,
457  arg, force_ro ? "true" : "false", type ? *type : -1);
458 
459  if (_cbfs_boot_lookup(name, force_ro, &mdata, &rdev))
460  return NULL;
461 
462  if (type) {
463  const enum cbfs_type real_type = be32toh(mdata.h.type);
464  if (*type == CBFS_TYPE_QUERY)
465  *type = real_type;
466  else if (*type != real_type) {
467  ERROR("'%s' type mismatch (is %u, expected %u)\n",
468  mdata.h.filename, real_type, *type);
469  return NULL;
470  }
471  }
472 
473  /* Update the rdev with the preload content */
474  if (!force_ro && get_preload_rdev(&rdev, name) == CB_SUCCESS)
475  preload_successful = true;
476 
477  void *ret = do_alloc(&mdata, &rdev, allocator, arg, size_out, false);
478 
479  /* When using cbfs_preload we need to free the preload buffer after populating the
480  * destination buffer. We know we must have a mem_rdev here, so extra mmap is fine. */
481  if (preload_successful)
483 
484  return ret;
485 }
486 
487 void *_cbfs_unverified_area_alloc(const char *area, const char *name,
488  cbfs_allocator_t allocator, void *arg, size_t *size_out)
489 {
490  struct region_device area_rdev, file_rdev;
491  union cbfs_mdata mdata;
492  size_t data_offset;
493 
494  DEBUG("%s(area='%s', name='%s', alloc=%p(%p))\n", __func__, area, name, allocator, arg);
495 
496  if (fmap_locate_area_as_rdev(area, &area_rdev))
497  return NULL;
498 
499  if (cbfs_lookup(&area_rdev, name, &mdata, &data_offset, NULL)) {
500  ERROR("'%s' not found in '%s'\n", name, area);
501  return NULL;
502  }
503 
504  if (rdev_chain(&file_rdev, &area_rdev, data_offset, be32toh(mdata.h.len)))
505  return NULL;
506 
507  return do_alloc(&mdata, &file_rdev, allocator, arg, size_out, true);
508 }
509 
510 void *_cbfs_default_allocator(void *arg, size_t size, const union cbfs_mdata *unused)
511 {
512  struct _cbfs_default_allocator_arg *darg = arg;
513  if (size > darg->buf_size)
514  return NULL;
515  return darg->buf;
516 }
517 
518 void *_cbfs_cbmem_allocator(void *arg, size_t size, const union cbfs_mdata *unused)
519 {
520  return cbmem_add((uintptr_t)arg, size);
521 }
522 
523 enum cb_err cbfs_prog_stage_load(struct prog *pstage)
524 {
525  union cbfs_mdata mdata;
526  struct region_device rdev;
527  enum cb_err err;
528 
529  prog_locate_hook(pstage);
530 
531  if ((err = _cbfs_boot_lookup(prog_name(pstage), false, &mdata, &rdev)))
532  return err;
533 
534  assert(be32toh(mdata.h.type) == CBFS_TYPE_STAGE);
535  pstage->cbfs_type = CBFS_TYPE_STAGE;
536 
537  enum cbfs_compression compression = CBFS_COMPRESS_NONE;
538  const struct cbfs_file_attr_compression *cattr = cbfs_find_attr(&mdata,
539  CBFS_FILE_ATTR_TAG_COMPRESSION, sizeof(*cattr));
540  if (cattr)
541  compression = be32toh(cattr->compression);
542 
543  const struct cbfs_file_attr_stageheader *sattr = cbfs_find_attr(&mdata,
544  CBFS_FILE_ATTR_TAG_STAGEHEADER, sizeof(*sattr));
545  if (!sattr)
546  return CB_ERR;
547  prog_set_area(pstage, (void *)(uintptr_t)be64toh(sattr->loadaddr),
548  be32toh(sattr->memlen));
549  prog_set_entry(pstage, prog_start(pstage) +
550  be32toh(sattr->entry_offset), NULL);
551 
552  /* Hacky way to not load programs over read only media. The stages
553  * that would hit this path initialize themselves. */
555  !CONFIG(NO_XIP_EARLY_STAGES) && CONFIG(BOOT_DEVICE_MEMORY_MAPPED)) {
556  void *mapping = rdev_mmap_full(&rdev);
557  rdev_munmap(&rdev, mapping);
558  if (cbfs_file_hash_mismatch(mapping, region_device_sz(&rdev), &mdata, false))
559  return CB_CBFS_HASH_MISMATCH;
560  if (mapping == prog_start(pstage))
561  return CB_SUCCESS;
562  }
563 
564  /* LZ4 stages can be decompressed in-place to save mapping scratch space. Load the
565  compressed data to the end of the buffer and point &rdev to that memory location. */
566  if (cbfs_lz4_enabled() && compression == CBFS_COMPRESS_LZ4) {
567  size_t in_size = region_device_sz(&rdev);
568  void *compr_start = prog_start(pstage) + prog_size(pstage) - in_size;
569  if (rdev_readat(&rdev, compr_start, 0, in_size) != in_size)
570  return CB_ERR;
571  rdev_chain_mem(&rdev, compr_start, in_size);
572  }
573 
574  size_t fsize = cbfs_load_and_decompress(&rdev, prog_start(pstage), prog_size(pstage),
575  compression, &mdata, false);
576  if (!fsize)
577  return CB_ERR;
578 
579  /* Clear area not covered by file. */
580  memset(prog_start(pstage) + fsize, 0, prog_size(pstage) - fsize);
581 
583  SEG_FINAL);
584 
585  return CB_SUCCESS;
586 }
587 
589 {
590  if (CONFIG(NO_CBFS_MCACHE) || ENV_SMM)
591  return;
592 
593  if (cbd->mcache_size)
594  return;
595 
596  const struct cbmem_entry *entry;
597  if (cbmem_possibly_online() &&
598  (entry = cbmem_entry_find(id))) {
599  cbd->mcache = cbmem_entry_start(entry);
600  cbd->mcache_size = cbmem_entry_size(entry);
601  } else if (ENV_ROMSTAGE_OR_BEFORE) {
602  u8 *boundary = _ecbfs_mcache - REGION_SIZE(cbfs_mcache) *
603  CONFIG_CBFS_MCACHE_RW_PERCENTAGE / 100;
604  boundary = (u8 *)ALIGN_DOWN((uintptr_t)boundary, CBFS_MCACHE_ALIGNMENT);
605  if (id == CBMEM_ID_CBFS_RO_MCACHE) {
606  cbd->mcache = _cbfs_mcache;
607  cbd->mcache_size = boundary - _cbfs_mcache;
608  } else if (id == CBMEM_ID_CBFS_RW_MCACHE) {
609  cbd->mcache = boundary;
610  cbd->mcache_size = _ecbfs_mcache - boundary;
611  }
612  }
613 }
614 
615 enum cb_err cbfs_init_boot_device(const struct cbfs_boot_device *cbd,
616  struct vb2_hash *mdata_hash)
617 {
618  /* If we have an mcache, mcache_build() will also check mdata hash. */
619  if (!CONFIG(NO_CBFS_MCACHE) && !ENV_SMM && cbd->mcache_size > 0)
620  return cbfs_mcache_build(&cbd->rdev, cbd->mcache, cbd->mcache_size, mdata_hash);
621 
622  /* No mcache and no verification means we have nothing special to do. */
623  if (!CONFIG(CBFS_VERIFICATION) || !mdata_hash)
624  return CB_SUCCESS;
625 
626  /* Verification only: use cbfs_walk() without a walker() function to just run through
627  the CBFS once, will return NOT_FOUND by default. */
628  enum cb_err err = cbfs_walk(&cbd->rdev, NULL, NULL, mdata_hash, 0);
629  if (err == CB_CBFS_NOT_FOUND)
630  err = CB_SUCCESS;
631  return err;
632 }
633 
634 const struct cbfs_boot_device *cbfs_get_boot_device(bool force_ro)
635 {
636  static struct cbfs_boot_device ro;
637 
638  /* Ensure we always init RO mcache, even if the first file is from the RW CBFS.
639  Otherwise it may not be available when needed in later stages. */
640  if (ENV_INITIAL_STAGE && !force_ro && !region_device_sz(&ro.rdev))
641  cbfs_get_boot_device(true);
642 
643  if (!force_ro) {
644  const struct cbfs_boot_device *rw = vboot_get_cbfs_boot_device();
645  /* This will return NULL if vboot isn't enabled, didn't run yet or decided to
646  boot into recovery mode. */
647  if (rw)
648  return rw;
649  }
650 
651  /* In rare cases post-RAM stages may run this before cbmem_initialize(), so we can't
652  lock in the result of find_mcache() on the first try and should keep trying every
653  time until an mcache is found. */
655 
656  if (region_device_sz(&ro.rdev))
657  return &ro;
658 
659  if (fmap_locate_area_as_rdev("COREBOOT", &ro.rdev))
660  die("Cannot locate primary CBFS");
661 
662  if (ENV_INITIAL_STAGE) {
664  if (err == CB_CBFS_HASH_MISMATCH)
665  die("RO CBFS metadata hash verification failure");
666  else if (CONFIG(TOCTOU_SAFETY) && err == CB_CBFS_CACHE_FULL)
667  die("RO mcache overflow breaks TOCTOU safety!\n");
668  else if (err && err != CB_CBFS_CACHE_FULL)
669  die("RO CBFS initialization error: %d", err);
670  }
671 
672  return &ro;
673 }
674 
675 #if !CONFIG(NO_CBFS_MCACHE)
676 static void mcache_to_cbmem(const struct cbfs_boot_device *cbd, u32 cbmem_id)
677 {
678  if (!cbd)
679  return;
680 
681  size_t real_size = cbfs_mcache_real_size(cbd->mcache, cbd->mcache_size);
682  void *cbmem_mcache = cbmem_add(cbmem_id, real_size);
683  if (!cbmem_mcache) {
684  printk(BIOS_ERR, "Cannot allocate CBMEM mcache %#x (%#zx bytes)!\n",
685  cbmem_id, real_size);
686  return;
687  }
688  memcpy(cbmem_mcache, cbd->mcache, real_size);
689 }
690 
691 static void cbfs_mcache_migrate(int unused)
692 {
695 }
697 #endif
const char * name
Definition: mmu.c:92
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
void * memset(void *dstpp, int c, size_t len)
Definition: memset.c:12
#define dead_code()
Definition: assert.h:89
#define assert(statement)
Definition: assert.h:74
#define ALIGN_DOWN(x, a)
Definition: helpers.h:18
cb_err
coreboot error codes
Definition: cb_err.h:15
@ CB_ERR
Generic error code.
Definition: cb_err.h:17
@ CB_ERR_ARG
Invalid argument.
Definition: cb_err.h:18
@ CB_CBFS_CACHE_FULL
Metadata cache overflowed.
Definition: cb_err.h:42
@ CB_SUCCESS
Call completed successfully.
Definition: cb_err.h:16
@ CB_CBFS_NOT_FOUND
File not found in directory.
Definition: cb_err.h:40
@ CB_CBFS_HASH_MISMATCH
Master hash validation failed.
Definition: cb_err.h:41
void cbfs_unmap(void *mapping)
Definition: cbfs.c:86
struct mem_pool cbfs_cache
Definition: cbfs.c:26
static bool fsps_env(void)
Definition: cbfs.c:98
static void * do_alloc(union cbfs_mdata *mdata, struct region_device *rdev, cbfs_allocator_t allocator, void *arg, size_t *size_out, bool skip_verification)
Definition: cbfs.c:397
static struct cbfs_preload_context * find_cbfs_preload_context(const char *name)
Definition: cbfs.c:349
void cbfs_boot_device_find_mcache(struct cbfs_boot_device *cbd, uint32_t id)
Definition: cbfs.c:588
static struct list_node cbfs_preload_context_list
Definition: cbfs.c:258
static enum cb_err cbfs_preload_thread_entry(void *arg)
Definition: cbfs.c:287
void * _cbfs_default_allocator(void *arg, size_t size, const union cbfs_mdata *unused)
Definition: cbfs.c:510
enum cb_err cbfs_init_boot_device(const struct cbfs_boot_device *cbd, struct vb2_hash *mdata_hash)
Definition: cbfs.c:615
static size_t cbfs_load_and_decompress(const struct region_device *rdev, void *buffer, size_t buffer_size, uint32_t compression, const union cbfs_mdata *mdata, bool skip_verification)
Definition: cbfs.c:186
static void append_cbfs_preload_context(struct cbfs_preload_context *context)
Definition: cbfs.c:275
static struct cbfs_preload_context * alloc_cbfs_preload_context(size_t additional)
Definition: cbfs.c:260
void * _cbfs_cbmem_allocator(void *arg, size_t size, const union cbfs_mdata *unused)
Definition: cbfs.c:518
void * _cbfs_alloc(const char *name, cbfs_allocator_t allocator, void *arg, size_t *size_out, bool force_ro, enum cbfs_type *type)
Definition: cbfs.c:449
static bool cbfs_lz4_enabled(void)
Definition: cbfs.c:114
static void mcache_to_cbmem(const struct cbfs_boot_device *cbd, u32 cbmem_id)
Definition: cbfs.c:676
ROMSTAGE_CBMEM_INIT_HOOK(switch_to_postram_cache)
static void free_cbfs_preload_context(struct cbfs_preload_context *context)
Definition: cbfs.c:280
static bool fspm_env(void)
Definition: cbfs.c:106
static void cbfs_mcache_migrate(int unused)
Definition: cbfs.c:691
static bool cbfs_file_hash_mismatch(const void *buffer, size_t size, const union cbfs_mdata *mdata, bool skip_verification)
Definition: cbfs.c:148
static enum cb_err get_preload_rdev(struct region_device *rdev, const char *name)
Definition: cbfs.c:361
const struct cbfs_boot_device * cbfs_get_boot_device(bool force_ro)
Definition: cbfs.c:634
static bool cbfs_lzma_enabled(void)
Definition: cbfs.c:130
void cbfs_preload(const char *name)
Definition: cbfs.c:299
void * _cbfs_unverified_area_alloc(const char *area, const char *name, cbfs_allocator_t allocator, void *arg, size_t *size_out)
Definition: cbfs.c:487
enum cb_err _cbfs_boot_lookup(const char *name, bool force_ro, union cbfs_mdata *mdata, struct region_device *rdev)
Definition: cbfs.c:37
static void switch_to_postram_cache(int unused)
Definition: cbfs.c:29
enum cb_err cbfs_prog_stage_load(struct prog *pstage)
Definition: cbfs.c:523
void *(* cbfs_allocator_t)(void *arg, size_t size, const union cbfs_mdata *mdata)
Definition: cbfs.h:76
#define ERROR(...)
Definition: cbfs_glue.h:22
enum cb_err cbfs_mcache_build(cbfs_dev_t dev, void *mcache, size_t size, struct vb2_hash *metadata_hash)
Definition: cbfs_mcache.c:65
enum cb_err cbfs_mcache_lookup(const void *mcache, size_t mcache_size, const char *name, union cbfs_mdata *mdata_out, size_t *data_offset_out)
Definition: cbfs_mcache.c:91
size_t cbfs_mcache_real_size(const void *mcache, size_t mcache_size)
Definition: cbfs_mcache.c:125
const struct vb2_hash * cbfs_file_hash(const union cbfs_mdata *mdata)
Definition: cbfs_private.c:199
enum cb_err cbfs_walk(cbfs_dev_t dev, enum cb_err(*walker)(cbfs_dev_t dev, size_t offset, const union cbfs_mdata *mdata, size_t already_read, void *arg), void *arg, struct vb2_hash *metadata_hash, enum cbfs_walk_flags flags)
Definition: cbfs_private.c:25
enum cb_err cbfs_lookup(cbfs_dev_t dev, const char *name, union cbfs_mdata *mdata_out, size_t *data_offset_out, struct vb2_hash *metadata_hash)
Definition: cbfs_private.c:155
const void * cbfs_find_attr(const union cbfs_mdata *mdata, uint32_t attr_tag, size_t size_check)
Definition: cbfs_private.c:167
#define CBFS_MCACHE_ALIGNMENT
Definition: cbfs_private.h:101
cbfs_compression
@ CBFS_COMPRESS_LZMA
@ CBFS_COMPRESS_NONE
@ CBFS_COMPRESS_LZ4
cbfs_type
@ CBFS_TYPE_STAGE
@ CBFS_TYPE_QUERY
@ CBFS_FILE_ATTR_TAG_COMPRESSION
@ CBFS_FILE_ATTR_TAG_STAGEHEADER
static int cbmem_possibly_online(void)
Definition: cbmem.h:158
void * cbmem_entry_start(const struct cbmem_entry *entry)
Definition: imd_cbmem.c:190
const struct cbmem_entry * cbmem_entry_find(u32 id)
Definition: imd_cbmem.c:157
void * cbmem_add(u32 id, u64 size)
Definition: imd_cbmem.c:144
u64 cbmem_entry_size(const struct cbmem_entry *entry)
Definition: imd_cbmem.c:185
#define CBMEM_ID_CBFS_RO_MCACHE
Definition: cbmem_id.h:77
#define CBMEM_ID_CBFS_RW_MCACHE
Definition: cbmem_id.h:78
#define printk(level,...)
Definition: stdlib.h:16
size_t ulz4fn(const void *src, size_t srcn, void *dst, size_t dstn)
Definition: lz4_wrapper.c:96
void __noreturn die(const char *fmt,...)
Definition: die.c:17
uint32_t tspi_cbfs_measurement(const char *name, uint32_t type, const struct vb2_hash *hash)
Extend a measurement hash taken for a CBFS file into the appropriate PCR.
Definition: crtm.c:98
#define TPM_MEASURE_ALGO
Definition: crtm.h:19
#define DEBUG
Definition: software_i2c.c:12
@ CONFIG
Definition: dsi_common.h:201
static struct region_device rdev
Definition: flashconsole.c:14
int fmap_locate_area_as_rdev(const char *name, struct region_device *area)
Definition: fmap.c:144
static uint64_t be64toh(uint64_t big_endian_64bits)
Definition: endian.h:150
static uint32_t be32toh(uint32_t big_endian_32bits)
Definition: endian.h:130
#define REGION_SIZE(name)
Definition: symbols.h:10
struct bootblock_arg arg
Definition: decompressor.c:22
unsigned int type
Definition: edid.c:57
void timestamp_add_now(enum timestamp_id id)
Definition: timestamp.c:141
size_t ulzman(const void *src, size_t srcn, void *dst, size_t dstn)
Definition: lzma.c:19
void list_append(struct list_node *node, struct list_node *head)
Definition: list.c:32
#define list_for_each(ptr, head, member)
Definition: list.h:21
void list_remove(struct list_node *node)
Definition: list.c:6
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
#define MEM_POOL_INIT(buf_, size_, alignment_)
Definition: mem_pool.h:32
void * mem_pool_alloc(struct mem_pool *mp, size_t sz)
Definition: mem_pool.c:6
void mem_pool_free(struct mem_pool *mp, void *alloc)
Definition: mem_pool.c:29
static void mem_pool_init(struct mem_pool *mp, void *buf, size_t sz, size_t alignment)
Definition: mem_pool.h:50
struct vb2_hash * metadata_hash_get(void)
Definition: metadata_hash.c:39
@ SEG_FINAL
void prog_segment_loaded(uintptr_t start, size_t size, int flags)
Definition: prog_ops.c:6
static void prog_set_entry(struct prog *prog, void *e, void *arg)
static const char * prog_name(const struct prog *prog)
static void * prog_start(const struct prog *prog)
int prog_locate_hook(struct prog *prog)
Definition: prog_loaders.c:48
static size_t prog_size(const struct prog *prog)
static void prog_set_area(struct prog *prog, void *start, size_t size)
u8 buffer[C2P_BUFFER_MAXSIZE]
Definition: psp_smm.c:18
int rdev_munmap(const struct region_device *rd, void *mapping)
Definition: region.c:65
static size_t region_device_sz(const struct region_device *rdev)
Definition: region.h:132
int rdev_chain_mem(struct region_device *child, const void *base, size_t size)
Definition: region.c:293
static void * rdev_mmap_full(const struct region_device *rd)
Definition: region.h:148
int rdev_chain(struct region_device *child, const struct region_device *parent, size_t offset, size_t size)
Definition: region.c:136
ssize_t rdev_readat(const struct region_device *rd, void *b, size_t offset, size_t size)
Definition: region.c:77
static ssize_t rdev_read_full(const struct region_device *rd, void *b)
Definition: region.h:166
#define ENV_BOOTBLOCK
Definition: rules.h:148
#define ENV_STAGE_SUPPORTS_COOP
Definition: rules.h:310
#define ENV_SMM
Definition: rules.h:151
#define ENV_RAMSTAGE
Definition: rules.h:150
#define ENV_ROMSTAGE
Definition: rules.h:149
#define ENV_STRING
Definition: rules.h:156
#define ENV_INITIAL_STAGE
Definition: rules.h:292
#define ENV_ROMSTAGE_OR_BEFORE
Definition: rules.h:263
#define ENV_SEPARATE_VERSTAGE
Definition: rules.h:152
#define ENV_POSTCAR
Definition: rules.h:154
#define NULL
Definition: stddef.h:19
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
uint8_t u8
Definition: stdint.h:45
int strcmp(const char *s1, const char *s2)
Definition: string.c:103
char * strcpy(char *dst, const char *src)
Definition: string.c:92
size_t strlen(const char *src)
Definition: string.c:42
void * mcache
Definition: cbfs.h:168
size_t mcache_size
Definition: cbfs.h:169
struct region_device rdev
Definition: cbfs.h:167
uint32_t len
uint32_t type
char filename[0]
struct region_device rdev
Definition: cbfs.c:251
struct thread_handle handle
Definition: cbfs.c:252
struct list_node list_node
Definition: cbfs.c:253
Definition: list.h:7
size_t size
Definition: mem_pool.h:25
enum cbfs_type cbfs_type
int thread_run(struct thread_handle *handle, enum cb_err(*func)(void *), void *arg)
Definition: thread.c:272
enum cb_err thread_join(struct thread_handle *handle)
Definition: thread.c:384
@ TS_ULZ4F_END
@ TS_ULZMA_START
@ TS_ULZMA_END
@ TS_ULZ4F_START
struct cbfs_file h
Definition: cbfs_mdata.h:21
const struct cbfs_boot_device * vboot_get_cbfs_boot_device(void)
Definition: vboot_loader.c:73