From: Andreas Reichel <[email protected]>

For SWupdate, not only the update state, but also the currently
performed action is important. The padding byte in the environment
is used to store, if the environment copy is currently being used to
update the system and thus renamed to 'in_progress'.

Signed-off-by: Andreas Reichel <[email protected]>
---
 env/env_api.c                 | 20 +++++++++++++++-----
 env/env_api_fat.c             | 25 +++++++++++++++++++++++++
 include/ebgenv.h              |  1 -
 include/env_api.h             |  1 +
 include/envdata.h             |  2 +-
 tools/tests/test_ebgenv_api.c | 34 ++++++++++++++--------------------
 6 files changed, 56 insertions(+), 27 deletions(-)

diff --git a/env/env_api.c b/env/env_api.c
index abfa49a..2961b77 100644
--- a/env/env_api.c
+++ b/env/env_api.c
@@ -65,9 +65,19 @@ int ebg_env_create_new(ebgenv_t *e)
                return EIO;
        }
 
-       if (!e->ebg_new_env_created) {
-               BGENV *latest_env = bgenv_open_latest();
+       BGENV *latest_env = bgenv_open_latest();
+       if (!latest_env) {
+               return EIO;
+       }
+
+       BG_ENVDATA *latest_data = ((BGENV *)latest_env)->data;
+
+       if (latest_data->in_progress != 1) {
                e->bgenv = (void *)bgenv_create_new();
+               if (!e->bgenv) {
+                       bgenv_close(latest_env);
+                       return errno;
+               }
                BG_ENVDATA *new_data = ((BGENV *)e->bgenv)->data;
                uint32_t new_rev = new_data->revision;
                uint8_t new_ustate = new_data->ustate;
@@ -75,11 +85,11 @@ int ebg_env_create_new(ebgenv_t *e)
                new_data->revision = new_rev;
                new_data->ustate = new_ustate;
                bgenv_close(latest_env);
+       } else {
+               e->bgenv = latest_env;
        }
 
-       e->ebg_new_env_created = e->bgenv != NULL;
-
-       return e->bgenv == NULL ? errno : 0;
+       return 0;
 }
 
 int ebg_env_open_current(ebgenv_t *e)
diff --git a/env/env_api_fat.c b/env/env_api_fat.c
index 1b59313..89eb3f0 100644
--- a/env/env_api_fat.c
+++ b/env/env_api_fat.c
@@ -38,6 +38,9 @@ EBGENVKEY bgenv_str2enum(char *key)
        if (strncmp(key, "ustate", strlen("ustate") + 1) == 0) {
                return EBGENV_USTATE;
        }
+       if (strncmp(key, "in_progress", strlen("in_progress") + 1) == 0) {
+               return EBGENV_IN_PROGRESS;
+       }
        return EBGENV_UNKNOWN;
 }
 
@@ -311,6 +314,16 @@ int bgenv_get(BGENV *env, char *key, uint64_t *type, void 
*data,
                        *type = USERVAR_TYPE_UINT16;
                }
                break;
+       case EBGENV_IN_PROGRESS:
+               sprintf(buffer, "%u", env->data->in_progress);
+               if (!data) {
+                       return strlen(buffer)+1;
+               }
+               strncpy(data, buffer, strlen(buffer)+1);
+               if (type) {
+                       *type = USERVAR_TYPE_UINT8;
+               }
+               break;
        default:
                if (!data) {
                        return 0;
@@ -383,6 +396,18 @@ int bgenv_set(BGENV *env, char *key, uint64_t type, void 
*data,
                }
                env->data->ustate = val;
                break;
+       case EBGENV_IN_PROGRESS:
+               errno = 0;
+               val = strtol(value, &p, 10);
+               if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) ||
+                   (errno != 0 && val == 0)) {
+                       return -errno;
+               }
+               if (p == value) {
+                       return -EINVAL;
+               }
+               env->data->in_progress = val;
+               break;
        default:
                return -EINVAL;
        }
diff --git a/include/ebgenv.h b/include/ebgenv.h
index 17c4410..d33c0d6 100644
--- a/include/ebgenv.h
+++ b/include/ebgenv.h
@@ -35,7 +35,6 @@
 
 typedef struct {
        void *bgenv;
-       bool ebg_new_env_created;
 } ebgenv_t;
 
 /** @brief Tell the library to output information for the user.
diff --git a/include/env_api.h b/include/env_api.h
index d541f66..4d652ff 100644
--- a/include/env_api.h
+++ b/include/env_api.h
@@ -51,6 +51,7 @@ typedef enum {
        EBGENV_WATCHDOG_TIMEOUT_SEC,
        EBGENV_REVISION,
        EBGENV_USTATE,
+       EBGENV_IN_PROGRESS,
        EBGENV_UNKNOWN
 } EBGENVKEY;
 
diff --git a/include/envdata.h b/include/envdata.h
index 011053a..42dcd34 100644
--- a/include/envdata.h
+++ b/include/envdata.h
@@ -34,7 +34,7 @@
 struct _BG_ENVDATA {
        uint16_t kernelfile[ENV_STRING_LENGTH];
        uint16_t kernelparams[ENV_STRING_LENGTH];
-       uint8_t padding;
+       uint8_t in_progress;
        uint8_t ustate;
        uint16_t watchdog_timeout_sec;
        uint32_t revision;
diff --git a/tools/tests/test_ebgenv_api.c b/tools/tests/test_ebgenv_api.c
index f6bebb7..4820bac 100644
--- a/tools/tests/test_ebgenv_api.c
+++ b/tools/tests/test_ebgenv_api.c
@@ -92,32 +92,19 @@ START_TEST(ebgenv_api_ebg_env_create_new)
        char *kernelparams = "param456";
 
        memset(&e, 0, sizeof(e));
+       memset(envdata, 0, sizeof(envdata));
+
+       for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) {
+               envdata[i].revision = i + 1;
+       }
 
        /* Test if ebg_env_create_new returns EIO if bgenv_init
         * returns false
         */
        bgenv_init_fake.return_val = false;
-       ret = ebg_env_create_new(&e);
-       ck_assert_int_eq(ret, EIO);
-
-       /* Test if errno is returned by ebg_env_created, if the bgenv pointer
-        * is NULL but ebg_new_env_created is true, which is contradictory.
-        * Also, ebg_new_env_created must be reset to false.
-        */
-       bgenv_init_fake.return_val = true;
        bgenv_close_fake.return_val = true;
-       for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++)
-       {
-               envdata[i].revision = i;
-       }
-       e.ebg_new_env_created = true;
-       e.bgenv = NULL;
-       errno = 3044;
-
        ret = ebg_env_create_new(&e);
-
-       ck_assert_int_eq(ret, 3044);
-       ck_assert(e.ebg_new_env_created == false);
+       ck_assert_int_eq(ret, EIO);
 
        /* Check if values of the latest environment are copied if a new
         * environment is created. The new environment must overwrite the
@@ -132,13 +119,20 @@ START_TEST(ebgenv_api_ebg_env_create_new)
               strlen(kernelparams) * 2 + 2);
        errno = 0;
 
+       bgenv_init_fake.return_val = true;
+       bgenv_close_fake.return_val = true;
        ret = ebg_env_create_new(&e);
 
        ck_assert_int_eq(errno, 0);
        ck_assert_int_eq(ret, 0);
+
        ck_assert(((BGENV *)e.bgenv)->data == &envdata[0]);
+
+
+       ck_assert_int_eq(((BGENV *)e.bgenv)->data->in_progress, 0);
        ck_assert_int_eq(
-               ((BGENV *)e.bgenv)->data->revision, ENV_NUM_CONFIG_PARTS);
+               ((BGENV *)e.bgenv)->data->revision, ENV_NUM_CONFIG_PARTS+1);
+
        ck_assert_int_eq(((BGENV *)e.bgenv)->data->ustate, USTATE_INSTALLED);
        ck_assert_int_eq(((BGENV *)e.bgenv)->data->watchdog_timeout_sec, 44);
        (void)str16to8(buffer, ((BGENV *)e.bgenv)->data->kernelfile);
-- 
2.15.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 post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/efibootguard-dev/20171127121430.31448-2-andreas.reichel.ext%40siemens.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to