summaryrefslogtreecommitdiffstats
path: root/layout.c
diff options
context:
space:
mode:
authorDaniel Campello <campello@chromium.org>2021-04-13 10:47:25 -0600
committerEdward O'Callaghan <quasisec@chromium.org>2021-04-27 23:41:53 +0000
commit45d50a101e8073191e6d88143990ed91d3bfe815 (patch)
treeae1493908fd9a015e09283c8af9609917a59288d /layout.c
parent3f19ba95f1ea2fbd83f96fe9aa3ee78651e33899 (diff)
downloadflashrom-45d50a101e8073191e6d88143990ed91d3bfe815.tar.gz
flashrom-45d50a101e8073191e6d88143990ed91d3bfe815.tar.bz2
flashrom-45d50a101e8073191e6d88143990ed91d3bfe815.zip
layout: Add -i <region>[:<file>] support
Add an optional sub-parameter to the -i parameter to allow building the image to be written from multiple files. This will also allow regions to be read from flash and written to separate image files. This is a rebase of a patch that was ported from chromiumos. A lot of things have changed, but the idea is the same. Original patch by Louis Yung-Chieh Lo <yjlou@chromium.org>: Summary: Support -i partition:file feature for both read and write. Commit: 9c7525f Review URL: http://codereview.chromium.org/6611015 Ported version by Stefan Tauner <stefan.tauner@student.tuwien.ac.at> and Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>: Summary: [PATCH 2/6] layout: Add -i <region>[:<file>] support. Review URL: https://mail.coreboot.org/pipermail/flashrom/2013-October/011729.html Change-Id: Ic5465659605d8431d931053967b40290195cfd99 Signed-off-by: David Hendricks <dhendrix@chromium.org> Signed-off-by: Stefan Tauner <stefan.tauner@student.tuwien.ac.at> Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> Signed-off-by: Nico Huber <nico.huber@secunet.com> Signed-off-by: Edward O'Callaghan <quasisec@google.com> Signed-off-by: Daniel Campello <campello@chromium.org> Co-Authored-by: Edward O'Callaghan <quasisec@google.com> Co-Authored-by: Daniel Campello <campello@chromium.org> Reviewed-on: https://review.coreboot.org/c/flashrom/+/23021 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Sam McNally <sammc@google.com> Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Diffstat (limited to 'layout.c')
-rw-r--r--layout.c116
1 files changed, 92 insertions, 24 deletions
diff --git a/layout.c b/layout.c
index 272912c68..d0d2607e1 100644
--- a/layout.c
+++ b/layout.c
@@ -52,7 +52,7 @@ int read_romlayout(const char *name)
romlayout = fopen(name, "r");
if (!romlayout) {
- msg_gerr("ERROR: Could not open ROM layout (%s).\n",
+ msg_gerr("ERROR: Could not open layout file (%s).\n",
name);
return -1;
}
@@ -82,6 +82,7 @@ int read_romlayout(const char *name)
layout->entries[layout->num_entries].start = strtol(tstr1, (char **)NULL, 16);
layout->entries[layout->num_entries].end = strtol(tstr2, (char **)NULL, 16);
layout->entries[layout->num_entries].included = false;
+ layout->entries[layout->num_entries].file = NULL;
layout->entries[layout->num_entries].name = strdup(tempname);
if (!layout->entries[layout->num_entries].name) {
msg_gerr("Error adding layout entry: %s\n", strerror(errno));
@@ -105,44 +106,76 @@ _close_ret:
#endif
/* register an include argument (-i) for later processing */
-int register_include_arg(struct layout_include_args **args, char *name)
+int register_include_arg(struct layout_include_args **args, const char *arg)
{
struct layout_include_args *tmp;
- if (name == NULL) {
+ char *colon;
+ char *name;
+ char *file;
+
+ if (arg == NULL) {
msg_gerr("<NULL> is a bad region name.\n");
return 1;
}
- tmp = *args;
- while (tmp) {
+ /* -i <image>[:<file>] */
+ colon = strchr(arg, ':');
+ if (colon && !colon[1]) {
+ msg_gerr("Missing filename parameter in %s\n", arg);
+ return 1;
+ }
+ name = colon ? strndup(arg, colon - arg) : strdup(arg);
+ file = colon ? strdup(colon + 1) : NULL;
+
+ for (tmp = *args; tmp; tmp = tmp->next) {
if (!strcmp(tmp->name, name)) {
msg_gerr("Duplicate region name: \"%s\".\n", name);
- return 1;
+ goto error;
}
- tmp = tmp->next;
}
tmp = malloc(sizeof(struct layout_include_args));
if (tmp == NULL) {
msg_gerr("Could not allocate memory");
- return 1;
+ goto error;
}
tmp->name = name;
+ tmp->file = file;
tmp->next = *args;
*args = tmp;
-
return 0;
+
+error:
+ free(name);
+ free(file);
+ return 1;
+}
+
+/* returns 0 to indicate success, 1 to indicate failure */
+static int include_region(struct flashrom_layout *const l, const char *name,
+ const char *file)
+{
+ size_t i;
+ for (i = 0; i < l->num_entries; ++i) {
+ if (!strcmp(l->entries[i].name, name)) {
+ l->entries[i].included = true;
+ if (file)
+ l->entries[i].file = strdup(file);
+ return 0;
+ }
+ }
+ return 1;
}
/* returns -1 if an entry is not found, 0 if found. */
-static int find_romentry(struct flashrom_layout *const l, char *name)
+static int find_romentry(struct flashrom_layout *const l, char *name, char *file)
{
if (l->num_entries == 0)
return -1;
msg_gspew("Looking for region \"%s\"... ", name);
- if (flashrom_layout_include_region(l, name)) {
+ if (include_region(l, name, file)) {
msg_gspew("not found.\n");
return -1;
}
@@ -161,7 +194,7 @@ int process_include_args(struct flashrom_layout *l, const struct layout_include_
if (args == NULL)
return 0;
- /* User has specified an area, but no layout file is loaded. */
+ /* User has specified an include argument, but no layout is loaded. */
if (l->num_entries == 0) {
msg_gerr("Region requested (with -i \"%s\"), "
"but no layout data is available.\n",
@@ -171,7 +204,7 @@ int process_include_args(struct flashrom_layout *l, const struct layout_include_
tmp = args;
while (tmp) {
- if (find_romentry(l, tmp->name) < 0) {
+ if (find_romentry(l, tmp->name, tmp->file) < 0) {
msg_gerr("Invalid region specified: \"%s\".\n",
tmp->name);
return 1;
@@ -180,10 +213,14 @@ int process_include_args(struct flashrom_layout *l, const struct layout_include_
found++;
}
- msg_ginfo("Using region%s:", found > 1 ? "s" : "");
+ msg_ginfo("Using region%s: ", found > 1 ? "s" : "");
tmp = args;
while (tmp) {
- msg_ginfo(" \"%s\"%s", tmp->name, found > 1 ? "," : "");
+ msg_ginfo("\"%s\"", tmp->name);
+ if (tmp->file)
+ msg_ginfo(":\"%s\"", tmp->file);
+ if (found > 1)
+ msg_ginfo(", ");
found--;
tmp = tmp->next;
}
@@ -191,6 +228,39 @@ int process_include_args(struct flashrom_layout *l, const struct layout_include_
return 0;
}
+/* returns boolean 1 if any regions overlap, 0 otherwise */
+int included_regions_overlap(const struct flashrom_layout *const l)
+{
+ size_t i;
+ int overlap_detected = 0;
+
+ for (i = 0; i < l->num_entries; i++) {
+ size_t j;
+
+ if (!l->entries[i].included)
+ continue;
+
+ for (j = i + 1; j < l->num_entries; j++) {
+ if (!l->entries[j].included)
+ continue;
+
+ if (l->entries[i].start > l->entries[j].end)
+ continue;
+
+ if (l->entries[i].end < l->entries[j].start)
+ continue;
+
+ msg_gdbg("Regions %s [0x%08x-0x%08x] and "
+ "%s [0x%08x-0x%08x] overlap\n",
+ l->entries[i].name, l->entries[i].start,
+ l->entries[i].end, l->entries[j].name,
+ l->entries[j].start, l->entries[j].end);
+ overlap_detected = 1;
+ }
+ }
+ return overlap_detected;
+}
+
void layout_cleanup(struct layout_include_args **args)
{
struct flashrom_layout *const layout = get_global_layout();
@@ -199,12 +269,15 @@ void layout_cleanup(struct layout_include_args **args)
while (*args) {
tmp = (*args)->next;
+ free((*args)->name);
+ free((*args)->file);
free(*args);
*args = tmp;
}
for (i = 0; i < layout->num_entries; i++) {
free(layout->entries[i].name);
+ free(layout->entries[i].file);
layout->entries[i].included = false;
}
layout->num_entries = 0;
@@ -287,14 +360,7 @@ const struct romentry *layout_next_included(
*/
int flashrom_layout_include_region(struct flashrom_layout *const layout, const char *name)
{
- size_t i;
- for (i = 0; i < layout->num_entries; ++i) {
- if (!strcmp(layout->entries[i].name, name)) {
- layout->entries[i].included = true;
- return 0;
- }
- }
- return 1;
+ return include_region(layout, name, NULL);
}
/**
@@ -309,8 +375,10 @@ void flashrom_layout_release(struct flashrom_layout *const layout)
if (!layout || layout == get_global_layout())
return;
- for (i = 0; i < layout->num_entries; ++i)
+ for (i = 0; i < layout->num_entries; ++i) {
free(layout->entries[i].name);
+ free(layout->entries[i].file);
+ }
free(layout);
}