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