From ce175f2e274d042f74730111dd28526dfe983128 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Thu, 28 Aug 2025 11:26:11 -0500 Subject: [PATCH] Introduce a linked list abstraction For some reason qdl was written with open-coded linked list operations throughout the implementation, resulting in ugly boiler plate code sprinkled over the code base. Integrate the linked list abstraction used in a few other of our open-source projects to clean up the code. Signed-off-by: Bjorn Andersson --- list.h | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ patch.c | 22 ++++++----------- patch.h | 4 ++- program.c | 61 +++++++++++----------------------------------- program.h | 6 +++-- read.c | 24 +++++------------- read.h | 5 +++- ufs.c | 23 +++++++----------- ufs.h | 4 ++- 9 files changed, 123 insertions(+), 99 deletions(-) create mode 100644 list.h diff --git a/list.h b/list.h new file mode 100644 index 0000000..744bcdf --- /dev/null +++ b/list.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2016, Linaro Ltd. + */ +#ifndef __LIST_H__ +#define __LIST_H__ + +#include +#include + +struct list_head { + struct list_head *prev; + struct list_head *next; +}; + +#define LIST_INIT(list) { &(list), &(list) } + +static inline void list_init(struct list_head *list) +{ + list->prev = list; + list->next = list; +} + +static inline bool list_empty(struct list_head *list) +{ + return list->next == list; +} + +static inline void list_add(struct list_head *list, struct list_head *item) +{ + struct list_head *prev = list->prev; + + item->next = list; + item->prev = prev; + + prev->next = item; + list->prev = item; +} + +static inline void list_del(struct list_head *item) +{ + item->prev->next = item->next; + item->next->prev = item->prev; +} + +#define list_for_each(item, list) \ + for (item = (list)->next; item != list; item = item->next) + +#define list_for_each_safe(item, tmp, list) \ + for (item = (list)->next, tmp = item->next; item != list; item = tmp, tmp = item->next) + +#define list_entry(item, type, member) \ + container_of(item, type, member) + +#define list_entry_first(list, type, member) \ + container_of((list)->next, type, member) + +#define list_entry_next(item, member) \ + container_of((item)->member.next, typeof(*(item)), member) + +#define list_for_each_entry(item, list, member) \ + for (item = list_entry_first(list, typeof(*(item)), member); \ + &item->member != list; \ + item = list_entry_next(item, member)) + +#define list_for_each_entry_safe(item, next, list, member) \ + for (item = list_entry_first(list, typeof(*(item)), member), \ + next = list_entry_next(item, member); \ + &item->member != list; \ + item = next, \ + next = list_entry_next(item, member)) \ + +#endif diff --git a/patch.c b/patch.c index 5502a09..2603f71 100644 --- a/patch.c +++ b/patch.c @@ -13,8 +13,7 @@ #include "patch.h" #include "qdl.h" -static struct patch *patches; -static struct patch *patches_last; +static struct list_head patches = LIST_INIT(patches); int patch_load(const char *patch_file) { @@ -59,13 +58,7 @@ int patch_load(const char *patch_file) continue; } - if (patches) { - patches_last->next = patch; - patches_last = patch; - } else { - patches = patch; - patches_last = patch; - } + list_add(&patches, &patch->node); } xmlFreeDoc(doc); @@ -80,12 +73,12 @@ int patch_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, s unsigned int idx = 0; int ret; - for (patch = patches; patch; patch = patch->next) { + list_for_each_entry(patch, &patches, node) { if (!strcmp(patch->filename, "DISK")) count++; } - for (patch = patches; patch; patch = patch->next) { + list_for_each_entry(patch, &patches, node) { if (strcmp(patch->filename, "DISK")) continue; @@ -103,11 +96,10 @@ int patch_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, s void free_patches(void) { - struct patch *patch = patches; + struct patch *patch; struct patch *next; - for (patch = patches; patch; patch = next) { - next = patch->next; + list_for_each_entry_safe(patch, next, &patches, node) { free((void *)patch->filename); free((void *)patch->start_sector); free((void *)patch->value); @@ -115,5 +107,5 @@ void free_patches(void) free(patch); } - patches = NULL; + list_init(&patches); } diff --git a/patch.h b/patch.h index 9726303..30f5df4 100644 --- a/patch.h +++ b/patch.h @@ -2,6 +2,8 @@ #ifndef __PATCH_H__ #define __PATCH_H__ +#include "list.h" + struct qdl_device; struct patch { @@ -14,7 +16,7 @@ struct patch { const char *value; const char *what; - struct patch *next; + struct list_head node; }; int patch_load(const char *patch_file); diff --git a/program.c b/program.c index edf0f65..e11f5ab 100644 --- a/program.c +++ b/program.c @@ -20,8 +20,7 @@ #include "sparse.h" #include "gpt.h" -static struct program *programes; -static struct program *programes_last; +static struct list_head programs = LIST_INIT(programs); static int load_erase_tag(xmlNode *node, bool is_nand) { @@ -47,13 +46,7 @@ static int load_erase_tag(xmlNode *node, bool is_nand) return -EINVAL; } - if (programes) { - programes_last->next = program; - programes_last = program; - } else { - programes = program; - programes_last = program; - } + list_add(&programs, &program->node); return 0; } @@ -82,14 +75,8 @@ static int program_load_sparse(struct program *program, int fd) if ((off_t)program->sector_size * program->num_sectors == lseek(fd, 0, SEEK_END)) { program->sparse = false; - - if (programes) { - programes_last->next = program; - programes_last = program; - } else { - programes = program; - programes_last = program; - } + list_add(&programs, &program->node); + return 0; } ux_err("[PROGRAM] Unable to parse sparse header at %s...failed\n", @@ -149,14 +136,7 @@ static int program_load_sparse(struct program *program, int fd) else program_sparse->sparse_fill_value = sparse_fill_value; - program_sparse->next = NULL; - if (programes) { - programes_last->next = program_sparse; - programes_last = program_sparse; - } else { - programes = program_sparse; - programes_last = program_sparse; - } + list_add(&programs, &program_sparse->node); } start_sector = (unsigned int)strtoul(program->start_sector, NULL, 0); @@ -239,13 +219,7 @@ static int load_program_tag(xmlNode *node, bool is_nand, bool allow_missing, con program->filename = NULL; } - if (programes) { - programes_last->next = program; - programes_last = program; - } else { - programes = program; - programes_last = program; - } + list_add(&programs, &program->node); if (fd >= 0) close(fd); @@ -296,7 +270,7 @@ int program_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, int ret; int fd; - for (program = programes; program; program = program->next) { + list_for_each_entry(program, &programs, node) { if (program->is_erase || !program->filename) continue; @@ -321,7 +295,7 @@ int erase_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, s struct program *program; int ret; - for (program = programes; program; program = program->next) { + list_for_each_entry(program, &programs, node) { if (!program->is_erase) continue; @@ -338,7 +312,7 @@ static struct program *program_find_partition(const char *partition) struct program *program; const char *label; - for (program = programes; program; program = program->next) { + list_for_each_entry(program, &programs, node) { label = program->label; if (!label) continue; @@ -412,11 +386,10 @@ int program_is_sec_partition_flashed(void) void free_programs(void) { - struct program *program = programes; + struct program *program; struct program *next; - for (program = programes; program; program = next) { - next = program->next; + list_for_each_entry_safe(program, next, &programs, node) { free((void *)program->filename); free((void *)program->label); free((void *)program->start_sector); @@ -424,7 +397,7 @@ void free_programs(void) free(program); } - programes = NULL; + list_init(&programs); } int program_cmd_add(const char *address, const char *filename) @@ -457,13 +430,7 @@ int program_cmd_add(const char *address, const char *filename) program->is_erase = false; program->gpt_partition = gpt_partition; - if (programes) { - programes_last->next = program; - programes_last = program; - } else { - programes = program; - programes_last = program; - } + list_add(&programs, &program->node); return 0; } @@ -475,7 +442,7 @@ int program_resolve_gpt_deferrals(struct qdl_device *qdl) char buf[20]; int ret; - for (program = programes; program; program = program->next) { + list_for_each_entry(program, &programs, node) { if (!program->gpt_partition) continue; diff --git a/program.h b/program.h index 49fde8e..c86d12e 100644 --- a/program.h +++ b/program.h @@ -5,7 +5,7 @@ #include #include #include -#include "qdl.h" +#include "list.h" struct program { unsigned int pages_per_block; @@ -28,9 +28,11 @@ struct program { const char *gpt_partition; - struct program *next; + struct list_head node; }; +struct qdl_device; + int program_load(const char *program_file, bool is_nand, bool allow_missing, const char *incdir); 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)); diff --git a/read.c b/read.c index 18d1253..697102e 100644 --- a/read.c +++ b/read.c @@ -11,13 +11,13 @@ #include #include +#include "list.h" #include "read.h" #include "qdl.h" #include "oscompat.h" #include "gpt.h" -static struct read_op *read_ops; -static struct read_op *read_ops_last; +static struct list_head read_ops = LIST_INIT(read_ops); int read_op_load(const char *read_op_file, const char *incdir) { @@ -67,13 +67,7 @@ int read_op_load(const char *read_op_file, const char *incdir) read_op->filename = strdup(tmp); } - if (read_ops) { - read_ops_last->next = read_op; - read_ops_last = read_op; - } else { - read_ops = read_op; - read_ops_last = read_op; - } + list_add(&read_ops, &read_op->node); } xmlFreeDoc(doc); @@ -87,7 +81,7 @@ int read_op_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, int ret; int fd; - for (read_op = read_ops; read_op; read_op = read_op->next) { + list_for_each_entry(read_op, &read_ops, node) { fd = open(read_op->filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644); if (fd < 0) { ux_info("unable to open %s...\n", read_op->filename); @@ -133,13 +127,7 @@ int read_cmd_add(const char *address, const char *filename) read_op->start_sector = strdup(buf); read_op->gpt_partition = gpt_partition; - if (read_ops) { - read_ops_last->next = read_op; - read_ops_last = read_op; - } else { - read_ops = read_op; - read_ops_last = read_op; - } + list_add(&read_ops, &read_op->node); return 0; } @@ -151,7 +139,7 @@ int read_resolve_gpt_deferrals(struct qdl_device *qdl) char buf[20]; int ret; - for (read_op = read_ops; read_op; read_op = read_op->next) { + list_for_each_entry(read_op, &read_ops, node) { if (!read_op->gpt_partition) continue; diff --git a/read.h b/read.h index 3144870..164555e 100644 --- a/read.h +++ b/read.h @@ -4,6 +4,8 @@ #include +#include "list.h" + struct qdl_device; struct read_op { @@ -13,7 +15,8 @@ struct read_op { unsigned int num_sectors; const char *start_sector; const char *gpt_partition; - struct read_op *next; + + struct list_head node; }; int read_op_load(const char *read_op_file, const char *incdir); diff --git a/ufs.c b/ufs.c index d6751f7..90ecdf5 100644 --- a/ufs.c +++ b/ufs.c @@ -15,12 +15,12 @@ #include "ufs.h" #include "qdl.h" +#include "list.h" #include "patch.h" struct ufs_common *ufs_common_p; struct ufs_epilogue *ufs_epilogue_p; -struct ufs_body *ufs_body_p; -struct ufs_body *ufs_body_last; +static struct list_head ufs_bodies = LIST_INIT(ufs_bodies); static const char notice_bconfigdescrlock[] = "\n" "Please pay attention that UFS provisioning is irreversible (OTP) operation unless parameter bConfigDescrLock = 0.\n" @@ -124,6 +124,7 @@ int ufs_load(const char *ufs_file, bool finalize_provisioning) xmlDoc *doc; int retval = 0; struct ufs_body *ufs_body_tmp; + struct ufs_body *ufs_body; if (ufs_common_p) { ux_err("Only one UFS provisioning XML allowed, \"%s\" ignored\n", @@ -169,13 +170,7 @@ int ufs_load(const char *ufs_file, bool finalize_provisioning) } else if (xmlGetProp(node, (xmlChar *)"LUNum")) { ufs_body_tmp = ufs_parse_body(node); if (ufs_body_tmp) { - if (ufs_body_p) { - ufs_body_last->next = ufs_body_tmp; - ufs_body_last = ufs_body_tmp; - } else { - ufs_body_p = ufs_body_tmp; - ufs_body_last = ufs_body_tmp; - } + list_add(&ufs_bodies, &ufs_body_tmp->node); } else { ux_err("invalid UFS body tag found in \"%s\"\n", ufs_file); @@ -210,7 +205,7 @@ int ufs_load(const char *ufs_file, bool finalize_provisioning) xmlFreeDoc(doc); - if (!retval && (!ufs_common_p || !ufs_body_p || !ufs_epilogue_p)) { + if (!retval && (!ufs_common_p || list_empty(&ufs_bodies) || !ufs_epilogue_p)) { ux_err("incomplete UFS provisioning information in \"%s\"\n", ufs_file); retval = -EINVAL; } @@ -219,8 +214,8 @@ int ufs_load(const char *ufs_file, bool finalize_provisioning) if (ufs_common_p) { free(ufs_common_p); } - if (ufs_body_p) { - free(ufs_body_p); + list_for_each_entry_safe(ufs_body, ufs_body_tmp, &ufs_bodies, node) { + free(ufs_body); } if (ufs_epilogue_p) { free(ufs_epilogue_p); @@ -260,7 +255,7 @@ int ufs_provisioning_execute(struct qdl_device *qdl, ret = apply_ufs_common(qdl, ufs_common_p); if (ret) return ret; - for (body = ufs_body_p; body; body = body->next) { + list_for_each_entry(body, &ufs_bodies, node) { ret = apply_ufs_body(qdl, body); if (ret) return ret; @@ -275,7 +270,7 @@ int ufs_provisioning_execute(struct qdl_device *qdl, ret = apply_ufs_common(qdl, ufs_common_p); if (ret) return ret; - for (body = ufs_body_p; body; body = body->next) { + list_for_each_entry(body, &ufs_bodies, node) { ret = apply_ufs_body(qdl, body); if (ret) return ret; diff --git a/ufs.h b/ufs.h index ffbe33c..5c17449 100644 --- a/ufs.h +++ b/ufs.h @@ -6,6 +6,8 @@ #define __UFS_H__ #include +#include "list.h" + struct qdl_device; struct ufs_common { @@ -37,7 +39,7 @@ struct ufs_body { unsigned int wContextCapabilities; const char *desc; - struct ufs_body *next; + struct list_head node; }; struct ufs_epilogue {