blob: 0722e4a891d43350b2988e0b0a6a62515d79149e [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{
17#ifdef CONFIG_DM_VIDEO
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#endif
39}
40
Simon Glassed38aef2020-05-10 11:40:03 -060041static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc,
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010042 char * const argv[])
43{
44 ulong addr, size;
45 int dev, ret;
46 enum stm32prog_link_t link = LINK_UNDEFINED;
47 bool reset = false;
Patrick Delaunayc2fdd572020-03-18 09:25:02 +010048 struct image_header_s header;
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010049 struct stm32prog_data *data;
Patrick Delaunay41e6ace2020-03-18 09:25:03 +010050 u32 uimage, dtb;
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010051
52 if (argc < 3 || argc > 5)
53 return CMD_RET_USAGE;
54
55 if (!strcmp(argv[1], "usb"))
56 link = LINK_USB;
Patrick Delaunayb823d992020-03-18 09:25:00 +010057 else if (!strcmp(argv[1], "serial"))
58 link = LINK_SERIAL;
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010059
60 if (link == LINK_UNDEFINED) {
61 pr_err("not supported link=%s\n", argv[1]);
62 return CMD_RET_USAGE;
63 }
Patrick Delaunayb823d992020-03-18 09:25:00 +010064
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010065 dev = (int)simple_strtoul(argv[2], NULL, 10);
66
67 addr = STM32_DDR_BASE;
68 size = 0;
69 if (argc > 3) {
70 addr = simple_strtoul(argv[3], NULL, 16);
71 if (!addr)
72 return CMD_RET_FAILURE;
73 }
74 if (argc > 4)
75 size = simple_strtoul(argv[4], NULL, 16);
76
Patrick Delaunayc2fdd572020-03-18 09:25:02 +010077 /* check STM32IMAGE presence */
78 if (size == 0 &&
79 !stm32prog_header_check((struct raw_header_s *)addr, &header)) {
80 size = header.image_length + BL_HEADER_SIZE;
81
82 /* uImage detected in STM32IMAGE, execute the script */
83 if (IMAGE_FORMAT_LEGACY ==
84 genimg_get_format((void *)(addr + BL_HEADER_SIZE)))
85 return image_source_script(addr + BL_HEADER_SIZE,
86 "script@1");
87 }
88
Patrick Delaunay8610f222020-03-18 09:25:01 +010089 enable_vidconsole();
90
Patrick Delaunay7daa91d2020-03-18 09:24:49 +010091 data = (struct stm32prog_data *)malloc(sizeof(*data));
92
93 if (!data) {
94 pr_err("Alloc failed.");
95 return CMD_RET_FAILURE;
96 }
97 stm32prog_data = data;
98
99 ret = stm32prog_init(data, addr, size);
100 if (ret)
101 printf("Invalid or missing layout file.");
102
103 /* prepare DFU for device read/write */
104 ret = stm32prog_dfu_init(data);
105 if (ret)
106 goto cleanup;
107
108 switch (link) {
Patrick Delaunayb823d992020-03-18 09:25:00 +0100109 case LINK_SERIAL:
110 ret = stm32prog_serial_init(data, dev);
111 if (ret)
112 goto cleanup;
113 reset = stm32prog_serial_loop(data);
114 break;
Patrick Delaunay7daa91d2020-03-18 09:24:49 +0100115 case LINK_USB:
116 reset = stm32prog_usb_loop(data, dev);
117 break;
118 default:
119 goto cleanup;
120 }
121
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100122 uimage = data->uimage;
123 dtb = data->dtb;
124
Patrick Delaunay7daa91d2020-03-18 09:24:49 +0100125 stm32prog_clean(data);
126 free(stm32prog_data);
127 stm32prog_data = NULL;
128
129 puts("Download done\n");
Patrick Delaunay41e6ace2020-03-18 09:25:03 +0100130
131 if (uimage) {
132 char boot_addr_start[20];
133 char dtb_addr[20];
134 char *bootm_argv[5] = {
135 "bootm", boot_addr_start, "-", dtb_addr, NULL
136 };
137 if (!dtb)
138 bootm_argv[3] = env_get("fdtcontroladdr");
139 else
140 snprintf(dtb_addr, sizeof(dtb_addr) - 1,
141 "0x%x", dtb);
142
143 snprintf(boot_addr_start, sizeof(boot_addr_start) - 1,
144 "0x%x", uimage);
145 printf("Booting kernel at %s - %s...\n\n\n",
146 boot_addr_start, bootm_argv[3]);
147 /* Try bootm for legacy and FIT format image */
148 if (genimg_get_format((void *)uimage) != IMAGE_FORMAT_INVALID)
149 do_bootm(cmdtp, 0, 4, bootm_argv);
150 else if CONFIG_IS_ENABLED(CMD_BOOTZ)
151 do_bootz(cmdtp, 0, 4, bootm_argv);
152 }
153
Patrick Delaunay7daa91d2020-03-18 09:24:49 +0100154 if (reset) {
155 puts("Reset...\n");
156 run_command("reset", 0);
157 }
158
159 return CMD_RET_SUCCESS;
160
161cleanup:
162 stm32prog_clean(data);
163 free(stm32prog_data);
164 stm32prog_data = NULL;
165
166 return CMD_RET_FAILURE;
167}
168
169U_BOOT_CMD(stm32prog, 5, 0, do_stm32prog,
170 "<link> <dev> [<addr>] [<size>]\n"
171 "start communication with tools STM32Cubeprogrammer on <link> with Flashlayout at <addr>",
Patrick Delaunayb823d992020-03-18 09:25:00 +0100172 "<link> = serial|usb\n"
Patrick Delaunay7daa91d2020-03-18 09:24:49 +0100173 "<dev> = device instance\n"
174 "<addr> = address of flashlayout\n"
175 "<size> = size of flashlayout\n"
176);
Patrick Delaunayc5112242020-03-18 09:24:55 +0100177
178bool stm32prog_get_tee_partitions(void)
179{
180 if (stm32prog_data)
181 return stm32prog_data->tee_detected;
182
183 return false;
184}
185
186bool stm32prog_get_fsbl_nor(void)
187{
188 if (stm32prog_data)
189 return stm32prog_data->fsbl_nor_detected;
190
191 return false;
192}