Files
Krystian Hebel 2bce548f3e util/smmstoretool: allow for writing raw type variables from file
Some variables can't be described using any of the predefined types.
Allow passing their values from a file.

Upstream-Status: Pending
Change-Id: Idb03e8dbdbdd446cc16cae584640cf1641ecc2c1
Signed-off-by: Krystian Hebel <krystian.hebel@3mdeb.com>
2025-07-22 16:18:26 +02:00

222 lines
4.5 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_UINT64:
if (data_size != 8) {
fprintf(stderr,
"warning: expected size of 8, got %zu\n",
data_size);
}
if (data_size >= 8)
printf("%llu\n", (unsigned long long)*(uint64_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,
bool *failed)
{
char *end;
unsigned long long uint = strtoull(source, &end, /*base=*/0);
if (*end != '\0') {
fprintf(stderr, "Trailing characters in \"%s\": %s\n",
source, end);
*failed = true;
return 0;
}
if (uint > max) {
fprintf(stderr, "Invalid %s value: %llu\n", type, uint);
*failed = true;
return 0;
}
*failed = false;
return uint;
}
void *make_data(const char source[], size_t *data_size, enum data_type type)
{
switch (type) {
void *data;
bool boolean;
uint64_t uint;
bool failed;
FILE *f;
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, &failed);
if (failed)
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, &failed);
if (failed)
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, &failed);
if (failed)
return NULL;
*data_size = 4;
data = xmalloc(*data_size);
*(uint32_t *)data = uint;
return data;
case DATA_TYPE_UINT64:
uint = parse_uint(source, "uint64", UINT64_MAX, &failed);
if (failed)
return NULL;
*data_size = 8;
data = xmalloc(*data_size);
*(uint64_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:
f = fopen(source, "rb");
if (!f) {
perror(source);
return NULL;
}
fseek(f, 0, SEEK_END);
*data_size = ftell(f);
fseek(f, 0, SEEK_SET);
data = xmalloc(*data_size);
if (fread(data, 1, *data_size, f) != *data_size) {
fprintf(stderr, "Error reading data from '%s', aborting\n", source);
free(data);
data = NULL;
}
fclose(f);
return data;
}
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, "uint64"))
*type = DATA_TYPE_UINT64;
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;
}