Hi,

On 11/14/2017 10:47 AM, [ext] Jan Kiszka wrote:
On 2017-11-07 15:12, [ext] Andreas J. Reichel wrote:
From: Andreas Reichel <[email protected]>

Store user variable types as uint64_t instead of a string. This enables
the possibility of definint flags. Flags are used to delete a user
variable (to destinguish between setting it empty or removing it) and to
mark variables with special properties. This will be used in a following
commit to define global user variables.

Bits 0..31 are reserved for standard datatype definitions,
bits 32..48 are reserved for user defined datatypes or flags,
bits 49..63 are reserved for internal flags.

Signed-off-by: Andreas Reichel <[email protected]>
---
  env/env_api.c                          |  9 ++--
  env/env_api_fat.c                      | 16 +++---
  env/uservars.c                         | 49 +++++++++++--------
  include/ebgenv.h                       | 26 ++++++++--
  include/env_api.h                      |  8 ++-
  include/uservars.h                     | 13 ++---
  tools/bg_setenv.c                      | 89 +++++++++++++++++++++++++---------
  tools/tests/test_ebgenv_api.c          | 33 +++++++------
  tools/tests/test_ebgenv_api_internal.c | 34 ++++++-------
  9 files changed, 172 insertions(+), 105 deletions(-)

diff --git a/env/env_api.c b/env/env_api.c
index 76f7b93..bd034af 100644
--- a/env/env_api.c
+++ b/env/env_api.c
@@ -99,7 +99,7 @@ int ebg_env_get(ebgenv_t *e, char *key, char *buffer)
                         ENV_STRING_LENGTH);
  }
-int ebg_env_get_ex(ebgenv_t *e, char *key, char *usertype, uint8_t *buffer,
+int ebg_env_get_ex(ebgenv_t *e, char *key, uint64_t *usertype, uint8_t *buffer,
                   uint32_t maxlen)
  {
        return bgenv_get((BGENV *)e->bgenv, key, usertype, buffer, maxlen);
@@ -111,7 +111,7 @@ int ebg_env_set(ebgenv_t *e, char *key, char *value)
                         strlen(value) + 1);
  }
-int ebg_env_set_ex(ebgenv_t *e, char *key, char *usertype, uint8_t *value,
+int ebg_env_set_ex(ebgenv_t *e, char *key, uint64_t usertype, uint8_t *value,
                   uint32_t datalen)
  {
        return bgenv_set((BGENV *)e->bgenv, key, usertype, value, datalen);
@@ -174,9 +174,8 @@ int ebg_env_setglobalstate(ebgenv_t *e, uint16_t ustate)
                return EINVAL;
        }
        (void)snprintf(buffer, sizeof(buffer), "%d", ustate);
-       res =
-           bgenv_set((BGENV *)e->bgenv, "ustate", "String", buffer,
-                     strlen(buffer) + 1);
+       res = bgenv_set((BGENV *)e->bgenv, "ustate", 0, buffer,
+                       strlen(buffer) + 1);
if (ustate != USTATE_OK) {
                return res;
diff --git a/env/env_api_fat.c b/env/env_api_fat.c
index 8eb1454..7d5e714 100644
--- a/env/env_api_fat.c
+++ b/env/env_api_fat.c
@@ -236,7 +236,8 @@ bool bgenv_close(BGENV *env)
        return false;
  }
-int bgenv_get(BGENV *env, char *key, char *type, void *data, uint32_t maxlen)
+int bgenv_get(BGENV *env, char *key, uint64_t *type, void *data,
+             uint32_t maxlen)
  {
        EBGENVKEY e;
        char buffer[ENV_STRING_LENGTH];
@@ -267,7 +268,7 @@ int bgenv_get(BGENV *env, char *key, char *type, void 
*data, uint32_t maxlen)
                }
                strncpy(data, buffer, strlen(buffer)+1);
                if (type) {
-                       sprintf(type, "char*");
+                       *type = USERVAR_TYPE_STRING_ASCII;
                }
                break;
        case EBGENV_KERNELPARAMS:
@@ -277,7 +278,7 @@ int bgenv_get(BGENV *env, char *key, char *type, void 
*data, uint32_t maxlen)
                }
                strncpy(data, buffer, strlen(buffer)+1);
                if (type) {
-                       sprintf(type, "char*");
+                       *type = USERVAR_TYPE_STRING_ASCII;
                }
                break;
        case EBGENV_WATCHDOG_TIMEOUT_SEC:
@@ -287,7 +288,7 @@ int bgenv_get(BGENV *env, char *key, char *type, void 
*data, uint32_t maxlen)
                }
                strncpy(data, buffer, strlen(buffer)+1);
                if (type) {
-                       sprintf(type, "uint16_t");
+                       *type = USERVAR_TYPE_UINT16;
                }
                break;
        case EBGENV_REVISION:
@@ -297,7 +298,7 @@ int bgenv_get(BGENV *env, char *key, char *type, void 
*data, uint32_t maxlen)
                }
                strncpy(data, buffer, strlen(buffer)+1);
                if (type) {
-                       sprintf(type, "uint32_t");
+                       *type = USERVAR_TYPE_UINT16;
                }
                break;
        case EBGENV_USTATE:
@@ -307,7 +308,7 @@ int bgenv_get(BGENV *env, char *key, char *type, void 
*data, uint32_t maxlen)
                }
                strncpy(data, buffer, strlen(buffer)+1);
                if (type) {
-                       sprintf(type, "uint16_t");
+                       *type = USERVAR_TYPE_UINT16;
                }
                break;
        default:
@@ -319,7 +320,8 @@ int bgenv_get(BGENV *env, char *key, char *type, void 
*data, uint32_t maxlen)
        return 0;
  }
-int bgenv_set(BGENV *env, char *key, char *type, void *data, uint32_t datalen)
+int bgenv_set(BGENV *env, char *key, uint64_t type, void *data,
+             uint32_t datalen)
  {
        EBGENVKEY e;
        int val;
diff --git a/env/uservars.c b/env/uservars.c
index cd3f24b..7e3dc26 100644
--- a/env/uservars.c
+++ b/env/uservars.c
@@ -14,21 +14,28 @@
  #include "env_api.h"
  #include "uservars.h"
-void bgenv_map_uservar(uint8_t *udata, char **key, char **type, uint8_t **val,
+void bgenv_map_uservar(uint8_t *udata, char **key, uint64_t *type, uint8_t 
**val,
                       uint32_t *record_size, uint32_t *data_size)
  {
        /* Each user variable is encoded as follows:
-        * |------------|--------------|-------------|----------------|
-        * | char KEY[] | uint32_t len | char type[] | uint8_t data[] |
-        * |------------|--------------|-------------|----------------|
-        * |   KEY      | < - - - - - - - - PAYLOAD - - - - - - - - > |
+        * |------------|--------------|---------------|----------------|
+        * | char KEY[] | uint32_t len | uint64_t type | uint8_t data[] |
+        * |------------|--------------|---------------|----------------|
+        * |   KEY      | < - - - - - - - - PAYLOAD - - - - - - - - - > |
         *
         * here char[] is a null-terminated string
         * 'len' is the payload size (visualized by the horizontal dashes)
+        *
+        * type is partitioned into the following bit fields:
+        * | 63      ...       49 | 48     ...     32 | 31     ...    0 |
+        * |    internal flags    |   user defined    |  standard types |
+        * |      (reserved)      |  (free for user)  |    (reserved)   |
+        *
+        * internal flags and standard types are declared in ebgenv.h
         */
        char *var_key;
        uint32_t *payload_size;
-       char *var_type;
+       uint64_t *var_type;
        uint8_t *data;
/* Get the key */
@@ -46,24 +53,24 @@ void bgenv_map_uservar(uint8_t *udata, char **key, char 
**type, uint8_t **val,
        }
/* Get position of the type field */
-       var_type = (char *)payload_size + sizeof(uint32_t);
+       var_type = (uint64_t *)((uint8_t *)payload_size + sizeof(uint32_t));
        if (type) {
-               *type = var_type;
+               *type = *var_type;
        }
/* Calculate the data size */
        if (data_size) {
                *data_size = *payload_size - sizeof(uint32_t) -
-                            strlen(var_type) - 1;
+                            sizeof(uint64_t);
        }
        /* Get the pointer to the data field */
-       data = (uint8_t *)(var_type + strlen(var_type) + 1);
+       data = (uint8_t *)(var_type + sizeof(uint64_t));
        if (val) {
                *val = data;
        }
  }
-void bgenv_serialize_uservar(uint8_t *p, char *key, char *type, void *data,
+void bgenv_serialize_uservar(uint8_t *p, char *key, uint64_t type, void *data,
                            uint32_t record_size)
  {
        uint32_t payload_size, data_size;
@@ -78,20 +85,21 @@ void bgenv_serialize_uservar(uint8_t *p, char *key, char 
*type, void *data,
        p += sizeof(uint32_t);
/* store datatype */
-       memcpy(p, type, strlen(type) + 1);
-       p += strlen(type) + 1;
+       *((uint64_t *)p) = type;
+       p += sizeof(uint64_t);
/* store data */
-       data_size = payload_size - strlen(type) - 1 - sizeof(uint32_t);
+       data_size = payload_size - sizeof(uint32_t) - sizeof(uint64_t);
        memcpy(p, data, data_size);
  }
-int bgenv_get_uservar(uint8_t *udata, char *key, char *type, void *data,
+int bgenv_get_uservar(uint8_t *udata, char *key, uint64_t *type, void *data,
                      uint32_t maxlen)
  {
        uint8_t *uservar, *value;
-       char *lkey, *ltype;
+       char *lkey;
        uint32_t dsize;
+       uint64_t ltype;
uservar = bgenv_find_uservar(udata, key); @@ -108,25 +116,24 @@ int bgenv_get_uservar(uint8_t *udata, char *key, char *type, void *data,
        memcpy(data, value, dsize);
if (type) {
-               memcpy(type, ltype, strlen(ltype) + 1);
+               *type = ltype;
        }
return 0;
  }
-int bgenv_set_uservar(uint8_t *udata, char *key, char *type, void *data,
+int bgenv_set_uservar(uint8_t *udata, char *key, uint64_t type, void *data,
                      uint32_t datalen)
  {
        uint32_t total_size;
        uint8_t *p;
- total_size = datalen + strlen(type) + 1 + sizeof(uint32_t) +
+       total_size = datalen + sizeof(uint64_t) + sizeof(uint32_t) +
                     strlen(key) + 1;
p = bgenv_find_uservar(udata, key);
        if (p) {
-               if (strncmp(type, USERVAR_TYPE_DELETED,
-                           strlen(USERVAR_TYPE_DELETED) + 1) == 0) {
+               if (type & USERVAR_TYPE_DELETED) {
                        bgenv_del_uservar(udata, p);
                        return 0;
                }
diff --git a/include/ebgenv.h b/include/ebgenv.h
index bb5b3c5..1257141 100644
--- a/include/ebgenv.h
+++ b/include/ebgenv.h
@@ -17,6 +17,23 @@
#include <errno.h> +#define USERVAR_TYPE_CHAR 1
+#define USERVAR_TYPE_UINT8             2
+#define USERVAR_TYPE_UINT16            3
+#define USERVAR_TYPE_UINT32            4
+#define USERVAR_TYPE_UINT64            5
+#define USERVAR_TYPE_SINT8             6
+#define USERVAR_TYPE_SINT16            7
+#define USERVAR_TYPE_SINT32            8
+#define USERVAR_TYPE_SINT64            9
+#define USERVAR_TYPE_STRING_ASCII      32
+#define USERVAR_TYPE_BOOL             64
+#define USERVAR_TYPE_GLOBAL    1ULL << 62
+#define USERVAR_TYPE_DELETED   1ULL << 63
+#define USERVAR_TYPE_DEFAULT USERVAR_TYPE_GLOBAL
+
+#define USERVAR_STANDARD_TYPE_MASK ((1ULL << 32) - 1)
+
  typedef struct {
        void *bgenv;
        bool ebg_new_env_created;
@@ -66,24 +83,23 @@ int ebg_env_set(ebgenv_t *e, char *key, char *value);
  /** @brief Store new content into variable
   *  @param e A pointer to an ebgenv_t context.
   *  @param key name of the environment variable to set
- *  @param datatype user specific string to identify the datatype of the value
+ *  @param user specific or predefined datatype of the value
   *  @param value arbitrary data to be stored into the variable
   *  @param datalen length of the data to be stored into the variable
   *  @return 0 on success, -errno on failure
   */
-int ebg_env_set_ex(ebgenv_t *e, char *key, char *datatype, uint8_t *value,
+int ebg_env_set_ex(ebgenv_t *e, char *key, uint64_t datatype, uint8_t *value,
                   uint32_t datalen);
/** @brief Get content of user variable
   *  @param e A pointer to an ebgenv_t context.
   *  @param key name of the environment variable to retrieve
- *  @param datatype buffer for user specific string to identify the
- *         datatype of the value
+ *  @param buffer to store the datatype of the value
   *  @param buffer destination for data to be stored into the variable
   *  @param maxlen size of provided buffer
   *  @return 0 on success, errno on failure
   */
-int ebg_env_get_ex(ebgenv_t *e, char *key, char *datatype, uint8_t *buffer,
+int ebg_env_get_ex(ebgenv_t *e, char *key, uint64_t *datatype, uint8_t *buffer,
                   uint32_t maxlen);
/** @brief Get available space for user variables
diff --git a/include/env_api.h b/include/env_api.h
index 5f535c5..8ea2c11 100644
--- a/include/env_api.h
+++ b/include/env_api.h
@@ -29,6 +29,7 @@
  #include "config.h"
  #include <zlib.h>
  #include "envdata.h"
+#include "ebgenv.h"
#ifdef DEBUG
  #define printf_debug(fmt, ...) printf(fmt, __VA_ARGS__)
@@ -44,9 +45,6 @@ extern bool bgenv_verbosity;
        if (bgenv_verbosity)                                                    
\
        fprintf(o, __VA_ARGS__)
-#define USERVAR_TYPE_DEFAULT "String"
-#define USERVAR_TYPE_DELETED "\0xDE\0xAD"
-
  typedef enum {
        EBGENV_KERNELFILE,
        EBGENV_KERNELPARAMS,
@@ -81,9 +79,9 @@ extern BG_ENVDATA *bgenv_read(BGENV *env);
  extern bool bgenv_close(BGENV *env);
extern BGENV *bgenv_create_new(void);
-extern int bgenv_get(BGENV *env, char *key, char *type, void *data,
+extern int bgenv_get(BGENV *env, char *key, uint64_t *type, void *data,
                     uint32_t maxlen);
-extern int bgenv_set(BGENV *env, char *key, char *type, void *data,
+extern int bgenv_set(BGENV *env, char *key, uint64_t type, void *data,
                     uint32_t datalen);
#endif // __ENV_API_H__
diff --git a/include/uservars.h b/include/uservars.h
index d33bcce..b1d1d7c 100644
--- a/include/uservars.h
+++ b/include/uservars.h
@@ -15,14 +15,15 @@
#include <stdint.h> -void bgenv_map_uservar(uint8_t *udata, char **key, char **type, uint8_t **val,
-                      uint32_t *record_size, uint32_t *data_size);
-void bgenv_serialize_uservar(uint8_t *p, char *key, char *type, void *data,
-                           uint32_t record_size);
+void bgenv_map_uservar(uint8_t *udata, char **key, uint64_t *type,
+                      uint8_t **val, uint32_t *record_size,
+                      uint32_t *data_size);
+void bgenv_serialize_uservar(uint8_t *p, char *key, uint64_t type, void *data,
+                            uint32_t record_size);
-int bgenv_get_uservar(uint8_t *udata, char *key, char *type, void *data,
+int bgenv_get_uservar(uint8_t *udata, char *key, uint64_t *type, void *data,
                      uint32_t maxlen);
-int bgenv_set_uservar(uint8_t *udata, char *key, char *type, void *data,
+int bgenv_set_uservar(uint8_t *udata, char *key, uint64_t type, void *data,
                      uint32_t datalen);
uint8_t *bgenv_find_uservar(uint8_t *udata, char *key);
diff --git a/tools/bg_setenv.c b/tools/bg_setenv.c
index 8aa6668..b438841 100644
--- a/tools/bg_setenv.c
+++ b/tools/bg_setenv.c
@@ -57,7 +57,7 @@ typedef enum { ENV_TASK_SET, ENV_TASK_DEL } BGENV_TASK;
  struct stailhead *headp;
  struct env_action {
        char *key;
-       char *type;
+       uint64_t type;
        uint8_t *data;
        BGENV_TASK task;
        STAILQ_ENTRY(env_action) journal;
@@ -70,12 +70,11 @@ static void journal_free_action(struct env_action *action)
        if (!action)
                return;
        free(action->data);
-       free(action->type);
        free(action->key);
        free(action);
  }
-static error_t journal_add_action(BGENV_TASK task, char *key, char *type,
+static error_t journal_add_action(BGENV_TASK task, char *key, uint64_t type,
                                  uint8_t *data, size_t datalen)
  {
        struct env_action *new_action;
@@ -91,12 +90,7 @@ static error_t journal_add_action(BGENV_TASK task, char 
*key, char *type,
                        goto newaction_nomem;
                }
        }
-       if (type) {
-               if (asprintf(&(new_action->type), "%s", type) == -1) {
-                       new_action->type = NULL;
-                       goto newaction_nomem;
-               }
-       }
+       new_action->type = type;
        if (data && datalen) {
                new_action->data = (uint8_t *)malloc(datalen);
                if (!new_action->data) {
@@ -121,8 +115,9 @@ static void journal_process_action(BGENV *env, struct 
env_action *action)
switch (action->task) {
        case ENV_TASK_SET:
-               VERBOSE(stdout, "Task = SET, key = %s, type = %s, val = %s\n",
-                       action->key, action->type, (char *)action->data);
+               VERBOSE(stdout, "Task = SET, key = %s, type = %llu, val = %s\n",
+                       action->key, (long long unsigned int)action->type,
+                       (char *)action->data);
                if (strncmp(action->key, "ustate", strlen("ustate")+1) == 0) {
                        uint16_t ustate;
                        unsigned long t;
@@ -207,7 +202,7 @@ static error_t set_uservars(char *arg)
value = strtok(NULL, "=");
        if (value == NULL) {
-               return journal_add_action(ENV_TASK_DEL, key, NULL, NULL, 0);
+               return journal_add_action(ENV_TASK_DEL, key, 0, NULL, 0);
        }
        return journal_add_action(ENV_TASK_SET, key, USERVAR_TYPE_DEFAULT,
                                  (uint8_t *)value, strlen(value) + 1);
@@ -229,7 +224,7 @@ static error_t parse_opt(int key, char *arg, struct 
argp_state *state)
                                ENV_STRING_LENGTH);
                        return 1;
                }
-               e = journal_add_action(ENV_TASK_SET, "kernelfile", "String",
+               e = journal_add_action(ENV_TASK_SET, "kernelfile", 0,
                                       (uint8_t *)arg, strlen(arg) + 1);
                break;
        case 'a':
@@ -240,7 +235,7 @@ static error_t parse_opt(int key, char *arg, struct 
argp_state *state)
                                ENV_STRING_LENGTH);
                        return 1;
                }
-               e = journal_add_action(ENV_TASK_SET, "kernelparams", "String",
+               e = journal_add_action(ENV_TASK_SET, "kernelparams", 0,
                                       (uint8_t *)arg, strlen(arg) + 1);
                break;
        case 'p':
@@ -287,7 +282,7 @@ static error_t parse_opt(int key, char *arg, struct 
argp_state *state)
                        if (res == -1) {
                                return ENOMEM;
                        }
-                       e = journal_add_action(ENV_TASK_SET, "ustate", "String",
+                       e = journal_add_action(ENV_TASK_SET, "ustate", 0,
                                               (uint8_t *)tmp, strlen(tmp) + 1);
                        VERBOSE(stdout, "Ustate set to %d (%s).\n", i,
                                ustate2str(i));
@@ -296,7 +291,7 @@ static error_t parse_opt(int key, char *arg, struct 
argp_state *state)
        case 'r':
                i = atoi(arg);
                VERBOSE(stdout, "Revision is set to %d.\n", i);
-               e = journal_add_action(ENV_TASK_SET, "revision", "String",
+               e = journal_add_action(ENV_TASK_SET, "revision", 0,
                                       (uint8_t *)arg, strlen(arg) + 1);
                break;
        case 'w':
@@ -305,9 +300,8 @@ static error_t parse_opt(int key, char *arg, struct 
argp_state *state)
                        VERBOSE(stdout,
                                "Setting watchdog timeout to %d seconds.\n", i);
                        e = journal_add_action(ENV_TASK_SET,
-                                              "watchdog_timeout_sec",
-                                              "String", (uint8_t *)arg,
-                                              strlen(arg) + 1);
+                                              "watchdog_timeout_sec", 0,
+                                              (uint8_t *)arg, strlen(arg) + 1);
                } else {
                        fprintf(stderr, "Watchdog timeout must be non-zero.\n");
                        return 1;
@@ -324,7 +318,7 @@ static error_t parse_opt(int key, char *arg, struct 
argp_state *state)
                VERBOSE(stdout,
                        "Confirming environment to work. Removing boot-once "
                        "and testing flag.\n");
-               e = journal_add_action(ENV_TASK_SET, "ustate", "String",
+               e = journal_add_action(ENV_TASK_SET, "ustate", 0,
                                       (uint8_t *)"0", 2);
                break;
        case 'u':
@@ -367,18 +361,65 @@ static error_t parse_opt(int key, char *arg, struct 
argp_state *state)
static void dump_uservars(uint8_t *udata)
  {
-       char *key, *value, *type;
+       char *key, *value;
+       uint64_t type;
        uint32_t rsize, dsize;
+       uint64_t val_unum;
+       int64_t val_snum;
while (*udata) {
                bgenv_map_uservar(udata, &key, &type, (uint8_t **)&value,
                                  &rsize, &dsize);
                printf("%s ", key);
-               if (strcmp(type, USERVAR_TYPE_DEFAULT) == 0) {
+               type &= USERVAR_STANDARD_TYPE_MASK;
+               if (type == USERVAR_TYPE_STRING_ASCII) {
                        printf("= %s\n", value);
-               } else {
-                       printf("( User defined type )\n");
+               } else
+               if (type >= USERVAR_TYPE_UINT8 && type <= USERVAR_TYPE_UINT64) {
+                       switch(type) {
+                       case USERVAR_TYPE_UINT8:
+                               val_unum = *((uint8_t *) value);
+                               break;
+                       case USERVAR_TYPE_UINT16:
+                               val_unum = *((uint16_t *) value);
+                               break;
+                       case USERVAR_TYPE_UINT32:
+                               val_unum = *((uint32_t *) value);
+                               break;
+                       case USERVAR_TYPE_UINT64:
+                               val_unum = *((uint64_t *) value);
+                               break;
+                       }
+                       printf("= %llu\n", (long long unsigned int) val_unum);
+               } else
+               if (type >= USERVAR_TYPE_SINT8 && type <= USERVAR_TYPE_SINT64) {
+                       switch(type) {
+                       case USERVAR_TYPE_SINT8:
+                               val_snum = *((int8_t *) value);
+                               break;
+                       case USERVAR_TYPE_SINT16:
+                               val_snum = *((int16_t *) value);
+                               break;
+                       case USERVAR_TYPE_SINT32:
+                               val_snum = *((int32_t *) value);
+                               break;
+                       case USERVAR_TYPE_SINT64:
+                               val_snum = *((int64_t *) value);
+                               break;
+                       }
+                       printf("= %lld\n", (long long signed int) val_snum);
+               } else
+               switch(type) {
+               case USERVAR_TYPE_CHAR:
+                       printf("= %c\n", (char) *value);
+                       break;
+               case USERVAR_TYPE_BOOL:
+                       printf("= %s\n", (bool) *value ? "true" : "false");
+                       break;
+               default:
+                       printf("( Type is not printable )\n");
                }

Fixing up the coding style here while merging to keep things readable.
Please use the right indention level and also avoid misleading

} else
if (...

in the future.

Should we invest some work to integrate a style checker into travis?

-- Claudius

--
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-54 Fax: (+49)-8142-66989-80 Email: [email protected]

--
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/31aec85b-519e-cead-e7aa-d0ecb8113802%40siemens.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to