1// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause 2/* 3 * Copyright (C) 2020, STMicroelectronics - All Rights Reserved 4 */ 5 6#include <bootm.h> 7#include <command.h> 8#include <dfu.h> 9#include <image.h> 10#include <asm/arch/stm32prog.h> 11#include <linux/printk.h> 12#include "stm32prog.h" 13 14struct stm32prog_data *stm32prog_data; 15 16static void enable_vidconsole(void) 17{ 18 char *stdname; 19 char buf[64]; 20 21 stdname = env_get("stdout"); 22 if (!stdname || !strstr(stdname, "vidconsole")) { 23 if (!stdname) 24 snprintf(buf, sizeof(buf), "serial,vidconsole"); 25 else 26 snprintf(buf, sizeof(buf), "%s,vidconsole", stdname); 27 env_set("stdout", buf); 28 } 29 30 stdname = env_get("stderr"); 31 if (!stdname || !strstr(stdname, "vidconsole")) { 32 if (!stdname) 33 snprintf(buf, sizeof(buf), "serial,vidconsole"); 34 else 35 snprintf(buf, sizeof(buf), "%s,vidconsole", stdname); 36 env_set("stderr", buf); 37 } 38} 39 40static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc, 41 char * const argv[]) 42{ 43 ulong addr, size; 44 int dev, ret; 45 enum stm32prog_link_t link = LINK_UNDEFINED; 46 bool reset = false; 47 struct image_header_s header; 48 struct stm32prog_data *data; 49 50 if (argc < 3 || argc > 5) 51 return CMD_RET_USAGE; 52 53 if (IS_ENABLED(CONFIG_CMD_STM32PROG_USB) && !strcmp(argv[1], "usb")) 54 link = LINK_USB; 55 else if (IS_ENABLED(CONFIG_CMD_STM32PROG_SERIAL) && !strcmp(argv[1], "serial")) 56 link = LINK_SERIAL; 57 58 if (link == LINK_UNDEFINED) { 59 log_err("not supported link=%s\n", argv[1]); 60 return CMD_RET_USAGE; 61 } 62 63 dev = (int)dectoul(argv[2], NULL); 64 65 addr = CONFIG_SYS_LOAD_ADDR; 66 size = 0; 67 if (argc > 3) { 68 addr = hextoul(argv[3], NULL); 69 if (!addr) 70 return CMD_RET_FAILURE; 71 } 72 if (argc > 4) 73 size = hextoul(argv[4], NULL); 74 75 /* check STM32IMAGE presence */ 76 if (size == 0) { 77 stm32prog_header_check(addr, &header); 78 if (header.type == HEADER_STM32IMAGE) { 79 size = header.image_length + header.length; 80 } 81 } 82 83 if (IS_ENABLED(CONFIG_VIDEO)) 84 enable_vidconsole(); 85 86 data = (struct stm32prog_data *)malloc(sizeof(*data)); 87 88 if (!data) { 89 log_err("Alloc failed."); 90 return CMD_RET_FAILURE; 91 } 92 stm32prog_data = data; 93 94 ret = stm32prog_init(data, addr, size); 95 if (ret) 96 log_debug("Invalid or missing layout file at 0x%lx.\n", addr); 97 98 /* prepare DFU for device read/write */ 99 ret = stm32prog_dfu_init(data); 100 if (ret) 101 goto cleanup; 102 103 switch (link) { 104 case LINK_SERIAL: 105 ret = stm32prog_serial_init(data, dev); 106 if (ret) 107 goto cleanup; 108 reset = stm32prog_serial_loop(data); 109 break; 110 case LINK_USB: 111 reset = stm32prog_usb_loop(data, dev); 112 break; 113 default: 114 goto cleanup; 115 } 116 117 stm32prog_clean(data); 118 free(stm32prog_data); 119 stm32prog_data = NULL; 120 121 puts("Download done\n"); 122 123 if (data->uimage) { 124 char boot_addr_start[20]; 125 char dtb_addr[20]; 126 char initrd_addr[40]; 127 char *fdt_arg, *initrd_arg; 128 const void *uimage = (void *)data->uimage; 129 const void *dtb = (void *)data->dtb; 130 const void *initrd = (void *)data->initrd; 131 struct bootm_info bmi; 132 133 fdt_arg = dtb_addr; 134 if (!dtb) 135 fdt_arg = env_get("fdtcontroladdr"); 136 else 137 snprintf(dtb_addr, sizeof(dtb_addr) - 1, "0x%p", dtb); 138 139 snprintf(boot_addr_start, sizeof(boot_addr_start) - 1, 140 "0x%p", uimage); 141 142 initrd_arg = NULL; 143 if (initrd) { 144 snprintf(initrd_addr, sizeof(initrd_addr) - 1, 145 "0x%p:0x%zx", initrd, data->initrd_size); 146 initrd_arg = initrd_addr; 147 } 148 149 printf("Booting kernel at %s %s %s...\n\n\n", boot_addr_start, 150 initrd_arg ?: "-", fdt_arg); 151 152 bootm_init(&bmi); 153 bmi.addr_img = boot_addr_start; 154 bmi.conf_ramdisk = initrd_arg; 155 bmi.conf_fdt = fdt_arg; 156 157 /* Try bootm for legacy and FIT format image */ 158 if (genimg_get_format(uimage) != IMAGE_FORMAT_INVALID) 159 bootm_run(&bmi); 160 else if (IS_ENABLED(CONFIG_CMD_BOOTZ)) 161 bootz_run(&bmi); 162 } 163 if (data->script) 164 cmd_source_script(data->script, NULL, NULL); 165 166 if (reset) { 167 puts("Reset...\n"); 168 run_command("reset", 0); 169 } 170 171 return CMD_RET_SUCCESS; 172 173cleanup: 174 stm32prog_clean(data); 175 free(stm32prog_data); 176 stm32prog_data = NULL; 177 178 return CMD_RET_FAILURE; 179} 180 181U_BOOT_CMD(stm32prog, 5, 0, do_stm32prog, 182 "start communication with tools STM32Cubeprogrammer", 183 "<link> <dev> [<addr>] [<size>]\n" 184 " <link> = serial|usb\n" 185 " <dev> = device instance\n" 186 " <addr> = address of flashlayout\n" 187 " <size> = size of flashlayout (optional for image with STM32 header)\n" 188); 189 190 191bool stm32prog_get_fsbl_nor(void) 192{ 193 if (stm32prog_data) 194 return stm32prog_data->fsbl_nor_detected; 195 196 return false; 197} 198