From bd47e4a1d9ab7383ee96468308813b796e5f271b Mon Sep 17 00:00:00 2001 From: William Bright Date: Thu, 12 Mar 2026 15:36:39 +0000 Subject: [PATCH 1/2] qdl: Add support for having up to 32 include folder when searching for files. This is particularly useful for yocto builds since binaries are generated into three folders whereas currently QDL only supports searching for files in two folders. Signed-off-by: William Bright --- program.c | 14 +++++++++----- program.h | 2 +- qdl.c | 14 ++++++++++---- read.c | 18 +++++++++++++----- read.h | 2 +- 5 files changed, 34 insertions(+), 16 deletions(-) diff --git a/program.c b/program.c index e11f5ab8..d4c1f64f 100644 --- a/program.c +++ b/program.c @@ -148,13 +148,14 @@ static int program_load_sparse(struct program *program, int fd) return 0; } -static int load_program_tag(xmlNode *node, bool is_nand, bool allow_missing, const char *incdir) +static int load_program_tag(xmlNode *node, bool is_nand, bool allow_missing, const char *incdir[], int incdir_count) { struct program *program; char tmp[PATH_MAX]; int errors = 0; int ret; int fd = -1; + bool found = false; program = calloc(1, sizeof(struct program)); @@ -184,11 +185,14 @@ static int load_program_tag(xmlNode *node, bool is_nand, bool allow_missing, con } if (program->filename) { - if (incdir) { - snprintf(tmp, PATH_MAX, "%s/%s", incdir, program->filename); + for (int i = 0; i < incdir_count && incdir[i]; ++i) { + snprintf(tmp, PATH_MAX, "%s/%s", incdir[i], program->filename); if (access(tmp, F_OK) != -1) { free((void *)program->filename); program->filename = strdup(tmp); + if(found) + ux_info("multiple files found for %s, using %s\n", program->filename, tmp); + found = true; } } @@ -227,7 +231,7 @@ static int load_program_tag(xmlNode *node, bool is_nand, bool allow_missing, con return 0; } -int program_load(const char *program_file, bool is_nand, bool allow_missing, const char *incdir) +int program_load(const char *program_file, bool is_nand, bool allow_missing, const char *incdir[], int incdir_count) { xmlNode *node; xmlNode *root; @@ -248,7 +252,7 @@ int program_load(const char *program_file, bool is_nand, bool allow_missing, con if (!xmlStrcmp(node->name, (xmlChar *)"erase")) errors = load_erase_tag(node, is_nand); else if (!xmlStrcmp(node->name, (xmlChar *)"program")) - errors = load_program_tag(node, is_nand, allow_missing, incdir); + errors = load_program_tag(node, is_nand, allow_missing, incdir, incdir_count); else { ux_err("unrecognized tag \"%s\" in program-type file \"%s\"\n", node->name, program_file); errors = -EINVAL; diff --git a/program.h b/program.h index c86d12e2..714026e8 100644 --- a/program.h +++ b/program.h @@ -33,7 +33,7 @@ struct program { struct qdl_device; -int program_load(const char *program_file, bool is_nand, bool allow_missing, const char *incdir); +int program_load(const char *program_file, bool is_nand, bool allow_missing, const char *incdir[], int incdir_count); int program_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct program *program, int fd)); int erase_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct program *program)); int program_find_bootable_partition(bool *multiple_found); diff --git a/qdl.c b/qdl.c index 0f7cdc66..ea41f849 100644 --- a/qdl.c +++ b/qdl.c @@ -561,7 +561,7 @@ static int qdl_flash(int argc, char **argv) { enum qdl_storage_type storage_type = QDL_STORAGE_UFS; struct sahara_image sahara_images[MAPPING_SZ] = {}; - char *incdir = NULL; + const char *incdir[32] = {0}; char *serial = NULL; const char *vip_generate_dir = NULL; const char *vip_table_path = NULL; @@ -575,6 +575,7 @@ static int qdl_flash(int argc, char **argv) unsigned int slot = UINT_MAX; struct qdl_device *qdl = NULL; enum QDL_DEVICE_TYPE qdl_dev_type = QDL_DEVICE_USB; + int incdir_count = 0; static struct option options[] = { {"debug", no_argument, 0, 'd'}, @@ -614,7 +615,12 @@ static int qdl_flash(int argc, char **argv) allow_missing = true; break; case 'i': - incdir = optarg; + if (incdir_count < sizeof(incdir) / sizeof(incdir[0])) { + incdir[incdir_count] = optarg; + incdir_count++; + } else { + errx(1, "maximum number of include directories exceeded"); + } break; case 'l': qdl_finalize_provisioning = true; @@ -698,7 +704,7 @@ static int qdl_flash(int argc, char **argv) errx(1, "patch_load %s failed", argv[optind]); break; case QDL_FILE_PROGRAM: - ret = program_load(argv[optind], storage_type == QDL_STORAGE_NAND, allow_missing, incdir); + ret = program_load(argv[optind], storage_type == QDL_STORAGE_NAND, allow_missing, incdir, incdir_count); if (ret < 0) errx(1, "program_load %s failed", argv[optind]); @@ -707,7 +713,7 @@ static int qdl_flash(int argc, char **argv) " changes. Allow explicitly with --allow-fusing parameter"); break; case QDL_FILE_READ: - ret = read_op_load(argv[optind], incdir); + ret = read_op_load(argv[optind], incdir, incdir_count); if (ret < 0) errx(1, "read_op_load %s failed", argv[optind]); break; diff --git a/read.c b/read.c index 697102e4..0c00d876 100644 --- a/read.c +++ b/read.c @@ -19,7 +19,7 @@ static struct list_head read_ops = LIST_INIT(read_ops); -int read_op_load(const char *read_op_file, const char *incdir) +int read_op_load(const char *read_op_file, const char *incdir[], int incdir_count) { struct read_op *read_op; xmlNode *node; @@ -27,6 +27,7 @@ int read_op_load(const char *read_op_file, const char *incdir) xmlDoc *doc; int errors; char tmp[PATH_MAX]; + bool found = false; doc = xmlReadFile(read_op_file, NULL, 0); if (!doc) { @@ -61,10 +62,17 @@ int read_op_load(const char *read_op_file, const char *incdir) continue; } - if (incdir) { - snprintf(tmp, PATH_MAX, "%s/%s", incdir, read_op->filename); - if (access(tmp, F_OK) != -1) - read_op->filename = strdup(tmp); + if (read_op->filename) { + for (int i = 0; i < incdir_count && incdir[i]; ++i) { + snprintf(tmp, PATH_MAX, "%s/%s", incdir[i], read_op->filename); + if (access(tmp, F_OK) != -1) { + free((void *)read_op->filename); + read_op->filename = strdup(tmp); + if(found) + ux_info("multiple files found for %s, using %s\n", read_op->filename, tmp); + found = true; + } + } } list_add(&read_ops, &read_op->node); diff --git a/read.h b/read.h index 164555ee..e3749538 100644 --- a/read.h +++ b/read.h @@ -19,7 +19,7 @@ struct read_op { struct list_head node; }; -int read_op_load(const char *read_op_file, const char *incdir); +int read_op_load(const char *read_op_file, const char *incdir[], int incdir_count); int read_op_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct read_op *read_op, int fd)); int read_cmd_add(const char *source, const char *filename); From d43e4d84e9d3f4c233fa72e01f52f3e9d07a1de1 Mon Sep 17 00:00:00 2001 From: William Bright Date: Thu, 26 Mar 2026 19:11:50 +0000 Subject: [PATCH 2/2] qdl: replace fixed-size include directory array with linked list Use list_head from list.h to carry include directories instead of a hardcoded 32-entry array, removing the arbitrary limit on the number of -i options. Formatting issues of the previous patch were also fixed in the process of making this change. Signed-off-by: William Bright --- program.c | 13 +++++++------ program.h | 2 +- qdl.c | 26 ++++++++++++++++---------- qdl.h | 5 +++++ read.c | 12 +++++++----- read.h | 2 +- 6 files changed, 37 insertions(+), 23 deletions(-) diff --git a/program.c b/program.c index d4c1f64f..edf35989 100644 --- a/program.c +++ b/program.c @@ -148,8 +148,9 @@ static int program_load_sparse(struct program *program, int fd) return 0; } -static int load_program_tag(xmlNode *node, bool is_nand, bool allow_missing, const char *incdir[], int incdir_count) +static int load_program_tag(xmlNode *node, bool is_nand, bool allow_missing, struct list_head *incdirs) { + struct incdir_entry *incdir; struct program *program; char tmp[PATH_MAX]; int errors = 0; @@ -185,12 +186,12 @@ static int load_program_tag(xmlNode *node, bool is_nand, bool allow_missing, con } if (program->filename) { - for (int i = 0; i < incdir_count && incdir[i]; ++i) { - snprintf(tmp, PATH_MAX, "%s/%s", incdir[i], program->filename); + list_for_each_entry(incdir, incdirs, node) { + snprintf(tmp, PATH_MAX, "%s/%s", incdir->path, program->filename); if (access(tmp, F_OK) != -1) { free((void *)program->filename); program->filename = strdup(tmp); - if(found) + if (found) ux_info("multiple files found for %s, using %s\n", program->filename, tmp); found = true; } @@ -231,7 +232,7 @@ static int load_program_tag(xmlNode *node, bool is_nand, bool allow_missing, con return 0; } -int program_load(const char *program_file, bool is_nand, bool allow_missing, const char *incdir[], int incdir_count) +int program_load(const char *program_file, bool is_nand, bool allow_missing, struct list_head *incdirs) { xmlNode *node; xmlNode *root; @@ -252,7 +253,7 @@ int program_load(const char *program_file, bool is_nand, bool allow_missing, con if (!xmlStrcmp(node->name, (xmlChar *)"erase")) errors = load_erase_tag(node, is_nand); else if (!xmlStrcmp(node->name, (xmlChar *)"program")) - errors = load_program_tag(node, is_nand, allow_missing, incdir, incdir_count); + errors = load_program_tag(node, is_nand, allow_missing, incdirs); else { ux_err("unrecognized tag \"%s\" in program-type file \"%s\"\n", node->name, program_file); errors = -EINVAL; diff --git a/program.h b/program.h index 714026e8..f3a2ac27 100644 --- a/program.h +++ b/program.h @@ -33,7 +33,7 @@ struct program { struct qdl_device; -int program_load(const char *program_file, bool is_nand, bool allow_missing, const char *incdir[], int incdir_count); +int program_load(const char *program_file, bool is_nand, bool allow_missing, struct list_head *incdirs); int program_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct program *program, int fd)); int erase_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct program *program)); int program_find_bootable_partition(bool *multiple_found); diff --git a/qdl.c b/qdl.c index ea41f849..a3485e7d 100644 --- a/qdl.c +++ b/qdl.c @@ -557,11 +557,20 @@ static int qdl_ramdump(int argc, char **argv) return ret; } +static void free_incdirs(struct list_head *incdirs) +{ + struct incdir_entry *incdir, *tmp; + + list_for_each_entry_safe(incdir, tmp, incdirs, node) + free(incdir); +} + static int qdl_flash(int argc, char **argv) { enum qdl_storage_type storage_type = QDL_STORAGE_UFS; struct sahara_image sahara_images[MAPPING_SZ] = {}; - const char *incdir[32] = {0}; + struct list_head incdirs = LIST_INIT(incdirs); + struct incdir_entry *incdir; char *serial = NULL; const char *vip_generate_dir = NULL; const char *vip_table_path = NULL; @@ -575,7 +584,6 @@ static int qdl_flash(int argc, char **argv) unsigned int slot = UINT_MAX; struct qdl_device *qdl = NULL; enum QDL_DEVICE_TYPE qdl_dev_type = QDL_DEVICE_USB; - int incdir_count = 0; static struct option options[] = { {"debug", no_argument, 0, 'd'}, @@ -615,12 +623,9 @@ static int qdl_flash(int argc, char **argv) allow_missing = true; break; case 'i': - if (incdir_count < sizeof(incdir) / sizeof(incdir[0])) { - incdir[incdir_count] = optarg; - incdir_count++; - } else { - errx(1, "maximum number of include directories exceeded"); - } + incdir = calloc(1, sizeof(*incdir)); + incdir->path = optarg; + list_add(&incdirs, &incdir->node); break; case 'l': qdl_finalize_provisioning = true; @@ -704,7 +709,7 @@ static int qdl_flash(int argc, char **argv) errx(1, "patch_load %s failed", argv[optind]); break; case QDL_FILE_PROGRAM: - ret = program_load(argv[optind], storage_type == QDL_STORAGE_NAND, allow_missing, incdir, incdir_count); + ret = program_load(argv[optind], storage_type == QDL_STORAGE_NAND, allow_missing, &incdirs); if (ret < 0) errx(1, "program_load %s failed", argv[optind]); @@ -713,7 +718,7 @@ static int qdl_flash(int argc, char **argv) " changes. Allow explicitly with --allow-fusing parameter"); break; case QDL_FILE_READ: - ret = read_op_load(argv[optind], incdir, incdir_count); + ret = read_op_load(argv[optind], &incdirs); if (ret < 0) errx(1, "read_op_load %s failed", argv[optind]); break; @@ -776,6 +781,7 @@ static int qdl_flash(int argc, char **argv) free_programs(); free_patches(); + free_incdirs(&incdirs); if (qdl) { if (qdl->vip_data.state != VIP_DISABLED) diff --git a/qdl.h b/qdl.h index 6b515381..c86cce0a 100644 --- a/qdl.h +++ b/qdl.h @@ -41,6 +41,11 @@ (__typeof__(p))(((uintptr_t)(p) + _mask) & ~_mask); \ }) +struct incdir_entry { + const char *path; + struct list_head node; +}; + #define MAPPING_SZ 64 #define SAHARA_ID_EHOSTDL_IMG 13 diff --git a/read.c b/read.c index 0c00d876..1190cf7c 100644 --- a/read.c +++ b/read.c @@ -19,8 +19,9 @@ static struct list_head read_ops = LIST_INIT(read_ops); -int read_op_load(const char *read_op_file, const char *incdir[], int incdir_count) +int read_op_load(const char *read_op_file, struct list_head *incdirs) { + struct incdir_entry *incdir; struct read_op *read_op; xmlNode *node; xmlNode *root; @@ -63,13 +64,14 @@ int read_op_load(const char *read_op_file, const char *incdir[], int incdir_coun } if (read_op->filename) { - for (int i = 0; i < incdir_count && incdir[i]; ++i) { - snprintf(tmp, PATH_MAX, "%s/%s", incdir[i], read_op->filename); + list_for_each_entry(incdir, incdirs, node) { + snprintf(tmp, PATH_MAX, "%s/%s", incdir->path, read_op->filename); if (access(tmp, F_OK) != -1) { free((void *)read_op->filename); read_op->filename = strdup(tmp); - if(found) - ux_info("multiple files found for %s, using %s\n", read_op->filename, tmp); + if (found) + ux_info("multiple files found for %s, using %s\n", + read_op->filename, tmp); found = true; } } diff --git a/read.h b/read.h index e3749538..60f0799a 100644 --- a/read.h +++ b/read.h @@ -19,7 +19,7 @@ struct read_op { struct list_head node; }; -int read_op_load(const char *read_op_file, const char *incdir[], int incdir_count); +int read_op_load(const char *read_op_file, struct list_head *incdirs); int read_op_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct read_op *read_op, int fd)); int read_cmd_add(const char *source, const char *filename);