Added the possibility to read and write INI files via iniparser, a small library that has been forked from its original sources at https://github.com/ndevilla/iniparser.
Signed-off-by: Tobias Schmidl <[email protected]> --- Makefile.am | 1 + env/env_user_config_file.c | 180 +++++++++++++++++++++++++++++++++ envdata.ini.example | 10 ++ include/env_user_config_file.h | 23 +++++ include/envdata.h | 10 ++ tools/bg_printenv.c | 41 +++++--- 6 files changed, 249 insertions(+), 16 deletions(-) create mode 100644 env/env_user_config_file.c create mode 100644 envdata.ini.example create mode 100644 include/env_user_config_file.h diff --git a/Makefile.am b/Makefile.am index cb5d63a..0f3f2b6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -89,6 +89,7 @@ libebgenv_a_SOURCES = \ env/env_config_file.c \ env/env_config_partitions.c \ env/env_disk_utils.c \ + env/env_user_config_file.c \ env/uservars.c \ tools/ebgpart.c \ 3rdparty/iniparser/dictionary.c \ diff --git a/env/env_user_config_file.c b/env/env_user_config_file.c new file mode 100644 index 0000000..4b24d9c --- /dev/null +++ b/env/env_user_config_file.c @@ -0,0 +1,180 @@ +/* + * EFI Boot Guard + * + * Copyright (c) Siemens AG, 2022 + * + * Authors: + * Tobias Schmidl <[email protected]> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include "env_user_config_file.h" +#include "version.h" +#include <iniparser/iniparser.h> +#include <sys/param.h> + +#ifndef ERROR +#define ERROR wprintf +#endif + +#ifndef INFO +#define INFO wprintf +#endif + +#ifndef WARNING +#define WARNING wprintf +#endif + +extern EBGENVKEY bgenv_str2enum(char *key); + +int env_user_config_file_read(const char *file_name, BG_ENVDATA *data, + bool verbose) +{ + bool bgenv_verbosity = verbose; + VERBOSE(stderr, "entered %s.\n", __PRETTY_FUNCTION__); + int return_value = 0; + + dictionary *ini_file = iniparser_load(file_name); + if (ini_file == NULL) { // exit if we cannot parse the ini file + ERROR(L"Cannot parse the INI file.\n"); + return EINVAL; + } + + const int number_of_sections = iniparser_getnsec(ini_file); + VERBOSE(stderr, "found %i sections.\n", number_of_sections); + for (int i = 0; i < number_of_sections; + ++i) { // iterate over all sections + const char *section_name = iniparser_getsecname(ini_file, i); + const int number_of_keys = + iniparser_getsecnkeys(ini_file, section_name); + VERBOSE(stderr, "Section: %s (%i keys)\n", section_name, + number_of_keys); + + /* we're not in the correct section */ + if (strcmp(section_name, BG_ENVDATA_STRING) != 0) continue; + + /* get the section keys */ + const char *keys[number_of_keys + 1]; + if (NULL == + iniparser_getseckeys( + ini_file, section_name, + keys)) { // exit if we cannot get the sections + ERROR(L"Cannot get the section keys.\n"); + return_value = EINVAL; + goto cleanup_get; + } + + int prefix_index = 0; + { // get key prefix + const char *first_string = keys[0]; + for (; prefix_index < strlen(first_string); + ++prefix_index) + if (first_string[prefix_index] == ':') break; + if (prefix_index + 1 < strlen(first_string)) + VERBOSE(stderr, "index: %i\n", prefix_index); + } + + for (int j = 0; j < number_of_keys; + ++j) { // iterate over all keys + const char *key = keys[j] + prefix_index + 1; + const char *value = + iniparser_getstring(ini_file, keys[j], NULL); + if (strcmp(key, BG_ENV_KERNELFILE_STRING) == 0 && + strlen(value) < ENV_STRING_LENGTH) { + str8to16(data->kernelfile, value); + VERBOSE(stderr, + BG_ENV_KERNELFILE_STRING ": %s\n", + value); + } else if (strcmp(key, BG_ENV_KERNELPARAMS_STRING) == + 0 && + strlen(value) < ENV_STRING_LENGTH) { + str8to16(data->kernelparams, value); + VERBOSE(stderr, + BG_ENV_KERNELPARAMS_STRING ": %s\n", + value); + } else if (strcmp(key, BG_ENV_IN_PROGRESS_STRING) == + 0) { + data->in_progress = MIN( + strtoul(value, NULL, 10), UINT8_MAX); + VERBOSE(stdout, + BG_ENV_IN_PROGRESS_STRING ": %hhu\n", + data->in_progress); + } else if (strcmp(key, BG_ENV_USTATE_STRING) == 0) { + data->ustate = MIN(strtoul(value, NULL, 10), + UINT8_MAX); + VERBOSE(stdout, BG_ENV_USTATE_STRING ": %hhu\n", + data->ustate); + } else if (strcmp(key, + BG_ENV_WATCHDOG_TIMEOUT_SEC_STRING) == + 0) { + data->watchdog_timeout_sec = MIN( + strtoul(value, NULL, 10), UINT16_MAX); + VERBOSE(stdout, + BG_ENV_WATCHDOG_TIMEOUT_SEC_STRING + ": %hu\n", + data->watchdog_timeout_sec); + } else if (strcmp(key, BG_ENV_REVISION_STRING) == 0) { + data->revision = strtoul(value, NULL, 0); + VERBOSE(stdout, + BG_ENV_REVISION_STRING ": 0x%08lx\n", + data->revision); + } else + VERBOSE(stderr, "<unknown>: %s\n", value); + } + } + +cleanup_get: + iniparser_freedict(ini_file); + VERBOSE(stderr, "left %s\n.", __PRETTY_FUNCTION__); + return return_value; +} + +int env_user_config_file_write(const char *file_name, const BG_ENVDATA *data, + bool verbose) +{ + return 1; +} + +#ifdef INI_MAIN + +void print_usage_and_exit(const char *program_name) __attribute__((noreturn)); +void print_usage_and_exit(const char *program_name) +{ + fprintf(stderr, "Usage: %s [-v] -i <inputfile>\n", program_name); + fprintf(stderr, "\nWhere:\n\t-v\t\t\tMore verbose output\n\t-i " + "<inputfile>\t\tInput ini\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + fprintf(stderr, "version: %s\n", EFIBOOTGUARD_VERSION); + const char *input_file = NULL; + bool verbose = false; + for (int opt = 0; - 1 != (opt = getopt(argc, argv, "vi:"));) { + switch (opt) { + case 'v': + verbose = true; + break; + case 'i': + input_file = optarg; + break; + default: + print_usage_and_exit(argv[0]); + break; + } + } + if (input_file == NULL) print_usage_and_exit(argv[0]); + + BG_ENVDATA data; + int return_value = + env_user_config_file_read(input_file, &data, verbose); + fprintf(stderr, "env_user_config_file_read: %i\n", return_value); + return return_value; +} + +#endif diff --git a/envdata.ini.example b/envdata.ini.example new file mode 100644 index 0000000..73e3d3c --- /dev/null +++ b/envdata.ini.example @@ -0,0 +1,10 @@ + +[bg_envdata] +kernelfile = +kernelparams = +in_progress = 0 +ustate = 0 +watchdog_timeout_sec = 0 +revision = 0x00000000 + + diff --git a/include/env_user_config_file.h b/include/env_user_config_file.h new file mode 100644 index 0000000..a74714e --- /dev/null +++ b/include/env_user_config_file.h @@ -0,0 +1,23 @@ +/* + * EFI Boot Guard + * + * Copyright (c) Siemens AG, 2017 + * + * Authors: + * Andreas Reichel <[email protected]> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#pragma once + +#include <stdio.h> +#include "env_api.h" + +int env_user_config_file_read(const char *file_name, BG_ENVDATA *data, + bool verbose); +int env_user_config_file_write(const char *file_name, const BG_ENVDATA *data, + bool verbose); diff --git a/include/envdata.h b/include/envdata.h index fddfa7f..cbc3fac 100644 --- a/include/envdata.h +++ b/include/envdata.h @@ -17,6 +17,8 @@ #include <stdint.h> #define FAT_ENV_FILENAME "BGENV.DAT" +#define FAT_ENV_INI_FILENAME "BGENV.INI" +#define BG_ENVDATA_STRING "bg_envdata" #define ENV_STRING_LENGTH 255 #define USTATE_OK 0 @@ -44,4 +46,12 @@ struct _BG_ENVDATA { }; #pragma pack(pop) +#define BG_ENV_KERNELFILE_STRING "kernelfile" +#define BG_ENV_KERNELPARAMS_STRING "kernelparams" +#define BG_ENV_IN_PROGRESS_STRING "in_progress" +#define BG_ENV_USTATE_STRING "ustate" +#define BG_ENV_WATCHDOG_TIMEOUT_SEC_STRING "watchdog_timeout_sec" +#define BG_ENV_REVISION_STRING "revision" +#define BG_ENV_CRC32_STRING "crc32" + typedef struct _BG_ENVDATA BG_ENVDATA; diff --git a/tools/bg_printenv.c b/tools/bg_printenv.c index 69d428b..248c8ae 100644 --- a/tools/bg_printenv.c +++ b/tools/bg_printenv.c @@ -17,6 +17,7 @@ #include "bg_envtools.h" #include "bg_printenv.h" +#include "env_user_config_file.h" static char tool_doc[] = "bg_printenv - Environment tool for the EFI Boot Guard"; @@ -91,42 +92,42 @@ static void dump_uservars(uint8_t *udata, bool raw) fprintf(stdout, raw ? "=%s\n" : " = %s\n", value); } else if (type >= USERVAR_TYPE_UINT8 && type <= USERVAR_TYPE_UINT64) { - switch(type) { + switch (type) { case USERVAR_TYPE_UINT8: - val_unum = *((uint8_t *) value); + val_unum = *((uint8_t *)value); break; case USERVAR_TYPE_UINT16: - val_unum = *((uint16_t *) value); + val_unum = *((uint16_t *)value); break; case USERVAR_TYPE_UINT32: - val_unum = *((uint32_t *) value); + val_unum = *((uint32_t *)value); break; case USERVAR_TYPE_UINT64: - val_unum = *((uint64_t *) value); + val_unum = *((uint64_t *)value); break; } fprintf(stdout, raw ? "=%llu\n" : " = %llu\n", (long long unsigned int)val_unum); } else if (type >= USERVAR_TYPE_SINT8 && type <= USERVAR_TYPE_SINT64) { - switch(type) { + switch (type) { case USERVAR_TYPE_SINT8: - val_snum = *((int8_t *) value); + val_snum = *((int8_t *)value); break; case USERVAR_TYPE_SINT16: - val_snum = *((int16_t *) value); + val_snum = *((int16_t *)value); break; case USERVAR_TYPE_SINT32: - val_snum = *((int32_t *) value); + val_snum = *((int32_t *)value); break; case USERVAR_TYPE_SINT64: - val_snum = *((int64_t *) value); + val_snum = *((int64_t *)value); break; } fprintf(stdout, raw ? "=%lld\n" : " = %lld\n", (long long signed int)val_snum); } else { - switch(type) { + switch (type) { case USERVAR_TYPE_CHAR: fprintf(stdout, raw ? "=%c\n" : " = %c\n", (char)*value); @@ -220,8 +221,9 @@ void dump_envs(const struct fields *output_fields, bool raw) } BGENV *env = bgenv_open_by_index(i); if (!env) { - fprintf(stderr, "Error, could not read environment " - "for index %d\n", + fprintf(stderr, + "Error, could not read environment " + "for index %d\n", i); return; } @@ -253,13 +255,20 @@ static void dump_env_by_index(uint32_t index, struct fields output_fields, bgenv_close(env); } -static int printenv_from_file(char *envfilepath, const struct fields *output_fields, - bool raw) +static int printenv_from_file(char *envfilepath, + const struct fields *output_fields, bool raw) { int success = 0; BG_ENVDATA data; - success = get_env(envfilepath, &data); + const char *file_name = strrchr(envfilepath, '/'); + file_name = (file_name != NULL) ? file_name + 1 : envfilepath; + + if (strcasecmp(file_name, FAT_ENV_INI_FILENAME) == 0) + success = (env_user_config_file_read(envfilepath, &data, + false) == 0); + else + success = get_env(envfilepath, &data); if (success) { dump_env(&data, output_fields, raw); return 0; -- 2.36.1 -- You received this message because you are subscribed to the Google Groups "EFI Boot Guard" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/efibootguard-dev/20220812114246.1727090-3-tobiasschmidl%40siemens.com.
