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