blob: f0ae7a80ef7f5367d6c5b0d96e631def4af27528 [file] [log] [blame]
Angel Pons32859fc2020-04-02 23:48:27 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Peter Stuge483b7bb2009-04-14 07:40:01 +00002
3#ifndef _CBFS_H_
4#define _CBFS_H_
5
Julius Werner1e37c9c2019-12-11 17:09:39 -08006#include <cbmem.h>
Julius Werner7778cf22021-01-05 18:54:19 -08007#include <commonlib/bsd/cbfs_mdata.h>
Julius Werner9b1f3cc2020-12-30 17:30:12 -08008#include <commonlib/mem_pool.h>
Julius Werner57d4bc62021-11-15 10:13:37 -08009#include <commonlib/region.h>
Julius Werner9f376472021-08-11 18:20:11 -070010#include <endian.h>
Aaron Durbin899d13d2015-05-15 23:39:23 -050011#include <program_loading.h>
Julius Werner1e37c9c2019-12-11 17:09:39 -080012#include <types.h>
Julius Wernerfdabf3f2020-05-06 17:06:35 -070013#include <vb2_sha.h>
Daisuke Nojirie1298df2014-12-01 15:30:01 -080014
Aaron Durbin899d13d2015-05-15 23:39:23 -050015
Julius Werner11075fc2020-12-29 17:51:04 -080016/**********************************************************************************************
17 * CBFS FILE ACCESS APIs *
18 **********************************************************************************************/
Julius Werner723e3b12020-12-29 17:33:30 -080019
Julius Werner7778cf22021-01-05 18:54:19 -080020/*
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.
26 *
27 * There are three main flavors of CBFS accessors:
28 *
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.
32 *
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.
40 *
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.
47 *
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.
51 *
52 * All of these flavors have variations with any of the following optional parameters added:
53 *
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.
57 *
Julius Werner05714cc2021-04-15 23:25:44 -070058 * ..._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.
62 *
Julius Werner7778cf22021-01-05 18:54:19 -080063 * ..._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.
67 */
Julius Werner11075fc2020-12-29 17:51:04 -080068
Julius Werner7778cf22021-01-05 18:54:19 -080069/*
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.
75 */
Julius Werner4676ec52021-03-10 16:52:14 -080076typedef void *(*cbfs_allocator_t)(void *arg, size_t size, const union cbfs_mdata *mdata);
Julius Werner7778cf22021-01-05 18:54:19 -080077
78static inline size_t cbfs_load(const char *name, void *buf, size_t size);
79static inline size_t cbfs_ro_load(const char *name, void *buf, size_t size);
80static inline size_t cbfs_type_load(const char *name, void *buf, size_t size,
81 enum cbfs_type *type);
82static inline size_t cbfs_ro_type_load(const char *name, void *buf, size_t size,
83 enum cbfs_type *type);
Julius Werner05714cc2021-04-15 23:25:44 -070084static inline size_t cbfs_unverified_area_load(const char *area, const char *name,
85 void *buf, size_t size);
Julius Werner7778cf22021-01-05 18:54:19 -080086
87static inline void *cbfs_map(const char *name, size_t *size_out);
Julius Werner11075fc2020-12-29 17:51:04 -080088static inline void *cbfs_ro_map(const char *name, size_t *size_out);
Julius Werner7778cf22021-01-05 18:54:19 -080089static inline void *cbfs_type_map(const char *name, size_t *size_out, enum cbfs_type *type);
90static inline void *cbfs_ro_type_map(const char *name, size_t *size_out, enum cbfs_type *type);
Julius Werner05714cc2021-04-15 23:25:44 -070091static inline void *cbfs_unverified_area_map(const char *area, const char *name,
92 size_t *size_out);
Julius Werner7778cf22021-01-05 18:54:19 -080093
94static inline void *cbfs_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
95 size_t *size_out);
96static inline void *cbfs_ro_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
97 size_t *size_out);
98static inline void *cbfs_type_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
99 size_t *size_out, enum cbfs_type *type);
100static inline void *cbfs_ro_type_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
101 size_t *size_out, enum cbfs_type *type);
Julius Werner05714cc2021-04-15 23:25:44 -0700102static inline void *cbfs_unverified_area_alloc(const char *area, const char *name,
103 cbfs_allocator_t allocator, void *arg,
104 size_t *size_out);
Julius Werner7778cf22021-01-05 18:54:19 -0800105
106static inline void *cbfs_cbmem_alloc(const char *name, uint32_t cbmem_id, size_t *size_out);
107static inline void *cbfs_ro_cbmem_alloc(const char *name, uint32_t cbmem_id, size_t *size_out);
108static inline void *cbfs_type_cbmem_alloc(const char *name, uint32_t cbmem_id, size_t *size_out,
109 enum cbfs_type *type);
110static inline void *cbfs_ro_type_cbmem_alloc(const char *name, uint32_t cbmem_id,
111 size_t *size_out, enum cbfs_type *type);
Julius Werner05714cc2021-04-15 23:25:44 -0700112static inline void *cbfs_unverified_area_cbmem_alloc(const char *area, const char *name,
113 uint32_t cbmem_id, size_t *size_out);
Julius Werner11075fc2020-12-29 17:51:04 -0800114
Raul E Rangel4cfb8622021-11-01 13:40:14 -0600115/*
116 * Starts the processes of preloading a file into RAM.
117 *
118 * This method depends on COOP_MULTITASKING to parallelize the loading. This method is only
119 * effective when the underlying rdev supports DMA operations.
120 *
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.
124 *
125 * This method does not have a return value because the system should boot regardless if this
126 * method succeeds or fails.
127 */
128void cbfs_preload(const char *name);
129
Julius Werner723e3b12020-12-29 17:33:30 -0800130/* 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. */
Julius Werner9b1f3cc2020-12-30 17:30:12 -0800132void cbfs_unmap(void *mapping);
Julius Werner723e3b12020-12-29 17:33:30 -0800133
Aaron Durbin899d13d2015-05-15 23:39:23 -0500134/* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */
Julius Werner69cc5572022-03-04 17:49:56 -0800135enum cb_err cbfs_prog_stage_load(struct prog *prog);
Aaron Durbin899d13d2015-05-15 23:39:23 -0500136
Julius Werner57d4bc62021-11-15 10:13:37 -0800137/* 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. */
139static inline size_t cbfs_get_size(const char *name);
140static inline size_t cbfs_ro_get_size(const char *name);
141
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. */
144static inline enum cbfs_type cbfs_get_type(const char *name);
145static inline enum cbfs_type cbfs_ro_get_type(const char *name);
146
147/* Check whether a CBFS file exists. */
148static inline bool cbfs_file_exists(const char *name);
149static inline bool cbfs_ro_file_exists(const char *name);
150
Julius Werner9b1f3cc2020-12-30 17:30:12 -0800151
Julius Werner11075fc2020-12-29 17:51:04 -0800152/**********************************************************************************************
153 * BOOT DEVICE HELPER APIs *
154 **********************************************************************************************/
155
Julius Werner0d9072b2020-03-05 12:51:08 -0800156/*
Julius Werner9b1f3cc2020-12-30 17:30:12 -0800157 * The shared memory pool for backing mapped CBFS files, and other CBFS allocation needs.
Julius Werner9b1f3cc2020-12-30 17:30:12 -0800158 */
Julius Werner9b1f3cc2020-12-30 17:30:12 -0800159extern struct mem_pool cbfs_cache;
160
161/*
Julius Werner723e3b12020-12-29 17:33:30 -0800162 * 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().
Julius Werner0d9072b2020-03-05 12:51:08 -0800165 */
Julius Werner1e37c9c2019-12-11 17:09:39 -0800166struct cbfs_boot_device {
167 struct region_device rdev;
168 void *mcache;
169 size_t mcache_size;
170};
171
172/* Helper to fill out |mcache| and |mcache_size| in a cbfs_boot_device. */
173void cbfs_boot_device_find_mcache(struct cbfs_boot_device *cbd, uint32_t id);
174
175/*
Julius Werner723e3b12020-12-29 17:33:30 -0800176 * 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).
Julius Werner1e37c9c2019-12-11 17:09:39 -0800179 */
180const struct cbfs_boot_device *cbfs_get_boot_device(bool force_ro);
Aaron Durbin899d13d2015-05-15 23:39:23 -0500181
Julius Wernerfdabf3f2020-05-06 17:06:35 -0700182/*
Julius Werner723e3b12020-12-29 17:33:30 -0800183 * 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
186 * first CBFS access.
Julius Wernerfdabf3f2020-05-06 17:06:35 -0700187 */
Julius Werner69cc5572022-03-04 17:49:56 -0800188enum cb_err cbfs_init_boot_device(const struct cbfs_boot_device *cbd,
189 struct vb2_hash *metadata_hash);
Julius Wernerfdabf3f2020-05-06 17:06:35 -0700190
Julius Werner11075fc2020-12-29 17:51:04 -0800191
192/**********************************************************************************************
Julius Werner11075fc2020-12-29 17:51:04 -0800193 * INTERNAL HELPERS FOR INLINES, DO NOT USE. *
194 **********************************************************************************************/
Julius Werner69cc5572022-03-04 17:49:56 -0800195enum cb_err _cbfs_boot_lookup(const char *name, bool force_ro,
196 union cbfs_mdata *mdata, struct region_device *rdev);
Julius Werner57d4bc62021-11-15 10:13:37 -0800197
Julius Werner7778cf22021-01-05 18:54:19 -0800198void *_cbfs_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
199 size_t *size_out, bool force_ro, enum cbfs_type *type);
Julius Werner11075fc2020-12-29 17:51:04 -0800200
Julius Werner05714cc2021-04-15 23:25:44 -0700201void *_cbfs_unverified_area_alloc(const char *area, const char *name,
202 cbfs_allocator_t allocator, void *arg, size_t *size_out);
203
Julius Werner7778cf22021-01-05 18:54:19 -0800204struct _cbfs_default_allocator_arg {
205 void *buf;
206 size_t buf_size;
207};
Julius Werner4676ec52021-03-10 16:52:14 -0800208void *_cbfs_default_allocator(void *arg, size_t size, const union cbfs_mdata *unused);
Julius Werner7778cf22021-01-05 18:54:19 -0800209
Julius Werner4676ec52021-03-10 16:52:14 -0800210void *_cbfs_cbmem_allocator(void *arg, size_t size, const union cbfs_mdata *unused);
Julius Werner11075fc2020-12-29 17:51:04 -0800211
212/**********************************************************************************************
213 * INLINE IMPLEMENTATIONS *
214 **********************************************************************************************/
Julius Werner7778cf22021-01-05 18:54:19 -0800215static inline void *cbfs_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
216 size_t *size_out)
217{
218 return cbfs_type_alloc(name, allocator, arg, size_out, NULL);
219}
220
221static inline void *cbfs_ro_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
222 size_t *size_out)
223{
224 return cbfs_ro_type_alloc(name, allocator, arg, size_out, NULL);
225}
226
227static inline void *cbfs_type_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
228 size_t *size_out, enum cbfs_type *type)
229{
230 return _cbfs_alloc(name, allocator, arg, size_out, false, type);
231}
232
233static inline void *cbfs_ro_type_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
234 size_t *size_out, enum cbfs_type *type)
235{
236 return _cbfs_alloc(name, allocator, arg, size_out, true, type);
237}
238
Julius Werner05714cc2021-04-15 23:25:44 -0700239static inline void *cbfs_unverified_area_alloc(const char *area, const char *name,
240 cbfs_allocator_t allocator, void *arg,
241 size_t *size_out)
242{
243 return _cbfs_unverified_area_alloc(area, name, allocator, arg, size_out);
244}
245
Julius Werner11075fc2020-12-29 17:51:04 -0800246static inline void *cbfs_map(const char *name, size_t *size_out)
247{
Julius Werner7778cf22021-01-05 18:54:19 -0800248 return cbfs_type_map(name, size_out, NULL);
Julius Werner11075fc2020-12-29 17:51:04 -0800249}
250
251static inline void *cbfs_ro_map(const char *name, size_t *size_out)
252{
Julius Werner7778cf22021-01-05 18:54:19 -0800253 return cbfs_ro_type_map(name, size_out, NULL);
Julius Werner11075fc2020-12-29 17:51:04 -0800254}
255
Julius Werner7778cf22021-01-05 18:54:19 -0800256static inline void *cbfs_type_map(const char *name, size_t *size_out, enum cbfs_type *type)
Julius Werner11075fc2020-12-29 17:51:04 -0800257{
Julius Werner7778cf22021-01-05 18:54:19 -0800258 return cbfs_type_alloc(name, NULL, NULL, size_out, type);
Julius Werner11075fc2020-12-29 17:51:04 -0800259}
260
Julius Werner7778cf22021-01-05 18:54:19 -0800261static inline void *cbfs_ro_type_map(const char *name, size_t *size_out, enum cbfs_type *type)
Julius Werner11075fc2020-12-29 17:51:04 -0800262{
Julius Werner7778cf22021-01-05 18:54:19 -0800263 return cbfs_ro_type_alloc(name, NULL, NULL, size_out, type);
264}
265
Julius Werner05714cc2021-04-15 23:25:44 -0700266static inline void *cbfs_unverified_area_map(const char *area, const char *name,
267 size_t *size_out)
268{
269 return _cbfs_unverified_area_alloc(area, name, NULL, NULL, size_out);
270}
271
Julius Werner7778cf22021-01-05 18:54:19 -0800272static inline size_t _cbfs_load(const char *name, void *buf, size_t size, bool force_ro,
273 enum cbfs_type *type)
274{
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))
277 return size;
278 else
279 return 0;
280}
281
282static inline size_t cbfs_load(const char *name, void *buf, size_t size)
283{
284 return cbfs_type_load(name, buf, size, NULL);
285}
286
287static inline size_t cbfs_type_load(const char *name, void *buf, size_t size,
288 enum cbfs_type *type)
289{
290 return _cbfs_load(name, buf, size, false, type);
291}
292
293static inline size_t cbfs_ro_load(const char *name, void *buf, size_t size)
294{
295 return cbfs_ro_type_load(name, buf, size, NULL);
296}
297
298static inline size_t cbfs_ro_type_load(const char *name, void *buf, size_t size,
299 enum cbfs_type *type)
300{
301 return _cbfs_load(name, buf, size, true, type);
302}
303
Julius Werner05714cc2021-04-15 23:25:44 -0700304static inline size_t cbfs_unverified_area_load(const char *area, const char *name,
305 void *buf, size_t size)
306{
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))
309 return size;
310 else
311 return 0;
312}
313
Julius Werner7778cf22021-01-05 18:54:19 -0800314static inline void *cbfs_cbmem_alloc(const char *name, uint32_t cbmem_id, size_t *size_out)
315{
316 return cbfs_type_cbmem_alloc(name, cbmem_id, size_out, NULL);
317}
318
319static inline void *cbfs_ro_cbmem_alloc(const char *name, uint32_t cbmem_id, size_t *size_out)
320{
321 return cbfs_ro_type_cbmem_alloc(name, cbmem_id, size_out, NULL);
322}
323
324static inline void *cbfs_type_cbmem_alloc(const char *name, uint32_t cbmem_id, size_t *size_out,
325 enum cbfs_type *type)
326{
327 return cbfs_type_alloc(name, _cbfs_cbmem_allocator, (void *)(uintptr_t)cbmem_id,
328 size_out, type);
329}
330
331static inline void *cbfs_ro_type_cbmem_alloc(const char *name, uint32_t cbmem_id,
332 size_t *size_out, enum cbfs_type *type)
333{
334 return cbfs_ro_type_alloc(name, _cbfs_cbmem_allocator, (void *)(uintptr_t)cbmem_id,
335 size_out, type);
Julius Werner11075fc2020-12-29 17:51:04 -0800336}
337
Julius Werner05714cc2021-04-15 23:25:44 -0700338static inline void *cbfs_unverified_area_cbmem_alloc(const char *area, const char *name,
339 uint32_t cbmem_id, size_t *size_out)
340{
341 return _cbfs_unverified_area_alloc(area, name, _cbfs_cbmem_allocator,
342 (void *)(uintptr_t)cbmem_id, size_out);
343}
344
Julius Werner57d4bc62021-11-15 10:13:37 -0800345static inline size_t cbfs_get_size(const char *name)
346{
347 union cbfs_mdata mdata;
348 struct region_device rdev;
349 if (_cbfs_boot_lookup(name, false, &mdata, &rdev) != CB_SUCCESS)
350 return 0;
351 return be32toh(mdata.h.len);
352}
353
354static inline size_t cbfs_ro_get_size(const char *name)
355{
356 union cbfs_mdata mdata;
357 struct region_device rdev;
358 if (_cbfs_boot_lookup(name, true, &mdata, &rdev) != CB_SUCCESS)
359 return 0;
360 return be32toh(mdata.h.len);
361}
362
363static inline enum cbfs_type cbfs_get_type(const char *name)
364{
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);
370}
371
372static inline enum cbfs_type cbfs_ro_get_type(const char *name)
373{
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);
379}
380
381static inline bool cbfs_file_exists(const char *name)
382{
383 union cbfs_mdata mdata;
384 struct region_device rdev;
385 if (_cbfs_boot_lookup(name, false, &mdata, &rdev) != CB_SUCCESS)
386 return false;
387 return true;
388}
389
390static inline bool cbfs_ro_file_exists(const char *name)
391{
392 union cbfs_mdata mdata;
393 struct region_device rdev;
394 if (_cbfs_boot_lookup(name, true, &mdata, &rdev) != CB_SUCCESS)
395 return false;
396 return true;
397}
398
Peter Stuge483b7bb2009-04-14 07:40:01 +0000399#endif