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 <[email protected]>
---
 .../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 <[email protected]>
-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 <[email protected]>
----
- 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, <[email protected]>
-+ *
-+ * 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, <[email protected]>
-+ *
-+ * 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, <[email protected]>
-+ *
-+ * 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 <[email protected]>
-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 <[email protected]>
----
- 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 <[email protected]>
-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 <[email protected]>
----
- 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 <[email protected]>
-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 <[email protected]>
----
- 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 <[email protected]>
-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 <[email protected]>
-Acked-by: Stefano Babic <[email protected]>
----
- 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



Reply via email to