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>
181 lines
3.7 KiB
C
181 lines
3.7 KiB
C
/* 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;
|
|
}
|