diff options
-rw-r--r-- | Documentation/util/smmstoretool/index.md | 24 | ||||
-rw-r--r-- | util/smmstoretool/Makefile | 7 | ||||
-rw-r--r-- | util/smmstoretool/main.c | 16 | ||||
-rw-r--r-- | util/smmstoretool/storage.c | 28 | ||||
-rw-r--r-- | util/smmstoretool/storage.h | 1 |
5 files changed, 59 insertions, 17 deletions
diff --git a/Documentation/util/smmstoretool/index.md b/Documentation/util/smmstoretool/index.md index f7af60579d..5be6ffc79b 100644 --- a/Documentation/util/smmstoretool/index.md +++ b/Documentation/util/smmstoretool/index.md @@ -4,13 +4,20 @@ Offline SMMSTORE variable modification tool. ## Operation +### File formats + +To discover SMMSTORE, the tool first looks for FMAP header and, if found, for +SMMSTORE region. If FMAP is found but it has no SMMSTORE region, that's an +error. If there is no FMAP, the whole file is assumed to be SMMSTORE +region (e.g., extracted via `cbfstool`). + ### Storage initialization If SMMSTORE presence isn't detected and an update operation is requested, the -store spanning the whole file is created automatically. Size of the store file -must be a multiple of 64 KiB (block size in version 2 of SMMSTORE protocol), -the variable storage itself will be 64 KiB in size. That's the way EDK2 makes -use of it. +store spanning the whole region is created automatically. Size of the store +region must be a multiple of 64 KiB (block size in version 2 of SMMSTORE +protocol), the variable storage itself will be 64 KiB in size. That's the way +EDK2 makes use of it. Unlike online editing which mostly appends new variable entries each storage update with this tool drops all deleted or incomplete entries. @@ -28,7 +35,7 @@ Start with: ``` $ smmstoretool -h -Usage: smmstoretool smm-store-file sub-command +Usage: smmstoretool smm-store-file|rom sub-command smmstoretool -h|--help Sub-commands: @@ -58,7 +65,8 @@ to typical configuration values are supported: ## Examples -`SMMSTORE` is the name of a file containing SMMSTORE data. +`SMMSTORE` is the name of a file containing SMMSTORE data or a full ROM image +with FMAP that includes SMMSTORE region. ### Variable listing @@ -111,9 +119,13 @@ $ smmstoretool SMMSTORE remove -g dasharo -n NetworkBoot If one edits a newly generated Dasharo `coreboot.rom`: ```bash +# editing exported storage cbfstool coreboot.rom read -r SMMSTORE -f SMMSTORE smmstoretool SMMSTORE set -g dasharo -n NetworkBoot -t bool -v true cbfstool coreboot.rom write -r SMMSTORE -f SMMSTORE + +# editing in-place storage +smmstoretool coreboot.rom set -g dasharo -n NetworkBoot -t bool -v true ``` On the first boot, "Network Boot" setting will already be enabled. diff --git a/util/smmstoretool/Makefile b/util/smmstoretool/Makefile index 78b77caa2d..d73c25165a 100644 --- a/util/smmstoretool/Makefile +++ b/util/smmstoretool/Makefile @@ -14,6 +14,7 @@ HOSTCFLAGS ?= $(CFLAGS) HOSTCFLAGS += -Wall -Wextra -MMD -MP -O3 HOSTCFLAGS += -I $(ROOT)/commonlib/bsd/include HOSTCFLAGS += -I $(ROOT)/vendorcode/intel/edk2/ +HOSTCFLAGS += -I $(TOP)/util/cbfstool/flashmap/ HOSTCFLAGS += -I $(MDE) HOSTLDFLAGS ?= $(LDFLAGS) @@ -27,7 +28,10 @@ else $(error Unsupported machine: '$(MACHINE)') endif +# there files are in this directory SRC := data.c fv.c guids.c main.c storage.c utils.c vs.c +# and these are in $(TOP)/util/cbfstool/flashmap/ +SRC += fmap.c kv_pair.c valstr.c OBJ := $(SRC:.c=.o) DEP := $(SRC:.c=.o.d) @@ -53,4 +57,7 @@ $(PRG): $(OBJ) %.o: %.c $(HOSTCC) $(HOSTCFLAGS) -c -o $@ -MF $@.d $< +%.o: $(TOP)/util/cbfstool/flashmap/%.c + $(HOSTCC) $(HOSTCFLAGS) -c -o $@ -MF $@.d $< + -include $(DEP) diff --git a/util/smmstoretool/main.c b/util/smmstoretool/main.c index eff5d9c02b..4857b624ba 100644 --- a/util/smmstoretool/main.c +++ b/util/smmstoretool/main.c @@ -77,7 +77,7 @@ static const struct subcommand_t sub_commands[] = { static const int sub_command_count = ARRAY_SIZE(sub_commands); -static const char *USAGE_FMT = "Usage: %s smm-store-file sub-command\n" +static const char *USAGE_FMT = "Usage: %s smm-store-file|rom sub-command\n" " %s -h|--help\n"; static const char *program_name; @@ -131,7 +131,7 @@ static void print_types(FILE *f) static void help_set(FILE *f, const struct subcommand_t *info) { fprintf(f, "Create or update a variable:\n"); - fprintf(f, " %s smm-store-file %s \\\n", program_name, info->name); + fprintf(f, " %s smm-store-file|rom %s \\\n", program_name, info->name); fprintf(f, " -g vendor-guid \\\n"); fprintf(f, " -n variable-name \\\n"); fprintf(f, " -t variable-type \\\n"); @@ -229,7 +229,7 @@ static int process_set(int argc, char *argv[], const char store_file[]) static void help_list(FILE *f, const struct subcommand_t *info) { fprintf(f, "List variables in the store:\n"); - fprintf(f, " %s smm-store-file %s\n", program_name, info->name); + fprintf(f, " %s smm-store-file|rom %s\n", program_name, info->name); } static int process_list(int argc, char *argv[], const char store_file[]) @@ -261,7 +261,7 @@ static int process_list(int argc, char *argv[], const char store_file[]) static void help_get(FILE *f, const struct subcommand_t *info) { fprintf(f, "Read variable's value:\n"); - fprintf(f, " %s smm-store-file %s \\\n", program_name, info->name); + fprintf(f, " %s smm-store-file|rom %s \\\n", program_name, info->name); fprintf(f, " -g vendor-guid \\\n"); fprintf(f, " -n variable-name \\\n"); fprintf(f, " -t variable-type\n"); @@ -334,10 +334,10 @@ static int process_get(int argc, char *argv[], const char store_file[]) static void help_help(FILE *f, const struct subcommand_t *info) { fprintf(f, "Display generic help:\n"); - fprintf(f, " %s smm-store-file %s\n", program_name, info->name); + fprintf(f, " %s smm-store-file|rom %s\n", program_name, info->name); fprintf(f, "\n"); fprintf(f, "Display sub-command help:\n"); - fprintf(f, " %s smm-store-file %s sub-command\n", + fprintf(f, " %s smm-store-file|rom %s sub-command\n", program_name, info->name); } @@ -375,7 +375,7 @@ static int process_help(int argc, char *argv[], const char store_file[]) static void help_remove(FILE *f, const struct subcommand_t *info) { fprintf(f, "Remove a variable:\n"); - fprintf(f, " %s smm-store-file %s \\\n", program_name, info->name); + fprintf(f, " %s smm-store-file|rom %s \\\n", program_name, info->name); fprintf(f, " -g vendor-guid \\\n"); fprintf(f, " -n variable-name\n"); } @@ -432,7 +432,7 @@ static int process_remove(int argc, char *argv[], const char store_file[]) static void help_guids(FILE *f, const struct subcommand_t *info) { fprintf(f, "List recognized GUIDS:\n"); - fprintf(f, " %s smm-store-file %s\n", program_name, info->name); + fprintf(f, " %s smm-store-file|rom %s\n", program_name, info->name); } static int process_guids(int argc, char *argv[], const char store_file[]) diff --git a/util/smmstoretool/storage.c b/util/smmstoretool/storage.c index abc6840b67..8a02384108 100644 --- a/util/smmstoretool/storage.c +++ b/util/smmstoretool/storage.c @@ -5,6 +5,9 @@ #include <assert.h> #include <stdio.h> +#include "commonlib/bsd/compiler.h" +#include "fmap.h" + #include "fv.h" #include "utils.h" @@ -19,8 +22,27 @@ bool storage_open(const char store_file[], struct storage_t *storage, bool rw) 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->file, &storage->store_area, &auth_vars)) { + if (!fv_parse(storage->region, &storage->store_area, &auth_vars)) { if (!rw) { fprintf(stderr, "Failed to find variable store in \"%s\"\n", @@ -28,14 +50,14 @@ bool storage_open(const char store_file[], struct storage_t *storage, bool rw) goto error; } - if (!fv_init(storage->file)) { + if (!fv_init(storage->region)) { fprintf(stderr, "Failed to create variable store in \"%s\"\n", store_file); goto error; } - if (!fv_parse(storage->file, &storage->store_area, &auth_vars)) { + if (!fv_parse(storage->region, &storage->store_area, &auth_vars)) { fprintf(stderr, "Failed to parse newly formatted store in \"%s\"\n", store_file); diff --git a/util/smmstoretool/storage.h b/util/smmstoretool/storage.h index eb5cb08fc5..8b91713f14 100644 --- a/util/smmstoretool/storage.h +++ b/util/smmstoretool/storage.h @@ -9,6 +9,7 @@ struct storage_t { bool rw; struct mem_range_t file; + struct mem_range_t region; struct mem_range_t store_area; struct var_store_t vs; }; |