Adding --raw to the bg_printenv command-line enables raw output mode
which can be used for shell scripting purposes.

Examples:

* Bring the fields as variables into your shell:

$ source <(bg_printenv --current --output kernel,ustate --raw)
$ echo "kernel: $KERNEL, ustate: $USTATE"
kernel: C:BOOTA:linux.efi, ustate: 0

* Assing the current ustate to a variable:

$ USTATE=$(bg_printenv --current --output ustate --raw)
$ echo "$USTATE"
USTATE=0

Signed-off-by: Michael Adler <[email protected]>
---
 tests/bg_setenv.bats |  20 ++++++
 tools/bg_setenv.c    | 151 +++++++++++++++++++++++++++++--------------
 2 files changed, 123 insertions(+), 48 deletions(-)

diff --git a/tests/bg_setenv.bats b/tests/bg_setenv.bats
index f4739fd..67cee8f 100755
--- a/tests/bg_setenv.bats
+++ b/tests/bg_setenv.bats
@@ -134,3 +134,23 @@ ustate:           0 (OK)" ]]
     run bg_printenv "--filepath=$envfile" --output 
in_progress,revision,kernel,kernelargs,watchdog_timeout,ustate,user
     [[ "$output" = "$expected_output" ]]
 }
+
+@test "bg_printenv ustate raw" {
+    local envfile
+    envfile="$(mktemp -d)/BGENV.DAT"
+
+    create_sample_bgenv "$envfile"
+    run bg_printenv "--filepath=$envfile" --output ustate --raw
+    [[ "$output" = "USTATE=0" ]]
+}
+
+@test "bg_printenv multiple fields raw" {
+    local envfile
+    envfile="$(mktemp -d)/BGENV.DAT"
+
+    create_sample_bgenv "$envfile"
+    run bg_printenv "--filepath=$envfile" --output ustate,kernel,kernelargs 
--raw
+    [[ "$output" = "KERNEL=C:BOOT:kernel.efi
+KERNELARGS=root=/dev/sda
+USTATE=0" ]]
+}
diff --git a/tools/bg_setenv.c b/tools/bg_setenv.c
index 2f6105f..4b9884f 100644
--- a/tools/bg_setenv.c
+++ b/tools/bg_setenv.c
@@ -64,6 +64,7 @@ static struct argp_option options_printenv[] = {
         "Available fields: in_progress, revision, kernel, kernelargs, "
         "watchdog_timeout, ustate, user. "
         "If omitted, all available fields are printed."},
+       {"raw", 'r', 0, 0, "Raw output mode, e.g. for shell scripting"},
        {},
 };
 
@@ -95,6 +96,7 @@ struct arguments_printenv {
        bool current;
        /* a bitset to decide which fields are printed */
        int output_fields;
+       bool raw;
 };
 
 #define MASK_IN_PROGRESS  (1 << 0)
@@ -517,6 +519,9 @@ static error_t parse_printenv_opt(int key, char *arg, 
struct argp_state *state)
        case 'o':
                e = parse_output_fields(arg, &arguments->output_fields);
                break;
+       case 'r':
+               arguments->raw = true;
+               break;
        case ARGP_KEY_ARG:
                /* too many arguments - program terminates with call to
                 * argp_usage with non-zero return code */
@@ -529,7 +534,7 @@ static error_t parse_printenv_opt(int key, char *arg, 
struct argp_state *state)
        return e;
 }
 
-static void dump_uservars(uint8_t *udata)
+static void dump_uservars(uint8_t *udata, bool raw)
 {
        char *key, *value;
        uint64_t type;
@@ -540,10 +545,10 @@ static void dump_uservars(uint8_t *udata)
        while (*udata) {
                bgenv_map_uservar(udata, &key, &type, (uint8_t **)&value,
                                  &rsize, &dsize);
-               fprintf(stdout, "%s ", key);
+               fprintf(stdout, "%s", key);
                type &= USERVAR_STANDARD_TYPE_MASK;
                if (type == USERVAR_TYPE_STRING_ASCII) {
-                       fprintf(stdout, "= %s\n", value);
+                       fprintf(stdout, raw ? "=%s\n" : " = %s\n", value);
                } else if (type >= USERVAR_TYPE_UINT8 &&
                           type <= USERVAR_TYPE_UINT64) {
                        switch(type) {
@@ -560,8 +565,8 @@ static void dump_uservars(uint8_t *udata)
                                val_unum = *((uint64_t *) value);
                                break;
                        }
-                       fprintf(stdout, "= %llu\n",
-                               (long long unsigned int) val_unum);
+                       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) {
@@ -578,19 +583,20 @@ static void dump_uservars(uint8_t *udata)
                                val_snum = *((int64_t *) value);
                                break;
                        }
-                       fprintf(stdout, "= %lld\n",
-                               (long long signed int) val_snum);
+                       fprintf(stdout, raw ? "=%lld\n" : " = %lld\n",
+                               (long long signed int)val_snum);
                } else {
                        switch(type) {
                        case USERVAR_TYPE_CHAR:
-                               fprintf(stdout, "= %c\n", (char) *value);
+                               fprintf(stdout, raw ? "=%c\n" : " = %c\n",
+                                       (char)*value);
                                break;
                        case USERVAR_TYPE_BOOL:
-                               fprintf(stdout, "= %s\n",
-                                      (bool) *value ? "true" : "false");
+                               fprintf(stdout, raw ? "=%s\n" : " = %s\n",
+                                       (bool)*value ? "true" : "false");
                                break;
                        default:
-                               fprintf(stdout, "( Type is not printable )\n");
+                               fprintf(stdout, " ( Type is not printable )\n");
                        }
                }
 
@@ -598,39 +604,71 @@ static void dump_uservars(uint8_t *udata)
        }
 }
 
-static void dump_env(BG_ENVDATA *env, int output_fields)
+static void dump_env(BG_ENVDATA *env, int output_fields, bool raw)
 {
        char buffer[ENV_STRING_LENGTH];
-       fprintf(stdout, "Values:\n");
+       if (!raw) {
+               fprintf(stdout, "Values:\n");
+       }
        if (output_fields & MASK_IN_PROGRESS) {
-               fprintf(stdout, "in_progress:      %s\n",
-                       env->in_progress ? "yes" : "no");
+               if (raw) {
+                       fprintf(stdout, "IN_PROGRESS=%d\n", env->in_progress);
+               } else {
+                       fprintf(stdout, "in_progress:      %s\n",
+                               env->in_progress ? "yes" : "no");
+               }
        }
        if (output_fields & MASK_REVISION) {
-               fprintf(stdout, "revision:         %u\n", env->revision);
+               if (raw) {
+                       fprintf(stdout, "REVISION=%d\n", env->revision);
+               } else {
+                       fprintf(stdout, "revision:         %u\n",
+                               env->revision);
+               }
        }
        if (output_fields & MASK_KERNEL) {
-               fprintf(stdout, "kernel:           %s\n",
-                       str16to8(buffer, env->kernelfile));
+               char *kernelfile = str16to8(buffer, env->kernelfile);
+               if (raw) {
+                       fprintf(stdout, "KERNEL=%s\n", kernelfile);
+               } else {
+                       fprintf(stdout, "kernel:           %s\n", kernelfile);
+               }
        }
        if (output_fields & MASK_KERNELARGS) {
-               fprintf(stdout, "kernelargs:       %s\n",
-                       str16to8(buffer, env->kernelparams));
+               char *kernelargs = str16to8(buffer, env->kernelparams);
+               if (raw) {
+                       fprintf(stdout, "KERNELARGS=%s\n", kernelargs);
+               } else {
+                       fprintf(stdout, "kernelargs:       %s\n", kernelargs);
+               }
        }
        if (output_fields & MASK_WDOG_TIMEOUT) {
-               fprintf(stdout, "watchdog timeout: %u seconds\n",
-                       env->watchdog_timeout_sec);
+               if (raw) {
+                       fprintf(stdout, "WATCHDOG_TIMEOUT=%u\n",
+                               env->watchdog_timeout_sec);
+               } else {
+                       fprintf(stdout, "watchdog timeout: %u seconds\n",
+                               env->watchdog_timeout_sec);
+               }
        }
        if (output_fields & MASK_USTATE) {
-               fprintf(stdout, "ustate:           %u (%s)\n",
-                       (uint8_t)env->ustate, ustate2str(env->ustate));
+               if (raw) {
+                       fprintf(stdout, "USTATE=%u\n", env->ustate);
+               } else {
+                       fprintf(stdout, "ustate:           %u (%s)\n",
+                               (uint8_t)env->ustate, ustate2str(env->ustate));
+               }
        }
        if (output_fields & MASK_USER) {
-               fprintf(stdout, "\n");
-               fprintf(stdout, "user variables:\n");
-               dump_uservars(env->userdata);
+               if (!raw) {
+                       fprintf(stdout, "\n");
+                       fprintf(stdout, "user variables:\n");
+               }
+               dump_uservars(env->userdata, raw);
+       }
+       if (!raw) {
+               fprintf(stdout, "\n\n");
        }
-       fprintf(stdout, "\n\n");
 }
 
 static void update_environment(BGENV *env, bool verbosity)
@@ -652,11 +690,13 @@ static void update_environment(BGENV *env, bool verbosity)
 
 }
 
-static void dump_envs(int output_fields)
+static void dump_envs(int output_fields, bool raw)
 {
        for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) {
-               fprintf(stdout, "\n----------------------------\n");
-               fprintf(stdout, " Config Partition #%d ", i);
+               if (!raw) {
+                       fprintf(stdout, "\n----------------------------\n");
+                       fprintf(stdout, " Config Partition #%d ", i);
+               }
                BGENV *env = bgenv_open_by_index(i);
                if (!env) {
                        fprintf(stderr, "Error, could not read environment "
@@ -664,30 +704,30 @@ static void dump_envs(int output_fields)
                                i);
                        return;
                }
-               dump_env(env->data, output_fields);
+               dump_env(env->data, output_fields, raw);
                bgenv_close(env);
        }
 }
 
-static void dump_latest_env(int output_fields)
+static void dump_latest_env(int output_fields, bool raw)
 {
        BGENV *env = bgenv_open_latest();
        if (!env) {
                fprintf(stderr, "Failed to retrieve latest environment.\n");
                return;
        }
-       dump_env(env->data, output_fields);
+       dump_env(env->data, output_fields, raw);
        bgenv_close(env);
 }
 
-static void dump_env_by_index(uint32_t index, int output_fields)
+static void dump_env_by_index(uint32_t index, int output_fields, bool raw)
 {
        BGENV *env = bgenv_open_by_index(index);
        if (!env) {
                fprintf(stderr, "Failed to retrieve latest environment.\n");
                return;
        }
-       dump_env(env->data, output_fields);
+       dump_env(env->data, output_fields, raw);
        bgenv_close(env);
 }
 
@@ -716,14 +756,14 @@ static bool get_env(char *configfilepath, BG_ENVDATA 
*data)
        return result;
 }
 
-static int printenv_from_file(char *envfilepath, int output_fields)
+static int printenv_from_file(char *envfilepath, int output_fields, bool raw)
 {
        int success = 0;
        BG_ENVDATA data;
 
        success = get_env(envfilepath, &data);
        if (success) {
-               dump_env(&data, output_fields);
+               dump_env(&data, output_fields, raw);
                return 0;
        } else {
                fprintf(stderr, "Error reading environment file.\n");
@@ -748,7 +788,7 @@ static int dumpenv_to_file(char *envfilepath, bool 
verbosity, bool preserve_env)
 
        update_environment(&env, verbosity);
        if (verbosity) {
-               dump_env(env.data, MASK_ALL);
+               dump_env(env.data, MASK_ALL, false);
        }
        FILE *of = fopen(envfilepath, "wb");
        if (of) {
@@ -804,10 +844,18 @@ static error_t bg_printenv(int argc, char **argv)
                fprintf(stderr, "Error, only one of -c/-f/-p can be set.\n");
                return 1;
        }
+       if (arguments.raw && counter != 1) {
+               /* raw mode makes only sense if applied to a single
+                * partition */
+               fprintf(stderr, "Error, raw is set but "
+                               "current/filepath/which_part is not set. "
+                               "Must use -r and -c/-f/-p simultaneously.\n");
+               return 1;
+       }
 
        if (common->envfilepath) {
                e = printenv_from_file(common->envfilepath,
-                                      arguments.output_fields);
+                                      arguments.output_fields, arguments.raw);
                free(common->envfilepath);
                return e;
        }
@@ -819,14 +867,19 @@ static error_t bg_printenv(int argc, char **argv)
        }
 
        if (arguments.current) {
-               fprintf(stdout, "Using latest config partition\n");
-               dump_latest_env(arguments.output_fields);
+               if (!arguments.raw) {
+                       fprintf(stdout, "Using latest config partition\n");
+               }
+               dump_latest_env(arguments.output_fields, arguments.raw);
        } else if (common->part_specified) {
-               fprintf(stdout, "Using config partition #%d\n",
-                       arguments.common.which_part);
-               dump_env_by_index(common->which_part, arguments.output_fields);
+               if (!arguments.raw) {
+                       fprintf(stdout, "Using config partition #%d\n",
+                               arguments.common.which_part);
+               }
+               dump_env_by_index(common->which_part, arguments.output_fields,
+                                 arguments.raw);
        } else {
-               dump_envs(arguments.output_fields);
+               dump_envs(arguments.output_fields, arguments.raw);
        }
 
        bgenv_finalize();
@@ -887,7 +940,7 @@ static error_t bg_setenv(int argc, char **argv)
        }
 
        if (arguments.common.verbosity) {
-               dump_envs(MASK_ALL);
+               dump_envs(MASK_ALL, false);
        }
 
        BGENV *env_new = NULL;
@@ -931,6 +984,8 @@ static error_t bg_setenv(int argc, char **argv)
                bgenv_close(env_current);
        } else {
                if (arguments.common.part_specified) {
+                       fprintf(stdout, "Using config partition #%d\n",
+                               arguments.common.which_part);
                        env_new = bgenv_open_by_index(
                                arguments.common.which_part);
                } else {
@@ -949,7 +1004,7 @@ static error_t bg_setenv(int argc, char **argv)
        if (arguments.common.verbosity) {
                fprintf(stdout, "New environment data:\n");
                fprintf(stdout, "---------------------\n");
-               dump_env(env_new->data, MASK_ALL);
+               dump_env(env_new->data, MASK_ALL, false);
        }
        if (!bgenv_write(env_new)) {
                fprintf(stderr, "Error storing environment.\n");
-- 
2.33.0

-- 
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/20211103145707.3012399-10-michael.adler%40siemens.com.

Reply via email to