cbfs.h
1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #ifndef _CBFS_H_ 4 #define _CBFS_H_ 5 6 #include <cbmem.h> 7 #include <commonlib/bsd/cbfs_mdata.h> 8 #include <commonlib/mem_pool.h> 9 #include <commonlib/region.h> 10 #include <endian.h> 11 #include <program_loading.h> 12 #include <types.h> 13 #include <vb2_sha.h> 14 15 16 /********************************************************************************************** 17 * CBFS FILE ACCESS APIs * 18 **********************************************************************************************/ 19 20 /* 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 * 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. 62 * 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. 67 */ 68 69 /* 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 */ 76 typedef void *(*cbfs_allocator_t)(void *arg, size_t size, const union cbfs_mdata *mdata); 77 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); 86 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, 92 size_t *size_out); 93 94 static inline void *cbfs_alloc(const char *name, cbfs_allocator_t allocator, void *arg, 95 size_t *size_out); 96 static inline void *cbfs_ro_alloc(const char *name, cbfs_allocator_t allocator, void *arg, 97 size_t *size_out); 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, 104 size_t *size_out); 105 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); 114 115 /* 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 */ 128 void cbfs_preload(const char *name); 129 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); 133 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); 136 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); 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. */ 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); 146 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); 150 151 152 /********************************************************************************************** 153 * BOOT DEVICE HELPER APIs * 154 **********************************************************************************************/ 155 156 /* 157 * The shared memory pool for backing mapped CBFS files, and other CBFS allocation needs. 158 */ 159 extern struct mem_pool cbfs_cache; 160 161 /* 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(). 165 */ 166 struct 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. */ 173 void cbfs_boot_device_find_mcache(struct cbfs_boot_device *cbd, uint32_t id); 174 175 /* 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). 179 */ 180 const struct cbfs_boot_device *cbfs_get_boot_device(bool force_ro); 181 182 /* 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 186 * first CBFS access. 187 */ 188 enum cb_err cbfs_init_boot_device(const struct cbfs_boot_device *cbd, 189 struct vb2_hash *metadata_hash); 190 191 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); 197 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); 200 201 void *_cbfs_unverified_area_alloc(const char *area, const char *name, 202 cbfs_allocator_t allocator, void *arg, size_t *size_out); 203 204 struct _cbfs_default_allocator_arg { 205 void *buf; 206 size_t buf_size; 207 }; 208 void *_cbfs_default_allocator(void *arg, size_t size, const union cbfs_mdata *unused); 209 210 void *_cbfs_cbmem_allocator(void *arg, size_t size, const union cbfs_mdata *unused); 211 212 /********************************************************************************************** 213 * INLINE IMPLEMENTATIONS * 214 **********************************************************************************************/ 215 static 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 221 static 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 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) 229 { 230 return _cbfs_alloc(name, allocator, arg, size_out, false, type); 231 } 232 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) 235 { 236 return _cbfs_alloc(name, allocator, arg, size_out, true, type); 237 } 238 239 static 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 246 static inline void *cbfs_map(const char *name, size_t *size_out) 247 { 248 return cbfs_type_map(name, size_out, NULL); 249 } 250 251 static inline void *cbfs_ro_map(const char *name, size_t *size_out) 252 { 253 return cbfs_ro_type_map(name, size_out, NULL); 254 } 255 256 static inline void *cbfs_type_map(const char *name, size_t *size_out, enum cbfs_type *type) 257 { 258 return cbfs_type_alloc(name, NULL, NULL, size_out, type); 259 } 260 261 static inline void *cbfs_ro_type_map(const char *name, size_t *size_out, enum cbfs_type *type) 262 { 263 return cbfs_ro_type_alloc(name, NULL, NULL, size_out, type); 264 } 265 266 static 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 272 static 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 282 static 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 287 static 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 293 static 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 298 static 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 304 static 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 314 static 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 319 static 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 324 static 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 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) 333 { 334 return cbfs_ro_type_alloc(name, _cbfs_cbmem_allocator, (void *)(uintptr_t)cbmem_id, 335 size_out, type); 336 } 337 338 static 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 345 static 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 354 static 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 363 static 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 372 static 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 381 static 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 390 static 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 399 #endif