binman: Rename ExpandToLimit to extend_to_limit
[platform/kernel/u-boot.git] / env / flags.c
index 3c50620..e3e833c 100644 (file)
@@ -1,10 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2012
  * Joe Hershberger, National Instruments, joe.hershberger@ni.com
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
+#include <env.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
 
 #include "fw_env.h"
 #include <env_attr.h>
 #include <env_flags.h>
-#define getenv fw_getenv
+#define env_get fw_getenv
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 #else
 #include <common.h>
-#include <environment.h>
+#include <env_internal.h>
 #endif
 
 #ifdef CONFIG_CMD_NET
 #define ENV_FLAGS_NET_VARTYPE_REPS ""
 #endif
 
+#ifdef CONFIG_ENV_WRITEABLE_LIST
+#define ENV_FLAGS_WRITEABLE_VARACCESS_REPS "w"
+#else
+#define ENV_FLAGS_WRITEABLE_VARACCESS_REPS ""
+#endif
+
 static const char env_flags_vartype_rep[] = "sdxb" ENV_FLAGS_NET_VARTYPE_REPS;
-static const char env_flags_varaccess_rep[] = "aroc";
+static const char env_flags_varaccess_rep[] =
+       "aroc" ENV_FLAGS_WRITEABLE_VARACCESS_REPS;
 static const int env_flags_varaccess_mask[] = {
        0,
        ENV_FLAGS_VARACCESS_PREVENT_DELETE |
@@ -38,7 +45,11 @@ static const int env_flags_varaccess_mask[] = {
        ENV_FLAGS_VARACCESS_PREVENT_DELETE |
                ENV_FLAGS_VARACCESS_PREVENT_OVERWR,
        ENV_FLAGS_VARACCESS_PREVENT_DELETE |
-               ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR};
+               ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR,
+#ifdef CONFIG_ENV_WRITEABLE_LIST
+       ENV_FLAGS_VARACCESS_WRITEABLE,
+#endif
+       };
 
 #ifdef CONFIG_CMD_ENV_FLAGS
 static const char * const env_flags_vartype_names[] = {
@@ -56,6 +67,9 @@ static const char * const env_flags_varaccess_names[] = {
        "read-only",
        "write-once",
        "change-default",
+#ifdef CONFIG_ENV_WRITEABLE_LIST
+       "writeable",
+#endif
 };
 
 /*
@@ -130,21 +144,25 @@ enum env_flags_vartype env_flags_parse_vartype(const char *flags)
  */
 enum env_flags_varaccess env_flags_parse_varaccess(const char *flags)
 {
+       enum env_flags_varaccess va_default = env_flags_varaccess_any;
+       enum env_flags_varaccess va;
        char *access;
 
        if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC)
-               return env_flags_varaccess_any;
+               return va_default;
 
        access = strchr(env_flags_varaccess_rep,
                flags[ENV_FLAGS_VARACCESS_LOC]);
 
-       if (access != NULL)
-               return (enum env_flags_varaccess)
+       if (access != NULL) {
+               va = (enum env_flags_varaccess)
                        (access - &env_flags_varaccess_rep[0]);
+               return va;
+       }
 
        printf("## Warning: Unknown environment variable access method '%c'\n",
                flags[ENV_FLAGS_VARACCESS_LOC]);
-       return env_flags_varaccess_any;
+       return va_default;
 }
 
 /*
@@ -152,17 +170,21 @@ enum env_flags_varaccess env_flags_parse_varaccess(const char *flags)
  */
 enum env_flags_varaccess env_flags_parse_varaccess_from_binflags(int binflags)
 {
+       enum env_flags_varaccess va_default = env_flags_varaccess_any;
+       enum env_flags_varaccess va;
        int i;
 
        for (i = 0; i < ARRAY_SIZE(env_flags_varaccess_mask); i++)
                if (env_flags_varaccess_mask[i] ==
-                   (binflags & ENV_FLAGS_VARACCESS_BIN_MASK))
-                       return (enum env_flags_varaccess)i;
+                   (binflags & ENV_FLAGS_VARACCESS_BIN_MASK)) {
+                       va = (enum env_flags_varaccess)i;
+                       return va;
+       }
 
        printf("Warning: Non-standard access flags. (0x%x)\n",
                binflags & ENV_FLAGS_VARACCESS_BIN_MASK);
 
-       return env_flags_varaccess_any;
+       return va_default;
 }
 
 static inline int is_hex_prefix(const char *value)
@@ -308,7 +330,7 @@ static inline int env_flags_lookup(const char *flags_list, const char *name,
  */
 enum env_flags_vartype env_flags_get_type(const char *name)
 {
-       const char *flags_list = getenv(ENV_FLAGS_VAR);
+       const char *flags_list = env_get(ENV_FLAGS_VAR);
        char flags[ENV_FLAGS_ATTR_MAX_LEN + 1];
 
        if (env_flags_lookup(flags_list, name, flags))
@@ -325,14 +347,15 @@ enum env_flags_vartype env_flags_get_type(const char *name)
  */
 enum env_flags_varaccess env_flags_get_varaccess(const char *name)
 {
-       const char *flags_list = getenv(ENV_FLAGS_VAR);
+       const char *flags_list = env_get(ENV_FLAGS_VAR);
+       enum env_flags_varaccess va_default = env_flags_varaccess_any;
        char flags[ENV_FLAGS_ATTR_MAX_LEN + 1];
 
        if (env_flags_lookup(flags_list, name, flags))
-               return env_flags_varaccess_any;
+               return va_default;
 
        if (strlen(flags) <= ENV_FLAGS_VARACCESS_LOC)
-               return env_flags_varaccess_any;
+               return va_default;
 
        return env_flags_parse_varaccess(flags);
 }
@@ -419,14 +442,18 @@ static const char *flags_list;
  * This is called specifically when the variable did not exist in the hash
  * previously, so the blanket update did not find this variable.
  */
-void env_flags_init(ENTRY *var_entry)
+void env_flags_init(struct env_entry *var_entry)
 {
        const char *var_name = var_entry->key;
        char flags[ENV_FLAGS_ATTR_MAX_LEN + 1] = "";
        int ret = 1;
 
        if (first_call) {
-               flags_list = getenv(ENV_FLAGS_VAR);
+#ifdef CONFIG_ENV_WRITEABLE_LIST
+               flags_list = ENV_FLAGS_LIST_STATIC;
+#else
+               flags_list = env_get(ENV_FLAGS_VAR);
+#endif
                first_call = 0;
        }
        /* look in the ".flags" and static for a reference to this variable */
@@ -441,7 +468,7 @@ void env_flags_init(ENTRY *var_entry)
  * Called on each existing env var prior to the blanket update since removing
  * a flag in the flag list should remove its flags.
  */
-static int clear_flags(ENTRY *entry)
+static int clear_flags(struct env_entry *entry)
 {
        entry->flags = 0;
 
@@ -453,12 +480,11 @@ static int clear_flags(ENTRY *entry)
  */
 static int set_flags(const char *name, const char *value, void *priv)
 {
-       ENTRY e, *ep;
+       struct env_entry e, *ep;
 
        e.key   = name;
        e.data  = NULL;
-       e.callback = NULL;
-       hsearch_r(e, FIND, &ep, &env_htab, 0);
+       hsearch_r(e, ENV_FIND, &ep, &env_htab, 0);
 
        /* does the env variable actually exist? */
        if (ep != NULL) {
@@ -496,8 +522,8 @@ U_BOOT_ENV_CALLBACK(flags, on_flags);
  * overwriting of write-once variables.
  */
 
-int env_flags_validate(const ENTRY *item, const char *newval, enum env_op op,
-       int flag)
+int env_flags_validate(const struct env_entry *item, const char *newval,
+                      enum env_op op, int flag)
 {
        const char *name;
        const char *oldval = NULL;
@@ -524,10 +550,26 @@ int env_flags_validate(const ENTRY *item, const char *newval, enum env_op op,
        }
 
        /* check for access permission */
-#ifndef CONFIG_ENV_ACCESS_IGNORE_FORCE
-       if (flag & H_FORCE)
+#ifdef CONFIG_ENV_WRITEABLE_LIST
+       if (flag & H_DEFAULT)
+               return 0;       /* Default env is always OK */
+
+       /*
+        * External writeable variables can be overwritten by external env,
+        * anything else can not be overwritten by external env.
+        */
+       if ((flag & H_EXTERNAL) &&
+           !(item->flags & ENV_FLAGS_VARACCESS_WRITEABLE))
+               return 1;
+#endif
+
+       if (flag & H_FORCE) {
+#ifdef CONFIG_ENV_ACCESS_IGNORE_FORCE
+               printf("## Error: Can't force access to \"%s\"\n", name);
+#else
                return 0;
 #endif
+       }
        switch (op) {
        case env_op_delete:
                if (item->flags & ENV_FLAGS_VARACCESS_PREVENT_DELETE) {
@@ -541,7 +583,7 @@ int env_flags_validate(const ENTRY *item, const char *newval, enum env_op op,
                        return 1;
                } else if (item->flags &
                    ENV_FLAGS_VARACCESS_PREVENT_NONDEF_OVERWR) {
-                       const char *defval = getenv_default(name);
+                       const char *defval = env_get_default(name);
 
                        if (defval == NULL)
                                defval = "";