blob: 3957e06e5d90f806ffb48177fbc3ab057fa76f09 [file] [log] [blame]
Patrick Delaunay7daa91d2020-03-18 09:24:49 +01001// 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 <command.h>
8#include <dfu.h>
Patrick Delaunayc2fdd572020-03-18 09:25:02 +01009#include <image.h>
Patrick Delaunayc5112242020-03-18 09:24:55 +010010#include <asm/arch/stm32prog.h>
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010011#include "stm32prog.h"
12
13struct stm32prog_data *stm32prog_data;
14
Patrick Delaunay8610f222020-03-18 09:25:01 +010015static void enable_vidconsole(void)
16{
Patrick Delaunay8610f222020-03-18 09:25:01 +010017 char *stdname;
18 char buf[64];
19
20 stdname = env_get("stdout");
21 if (!stdname || !strstr(stdname, "vidconsole")) {
22 if (!stdname)
23 snprintf(buf, sizeof(buf), "serial,vidconsole");
24 else
25 snprintf(buf, sizeof(buf), "%s,vidconsole", stdname);
26 env_set("stdout", buf);
27 }
28
29 stdname = env_get("stderr");
30 if (!stdname || !strstr(stdname, "vidconsole")) {
31 if (!stdname)
32 snprintf(buf, sizeof(buf), "serial,vidconsole");
33 else
34 snprintf(buf, sizeof(buf), "%s,vidconsole", stdname);
35 env_set("stderr", buf);
36 }
Patrick Delaunay8610f222020-03-18 09:25:01 +010037}
38
Simon Glassed38aef2020-05-10 11:40:03 -060039static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc,
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010040 char * const argv[])
41{
42 ulong addr, size;
43 int dev, ret;
44 enum stm32prog_link_t link = LINK_UNDEFINED;
45 bool reset = false;
Patrick Delaunayc2fdd572020-03-18 09:25:02 +010046 struct image_header_s header;
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010047 struct stm32prog_data *data;
48
49 if (argc < 3 || argc > 5)
50 return CMD_RET_USAGE;
51
Patrick Delaunay29b2e2e2021-02-25 13:37:01 +010052 if (IS_ENABLED(CONFIG_CMD_STM32PROG_USB) && !strcmp(argv[1], "usb"))
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010053 link = LINK_USB;
Patrick Delaunay29b2e2e2021-02-25 13:37:01 +010054 else if (IS_ENABLED(CONFIG_CMD_STM32PROG_SERIAL) && !strcmp(argv[1], "serial"))
Patrick Delaunayb823d992020-03-18 09:25:00 +010055 link = LINK_SERIAL;
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010056
57 if (link == LINK_UNDEFINED) {
Patrick Delaunay2b15af52020-11-06 19:01:30 +010058 log_err("not supported link=%s\n", argv[1]);
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010059 return CMD_RET_USAGE;
60 }
Patrick Delaunayb823d992020-03-18 09:25:00 +010061
Simon Glassff9b9032021-07-24 09:03:30 -060062 dev = (int)dectoul(argv[2], NULL);
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010063
64 addr = STM32_DDR_BASE;
65 size = 0;
66 if (argc > 3) {
Simon Glass3ff49ec2021-07-24 09:03:29 -060067 addr = hextoul(argv[3], NULL);
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010068 if (!addr)
69 return CMD_RET_FAILURE;
70 }
71 if (argc > 4)
Simon Glass3ff49ec2021-07-24 09:03:29 -060072 size = hextoul(argv[4], NULL);
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010073
Patrick Delaunayc2fdd572020-03-18 09:25:02 +010074 /* check STM32IMAGE presence */
Patrick Delaunay19676ef2021-04-02 14:05:17 +020075 if (size == 0) {
Patrick Delaunay953d8bf2022-03-28 19:25:29 +020076 stm32prog_header_check(addr, &header);
Patrick Delaunay19676ef2021-04-02 14:05:17 +020077 if (header.type == HEADER_STM32IMAGE) {
Patrick Delaunay953d8bf2022-03-28 19:25:29 +020078 size = header.image_length + header.length;
Patrick Delaunayc2fdd572020-03-18 09:25:02 +010079
Patrick Delaunay3a44a072021-05-18 15:12:07 +020080#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
Patrick Delaunay19676ef2021-04-02 14:05:17 +020081 /* uImage detected in STM32IMAGE, execute the script */
82 if (IMAGE_FORMAT_LEGACY ==
Patrick Delaunay953d8bf2022-03-28 19:25:29 +020083 genimg_get_format((void *)(addr + header.length)))
84 return image_source_script(addr + header.length, "script@1");
Patrick Delaunay3a44a072021-05-18 15:12:07 +020085#endif
Patrick Delaunay19676ef2021-04-02 14:05:17 +020086 }
Patrick Delaunayc2fdd572020-03-18 09:25:02 +010087 }
88
Patrick Delaunay8040da12020-07-31 16:31:52 +020089 if (IS_ENABLED(CONFIG_DM_VIDEO))
90 enable_vidconsole();
Patrick Delaunay8610f222020-03-18 09:25:01 +010091
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010092 data = (struct stm32prog_data *)malloc(sizeof(*data));
93
94 if (!data) {
Patrick Delaunay2b15af52020-11-06 19:01:30 +010095 log_err("Alloc failed.");
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010096 return CMD_RET_FAILURE;
97 }
98 stm32prog_data = data;
99
100 ret = stm32prog_init(data, addr, size);
101 if (ret)
Patrick Delaunaybe7d21e2021-05-18 15:12:11 +0200102 log_debug("Invalid or missing layout file at 0x%lx.\n", addr);
Patrick Delaunay7daa91d2020-03-18 09:24:49 +0100103
104 /* prepare DFU for device read/write */
105 ret = stm32prog_dfu_init(data);
106 if (ret)
107 goto cleanup;
108
109 switch (link) {
Patrick Delaunayb823d992020-03-18 09:25:00 +0100110 case LINK_SERIAL:
111 ret = stm32prog_serial_init(data, dev);
112 if (ret)
113 goto cleanup;
114 reset = stm32prog_serial_loop(data);
115 break;
Patrick Delaunay7daa91d2020-03-18 09:24:49 +0100116 case LINK_USB:
117 reset = stm32prog_usb_loop(data, dev);
118 break;
119 default:
120 goto cleanup;
121 }
122
123 stm32prog_clean(data);
124 free(stm32prog_data);
125 stm32prog_data = NULL;
126
127 puts("Download done\n");
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100128
Patrick Delaunayab198fe2021-05-18 15:12:06 +0200129 if (data->uimage) {
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100130 char boot_addr_start[20];
131 char dtb_addr[20];
Patrick Delaunayab198fe2021-05-18 15:12:06 +0200132 char initrd_addr[40];
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100133 char *bootm_argv[5] = {
134 "bootm", boot_addr_start, "-", dtb_addr, NULL
135 };
Patrick Delaunayab198fe2021-05-18 15:12:06 +0200136 u32 uimage = data->uimage;
137 u32 dtb = data->dtb;
138 u32 initrd = data->initrd;
139
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100140 if (!dtb)
141 bootm_argv[3] = env_get("fdtcontroladdr");
142 else
143 snprintf(dtb_addr, sizeof(dtb_addr) - 1,
144 "0x%x", dtb);
145
146 snprintf(boot_addr_start, sizeof(boot_addr_start) - 1,
147 "0x%x", uimage);
Patrick Delaunayab198fe2021-05-18 15:12:06 +0200148
149 if (initrd) {
150 snprintf(initrd_addr, sizeof(initrd_addr) - 1, "0x%x:0x%x",
151 initrd, data->initrd_size);
152 bootm_argv[2] = initrd_addr;
153 }
154
155 printf("Booting kernel at %s %s %s...\n\n\n",
156 boot_addr_start, bootm_argv[2], bootm_argv[3]);
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100157 /* Try bootm for legacy and FIT format image */
158 if (genimg_get_format((void *)uimage) != IMAGE_FORMAT_INVALID)
159 do_bootm(cmdtp, 0, 4, bootm_argv);
Bin Mengd0d1df62020-07-08 00:19:22 -0700160 else if (CONFIG_IS_ENABLED(CMD_BOOTZ))
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100161 do_bootz(cmdtp, 0, 4, bootm_argv);
162 }
163
Patrick Delaunay7daa91d2020-03-18 09:24:49 +0100164 if (reset) {
165 puts("Reset...\n");
166 run_command("reset", 0);
167 }
168
169 return CMD_RET_SUCCESS;
170
171cleanup:
172 stm32prog_clean(data);
173 free(stm32prog_data);
174 stm32prog_data = NULL;
175
176 return CMD_RET_FAILURE;
177}
178
179U_BOOT_CMD(stm32prog, 5, 0, do_stm32prog,
Patrick Delaunay97076982021-06-28 14:44:33 +0200180 "start communication with tools STM32Cubeprogrammer",
Patrick Delaunay7daa91d2020-03-18 09:24:49 +0100181 "<link> <dev> [<addr>] [<size>]\n"
Patrick Delaunay97076982021-06-28 14:44:33 +0200182 " <link> = serial|usb\n"
183 " <dev> = device instance\n"
184 " <addr> = address of flashlayout\n"
185 " <size> = size of flashlayout (optional for image with STM32 header)\n"
Patrick Delaunay7daa91d2020-03-18 09:24:49 +0100186);
Patrick Delaunayc5112242020-03-18 09:24:55 +0100187
Patrick Delaunay1008a502021-07-26 11:21:38 +0200188#ifdef CONFIG_STM32MP15x_STM32IMAGE
Patrick Delaunayc5112242020-03-18 09:24:55 +0100189bool stm32prog_get_tee_partitions(void)
190{
191 if (stm32prog_data)
192 return stm32prog_data->tee_detected;
193
194 return false;
195}
Patrick Delaunay1008a502021-07-26 11:21:38 +0200196#endif
Patrick Delaunayc5112242020-03-18 09:24:55 +0100197
198bool stm32prog_get_fsbl_nor(void)
199{
200 if (stm32prog_data)
201 return stm32prog_data->fsbl_nor_detected;
202
203 return false;
204}