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 <bjorn.andersson@oss.qualcomm.com>
This commit is contained in:
Bjorn Andersson
2025-08-28 11:26:11 -05:00
committed by Bjorn Andersson
parent 6a67b6bd64
commit ce175f2e27
9 changed files with 123 additions and 99 deletions

73
list.h Normal file
View File

@@ -0,0 +1,73 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/*
* Copyright (c) 2016, Linaro Ltd.
*/
#ifndef __LIST_H__
#define __LIST_H__
#include <stdbool.h>
#include <stddef.h>
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

22
patch.c
View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -5,7 +5,7 @@
#include <sys/types.h>
#include <stdbool.h>
#include <stdint.h>
#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));

24
read.c
View File

@@ -11,13 +11,13 @@
#include <libxml/parser.h>
#include <libxml/tree.h>
#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;

5
read.h
View File

@@ -4,6 +4,8 @@
#include <stdbool.h>
#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);

23
ufs.c
View File

@@ -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;

4
ufs.h
View File

@@ -6,6 +6,8 @@
#define __UFS_H__
#include <stdbool.h>
#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 {