From 5074a8a3c0d0d1e11a1d51a7fb0ce8746668046f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:46 -0600 Subject: bloblist: Reserve an aligned base Make sure that the bloblist starts on an aligned boundary. This protects against one of the early allocating causing the alignment to be lost. Signed-off-by: Simon Glass --- common/board_f.c | 1 + 1 file changed, 1 insertion(+) (limited to 'common') diff --git a/common/board_f.c b/common/board_f.c index 591f18f391..4852a3b0d8 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -588,6 +588,7 @@ static int reserve_stacks(void) static int reserve_bloblist(void) { #ifdef CONFIG_BLOBLIST + gd->start_addr_sp &= ~0xf; gd->start_addr_sp -= CONFIG_BLOBLIST_SIZE; gd->new_bloblist = map_sysmem(gd->start_addr_sp, CONFIG_BLOBLIST_SIZE); #endif -- cgit v1.2.3 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') diff --git a/common/bootstage.c b/common/bootstage.c index 56ef91ad85..257dc5d402 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') diff --git a/common/bootstage.c b/common/bootstage.c index 257dc5d402..fe36bac047 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') diff --git a/common/bootstage.c b/common/bootstage.c index fe36bac047..4557ed4508 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/board_f.c | 1 + common/board_r.c | 1 - common/bootstage.c | 25 ++++++++++++++++++++++--- 3 files changed, 23 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/board_f.c b/common/board_f.c index 4852a3b0d8..e3591cbaeb 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -696,6 +696,7 @@ static int reloc_bootstage(void) 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 d6fb5047a2..c1ecb06b74 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -670,7 +670,6 @@ static init_fnc_t init_sequence_r[] = { #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 4557ed4508..e8b7bbf81a 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 From 5256beecb8a14efba805a2f3f14afb33752ac71a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:51 -0600 Subject: bootstage: Mark the start/end of TPL and SPL separately At present bootstage in TPL and SPL use the same ID so it is not possible to see the timing of each. Separate out the IDs and use the correct one depending on which phase we are at. Example output: Timer summary in microseconds (14 records): Mark Elapsed Stage 0 0 reset 224,787 224,787 TPL 282,248 57,461 end TPL 341,067 58,819 SPL 925,436 584,369 end SPL 931,710 6,274 board_init_f 1,035,482 103,772 board_init_r 1,387,852 352,370 main_loop 1,387,911 59 id=175 Accumulated time: 196 dm_r 8,300 dm_spl 14,139 dm_f 229,121 fsp-m 262,992 fsp-s Signed-off-by: Simon Glass --- common/spl/spl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/spl/spl.c b/common/spl/spl.c index a9d3e847af..eabb1fbc13 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -402,7 +402,8 @@ static int spl_common_init(bool setup_malloc) ret); return ret; } - bootstage_mark_name(BOOTSTAGE_ID_START_SPL, "spl"); + bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_START_TPL : + BOOTSTAGE_ID_START_SPL, SPL_TPL_NAME); #if CONFIG_IS_ENABLED(LOG) ret = log_init(); if (ret) { @@ -418,7 +419,8 @@ static int spl_common_init(bool setup_malloc) } } if (CONFIG_IS_ENABLED(DM)) { - bootstage_start(BOOTSTATE_ID_ACCUM_DM_SPL, "dm_spl"); + bootstage_start(BOOTSTATE_ID_ACCUM_DM_SPL, + spl_phase() == PHASE_TPL ? "dm tpl" : "dm_spl"); /* With CONFIG_SPL_OF_PLATDATA, bring in all devices */ ret = dm_init_and_scan(!CONFIG_IS_ENABLED(OF_PLATDATA)); bootstage_accum(BOOTSTATE_ID_ACCUM_DM_SPL); @@ -704,8 +706,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2) debug("SPL malloc() used 0x%lx bytes (%ld KB)\n", gd->malloc_ptr, gd->malloc_ptr / 1024); #endif + bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_END_TPL : + BOOTSTAGE_ID_END_SPL, "end " SPL_TPL_NAME); #ifdef CONFIG_BOOTSTAGE_STASH - bootstage_mark_name(BOOTSTAGE_ID_END_SPL, "end_spl"); ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR, CONFIG_BOOTSTAGE_STASH_SIZE); if (ret) -- cgit v1.2.3 From 31f9f0ea571c12e914eda400b242d4a0a4b39f43 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:52 -0600 Subject: bootstage: Allow SPL to obtain bootstage info from TPL It is possible to enable bootstage in TPL. TPL can stash the info for SPL. But at present this information is then lost because SPL does not read from the stash. Add support for SPL not being the first phase to enable bootstage. Signed-off-by: Simon Glass --- common/spl/spl.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'common') diff --git a/common/spl/spl.c b/common/spl/spl.c index eabb1fbc13..f1ad8dc9da 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -396,12 +397,23 @@ static int spl_common_init(bool setup_malloc) gd->malloc_ptr = 0; } #endif - ret = bootstage_init(true); + ret = bootstage_init(u_boot_first_phase()); if (ret) { debug("%s: Failed to set up bootstage: ret=%d\n", __func__, ret); return ret; } +#ifdef CONFIG_BOOTSTAGE_STASH + if (!u_boot_first_phase()) { + const void *stash = map_sysmem(CONFIG_BOOTSTAGE_STASH_ADDR, + CONFIG_BOOTSTAGE_STASH_SIZE); + + ret = bootstage_unstash(stash, CONFIG_BOOTSTAGE_STASH_SIZE); + if (ret) + debug("%s: Failed to unstash bootstage: ret=%d\n", + __func__, ret); + } +#endif /* CONFIG_BOOTSTAGE_STASH */ bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_START_TPL : BOOTSTAGE_ID_START_SPL, SPL_TPL_NAME); #if CONFIG_IS_ENABLED(LOG) -- cgit v1.2.3 From d60ae4c59df55c08dc96202ff58fed21ab3afb7d Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 10:05:22 +0200 Subject: fdt: Fix alignment issue when reading 64-bits properties from fdt The FDT specification [0] gives a requirement of aligning properties on 32-bits. Make sure that the compiler is aware of this constraint when accessing 64-bits properties. [0]: https://github.com/devicetree-org/devicetree-specification/blob/master/source/flattened-format.rst Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- common/fdt_support.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/fdt_support.c b/common/fdt_support.c index baf7924ff6..6834399039 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -1566,7 +1566,7 @@ static int fdt_read_prop(const fdt32_t *prop, int prop_len, int cell_off, uint64_t *val, int cells) { const fdt32_t *prop32 = &prop[cell_off]; - const fdt64_t *prop64 = (const fdt64_t *)&prop[cell_off]; + const unaligned_fdt64_t *prop64 = (const fdt64_t *)&prop[cell_off]; if ((cell_off + cells) > prop_len) return -FDT_ERR_NOSPACE; -- cgit v1.2.3