bootstage: Correct relocation algorithm
At present bootstage relocation assumes that it is possible to point back
to memory available before relocation, so it does not relocate the
strings. However this is not the case on some platforms, such as x86 which
uses the cache as RAM and loses access to this when the cache is enabled.
Move the relocation step to before U-Boot relocates, expand the allocated
region to include space for the strings and relocate the strings at the
same time as the bootstage records.
This ensures that bootstage data can remain accessible from TPL through
SPL to U-Boot before/after relocation.
Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/common/board_f.c b/common/board_f.c
index 4852a3b..e3591cb 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -696,6 +696,7 @@
gd->bootstage, gd->new_bootstage, size);
memcpy(gd->new_bootstage, gd->bootstage, size);
gd->bootstage = gd->new_bootstage;
+ bootstage_relocate();
}
#endif
diff --git a/common/board_r.c b/common/board_r.c
index d6fb504..c1ecb06 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -670,7 +670,6 @@
#ifdef CONFIG_SYS_NONCACHED_MEMORY
initr_noncached,
#endif
- bootstage_relocate,
#ifdef CONFIG_OF_LIVE
initr_of_live,
#endif
diff --git a/common/bootstage.c b/common/bootstage.c
index 4557ed4..e8b7bbf 100644
--- a/common/bootstage.c
+++ b/common/bootstage.c
@@ -53,14 +53,23 @@
{
struct bootstage_data *data = gd->bootstage;
int i;
+ char *ptr;
+
+ /* Figure out where to relocate the strings to */
+ ptr = (char *)(data + 1);
/*
* Duplicate all strings. They may point to an old location in the
* program .text section that can eventually get trashed.
*/
debug("Relocating %d records\n", data->rec_count);
- for (i = 0; i < data->rec_count; i++)
- data->record[i].name = strdup(data->record[i].name);
+ for (i = 0; i < data->rec_count; i++) {
+ const char *from = data->record[i].name;
+
+ strcpy(ptr, from);
+ data->record[i].name = ptr;
+ ptr += strlen(ptr) + 1;
+ }
return 0;
}
@@ -490,7 +499,17 @@
int bootstage_get_size(void)
{
- return sizeof(struct bootstage_data);
+ struct bootstage_data *data = gd->bootstage;
+ struct bootstage_record *rec;
+ int size;
+ int i;
+
+ size = sizeof(struct bootstage_data);
+ for (rec = data->record, i = 0; i < data->rec_count;
+ i++, rec++)
+ size += strlen(rec->name) + 1;
+
+ return size;
}
int bootstage_init(bool first)