diff options
author | Sergii Dmytruk <sergii.dmytruk@3mdeb.com> | 2023-11-17 19:31:20 +0200 |
---|---|---|
committer | Martin L Roth <gaumless@gmail.com> | 2024-03-09 23:22:55 +0000 |
commit | 04bd9651435843ce4b03c9717f2965fe344fe5cc (patch) | |
tree | 0193502b26818c738206a60862c689485d533a50 /util/smmstoretool/data.c | |
parent | 7a51acfbe91c7f9d01837103341526abb6ea46f4 (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.c | 180 |
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; +} |