1 /* SPDX-License-Identifier: GPL-2.0-only */
7 #include <commonlib/bsd/cbfs_mdata.h>
8 #include <commonlib/mem_pool.h>
9 #include <commonlib/region.h>
11 #include <program_loading.h>
16 /**********************************************************************************************
17 * CBFS FILE ACCESS APIs *
18 **********************************************************************************************/
21 * These are the APIs used to access files in CBFS. In order to keep the calls simple and free
22 * of clutter in the common cases, but still offer all advanced functionality when needed, there
23 * are many different variations that are implemented by wrapping the same underlying API with
24 * static inlines. All accessors have in common that they look up files by name, and will
25 * transparently decompress files that are compressed.
27 * There are three main flavors of CBFS accessors:
29 * size_t cbfs_load(char *name, void *buf, size_t size): Loads the contents of a CBFS file into
30 * a buffer provided by the caller (by providing pointer and size to it). Will return the
31 * amount of bytes loaded on success, or 0 on error.
33 * void *cbfs_map(char *name, size_t *size_out): Maps a file into the address space. If the file
34 * is not compressed and the platform supports direct memory-mapping for the boot medium,
35 * a pointer to the platform mapping is returned directly. In all other cases, memory will
36 * be allocated from the cbfs_cache and file data will be loaded into there. Returns a
37 * pointer to the mapping on success, or NULL on error. If an optional size_out parameter
38 * is passed in, it will be filled out with the size of the mapped data. Caller should call
39 * cbfs_unmap() after it is done using the mapping to free up the cbfs_cache if possible.
41 * void *cbfs_alloc(char *name, cbfs_allocator_t allocator, void *arg, size_t *size_out): Loads
42 * file data into memory provided by a custom allocator function that the caller passes in.
43 * The caller may pass an argument that is passed through verbatim to the allocator.
44 * Returns the pointer returned by the allocator (where the file data was loaded to) on
45 * success, or NULL on error. If an optional size_out parameter is passed in, it will be
46 * filled out with the size of the loaded data.
48 * void *cbfs_cbmem_alloc(char *name, uint32_t cbmem_id, size_t *size_out): Wrapper around
49 * cbfs_alloc() that will provide an allocator function for allocating space for the file
50 * data in CBMEM, with the provided CBMEM ID.
52 * All of these flavors have variations with any of the following optional parameters added:
54 * ..._ro_...: Will force looking up the CBFS file in the read-only CBFS (the "COREBOOT" FMAP
55 * section), even when running in an RW stage from one of the RW CBFSs. Only relevant if
56 * CONFIG(VBOOT) is set.
58 * ..._unverified_area_...: Will look for the CBFS file in the named FMAP area, rather than
59 * any of the default (RO or RW) CBFSs. Files accessed this way are *not* verified in any
60 * way (even if CONFIG(CBFS_VERIFICATION) is enabled) and should always be treated as
61 * untrusted (potentially malicious) data. Mutually exclusive with the ..._ro_... variant.
63 * ..._type_...: May pass in an extra enum cbfs_type *type parameter. If the value it points to
64 * is CBFS_TYPE_QUERY, it will be replaced with the actual CBFS type of the found file. If
65 * it is anything else, the type will be compared with the actually found type, and the
66 * operation will fail if they don't match.
70 * An allocator function for passing to cbfs_alloc(). Takes the argument that was originally
71 * passed to cbfs_alloc(), the size of the file to be loaded, and a pointer to the already
72 * loaded and verified file metadata (for rare cases where the allocator needs to check custom
73 * attributes). Must return a pointer to space of the requested size where the file data should
74 * be loaded, or NULL to make the operation fail.
76 typedef void *(*cbfs_allocator_t
)(void *arg
, size_t size
, const union cbfs_mdata
*mdata
);
78 static inline size_t cbfs_load(const char *name
, void *buf
, size_t size
);
79 static inline size_t cbfs_ro_load(const char *name
, void *buf
, size_t size
);
80 static inline size_t cbfs_type_load(const char *name
, void *buf
, size_t size
,
81 enum cbfs_type
*type
);
82 static inline size_t cbfs_ro_type_load(const char *name
, void *buf
, size_t size
,
83 enum cbfs_type
*type
);
84 static inline size_t cbfs_unverified_area_load(const char *area
, const char *name
,
85 void *buf
, size_t size
);
87 static inline void *cbfs_map(const char *name
, size_t *size_out
);
88 static inline void *cbfs_ro_map(const char *name
, size_t *size_out
);
89 static inline void *cbfs_type_map(const char *name
, size_t *size_out
, enum cbfs_type
*type
);
90 static inline void *cbfs_ro_type_map(const char *name
, size_t *size_out
, enum cbfs_type
*type
);
91 static inline void *cbfs_unverified_area_map(const char *area
, const char *name
,
94 static inline void *cbfs_alloc(const char *name
, cbfs_allocator_t allocator
, void *arg
,
96 static inline void *cbfs_ro_alloc(const char *name
, cbfs_allocator_t allocator
, void *arg
,
98 static inline void *cbfs_type_alloc(const char *name
, cbfs_allocator_t allocator
, void *arg
,
99 size_t *size_out
, enum cbfs_type
*type
);
100 static inline void *cbfs_ro_type_alloc(const char *name
, cbfs_allocator_t allocator
, void *arg
,
101 size_t *size_out
, enum cbfs_type
*type
);
102 static inline void *cbfs_unverified_area_alloc(const char *area
, const char *name
,
103 cbfs_allocator_t allocator
, void *arg
,
106 static inline void *cbfs_cbmem_alloc(const char *name
, uint32_t cbmem_id
, size_t *size_out
);
107 static inline void *cbfs_ro_cbmem_alloc(const char *name
, uint32_t cbmem_id
, size_t *size_out
);
108 static inline void *cbfs_type_cbmem_alloc(const char *name
, uint32_t cbmem_id
, size_t *size_out
,
109 enum cbfs_type
*type
);
110 static inline void *cbfs_ro_type_cbmem_alloc(const char *name
, uint32_t cbmem_id
,
111 size_t *size_out
, enum cbfs_type
*type
);
112 static inline void *cbfs_unverified_area_cbmem_alloc(const char *area
, const char *name
,
113 uint32_t cbmem_id
, size_t *size_out
);
116 * Starts the processes of preloading a file into RAM.
118 * This method depends on COOP_MULTITASKING to parallelize the loading. This method is only
119 * effective when the underlying rdev supports DMA operations.
121 * When `cbfs_load`, `cbfs_alloc`, or `cbfs_map` are called after a preload has been started,
122 * they will wait for the preload to complete (if it hasn't already) and then perform
123 * verification and/or decompression.
125 * This method does not have a return value because the system should boot regardless if this
126 * method succeeds or fails.
128 void cbfs_preload(const char *name
);
130 /* Removes a previously allocated CBFS mapping. Should try to unmap mappings in strict LIFO
131 order where possible, since mapping backends often don't support more complicated cases. */
132 void cbfs_unmap(void *mapping
);
134 /* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */
135 enum cb_err
cbfs_prog_stage_load(struct prog
*prog
);
137 /* Returns the size of a CBFS file, or 0 on error. Avoid using this function to allocate space,
138 and instead use cbfs_alloc() so the file only needs to be looked up once. */
139 static inline size_t cbfs_get_size(const char *name
);
140 static inline size_t cbfs_ro_get_size(const char *name
);
142 /* Returns the type of a CBFS file, or CBFS_TYPE_NULL on error. Use cbfs_type_load() instead of
143 this where possible to avoid looking up the file more than once. */
144 static inline enum cbfs_type
cbfs_get_type(const char *name
);
145 static inline enum cbfs_type
cbfs_ro_get_type(const char *name
);
147 /* Check whether a CBFS file exists. */
148 static inline bool cbfs_file_exists(const char *name
);
149 static inline bool cbfs_ro_file_exists(const char *name
);
152 /**********************************************************************************************
153 * BOOT DEVICE HELPER APIs *
154 **********************************************************************************************/
157 * The shared memory pool for backing mapped CBFS files, and other CBFS allocation needs.
159 extern struct mem_pool cbfs_cache
;
162 * Data structure that represents "a" CBFS boot device, with optional metadata cache. Generally
163 * we only have one of these, or two (RO and RW) when CONFIG(VBOOT) is set. The region device
164 * stored here must always be a subregion of boot_device_ro().
166 struct cbfs_boot_device
{
167 struct region_device rdev
;
172 /* Helper to fill out |mcache| and |mcache_size| in a cbfs_boot_device. */
173 void cbfs_boot_device_find_mcache(struct cbfs_boot_device
*cbd
, uint32_t id
);
176 * Retrieves the currently active CBFS boot device. If |force_ro| is set, will always return the
177 * read-only CBFS instead (this only makes a difference when CONFIG(VBOOT) is enabled). May
178 * perform certain CBFS initialization tasks. Returns NULL on error (e.g. boot device IO error).
180 const struct cbfs_boot_device
*cbfs_get_boot_device(bool force_ro
);
183 * Builds the mcache (if |cbd->mcache| is set) and verifies |metadata_hash| (if it is not NULL).
184 * If CB_CBFS_CACHE_FULL is returned, the mcache is incomplete but still valid and the metadata
185 * hash was still verified. Should be called once per *boot* (not once per stage) before the
188 enum cb_err
cbfs_init_boot_device(const struct cbfs_boot_device
*cbd
,
189 struct vb2_hash
*metadata_hash
);
192 /**********************************************************************************************
193 * INTERNAL HELPERS FOR INLINES, DO NOT USE. *
194 **********************************************************************************************/
195 enum cb_err
_cbfs_boot_lookup(const char *name
, bool force_ro
,
196 union cbfs_mdata
*mdata
, struct region_device
*rdev
);
198 void *_cbfs_alloc(const char *name
, cbfs_allocator_t allocator
, void *arg
,
199 size_t *size_out
, bool force_ro
, enum cbfs_type
*type
);
201 void *_cbfs_unverified_area_alloc(const char *area
, const char *name
,
202 cbfs_allocator_t allocator
, void *arg
, size_t *size_out
);
204 struct _cbfs_default_allocator_arg
{
208 void *_cbfs_default_allocator(void *arg
, size_t size
, const union cbfs_mdata
*unused
);
210 void *_cbfs_cbmem_allocator(void *arg
, size_t size
, const union cbfs_mdata
*unused
);
212 /**********************************************************************************************
213 * INLINE IMPLEMENTATIONS *
214 **********************************************************************************************/
215 static inline void *cbfs_alloc(const char *name
, cbfs_allocator_t allocator
, void *arg
,
218 return cbfs_type_alloc(name
, allocator
, arg
, size_out
, NULL
);
221 static inline void *cbfs_ro_alloc(const char *name
, cbfs_allocator_t allocator
, void *arg
,
224 return cbfs_ro_type_alloc(name
, allocator
, arg
, size_out
, NULL
);
227 static inline void *cbfs_type_alloc(const char *name
, cbfs_allocator_t allocator
, void *arg
,
228 size_t *size_out
, enum cbfs_type
*type
)
230 return _cbfs_alloc(name
, allocator
, arg
, size_out
, false, type
);
233 static inline void *cbfs_ro_type_alloc(const char *name
, cbfs_allocator_t allocator
, void *arg
,
234 size_t *size_out
, enum cbfs_type
*type
)
236 return _cbfs_alloc(name
, allocator
, arg
, size_out
, true, type
);
239 static inline void *cbfs_unverified_area_alloc(const char *area
, const char *name
,
240 cbfs_allocator_t allocator
, void *arg
,
243 return _cbfs_unverified_area_alloc(area
, name
, allocator
, arg
, size_out
);
246 static inline void *cbfs_map(const char *name
, size_t *size_out
)
248 return cbfs_type_map(name
, size_out
, NULL
);
251 static inline void *cbfs_ro_map(const char *name
, size_t *size_out
)
253 return cbfs_ro_type_map(name
, size_out
, NULL
);
256 static inline void *cbfs_type_map(const char *name
, size_t *size_out
, enum cbfs_type
*type
)
258 return cbfs_type_alloc(name
, NULL
, NULL
, size_out
, type
);
261 static inline void *cbfs_ro_type_map(const char *name
, size_t *size_out
, enum cbfs_type
*type
)
263 return cbfs_ro_type_alloc(name
, NULL
, NULL
, size_out
, type
);
266 static inline void *cbfs_unverified_area_map(const char *area
, const char *name
,
269 return _cbfs_unverified_area_alloc(area
, name
, NULL
, NULL
, size_out
);
272 static inline size_t _cbfs_load(const char *name
, void *buf
, size_t size
, bool force_ro
,
273 enum cbfs_type
*type
)
275 struct _cbfs_default_allocator_arg arg
= { .buf
= buf
, .buf_size
= size
};
276 if (_cbfs_alloc(name
, _cbfs_default_allocator
, &arg
, &size
, force_ro
, type
))
282 static inline size_t cbfs_load(const char *name
, void *buf
, size_t size
)
284 return cbfs_type_load(name
, buf
, size
, NULL
);
287 static inline size_t cbfs_type_load(const char *name
, void *buf
, size_t size
,
288 enum cbfs_type
*type
)
290 return _cbfs_load(name
, buf
, size
, false, type
);
293 static inline size_t cbfs_ro_load(const char *name
, void *buf
, size_t size
)
295 return cbfs_ro_type_load(name
, buf
, size
, NULL
);
298 static inline size_t cbfs_ro_type_load(const char *name
, void *buf
, size_t size
,
299 enum cbfs_type
*type
)
301 return _cbfs_load(name
, buf
, size
, true, type
);
304 static inline size_t cbfs_unverified_area_load(const char *area
, const char *name
,
305 void *buf
, size_t size
)
307 struct _cbfs_default_allocator_arg arg
= { .buf
= buf
, .buf_size
= size
};
308 if (_cbfs_unverified_area_alloc(area
, name
, _cbfs_default_allocator
, &arg
, &size
))
314 static inline void *cbfs_cbmem_alloc(const char *name
, uint32_t cbmem_id
, size_t *size_out
)
316 return cbfs_type_cbmem_alloc(name
, cbmem_id
, size_out
, NULL
);
319 static inline void *cbfs_ro_cbmem_alloc(const char *name
, uint32_t cbmem_id
, size_t *size_out
)
321 return cbfs_ro_type_cbmem_alloc(name
, cbmem_id
, size_out
, NULL
);
324 static inline void *cbfs_type_cbmem_alloc(const char *name
, uint32_t cbmem_id
, size_t *size_out
,
325 enum cbfs_type
*type
)
327 return cbfs_type_alloc(name
, _cbfs_cbmem_allocator
, (void *)(uintptr_t)cbmem_id
,
331 static inline void *cbfs_ro_type_cbmem_alloc(const char *name
, uint32_t cbmem_id
,
332 size_t *size_out
, enum cbfs_type
*type
)
334 return cbfs_ro_type_alloc(name
, _cbfs_cbmem_allocator
, (void *)(uintptr_t)cbmem_id
,
338 static inline void *cbfs_unverified_area_cbmem_alloc(const char *area
, const char *name
,
339 uint32_t cbmem_id
, size_t *size_out
)
341 return _cbfs_unverified_area_alloc(area
, name
, _cbfs_cbmem_allocator
,
342 (void *)(uintptr_t)cbmem_id
, size_out
);
345 static inline size_t cbfs_get_size(const char *name
)
347 union cbfs_mdata mdata
;
348 struct region_device rdev
;
349 if (_cbfs_boot_lookup(name
, false, &mdata
, &rdev
) != CB_SUCCESS
)
351 return be32toh(mdata
.h
.len
);
354 static inline size_t cbfs_ro_get_size(const char *name
)
356 union cbfs_mdata mdata
;
357 struct region_device rdev
;
358 if (_cbfs_boot_lookup(name
, true, &mdata
, &rdev
) != CB_SUCCESS
)
360 return be32toh(mdata
.h
.len
);
363 static inline enum cbfs_type
cbfs_get_type(const char *name
)
365 union cbfs_mdata mdata
;
366 struct region_device rdev
;
367 if (_cbfs_boot_lookup(name
, false, &mdata
, &rdev
) != CB_SUCCESS
)
368 return CBFS_TYPE_NULL
;
369 return be32toh(mdata
.h
.type
);
372 static inline enum cbfs_type
cbfs_ro_get_type(const char *name
)
374 union cbfs_mdata mdata
;
375 struct region_device rdev
;
376 if (_cbfs_boot_lookup(name
, true, &mdata
, &rdev
) != CB_SUCCESS
)
377 return CBFS_TYPE_NULL
;
378 return be32toh(mdata
.h
.type
);
381 static inline bool cbfs_file_exists(const char *name
)
383 union cbfs_mdata mdata
;
384 struct region_device rdev
;
385 if (_cbfs_boot_lookup(name
, false, &mdata
, &rdev
) != CB_SUCCESS
)
390 static inline bool cbfs_ro_file_exists(const char *name
)
392 union cbfs_mdata mdata
;
393 struct region_device rdev
;
394 if (_cbfs_boot_lookup(name
, true, &mdata
, &rdev
) != CB_SUCCESS
)