blob: 8670535844d3e57f3fa7d63bb8540a03f79a1eaa [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>
Simon Glassbdd5f812023-09-14 18:21:46 -060011#include <linux/printk.h>
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010012#include "stm32prog.h"
13
14struct stm32prog_data *stm32prog_data;
15
Patrick Delaunay8610f222020-03-18 09:25:01 +010016static void enable_vidconsole(void)
17{
Patrick Delaunay8610f222020-03-18 09:25:01 +010018 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 }
Patrick Delaunay8610f222020-03-18 09:25:01 +010038}
39
Simon Glassed38aef2020-05-10 11:40:03 -060040static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc,
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010041 char * const argv[])
42{
43 ulong addr, size;
44 int dev, ret;
45 enum stm32prog_link_t link = LINK_UNDEFINED;
46 bool reset = false;
Patrick Delaunayc2fdd572020-03-18 09:25:02 +010047 struct image_header_s header;
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010048 struct stm32prog_data *data;
49
50 if (argc < 3 || argc > 5)
51 return CMD_RET_USAGE;
52
Patrick Delaunay29b2e2e2021-02-25 13:37:01 +010053 if (IS_ENABLED(CONFIG_CMD_STM32PROG_USB) && !strcmp(argv[1], "usb"))
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010054 link = LINK_USB;
Patrick Delaunay29b2e2e2021-02-25 13:37:01 +010055 else if (IS_ENABLED(CONFIG_CMD_STM32PROG_SERIAL) && !strcmp(argv[1], "serial"))
Patrick Delaunayb823d992020-03-18 09:25:00 +010056 link = LINK_SERIAL;
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010057
58 if (link == LINK_UNDEFINED) {
Patrick Delaunay2b15af52020-11-06 19:01:30 +010059 log_err("not supported link=%s\n", argv[1]);
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010060 return CMD_RET_USAGE;
61 }
Patrick Delaunayb823d992020-03-18 09:25:00 +010062
Simon Glassff9b9032021-07-24 09:03:30 -060063 dev = (int)dectoul(argv[2], NULL);
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010064
Patrick Delaunaye334d322022-09-06 18:53:18 +020065 addr = CONFIG_SYS_LOAD_ADDR;
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010066 size = 0;
67 if (argc > 3) {
Simon Glass3ff49ec2021-07-24 09:03:29 -060068 addr = hextoul(argv[3], NULL);
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010069 if (!addr)
70 return CMD_RET_FAILURE;
71 }
72 if (argc > 4)
Simon Glass3ff49ec2021-07-24 09:03:29 -060073 size = hextoul(argv[4], NULL);
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010074
Patrick Delaunayc2fdd572020-03-18 09:25:02 +010075 /* check STM32IMAGE presence */
Patrick Delaunay19676ef2021-04-02 14:05:17 +020076 if (size == 0) {
Patrick Delaunay953d8bf2022-03-28 19:25:29 +020077 stm32prog_header_check(addr, &header);
Patrick Delaunay19676ef2021-04-02 14:05:17 +020078 if (header.type == HEADER_STM32IMAGE) {
Patrick Delaunay953d8bf2022-03-28 19:25:29 +020079 size = header.image_length + header.length;
Patrick Delaunay19676ef2021-04-02 14:05:17 +020080 }
Patrick Delaunayc2fdd572020-03-18 09:25:02 +010081 }
82
Simon Glass52cb5042022-10-18 07:46:31 -060083 if (IS_ENABLED(CONFIG_VIDEO))
Patrick Delaunay8040da12020-07-31 16:31:52 +020084 enable_vidconsole();
Patrick Delaunay8610f222020-03-18 09:25:01 +010085
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010086 data = (struct stm32prog_data *)malloc(sizeof(*data));
87
88 if (!data) {
Patrick Delaunay2b15af52020-11-06 19:01:30 +010089 log_err("Alloc failed.");
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010090 return CMD_RET_FAILURE;
91 }
92 stm32prog_data = data;
93
94 ret = stm32prog_init(data, addr, size);
95 if (ret)
Patrick Delaunaybe7d21e2021-05-18 15:12:11 +020096 log_debug("Invalid or missing layout file at 0x%lx.\n", addr);
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010097
98 /* prepare DFU for device read/write */
99 ret = stm32prog_dfu_init(data);
100 if (ret)
101 goto cleanup;
102
103 switch (link) {
Patrick Delaunayb823d992020-03-18 09:25:00 +0100104 case LINK_SERIAL:
105 ret = stm32prog_serial_init(data, dev);
106 if (ret)
107 goto cleanup;
108 reset = stm32prog_serial_loop(data);
109 break;
Patrick Delaunay7daa91d2020-03-18 09:24:49 +0100110 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");
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100122
Patrick Delaunayab198fe2021-05-18 15:12:06 +0200123 if (data->uimage) {
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100124 char boot_addr_start[20];
125 char dtb_addr[20];
Patrick Delaunayab198fe2021-05-18 15:12:06 +0200126 char initrd_addr[40];
Simon Glass43e88a62023-12-15 20:14:22 -0700127 char *fdt_arg, *initrd_arg;
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100128 char *bootm_argv[5] = {
Simon Glass43e88a62023-12-15 20:14:22 -0700129 "bootm", boot_addr_start,
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100130 };
Patrick Delaunay21ea4ef2022-09-06 18:53:19 +0200131 const void *uimage = (void *)data->uimage;
132 const void *dtb = (void *)data->dtb;
133 const void *initrd = (void *)data->initrd;
Patrick Delaunayab198fe2021-05-18 15:12:06 +0200134
Simon Glass43e88a62023-12-15 20:14:22 -0700135 fdt_arg = dtb_addr;
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100136 if (!dtb)
Simon Glass43e88a62023-12-15 20:14:22 -0700137 fdt_arg = env_get("fdtcontroladdr");
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100138 else
Simon Glass43e88a62023-12-15 20:14:22 -0700139 snprintf(dtb_addr, sizeof(dtb_addr) - 1, "0x%p", dtb);
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100140
141 snprintf(boot_addr_start, sizeof(boot_addr_start) - 1,
Patrick Delaunay21ea4ef2022-09-06 18:53:19 +0200142 "0x%p", uimage);
Patrick Delaunayab198fe2021-05-18 15:12:06 +0200143
Simon Glass43e88a62023-12-15 20:14:22 -0700144 initrd_arg = "-";
Patrick Delaunayab198fe2021-05-18 15:12:06 +0200145 if (initrd) {
Simon Glass43e88a62023-12-15 20:14:22 -0700146 snprintf(initrd_addr, sizeof(initrd_addr) - 1,
147 "0x%p:0x%zx", initrd, data->initrd_size);
148 initrd_arg = initrd_addr;
Patrick Delaunayab198fe2021-05-18 15:12:06 +0200149 }
150
Simon Glass43e88a62023-12-15 20:14:22 -0700151 printf("Booting kernel at %s %s %s...\n\n\n", boot_addr_start,
152 initrd_arg, fdt_arg);
153 bootm_argv[2] = initrd_arg;
154 bootm_argv[3] = fdt_arg;
155
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100156 /* Try bootm for legacy and FIT format image */
Patrick Delaunay21ea4ef2022-09-06 18:53:19 +0200157 if (genimg_get_format(uimage) != IMAGE_FORMAT_INVALID)
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100158 do_bootm(cmdtp, 0, 4, bootm_argv);
Simon Glassa5de9972023-02-05 15:36:25 -0700159 else if (IS_ENABLED(CONFIG_CMD_BOOTZ))
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100160 do_bootz(cmdtp, 0, 4, bootm_argv);
161 }
Patrick Delaunayb9ef46b2022-03-28 19:25:32 +0200162 if (data->script)
Simon Glassdaee3ba2023-01-06 08:52:28 -0600163 cmd_source_script(data->script, NULL, NULL);
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100164
Patrick Delaunay7daa91d2020-03-18 09:24:49 +0100165 if (reset) {
166 puts("Reset...\n");
167 run_command("reset", 0);
168 }
169
170 return CMD_RET_SUCCESS;
171
172cleanup:
173 stm32prog_clean(data);
174 free(stm32prog_data);
175 stm32prog_data = NULL;
176
177 return CMD_RET_FAILURE;
178}
179
180U_BOOT_CMD(stm32prog, 5, 0, do_stm32prog,
Patrick Delaunay97076982021-06-28 14:44:33 +0200181 "start communication with tools STM32Cubeprogrammer",
Patrick Delaunay7daa91d2020-03-18 09:24:49 +0100182 "<link> <dev> [<addr>] [<size>]\n"
Patrick Delaunay97076982021-06-28 14:44:33 +0200183 " <link> = serial|usb\n"
184 " <dev> = device instance\n"
185 " <addr> = address of flashlayout\n"
186 " <size> = size of flashlayout (optional for image with STM32 header)\n"
Patrick Delaunay7daa91d2020-03-18 09:24:49 +0100187);
Patrick Delaunayc5112242020-03-18 09:24:55 +0100188
Patrick Delaunayc5112242020-03-18 09:24:55 +0100189
190bool stm32prog_get_fsbl_nor(void)
191{
192 if (stm32prog_data)
193 return stm32prog_data->fsbl_nor_detected;
194
195 return false;
196}