summaryrefslogtreecommitdiff
path: root/util/smmstoretool/data.c
diff options
context:
space:
mode:
authorSergii Dmytruk <sergii.dmytruk@3mdeb.com>2023-11-17 19:31:20 +0200
committerMartin L Roth <gaumless@gmail.com>2024-03-09 23:22:55 +0000
commit04bd9651435843ce4b03c9717f2965fe344fe5cc (patch)
tree0193502b26818c738206a60862c689485d533a50 /util/smmstoretool/data.c
parent7a51acfbe91c7f9d01837103341526abb6ea46f4 (diff)
util: add smmstoretool for editing SMMSTORE
Offline SMMSTORE variable modification tool. Can be used to pre-configure ROM image or debug EFI state stored in a dump. Change-Id: I6c1c06f1d0c39c13b5be76a3070f09b715aca6e0 Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/79080 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Michał Żygowski <michal.zygowski@3mdeb.com> Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Diffstat (limited to 'util/smmstoretool/data.c')
-rw-r--r--util/smmstoretool/data.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/util/smmstoretool/data.c b/util/smmstoretool/data.c
new file mode 100644
index 0000000000..778bf8a6cb
--- /dev/null
+++ b/util/smmstoretool/data.c
@@ -0,0 +1,180 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "data.h"
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils.h"
+
+void print_data(const uint8_t data[], size_t data_size, enum data_type type)
+{
+ if (data_size == 0)
+ return;
+
+ switch (type) {
+ case DATA_TYPE_BOOL:
+ bool value = false;
+ for (size_t i = 0; i < data_size; ++i) {
+ if (data[i] != 0) {
+ value = true;
+ break;
+ }
+ }
+ printf("%s\n", value ? "true" : "false");
+ break;
+ case DATA_TYPE_UINT8:
+ if (data_size != 1) {
+ fprintf(stderr,
+ "warning: expected size of 1, got %zu\n",
+ data_size);
+ }
+
+ if (data_size >= 1)
+ printf("%u\n", *(uint8_t *)data);
+ break;
+ case DATA_TYPE_UINT16:
+ if (data_size != 2) {
+ fprintf(stderr,
+ "warning: expected size of 2, got %zu\n",
+ data_size);
+ }
+
+ if (data_size >= 2)
+ printf("%u\n", *(uint16_t *)data);
+ break;
+ case DATA_TYPE_UINT32:
+ if (data_size != 4) {
+ fprintf(stderr,
+ "warning: expected size of 4, got %zu\n",
+ data_size);
+ }
+
+ if (data_size >= 4)
+ printf("%u\n", *(uint32_t *)data);
+ break;
+ case DATA_TYPE_ASCII:
+ for (size_t i = 0; i < data_size; ++i) {
+ char c = data[i];
+ if (isprint(c))
+ printf("%c", c);
+ }
+ printf("\n");
+ break;
+ case DATA_TYPE_UNICODE:
+ char *chars = to_chars((const CHAR16 *)data, data_size);
+ printf("%s\n", chars);
+ free(chars);
+ break;
+ case DATA_TYPE_RAW:
+ fwrite(data, 1, data_size, stdout);
+ break;
+ }
+}
+
+static uint64_t parse_uint(const char source[],
+ const char type[],
+ unsigned long long max)
+{
+ char *end;
+ unsigned long long uint = strtoull(source, &end, /*base=*/0);
+ if (*end != '\0') {
+ fprintf(stderr, "Trailing characters in \"%s\": %s\n",
+ source, end);
+ return UINT64_MAX;
+ }
+ if (uint > max) {
+ fprintf(stderr, "Invalid %s value: %llu\n", type, uint);
+ return UINT64_MAX;
+ }
+
+ return uint;
+}
+
+void *make_data(const char source[], size_t *data_size, enum data_type type)
+{
+ switch (type) {
+ void *data;
+ bool boolean;
+ unsigned long long uint;
+
+ case DATA_TYPE_BOOL:
+ if (str_eq(source, "true")) {
+ boolean = true;
+ } else if (str_eq(source, "false")) {
+ boolean = false;
+ } else {
+ fprintf(stderr, "Invalid boolean value: \"%s\"\n",
+ source);
+ return NULL;
+ }
+
+ *data_size = 1;
+ data = xmalloc(*data_size);
+ *(uint8_t *)data = boolean;
+ return data;
+ case DATA_TYPE_UINT8:
+ uint = parse_uint(source, "uint8", UINT8_MAX);
+ if (uint == UINT64_MAX)
+ return NULL;
+
+ *data_size = 1;
+ data = xmalloc(*data_size);
+ *(uint8_t *)data = uint;
+ return data;
+ case DATA_TYPE_UINT16:
+ uint = parse_uint(source, "uint16", UINT16_MAX);
+ if (uint == UINT64_MAX)
+ return NULL;
+
+ *data_size = 2;
+ data = xmalloc(*data_size);
+ *(uint16_t *)data = uint;
+ return data;
+ case DATA_TYPE_UINT32:
+ uint = parse_uint(source, "uint32", UINT32_MAX);
+ if (uint == UINT64_MAX)
+ return NULL;
+
+ *data_size = 4;
+ data = xmalloc(*data_size);
+ *(uint32_t *)data = uint;
+ return data;
+ case DATA_TYPE_ASCII:
+ *data_size = strlen(source) + 1;
+ return strdup(source);
+ case DATA_TYPE_UNICODE:
+ return to_uchars(source, data_size);
+ case DATA_TYPE_RAW:
+ fprintf(stderr, "Raw data type is output only\n");
+ return NULL;
+ }
+
+ return NULL;
+}
+
+bool parse_data_type(const char str[], enum data_type *type)
+{
+ if (str_eq(str, "bool"))
+ *type = DATA_TYPE_BOOL;
+ else if (str_eq(str, "uint8"))
+ *type = DATA_TYPE_UINT8;
+ else if (str_eq(str, "uint16"))
+ *type = DATA_TYPE_UINT16;
+ else if (str_eq(str, "uint32"))
+ *type = DATA_TYPE_UINT32;
+ else if (str_eq(str, "ascii"))
+ *type = DATA_TYPE_ASCII;
+ else if (str_eq(str, "unicode"))
+ *type = DATA_TYPE_UNICODE;
+ else if (str_eq(str, "raw"))
+ *type = DATA_TYPE_RAW;
+ else
+ return false;
+
+ return true;
+}