From mboxrd@z Thu Jan 1 00:00:00 1970 Delivery-date: Mon, 02 Mar 2026 10:25:36 +0100 Received: from metis.whiteo.stw.pengutronix.de ([2a0a:edc0:2:b01:1d::104]) by lore.white.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vwzWx-007Esp-1O for lore@lore.pengutronix.de; Mon, 02 Mar 2026 10:25:36 +0100 Received: from [127.0.0.1] (helo=metis.whiteo.stw.pengutronix.de) by metis.whiteo.stw.pengutronix.de with esmtp (Exim 4.92) (envelope-from ) id 1vwzWy-0002d1-2O; Mon, 02 Mar 2026 10:25:36 +0100 Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1vwzWg-0002Uh-2r; Mon, 02 Mar 2026 10:25:18 +0100 Received: from dude05.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::54]) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vwzWe-003M6J-1k; Mon, 02 Mar 2026 10:25:17 +0100 Received: from mol by dude05.red.stw.pengutronix.de with local (Exim 4.98.2) (envelope-from ) id 1vwzWf-0000000Eh67-3VRr; Mon, 02 Mar 2026 10:25:17 +0100 From: Michael Olbrich To: ptxdist@pengutronix.de Date: Mon, 2 Mar 2026 10:25:17 +0100 Message-ID: <20260302092517.3502252-1-m.olbrich@pengutronix.de> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260212100924.1556815-1-ada@thorsis.com> References: <20260212100924.1556815-1-ada@thorsis.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subject: Re: [ptxdist] [APPLIED] libubootenv: version bump 0.3.6 -> 0.3.7 X-BeenThere: ptxdist@pengutronix.de X-Mailman-Version: 2.1.29 Precedence: list List-Id: PTXdist Development Mailing List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: ptxdist@pengutronix.de Cc: Alexander Dahl Sender: "ptxdist" X-SA-Exim-Connect-IP: 127.0.0.1 X-SA-Exim-Mail-From: ptxdist-bounces@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false Thanks, applied as 63876ac3c6c9d9cb660da274b42a25407d5209dd. Michael [sent from post-receive hook] On Mon, 02 Mar 2026 10:25:17 +0100, Alexander Dahl wrote: > All patches gone upstream. Changes from 0.3.6 to 0.3.7 are basically > all those patches plus some build warnings removed and typos fixed. > > Signed-off-by: Alexander Dahl > Message-Id: <20260212100924.1556815-1-ada@thorsis.com> > Signed-off-by: Michael Olbrich > > diff --git a/patches/libubootenv-0.3.6/0001-Make-libyaml-optional.patch b/patches/libubootenv-0.3.6/0001-Make-libyaml-optional.patch > deleted file mode 100644 > index 631d0f1ef7fb..000000000000 > --- a/patches/libubootenv-0.3.6/0001-Make-libyaml-optional.patch > +++ /dev/null > @@ -1,1507 +0,0 @@ > -From: Stefano Babic > -Date: Tue, 29 Oct 2024 09:23:20 +0100 > -Subject: [PATCH] Make libyaml optional > - > -NewYAML format is required for extended features because the format > -foreseen by U-Boot is very limited. However, some systems due to > -low resources don't want to link to libyaml. Add the option > -NO_YML_SUPPORT to disable YAML configuration file and just use > -fw_env.config in the U-Boot format. > - > -There are no functional changes in this patch - function depending on > -YML are moved in a separate file, and some functions are factorized. > - > -Signed-off-by: Stefano Babic > ---- > - CMakeLists.txt | 6 + > - src/CMakeLists.txt | 9 +- > - src/common.c | 248 +++++++++++++++++++ > - src/common.h | 15 ++ > - src/extended_config.c | 452 ++++++++++++++++++++++++++++++++++ > - src/uboot_env.c | 655 +------------------------------------------------- > - 6 files changed, 735 insertions(+), 650 deletions(-) > - create mode 100644 src/common.c > - create mode 100644 src/common.h > - create mode 100644 src/extended_config.c > - > -diff --git a/CMakeLists.txt b/CMakeLists.txt > -index 3bb93e16b42b..796d7bcffb29 100644 > ---- a/CMakeLists.txt > -+++ b/CMakeLists.txt > -@@ -12,6 +12,8 @@ set(VERSION "0.3.6") > - SET(SOVERSION "0") > - add_definitions(-DVERSION="${VERSION}") > - > -+option(NO_YML_SUPPORT "YML Support") > -+ > - if(DEFAULT_CFG_FILE) > - add_definitions(-DDEFAULT_CFG_FILE="${DEFAULT_CFG_FILE}") > - endif(DEFAULT_CFG_FILE) > -@@ -20,6 +22,10 @@ if(DEFAULT_ENV_FILE) > - add_definitions(-DDEFAULT_ENV_FILE="${DEFAULT_ENV_FILE}") > - endif(DEFAULT_ENV_FILE) > - > -+if(NO_YML_SUPPORT) > -+ add_definitions(-DNO_YAML_SUPPORT) > -+endif(NO_YML_SUPPORT) > -+ > - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") > - > - #set(CMAKE_C_FLAGS_DEBUG "-g") > -diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt > -index 63d48225f83b..c56d0c756528 100644 > ---- a/src/CMakeLists.txt > -+++ b/src/CMakeLists.txt > -@@ -6,6 +6,9 @@ cmake_minimum_required (VERSION 2.6) > - SET(libubootenv_SOURCES > - uboot_env.c > - uboot_mtd.c > -+ extended_config.c > -+ common.c > -+ common.h > - uboot_private.h > - ) > - > -@@ -22,7 +25,11 @@ SET_TARGET_PROPERTIES(ubootenv PROPERTIES VERSION ${VERSION} SOVERSION ${SOVERSI > - ADD_LIBRARY(ubootenv_static STATIC ${libubootenv_SOURCES} ${include_HEADERS}) > - SET_TARGET_PROPERTIES(ubootenv_static PROPERTIES OUTPUT_NAME ubootenv) > - add_executable(fw_printenv fw_printenv.c) > --target_link_libraries(ubootenv z yaml) > -+target_link_libraries(ubootenv z) > -+if (NOT NO_YML_SUPPORT) > -+target_link_libraries(ubootenv yaml) > -+endif(NOT NO_YML_SUPPORT) > -+ > - target_link_libraries(fw_printenv ubootenv) > - add_custom_target(fw_setenv ALL ${CMAKE_COMMAND} -E create_symlink fw_printenv fw_setenv) > - > -diff --git a/src/common.c b/src/common.c > -new file mode 100644 > -index 000000000000..2cbde93a7140 > ---- /dev/null > -+++ b/src/common.c > -@@ -0,0 +1,248 @@ > -+/* > -+ * (C) Copyright 2024 > -+ * Stefano Babic, > -+ * > -+ * SPDX-License-Identifier: LGPL-2.1-or-later > -+ */ > -+ > -+#define _GNU_SOURCE > -+ > -+#include > -+#include > -+#include > -+#include > -+#include > -+#include > -+#include > -+#include > -+#include > -+#include > -+#include > -+#include > -+#ifdef __FreeBSD__ > -+#include > -+#define BLKGETSIZE64 DIOCGMEDIASIZE > -+#else > -+#include > -+#endif > -+ > -+#include "uboot_private.h" > -+#include "common.h" > -+ > -+static enum device_type get_device_type(char *device) > -+{ > -+ enum device_type type = DEVICE_NONE; > -+ > -+ if (!strncmp(device, DEVICE_MTD_NAME, strlen(DEVICE_MTD_NAME))) > -+ if (strchr(device, DEVNAME_SEPARATOR)) { > -+ type = DEVICE_UBI; > -+ } else { > -+ type = DEVICE_MTD; > -+ } > -+ else if (!strncmp(device, DEVICE_UBI_NAME, strlen(DEVICE_UBI_NAME))) > -+ type = DEVICE_UBI; > -+ else if (strlen(device) > 0) > -+ type = DEVICE_FILE; > -+ > -+ return type; > -+} > -+ > -+int normalize_device_path(char *path, struct uboot_flash_env *dev) > -+{ > -+ char *sep = NULL, *normalized = NULL; > -+ size_t normalized_len = 0, volume_len = 0, output_len = 0; > -+ > -+ /* > -+ * if volume name is present, split into device path and volume > -+ * since only the device path needs normalized > -+ */ > -+ sep = strchr(path, DEVNAME_SEPARATOR); > -+ if (sep) > -+ { > -+ volume_len = strlen(sep); > -+ *sep = '\0'; > -+ } > -+ > -+ if ((normalized = realpath(path, NULL)) == NULL) > -+ { > -+ /* device file didn't exist */ > -+ return -EINVAL; > -+ } > -+ > -+ normalized_len = strlen(normalized); > -+ output_len = sizeof(dev->devname) - 1; /* leave room for null */ > -+ if ((normalized_len + volume_len) > output_len) > -+ { > -+ /* full name is too long to fit */ > -+ free(normalized); > -+ return -EINVAL; > -+ } > -+ > -+ /* > -+ * save normalized path to device file, > -+ * and possibly append separator char & volume name > -+ */ > -+ memset(dev->devname, 0, sizeof(dev->devname)); > -+ strncpy(dev->devname, normalized, output_len); > -+ free(normalized); > -+ > -+ if (sep) > -+ { > -+ *sep = DEVNAME_SEPARATOR; > -+ strncpy(dev->devname + normalized_len, sep, output_len - normalized_len); > -+ } > -+ > -+ return 0; > -+} > -+ > -+void set_var_access_type(struct var_entry *entry, const char *pvarflags) > -+{ > -+ if (entry) { > -+ for (int i = 0; i < strlen(pvarflags); i++) { > -+ switch (pvarflags[i]) { > -+ case 's': > -+ entry->type = TYPE_ATTR_STRING; > -+ break; > -+ case 'd': > -+ entry->type = TYPE_ATTR_DECIMAL; > -+ break; > -+ case 'x': > -+ entry->type = TYPE_ATTR_HEX; > -+ break; > -+ case 'b': > -+ entry->type = TYPE_ATTR_BOOL; > -+ break; > -+ case 'i': > -+ entry->type = TYPE_ATTR_IP; > -+ break; > -+ case 'm': > -+ entry->type = TYPE_ATTR_MAC; > -+ break; > -+ case 'a': > -+ entry->access = ACCESS_ATTR_ANY; > -+ break; > -+ case 'r': > -+ entry->access = ACCESS_ATTR_READ_ONLY; > -+ break; > -+ case 'o': > -+ entry->access = ACCESS_ATTR_WRITE_ONCE; > -+ break; > -+ case 'c': > -+ entry->access = ACCESS_ATTR_CHANGE_DEFAULT; > -+ break; > -+ default: /* ignore it */ > -+ break; > -+ } > -+ } > -+ } > -+} > -+ > -+struct var_entry *create_var_entry(const char *name) > -+{ > -+ struct var_entry *entry; > -+ > -+ entry = (struct var_entry *)calloc(1, sizeof(*entry)); > -+ if (!entry) > -+ return NULL; > -+ entry->name = strdup(name); > -+ if (!entry->name) { > -+ free(entry); > -+ return NULL; > -+ } > -+ > -+ return entry; > -+} > -+ > -+bool check_compatible_devices(struct uboot_ctx *ctx) > -+{ > -+ if (!ctx->redundant) > -+ return true; > -+ > -+ if (ctx->envdevs[0].mtdinfo.type != ctx->envdevs[1].mtdinfo.type) > -+ return false; > -+ if (ctx->envdevs[0].flagstype != ctx->envdevs[1].flagstype) > -+ return false; > -+ if (ctx->envdevs[0].envsize != ctx->envdevs[1].envsize) > -+ return false; > -+ > -+ return true; > -+} > -+ > -+int check_env_device(struct uboot_flash_env *dev) > -+{ > -+ int fd, ret; > -+ struct stat st; > -+ > -+ dev->device_type = get_device_type(dev->devname); > -+ if (dev->device_type == DEVICE_NONE) > -+ return -EBADF; > -+ > -+ if (dev->device_type == DEVICE_UBI) { > -+ ret = libubootenv_ubi_update_name(dev); > -+ if (ret) > -+ return ret; > -+ } > -+ > -+ ret = stat(dev->devname, &st); > -+ if (ret < 0) > -+ return -EBADF; > -+ fd = open(dev->devname, O_RDONLY); > -+ if (fd < 0) > -+ return -EBADF; > -+ > -+ if (S_ISCHR(st.st_mode)) { > -+ if (dev->device_type == DEVICE_MTD) { > -+ ret = libubootenv_mtdgetinfo(fd, dev); > -+ if (ret < 0 || (dev->mtdinfo.type != MTD_NORFLASH && > -+ dev->mtdinfo.type != MTD_NANDFLASH)) { > -+ close(fd); > -+ return -EBADF; > -+ } > -+ if (dev->sectorsize == 0) { > -+ dev->sectorsize = dev->mtdinfo.erasesize; > -+ } > -+ } > -+ } > -+ > -+ switch (dev->device_type) { > -+ case DEVICE_FILE: > -+ dev->flagstype = FLAGS_INCREMENTAL; > -+ break; > -+ case DEVICE_MTD: > -+ switch (dev->mtdinfo.type) { > -+ case MTD_NORFLASH: > -+ dev->flagstype = FLAGS_BOOLEAN; > -+ break; > -+ case MTD_NANDFLASH: > -+ dev->flagstype = FLAGS_INCREMENTAL; > -+ }; > -+ break; > -+ case DEVICE_UBI: > -+ dev->flagstype = FLAGS_INCREMENTAL; > -+ break; > -+ default: > -+ close(fd); > -+ return -EBADF; > -+ }; > -+ > -+ /* > -+ * Check for negative offsets, treat it as backwards offset > -+ * from the end of the block device > -+ */ > -+ if (dev->offset < 0) { > -+ uint64_t blkdevsize; > -+ int rc; > -+ > -+ rc = ioctl(fd, BLKGETSIZE64, &blkdevsize); > -+ if (rc < 0) { > -+ close(fd); > -+ return -EINVAL; > -+ } > -+ > -+ dev->offset += blkdevsize; > -+ } > -+ > -+ close(fd); > -+ > -+ return 0; > -+} > -diff --git a/src/common.h b/src/common.h > -new file mode 100644 > -index 000000000000..adacd4896741 > ---- /dev/null > -+++ b/src/common.h > -@@ -0,0 +1,15 @@ > -+/* > -+ * (C) Copyright 2024 > -+ * Stefano Babic, > -+ * > -+ * SPDX-License-Identifier: LGPL-2.1-or-later > -+ */ > -+ > -+ > -+#include "uboot_private.h" > -+ > -+struct var_entry *create_var_entry(const char *name); > -+void set_var_access_type(struct var_entry *entry, const char *pvarflags); > -+int normalize_device_path(char *path, struct uboot_flash_env *dev); > -+int check_env_device(struct uboot_flash_env *dev); > -+bool check_compatible_devices(struct uboot_ctx *ctx); > -diff --git a/src/extended_config.c b/src/extended_config.c > -new file mode 100644 > -index 000000000000..ec814f484efd > ---- /dev/null > -+++ b/src/extended_config.c > -@@ -0,0 +1,452 @@ > -+/* > -+ * (C) Copyright 2024 > -+ * Stefano Babic, > -+ * > -+ * SPDX-License-Identifier: LGPL-2.1-or-later > -+ */ > -+ > -+/** > -+ * @file extended_config.c > -+ * > -+ * @brief Implement the extended config file YAML > -+ * > -+ */ > -+#define _GNU_SOURCE > -+ > -+#if !defined(NO_YAML_SUPPORT) > -+#include > -+#include > -+#include > -+#include > -+#include > -+#include > -+#include > -+ > -+#include "uboot_private.h" > -+#include "common.h" > -+ > -+/* yaml_* functions return 1 on success and 0 on failure. */ > -+enum yaml_status { > -+ SUCCESS = 0, > -+ FAILURE = 1 > -+}; > -+ > -+enum yaml_state { > -+ STATE_START, /* start state */ > -+ STATE_STREAM, /* start/end stream */ > -+ STATE_DOCUMENT, /* start/end document */ > -+ STATE_SECTION, /* top level */ > -+ > -+ STATE_NAMESPACE, /* Init Configuration Namespace */ > -+ STATE_NAMESPACE_FIELDS, /* namespace key list */ > -+ STATE_NKEY, /* Check key names */ > -+ STATE_NSIZE, /* Size key-value pair */ > -+ STATE_NLOCKFILE, /* Lockfile key-value pair */ > -+ STATE_DEVVALUES, /* Devices key names */ > -+ STATE_WRITELIST, /* List with vars that are accepted by write > -+ * if list is missing, all vars are accepted > -+ * var is in the format name:flags, see U-Boot > -+ * documentation > -+ */ > -+ > -+ STATE_NPATH, > -+ STATE_NOFFSET, > -+ STATE_NSECTORSIZE, > -+ STATE_NUNLOCK, > -+ STATE_STOP /* end state */ > -+}; > -+ > -+typedef enum yaml_parse_error_e { > -+ YAML_UNEXPECTED_STATE, > -+ YAML_UNEXPECTED_KEY, > -+ YAML_BAD_DEVICE, > -+ YAML_BAD_DEVNAME, > -+ YAML_BAD_VARLIST, > -+ YAML_DUPLICATE_VARLIST, > -+ YAML_OOM, > -+} yaml_parse_error_type_t; > -+ > -+struct parser_state { > -+ enum yaml_state state; /* The current parse state */ > -+ struct uboot_ctx *ctxsets; /* Array of vars set ctx */ > -+ struct uboot_ctx *ctx; /* Current ctx in parsing */ > -+ unsigned int nelem; /* Number of elemets in ctxsets */ > -+ unsigned int cdev; /* current device in parsing */ > -+ yaml_parse_error_type_t error; /* error causing parser to stop */ > -+ yaml_event_type_t event_type; /* event type causing error */ > -+}; > -+ > -+static int consume_event(struct parser_state *s, yaml_event_t *event) > -+{ > -+ char *value; > -+ struct uboot_flash_env *dev; > -+ struct uboot_ctx *newctx; > -+ int cdev; > -+ > -+ switch (s->state) { > -+ case STATE_START: > -+ switch (event->type) { > -+ case YAML_STREAM_START_EVENT: > -+ s->state = STATE_STREAM; > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_STREAM: > -+ switch (event->type) { > -+ case YAML_DOCUMENT_START_EVENT: > -+ s->state = STATE_DOCUMENT; > -+ break; > -+ case YAML_STREAM_END_EVENT: > -+ s->state = STATE_STOP; > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_DOCUMENT: > -+ switch (event->type) { > -+ case YAML_MAPPING_START_EVENT: > -+ s->state = STATE_SECTION; > -+ break; > -+ case YAML_DOCUMENT_END_EVENT: > -+ s->state = STATE_STREAM; > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_SECTION: > -+ switch (event->type) { > -+ case YAML_SCALAR_EVENT: > -+ value = (char *)event->data.scalar.value; > -+ newctx = calloc (s->nelem + 1, sizeof(*newctx)); > -+ for (int i = 0; i < s->nelem; i++) { > -+ newctx[i] = s->ctxsets[i]; > -+ } > -+ if (s->ctxsets) free(s->ctxsets); > -+ s->ctxsets = newctx; > -+ s->ctx = &newctx[s->nelem]; > -+ s->ctx->name = strdup(value); > -+ s->nelem++; > -+ s->state = STATE_NAMESPACE; > -+ break; > -+ case YAML_MAPPING_END_EVENT: > -+ s->state = STATE_DOCUMENT; > -+ break; > -+ case YAML_DOCUMENT_END_EVENT: > -+ s->state = STATE_STREAM; > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_NAMESPACE: > -+ switch (event->type) { > -+ case YAML_MAPPING_START_EVENT: > -+ s->state = STATE_NAMESPACE_FIELDS; > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_NAMESPACE_FIELDS: > -+ switch (event->type) { > -+ case YAML_SCALAR_EVENT: > -+ value = (char *)event->data.scalar.value; > -+ if (!strcmp(value, "size")) { > -+ s->state = STATE_NSIZE; > -+ } else if (!strcmp(value, "lockfile")) { > -+ s->state = STATE_NLOCKFILE; > -+ } else if (!strcmp(value, "devices")) { > -+ s->state = STATE_DEVVALUES; > -+ s->cdev = 0; > -+ } else if (!strcmp(value, "writelist")) { > -+ s->state = STATE_WRITELIST; > -+ } else { > -+ s->error = YAML_UNEXPECTED_KEY; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ case YAML_MAPPING_END_EVENT: > -+ s->state = STATE_SECTION; > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_NSIZE: > -+ switch (event->type) { > -+ case YAML_SCALAR_EVENT: > -+ value = (char *)event->data.scalar.value; > -+ errno = 0; > -+ s->ctx->size = strtoull(value, NULL, 0); > -+ s->state = STATE_NAMESPACE_FIELDS; > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_NLOCKFILE: > -+ switch (event->type) { > -+ case YAML_SCALAR_EVENT: > -+ value = (char *)event->data.scalar.value; > -+ s->ctx->lockfile = strdup(value); > -+ s->state = STATE_NAMESPACE_FIELDS; > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_DEVVALUES: > -+ switch (event->type) { > -+ case YAML_MAPPING_START_EVENT: > -+ case YAML_SEQUENCE_START_EVENT: > -+ break; > -+ case YAML_MAPPING_END_EVENT: > -+ dev = &s->ctx->envdevs[s->cdev]; > -+ if (check_env_device(dev) < 0) { > -+ s->error = YAML_BAD_DEVICE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ s->cdev++; > -+ break; > -+ case YAML_SEQUENCE_END_EVENT: > -+ s->state = STATE_NAMESPACE_FIELDS; > -+ break; > -+ case YAML_SCALAR_EVENT: > -+ value = (char *)event->data.scalar.value; > -+ if (s->cdev) > -+ s->ctx->redundant = true; > -+ if (!strcmp(value, "path")) { > -+ s->state = STATE_NPATH; > -+ } else if (!strcmp(value, "offset")) { > -+ s->state = STATE_NOFFSET; > -+ } else if (!strcmp(value, "sectorsize")) { > -+ s->state = STATE_NSECTORSIZE; > -+ } else if (!strcmp(value, "disablelock")) { > -+ s->state = STATE_NUNLOCK; > -+ } else { > -+ s->error = YAML_UNEXPECTED_KEY; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_WRITELIST: > -+ switch (event->type) { > -+ > -+ char *varflag, *name; > -+ struct var_entry *entry; > -+ > -+ case YAML_MAPPING_START_EVENT: > -+ case YAML_SEQUENCE_START_EVENT: > -+ break; > -+ case YAML_MAPPING_END_EVENT: > -+ break; > -+ case YAML_SEQUENCE_END_EVENT: > -+ s->state = STATE_NAMESPACE_FIELDS; > -+ break; > -+ case YAML_SCALAR_EVENT: > -+ value = (char *)event->data.scalar.value; > -+ > -+ /* > -+ * Format is name:flags, split it into two values > -+ */ > -+ varflag = strchr(value, ':'); > -+ if (!varflag || varflag > value + (strlen(value) - 1)) { > -+ s->error = YAML_BAD_VARLIST; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ *varflag++ = '\0'; > -+ > -+ /* > -+ * Check there is not yet an entry for this variable > -+ */ > -+ LIST_FOREACH(entry, &s->ctx->writevarlist, next) { > -+ if (strcmp(entry->name, value) == 0) { > -+ s->error = YAML_DUPLICATE_VARLIST; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ } > -+ > -+ /* > -+ * Insert variable with its configuration into the list > -+ * of modifiable vars > -+ */ > -+ entry = create_var_entry(value); > -+ if (!entry) { > -+ s->error = YAML_OOM; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ set_var_access_type(entry, varflag); > -+ LIST_INSERT_HEAD(&s->ctx->writevarlist, entry, next); > -+ > -+#if !defined(NDEBUG) > -+ fprintf(stdout, "Writelist: %s flags %s\n", value, varflag); > -+#endif > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_NPATH: > -+ switch (event->type) { > -+ case YAML_SCALAR_EVENT: > -+ dev = &s->ctx->envdevs[s->cdev]; > -+ value = (char *)event->data.scalar.value; > -+ if (normalize_device_path(value, dev) < 0) { > -+ s->error = YAML_BAD_DEVNAME; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ dev->envsize = s->ctx->size; > -+ s->state = STATE_DEVVALUES; > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_NOFFSET: > -+ switch (event->type) { > -+ case YAML_SCALAR_EVENT: > -+ dev = &s->ctx->envdevs[s->cdev]; > -+ value = (char *)event->data.scalar.value; > -+ dev->offset = strtoull(value, NULL, 0); > -+ s->state = STATE_DEVVALUES; > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_NSECTORSIZE: > -+ switch (event->type) { > -+ case YAML_SCALAR_EVENT: > -+ dev = &s->ctx->envdevs[s->cdev]; > -+ value = (char *)event->data.scalar.value; > -+ dev->sectorsize = strtoull(value, NULL, 0); > -+ s->state = STATE_DEVVALUES; > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_NUNLOCK: > -+ switch (event->type) { > -+ case YAML_SCALAR_EVENT: > -+ dev = &s->ctx->envdevs[s->cdev]; > -+ value = (char *)event->data.scalar.value; > -+ if (!strcmp(value, "yes")) > -+ dev->disable_mtd_lock = 1; > -+ s->state = STATE_DEVVALUES; > -+ break; > -+ default: > -+ s->error = YAML_UNEXPECTED_STATE; > -+ s->event_type = event->type; > -+ return FAILURE; > -+ } > -+ break; > -+ > -+ case STATE_STOP: > -+ break; > -+ } > -+ return SUCCESS; > -+} > -+ > -+int parse_yaml_config(struct uboot_ctx **ctxlist, FILE *fp) > -+{ > -+ yaml_parser_t parser; > -+ yaml_event_t event; > -+ enum yaml_status status; > -+ struct parser_state state; > -+ struct uboot_ctx *ctx; > -+ > -+ if (!yaml_parser_initialize(&parser)) > -+ return -ENOMEM; > -+ > -+ /* Set input file */ > -+ yaml_parser_set_input_file(&parser, fp); > -+ memset(&state, 0, sizeof(state)); > -+ state.state = STATE_START; > -+ do { > -+ if (!yaml_parser_parse(&parser, &event)) { > -+ status = FAILURE; > -+ goto cleanup; > -+ } > -+ status = consume_event(&state, &event); > -+ yaml_event_delete(&event); > -+ if (status == FAILURE) { > -+ goto cleanup; > -+ } > -+ } while (state.state != STATE_STOP); > -+ > -+ state.ctxsets[0].nelem = state.nelem; > -+ > -+ for (int i = 0; i < state.nelem; i++) { > -+ ctx = &state.ctxsets[i]; > -+ ctx->ctxlist = &state.ctxsets[0]; > -+ if (ctx->redundant && !check_compatible_devices(ctx)) { > -+ status = FAILURE; > -+ break; > -+ } > -+ } > -+ > -+ > -+cleanup: > -+ yaml_parser_delete(&parser); > -+ if (status == FAILURE) { > -+ if (state.ctxsets) free (state.ctxsets); > -+ state.ctxsets = NULL; > -+ } > -+ *ctxlist = state.ctxsets; > -+ return status; > -+} > -+#endif > -diff --git a/src/uboot_env.c b/src/uboot_env.c > -index 0b4f9f4d0458..d8b93dac7479 100644 > ---- a/src/uboot_env.c > -+++ b/src/uboot_env.c > -@@ -21,12 +21,6 @@ > - #include > - #include > - #include > --#ifdef __FreeBSD__ > --#include > --#define BLKGETSIZE64 DIOCGMEDIASIZE > --#else > --#include > --#endif > - #include > - #include > - #include > -@@ -38,60 +32,15 @@ > - #include > - #include > - #include > --#include > - > - #include "uboot_private.h" > -+#include "common.h" > - > --/* yaml_* functions return 1 on success and 0 on failure. */ > --enum yaml_status { > -- SUCCESS = 0, > -- FAILURE = 1 > --}; > -- > --enum yaml_state { > -- STATE_START, /* start state */ > -- STATE_STREAM, /* start/end stream */ > -- STATE_DOCUMENT, /* start/end document */ > -- STATE_SECTION, /* top level */ > -- > -- STATE_NAMESPACE, /* Init Configuration Namespace */ > -- STATE_NAMESPACE_FIELDS, /* namespace key list */ > -- STATE_NKEY, /* Check key names */ > -- STATE_NSIZE, /* Size key-value pair */ > -- STATE_NLOCKFILE, /* Lockfile key-value pair */ > -- STATE_DEVVALUES, /* Devices key names */ > -- STATE_WRITELIST, /* List with vars that are accepted by write > -- * if list is missing, all vars are accepted > -- * var is in the format name:flags, see U-Boot > -- * documentation > -- */ > -- > -- STATE_NPATH, > -- STATE_NOFFSET, > -- STATE_NSECTORSIZE, > -- STATE_NUNLOCK, > -- STATE_STOP /* end state */ > --}; > -- > --typedef enum yaml_parse_error_e { > -- YAML_UNEXPECTED_STATE, > -- YAML_UNEXPECTED_KEY, > -- YAML_BAD_DEVICE, > -- YAML_BAD_DEVNAME, > -- YAML_BAD_VARLIST, > -- YAML_DUPLICATE_VARLIST, > -- YAML_OOM, > --} yaml_parse_error_type_t; > -- > --struct parser_state { > -- enum yaml_state state; /* The current parse state */ > -- struct uboot_ctx *ctxsets; /* Array of vars set ctx */ > -- struct uboot_ctx *ctx; /* Current ctx in parsing */ > -- unsigned int nelem; /* Number of elemets in ctxsets */ > -- unsigned int cdev; /* current device in parsing */ > -- yaml_parse_error_type_t error; /* error causing parser to stop */ > -- yaml_event_type_t event_type; /* event type causing error */ > --}; > -+#if defined(NO_YAML_SUPPORT) > -+#define parse_yaml_config(ctx,fp) -1 > -+#else > -+extern int parse_yaml_config(struct uboot_ctx **ctxlist, FILE *fp); > -+#endif > - > - #define FREE_ENTRY do { \ > - free(entry->name); \ > -@@ -152,64 +101,6 @@ static char attr_tostring(type_attribute a) > - return 's'; > - } > - > --static void set_var_access_type(struct var_entry *entry, const char *pvarflags) > --{ > -- if (entry) { > -- for (int i = 0; i < strlen(pvarflags); i++) { > -- switch (pvarflags[i]) { > -- case 's': > -- entry->type = TYPE_ATTR_STRING; > -- break; > -- case 'd': > -- entry->type = TYPE_ATTR_DECIMAL; > -- break; > -- case 'x': > -- entry->type = TYPE_ATTR_HEX; > -- break; > -- case 'b': > -- entry->type = TYPE_ATTR_BOOL; > -- break; > -- case 'i': > -- entry->type = TYPE_ATTR_IP; > -- break; > -- case 'm': > -- entry->type = TYPE_ATTR_MAC; > -- break; > -- case 'a': > -- entry->access = ACCESS_ATTR_ANY; > -- break; > -- case 'r': > -- entry->access = ACCESS_ATTR_READ_ONLY; > -- break; > -- case 'o': > -- entry->access = ACCESS_ATTR_WRITE_ONCE; > -- break; > -- case 'c': > -- entry->access = ACCESS_ATTR_CHANGE_DEFAULT; > -- break; > -- default: /* ignore it */ > -- break; > -- } > -- } > -- } > --} > -- > --static struct var_entry *create_var_entry(const char *name) > --{ > -- struct var_entry *entry; > -- > -- entry = (struct var_entry *)calloc(1, sizeof(*entry)); > -- if (!entry) > -- return NULL; > -- entry->name = strdup(name); > -- if (!entry->name) { > -- free(entry); > -- return NULL; > -- } > -- > -- return entry; > --} > -- > - static char access_tostring(access_attribute a) > - { > - switch(a) { > -@@ -389,166 +280,6 @@ static int __libuboot_set_env(struct uboot_ctx *ctx, const char *varname, const > - return 0; > - } > - > --static enum device_type get_device_type(char *device) > --{ > -- enum device_type type = DEVICE_NONE; > -- > -- if (!strncmp(device, DEVICE_MTD_NAME, strlen(DEVICE_MTD_NAME))) > -- if (strchr(device, DEVNAME_SEPARATOR)) { > -- type = DEVICE_UBI; > -- } else { > -- type = DEVICE_MTD; > -- } > -- else if (!strncmp(device, DEVICE_UBI_NAME, strlen(DEVICE_UBI_NAME))) > -- type = DEVICE_UBI; > -- else if (strlen(device) > 0) > -- type = DEVICE_FILE; > -- > -- return type; > --} > -- > --static int normalize_device_path(char *path, struct uboot_flash_env *dev) > --{ > -- char *sep = NULL, *normalized = NULL; > -- size_t normalized_len = 0, volume_len = 0, output_len = 0; > -- > -- /* > -- * if volume name is present, split into device path and volume > -- * since only the device path needs normalized > -- */ > -- sep = strchr(path, DEVNAME_SEPARATOR); > -- if (sep) > -- { > -- volume_len = strlen(sep); > -- *sep = '\0'; > -- } > -- > -- if ((normalized = realpath(path, NULL)) == NULL) > -- { > -- /* device file didn't exist */ > -- return -EINVAL; > -- } > -- > -- normalized_len = strlen(normalized); > -- output_len = sizeof(dev->devname) - 1; /* leave room for null */ > -- if ((normalized_len + volume_len) > output_len) > -- { > -- /* full name is too long to fit */ > -- free(normalized); > -- return -EINVAL; > -- } > -- > -- /* > -- * save normalized path to device file, > -- * and possibly append separator char & volume name > -- */ > -- memset(dev->devname, 0, sizeof(dev->devname)); > -- strncpy(dev->devname, normalized, output_len); > -- free(normalized); > -- > -- if (sep) > -- { > -- *sep = DEVNAME_SEPARATOR; > -- strncpy(dev->devname + normalized_len, sep, output_len - normalized_len); > -- } > -- > -- return 0; > --} > -- > --static int check_env_device(struct uboot_flash_env *dev) > --{ > -- int fd, ret; > -- struct stat st; > -- > -- dev->device_type = get_device_type(dev->devname); > -- if (dev->device_type == DEVICE_NONE) > -- return -EBADF; > -- > -- if (dev->device_type == DEVICE_UBI) { > -- ret = libubootenv_ubi_update_name(dev); > -- if (ret) > -- return ret; > -- } > -- > -- ret = stat(dev->devname, &st); > -- if (ret < 0) > -- return -EBADF; > -- fd = open(dev->devname, O_RDONLY); > -- if (fd < 0) > -- return -EBADF; > -- > -- if (S_ISCHR(st.st_mode)) { > -- if (dev->device_type == DEVICE_MTD) { > -- ret = libubootenv_mtdgetinfo(fd, dev); > -- if (ret < 0 || (dev->mtdinfo.type != MTD_NORFLASH && > -- dev->mtdinfo.type != MTD_NANDFLASH)) { > -- close(fd); > -- return -EBADF; > -- } > -- if (dev->sectorsize == 0) { > -- dev->sectorsize = dev->mtdinfo.erasesize; > -- } > -- } > -- } > -- > -- switch (dev->device_type) { > -- case DEVICE_FILE: > -- dev->flagstype = FLAGS_INCREMENTAL; > -- break; > -- case DEVICE_MTD: > -- switch (dev->mtdinfo.type) { > -- case MTD_NORFLASH: > -- dev->flagstype = FLAGS_BOOLEAN; > -- break; > -- case MTD_NANDFLASH: > -- dev->flagstype = FLAGS_INCREMENTAL; > -- }; > -- break; > -- case DEVICE_UBI: > -- dev->flagstype = FLAGS_INCREMENTAL; > -- break; > -- default: > -- close(fd); > -- return -EBADF; > -- }; > -- > -- /* > -- * Check for negative offsets, treat it as backwards offset > -- * from the end of the block device > -- */ > -- if (dev->offset < 0) { > -- uint64_t blkdevsize; > -- int rc; > -- > -- rc = ioctl(fd, BLKGETSIZE64, &blkdevsize); > -- if (rc < 0) { > -- close(fd); > -- return -EINVAL; > -- } > -- > -- dev->offset += blkdevsize; > -- } > -- > -- close(fd); > -- > -- return 0; > --} > -- > --static bool check_compatible_devices(struct uboot_ctx *ctx) > --{ > -- if (!ctx->redundant) > -- return true; > -- > -- if (ctx->envdevs[0].mtdinfo.type != ctx->envdevs[1].mtdinfo.type) > -- return false; > -- if (ctx->envdevs[0].flagstype != ctx->envdevs[1].flagstype) > -- return false; > -- if (ctx->envdevs[0].envsize != ctx->envdevs[1].envsize) > -- return false; > -- > -- return true; > --} > -- > - static int fileread(struct uboot_flash_env *dev, void *data) > - { > - int ret = 0; > -@@ -1035,380 +766,6 @@ static int libuboot_load(struct uboot_ctx *ctx) > - return ctx->valid ? 0 : -ENODATA; > - } > - > --static int consume_event(struct parser_state *s, yaml_event_t *event) > --{ > -- char *value; > -- struct uboot_flash_env *dev; > -- struct uboot_ctx *newctx; > -- int cdev; > -- > -- switch (s->state) { > -- case STATE_START: > -- switch (event->type) { > -- case YAML_STREAM_START_EVENT: > -- s->state = STATE_STREAM; > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_STREAM: > -- switch (event->type) { > -- case YAML_DOCUMENT_START_EVENT: > -- s->state = STATE_DOCUMENT; > -- break; > -- case YAML_STREAM_END_EVENT: > -- s->state = STATE_STOP; > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_DOCUMENT: > -- switch (event->type) { > -- case YAML_MAPPING_START_EVENT: > -- s->state = STATE_SECTION; > -- break; > -- case YAML_DOCUMENT_END_EVENT: > -- s->state = STATE_STREAM; > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_SECTION: > -- switch (event->type) { > -- case YAML_SCALAR_EVENT: > -- value = (char *)event->data.scalar.value; > -- newctx = calloc (s->nelem + 1, sizeof(*newctx)); > -- for (int i = 0; i < s->nelem; i++) { > -- newctx[i] = s->ctxsets[i]; > -- } > -- if (s->ctxsets) free(s->ctxsets); > -- s->ctxsets = newctx; > -- s->ctx = &newctx[s->nelem]; > -- s->ctx->name = strdup(value); > -- s->nelem++; > -- s->state = STATE_NAMESPACE; > -- break; > -- case YAML_MAPPING_END_EVENT: > -- s->state = STATE_DOCUMENT; > -- break; > -- case YAML_DOCUMENT_END_EVENT: > -- s->state = STATE_STREAM; > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_NAMESPACE: > -- switch (event->type) { > -- case YAML_MAPPING_START_EVENT: > -- s->state = STATE_NAMESPACE_FIELDS; > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_NAMESPACE_FIELDS: > -- switch (event->type) { > -- case YAML_SCALAR_EVENT: > -- value = (char *)event->data.scalar.value; > -- if (!strcmp(value, "size")) { > -- s->state = STATE_NSIZE; > -- } else if (!strcmp(value, "lockfile")) { > -- s->state = STATE_NLOCKFILE; > -- } else if (!strcmp(value, "devices")) { > -- s->state = STATE_DEVVALUES; > -- s->cdev = 0; > -- } else if (!strcmp(value, "writelist")) { > -- s->state = STATE_WRITELIST; > -- } else { > -- s->error = YAML_UNEXPECTED_KEY; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- case YAML_MAPPING_END_EVENT: > -- s->state = STATE_SECTION; > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_NSIZE: > -- switch (event->type) { > -- case YAML_SCALAR_EVENT: > -- value = (char *)event->data.scalar.value; > -- errno = 0; > -- s->ctx->size = strtoull(value, NULL, 0); > -- s->state = STATE_NAMESPACE_FIELDS; > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_NLOCKFILE: > -- switch (event->type) { > -- case YAML_SCALAR_EVENT: > -- value = (char *)event->data.scalar.value; > -- s->ctx->lockfile = strdup(value); > -- s->state = STATE_NAMESPACE_FIELDS; > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_DEVVALUES: > -- switch (event->type) { > -- case YAML_MAPPING_START_EVENT: > -- case YAML_SEQUENCE_START_EVENT: > -- break; > -- case YAML_MAPPING_END_EVENT: > -- dev = &s->ctx->envdevs[s->cdev]; > -- if (check_env_device(dev) < 0) { > -- s->error = YAML_BAD_DEVICE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- s->cdev++; > -- break; > -- case YAML_SEQUENCE_END_EVENT: > -- s->state = STATE_NAMESPACE_FIELDS; > -- break; > -- case YAML_SCALAR_EVENT: > -- value = (char *)event->data.scalar.value; > -- if (s->cdev) > -- s->ctx->redundant = true; > -- if (!strcmp(value, "path")) { > -- s->state = STATE_NPATH; > -- } else if (!strcmp(value, "offset")) { > -- s->state = STATE_NOFFSET; > -- } else if (!strcmp(value, "sectorsize")) { > -- s->state = STATE_NSECTORSIZE; > -- } else if (!strcmp(value, "disablelock")) { > -- s->state = STATE_NUNLOCK; > -- } else { > -- s->error = YAML_UNEXPECTED_KEY; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_WRITELIST: > -- switch (event->type) { > -- > -- char *varflag, *name; > -- struct var_entry *entry; > -- > -- case YAML_MAPPING_START_EVENT: > -- case YAML_SEQUENCE_START_EVENT: > -- break; > -- case YAML_MAPPING_END_EVENT: > -- break; > -- case YAML_SEQUENCE_END_EVENT: > -- s->state = STATE_NAMESPACE_FIELDS; > -- break; > -- case YAML_SCALAR_EVENT: > -- value = (char *)event->data.scalar.value; > -- > -- /* > -- * Format is name:flags, split it into two values > -- */ > -- varflag = strchr(value, ':'); > -- if (!varflag || varflag > value + (strlen(value) - 1)) { > -- s->error = YAML_BAD_VARLIST; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- *varflag++ = '\0'; > -- > -- /* > -- * Check there is not yet an entry for this variable > -- */ > -- LIST_FOREACH(entry, &s->ctx->writevarlist, next) { > -- if (strcmp(entry->name, value) == 0) { > -- s->error = YAML_DUPLICATE_VARLIST; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- } > -- > -- /* > -- * Insert variable with its configuration into the list > -- * of modifiable vars > -- */ > -- entry = create_var_entry(value); > -- if (!entry) { > -- s->error = YAML_OOM; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- set_var_access_type(entry, varflag); > -- LIST_INSERT_HEAD(&s->ctx->writevarlist, entry, next); > -- > --#if !defined(NDEBUG) > -- fprintf(stdout, "Writelist: %s flags %s\n", value, varflag); > --#endif > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_NPATH: > -- switch (event->type) { > -- case YAML_SCALAR_EVENT: > -- dev = &s->ctx->envdevs[s->cdev]; > -- value = (char *)event->data.scalar.value; > -- if (normalize_device_path(value, dev) < 0) { > -- s->error = YAML_BAD_DEVNAME; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- dev->envsize = s->ctx->size; > -- s->state = STATE_DEVVALUES; > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_NOFFSET: > -- switch (event->type) { > -- case YAML_SCALAR_EVENT: > -- dev = &s->ctx->envdevs[s->cdev]; > -- value = (char *)event->data.scalar.value; > -- dev->offset = strtoull(value, NULL, 0); > -- s->state = STATE_DEVVALUES; > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_NSECTORSIZE: > -- switch (event->type) { > -- case YAML_SCALAR_EVENT: > -- dev = &s->ctx->envdevs[s->cdev]; > -- value = (char *)event->data.scalar.value; > -- dev->sectorsize = strtoull(value, NULL, 0); > -- s->state = STATE_DEVVALUES; > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_NUNLOCK: > -- switch (event->type) { > -- case YAML_SCALAR_EVENT: > -- dev = &s->ctx->envdevs[s->cdev]; > -- value = (char *)event->data.scalar.value; > -- if (!strcmp(value, "yes")) > -- dev->disable_mtd_lock = 1; > -- s->state = STATE_DEVVALUES; > -- break; > -- default: > -- s->error = YAML_UNEXPECTED_STATE; > -- s->event_type = event->type; > -- return FAILURE; > -- } > -- break; > -- > -- case STATE_STOP: > -- break; > -- } > -- return SUCCESS; > --} > -- > --int parse_yaml_config(struct uboot_ctx **ctxlist, FILE *fp) > --{ > -- yaml_parser_t parser; > -- yaml_event_t event; > -- enum yaml_status status; > -- struct parser_state state; > -- struct uboot_ctx *ctx; > -- > -- if (!yaml_parser_initialize(&parser)) > -- return -ENOMEM; > -- > -- /* Set input file */ > -- yaml_parser_set_input_file(&parser, fp); > -- memset(&state, 0, sizeof(state)); > -- state.state = STATE_START; > -- do { > -- if (!yaml_parser_parse(&parser, &event)) { > -- status = FAILURE; > -- goto cleanup; > -- } > -- status = consume_event(&state, &event); > -- yaml_event_delete(&event); > -- if (status == FAILURE) { > -- goto cleanup; > -- } > -- } while (state.state != STATE_STOP); > -- > -- state.ctxsets[0].nelem = state.nelem; > -- > -- for (int i = 0; i < state.nelem; i++) { > -- ctx = &state.ctxsets[i]; > -- ctx->ctxlist = &state.ctxsets[0]; > -- if (ctx->redundant && !check_compatible_devices(ctx)) { > -- status = FAILURE; > -- break; > -- } > -- } > -- > -- > --cleanup: > -- yaml_parser_delete(&parser); > -- if (status == FAILURE) { > -- if (state.ctxsets) free (state.ctxsets); > -- state.ctxsets = NULL; > -- } > -- *ctxlist = state.ctxsets; > -- return status; > --} > -- > - #define LINE_LENGTH 2048 > - int libuboot_load_file(struct uboot_ctx *ctx, const char *filename) > - { > diff --git a/patches/libubootenv-0.3.6/0002-extended_config-fix-segfault-on-empty-config.patch b/patches/libubootenv-0.3.6/0002-extended_config-fix-segfault-on-empty-config.patch > deleted file mode 100644 > index a4574ff5fef6..000000000000 > --- a/patches/libubootenv-0.3.6/0002-extended_config-fix-segfault-on-empty-config.patch > +++ /dev/null > @@ -1,40 +0,0 @@ > -From: James Hilliard > -Date: Thu, 24 Apr 2025 19:53:01 -0600 > -Subject: [PATCH] extended_config: fix segfault on empty config > - > -We need to validate that we have nelem and bail out if we don't. > - > -Fixes: > -==245== Invalid write of size 4 > -==245== at 0x4849E0C: parse_yaml_config (uboot_env.c:1390) > -==245== by 0x484A717: libuboot_read_config_ext (uboot_env.c:1484) > -==245== by 0x13F253: bootloader_initialize.constprop.0 (uboot.c:45) > -==245== by 0x13F457: do_env_set (uboot.c:72) > -==245== by 0x12B057: update_transaction_state (stream_interface.c:139) > -==245== by 0x12C367: extract_files (stream_interface.c:297) > -==245== by 0x12C367: network_initializer (stream_interface.c:658) > -==245== by 0x4EA89AF: ??? (in /usr/lib/libc.so.6) > -==245== by 0x4F0989B: ??? (in /usr/lib/libc.so.6) > -==245== Address 0x2e8 is not stack'd, malloc'd or (recently) free'd > - > -Signed-off-by: James Hilliard > ---- > - src/extended_config.c | 5 +++++ > - 1 file changed, 5 insertions(+) > - > -diff --git a/src/extended_config.c b/src/extended_config.c > -index ec814f484efd..45df3ec7a7ca 100644 > ---- a/src/extended_config.c > -+++ b/src/extended_config.c > -@@ -428,6 +428,11 @@ int parse_yaml_config(struct uboot_ctx **ctxlist, FILE *fp) > - } > - } while (state.state != STATE_STOP); > - > -+ if (state.nelem == 0) { > -+ status = FAILURE; > -+ goto cleanup; > -+ } > -+ > - state.ctxsets[0].nelem = state.nelem; > - > - for (int i = 0; i < state.nelem; i++) { > diff --git a/patches/libubootenv-0.3.6/0003-BUG-Fix-warning-when-copying-UBI-volume.patch b/patches/libubootenv-0.3.6/0003-BUG-Fix-warning-when-copying-UBI-volume.patch > deleted file mode 100644 > index 1ead8954860b..000000000000 > --- a/patches/libubootenv-0.3.6/0003-BUG-Fix-warning-when-copying-UBI-volume.patch > +++ /dev/null > @@ -1,35 +0,0 @@ > -From: Stefano Babic > -Date: Tue, 29 Apr 2025 13:49:15 +0200 > -Subject: [PATCH] BUG: Fix warning when copying UBI volume > -MIME-Version: 1.0 > -Content-Type: text/plain; charset=UTF-8 > -Content-Transfer-Encoding: 8bit > - > -Fix: > - > -/home/stefano/SWUpdate/libubootenv/src/uboot_mtd.c: In function ‘libubootenv_ubi_update_name’: > -/home/stefano/SWUpdate/libubootenv/src/uboot_mtd.c:283:17: warning: ‘memset’ writing 256 bytes into a region of size 236 overflows the destination [-Wstringop-overflow=] > - 283 | memset(volume, 0, DEVNAME_MAX_LENGTH); > - | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > -/home/stefano/SWUpdate/libubootenv/src/uboot_mtd.c:223:14: note: destination object ‘volume’ of size 236 > - > -This can lead to overwrite the buffer for the volumes. > - > -Signed-off-by: Stefano Babic > ---- > - src/uboot_mtd.c | 2 +- > - 1 file changed, 1 insertion(+), 1 deletion(-) > - > -diff --git a/src/uboot_mtd.c b/src/uboot_mtd.c > -index 81376e4ddc09..24e817d88944 100644 > ---- a/src/uboot_mtd.c > -+++ b/src/uboot_mtd.c > -@@ -280,7 +280,7 @@ int libubootenv_ubi_update_name(struct uboot_flash_env *dev) > - memset(device, 0, DEVNAME_MAX_LENGTH); > - memcpy(device, dev->devname, sep - dev->devname); > - > -- memset(volume, 0, DEVNAME_MAX_LENGTH); > -+ memset(volume, 0, VOLNAME_MAX_LENGTH); > - sscanf(sep + 1, "%s", &volume[0]); > - > - dev_id = ubi_get_dev_id(device); > diff --git a/patches/libubootenv-0.3.6/0004-libubootenv-fix-segfault-due-to-uninitialized-pointe.patch b/patches/libubootenv-0.3.6/0004-libubootenv-fix-segfault-due-to-uninitialized-pointe.patch > deleted file mode 100644 > index e7ae92fb8562..000000000000 > --- a/patches/libubootenv-0.3.6/0004-libubootenv-fix-segfault-due-to-uninitialized-pointe.patch > +++ /dev/null > @@ -1,32 +0,0 @@ > -From: Mohamed-nour Toumi > -Date: Mon, 28 Jul 2025 22:25:35 +0200 > -Subject: [PATCH] libubootenv: fix segfault due to uninitialized pointer in > - config parser > - > -Issue: The issue was introduced in commit c478e8d9, which replaced the use of %ms in sscanf() with a calloc()-based workaround for platforms where %ms is not supported (e.g., FreeBSD). > -However, this change inadvertently introduced a logic flaw: it uses calloc to emulate %ms% in sscanf() but also added 2 free instructions which could lead to free non-allocated memory on tmp when sscanf() > -is used to perform the dynamic allocation. > - > -Fix: Ensure `tmp` is initialized to NULL before each call to sscanf with `%ms` > -in `libuboot_read_config_ext()`. This prevents `free(tmp)` from crashing > -when sscanf fails to allocate memory (e.g., due to malformed config lines). > - > -Fixes segmentation fault observed when running swupdate with a ubootenv config file. > - > -Signed-off-by: Mohamed-nour Toumi > ---- > - src/uboot_env.c | 1 + > - 1 file changed, 1 insertion(+) > - > -diff --git a/src/uboot_env.c b/src/uboot_env.c > -index d8b93dac7479..9641800f4bdc 100644 > ---- a/src/uboot_env.c > -+++ b/src/uboot_env.c > -@@ -871,6 +871,7 @@ int libuboot_read_config_ext(struct uboot_ctx **ctxlist, const char *config) > - tmp, > - #else > - (void)len; > -+ tmp = NULL; > - ret = sscanf(line, "%ms %lli %zx %zx %lx %d", > - &tmp, > - #endif > diff --git a/patches/libubootenv-0.3.6/0005-extended_config.c-Catch-NULL-pointer-for-calloc.patch b/patches/libubootenv-0.3.6/0005-extended_config.c-Catch-NULL-pointer-for-calloc.patch > deleted file mode 100644 > index 9c89141c7a90..000000000000 > --- a/patches/libubootenv-0.3.6/0005-extended_config.c-Catch-NULL-pointer-for-calloc.patch > +++ /dev/null > @@ -1,30 +0,0 @@ > -From: Steffen Kothe > -Date: Sun, 31 Aug 2025 19:07:56 +0000 > -Subject: [PATCH] extended_config.c: Catch NULL pointer for calloc > - > -calloc is not guaranteed to return a valid pointer to a free memory > -area. > - > -Hence check for possible NULL return and fail immediately. > - > -Addresses possible CWE-690. > - > -Signed-off-by: Steffen Kothe > -Acked-by: Stefano Babic > ---- > - src/extended_config.c | 2 ++ > - 1 file changed, 2 insertions(+) > - > -diff --git a/src/extended_config.c b/src/extended_config.c > -index 45df3ec7a7ca..c3782e1fba94 100644 > ---- a/src/extended_config.c > -+++ b/src/extended_config.c > -@@ -131,6 +131,8 @@ static int consume_event(struct parser_state *s, yaml_event_t *event) > - case YAML_SCALAR_EVENT: > - value = (char *)event->data.scalar.value; > - newctx = calloc (s->nelem + 1, sizeof(*newctx)); > -+ if (newctx == NULL) > -+ return FAILURE; > - for (int i = 0; i < s->nelem; i++) { > - newctx[i] = s->ctxsets[i]; > - } > diff --git a/patches/libubootenv-0.3.6/series b/patches/libubootenv-0.3.6/series > deleted file mode 100644 > index b9356ee68463..000000000000 > --- a/patches/libubootenv-0.3.6/series > +++ /dev/null > @@ -1,8 +0,0 @@ > -# generated by git-ptx-patches > -#tag:base --start-number 1 > -0001-Make-libyaml-optional.patch > -0002-extended_config-fix-segfault-on-empty-config.patch > -0003-BUG-Fix-warning-when-copying-UBI-volume.patch > -0004-libubootenv-fix-segfault-due-to-uninitialized-pointe.patch > -0005-extended_config.c-Catch-NULL-pointer-for-calloc.patch > -# 8a759d09e861f42f9d568274b3aeb30b - git-ptx-patches magic > diff --git a/rules/libubootenv.make b/rules/libubootenv.make > index 1ec86693a4e3..8a317d6699eb 100644 > --- a/rules/libubootenv.make > +++ b/rules/libubootenv.make > @@ -14,8 +14,8 @@ PACKAGES-$(PTXCONF_LIBUBOOTENV) += libubootenv > # > # Paths and names > # > -LIBUBOOTENV_VERSION := 0.3.6 > -LIBUBOOTENV_MD5 := 7d6b623e8da435cf36e7fcd419a03e43 > +LIBUBOOTENV_VERSION := 0.3.7 > +LIBUBOOTENV_MD5 := 593b3eb88062955042593eb6ec19e4e6 > LIBUBOOTENV := libubootenv-$(LIBUBOOTENV_VERSION) > LIBUBOOTENV_SUFFIX := tar.gz > LIBUBOOTENV_URL := https://github.com/sbabic/libubootenv/archive/refs/tags/v$(LIBUBOOTENV_VERSION).$(LIBUBOOTENV_SUFFIX)