sunxi: Create helper function veryfing valid boot signature on MMC
Subsystems (3)
PATCH v3 1/3 sunxi: Create helper function veryfing valid boot signature on MMC
This patch extracts checking for valid SD card "eGON.BT0" signature from board_mmc_init into function sunxi_mmc_has_egon_boot_signature.
Buffer for mmc sector is allocated and freed at runtime. panic is triggered on malloc failure.
--- arch/arm/include/asm/arch-sunxi/mmc.h | 1 + board/sunxi/board.c | 8 ++------ drivers/mmc/sunxi_mmc.c | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 6 deletions(-)
arch/arm/include/asm/arch-sunxi/mmc.h +1 -0
@@ -127,4 +127,5 @@ struct sunxi_mmc {#define SUNXI_MMC_COMMON_RESET (1 << 18)struct mmc *sunxi_mmc_init (int sdc_no); +int sunxi_mmc_has_egon_boot_signature (struct mmc *mmc);#endif /* _SUNXI_MMC_H */
board/sunxi/board.c +2 -6
@@ -302,12 +302,8 @@ int board_mmc_init(bd_t *bis)* Both mmc0 and mmc2 are bootable, figure out where we're booting * from. Try mmc0 first, just like the brom does. */ -if (mmc_getcd (mmc0) &&mmc_init (mmc0) ==0 && - mmc0->block_dev.block_read (0 ,16 ,1 , buf) ==1 ) { - buf[12 ] =0 ; -if (strcmp (&buf[4 ],"eGON.BT0" ) ==0 ) -return 0 ; - } +if (sunxi_mmc_has_egon_boot_signature (mmc0)) +return 0 ;/* no bootable card in mmc0, so we must be booting from mmc2, swap */ mmc0->block_dev.dev =1 ;
drivers/mmc/sunxi_mmc.c +17 -0
@@ -431,6 +431,23 @@ static int sunxi_mmc_getcd(struct mmc *mmc)return !gpio_get_value (cd_pin); } +int sunxi_mmc_has_egon_boot_signature (struct mmc *mmc) +{ +char *buf =malloc (512 ); +int valid_signature =0 ; + +if (buf ==NULL ) +panic ("Failed to allocate memory\n" ); + +if (mmc_getcd (mmc) &&mmc_init (mmc) ==0 && + mmc->block_dev.block_read (0 ,16 ,1 , buf) ==1 && +strncmp (&buf[4 ],"eGON.BT0" ,8 ) ==0 ) + valid_signature =1 ; + +free (buf); +return valid_signature; +} +static const struct mmc_ops sunxi_mmc_ops = { .send_cmd = sunxi_mmc_send_cmd, .set_ios = sunxi_mmc_set_ios,
Signature · 1 line
2.4.1
PATCH v3 2/3 sunxi/spl: Detect at runtime where from SPL was read
Make possible using single u-boot-sunxi-with-spl.bin binary for both NAND memory and SD card. Detection where SPL was read from is implemented in spl_boot_device.
V2:
- Move signature verification to helper function
- Avoid unnecessary condition nesting
V3:
- Further simplification of conditions
- Move reassigning mmc block.dev numbers from board_mmc_init to spl_boot_device
- If signature wasn't found on mmc0 and SPL_NAND_SUPPORT isn't enabled don't assume mmc2 is a valid boot device - check for egon signature first
--- arch/arm/cpu/armv7/sunxi/board.c | 63 ++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 22 deletions(-)
arch/arm/cpu/armv7/sunxi/board.c +41 -22
@@ -11,6 +11,7 @@*/ #include <common.h> +#include <mmc.h> #include <i2c.h> #include <serial.h> #ifdef CONFIG_SPL_BUILD
@@ -22,6 +23,7 @@#include <asm/arch/gpio.h> #include <asm/arch/sys_proto.h> #include <asm/arch/timer.h> +#include <asm/arch/mmc.h> #include <linux/compiler.h>
@@ -117,26 +119,18 @@ void s_init(void) }#ifdef CONFIG_SPL_BUILD +DECLARE_GLOBAL_DATA_PTR ; +/* The sunxi internal brom will try to loader external bootloader * from mmc0, nand flash, mmc2. -* -* Unfortunately we can't check how SPL was loaded so assume it's -* always the first SD/MMC controller, unless it was explicitly -* stated that SPL is on nand flash. */ u32 spl_boot_device (void ) { -#if defined(CONFIG_SPL_NAND_SUPPORT ) +struct mmc *mmc0, *mmc1;/* -* This is compile time configuration informing SPL, that it -* was loaded from nand flash. -*/ -return BOOT_DEVICE_NAND ; -#else -/* -* When booting from the SD card, the "eGON.BT0" signature is expected -* to be found in memory at the address 0x0004 (see the "mksunxiboot" -* tool, which generates this header). +* When booting from the SD card or NAND memory, the "eGON.BT0" +* signature is expected to be found in memory at the address 0x0004 +* (see the "mksunxiboot" tool, which generates this header). * * When booting in the FEL mode over USB, this signature is patched in * memory and replaced with something else by the 'fel' tool. This other
@@ -144,16 +138,41 @@ u32 spl_boot_device(void)* valid bootable SD card image (because the BROM would refuse to * execute the SPL in this case). * -* This branch is just making a decision at runtime whether to load -* the main u-boot binary from the SD card (if the "eGON.BT0" signature -* is found) or return to the FEL code in the BROM to wait and receive -* the main u-boot binary over USB. +* This checks for the signature and if it is not found returns to +* the FEL code in the BROM to wait and receive the main u-boot +* binary over USB. If it is found, it determines where SPL was +* read from. */ -if (readl (4 ) ==0x4E4F4765 &&readl (8 ) ==0x3054422E )/* eGON.BT0 */ -return BOOT_DEVICE_MMC1 ; -else +if (readl (4 ) !=0x4E4F4765 ||readl (8 ) !=0x3054422E )/* eGON.BT0 */ return BOOT_DEVICE_BOARD ; -#endif + +/* The BROM will try to boot from mmc0 first, so try that first. */ +mmc_initialize (gd->bd); + mmc0 =find_mmc_device (0 ); +if (sunxi_mmc_has_egon_boot_signature (mmc0)) +return BOOT_DEVICE_MMC1 ; + +/* Fallback to booting NAND if enabled. */ +if (IS_ENABLED (CONFIG_SPL_NAND_SUPPORT )) +return BOOT_DEVICE_NAND ; + +if (IS_ENABLED (CONFIG_MMC_SUNXI_SLOT_EXTRA ) && +CONFIG_MMC_SUNXI_SLOT_EXTRA ==2 ) + { + mmc1 =find_mmc_device (1 ); +if (sunxi_mmc_has_egon_boot_signature (mmc1)) + { +/* spl_mmc.c: spl_mmc_load_image() is hard-coded to +* use find_mmc_device(0), no matter what we +* return. Swap mmc0 and mmc2 to make this work. */ + mmc0->block_dev.dev =1 ; + mmc1->block_dev.dev =0 ; + return BOOT_DEVICE_MMC2 + } + } + +panic ("Could not determine boot source\n" ); +return -1 ;/* Never reached */ }/* No confirmation data available in SPL yet. Hardcode bootmode */
Signature · 1 line
2.4.1
PATCH v3 2/3 sunxi/spl: Detect at runtime where from SPL was read
Hi,
Quoted 16 lines · Daniel Kochma?ski
Make possible using single
u-boot-sunxi-with-spl.binbinary for both NAND memory and SD card. Detection where SPL was read from is implemented inspl_boot_device.V2:
- Move signature verification to helper function
- Avoid unnecessary condition nestingV3:
- Further simplification of conditions
- Move reassigning mmc block.dev numbers fromboard_mmc_inittospl_boot_device
- If signature wasn't found on mmc0 andSPL_NAND_SUPPORTisn't enabled don't assume mmc2 is a valid boot device - check for egon signature first
Quoted 4 lines
Signed-off-by Daniel Kochma?ski <[email protected]>CC Roy Spliet <[email protected]>Cc Ian Campbell <[email protected]>Cc Hans De Goede <[email protected]>
Thanks, pushed with a few small coding style fixes (braces placement) to u-boot-sunxi/next for merging into v2015.10 .
Regards,
Hans
Quoted 108 lines
--- arch/arm/cpu/armv7/sunxi/board.c | 63 ++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 22 deletions(-)arch/arm/cpu/armv7/sunxi/board.c +41
-22@@ -11,6 +11,7 @@*/ #include <common.h> +#include <mmc.h> #include <i2c.h> #include <serial.h> #ifdef CONFIG_SPL_BUILD @@ -22,6 +23,7 @@#include <asm/arch/gpio.h> #include <asm/arch/sys_proto.h> #include <asm/arch/timer.h> +#include <asm/arch/mmc.h> #include <linux/compiler.h> @@ -117,26 +119,18 @@ void s_init(void) }#ifdef CONFIG_SPL_BUILD +DECLARE_GLOBAL_DATA_PTR ; +/* The sunxi internal brom will try to loader external bootloader * from mmc0, nand flash, mmc2. -* -* Unfortunately we can't check how SPL was loaded so assume it's -* always the first SD/MMC controller, unless it was explicitly -* stated that SPL is on nand flash. */ u32 spl_boot_device (void ) { -#if defined(CONFIG_SPL_NAND_SUPPORT ) +struct mmc *mmc0, *mmc1;/* -* This is compile time configuration informing SPL, that it -* was loaded from nand flash. -*/ -return BOOT_DEVICE_NAND ; -#else -/* -* When booting from the SD card, the "eGON.BT0" signature is expected -* to be found in memory at the address 0x0004 (see the "mksunxiboot" -* tool, which generates this header). +* When booting from the SD card or NAND memory, the "eGON.BT0" +* signature is expected to be found in memory at the address 0x0004 +* (see the "mksunxiboot" tool, which generates this header). * * When booting in the FEL mode over USB, this signature is patched in * memory and replaced with something else by the 'fel' tool. This other @@ -144,16 +138,41 @@ u32 spl_boot_device(void)* valid bootable SD card image (because the BROM would refuse to * execute the SPL in this case). * -* This branch is just making a decision at runtime whether to load -* the main u-boot binary from the SD card (if the "eGON.BT0" signature -* is found) or return to the FEL code in the BROM to wait and receive -* the main u-boot binary over USB. +* This checks for the signature and if it is not found returns to +* the FEL code in the BROM to wait and receive the main u-boot +* binary over USB. If it is found, it determines where SPL was +* read from. */ -if (readl (4 ) ==0x4E4F4765 &&readl (8 ) ==0x3054422E )/* eGON.BT0 */ -return BOOT_DEVICE_MMC1 ; -else +if (readl (4 ) !=0x4E4F4765 ||readl (8 ) !=0x3054422E )/* eGON.BT0 */ return BOOT_DEVICE_BOARD ; -#endif + +/* The BROM will try to boot from mmc0 first, so try that first. */ +mmc_initialize (gd->bd); + mmc0 =find_mmc_device (0 ); +if (sunxi_mmc_has_egon_boot_signature (mmc0)) +return BOOT_DEVICE_MMC1 ; + +/* Fallback to booting NAND if enabled. */ +if (IS_ENABLED (CONFIG_SPL_NAND_SUPPORT )) +return BOOT_DEVICE_NAND ; + +if (IS_ENABLED (CONFIG_MMC_SUNXI_SLOT_EXTRA ) && +CONFIG_MMC_SUNXI_SLOT_EXTRA ==2 ) + { + mmc1 =find_mmc_device (1 ); +if (sunxi_mmc_has_egon_boot_signature (mmc1)) + { +/* spl_mmc.c: spl_mmc_load_image() is hard-coded to +* use find_mmc_device(0), no matter what we +* return. Swap mmc0 and mmc2 to make this work. */ + mmc0->block_dev.dev =1 ; + mmc1->block_dev.dev =0 ; + return BOOT_DEVICE_MMC2 + } + } + +panic ("Could not determine boot source\n" ); +return -1 ;/* Never reached */ }/* No confirmation data available in SPL yet. Hardcode bootmode */
PATCH v3 3/3 mmc: Protect `mmc_initialize` from initilizing mmc multiple times
In reply to Daniel Kochmańskimmc_initialize might be called from various places and initializing list head of mmc_devices can lead to memory leaks.
--- drivers/mmc/mmc.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/mmc/mmc.c +5 -0
@@ -1758,6 +1758,11 @@ static void do_preinit(void)int mmc_initialize (bd_t *bis) { +static int initialized =0 ; +if (initialized)/* Avoid initializing mmc multiple times */ +return 0 ; + initialized =1 ; +INIT_LIST_HEAD (&mmc_devices); cur_dev_num =0 ;
Signature · 1 line
2.4.1
PATCH v3 3/3 mmc: Protect `mmc_initialize` from initilizing mmc multiple times
Hi,
Quoted 8 lines · Daniel Kochma?ski
mmc_initializemight be called from various places and initializing list head ofmmc_devicescan lead to memory leaks.Signed-off-by Daniel Kochma?ski <[email protected]>CC Roy Spliet <[email protected]>Cc Ian Campbell <[email protected]>Cc Hans De Goede <[email protected]>CC Pantelis Antoniou <[email protected]>
Thanks I've merged this one into u-boot-sunxi/next, for inclusion into u-boot v2015.10, I've fixed a few typos in the commit message and clarified the commit message a bit.
Pantelis, since this is an mmc patch may we have your ack for this one please? It is a dep for some sunxi changes so it is probably easiest if I just merge it through the sunxi tree.
Some background, we are adding support for booting from nand, and as such we need to make spl_boot_device() for sunxi smarter. The sunxi BROM does not communicate where it has loaded the SPL from, so we simply retrace it steps trying mmc0 first and looking for a valid bootsignature there.
This means calling mmc_initialize() from spl_boot_device() and if spl_boot_device() then finds a boot signature and returns BOOT_DEVICE_MMC1, then later on spl_mmc_load_image() will call mmc_initialize() a second time, this patch protects against this second call and turns the second call into a nop.
Regards,
Hans
Quoted 21 lines
--- drivers/mmc/mmc.c | 5 +++++ 1 file changed, 5 insertions(+)drivers/mmc/mmc.c +5
-0@@ -1758,6 +1758,11 @@ static void do_preinit(void)int mmc_initialize (bd_t *bis) { +static int initialized =0 ; +if (initialized)/* Avoid initializing mmc multiple times */ +return 0 ; + initialized =1 ; +INIT_LIST_HEAD (&mmc_devices); cur_dev_num =0 ;
PATCH v3 1/3 sunxi: Create helper function veryfing valid boot signature on MMC
In reply to Daniel KochmańskiHi,
Quoted 10 lines · Daniel Kochma?ski
This patch extracts checking for valid SD card "eGON.BT0" signature from
board_mmc_initinto functionsunxi_mmc_has_egon_boot_signature.Buffer for mmc sector is allocated and freed at runtime.
panicis triggered on malloc failure.Signed-off-by Daniel Kochma?ski <[email protected]>CC Roy Spliet <[email protected]>Cc Ian Campbell <[email protected]>Cc Hans De Goede <[email protected]>
Thanks, pushed with a small bug-fix to u-boot-sunxi/next for merging into v2015.10 .
Regards,
Hans
Quoted 64 lines
--- arch/arm/include/asm/arch-sunxi/mmc.h | 1 + board/sunxi/board.c | 8 ++------ drivers/mmc/sunxi_mmc.c | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 6 deletions(-)arch/arm/include/asm/arch-sunxi/mmc.h +1
-0@@ -127,4 +127,5 @@ struct sunxi_mmc {#define SUNXI_MMC_COMMON_RESET (1 << 18)struct mmc *sunxi_mmc_init (int sdc_no); +int sunxi_mmc_has_egon_boot_signature (struct mmc *mmc);#endif /* _SUNXI_MMC_H */ board/sunxi/board.c +2
-6@@ -302,12 +302,8 @@ int board_mmc_init(bd_t *bis)* Both mmc0 and mmc2 are bootable, figure out where we're booting * from. Try mmc0 first, just like the brom does. */ -if (mmc_getcd (mmc0) &&mmc_init (mmc0) ==0 && - mmc0->block_dev.block_read (0 ,16 ,1 , buf) ==1 ) { - buf[12 ] =0 ; -if (strcmp (&buf[4 ],"eGON.BT0" ) ==0 ) -return 0 ; - } +if (sunxi_mmc_has_egon_boot_signature (mmc0)) +return 0 ;/* no bootable card in mmc0, so we must be booting from mmc2, swap */ mmc0->block_dev.dev =1 ;drivers/mmc/sunxi_mmc.c +17
-0@@ -431,6 +431,23 @@ static int sunxi_mmc_getcd(struct mmc *mmc)return !gpio_get_value (cd_pin); } +int sunxi_mmc_has_egon_boot_signature (struct mmc *mmc) +{ +char *buf =malloc (512 ); +int valid_signature =0 ; + +if (buf ==NULL ) +panic ("Failed to allocate memory\n" ); + +if (mmc_getcd (mmc) &&mmc_init (mmc) ==0 && + mmc->block_dev.block_read (0 ,16 ,1 , buf) ==1 && +strncmp (&buf[4 ],"eGON.BT0" ,8 ) ==0 ) + valid_signature =1 ; + +free (buf); +return valid_signature; +} +static const struct mmc_ops sunxi_mmc_ops = { .send_cmd = sunxi_mmc_send_cmd, .set_ios = sunxi_mmc_set_ios,