blob: 37bac308d8bf017cf6915d8b955da27026922307 [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>
Aaron Durbin295d58b2015-12-15 13:33:51 -06008#include <commonlib/cbfs.h>
Julius Werner9b1f3cc2020-12-30 17:30:12 -08009#include <commonlib/mem_pool.h>
Aaron Durbin899d13d2015-05-15 23:39:23 -050010#include <program_loading.h>
Julius Werner1e37c9c2019-12-11 17:09:39 -080011#include <types.h>
Julius Wernerfdabf3f2020-05-06 17:06:35 -070012#include <vb2_sha.h>
Daisuke Nojirie1298df2014-12-01 15:30:01 -080013
Aaron Durbin899d13d2015-05-15 23:39:23 -050014
Julius Werner11075fc2020-12-29 17:51:04 -080015/**********************************************************************************************
16 * CBFS FILE ACCESS APIs *
17 **********************************************************************************************/
Julius Werner723e3b12020-12-29 17:33:30 -080018
Julius Werner7778cf22021-01-05 18:54:19 -080019/*
20 * These are the APIs used to access files in CBFS. In order to keep the calls simple and free
21 * of clutter in the common cases, but still offer all advanced functionality when needed, there
22 * are many different variations that are implemented by wrapping the same underlying API with
23 * static inlines. All accessors have in common that they look up files by name, and will
24 * transparently decompress files that are compressed.
25 *
26 * There are three main flavors of CBFS accessors:
27 *
28 * size_t cbfs_load(char *name, void *buf, size_t size): Loads the contents of a CBFS file into
29 * a buffer provided by the caller (by providing pointer and size to it). Will return the
30 * amount of bytes loaded on success, or 0 on error.
31 *
32 * void *cbfs_map(char *name, size_t *size_out): Maps a file into the address space. If the file
33 * is not compressed and the platform supports direct memory-mapping for the boot medium,
34 * a pointer to the platform mapping is returned directly. In all other cases, memory will
35 * be allocated from the cbfs_cache and file data will be loaded into there. Returns a
36 * pointer to the mapping on success, or NULL on error. If an optional size_out parameter
37 * is passed in, it will be filled out with the size of the mapped data. Caller should call
38 * cbfs_unmap() after it is done using the mapping to free up the cbfs_cache if possible.
39 *
40 * void *cbfs_alloc(char *name, cbfs_allocator_t allocator, void *arg, size_t *size_out): Loads
41 * file data into memory provided by a custom allocator function that the caller passes in.
42 * The caller may pass an argument that is passed through verbatim to the allocator.
43 * Returns the pointer returned by the allocator (where the file data was loaded to) on
44 * success, or NULL on error. If an optional size_out parameter is passed in, it will be
45 * filled out with the size of the loaded data.
46 *
47 * void *cbfs_cbmem_alloc(char *name, uint32_t cbmem_id, size_t *size_out): Wrapper around
48 * cbfs_alloc() that will provide an allocator function for allocating space for the file
49 * data in CBMEM, with the provided CBMEM ID.
50 *
51 * All of these flavors have variations with any of the following optional parameters added:
52 *
53 * ..._ro_...: Will force looking up the CBFS file in the read-only CBFS (the "COREBOOT" FMAP
54 * section), even when running in an RW stage from one of the RW CBFSs. Only relevant if
55 * CONFIG(VBOOT) is set.
56 *
57 * ..._type_...: May pass in an extra enum cbfs_type *type parameter. If the value it points to
58 * is CBFS_TYPE_QUERY, it will be replaced with the actual CBFS type of the found file. If
59 * it is anything else, the type will be compared with the actually found type, and the
60 * operation will fail if they don't match.
61 */
Julius Werner11075fc2020-12-29 17:51:04 -080062
Julius Werner7778cf22021-01-05 18:54:19 -080063/*
64 * An allocator function for passing to cbfs_alloc(). Takes the argument that was originally
65 * passed to cbfs_alloc(), the size of the file to be loaded, and a pointer to the already
66 * loaded and verified file metadata (for rare cases where the allocator needs to check custom
67 * attributes). Must return a pointer to space of the requested size where the file data should
68 * be loaded, or NULL to make the operation fail.
69 */
Julius Werner4676ec52021-03-10 16:52:14 -080070typedef void *(*cbfs_allocator_t)(void *arg, size_t size, const union cbfs_mdata *mdata);
Julius Werner7778cf22021-01-05 18:54:19 -080071
72static inline size_t cbfs_load(const char *name, void *buf, size_t size);
73static inline size_t cbfs_ro_load(const char *name, void *buf, size_t size);
74static inline size_t cbfs_type_load(const char *name, void *buf, size_t size,
75 enum cbfs_type *type);
76static inline size_t cbfs_ro_type_load(const char *name, void *buf, size_t size,
77 enum cbfs_type *type);
78
79static inline void *cbfs_map(const char *name, size_t *size_out);
Julius Werner11075fc2020-12-29 17:51:04 -080080static inline void *cbfs_ro_map(const char *name, size_t *size_out);
Julius Werner7778cf22021-01-05 18:54:19 -080081static inline void *cbfs_type_map(const char *name, size_t *size_out, enum cbfs_type *type);
82static inline void *cbfs_ro_type_map(const char *name, size_t *size_out, enum cbfs_type *type);
83
84static inline void *cbfs_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
85 size_t *size_out);
86static inline void *cbfs_ro_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
87 size_t *size_out);
88static inline void *cbfs_type_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
89 size_t *size_out, enum cbfs_type *type);
90static inline void *cbfs_ro_type_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
91 size_t *size_out, enum cbfs_type *type);
92
93static inline void *cbfs_cbmem_alloc(const char *name, uint32_t cbmem_id, size_t *size_out);
94static inline void *cbfs_ro_cbmem_alloc(const char *name, uint32_t cbmem_id, size_t *size_out);
95static inline void *cbfs_type_cbmem_alloc(const char *name, uint32_t cbmem_id, size_t *size_out,
96 enum cbfs_type *type);
97static inline void *cbfs_ro_type_cbmem_alloc(const char *name, uint32_t cbmem_id,
98 size_t *size_out, enum cbfs_type *type);
Julius Werner11075fc2020-12-29 17:51:04 -080099
Julius Werner723e3b12020-12-29 17:33:30 -0800100/* Removes a previously allocated CBFS mapping. Should try to unmap mappings in strict LIFO
101 order where possible, since mapping backends often don't support more complicated cases. */
Julius Werner9b1f3cc2020-12-30 17:30:12 -0800102void cbfs_unmap(void *mapping);
Julius Werner723e3b12020-12-29 17:33:30 -0800103
Aaron Durbin899d13d2015-05-15 23:39:23 -0500104/* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */
105int cbfs_prog_stage_load(struct prog *prog);
106
Julius Werner9b1f3cc2020-12-30 17:30:12 -0800107
Julius Werner11075fc2020-12-29 17:51:04 -0800108/**********************************************************************************************
109 * BOOT DEVICE HELPER APIs *
110 **********************************************************************************************/
111
Julius Werner0d9072b2020-03-05 12:51:08 -0800112/*
Julius Werner9b1f3cc2020-12-30 17:30:12 -0800113 * The shared memory pool for backing mapped CBFS files, and other CBFS allocation needs.
114 * On x86 platforms, this would only be needed to transparently map compressed files, but it
115 * would require a permanent CBMEM carveout to be safe to use during S3 resume. Since it's not
116 * clear whether this feature is necessary or worth the wasted memory, it is currently disabled
117 * but could be added behind a Kconfig later if desired.
118 */
119#define CBFS_CACHE_AVAILABLE (!CONFIG(ARCH_X86))
120extern struct mem_pool cbfs_cache;
121
122/*
Julius Werner723e3b12020-12-29 17:33:30 -0800123 * Data structure that represents "a" CBFS boot device, with optional metadata cache. Generally
124 * we only have one of these, or two (RO and RW) when CONFIG(VBOOT) is set. The region device
125 * stored here must always be a subregion of boot_device_ro().
Julius Werner0d9072b2020-03-05 12:51:08 -0800126 */
Julius Werner1e37c9c2019-12-11 17:09:39 -0800127struct cbfs_boot_device {
128 struct region_device rdev;
129 void *mcache;
130 size_t mcache_size;
131};
132
133/* Helper to fill out |mcache| and |mcache_size| in a cbfs_boot_device. */
134void cbfs_boot_device_find_mcache(struct cbfs_boot_device *cbd, uint32_t id);
135
136/*
Julius Werner723e3b12020-12-29 17:33:30 -0800137 * Retrieves the currently active CBFS boot device. If |force_ro| is set, will always return the
138 * read-only CBFS instead (this only makes a difference when CONFIG(VBOOT) is enabled). May
139 * perform certain CBFS initialization tasks. Returns NULL on error (e.g. boot device IO error).
Julius Werner1e37c9c2019-12-11 17:09:39 -0800140 */
141const struct cbfs_boot_device *cbfs_get_boot_device(bool force_ro);
Aaron Durbin899d13d2015-05-15 23:39:23 -0500142
Julius Wernerfdabf3f2020-05-06 17:06:35 -0700143/*
Julius Werner723e3b12020-12-29 17:33:30 -0800144 * Builds the mcache (if |cbd->mcache| is set) and verifies |metadata_hash| (if it is not NULL).
145 * If CB_CBFS_CACHE_FULL is returned, the mcache is incomplete but still valid and the metadata
146 * hash was still verified. Should be called once per *boot* (not once per stage) before the
147 * first CBFS access.
Julius Wernerfdabf3f2020-05-06 17:06:35 -0700148 */
149cb_err_t cbfs_init_boot_device(const struct cbfs_boot_device *cbd,
150 struct vb2_hash *metadata_hash);
151
Julius Werner11075fc2020-12-29 17:51:04 -0800152
153/**********************************************************************************************
154 * LEGACY APIs, TO BE DEPRECATED/REPLACED *
155 **********************************************************************************************/
156
157/* Locate file by name and optional type. Return 0 on success. < 0 on error. */
158int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type);
159/* Locate file in a specific region of fmap. Return 0 on success. < 0 on error*/
160int cbfs_locate_file_in_region(struct cbfsf *fh, const char *region_name,
161 const char *name, uint32_t *type);
162
163/* Return mapping of option ROM found in boot device. NULL on error. */
164void *cbfs_boot_map_optionrom(uint16_t vendor, uint16_t device);
165/* Return mapping of option ROM with revision number. Returns NULL on error. */
166void *cbfs_boot_map_optionrom_revision(uint16_t vendor, uint16_t device, uint8_t rev);
167
168/* Load |in_size| bytes from |rdev| at |offset| to the |buffer_size| bytes large |buffer|,
169 decompressing it according to |compression| in the process. Returns the decompressed file
170 size, or 0 on error. LZMA files will be mapped for decompression. LZ4 files will be
171 decompressed in-place with the buffer size requirements outlined in compression.h. */
172size_t cbfs_load_and_decompress(const struct region_device *rdev, size_t offset,
173 size_t in_size, void *buffer, size_t buffer_size, uint32_t compression);
174
Julius Werner9b1f3cc2020-12-30 17:30:12 -0800175
Julius Werner11075fc2020-12-29 17:51:04 -0800176/**********************************************************************************************
177 * INTERNAL HELPERS FOR INLINES, DO NOT USE. *
178 **********************************************************************************************/
Julius Werner7778cf22021-01-05 18:54:19 -0800179void *_cbfs_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
180 size_t *size_out, bool force_ro, enum cbfs_type *type);
Julius Werner11075fc2020-12-29 17:51:04 -0800181
Julius Werner7778cf22021-01-05 18:54:19 -0800182struct _cbfs_default_allocator_arg {
183 void *buf;
184 size_t buf_size;
185};
Julius Werner4676ec52021-03-10 16:52:14 -0800186void *_cbfs_default_allocator(void *arg, size_t size, const union cbfs_mdata *unused);
Julius Werner7778cf22021-01-05 18:54:19 -0800187
Julius Werner4676ec52021-03-10 16:52:14 -0800188void *_cbfs_cbmem_allocator(void *arg, size_t size, const union cbfs_mdata *unused);
Julius Werner11075fc2020-12-29 17:51:04 -0800189
190/**********************************************************************************************
191 * INLINE IMPLEMENTATIONS *
192 **********************************************************************************************/
Julius Werner7778cf22021-01-05 18:54:19 -0800193static inline void *cbfs_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
194 size_t *size_out)
195{
196 return cbfs_type_alloc(name, allocator, arg, size_out, NULL);
197}
198
199static inline void *cbfs_ro_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
200 size_t *size_out)
201{
202 return cbfs_ro_type_alloc(name, allocator, arg, size_out, NULL);
203}
204
205static inline void *cbfs_type_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
206 size_t *size_out, enum cbfs_type *type)
207{
208 return _cbfs_alloc(name, allocator, arg, size_out, false, type);
209}
210
211static inline void *cbfs_ro_type_alloc(const char *name, cbfs_allocator_t allocator, void *arg,
212 size_t *size_out, enum cbfs_type *type)
213{
214 return _cbfs_alloc(name, allocator, arg, size_out, true, type);
215}
216
Julius Werner11075fc2020-12-29 17:51:04 -0800217static inline void *cbfs_map(const char *name, size_t *size_out)
218{
Julius Werner7778cf22021-01-05 18:54:19 -0800219 return cbfs_type_map(name, size_out, NULL);
Julius Werner11075fc2020-12-29 17:51:04 -0800220}
221
222static inline void *cbfs_ro_map(const char *name, size_t *size_out)
223{
Julius Werner7778cf22021-01-05 18:54:19 -0800224 return cbfs_ro_type_map(name, size_out, NULL);
Julius Werner11075fc2020-12-29 17:51:04 -0800225}
226
Julius Werner7778cf22021-01-05 18:54:19 -0800227static inline void *cbfs_type_map(const char *name, size_t *size_out, enum cbfs_type *type)
Julius Werner11075fc2020-12-29 17:51:04 -0800228{
Julius Werner7778cf22021-01-05 18:54:19 -0800229 return cbfs_type_alloc(name, NULL, NULL, size_out, type);
Julius Werner11075fc2020-12-29 17:51:04 -0800230}
231
Julius Werner7778cf22021-01-05 18:54:19 -0800232static inline void *cbfs_ro_type_map(const char *name, size_t *size_out, enum cbfs_type *type)
Julius Werner11075fc2020-12-29 17:51:04 -0800233{
Julius Werner7778cf22021-01-05 18:54:19 -0800234 return cbfs_ro_type_alloc(name, NULL, NULL, size_out, type);
235}
236
237static inline size_t _cbfs_load(const char *name, void *buf, size_t size, bool force_ro,
238 enum cbfs_type *type)
239{
240 struct _cbfs_default_allocator_arg arg = { .buf = buf, .buf_size = size };
241 if (_cbfs_alloc(name, _cbfs_default_allocator, &arg, &size, force_ro, type))
242 return size;
243 else
244 return 0;
245}
246
247static inline size_t cbfs_load(const char *name, void *buf, size_t size)
248{
249 return cbfs_type_load(name, buf, size, NULL);
250}
251
252static inline size_t cbfs_type_load(const char *name, void *buf, size_t size,
253 enum cbfs_type *type)
254{
255 return _cbfs_load(name, buf, size, false, type);
256}
257
258static inline size_t cbfs_ro_load(const char *name, void *buf, size_t size)
259{
260 return cbfs_ro_type_load(name, buf, size, NULL);
261}
262
263static inline size_t cbfs_ro_type_load(const char *name, void *buf, size_t size,
264 enum cbfs_type *type)
265{
266 return _cbfs_load(name, buf, size, true, type);
267}
268
269static inline void *cbfs_cbmem_alloc(const char *name, uint32_t cbmem_id, size_t *size_out)
270{
271 return cbfs_type_cbmem_alloc(name, cbmem_id, size_out, NULL);
272}
273
274static inline void *cbfs_ro_cbmem_alloc(const char *name, uint32_t cbmem_id, size_t *size_out)
275{
276 return cbfs_ro_type_cbmem_alloc(name, cbmem_id, size_out, NULL);
277}
278
279static inline void *cbfs_type_cbmem_alloc(const char *name, uint32_t cbmem_id, size_t *size_out,
280 enum cbfs_type *type)
281{
282 return cbfs_type_alloc(name, _cbfs_cbmem_allocator, (void *)(uintptr_t)cbmem_id,
283 size_out, type);
284}
285
286static inline void *cbfs_ro_type_cbmem_alloc(const char *name, uint32_t cbmem_id,
287 size_t *size_out, enum cbfs_type *type)
288{
289 return cbfs_ro_type_alloc(name, _cbfs_cbmem_allocator, (void *)(uintptr_t)cbmem_id,
290 size_out, type);
Julius Werner11075fc2020-12-29 17:51:04 -0800291}
292
Peter Stuge483b7bb2009-04-14 07:40:01 +0000293#endif