summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/util/smmstoretool/index.md24
-rw-r--r--util/smmstoretool/Makefile7
-rw-r--r--util/smmstoretool/main.c16
-rw-r--r--util/smmstoretool/storage.c28
-rw-r--r--util/smmstoretool/storage.h1
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;
};