From 4d145f26dd06d9de0c2da3ff2c1f8be1ac9dbd2b Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Fri, 11 Dec 2020 19:56:47 +0100 Subject: bootcount: allow to use this feature on TPL This commit add an option TPL_BOOTCOUNT_LIMIT to use bootcount on TPL. Signed-off-by: Philippe Reynes Reviewed-by: Simon Glass --- include/bootcount.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/bootcount.h b/include/bootcount.h index cd304039849..b1d1fe53d1a 100644 --- a/include/bootcount.h +++ b/include/bootcount.h @@ -69,7 +69,7 @@ void bootcount_store(ulong); */ ulong bootcount_load(void); -#if defined(CONFIG_SPL_BOOTCOUNT_LIMIT) || defined(CONFIG_BOOTCOUNT_LIMIT) +#if defined(CONFIG_SPL_BOOTCOUNT_LIMIT) || defined(CONFIG_TPL_BOOTCOUNT_LIMIT) || defined(CONFIG_BOOTCOUNT_LIMIT) #if !defined(CONFIG_SYS_BOOTCOUNT_LE) && !defined(CONFIG_SYS_BOOTCOUNT_BE) # if __BYTE_ORDER == __LITTLE_ENDIAN @@ -130,7 +130,7 @@ static inline void bootcount_inc(void) #ifndef CONFIG_SPL_BUILD /* Only increment bootcount when no bootcount support in SPL */ -#ifndef CONFIG_SPL_BOOTCOUNT_LIMIT +#if !defined(CONFIG_SPL_BOOTCOUNT_LIMIT) && !defined(CONFIG_TPL_BOOTCOUNT_LIMIT) bootcount_store(++bootcount); #endif env_set_ulong("bootcount", bootcount); @@ -140,5 +140,5 @@ static inline void bootcount_inc(void) #else static inline int bootcount_error(void) { return 0; } static inline void bootcount_inc(void) {} -#endif /* CONFIG_SPL_BOOTCOUNT_LIMIT || CONFIG_BOOTCOUNT_LIMIT */ +#endif /* CONFIG_SPL_BOOTCOUNT_LIMIT || CONFIG_TPL_BOOTCOUNT_LIMIT || CONFIG_BOOTCOUNT_LIMIT */ #endif /* _BOOTCOUNT_H__ */ -- cgit v1.3.1 From b7cfe32e186d453001a12ee0ee2c85d08a0ecd53 Mon Sep 17 00:00:00 2001 From: Volodymyr Babchuk Date: Tue, 5 Jan 2021 20:03:11 +0000 Subject: smccc: fix sign bit expansion Signed ARM_SMCCC_FAST_CALL value is shifted to 31'st bit. Then, it is expanded to 64 bit value, which results in 1s in higher 32 bits. This causes corrupted values in 64-bit SMC IDs and issues in buggy handlers of 32-bit calls. We need to make ARM_SMCCC_FAST_CALL unsigned long, so it would work properly on 32 bit architectures. Signed-off-by: Volodymyr Babchuk Reviewed-by: Jens Wiklander --- include/linux/arm-smccc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index 2d1e6cc1564..7f2be233947 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -11,8 +11,8 @@ * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html */ -#define ARM_SMCCC_STD_CALL 0 -#define ARM_SMCCC_FAST_CALL 1 +#define ARM_SMCCC_STD_CALL 0UL +#define ARM_SMCCC_FAST_CALL 1UL #define ARM_SMCCC_TYPE_SHIFT 31 #define ARM_SMCCC_SMC_32 0 -- cgit v1.3.1 From 09d9ba9097ceb374f2802506c9e755fd8d5dd861 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:42 -0700 Subject: spl: Add functions for next and previous phase It is useful to be able to figure out which phase we are loading next and which phase we came from. Add some functions to handle this as well as returning the name of a phase. This allows messages like "Booting to x" where x is the next phase. At present, TPL says 'Jumping to U-Boot' at the end, when in fact it is jumping to SPL. This is confusing, so use the new functions to correct this. Tests for this will come with an upcoming minor SPL test refactor. Signed-off-by: Simon Glass --- common/spl/spl.c | 2 +- include/spl.h | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/common/spl/spl.c b/common/spl/spl.c index 8b7374487d3..8cb6f3d531f 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -734,7 +734,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2) debug("Failed to stash bootstage: err=%d\n", ret); #endif - debug("loaded - jumping to U-Boot...\n"); + debug("loaded - jumping to %s...\n", spl_phase_name(spl_next_phase())); spl_board_prepare_for_boot(); jump_to_image_no_args(&spl_image); } diff --git a/include/spl.h b/include/spl.h index a7648787b74..faffeb519ac 100644 --- a/include/spl.h +++ b/include/spl.h @@ -58,6 +58,7 @@ static inline bool u_boot_first_phase(void) } enum u_boot_phase { + PHASE_NONE, /* Invalid phase, signifying before U-Boot */ PHASE_TPL, /* Running in TPL */ PHASE_SPL, /* Running in SPL */ PHASE_BOARD_F, /* Running in U-Boot before relocation */ @@ -123,6 +124,58 @@ static inline enum u_boot_phase spl_phase(void) #endif } +/** + * spl_prev_phase() - Figure out the previous U-Boot phase + * + * @return the previous phase from this one, e.g. if called in SPL this returns + * PHASE_TPL, if TPL is enabled + */ +static inline enum u_boot_phase spl_prev_phase(void) +{ +#ifdef CONFIG_TPL_BUILD + return PHASE_NONE; +#elif defined(CONFIG_SPL_BUILD) + return IS_ENABLED(CONFIG_TPL) ? PHASE_TPL : PHASE_NONE; +#else + return IS_ENABLED(CONFIG_SPL) ? PHASE_SPL : PHASE_NONE; +#endif +} + +/** + * spl_next_phase() - Figure out the next U-Boot phase + * + * @return the next phase from this one, e.g. if called in TPL this returns + * PHASE_SPL + */ +static inline enum u_boot_phase spl_next_phase(void) +{ +#ifdef CONFIG_TPL_BUILD + return PHASE_SPL; +#else + return PHASE_BOARD_F; +#endif +} + +/** + * spl_phase_name() - Get the name of the current phase + * + * @return phase name + */ +static inline const char *spl_phase_name(enum u_boot_phase phase) +{ + switch (phase) { + case PHASE_TPL: + return "TPL"; + case PHASE_SPL: + return "SPL"; + case PHASE_BOARD_F: + case PHASE_BOARD_R: + return "U-Boot"; + default: + return "phase?"; + } +} + /* A string name for SPL or TPL */ #ifdef CONFIG_SPL_BUILD # ifdef CONFIG_TPL_BUILD -- cgit v1.3.1 From 9fe064646d2c9f3914cd5ceae51c34020aa77599 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:43 -0700 Subject: bloblist: Support relocating to a larger space Typically in TPL/SPL the bloblist is quite small. But U-Boot proper may want to add a lot more to it, such as ACPI tables. Add a way to expand the bloblist by relocating it in U-Boot proper, along with the other relocation activities. Signed-off-by: Simon Glass --- common/Kconfig | 10 ++++++++++ common/bloblist.c | 11 +++++++++++ common/board_f.c | 10 ++++++---- include/bloblist.h | 10 ++++++++++ test/bloblist.c | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/common/Kconfig b/common/Kconfig index d8982ba3776..45535e3501d 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -697,6 +697,16 @@ config BLOBLIST_ADDR Sets the address of the bloblist, set up by the first part of U-Boot which runs. Subsequent U-Boot stages typically use the same address. +config BLOBLIST_SIZE_RELOC + hex "Size of bloblist after relocation" + depends on BLOBLIST + default BLOBLIST_SIZE + help + Sets the size of the bloblist in bytes after relocation. Since U-Boot + has a lot more memory available then, it is possible to use a larger + size than the one set up by SPL. This bloblist is set up during the + relocation process. + endmenu source "common/spl/Kconfig" diff --git a/common/bloblist.c b/common/bloblist.c index 33b58623807..e32f551e27e 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -317,6 +317,15 @@ void bloblist_show_list(void) } } +void bloblist_reloc(void *to, uint to_size, void *from, uint from_size) +{ + struct bloblist_hdr *hdr; + + memcpy(to, from, from_size); + hdr = to; + hdr->size = to_size; +} + int bloblist_init(void) { bool expected; @@ -327,6 +336,8 @@ int bloblist_init(void) * that runs */ expected = !u_boot_first_phase(); + if (spl_prev_phase() == PHASE_TPL && !IS_ENABLED(CONFIG_TPL_BLOBLIST)) + expected = false; if (expected) ret = bloblist_check(CONFIG_BLOBLIST_ADDR, CONFIG_BLOBLIST_SIZE); diff --git a/common/board_f.c b/common/board_f.c index ae3001bed1b..4327a43a33b 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -568,9 +568,10 @@ static int reserve_bloblist(void) { #ifdef CONFIG_BLOBLIST /* Align to a 4KB boundary for easier reading of addresses */ - gd->start_addr_sp = ALIGN_DOWN(gd->start_addr_sp - CONFIG_BLOBLIST_SIZE, - 0x1000); - gd->new_bloblist = map_sysmem(gd->start_addr_sp, CONFIG_BLOBLIST_SIZE); + gd->start_addr_sp = ALIGN_DOWN(gd->start_addr_sp - + CONFIG_BLOBLIST_SIZE_RELOC, 0x1000); + gd->new_bloblist = map_sysmem(gd->start_addr_sp, + CONFIG_BLOBLIST_SIZE_RELOC); #endif return 0; @@ -658,7 +659,8 @@ static int reloc_bloblist(void) debug("Copying bloblist from %p to %p, size %x\n", gd->bloblist, gd->new_bloblist, size); - memcpy(gd->new_bloblist, gd->bloblist, size); + bloblist_reloc(gd->new_bloblist, CONFIG_BLOBLIST_SIZE_RELOC, + gd->bloblist, size); gd->bloblist = gd->new_bloblist; } #endif diff --git a/include/bloblist.h b/include/bloblist.h index 8cdce61187a..964b974fdaf 100644 --- a/include/bloblist.h +++ b/include/bloblist.h @@ -242,6 +242,16 @@ void bloblist_show_list(void); */ const char *bloblist_tag_name(enum bloblist_tag_t tag); +/** + * bloblist_reloc() - Relocate the bloblist and optionally resize it + * + * @to: Pointer to new bloblist location (must not overlap old location) + * @to:size: New size for bloblist (must be larger than from_size) + * @from: Pointer to bloblist to relocate + * @from_size: Size of bloblist to relocate + */ +void bloblist_reloc(void *to, uint to_size, void *from, uint from_size); + /** * bloblist_init() - Init the bloblist system with a single bloblist * diff --git a/test/bloblist.c b/test/bloblist.c index 900299dd68e..85a6c39680e 100644 --- a/test/bloblist.c +++ b/test/bloblist.c @@ -347,6 +347,42 @@ static int bloblist_test_align(struct unit_test_state *uts) } BLOBLIST_TEST(bloblist_test_align, 0); +/* Test relocation of a bloblist */ +static int bloblist_test_reloc(struct unit_test_state *uts) +{ + const uint large_size = TEST_BLOBLIST_SIZE; + const uint small_size = 0x20; + void *old_ptr, *new_ptr; + void *blob1, *blob2; + ulong new_addr; + ulong new_size; + + ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); + old_ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); + + /* Add one blob and then one that won't fit */ + blob1 = bloblist_add(TEST_TAG, small_size, 0); + ut_assertnonnull(blob1); + blob2 = bloblist_add(TEST_TAG2, large_size, 0); + ut_assertnull(blob2); + + /* Relocate the bloblist somewhere else, a bit larger */ + new_addr = TEST_ADDR + TEST_BLOBLIST_SIZE; + new_size = TEST_BLOBLIST_SIZE + 0x100; + new_ptr = map_sysmem(new_addr, TEST_BLOBLIST_SIZE); + bloblist_reloc(new_ptr, new_size, old_ptr, TEST_BLOBLIST_SIZE); + gd->bloblist = new_ptr; + + /* Check the old blob is there and that we can now add the bigger one */ + ut_assertnonnull(bloblist_find(TEST_TAG, small_size)); + ut_assertnull(bloblist_find(TEST_TAG2, small_size)); + blob2 = bloblist_add(TEST_TAG2, large_size, 0); + ut_assertnonnull(blob2); + + return 0; +} +BLOBLIST_TEST(bloblist_test_reloc, 0); + int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { -- cgit v1.3.1 From 7d70116fc752a2b97a67ee839be16239074614ce Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:46 -0700 Subject: video: Allow syncing the entire framebuffer to the copy In some cases so much of the framebuffer is updated that it is not worth copying the changes piece by piece to the copy framebuffer. Add a function to copy the whole thing. Signed-off-by: Simon Glass --- drivers/video/video-uclass.c | 10 ++++++++++ include/video.h | 14 ++++++++++++++ 2 files changed, 24 insertions(+) (limited to 'include') diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index a1d527529ff..91d078a9d5f 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -290,6 +290,16 @@ int video_sync_copy(struct udevice *dev, void *from, void *to) return 0; } + +int video_sync_copy_all(struct udevice *dev) +{ + struct video_priv *priv = dev_get_uclass_priv(dev); + + video_sync_copy(dev, priv->fb, priv->fb + priv->fb_size); + + return 0; +} + #endif /* Set up the colour map */ diff --git a/include/video.h b/include/video.h index 74d822fadbb..827733305e8 100644 --- a/include/video.h +++ b/include/video.h @@ -246,11 +246,25 @@ void video_set_default_colors(struct udevice *dev, bool invert); * frame buffer start */ int video_sync_copy(struct udevice *dev, void *from, void *to); + +/** + * video_sync_copy_all() - Sync the entire framebuffer to the copy + * + * @dev: Vidconsole device being updated + * @return 0 (always) + */ +int video_sync_copy_all(struct udevice *dev); #else static inline int video_sync_copy(struct udevice *dev, void *from, void *to) { return 0; } + +static inline int video_sync_copy_all(struct udevice *dev) +{ + return 0; +} + #endif #ifndef CONFIG_DM_VIDEO -- cgit v1.3.1 From f8a2d191cf3a200c080fbf6f8e095589d3afd57f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:51 -0700 Subject: uuid: Add a comment for UUID_STR_LEN This macro is the length of the string but excludes the terminator. Users must add 1 when declaring a large-enough string. Add a comment to make this clear. Signed-off-by: Simon Glass --- include/uuid.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/uuid.h b/include/uuid.h index 0c653cb0874..4a4883d3b5b 100644 --- a/include/uuid.h +++ b/include/uuid.h @@ -23,6 +23,7 @@ struct uuid { #define UUID_STR_FORMAT_GUID BIT(0) #define UUID_STR_UPPER_CASE BIT(1) +/* Use UUID_STR_LEN + 1 for string space */ #define UUID_STR_LEN 36 #define UUID_BIN_LEN sizeof(struct uuid) -- cgit v1.3.1 From 1e35a4d2282329093ae384bfbb8df844e23798c6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 13 Jan 2021 20:29:57 -0700 Subject: binman: Allow reading entries from a subnode Some images may have multiple copies of the same thing, e.g. two versions of the read/write U-Boots. It is necessary to read data from one or other of these under selection of the verified-boot logic. Add a function to select the subnode to use. Signed-off-by: Simon Glass --- include/binman.h | 14 ++++++++++++++ lib/binman.c | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) (limited to 'include') diff --git a/include/binman.h b/include/binman.h index 8b89a9666d5..5958dfb4485 100644 --- a/include/binman.h +++ b/include/binman.h @@ -70,6 +70,20 @@ int binman_entry_find(const char *name, struct binman_entry *entry); */ ofnode binman_section_find_node(const char *name); +/** + * binman_select_subnode() - Select a subnode to use to find entries + * + * Normally binman selects the top-level node for future entry requests, such as + * binman_entry_find(). This function allows a subnode to be chosen instead. + * + * @name: Name of subnode, typically a section. This must be in the top-level + * binman node + * @return 0 if OK, -EINVAL if there is no /binman node, -ECHILD if multiple + * images are being used but the first image is not available, -ENOENT if + * the requested subnode cannot be found + */ +int binman_select_subnode(const char *name); + /** * binman_init() - Set up the binman symbol information * diff --git a/lib/binman.c b/lib/binman.c index b6d9dff5b7c..f415df30545 100644 --- a/lib/binman.c +++ b/lib/binman.c @@ -116,6 +116,24 @@ int binman_get_rom_offset(void) return binman->rom_offset; } +int binman_select_subnode(const char *name) +{ + ofnode node; + int ret; + + ret = find_image_node(&node); + if (ret) + return log_msg_ret("main", -ENOENT); + node = ofnode_find_subnode(node, name); + if (!ofnode_valid(node)) + return log_msg_ret("node", -ENOENT); + binman->image = node; + log_debug("binman: Selected image subnode '%s'\n", + ofnode_get_name(binman->image)); + + return 0; +} + int binman_init(void) { int ret; -- cgit v1.3.1