Input file is parsed for FMAP and SMMSTORE region which is used if found. Otherwise, the whole file is assumed to be the region. Passing an image with FMAP that lacks SMMSTORER is an error. Change-Id: Ieab555d7bbcfa4dadf6a5070d1297acd737440fb Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/80903 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
96 lines
2.2 KiB
C
96 lines
2.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#include "storage.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
|
|
#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;
|
|
}
|
|
|
|
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);
|
|
}
|