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