layout: Use linked list for `struct romentry`
This gets rid of the entry limit and hopefully makes future layout
handling easier. We start by making `struct flashrom_layout` private
to `layout.c`.
Change-Id: I60a0aa1007ebcd5eb401db116f835d129b3e9732
Signed-off-by: Nico Huber <nico.h@gmx.de>
Original-Reviewed-on: https://review.coreboot.org/c/flashrom/+/33521
Original-Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Original-Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/flashrom-stable/+/72217
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/layout.c b/layout.c
index 36fa0b6..917853e 100644
--- a/layout.c
+++ b/layout.c
@@ -24,12 +24,17 @@
#include "programmer.h"
#include "layout.h"
-static struct romentry entries[MAX_ROMLAYOUT];
-static struct flashrom_layout global_layout = { entries, MAX_ROMLAYOUT, 0 };
+struct flashrom_layout {
+ struct romentry *head;
+};
+
+static struct flashrom_layout *global_layout;
struct flashrom_layout *get_global_layout(void)
{
- return &global_layout;
+ if (!global_layout)
+ flashrom_layout_new(&global_layout, 0);
+ return global_layout;
}
const struct flashrom_layout *get_default_layout(const struct flashrom_flashctx *const flashctx)
@@ -39,7 +44,7 @@
const struct flashrom_layout *get_layout(const struct flashrom_flashctx *const flashctx)
{
- if (flashctx->layout && flashctx->layout->num_entries)
+ if (flashctx->layout)
return flashctx->layout;
else
return get_default_layout(flashctx);
@@ -48,16 +53,7 @@
static struct romentry *mutable_layout_next(
const struct flashrom_layout *const layout, struct romentry *iterator)
{
- const struct romentry *const end = layout->entries + layout->num_entries;
-
- if (iterator)
- ++iterator;
- else
- iterator = &layout->entries[0];
-
- if (iterator < end)
- return iterator;
- return NULL;
+ return iterator ? iterator->next : layout->head;
}
#ifndef __LIBPAYLOAD__
@@ -79,11 +75,6 @@
while (!feof(romlayout)) {
char *tstr1, *tstr2;
- if (layout->num_entries >= layout->capacity) {
- msg_gerr("Maximum number of ROM images (%zu) in layout "
- "file reached.\n", layout->capacity);
- goto _close_ret;
- }
if (2 != fscanf(romlayout, "%255s %255s\n", tempstr, tempname))
continue;
#if 0
@@ -144,7 +135,7 @@
/* returns -1 if an entry is not found, 0 if found. */
static int find_romentry(struct flashrom_layout *const l, char *name)
{
- if (l->num_entries == 0)
+ if (!l->head)
return -1;
msg_gspew("Looking for region \"%s\"... ", name);
@@ -168,7 +159,7 @@
return 0;
/* User has specified an area, but no layout file is loaded. */
- if (l->num_entries == 0) {
+ if (!l->head) {
msg_gerr("Region requested (with -i \"%s\"), "
"but no layout data is available.\n",
args->name);
@@ -200,7 +191,6 @@
void layout_cleanup(struct layout_include_args **args)
{
struct flashrom_layout *const layout = get_global_layout();
- unsigned int i;
struct layout_include_args *tmp;
while (*args) {
@@ -209,11 +199,8 @@
*args = tmp;
}
- for (i = 0; i < layout->num_entries; i++) {
- free(layout->entries[i].name);
- layout->entries[i].included = false;
- }
- layout->num_entries = 0;
+ global_layout = NULL;
+ flashrom_layout_release(layout);
}
/* Validate and - if needed - normalize layout entries. */
@@ -271,7 +258,7 @@
const struct romentry *layout_next(
const struct flashrom_layout *const layout, const struct romentry *iterator)
{
- return mutable_layout_next(layout, (struct romentry *)iterator);
+ return iterator ? iterator->next : layout->head;
}
/**
@@ -290,17 +277,13 @@
*/
int flashrom_layout_new(struct flashrom_layout **const layout, const unsigned int count)
{
- *layout = malloc(sizeof(**layout) + count * sizeof(struct romentry));
+ *layout = malloc(sizeof(**layout));
if (!*layout) {
msg_gerr("Error creating layout: %s\n", strerror(errno));
return 1;
}
- const struct flashrom_layout tmp = {
- .entries = (void *)((char *)*layout + sizeof(**layout)),
- .capacity = count,
- .num_entries = 0,
- };
+ const struct flashrom_layout tmp = { 0 };
**layout = tmp;
return 0;
}
@@ -314,31 +297,35 @@
* @param name Name of the region.
*
* @return 0 on success,
- * 1 if out of memory,
- * 2 if the layout is full already.
+ * 1 if out of memory.
*/
int flashrom_layout_add_region(
struct flashrom_layout *const layout,
const size_t start, const size_t end, const char *const name)
{
- if (layout->num_entries >= layout->capacity) {
- msg_gerr("Error adding layout entry: No space left\n");
- return 2;
- }
+ struct romentry *const entry = malloc(sizeof(*entry));
+ if (!entry)
+ goto _err_ret;
- struct romentry *const entry = &layout->entries[layout->num_entries];
- entry->start = start;
- entry->end = end;
- entry->included = false;
- entry->name = strdup(name);
- if (!entry->name) {
- msg_gerr("Error adding layout entry: %s\n", strerror(errno));
- return 1;
- }
+ const struct romentry tmp = {
+ .next = layout->head,
+ .start = start,
+ .end = end,
+ .included = false,
+ .name = strdup(name),
+ };
+ *entry = tmp;
+ if (!entry->name)
+ goto _err_ret;
msg_gdbg("Added layout entry %08zx - %08zx named %s\n", start, end, name);
- ++layout->num_entries;
+ layout->head = entry;
return 0;
+
+_err_ret:
+ msg_gerr("Error adding layout entry: %s\n", strerror(errno));
+ free(entry);
+ return 1;
}
/**
@@ -369,13 +356,18 @@
*/
void flashrom_layout_release(struct flashrom_layout *const layout)
{
- unsigned int i;
-
- if (!layout || layout == get_global_layout())
+ if (layout == global_layout)
return;
- for (i = 0; i < layout->num_entries; ++i)
- free(layout->entries[i].name);
+ if (!layout)
+ return;
+
+ while (layout->head) {
+ struct romentry *const entry = layout->head;
+ layout->head = entry->next;
+ free(entry->name);
+ free(entry);
+ }
free(layout);
}