/* SPDX-License-Identifier: GPL-2.0-or-later */ #include "storage.h" #include #include #include "commonlib/bsd/compiler.h" #include "fmap.h" #include "fv.h" #include "utils.h" bool storage_open(const char store_file[], struct storage_t *storage, bool rw) { storage->rw = rw; storage->file = map_file(store_file, rw); if (storage->file.start == NULL) { fprintf(stderr, "Failed to load smm-store-file \"%s\"\n", store_file); return false; } /* If we won't find FMAP with SMMSTORE, use the whole file, but fail if * FMAP is there without SMMSTORE. */ storage->region = storage->file; long fmap_offset = fmap_find(storage->file.start, storage->file.length); if (fmap_offset >= 0) { struct fmap *fmap = (void *)(storage->file.start + fmap_offset); const struct fmap_area *area = fmap_find_area(fmap, "SMMSTORE"); if (area == NULL) { fprintf(stderr, "Found FMAP without SMMSTORE in \"%s\"\n", store_file); return false; } storage->region.start += area->offset; storage->region.length = area->size; } bool auth_vars; if (!fv_parse(storage->region, &storage->store_area, &auth_vars)) { if (!rw) { fprintf(stderr, "Failed to find variable store in \"%s\"\n", store_file); goto error; } fprintf(stderr, "\nThe variable store has not been found in the ROM image\n" "and is about to be initialized. This situation is normal\n" "for a release image, as the variable store is usually\n" "initialized on the first boot of the platform.\n\n"); if (!fv_init(storage->region)) { fprintf(stderr, "Failed to create variable store in \"%s\"\n", store_file); goto error; } if (!fv_parse(storage->region, &storage->store_area, &auth_vars)) { fprintf(stderr, "Failed to parse newly formatted store in \"%s\"\n", store_file); goto error; } fprintf(stderr, "Successfully created variable store in \"%s\"\n", store_file); } storage->vs = vs_load(storage->store_area, auth_vars); return true; error: unmap_file(storage->file); return false; } bool storage_write_back(struct storage_t *storage) { assert(storage->rw && "Only RW storage can be updated."); bool success = vs_store(&storage->vs, storage->store_area); if (!success) fprintf(stderr, "Failed to update variable store\n"); storage_drop(storage); return success; } void storage_drop(struct storage_t *storage) { unmap_file(storage->file); vs_free(&storage->vs); }