* [ptxdist] [PATCH] libubootenv: version bump 0.3.6 -> 0.3.7
@ 2026-02-12 10:09 Alexander Dahl via ptxdist
2026-03-02 9:25 ` [ptxdist] [APPLIED] " Michael Olbrich
0 siblings, 1 reply; 2+ messages in thread
From: Alexander Dahl via ptxdist @ 2026-02-12 10:09 UTC (permalink / raw)
To: ptxdist; +Cc: Alexander Dahl
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 <ada@thorsis.com>
---
.../0001-Make-libyaml-optional.patch | 1507 -----------------
..._config-fix-segfault-on-empty-config.patch | 40 -
...-Fix-warning-when-copying-UBI-volume.patch | 35 -
...segfault-due-to-uninitialized-pointe.patch | 32 -
...nfig.c-Catch-NULL-pointer-for-calloc.patch | 30 -
patches/libubootenv-0.3.6/series | 8 -
rules/libubootenv.make | 4 +-
7 files changed, 2 insertions(+), 1654 deletions(-)
delete mode 100644 patches/libubootenv-0.3.6/0001-Make-libyaml-optional.patch
delete mode 100644 patches/libubootenv-0.3.6/0002-extended_config-fix-segfault-on-empty-config.patch
delete mode 100644 patches/libubootenv-0.3.6/0003-BUG-Fix-warning-when-copying-UBI-volume.patch
delete mode 100644 patches/libubootenv-0.3.6/0004-libubootenv-fix-segfault-due-to-uninitialized-pointe.patch
delete mode 100644 patches/libubootenv-0.3.6/0005-extended_config.c-Catch-NULL-pointer-for-calloc.patch
delete mode 100644 patches/libubootenv-0.3.6/series
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 631d0f1ef..000000000
--- a/patches/libubootenv-0.3.6/0001-Make-libyaml-optional.patch
+++ /dev/null
@@ -1,1507 +0,0 @@
-From: Stefano Babic <stefano.babic@swupdate.org>
-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 <stefano.babic@swupdate.org>
----
- 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, <stefano.babic@swupdate.org>
-+ *
-+ * SPDX-License-Identifier: LGPL-2.1-or-later
-+ */
-+
-+#define _GNU_SOURCE
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <stdint.h>
-+#include <stddef.h>
-+#include <dirent.h>
-+#include <unistd.h>
-+#include <limits.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <fcntl.h>
-+#include <sys/stat.h>
-+#include <sys/ioctl.h>
-+#ifdef __FreeBSD__
-+#include <sys/disk.h>
-+#define BLKGETSIZE64 DIOCGMEDIASIZE
-+#else
-+#include <linux/fs.h>
-+#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, <stefano.babic@swupdate.org>
-+ *
-+ * 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, <stefano.babic@swupdate.org>
-+ *
-+ * 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 <stdio.h>
-+#include <stdlib.h>
-+#include <stdint.h>
-+#include <stddef.h>
-+#include <unistd.h>
-+#include <errno.h>
-+#include <yaml.h>
-+
-+#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 <dirent.h>
- #include <unistd.h>
- #include <limits.h>
--#ifdef __FreeBSD__
--#include <sys/disk.h>
--#define BLKGETSIZE64 DIOCGMEDIASIZE
--#else
--#include <linux/fs.h>
--#endif
- #include <string.h>
- #include <fcntl.h>
- #include <errno.h>
-@@ -38,60 +32,15 @@
- #include <sys/wait.h>
- #include <sys/ioctl.h>
- #include <zlib.h>
--#include <yaml.h>
-
- #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 a4574ff5f..000000000
--- a/patches/libubootenv-0.3.6/0002-extended_config-fix-segfault-on-empty-config.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From: James Hilliard <james.hilliard1@gmail.com>
-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 <james.hilliard1@gmail.com>
----
- 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 1ead89548..000000000
--- a/patches/libubootenv-0.3.6/0003-BUG-Fix-warning-when-copying-UBI-volume.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From: Stefano Babic <stefano.babic@swupdate.org>
-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 <stefano.babic@swupdate.org>
----
- 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 e7ae92fb8..000000000
--- 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 <mohamed.toumi_ext@softathome.com>
-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 <mohamed.toumi_ext@softathome.com>
----
- 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 9c89141c7..000000000
--- 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 <steffen.kothe@skothe.net>
-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 <steffen.kothe@skothe.net>
-Acked-by: Stefano Babic <stefano.babic@swupdate.org>
----
- 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 b9356ee68..000000000
--- 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 1ec86693a..8a317d669 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)
base-commit: 0f9d01296a5aed4d9fe6b9a32a4c495f4912ee8b
--
2.47.3
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [ptxdist] [APPLIED] libubootenv: version bump 0.3.6 -> 0.3.7
2026-02-12 10:09 [ptxdist] [PATCH] libubootenv: version bump 0.3.6 -> 0.3.7 Alexander Dahl via ptxdist
@ 2026-03-02 9:25 ` Michael Olbrich
0 siblings, 0 replies; 2+ messages in thread
From: Michael Olbrich @ 2026-03-02 9:25 UTC (permalink / raw)
To: ptxdist; +Cc: Alexander Dahl
Thanks, applied as 63876ac3c6c9d9cb660da274b42a25407d5209dd.
Michael
[sent from post-receive hook]
On Mon, 02 Mar 2026 10:25:17 +0100, Alexander Dahl <ada@thorsis.com> 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 <ada@thorsis.com>
> Message-Id: <20260212100924.1556815-1-ada@thorsis.com>
> Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
>
> 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 <stefano.babic@swupdate.org>
> -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 <stefano.babic@swupdate.org>
> ----
> - 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, <stefano.babic@swupdate.org>
> -+ *
> -+ * SPDX-License-Identifier: LGPL-2.1-or-later
> -+ */
> -+
> -+#define _GNU_SOURCE
> -+
> -+#include <stdio.h>
> -+#include <stdlib.h>
> -+#include <stdint.h>
> -+#include <stddef.h>
> -+#include <dirent.h>
> -+#include <unistd.h>
> -+#include <limits.h>
> -+#include <string.h>
> -+#include <errno.h>
> -+#include <fcntl.h>
> -+#include <sys/stat.h>
> -+#include <sys/ioctl.h>
> -+#ifdef __FreeBSD__
> -+#include <sys/disk.h>
> -+#define BLKGETSIZE64 DIOCGMEDIASIZE
> -+#else
> -+#include <linux/fs.h>
> -+#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, <stefano.babic@swupdate.org>
> -+ *
> -+ * 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, <stefano.babic@swupdate.org>
> -+ *
> -+ * 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 <stdio.h>
> -+#include <stdlib.h>
> -+#include <stdint.h>
> -+#include <stddef.h>
> -+#include <unistd.h>
> -+#include <errno.h>
> -+#include <yaml.h>
> -+
> -+#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 <dirent.h>
> - #include <unistd.h>
> - #include <limits.h>
> --#ifdef __FreeBSD__
> --#include <sys/disk.h>
> --#define BLKGETSIZE64 DIOCGMEDIASIZE
> --#else
> --#include <linux/fs.h>
> --#endif
> - #include <string.h>
> - #include <fcntl.h>
> - #include <errno.h>
> -@@ -38,60 +32,15 @@
> - #include <sys/wait.h>
> - #include <sys/ioctl.h>
> - #include <zlib.h>
> --#include <yaml.h>
> -
> - #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 <james.hilliard1@gmail.com>
> -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 <james.hilliard1@gmail.com>
> ----
> - 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 <stefano.babic@swupdate.org>
> -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 <stefano.babic@swupdate.org>
> ----
> - 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 <mohamed.toumi_ext@softathome.com>
> -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 <mohamed.toumi_ext@softathome.com>
> ----
> - 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 <steffen.kothe@skothe.net>
> -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 <steffen.kothe@skothe.net>
> -Acked-by: Stefano Babic <stefano.babic@swupdate.org>
> ----
> - 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)
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-03-02 9:25 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-02-12 10:09 [ptxdist] [PATCH] libubootenv: version bump 0.3.6 -> 0.3.7 Alexander Dahl via ptxdist
2026-03-02 9:25 ` [ptxdist] [APPLIED] " Michael Olbrich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox