From 53a4f253f129926bb5398634c8bae43ab788342d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:47 -0600 Subject: bootstage: Store the next ID in the stash When stashing bootstage info, store the next ID so that it can be used when the stash is restored. This avoids the ID starting at zero and potentially overwriting existing entries. Signed-off-by: Simon Glass --- common/bootstage.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'common/bootstage.c') diff --git a/common/bootstage.c b/common/bootstage.c index 56ef91ad859..257dc5d402f 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -41,10 +41,11 @@ enum { }; struct bootstage_hdr { - uint32_t version; /* BOOTSTAGE_VERSION */ - uint32_t count; /* Number of records */ - uint32_t size; /* Total data size (non-zero if valid) */ - uint32_t magic; /* Unused */ + u32 version; /* BOOTSTAGE_VERSION */ + u32 count; /* Number of records */ + u32 size; /* Total data size (non-zero if valid) */ + u32 magic; /* Magic number */ + u32 next_id; /* Next ID to use for bootstage */ }; int bootstage_relocate(void) @@ -392,6 +393,7 @@ int bootstage_stash(void *base, int size) hdr->count = count; hdr->size = 0; hdr->magic = BOOTSTAGE_MAGIC; + hdr->next_id = data->next_id; ptr += sizeof(*hdr); /* Write the records, silently stopping when we run out of space */ @@ -485,6 +487,7 @@ int bootstage_unstash(const void *base, int size) /* Mark the records as read */ data->rec_count += hdr->count; + data->next_id = hdr->next_id; debug("Unstashed %d records\n", hdr->count); return 0; -- cgit v1.2.3 From ed54bdaf88758854905b5d8ca5036a078b9ef168 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:48 -0600 Subject: bootstage: Fix counting of entries in stash The current code searches for empty records but these not existing with bootstage now. This used to be needed when bootstage records were stored in a spare array. Drop the unnecessary code and fix a code-style nit at the same time. Signed-off-by: Simon Glass --- common/bootstage.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'common/bootstage.c') diff --git a/common/bootstage.c b/common/bootstage.c index 257dc5d402f..fe36bac0474 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -373,7 +373,6 @@ int bootstage_stash(void *base, int size) const struct bootstage_record *rec; char buf[20]; char *ptr = base, *end = ptr + size; - uint32_t count; int i; if (hdr + 1 > (struct bootstage_hdr *)end) { @@ -384,22 +383,15 @@ int bootstage_stash(void *base, int size) /* Write an arbitrary version number */ hdr->version = BOOTSTAGE_VERSION; - /* Count the number of records, and write that value first */ - for (rec = data->record, i = count = 0; i < data->rec_count; - i++, rec++) { - if (rec->id != 0) - count++; - } - hdr->count = count; + hdr->count = data->rec_count; hdr->size = 0; hdr->magic = BOOTSTAGE_MAGIC; hdr->next_id = data->next_id; ptr += sizeof(*hdr); /* Write the records, silently stopping when we run out of space */ - for (rec = data->record, i = 0; i < data->rec_count; i++, rec++) { + for (rec = data->record, i = 0; i < data->rec_count; i++, rec++) append_data(&ptr, end, rec, sizeof(*rec)); - } /* Write the name strings */ for (rec = data->record, i = 0; i < data->rec_count; i++, rec++) { -- cgit v1.2.3 From 65b2d96f4c5e3f9084bc04cf5a5d7fc7a2285a72 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:49 -0600 Subject: bootstage: Avoid conflicts between stash/unstash At present there is a single shared address for bootstage data in both TPL and SPL. If SPL unstashs TPL bootstage info and then stashes it again to pass it to U-Boot, the new stash overwrites the strings of the old stash. Fix this by duplicating the strings into the malloc() region. This should be a small code. Fix the header-file order at the same time. This problem doesn't happen at the next stage (SPL->U-Boot) since U-Boot relocates the boostage data. Signed-off-by: Simon Glass --- common/bootstage.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'common/bootstage.c') diff --git a/common/bootstage.c b/common/bootstage.c index fe36bac0474..4557ed4508c 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -10,9 +10,10 @@ */ #include -#include #include +#include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -472,6 +473,8 @@ int bootstage_unstash(const void *base, int size) for (rec = data->record + data->next_id, i = 0; i < hdr->count; i++, rec++) { rec->name = ptr; + if (spl_phase() == PHASE_SPL) + rec->name = strdup(ptr); /* Assume no data corruption here */ ptr += strlen(ptr) + 1; -- cgit v1.2.3 From ac9cd4805c8b11f529b508921c2275b889265313 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:50 -0600 Subject: 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 --- common/bootstage.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'common/bootstage.c') diff --git a/common/bootstage.c b/common/bootstage.c index 4557ed4508c..e8b7bbf81a6 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -53,14 +53,23 @@ int bootstage_relocate(void) { 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_unstash(const void *base, int size) 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) -- cgit v1.2.3