[PATCH v3 1/5] cmd: mvebu: bubt: add A38x support

Add support for Armada 38x devices in bubt flashing utility. This is based on (and streamlined from) the support in the SolidRun master-a38x vendor fork branch.
Signed-off-by: Joel Johnson mrjoel@lixil.net Reviewed-by: Stefan Roese sr@denx.de
---
v2 changes - none v3 changes - none
--- cmd/mvebu/bubt.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-)
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index 2041a7a29a..d399fb6da4 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -85,7 +85,29 @@ struct mvebu_image_info { u32 encrypt_start_offset; u32 encrypt_size; }; -#endif /* CONFIG_ARMADA_XXX */ +#elif defined(CONFIG_ARMADA_38X) /* A38X */ + +/* Structure of the main header, version 1 (Armada 370/38x/XP) */ +struct a38x_main_hdr_v1 { + u8 blockid; /* 0x0 */ + u8 flags; /* 0x1 */ + u16 reserved2; /* 0x2-0x3 */ + u32 blocksize; /* 0x4-0x7 */ + u8 version; /* 0x8 */ + u8 headersz_msb; /* 0x9 */ + u16 headersz_lsb; /* 0xA-0xB */ + u32 srcaddr; /* 0xC-0xF */ + u32 destaddr; /* 0x10-0x13 */ + u32 execaddr; /* 0x14-0x17 */ + u8 options; /* 0x18 */ + u8 nandblocksize; /* 0x19 */ + u8 nandbadblklocation; /* 0x1A */ + u8 reserved4; /* 0x1B */ + u16 reserved5; /* 0x1C-0x1D */ + u8 ext; /* 0x1E */ + u8 checksum; /* 0x1F */ +}; +#endif
struct bubt_dev { char name[8]; @@ -621,7 +643,52 @@ static int check_image_header(void)
return 0; } +#elif defined(CONFIG_ARMADA_38X) +static size_t a38x_header_size(const struct a38x_main_hdr_v1 *h) +{ + if (h->version == 1) + return (h->headersz_msb << 16) | le16_to_cpu(h->headersz_lsb); + + printf("Error: Invalid A38x image (header version 0x%x unknown)!\n", + h->version); + return 0; +} + +static uint8_t image_checksum8(const void *start, size_t len) +{ + u8 csum = 0; + const u8 *p = start; + + while (len) { + csum += *p; + ++p; + --len; + } + + return csum; +}
+static int check_image_header(void) +{ + u8 checksum; + const struct a38x_main_hdr_v1 *hdr = + (struct a38x_main_hdr_v1 *)get_load_addr(); + const size_t image_size = a38x_header_size(hdr); + + if (!image_size) + return -ENOEXEC; + + checksum = image_checksum8(hdr, image_size); + checksum -= hdr->checksum; + if (checksum != hdr->checksum) { + printf("Error: Bad A38x image checksum. 0x%x != 0x%x\n", + checksum, hdr->checksum); + return -ENOEXEC; + } + + printf("Image checksum...OK!\n"); + return 0; +} #else /* Not ARMADA? */ static int check_image_header(void) {

Replace "U-BOOT" text with correct spelling
Signed-off-by: Joel Johnson mrjoel@lixil.net Reviewed-by: Stefan Roese sr@denx.de
---
v2 changes: - none v3 changes: - none
--- cmd/mvebu/bubt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index d399fb6da4..b80b81c82a 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -346,7 +346,7 @@ static int nand_burn_image(size_t image_size) /* Align U-Boot size to currently used blocksize */ image_size = ((image_size + (block_size - 1)) & (~(block_size - 1)));
- /* Erase the U-BOOT image space */ + /* Erase the U-Boot image space */ printf("Erasing 0x%x - 0x%x:...", 0, (int)image_size); ret = nand_erase(mtd, 0, image_size); if (ret) { @@ -734,7 +734,7 @@ static int bubt_read_file(struct bubt_dev *src) static int bubt_is_dev_active(struct bubt_dev *dev) { if (!dev->active) { - printf("Device "%s" not supported by U-BOOT image\n", + printf("Device "%s" not supported by U-Boot image\n", dev->name); return 0; } @@ -822,7 +822,7 @@ int do_bubt_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (!bubt_is_dev_active(src)) return -ENODEV;
- printf("Burning U-BOOT image "%s" from "%s" to "%s"\n", + printf("Burning U-Boot image "%s" from "%s" to "%s"\n", net_boot_file_name, src->name, dst->name);
image_size = bubt_read_file(src);

Ensure that the device to which an image is being written includes header information indicating boot support for the destination device.
This is derived from the support in the SolidRun master-a38x vendor fork.
Signed-off-by: Joel Johnson mrjoel@lixil.net
---
v2 changes: - none v3 changes: - use ARRAY_SIZE instead of #define size
--- cmd/mvebu/bubt.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-)
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index b80b81c82a..fbcad37c40 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -107,6 +107,24 @@ struct a38x_main_hdr_v1 { u8 ext; /* 0x1E */ u8 checksum; /* 0x1F */ }; + +struct a38x_boot_mode { + unsigned int id; + const char *name; +}; + +/* The blockid header field values used to indicate boot device of image */ +struct a38x_boot_mode a38x_boot_modes[] = { + { 0x4D, "i2c" }, + { 0x5A, "spi" }, + { 0x69, "uart" }, + { 0x78, "sata" }, + { 0x8B, "nand" }, + { 0x9C, "pex" }, + { 0xAE, "mmc" }, + {}, +}; + #endif
struct bubt_dev { @@ -644,6 +662,23 @@ static int check_image_header(void) return 0; } #elif defined(CONFIG_ARMADA_38X) +static int a38x_check_boot_mode(const struct bubt_dev *dst) +{ + int mode; + const struct a38x_main_hdr_v1 *hdr = + (struct a38x_main_hdr_v1 *)get_load_addr(); + + for (mode = 0; mode < ARRAY_SIZE(a38x_boot_modes); mode++) { + if (strcmp(a38x_boot_modes[mode].name, dst->name) == 0) + break; + } + + if (a38x_boot_modes[mode].id == hdr->blockid) + return 0; + + return -ENOEXEC; +} + static size_t a38x_header_size(const struct a38x_main_hdr_v1 *h) { if (h->version == 1) @@ -697,7 +732,7 @@ static int check_image_header(void) } #endif
-static int bubt_verify(size_t image_size) +static int bubt_verify(const struct bubt_dev *dst) { int err;
@@ -708,6 +743,14 @@ static int bubt_verify(size_t image_size) return err; }
+#if defined(CONFIG_ARMADA_38X) + err = a38x_check_boot_mode(dst); + if (err) { + puts("Error: image not built for destination device!\n"); + return err; + } +#endif + return 0; }
@@ -829,7 +872,7 @@ int do_bubt_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (!image_size) return -EIO;
- err = bubt_verify(image_size); + err = bubt_verify(dst); if (err) return err;

On 23.03.20 18:43, Joel Johnson wrote:
Ensure that the device to which an image is being written includes header information indicating boot support for the destination device.
This is derived from the support in the SolidRun master-a38x vendor fork.
Signed-off-by: Joel Johnson mrjoel@lixil.net
v2 changes:
- none
v3 changes:
- use ARRAY_SIZE instead of #define size
cmd/mvebu/bubt.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-)
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index b80b81c82a..fbcad37c40 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -107,6 +107,24 @@ struct a38x_main_hdr_v1 { u8 ext; /* 0x1E */ u8 checksum; /* 0x1F */ };
+struct a38x_boot_mode {
- unsigned int id;
- const char *name;
+};
+/* The blockid header field values used to indicate boot device of image */ +struct a38x_boot_mode a38x_boot_modes[] = {
- { 0x4D, "i2c" },
- { 0x5A, "spi" },
- { 0x69, "uart" },
- { 0x78, "sata" },
- { 0x8B, "nand" },
- { 0x9C, "pex" },
- { 0xAE, "mmc" },
- {},
+};
#endif
struct bubt_dev {
@@ -644,6 +662,23 @@ static int check_image_header(void) return 0; } #elif defined(CONFIG_ARMADA_38X) +static int a38x_check_boot_mode(const struct bubt_dev *dst) +{
- int mode;
- const struct a38x_main_hdr_v1 *hdr =
(struct a38x_main_hdr_v1 *)get_load_addr();
- for (mode = 0; mode < ARRAY_SIZE(a38x_boot_modes); mode++) {
if (strcmp(a38x_boot_modes[mode].name, dst->name) == 0)
break;
- }
- if (a38x_boot_modes[mode].id == hdr->blockid)
return 0;
- return -ENOEXEC;
+}
- static size_t a38x_header_size(const struct a38x_main_hdr_v1 *h) { if (h->version == 1)
@@ -697,7 +732,7 @@ static int check_image_header(void) } #endif
-static int bubt_verify(size_t image_size) +static int bubt_verify(const struct bubt_dev *dst) { int err;
@@ -708,6 +743,14 @@ static int bubt_verify(size_t image_size) return err; }
+#if defined(CONFIG_ARMADA_38X)
- err = a38x_check_boot_mode(dst);
- if (err) {
puts("Error: image not built for destination device!\n");
return err;
- }
+#endif
Sorry for spotting this so late, but could you please change this to
if (IS_ENABLED(CONFIG_ARMADA_38X)) { err = a38x_check_boot_mode(dst); ...
instead (less #ifdef's).
Other than that, please add my:
Reviewed-by: Stefan Roese sr@denx.de
Thanks, Stefan
- return 0; }
@@ -829,7 +872,7 @@ int do_bubt_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (!image_size) return -EIO;
- err = bubt_verify(image_size);
- err = bubt_verify(dst); if (err) return err;
Viele Grüße, Stefan

With support added for Armada 38x, include the bubt command in ClearFog defconfig.
Signed-off-by: Joel Johnson mrjoel@lixil.net Reviewed-by: Stefan Roese sr@denx.de
---
v2 changes: - none v3 changes: - none
--- configs/clearfog_defconfig | 1 + 1 file changed, 1 insertion(+)
diff --git a/configs/clearfog_defconfig b/configs/clearfog_defconfig index c938448c30..0d7e19e731 100644 --- a/configs/clearfog_defconfig +++ b/configs/clearfog_defconfig @@ -35,6 +35,7 @@ CONFIG_SPL_CMD_TLV_EEPROM=y CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y CONFIG_CMD_MMC=y +CONFIG_CMD_MVEBU_BUBT=y CONFIG_CMD_PCI=y CONFIG_CMD_SPI=y CONFIG_CMD_USB=y

When a mismatch is found trying to write an image for one boot method to a different boot device, print an error message including the image header marked target boot device type.
Signed-off-by: Joel Johnson mrjoel@lixil.net Reviewed-by: Stefan Roese sr@denx.de
---
v2 changes: - newly added in v2 series v3 changes: - none
--- cmd/mvebu/bubt.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index fbcad37c40..f992507041 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -676,6 +676,17 @@ static int a38x_check_boot_mode(const struct bubt_dev *dst) if (a38x_boot_modes[mode].id == hdr->blockid) return 0;
+ for (int i = 0; i < A38X_BOOT_MODE_MAX; i++) { + if (a38x_boot_modes[i].id == hdr->blockid) { + printf("Error: image meant to be booted from " + " "%s", not "%s"!\n", + a38x_boot_modes[i].name, dst->name); + return -ENOEXEC; + } + } + + printf("Error: unknown boot device in image header: 0x%x\n", + hdr->blockid); return -ENOEXEC; }
@@ -745,10 +756,8 @@ static int bubt_verify(const struct bubt_dev *dst)
#if defined(CONFIG_ARMADA_38X) err = a38x_check_boot_mode(dst); - if (err) { - puts("Error: image not built for destination device!\n"); + if (err) return err; - } #endif
return 0;

On 2020-03-23 11:43, Joel Johnson wrote:
When a mismatch is found trying to write an image for one boot method to a different boot device, print an error message including the image header marked target boot device type.
Signed-off-by: Joel Johnson mrjoel@lixil.net Reviewed-by: Stefan Roese sr@denx.de
v2 changes:
- newly added in v2 series
v3 changes:
- none
cmd/mvebu/bubt.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index fbcad37c40..f992507041 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -676,6 +676,17 @@ static int a38x_check_boot_mode(const struct bubt_dev *dst) if (a38x_boot_modes[mode].id == hdr->blockid) return 0;
- for (int i = 0; i < A38X_BOOT_MODE_MAX; i++) {
if (a38x_boot_modes[i].id == hdr->blockid) {
printf("Error: image meant to be booted from "
" \"%s\", not \"%s\"!\n",
a38x_boot_modes[i].name, dst->name);
return -ENOEXEC;
}
- }
- printf("Error: unknown boot device in image header: 0x%x\n",
return -ENOEXEC;hdr->blockid);
}
@@ -745,10 +756,8 @@ static int bubt_verify(const struct bubt_dev *dst)
#if defined(CONFIG_ARMADA_38X) err = a38x_check_boot_mode(dst);
- if (err) {
puts("Error: image not built for destination device!\n");
- if (err) return err;
- }
#endif
return 0;
I sent this one prematurely before complete build testing, I'll followup with further testing with a change to use ARRAY_SIZE here as well.
Joel

On 23.03.20 18:43, Joel Johnson wrote:
When a mismatch is found trying to write an image for one boot method to a different boot device, print an error message including the image header marked target boot device type.
Signed-off-by: Joel Johnson mrjoel@lixil.net Reviewed-by: Stefan Roese sr@denx.de
v2 changes:
- newly added in v2 series
v3 changes:
- none
cmd/mvebu/bubt.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index fbcad37c40..f992507041 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -676,6 +676,17 @@ static int a38x_check_boot_mode(const struct bubt_dev *dst) if (a38x_boot_modes[mode].id == hdr->blockid) return 0;
- for (int i = 0; i < A38X_BOOT_MODE_MAX; i++) {
This will fail, as A38X_BOOT_MODE_MAX is not defined any more. Please use ARRAY_SIZE() here as well.
Thanks, Stefan
if (a38x_boot_modes[i].id == hdr->blockid) {
printf("Error: image meant to be booted from "
" \"%s\", not \"%s\"!\n",
a38x_boot_modes[i].name, dst->name);
return -ENOEXEC;
}
- }
- printf("Error: unknown boot device in image header: 0x%x\n",
return -ENOEXEC; }hdr->blockid);
@@ -745,10 +756,8 @@ static int bubt_verify(const struct bubt_dev *dst)
#if defined(CONFIG_ARMADA_38X) err = a38x_check_boot_mode(dst);
- if (err) {
puts("Error: image not built for destination device!\n");
- if (err) return err;
} #endif
return 0;
Viele Grüße, Stefan

On 2020-03-24 01:28, Stefan Roese wrote:
On 23.03.20 18:43, Joel Johnson wrote:
When a mismatch is found trying to write an image for one boot method to a different boot device, print an error message including the image header marked target boot device type.
Signed-off-by: Joel Johnson mrjoel@lixil.net Reviewed-by: Stefan Roese sr@denx.de
v2 changes:
- newly added in v2 series
v3 changes:
- none
cmd/mvebu/bubt.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index fbcad37c40..f992507041 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -676,6 +676,17 @@ static int a38x_check_boot_mode(const struct bubt_dev *dst) if (a38x_boot_modes[mode].id == hdr->blockid) return 0;
- for (int i = 0; i < A38X_BOOT_MODE_MAX; i++) {
This will fail, as A38X_BOOT_MODE_MAX is not defined any more. Please use ARRAY_SIZE() here as well.
Thanks, Stefan
Yeah, I caught that but missed committing it for this series - I'd sent out a v4 with this fixed. A v5 with your other ifdef change will include it.
Joel
participants (2)
-
Joel Johnson
-
Stefan Roese