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 	u32 uimage, dtb;
49 
50 	if (argc < 3 ||  argc > 5)
51 		return CMD_RET_USAGE;
52 
53 	if (IS_ENABLED(CONFIG_CMD_STM32PROG_USB) && !strcmp(argv[1], "usb"))
54 		link = LINK_USB;
55 	else if (IS_ENABLED(CONFIG_CMD_STM32PROG_SERIAL) && !strcmp(argv[1], "serial"))
56 		link = LINK_SERIAL;
57 
58 	if (link == LINK_UNDEFINED) {
59 		log_err("not supported link=%s\n", argv[1]);
60 		return CMD_RET_USAGE;
61 	}
62 
63 	dev = (int)simple_strtoul(argv[2], NULL, 10);
64 
65 	addr = STM32_DDR_BASE;
66 	size = 0;
67 	if (argc > 3) {
68 		addr = simple_strtoul(argv[3], NULL, 16);
69 		if (!addr)
70 			return CMD_RET_FAILURE;
71 	}
72 	if (argc > 4)
73 		size = simple_strtoul(argv[4], NULL, 16);
74 
75 	/* check STM32IMAGE presence */
76 	if (size == 0) {
77 		stm32prog_header_check((struct raw_header_s *)addr, &header);
78 		if (header.type == HEADER_STM32IMAGE) {
79 			size = header.image_length + BL_HEADER_SIZE;
80 
81 			/* uImage detected in STM32IMAGE, execute the script */
82 			if (IMAGE_FORMAT_LEGACY ==
83 			    genimg_get_format((void *)(addr + BL_HEADER_SIZE)))
84 				return image_source_script(addr + BL_HEADER_SIZE, "script@1");
85 		}
86 	}
87 
88 	if (IS_ENABLED(CONFIG_DM_VIDEO))
89 		enable_vidconsole();
90 
91 	data = (struct stm32prog_data *)malloc(sizeof(*data));
92 
93 	if (!data) {
94 		log_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) {
109 	case LINK_SERIAL:
110 		ret = stm32prog_serial_init(data, dev);
111 		if (ret)
112 			goto cleanup;
113 		reset = stm32prog_serial_loop(data);
114 		break;
115 	case LINK_USB:
116 		reset = stm32prog_usb_loop(data, dev);
117 		break;
118 	default:
119 		goto cleanup;
120 	}
121 
122 	uimage = data->uimage;
123 	dtb = data->dtb;
124 
125 	stm32prog_clean(data);
126 	free(stm32prog_data);
127 	stm32prog_data = NULL;
128 
129 	puts("Download done\n");
130 
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 
154 	if (reset) {
155 		puts("Reset...\n");
156 		run_command("reset", 0);
157 	}
158 
159 	return CMD_RET_SUCCESS;
160 
161 cleanup:
162 	stm32prog_clean(data);
163 	free(stm32prog_data);
164 	stm32prog_data = NULL;
165 
166 	return CMD_RET_FAILURE;
167 }
168 
169 U_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>",
172 	   "<link> = serial|usb\n"
173 	   "<dev>  = device instance\n"
174 	   "<addr> = address of flashlayout\n"
175 	   "<size> = size of flashlayout\n"
176 );
177 
stm32prog_get_tee_partitions(void)178 bool stm32prog_get_tee_partitions(void)
179 {
180 	if (stm32prog_data)
181 		return stm32prog_data->tee_detected;
182 
183 	return false;
184 }
185 
stm32prog_get_fsbl_nor(void)186 bool stm32prog_get_fsbl_nor(void)
187 {
188 	if (stm32prog_data)
189 		return stm32prog_data->fsbl_nor_detected;
190 
191 	return false;
192 }
193