From patchwork Wed Jul 17 08:25:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1133179 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="dCrp+E+P"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 45pVjL72dhz9sLt for ; Wed, 17 Jul 2019 18:26:30 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id A4320C21E73; Wed, 17 Jul 2019 08:25:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 22A00C21DA1; Wed, 17 Jul 2019 08:25:38 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 95A13C21DA1; Wed, 17 Jul 2019 08:25:30 +0000 (UTC) Received: from mail-pg1-f193.google.com (mail-pg1-f193.google.com [209.85.215.193]) by lists.denx.de (Postfix) with ESMTPS id 742D1C21E42 for ; Wed, 17 Jul 2019 08:25:26 +0000 (UTC) Received: by mail-pg1-f193.google.com with SMTP id l21so10796340pgm.3 for ; Wed, 17 Jul 2019 01:25:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=6CP35A0uso/eCA9UxiKxXbxYJTAkRyhEerM3VcnLaMU=; b=dCrp+E+PoZXN/R6gm4UnY8ly6l8d8s8yj4d8X8PuxN5trXmeqWaI8MMDlKD1Li2pLA NwoOjlPgBBISMl6GtRIZuSwb610GJz+Pxf4bTNBLwbhLG9E5xXk0v6EhG6LRa+/P5Atg SYEk9RhpdJjg/8//aAjHqQLskFmZ4WTPS91URQS4/vHKZwVbR0pQmMVg5qCASfEjnEeT GzW+syza5x9B5zrmMZLFbSz9SOhVDZq4DKtnt4rdcP0mqYNapA9SQviSFNhcVuF/d+6q vwEPrRsH5yxlNAvETLPk+RFP45ooS6shuByGV16JWY8nY3wsUVfvcGELdu6CQBtttOeP r9dw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6CP35A0uso/eCA9UxiKxXbxYJTAkRyhEerM3VcnLaMU=; b=pY1ozj+aqPXWdmfttHaP07Hm9TM9+WsYriFZtHDtLWXZOoaaunKHhM/IS5zvwqWu1K DISw8nBsc/KUrQm0TrnKLS/uQ7JXX0ngkXRkqIlmGqyfoXXT/0SEgc+AfCoI1m1Tfnmj ks5EL2htVgRq6BQVZ7kdznNlXmt+DDQb7sqnde0UXm0MEYmYnbzs5lSx6zZGNqVi/OGT YUPM7WG2VPLU6fY9a0gcKUj2N45FfriJCnBVdFvPI60QRqTSrIrI+0wV9il35O6hzzuQ 9Ygc2fVgh1UVqCrP5Vy5rhPTrX312Al4dEmazoqh91ynGYywygq5z0RcL+gwV37rk3ue Is8Q== X-Gm-Message-State: APjAAAXaz6PIbkSepOMCBwd6KC8ctD6HeUlqVvT+2axN9aNv0QTy64DE NtvpT2PD2ANssXCQvVMx40WYeA== X-Google-Smtp-Source: APXvYqzgki62hC1akr4yHxXz8xOV4JwEbajlffVzTZA8B9hEF4OJFcOAB9zFpdG7Ka7+VjT90wcTOw== X-Received: by 2002:a63:60c1:: with SMTP id u184mr36011344pgb.275.1563351924655; Wed, 17 Jul 2019 01:25:24 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id a21sm27486111pfi.27.2019.07.17.01.25.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 17 Jul 2019 01:25:24 -0700 (PDT) From: AKASHI Takahiro To: trini@konsulko.com, xypron.glpk@gmx.de, agraf@csgraf.de, wd@denx.de Date: Wed, 17 Jul 2019 17:25:11 +0900 Message-Id: <20190717082525.891-3-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190717082525.891-1-takahiro.akashi@linaro.org> References: <20190717082525.891-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC, PATCH v4 02/16] env: extend interfaces to import/export U-Boot environment per context X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The following interfaces are extended to accept an additional argument, context: env_import() -> env_import_ext() env_export() -> env_export_ext() env_load() -> env_load_ext() env_save() -> env_save_ext() With this patch applied, we will be able to have different U-Boot environments each of which has its own "context," or dedicated backing storage. Currently, there are two contexts defined: ENVCTX_UBOOT: the legacy U-Boot environment variables ENVCTX_UEFI: UEFI variables which will be utilized in successive commits. Along with those changes, "env_t" structure is also modified so that we will be able to load/save environment data of arbitrary size, instead of fixed size of ENV_SIZE. Signed-off-by: AKASHI Takahiro --- env/common.c | 80 ++++++++++++++++++++++----- env/env.c | 92 +++++++++++++++++++++++-------- include/asm-generic/global_data.h | 7 ++- include/env_default.h | 1 + include/environment.h | 85 +++++++++++++++++++++++++--- 5 files changed, 220 insertions(+), 45 deletions(-) diff --git a/env/common.c b/env/common.c index bd340fe9d52d..c2a2d9f22feb 100644 --- a/env/common.c +++ b/env/common.c @@ -107,34 +107,48 @@ int set_default_vars(int nvars, char * const vars[], int flags) * Check if CRC is valid and (if yes) import the environment. * Note that "buf" may or may not be aligned. */ -int env_import(const char *buf, int check) +int env_import_ext(const char *buf, enum env_context ctx, int check) { - env_t *ep = (env_t *)buf; + env_hdr_t *ep = (env_hdr_t *)buf; if (check) { uint32_t crc; memcpy(&crc, &ep->crc, sizeof(crc)); - if (crc32(0, ep->data, ENV_SIZE) != crc) { - set_default_env("bad CRC", 0); + if (crc32(0, ep->data, ep->data_size) != crc) { + if (ctx == ENVCTX_UBOOT) + set_default_env("bad CRC", 0); + return -ENOMSG; /* needed for env_load() */ } } - if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, 0, - 0, NULL)) { + if (himport_ext(&env_htab, ctx, (char *)ep->data, ep->data_size, + /* + * FIXME: + * H_NOCLEAR is necessary here to handle + * multiple contexts simultaneously. + * This, however, breaks backward compatibility. + */ + '\0', H_NOCLEAR, 0, 0, NULL)) { gd->flags |= GD_FLG_ENV_READY; return 0; } pr_err("Cannot import environment: errno = %d\n", errno); - set_default_env("import failed", 0); + if (ctx == ENVCTX_UBOOT) + set_default_env("import failed", 0); return -EIO; } +int env_import(const char *buf, int check) +{ + return env_import_ext(buf, ENVCTX_UBOOT, check); +} + #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT static unsigned char env_flags; @@ -199,30 +213,68 @@ int env_import_redund(const char *buf1, int buf1_read_fail, env_flags = ep->flags; return env_import((char *)ep, 0); } + +int env_import_redund_ext(const char *buf1, int buf1_read_fail, + const char *buf2, int buf2_read_fail, + enum env_context ctx) +{ + /* TODO */ + return 0; +} #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */ /* Export the environment and generate CRC for it. */ -int env_export(env_t *env_out) +int env_export_ext(env_hdr_t **env_out, enum env_context ctx) { - char *res; + unsigned char *data; + size_t size; ssize_t len; + env_hdr_t *envp; - res = (char *)env_out->data; - len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL); + if (*env_out) { + data = (*env_out)->data; + size = (*env_out)->data_size; + } else { + data = NULL; + size = 0; + } + len = hexport_ext(&env_htab, ctx, '\0', 0, (char **)&data, size, + 0, NULL); if (len < 0) { - pr_err("Cannot export environment: errno = %d\n", errno); + pr_err("Cannot export environment: errno = %d\n", + errno); return 1; } - env_out->crc = crc32(0, env_out->data, ENV_SIZE); + if (*env_out) { + envp = *env_out; + } else { + envp = malloc(sizeof(*envp) + len); + if (!envp) { + pr_err("Out of memory\n"); + free(data); + return 1; + } + *env_out = envp; + + envp->data_size = len; + memcpy(envp->data, data, len); + free(data); + } + envp->crc = crc32(0, envp->data, envp->data_size); #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT - env_out->flags = ++env_flags; /* increase the serial */ + envp->flags = ++env_flags; /* increase the serial */ #endif return 0; } +int env_export(env_t *env_out) +{ + return env_export_ext((env_hdr_t **)&env_out, ENVCTX_UBOOT); +} + void env_relocate(void) { #if defined(CONFIG_NEEDS_MANUAL_RELOC) diff --git a/env/env.c b/env/env.c index 4b417b90a291..e4c9f1d779a0 100644 --- a/env/env.c +++ b/env/env.c @@ -85,12 +85,12 @@ static enum env_location env_locations[] = { #endif }; -static bool env_has_inited(enum env_location location) +static bool env_has_inited(enum env_context ctx, enum env_location location) { - return gd->env_has_init & BIT(location); + return gd->env_has_init[ctx] & BIT(location); } -static void env_set_inited(enum env_location location) +static void env_set_inited(enum env_context ctx, enum env_location location) { /* * We're using a 32-bits bitmask stored in gd (env_has_init) @@ -99,7 +99,7 @@ static void env_set_inited(enum env_location location) */ BUILD_BUG_ON(ARRAY_SIZE(env_locations) > BITS_PER_LONG); - gd->env_has_init |= BIT(location); + gd->env_has_init[ctx] |= BIT(location); } /** @@ -120,16 +120,21 @@ static void env_set_inited(enum env_location location) * Returns: * an enum env_location value on success, a negative error code otherwise */ -__weak enum env_location env_get_location(enum env_operation op, int prio) +__weak enum env_location env_get_location_ext(enum env_context ctx, + enum env_operation op, int prio) { if (prio >= ARRAY_SIZE(env_locations)) return ENVL_UNKNOWN; - gd->env_load_prio = prio; + gd->env_load_prio[ctx] = prio; return env_locations[prio]; } +__weak enum env_location env_get_location(enum env_operation op, int prio) +{ + return env_get_location_ext(ENVCTX_UBOOT, op, prio); +} /** * env_driver_lookup() - Finds the most suited environment location @@ -143,11 +148,16 @@ __weak enum env_location env_get_location(enum env_operation op, int prio) * Returns: * NULL on error, a pointer to a struct env_driver otherwise */ -static struct env_driver *env_driver_lookup(enum env_operation op, int prio) +static struct env_driver *env_driver_lookup(enum env_context ctx, + enum env_operation op, int prio) { - enum env_location loc = env_get_location(op, prio); + enum env_location loc; struct env_driver *drv; + if (ctx == ENVCTX_UBOOT) + loc = env_get_location(op, prio); + else + loc = env_get_location_ext(ctx, op, prio); if (loc == ENVL_UNKNOWN) return NULL; @@ -174,19 +184,21 @@ int env_get_char(int index) return env_get_char_spec(index); } -int env_load(void) +int env_load_ext(enum env_context ctx) { struct env_driver *drv; int best_prio = -1; int prio; - for (prio = 0; (drv = env_driver_lookup(ENVOP_LOAD, prio)); prio++) { + for (prio = 0; (drv = env_driver_lookup(ctx, ENVOP_LOAD, prio)); + prio++) { int ret; - if (!drv->load) + if ((ctx == ENVCTX_UBOOT && !drv->load) || + (ctx != ENVCTX_UBOOT && !drv->load_ext)) continue; - if (!env_has_inited(drv->location)) + if (!env_has_inited(ctx, drv->location)) continue; printf("Loading Environment from %s... ", drv->name); @@ -195,7 +207,10 @@ int env_load(void) * drv->load() in some underlying API, and it must be exactly * one message. */ - ret = drv->load(); + if (ctx == ENVCTX_UBOOT) + ret = drv->load(); + else + ret = drv->load_ext(ctx); if (!ret) { printf("OK\n"); return 0; @@ -221,27 +236,39 @@ int env_load(void) debug("Selecting environment with bad CRC\n"); else best_prio = 0; - env_get_location(ENVOP_LOAD, best_prio); + if (ctx == ENVCTX_UBOOT) + env_get_location(ENVOP_LOAD, best_prio); + else + env_get_location_ext(ctx, ENVOP_LOAD, best_prio); return -ENODEV; } -int env_save(void) +int env_load(void) +{ + return env_load_ext(ENVCTX_UBOOT); +} + +int env_save_ext(enum env_context ctx) { struct env_driver *drv; - drv = env_driver_lookup(ENVOP_SAVE, gd->env_load_prio); + drv = env_driver_lookup(ctx, ENVOP_SAVE, gd->env_load_prio[ctx]); if (drv) { int ret; - if (!drv->save) + if ((ctx == ENVCTX_UBOOT && !drv->save) || + (ctx != ENVCTX_UBOOT && !drv->save_ext)) return -ENODEV; - if (!env_has_inited(drv->location)) + if (!env_has_inited(ctx, drv->location)) return -ENODEV; printf("Saving Environment to %s... ", drv->name); - ret = drv->save(); + if (ctx == ENVCTX_UBOOT) + ret = drv->save(); + else + ret = drv->save_ext(ctx); if (ret) printf("Failed (%d)\n", ret); else @@ -254,15 +281,36 @@ int env_save(void) return -ENODEV; } +int env_save(void) +{ + return env_save_ext(ENVCTX_UBOOT); +} + int env_init(void) { struct env_driver *drv; int ret = -ENOENT; - int prio; + int ctx, prio; + + /* other than ENVCTX_UBOOT */ + for (ctx = 1; ctx < ENVCTX_COUNT; ctx++) { + for (prio = 0; (drv = env_driver_lookup(ctx, ENVOP_INIT, prio)); + prio++) { + if (!drv->init_ext || !(ret = drv->init_ext(ctx))) + env_set_inited(ctx, drv->location); + + debug("%s: Environment %s(%d) init done (ret=%d)\n", + __func__, drv->name, ctx, ret); + } + } - for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) { + /* ENVCTX_UBOOT */ + ret = -ENOENT; + for (prio = 0; (drv = env_driver_lookup(ENVCTX_UBOOT, ENVOP_INIT, + prio)); + prio++) { if (!drv->init || !(ret = drv->init())) - env_set_inited(drv->location); + env_set_inited(ENVCTX_UBOOT, drv->location); debug("%s: Environment %s init done (ret=%d)\n", __func__, drv->name, ret); diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 02a3ed683821..cc2debfd2deb 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -20,6 +20,7 @@ */ #ifndef __ASSEMBLY__ +#include #include #include #include @@ -50,8 +51,10 @@ typedef struct global_data { #endif unsigned long env_addr; /* Address of Environment struct */ unsigned long env_valid; /* Environment valid? enum env_valid */ - unsigned long env_has_init; /* Bitmask of boolean of struct env_location offsets */ - int env_load_prio; /* Priority of the loaded environment */ + unsigned long env_has_init[ENVCTX_COUNT_MAX]; + /* Bitmask of boolean of struct env_location offsets */ + int env_load_prio[ENVCTX_COUNT_MAX]; + /* Priority of the loaded environment */ unsigned long ram_base; /* Base address of RAM used by U-Boot */ unsigned long ram_top; /* Top address of RAM used by U-Boot */ diff --git a/include/env_default.h b/include/env_default.h index 86b639d3e283..dcf1523293f5 100644 --- a/include/env_default.h +++ b/include/env_default.h @@ -15,6 +15,7 @@ env_t environment __UBOOT_ENV_SECTION__(environment) = { #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT 1, /* Flags: valid */ #endif + ENV_SIZE, { #elif defined(DEFAULT_ENV_INSTANCE_STATIC) static char default_environment[] = { diff --git a/include/environment.h b/include/environment.h index cd966761416e..9fa085a9b728 100644 --- a/include/environment.h +++ b/include/environment.h @@ -134,21 +134,31 @@ extern unsigned long nand_env_oob_offset; #include "compiler.h" #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT -# define ENV_HEADER_SIZE (sizeof(uint32_t) + 1) - # define ACTIVE_FLAG 1 # define OBSOLETE_FLAG 0 + +#define ENVIRONMENT_HEADER \ + uint32_t crc; /* CRC32 over data bytes */ \ + uint32_t data_size; /* Environment data size */ \ + unsigned char flags; /* active/obsolete flags */ #else -# define ENV_HEADER_SIZE (sizeof(uint32_t)) +#define ENVIRONMENT_HEADER \ + uint32_t crc; /* CRC32 over data bytes */ \ + uint32_t data_size; /* Environment data size */ #endif +typedef struct environment_hdr { + ENVIRONMENT_HEADER + unsigned char data[]; /* Environment data */ +} env_hdr_t; + +# define ENV_HEADER_SIZE (sizeof(env_hdr_t)) + +/* For compatibility */ #define ENV_SIZE (CONFIG_ENV_SIZE - ENV_HEADER_SIZE) typedef struct environment_s { - uint32_t crc; /* CRC32 over data bytes */ -#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT - unsigned char flags; /* active/obsolete flags */ -#endif + ENVIRONMENT_HEADER unsigned char data[ENV_SIZE]; /* Environment data */ } env_t; @@ -202,6 +212,11 @@ enum env_operation { ENVOP_SAVE, /* we want to call the save function */ }; +enum env_context { + ENVCTX_UBOOT, + ENVCTX_COUNT, +}; + struct env_driver { const char *name; enum env_location location; @@ -216,6 +231,17 @@ struct env_driver { */ int (*load)(void); + /** + * load_ext() - Load given environment context from storage + * + * This method is optional. If not provided, no environment will be + * loaded. + * + * @ctx: context to be loaded + * Return: 0 if OK, -ve on error + */ + int (*load_ext)(enum env_context ctx); + /** * save() - Save the environment to storage * @@ -225,6 +251,16 @@ struct env_driver { */ int (*save)(void); + /** + * save_ext() - Save given environment context to storage + * + * This method is required for 'saveenv' to work. + * + * @ctx: context to be saved + * Return: 0 if OK, -ve on error + */ + int (*save_ext)(enum env_context ctx); + /** * init() - Set up the initial pre-relocation environment * @@ -234,6 +270,17 @@ struct env_driver { * other -ve on error */ int (*init)(void); + + /** + * init() - Set up the initial pre-relocation environment + * + * This method is optional. + * + * @ctx: context to be saved + * @return 0 if OK, -ENOENT if no initial environment could be found, + * other -ve on error + */ + int (*init_ext)(enum env_context ctx); }; /* Declare a new environment location driver */ @@ -269,14 +316,19 @@ int set_default_vars(int nvars, char * const vars[], int flags); /* Import from binary representation into hash table */ int env_import(const char *buf, int check); +int env_import_ext(const char *buf, enum env_context ctx, int check); /* Export from hash table into binary representation */ int env_export(env_t *env_out); +int env_export_ext(env_hdr_t **env_out, enum env_context ctx); #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT /* Select and import one of two redundant environments */ int env_import_redund(const char *buf1, int buf1_status, const char *buf2, int buf2_status); +int env_import_redund_ext(const char *buf1, int buf1_status, + const char *buf2, int buf2_status, + enum env_context ctx); #endif /** @@ -296,6 +348,14 @@ int env_get_char(int index); */ int env_load(void); +/** + * env_load_ext() - Load given environment context from storage + * + * @ctx: context to be loaded + * @return 0 if OK, -ve on error + */ +int env_load_ext(enum env_context ctx); + /** * env_save() - Save the environment to storage * @@ -303,6 +363,14 @@ int env_load(void); */ int env_save(void); +/** + * env_save_ext() - Save given environment context to storage + * + * @ctx: context to be saved + * @return 0 if OK, -ve on error + */ +int env_save_ext(enum env_context ctx); + /** * env_fix_drivers() - Updates envdriver as per relocation */ @@ -314,4 +382,7 @@ int eth_env_set_enetaddr(const char *name, const uint8_t *enetaddr); #endif /* DO_DEPS_ONLY */ +/* FIXME: ENVCTX_COUNT is protected by DO_DEPS_ONLY */ +#define ENVCTX_COUNT_MAX 2 + #endif /* _ENVIRONMENT_H_ */