Commit 504a1e84654a8b4b7f6cc672417fcbfa8e2b18c1

Authored by Luo Ji
1 parent 7163f0ca1c

MA-11693-1 [Android]Support m4 image flash for imx7ulp and im8mq

Support m4 image flash by fastboot: 'fastboot flash m4_os <path-to-image>'.

For 7ulp, m4 image will be excuted on POR and it doesn't depand on A
core, so the m4 image will be flashed to nor flash using 'sf' command.
For imx8m, m4 image will be loaded and excuted by A core. The m4 image
will be flashed to physical 'm4_os' partition and can be excuted by
'bootmcu' command.

Change-Id: I43bf0c9a484c5633cfe32dde3d738e33afdc775b
Signed-off-by: Luo Ji <ji.luo@nxp.com>

Showing 3 changed files with 261 additions and 2 deletions Side-by-side Diff

arch/arm/imx-common/Kconfig
... ... @@ -79,6 +79,12 @@
79 79 Select this to bind a ULP M4 image to final u-boot image
80 80 User needs put the M4 image ulp_m4.bin under u-boot directory
81 81  
  82 +config FLASH_MCUFIRMWARE_SUPPORT
  83 + bool "Enable mcu firmware flash support"
  84 + depends on ARCH_MX7ULP || ARCH_IMX8M
  85 + help
  86 + This enables the mcu firmware flash support for some SOCs.
  87 +
82 88 config IMX_TRUSTY_OS
83 89 bool "Support Trusty OS related feature"
84 90 depends on ARCH_MX6 || ARCH_MX7
drivers/usb/gadget/f_fastboot.c
... ... @@ -25,6 +25,7 @@
25 25 #include <linux/compiler.h>
26 26 #include <version.h>
27 27 #include <g_dnl.h>
  28 +#include "lib/avb/fsl/utils.h"
28 29 #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
29 30 #include <fb_mmc.h>
30 31 #endif
... ... @@ -82,6 +83,10 @@
82 83  
83 84 #define EP_BUFFER_SIZE 4096
84 85  
  86 +#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
  87 +struct fastboot_device_info fastboot_firmwareinfo;
  88 +#endif
  89 +
85 90 #if defined (CONFIG_ARCH_IMX8) || defined (CONFIG_ARCH_IMX8M)
86 91 #define DST_DECOMPRESS_LEN 1024*1024*32
87 92 #endif
... ... @@ -261,6 +266,9 @@
261 266 enum {
262 267 PTN_GPT_INDEX = 0,
263 268 PTN_TEE_INDEX,
  269 +#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
  270 + PTN_M4_OS_INDEX,
  271 +#endif
264 272 PTN_BOOTLOADER_INDEX,
265 273 };
266 274 static unsigned int download_bytes_unpadded;
... ... @@ -275,6 +283,98 @@
275 283 .transfer_buffer_size = 0,
276 284 };
277 285  
  286 +int read_from_partition_multi(const char* partition,
  287 + int64_t offset, size_t num_bytes, void* buffer, size_t* out_num_read)
  288 +{
  289 + struct fastboot_ptentry *pte;
  290 + unsigned char *bdata;
  291 + unsigned char *out_buf = (unsigned char *)buffer;
  292 + unsigned char *dst, *dst64 = NULL;
  293 + unsigned long blksz;
  294 + unsigned long s, cnt;
  295 + size_t num_read = 0;
  296 + lbaint_t part_start, part_end, bs, be, bm, blk_num;
  297 + margin_pos_t margin;
  298 + struct blk_desc *fs_dev_desc = NULL;
  299 + int dev_no;
  300 + int ret;
  301 +
  302 + assert(buffer != NULL && out_num_read != NULL);
  303 +
  304 + dev_no = mmc_get_env_dev();
  305 + if ((fs_dev_desc = blk_get_dev("mmc", dev_no)) == NULL) {
  306 + printf("mmc device not found\n");
  307 + return -1;
  308 + }
  309 +
  310 + pte = fastboot_flash_find_ptn(partition);
  311 + if (!pte) {
  312 + printf("no %s partition\n", partition);
  313 + return -1;
  314 + }
  315 +
  316 + blksz = fs_dev_desc->blksz;
  317 + part_start = pte->start;
  318 + part_end = pte->start + pte->length - 1;
  319 +
  320 + if (get_margin_pos((uint64_t)part_start, (uint64_t)part_end, blksz,
  321 + &margin, offset, num_bytes, true))
  322 + return -1;
  323 +
  324 + bs = (lbaint_t)margin.blk_start;
  325 + be = (lbaint_t)margin.blk_end;
  326 + s = margin.start;
  327 + bm = margin.multi;
  328 +
  329 + /* alloc a blksz mem */
  330 + bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz);
  331 + if (bdata == NULL) {
  332 + printf("Failed to allocate memory!\n");
  333 + return -1;
  334 + }
  335 +
  336 + /* support multi blk read */
  337 + while (bs <= be) {
  338 + if (!s && bm > 1) {
  339 + dst = out_buf;
  340 + dst64 = PTR_ALIGN(out_buf, 64); /* for mmc blk read alignment */
  341 + if (dst64 != dst) {
  342 + dst = dst64;
  343 + bm--;
  344 + }
  345 + blk_num = bm;
  346 + cnt = bm * blksz;
  347 + bm = 0; /* no more multi blk */
  348 + } else {
  349 + blk_num = 1;
  350 + cnt = blksz - s;
  351 + if (num_read + cnt > num_bytes)
  352 + cnt = num_bytes - num_read;
  353 + dst = bdata;
  354 + }
  355 + if (!fs_dev_desc->block_read(fs_dev_desc, bs, blk_num, dst)) {
  356 + ret = -1;
  357 + goto fail;
  358 + }
  359 +
  360 + if (dst == bdata)
  361 + memcpy(out_buf, bdata + s, cnt);
  362 + else if (dst == dst64)
  363 + memcpy(out_buf, dst, cnt); /* internal copy */
  364 +
  365 + s = 0;
  366 + bs += blk_num;
  367 + num_read += cnt;
  368 + out_buf += cnt;
  369 + }
  370 + *out_num_read = num_read;
  371 + ret = 0;
  372 +
  373 +fail:
  374 + free(bdata);
  375 + return ret;
  376 +}
  377 +
278 378 static void save_env(struct fastboot_ptentry *ptn,
279 379 char *var, char *val)
280 380 {
... ... @@ -470,6 +570,105 @@
470 570 return ret;
471 571 }
472 572  
  573 +#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
  574 +static void process_flash_sf(const char *cmdbuf)
  575 +{
  576 + if (download_bytes) {
  577 + struct fastboot_ptentry *ptn;
  578 + ptn = fastboot_flash_find_ptn(cmdbuf);
  579 + if (ptn == 0) {
  580 + fastboot_fail("partition does not exist");
  581 + } else if ((download_bytes > ptn->length)) {
  582 + fastboot_fail("image too large for partition");
  583 + /* TODO : Improve check for yaffs write */
  584 + } else {
  585 + int ret;
  586 + char sf_command[128];
  587 + /* Normal case */
  588 + /* Probe device */
  589 + sprintf(sf_command, "sf probe");
  590 + ret = run_command(sf_command, 0);
  591 + if (ret){
  592 + fastboot_fail("Probe sf failed");
  593 + return;
  594 + }
  595 + /* Erase */
  596 + sprintf(sf_command, "sf erase 0x%x 0x%x",ptn->start, /*start*/
  597 + ptn->length /*size*/);
  598 + ret = run_command(sf_command, 0);
  599 + if (ret) {
  600 + fastboot_fail("Erasing sf failed");
  601 + return;
  602 + }
  603 + /* Write image */
  604 + sprintf(sf_command, "sf write 0x%x 0x%x 0x%x",
  605 + (unsigned int)(ulong)interface.transfer_buffer, /* source */
  606 + ptn->start, /* start */
  607 + download_bytes /*size*/);
  608 + printf("sf write '%s'\n", ptn->name);
  609 + ret = run_command(sf_command, 0);
  610 + if (ret){
  611 + fastboot_fail("Writing sf failed");
  612 + return;
  613 + }
  614 + printf("sf write finished '%s'\n", ptn->name);
  615 + fastboot_okay("");
  616 + }
  617 + } else {
  618 + fastboot_fail("no image downloaded");
  619 + }
  620 +}
  621 +
  622 +#ifdef CONFIG_ARCH_IMX8M
  623 +/* Check if the mcu image is built for running from TCM */
  624 +static bool is_tcm_image(char *image_addr)
  625 +{
  626 + u32 stack, pc;
  627 +
  628 + stack = *(u32 *)image_addr;
  629 + pc = *(u32 *)(image_addr + 4);
  630 +
  631 + if ((stack != (u32)ANDROID_MCU_FIRMWARE_HEADER_STACK) ||
  632 + (pc != (u32)ANDROID_MCU_FIRMWARE_HEADER_PC)) {
  633 + printf("Please flash mcu firmware images for running from TCM\n");
  634 + return false;
  635 + } else
  636 + return true;
  637 +}
  638 +
  639 +static int do_bootmcu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  640 +{
  641 + int ret;
  642 + size_t out_num_read;
  643 + void *m4_base_addr = (void *)M4_BOOTROM_BASE_ADDR;
  644 + char command[32];
  645 +
  646 + ret = read_from_partition_multi(FASTBOOT_MCU_FIRMWARE_PARTITION,
  647 + 0, ANDROID_MCU_FIRMWARE_SIZE, (void *)m4_base_addr, &out_num_read);
  648 + if ((ret != 0) || (out_num_read != ANDROID_MCU_FIRMWARE_SIZE)) {
  649 + printf("Read M4 images failed!\n");
  650 + return 1;
  651 + } else {
  652 + printf("run command: 'bootaux 0x%x'\n",(unsigned int)(ulong)m4_base_addr);
  653 +
  654 + sprintf(command, "bootaux 0x%x", (unsigned int)(ulong)m4_base_addr);
  655 + ret = run_command(command, 0);
  656 + if (ret) {
  657 + printf("run 'bootaux' command failed!\n");
  658 + return 1;
  659 + }
  660 + }
  661 + return 0;
  662 +}
  663 +
  664 +U_BOOT_CMD(
  665 + bootmcu, 1, 0, do_bootmcu,
  666 + "boot mcu images\n",
  667 + "boot mcu images from 'm4_os' partition, only support images run from TCM"
  668 +);
  669 +#endif
  670 +#endif /* CONFIG_FLASH_MCUFIRMWARE_SUPPORT */
  671 +
473 672 #if defined(CONFIG_FASTBOOT_STORAGE_SATA)
474 673 static void process_flash_sata(const char *cmdbuf)
475 674 {
... ... @@ -898,6 +1097,27 @@
898 1097  
899 1098 static void rx_process_flash(const char *cmdbuf)
900 1099 {
  1100 +/* Check if we need to flash mcu firmware */
  1101 +#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
  1102 + if (!strncmp(cmdbuf, FASTBOOT_MCU_FIRMWARE_PARTITION,
  1103 + sizeof(FASTBOOT_MCU_FIRMWARE_PARTITION))) {
  1104 + switch (fastboot_firmwareinfo.type) {
  1105 + case DEV_SF:
  1106 + process_flash_sf(cmdbuf);
  1107 + break;
  1108 +#ifdef CONFIG_ARCH_IMX8M
  1109 + case DEV_MMC:
  1110 + if (is_tcm_image(interface.transfer_buffer))
  1111 + process_flash_mmc(cmdbuf);
  1112 + break;
  1113 +#endif
  1114 + default:
  1115 + printf("Don't support flash firmware\n");
  1116 + }
  1117 + return;
  1118 + }
  1119 +#endif
  1120 + /* Normal case */
901 1121 switch (fastboot_devinfo.type) {
902 1122 #if defined(CONFIG_FASTBOOT_STORAGE_SATA)
903 1123 case DEV_SATA:
... ... @@ -945,6 +1165,12 @@
945 1165 } else {
946 1166 return 1;
947 1167 }
  1168 +#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
  1169 + /* For imx7ulp, flash m4 images directly to spi nor-flash, M4 will
  1170 + * run automatically after powered on. For imx8mq, flash m4 images to
  1171 + * physical partition 'm4_os', m4 will be kicked off by A core. */
  1172 + fastboot_firmwareinfo.type = ANDROID_MCU_FRIMWARE_DEV_TYPE;
  1173 +#endif
948 1174  
949 1175 return 0;
950 1176 }
... ... @@ -1074,6 +1300,16 @@
1074 1300 ptable[PTN_TEE_INDEX].partition_id = TEE_HWPARTITION_ID;
1075 1301 strcpy(ptable[PTN_TEE_INDEX].fstype, "raw");
1076 1302  
  1303 + /* Add m4_os partition if we support mcu firmware image flash */
  1304 +#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
  1305 + strcpy(ptable[PTN_M4_OS_INDEX].name, FASTBOOT_MCU_FIRMWARE_PARTITION);
  1306 + ptable[PTN_M4_OS_INDEX].start = ANDROID_MCU_FIRMWARE_START / dev_desc->blksz;
  1307 + ptable[PTN_M4_OS_INDEX].length = ANDROID_MCU_FIRMWARE_SIZE / dev_desc->blksz;
  1308 + ptable[PTN_M4_OS_INDEX].flags = FASTBOOT_PTENTRY_FLAGS_UNERASEABLE;
  1309 + ptable[PTN_M4_OS_INDEX].partition_id = user_partition;
  1310 + strcpy(ptable[PTN_M4_OS_INDEX].fstype, "raw");
  1311 +#endif
  1312 +
1077 1313 /* Bootloader */
1078 1314 strcpy(ptable[PTN_BOOTLOADER_INDEX].name, FASTBOOT_PARTITION_BOOTLOADER);
1079 1315 ptable[PTN_BOOTLOADER_INDEX].start =
... ... @@ -1097,7 +1333,7 @@
1097 1333 if (ret)
1098 1334 break;
1099 1335 }
1100   - for (i = 0; i <= part_idx; i++)
  1336 + for (i = 0; i < tbl_idx; i++)
1101 1337 fastboot_flash_add_ptn(&ptable[i]);
1102 1338  
1103 1339 return 0;
include/fsl_fastboot.h
... ... @@ -8,6 +8,7 @@
8 8 #ifndef FSL_FASTBOOT_H
9 9 #define FSL_FASTBOOT_H
10 10 #include <stdbool.h>
  11 +#include <linux/types.h>
11 12  
12 13 #define FASTBOOT_PTENTRY_FLAGS_REPEAT(n) (n & 0x0f)
13 14 #define FASTBOOT_PTENTRY_FLAGS_REPEAT_MASK 0x0000000F
... ... @@ -46,6 +47,10 @@
46 47 #define FASTBOOT_PARTITION_AVBKEY "avbkey"
47 48 #endif
48 49  
  50 +#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
  51 +#define FASTBOOT_MCU_FIRMWARE_PARTITION "m4_os"
  52 +#endif
  53 +
49 54 #ifdef CONFIG_ANDROID_AB_SUPPORT
50 55 #define FASTBOOT_PARTITION_BOOT_A "boot_a"
51 56 #define FASTBOOT_PARTITION_RECOVERY "recovery"
... ... @@ -81,7 +86,11 @@
81 86 enum {
82 87 DEV_SATA,
83 88 DEV_MMC,
84   - DEV_NAND
  89 + DEV_NAND,
  90 +#ifdef CONFIG_FLASH_MCUFIRMWARE_SUPPORT
  91 + /* SPI Flash */
  92 + DEV_SF
  93 +#endif
85 94 };
86 95  
87 96 typedef enum {
... ... @@ -233,5 +242,13 @@
233 242 int check_parts_values(struct fastboot_ptentry *ptn);
234 243 #endif /*CONFIG_FASTBOOT_STORAGE_NAND*/
235 244  
  245 +/* Reads |num_bytes| from offset |offset| from partition with name
  246 + * |partition| (NUL-terminated UTF-8 string). If |offset| is
  247 + * negative, its absolute value should be interpreted as the number
  248 + * of bytes from the end of the partition.
  249 + * It's basically copied from fsl_read_from_partition_multi() because
  250 + * we may want to read partition when AVB is not enabled. */
  251 +int read_from_partition_multi(const char* partition,
  252 + int64_t offset, size_t num_bytes,void* buffer, size_t* out_num_read);
236 253 #endif /* FSL_FASTBOOT_H */