* Change API to use one state function
Provide one function to set and one to get the global update state
instead of six different.
* env: Remove BGENVTYPE from code
Since different storage backends come with different .c files, there
is no need for switch cases.
* move some functions to simplify API dependencies
env/env_api_fat.c | 297 ++++++++++++++++++++++++++++---------
include/env_api.h | 30 ++--
swupdate-adapter/ebgenv.c | 367 ++++++----------------------------------------
swupdate-adapter/ebgenv.h | 43 ++----
tools/bg_setenv.c | 14 +-
tools/tests/Makefile | 2 +-
tools/tests/test_api.c | 79 +++++-----
7 files changed, 354 insertions(+), 478 deletions(-)
diff --git a/env/env_api_fat.c b/env/env_api_fat.c
index de82b8c..ec97b14 100644
--- a/env/env_api_fat.c
+++ b/env/env_api_fat.c
@@ -17,6 +17,27 @@ const char *tmp_mnt_dir = "/tmp/mnt-XXXXXX";
static bool verbosity = false;
+static EBGENVKEY bgenv_str2enum(char *key)
+{
+ if (strncmp(key, "kernelfile", strlen("kernelfile") + 1) == 0) {
+ return EBGENV_KERNELFILE;
+ }
+ if (strncmp(key, "kernelparams", strlen("kernelparams") + 1) == 0) {
+ return EBGENV_KERNELPARAMS;
+ }
+ if (strncmp(key, "watchdog_timeout_sec",
+ strlen("watchdog_timeout_sec") + 1) == 0) {
+ return EBGENV_WATCHDOG_TIMEOUT_SEC;
+ }
+ if (strncmp(key, "revision", strlen("revision") + 1) == 0) {
+ return EBGENV_REVISION;
+ }
+ if (strncmp(key, "ustate", strlen("ustate") + 1) == 0) {
+ return EBGENV_USTATE;
+ }
+ return EBGENV_UNKNOWN;
+}
+
void be_verbose(bool v)
{
verbosity = v;
@@ -347,89 +368,72 @@ bool write_env(CONFIG_PART *part, BG_ENVDATA *env)
return result;
}
-CONFIG_PART config_parts[ENV_NUM_CONFIG_PARTS];
-BG_ENVDATA oldenvs[ENV_NUM_CONFIG_PARTS];
+static CONFIG_PART config_parts[ENV_NUM_CONFIG_PARTS];
+static BG_ENVDATA oldenvs[ENV_NUM_CONFIG_PARTS];
-bool bgenv_init(BGENVTYPE type)
+bool bgenv_init()
{
- switch (type) {
- case BGENVTYPE_FAT:
- memset((void *)&config_parts, 0,
- sizeof(CONFIG_PART) * ENV_NUM_CONFIG_PARTS);
- /* enumerate all config partitions */
- if (!probe_config_partitions(config_parts)) {
- VERBOSE(stderr, "Error finding config partitions.\n");
- return false;
- }
- for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) {
- read_env(&config_parts[i], &oldenvs[i]);
- uint32_t sum = crc32(0, (Bytef *)&oldenvs[i],
- sizeof(BG_ENVDATA) - sizeof(oldenvs[i].crc32));
- if (oldenvs[i].crc32 != sum) {
- VERBOSE(stderr, "Invalid CRC32!\n");
- continue;
- }
+ memset((void *)&config_parts, 0,
+ sizeof(CONFIG_PART) * ENV_NUM_CONFIG_PARTS);
+ /* enumerate all config partitions */
+ if (!probe_config_partitions(config_parts)) {
+ VERBOSE(stderr, "Error finding config partitions.\n");
+ return false;
+ }
+ for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) {
+ read_env(&config_parts[i], &oldenvs[i]);
+ uint32_t sum = crc32(0, (Bytef *)&oldenvs[i],
+ sizeof(BG_ENVDATA) - sizeof(oldenvs[i].crc32));
+ if (oldenvs[i].crc32 != sum) {
+ VERBOSE(stderr, "Invalid CRC32!\n");
+ continue;
}
- return true;
}
- return false;
+ return true;
}
-BGENV *bgenv_get_by_index(BGENVTYPE type, uint32_t index)
+BGENV *bgenv_open_by_index(uint32_t index)
{
BGENV *handle;
- switch (type) {
- case BGENVTYPE_FAT:
- /* get config partition by index and allocate handle */
- if (index >= ENV_NUM_CONFIG_PARTS) {
- return NULL;
- }
- if (!(handle = calloc(1, sizeof(BGENV)))) {
- return NULL;
- }
- handle->desc = (void *)&config_parts[index];
- handle->data = &oldenvs[index];
- handle->type = type;
- return handle;
+ /* get config partition by index and allocate handle */
+ if (index >= ENV_NUM_CONFIG_PARTS) {
+ return NULL;
}
- return NULL;
+ if (!(handle = calloc(1, sizeof(BGENV)))) {
+ return NULL;
+ }
+ handle->desc = (void *)&config_parts[index];
+ handle->data = &oldenvs[index];
+ return handle;
}
-BGENV *bgenv_get_oldest(BGENVTYPE type)
+BGENV *bgenv_open_oldest()
{
uint32_t minrev = 0xFFFFFFFF;
uint32_t min_idx = 0;
- switch (type) {
- case BGENVTYPE_FAT:
- for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) {
- if (oldenvs[i].revision < minrev) {
- minrev = oldenvs[i].revision;
- min_idx = i;
- }
+ for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) {
+ if (oldenvs[i].revision < minrev) {
+ minrev = oldenvs[i].revision;
+ min_idx = i;
}
- return bgenv_get_by_index(type, min_idx);
}
- return NULL;
+ return bgenv_open_by_index(min_idx);
}
-BGENV *bgenv_get_latest(BGENVTYPE type)
+BGENV *bgenv_open_latest()
{
uint32_t maxrev = 0;
uint32_t max_idx = 0;
- switch (type) {
- case BGENVTYPE_FAT:
- for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) {
- if (oldenvs[i].revision > maxrev) {
- maxrev = oldenvs[i].revision;
- max_idx = i;
- }
+ for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) {
+ if (oldenvs[i].revision > maxrev) {
+ maxrev = oldenvs[i].revision;
+ max_idx = i;
}
- return bgenv_get_by_index(type, max_idx);
}
- return NULL;
+ return bgenv_open_by_index(max_idx);
}
bool bgenv_write(BGENV *env)
@@ -439,23 +443,19 @@ bool bgenv_write(BGENV *env)
if (!env) {
return false;
}
- switch (env->type) {
- case BGENVTYPE_FAT:
- part = (CONFIG_PART *)env->desc;
- if (!part) {
- VERBOSE(
- stderr,
- "Invalid config partition to store environment.\n");
- return false;
- }
- if (!write_env(part, env->data)) {
- VERBOSE(stderr, "Could not write to %s\n",
- part->devpath);
- return false;
- }
- return true;
+ part = (CONFIG_PART *)env->desc;
+ if (!part) {
+ VERBOSE(
+ stderr,
+ "Invalid config partition to store environment.\n");
+ return false;
}
- return false;
+ if (!write_env(part, env->data)) {
+ VERBOSE(stderr, "Could not write to %s\n",
+ part->devpath);
+ return false;
+ }
+ return true;
}
BG_ENVDATA *bgenv_read(BGENV *env)
@@ -474,3 +474,154 @@ bool bgenv_close(BGENV *env)
}
return false;
}
+
+int bgenv_get(BGENV *env, char *key, char **type, void *data, size_t maxlen)
+{
+ EBGENVKEY e;
+
+ if (!key || !data || maxlen == 0) {
+ return EINVAL;
+ }
+ e = bgenv_str2enum(key);
+ if (e == EBGENV_UNKNOWN) {
+ return EINVAL;
+ }
+ if (!env) {
+ return EPERM;
+ }
+ switch (e) {
+ case EBGENV_KERNELFILE:
+ str16to8(data, env->data->kernelfile);
+ if (type) {
+ sprintf(*type, "char*");
+ }
+ break;
+ case EBGENV_KERNELPARAMS:
+ str16to8(data, env->data->kernelparams);
+ if (type) {
+ sprintf(*type, "char*");
+ }
+ break;
+ case EBGENV_WATCHDOG_TIMEOUT_SEC:
+ sprintf(data, "%lu", env->data->watchdog_timeout_sec);
+ if (type) {
+ sprintf(*type, "uint16_t");
+ }
+ break;
+ case EBGENV_REVISION:
+ sprintf(data, "%lu", env->data->revision);
+ if (type) {
+ sprintf(*type, "uint32_t");
+ }
+ break;
+ case EBGENV_USTATE:
+ sprintf(data, "%u", env->data->ustate);
+ if (type) {
+ sprintf(*type, "uint16_t");
+ }
+ break;
+ default:
+ return EINVAL;
+ }
+ return 0;
+}
+
+int bgenv_set(BGENV *env, char *key, char *type, void *data, size_t datalen)
+{
+ EBGENVKEY e;
+ int val;
+ char *p;
+ char *value = (char *)data;
+
+ if (!key || !data || datalen == 0) {
+ return EINVAL;
+ }
+
+ e = bgenv_str2enum(key);
+ if (e == EBGENV_UNKNOWN) {
+ return EINVAL;
+ }
+ if (!env) {
+ return EPERM;
+ }
+ switch (e) {
+ case EBGENV_REVISION:
+ 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->revision = val;
+ break;
+ case EBGENV_KERNELFILE:
+ str8to16(env->data->kernelfile, value);
+ break;
+ case EBGENV_KERNELPARAMS:
+ str8to16(env->data->kernelparams, value);
+ break;
+ case EBGENV_WATCHDOG_TIMEOUT_SEC:
+ 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->watchdog_timeout_sec = val;
+ break;
+ case EBGENV_USTATE:
+ 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->ustate = val;
+ break;
+ default:
+ return EINVAL;
+ }
+ return 0;
+}
+
+BGENV *bgenv_create_new()
+{
+ BGENV *env_latest;
+ BGENV *env_new;
+
+ env_latest = bgenv_open_latest();
+ if (!env_latest)
+ goto create_new_io_error;
+
+ int new_rev = env_latest->data->revision + 1;
+
+ if (!bgenv_close(env_latest))
+ goto create_new_io_error;
+
+ env_new = bgenv_open_oldest();
+ if (!env_new)
+ goto create_new_io_error;
+
+ /* zero fields */
+ memset(env_new->data, 0, sizeof(BG_ENVDATA));
+ /* update revision field and testing mode */
+ env_new->data->revision = new_rev;
+ env_new->data->ustate = 1;
+ /* set default watchdog timeout */
+ env_new->data->watchdog_timeout_sec = 30;
+
+ return env_new;
+
+create_new_io_error:
+ errno = EIO;
+ return NULL;
+}
diff --git a/include/env_api.h b/include/env_api.h
index 3e78ed3..b9bc15d 100644
--- a/include/env_api.h
+++ b/include/env_api.h
@@ -10,8 +10,8 @@
* the COPYING file in the top-level directory.
*/
-#ifndef __BG_UTILS_H__
-#define __BG_UTILS_H__
+#ifndef __ENV_API_H__
+#define __ENV_API_H__
#include <stddef.h>
#include <stdint.h>
@@ -47,7 +47,14 @@
if (verbosity) \
fprintf(o, __VA_ARGS__)
-typedef enum { BGENVTYPE_FAT } BGENVTYPE;
+typedef enum {
+ EBGENV_KERNELFILE,
+ EBGENV_KERNELPARAMS,
+ EBGENV_WATCHDOG_TIMEOUT_SEC,
+ EBGENV_REVISION,
+ EBGENV_USTATE,
+ EBGENV_UNKNOWN
+} EBGENVKEY;
typedef struct {
char *devpath;
@@ -56,7 +63,6 @@ typedef struct {
} CONFIG_PART;
typedef struct {
- BGENVTYPE type;
void *desc;
BG_ENVDATA *data;
} BGENV;
@@ -66,12 +72,18 @@ extern void be_verbose(bool v);
extern char *str16to8(char *buffer, wchar_t *src);
extern wchar_t *str8to16(wchar_t *buffer, char *src);
-extern bool bgenv_init(BGENVTYPE type);
-extern BGENV *bgenv_get_by_index(BGENVTYPE type, uint32_t index);
-extern BGENV *bgenv_get_oldest(BGENVTYPE type);
-extern BGENV *bgenv_get_latest(BGENVTYPE type);
+extern bool bgenv_init(void);
+extern BGENV *bgenv_open_by_index(uint32_t index);
+extern BGENV *bgenv_open_oldest(void);
+extern BGENV *bgenv_open_latest(void);
extern bool bgenv_write(BGENV *env);
extern BG_ENVDATA *bgenv_read(BGENV *env);
extern bool bgenv_close(BGENV *env);
-#endif // __BG_UTILS_H__
+extern BGENV *bgenv_create_new(void);
+extern int bgenv_get(BGENV *env, char *key, char **type, void *data,
+ size_t maxlen);
+extern int bgenv_set(BGENV *env, char *key, char *type, void *data,
+ size_t datalen);
+
+#endif // __ENV_API_H__
diff --git a/swupdate-adapter/ebgenv.c b/swupdate-adapter/ebgenv.c
index 951bdc7..2c3d52c 100644
--- a/swupdate-adapter/ebgenv.c
+++ b/swupdate-adapter/ebgenv.c
@@ -14,81 +14,10 @@
#include "ebgdefs.h"
#include "ebgenv.h"
-typedef enum {
- EBGENV_KERNELFILE,
- EBGENV_KERNELPARAMS,
- EBGENV_WATCHDOG_TIMEOUT_SEC,
- EBGENV_REVISION,
- EBGENV_USTATE,
- EBGENV_UNKNOWN
-} EBGENVKEY;
-
static BGENV *env_current = NULL;
-typedef struct _PCOLLECTOR {
- void *p;
- struct _PCOLLECTOR *next;
-} PCOLLECTOR;
-
-static PCOLLECTOR ebg_gc;
-
static bool ebg_new_env_created = false;
-static bool ebg_gc_addpointer(void *pnew)
-{
- PCOLLECTOR *pc = &ebg_gc;
-
- while (pc->next) {
- pc = pc->next;
- }
- pc->next = calloc(sizeof(PCOLLECTOR), 1);
- if (!pc->next) {
- return false;
- }
- pc = pc->next;
- pc->p = pnew;
- return true;
-}
-
-static void ebg_gc_cleanup()
-{
- PCOLLECTOR *pc = &ebg_gc;
-
- while (pc) {
- if (pc->p) {
- free(pc->p);
- }
- PCOLLECTOR *tmp = pc;
- pc = pc->next;
- if (tmp != &ebg_gc) {
- free(tmp);
- }
- }
- ebg_gc.p = NULL;
- ebg_gc.next = NULL;
-}
-
-static EBGENVKEY ebg_env_str2enum(char *key)
-{
- if (strncmp(key, "kernelfile", strlen("kernelfile") + 1) == 0) {
- return EBGENV_KERNELFILE;
- }
- if (strncmp(key, "kernelparams", strlen("kernelparams") + 1) == 0) {
- return EBGENV_KERNELPARAMS;
- }
- if (strncmp(key, "watchdog_timeout_sec",
- strlen("watchdog_timeout_sec") + 1) == 0) {
- return EBGENV_WATCHDOG_TIMEOUT_SEC;
- }
- if (strncmp(key, "revision", strlen("revision") + 1) == 0) {
- return EBGENV_REVISION;
- }
- if (strncmp(key, "ustate", strlen("ustate") + 1) == 0) {
- return EBGENV_USTATE;
- }
- return EBGENV_UNKNOWN;
-}
-
void ebg_beverbose(bool v)
{
be_verbose(v);
@@ -96,313 +25,113 @@ void ebg_beverbose(bool v)
int ebg_env_create_new(void)
{
- /* initialize garbage collector */
- ebg_gc.p = NULL;
- ebg_gc.next = NULL;
-
- if (!bgenv_init(BGENVTYPE_FAT)) {
+ if (!bgenv_init()) {
return EIO;
}
- env_current = bgenv_get_latest(BGENVTYPE_FAT);
-
- if (ebg_new_env_created)
- return env_current == NULL ? EIO : 0;
-
- if (!env_current) {
- return EIO;
+ if (!ebg_new_env_created) {
+ env_current = bgenv_create_new();
}
- /* first time env is opened, a new one is created for update
- * purpose */
- int new_rev = env_current->data->revision + 1;
- if (!bgenv_close(env_current)) {
- return EIO;
- }
- env_current = bgenv_get_oldest(BGENVTYPE_FAT);
- if (!env_current) {
- return EIO;
- }
- /* zero fields */
- memset(env_current->data, 0, sizeof(BG_ENVDATA));
- /* update revision field and testing mode */
- env_current->data->revision = new_rev;
- env_current->data->ustate = 1;
- /* set default watchdog timeout */
- env_current->data->watchdog_timeout_sec = 30;
- ebg_new_env_created = true;
+ ebg_new_env_created = env_current != NULL;
- return env_current == NULL ? EIO : 0;
+ return env_current == NULL ? errno : 0;
}
int ebg_env_open_current(void)
{
- /* initialize garbage collector */
- ebg_gc.p = NULL;
- ebg_gc.next = NULL;
-
- if (!bgenv_init(BGENVTYPE_FAT)) {
+ if (!bgenv_init()) {
return EIO;
}
- env_current = bgenv_get_latest(BGENVTYPE_FAT);
+ env_current = bgenv_open_latest();
return env_current == NULL ? EIO : 0;
}
-char *ebg_env_get(char *key)
+int ebg_env_get(char *key, char *buffer)
{
- EBGENVKEY e;
- char *buffer;
-
- if (!key) {
- errno = EINVAL;
- return NULL;
- }
- e = ebg_env_str2enum(key);
- if (e == EBGENV_UNKNOWN) {
- errno = EINVAL;
- return NULL;
- }
- if (!env_current) {
- errno = EPERM;
- return NULL;
- }
- switch (e) {
- case EBGENV_KERNELFILE:
- buffer = (char *)malloc(ENV_STRING_LENGTH);
- if (!buffer) {
- errno = ENOMEM;
- return NULL;
- }
- if (!ebg_gc_addpointer(buffer)) {
- errno = ENOMEM;
- return NULL;
- };
- str16to8(buffer, env_current->data->kernelfile);
- return buffer;
- case EBGENV_KERNELPARAMS:
- buffer = (char *)malloc(ENV_STRING_LENGTH);
- if (!buffer) {
- errno = ENOMEM;
- return NULL;
- }
- if (!ebg_gc_addpointer(buffer)) {
- errno = ENOMEM;
- return NULL;
- }
- str16to8(buffer, env_current->data->kernelparams);
- return buffer;
- case EBGENV_WATCHDOG_TIMEOUT_SEC:
- if (asprintf(&buffer, "%lu",
- env_current->data->watchdog_timeout_sec) < 0) {
- errno = ENOMEM;
- return NULL;
- }
- if (!ebg_gc_addpointer(buffer)) {
- errno = ENOMEM;
- return NULL;
- }
- return buffer;
- case EBGENV_REVISION:
- if (asprintf(&buffer, "%lu", env_current->data->revision) < 0) {
- errno = ENOMEM;
- return NULL;
- }
- if (!ebg_gc_addpointer(buffer)) {
- errno = ENOMEM;
- return NULL;
- }
- return buffer;
- case EBGENV_USTATE:
- if (asprintf(&buffer, "%u", env_current->data->ustate) < 0) {
- errno = ENOMEM;
- return NULL;
- }
- if (!ebg_gc_addpointer(buffer)) {
- errno = ENOMEM;
- return NULL;
- }
- return buffer;
- default:
- errno = EINVAL;
- return NULL;
- }
- errno = EINVAL;
- return NULL;
+ return bgenv_get(env_current, key, NULL, buffer, ENV_STRING_LENGTH);
}
int ebg_env_set(char *key, char *value)
{
- EBGENVKEY e;
- int val;
- char *p;
-
- if (!key || !value) {
- return EINVAL;
- }
- e = ebg_env_str2enum(key);
- if (e == EBGENV_UNKNOWN) {
- return EINVAL;
- }
- if (!env_current) {
- return EPERM;
- }
- switch (e) {
- case EBGENV_REVISION:
- 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_current->data->revision = val;
- break;
- case EBGENV_KERNELFILE:
- str8to16(env_current->data->kernelfile, value);
- break;
- case EBGENV_KERNELPARAMS:
- str8to16(env_current->data->kernelparams, value);
- break;
- case EBGENV_WATCHDOG_TIMEOUT_SEC:
- 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_current->data->watchdog_timeout_sec = val;
- break;
- case EBGENV_USTATE:
- 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_current->data->ustate = val;
- break;
- default:
- return EINVAL;
- }
- return 0;
+ return bgenv_set(env_current, key, "String", value, strlen(value));
}
-bool ebg_env_isupdatesuccessful(void)
+uint16_t ebg_env_getglobalstate()
{
+ BGENV *env;
+ int res = 4;
+
/* find all environments with revision 0 */
for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) {
- BGENV *env = bgenv_get_by_index(BGENVTYPE_FAT, i);
+ BGENV *env = bgenv_open_by_index(i);
if (!env) {
continue;
}
/* update was unsuccessful if there is a revision 0 config,
- * with
- * testing and boot_once set */
+ * with ustate == 3 */
if (env->data->revision == REVISION_FAILED &&
env->data->ustate == 3) {
(void)bgenv_close(env);
- return false;
+ res = 3;
}
(void)bgenv_close(env);
- }
- return true;
-}
-
-int ebg_env_clearerrorstate(void)
-{
- for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) {
- BGENV *env = bgenv_get_by_index(BGENVTYPE_FAT, i);
-
- if (!env) {
- continue;
- }
- if (env->data->revision == REVISION_FAILED &&
- env->data->ustate == 3) {
- env->data->ustate = 0;
- if (!bgenv_write(env)) {
- (void)bgenv_close(env);
- return EIO;
- }
- }
- if (!bgenv_close(env)) {
- return EIO;
+ if (res == 3) {
+ return res;
}
}
- return 0;
-}
-int ebg_env_confirmupdate(void)
-{
- return ebg_env_set("ustate", "0");
-}
-
-bool ebg_env_isokay(void)
-{
- BGENV *env;
- bool res = false;
-
- env = bgenv_get_latest(BGENVTYPE_FAT);
+ env = bgenv_open_latest();
if (!env) {
errno = EIO;
return res;
}
- if (env->data->ustate == 0) {
- res = true;
- }
+
+ res = env->data->ustate;
bgenv_close(env);
+
return res;
}
-bool ebg_env_isinstalled(void)
+int ebg_env_setglobalstate(uint16_t ustate)
{
- BGENV *env;
- bool res = false;
+ char buffer[2];
+ int res;
- env = bgenv_get_latest(BGENVTYPE_FAT);
- if (!env) {
- errno = EIO;
- return res;
- }
- if (env->data->ustate == 1) {
- res = true;
+ if (ustate > 3) {
+ return EINVAL;
}
- bgenv_close(env);
- return res;
-}
-
-bool ebg_env_istesting(void)
-{
- BGENV *env;
- bool res = false;
+ snprintf(buffer, sizeof(buffer), "%d", ustate);
+ res =
+ bgenv_set(env_current, "ustate", "String", buffer, strlen(buffer));
- env = bgenv_get_latest(BGENVTYPE_FAT);
- if (!env) {
- errno = EIO;
+ if (ustate != 0) {
return res;
}
- if (env->data->ustate == 2) {
- res = true;
+
+ for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) {
+ BGENV *env = bgenv_open_by_index(i);
+
+ if (!env) {
+ continue;
+ }
+ env->data->ustate = ustate;
+ if (!bgenv_write(env)) {
+ (void)bgenv_close(env);
+ return EIO;
+ }
+ if (!bgenv_close(env)) {
+ return EIO;
+ }
}
- bgenv_close(env);
- return res;
+ return 0;
}
int ebg_env_close(void)
{
- /* free all allocated memory */
- ebg_gc_cleanup();
-
/* if no environment is open, just return EIO */
if (!env_current) {
return EIO;
diff --git a/swupdate-adapter/ebgenv.h b/swupdate-adapter/ebgenv.h
index 97c23db..db20dda 100644
--- a/swupdate-adapter/ebgenv.h
+++ b/swupdate-adapter/ebgenv.h
@@ -36,12 +36,10 @@ int ebg_env_open_current(void);
/** @brief Retrieve variable content
* @param key an enum constant to specify the variable
- * @return a pointer to the buffer with the variable content on success,
- * NULL on failure. The returned pointer must not be freed and is freed
- * automatically on closing the environment. If NULL is returned, errno is
- * set.
+ * @buffer pointer to buffer containing requested value
+ * @return 0 on success, errno on failure
*/
-char *ebg_env_get(char *key);
+int ebg_env_get(char *key, char* buffer);
/** @brief Store new content into variable
* @param key name of the environment variable to set
@@ -50,36 +48,17 @@ char *ebg_env_get(char *key);
*/
int ebg_env_set(char *key, char *value);
-/** @brief Check if last update was successful
- * @return true if successful, false if not
- */
-bool ebg_env_isupdatesuccessful(void);
-
-/** @brief Reset all stored failure states
- * @return 0 if successful, errno on failure
- */
-int ebg_env_clearerrorstate(void);
-
-/** @brief Check if active env is clean
- * @return true if yes, errno set on failure
- */
-bool ebg_env_isokay(void);
-
-/** @brief Check if active env has state 'installed'
- * @return true if yes, errno set on failure
- */
-bool ebg_env_isinstalled(void);
-
-/** @brief Check if active env is in testing state
- * @return true if yes, errno set on failure
+/** @brief Get global ustate value, accounting for all environments
+ * @return ustate value
*/
-bool ebg_env_istesting(void);
+uint16_t ebg_env_getglobalstate(void);
-/** @brief Confirm environment after update - sets testing and boot_once
- * both to 0
- * @return 0 if successful, errno on failure
+/** @brief Set global ustate value, accounting for all environments
+ * if state is set to zero and updating only current environment
+ * if state is set to a non-zero value.
+ * @return errno on error, 0 if okay.
*/
-int ebg_env_confirmupdate(void);
+int ebg_env_setglobalstate(uint16_t ustate);
/** @brief Closes environment and finalize library. Changes are written
* before closing.
diff --git a/tools/bg_setenv.c b/tools/bg_setenv.c
index ad11138..7efd759 100644
--- a/tools/bg_setenv.c
+++ b/tools/bg_setenv.c
@@ -244,7 +244,7 @@ int main(int argc, char **argv)
}
int result = 0;
if (!arguments.output_to_file) {
- if (!bgenv_init(BGENVTYPE_FAT)) {
+ if (!bgenv_init()) {
fprintf(stderr,
"Error initializing FAT environment.\n");
return 1;
@@ -254,7 +254,7 @@ int main(int argc, char **argv)
printf("\n----------------------------\n");
printf(" Config Partition #%d ", i);
}
- BGENV *env = bgenv_get_by_index(BGENVTYPE_FAT, i);
+ BGENV *env = bgenv_open_by_index(i);
if (env) {
if (verbosity) {
dump_env(env->data);
@@ -272,7 +272,7 @@ int main(int argc, char **argv)
BGENV *env_current;
if (auto_update) {
/* search latest and oldest revision */
- env_current = bgenv_get_latest(BGENVTYPE_FAT);
+ env_current = bgenv_open_latest();
if (!env_current) {
fprintf(stderr, "Failed to retrieve "
"latest "
@@ -282,7 +282,7 @@ int main(int argc, char **argv)
arguments.tmpdata.revision =
env_current->data->revision + 1;
- env_new = bgenv_get_oldest(BGENVTYPE_FAT);
+ env_new = bgenv_open_oldest();
if (!env_new) {
fprintf(stderr, "Failed to retrieve "
"oldest "
@@ -316,12 +316,10 @@ int main(int argc, char **argv)
}
} else {
if (part_specified) {
- env_new = bgenv_get_by_index(
- BGENVTYPE_FAT,
+ env_new = bgenv_open_by_index(
arguments.which_part);
} else {
- env_new =
- bgenv_get_latest(BGENVTYPE_FAT);
+ env_new = bgenv_open_latest();
}
if (!env_new) {
fprintf(stderr, "Failed to retrieve "
diff --git a/tools/tests/Makefile b/tools/tests/Makefile
index 9c0af09..5c4b334 100644
--- a/tools/tests/Makefile
+++ b/tools/tests/Makefile
@@ -67,7 +67,7 @@ MOCKOBJS_test_api = $(ENV_API)
MOCKOBJS_SYMBOLS_$(ENV_API)-test_partitions = probe_config_file
MOCKOBJS_SYMBOLS_$(ENV_API)-test_environment = oldenvs configparts fopen fclose fread fwrite feof mount_partition
-MOCKOBJS_SYMBOLS_$(ENV_API)-test_api = bgenv_init bgenv_write bgenv_close bgenv_get_latest bgenv_get_by_index bgenv_get_oldest
+MOCKOBJS_SYMBOLS_$(ENV_API)-test_api = bgenv_init bgenv_write bgenv_close bgenv_open_latest bgenv_open_by_index bgenv_open_oldest
MOCKOBJS_SYMBOLS_ebgpart-test_partitions = ped_device_probe_all ped_device_get_next ped_disk_next_partition
TEST_TARGETS = test_partitions.target test_environment.target test_api.target
diff --git a/tools/tests/test_api.c b/tools/tests/test_api.c
index 53e573d..dfabdac 100644
--- a/tools/tests/test_api.c
+++ b/tools/tests/test_api.c
@@ -30,11 +30,8 @@ static BG_ENVDATA dataupdate = {0};
static int test_env_revision = 42;
static char *test_env_revision_str = "42";
-bool bgenv_init(BGENVTYPE type)
+bool bgenv_init()
{
- if (type != BGENVTYPE_FAT) {
- return false;
- }
return true;
}
@@ -48,17 +45,20 @@ bool bgenv_close(BGENV *env_current)
return true;
}
-BGENV *bgenv_get_by_index(BGENVTYPE type, uint32_t index)
+BGENV *bgenv_open_by_index(uint32_t index)
{
- return &envupdate;
+ if (index == 1) {
+ return &envupdate;
+ }
+ return &env;
}
-BGENV *bgenv_get_latest(BGENVTYPE type)
+BGENV *bgenv_open_latest()
{
return mock_ptr_type(BGENV *);
}
-BGENV *bgenv_get_oldest(BGENVTYPE type)
+BGENV *bgenv_open_oldest()
{
return mock_ptr_type(BGENV *);
}
@@ -67,21 +67,21 @@ static void test_api_openclose(void **state)
{
int ret;
- will_return(bgenv_get_latest, &env);
+ will_return(bgenv_open_latest, &env);
ret = ebg_env_open_current();
assert_int_equal(ret, 0);
will_return(bgenv_write, true);
ret = ebg_env_close();
assert_int_equal(ret, 0);
- will_return(bgenv_get_latest, &env);
+ will_return(bgenv_open_latest, &env);
ret = ebg_env_open_current();
assert_int_equal(ret, 0);
will_return(bgenv_write, false);
ret = ebg_env_close();
assert_int_equal(ret, EIO);
- will_return(bgenv_get_latest, NULL);
+ will_return(bgenv_open_latest, NULL);
ret = ebg_env_open_current();
assert_int_equal(ret, EIO);
ret = ebg_env_close();
@@ -93,8 +93,9 @@ static void test_api_openclose(void **state)
static void test_api_accesscurrent(void **state)
{
int ret;
+ char buffer[4096];
- will_return(bgenv_get_latest, &env);
+ will_return(bgenv_open_latest, &env);
ret = ebg_env_open_current();
assert_int_equal(ret, 0);
will_return(bgenv_write, true);
@@ -107,7 +108,7 @@ static void test_api_accesscurrent(void **state)
ret = ebg_env_set("kernelfile", "vmlinuz");
assert_int_equal(ret, EPERM);
- will_return(bgenv_get_latest, &env);
+ will_return(bgenv_open_latest, &env);
ret = ebg_env_open_current();
assert_int_equal(ret, 0);
@@ -121,20 +122,23 @@ static void test_api_accesscurrent(void **state)
ret = ebg_env_close();
assert_int_equal(ret, 0);
- char *value;
- value = ebg_env_get("kernelfile");
- assert_null(value);
- assert_int_equal(errno, EPERM);
+ ret = ebg_env_get("kernelfile", buffer);
+ assert_int_equal(ret, EPERM);
- will_return(bgenv_get_latest, &env);
+ will_return(bgenv_open_latest, &env);
ret = ebg_env_open_current();
assert_int_equal(ret, 0);
- assert_string_equal(ebg_env_get("kernelfile"), "vmlinuz");
- assert_string_equal(ebg_env_get("kernelparams"), "root=/dev/sda");
- assert_string_equal(ebg_env_get("watchdog_timeout_sec"), "13");
- assert_string_equal(ebg_env_get("ustate"), "1");
- assert_string_equal(ebg_env_get("revision"), test_env_revision_str);
+ assert_int_equal(ebg_env_get("kernelfile", buffer), 0);
+ assert_string_equal(buffer, "vmlinuz");
+ assert_int_equal(ebg_env_get("kernelparams", buffer), 0);
+ assert_string_equal(buffer, "root=/dev/sda");
+ assert_int_equal(ebg_env_get("watchdog_timeout_sec", buffer), 0);
+ assert_string_equal(buffer, "13");
+ assert_int_equal(ebg_env_get("ustate", buffer), 0);
+ assert_string_equal(buffer, "1");
+ assert_int_equal(ebg_env_get("revision", buffer), 0);
+ assert_string_equal(buffer, test_env_revision_str);
will_return(bgenv_write, true);
ret = ebg_env_close();
@@ -145,8 +149,8 @@ static void test_api_accesscurrent(void **state)
static void test_api_update(void **state)
{
- will_return(bgenv_get_latest, &env);
- will_return(bgenv_get_oldest, &envupdate);
+ will_return(bgenv_open_latest, &env);
+ will_return(bgenv_open_oldest, &envupdate);
assert_int_equal(ebg_env_create_new(), 0);
assert_int_equal(envupdate.data->revision, test_env_revision + 1);
@@ -155,21 +159,24 @@ static void test_api_update(void **state)
assert_int_equal(envupdate.data->ustate, 1);
assert_int_equal(ebg_env_set("ustate", "2"), 0);
- assert_int_equal(ebg_env_confirmupdate(), 0);
+ for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) {
+ will_return(bgenv_write, true);
+ }
+ assert_int_equal(ebg_env_setglobalstate(0), 0);
+ if (ENV_NUM_CONFIG_PARTS == 1) {
+ will_return(bgenv_open_latest, &envupdate);
+ }
assert_int_equal(ebg_env_set("revision", "0"), 0);
assert_int_equal(ebg_env_set("ustate", "3"), 0);
- assert_false(ebg_env_isupdatesuccessful());
+ assert_int_equal(ebg_env_getglobalstate(), 3);
- assert_int_equal(ebg_env_set("revision", "0"), 0);
- assert_int_equal(ebg_env_set("ustate", "0"), 0);
- assert_true(ebg_env_isupdatesuccessful());
-
- assert_int_equal(ebg_env_set("revision", "0"), 0);
- assert_int_equal(ebg_env_set("ustate", "3"), 0);
- will_return(bgenv_write, true);
- assert_int_equal(ebg_env_clearerrorstate(), 0);
- assert_true(ebg_env_isupdatesuccessful());
+ will_return(bgenv_open_latest, &env);
+ for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) {
+ will_return(bgenv_write, true);
+ }
+ assert_int_equal(ebg_env_setglobalstate(0), 0);
+ assert_int_equal(ebg_env_getglobalstate(), 0);
will_return(bgenv_write, true);
assert_int_equal(ebg_env_close(), 0);
--
2.13.3