Merge tag 'u-boot-atmel-fixes-2020.07-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/u-boot.git] / arch / arm / mach-stm32mp / cmd_stm32prog / cmd_stm32prog.c
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
15 static 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
41 static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc,
42                         char * const argv[])
43 {
44         ulong   addr, size;
45         int dev, ret;
46         enum stm32prog_link_t link = LINK_UNDEFINED;
47         bool reset = false;
48         struct image_header_s header;
49         struct stm32prog_data *data;
50         u32 uimage, dtb;
51
52         if (argc < 3 ||  argc > 5)
53                 return CMD_RET_USAGE;
54
55         if (!strcmp(argv[1], "usb"))
56                 link = LINK_USB;
57         else if (!strcmp(argv[1], "serial"))
58                 link = LINK_SERIAL;
59
60         if (link == LINK_UNDEFINED) {
61                 pr_err("not supported link=%s\n", argv[1]);
62                 return CMD_RET_USAGE;
63         }
64
65         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
77         /* 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
89         enable_vidconsole();
90
91         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) {
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
178 bool stm32prog_get_tee_partitions(void)
179 {
180         if (stm32prog_data)
181                 return stm32prog_data->tee_detected;
182
183         return false;
184 }
185
186 bool stm32prog_get_fsbl_nor(void)
187 {
188         if (stm32prog_data)
189                 return stm32prog_data->fsbl_nor_detected;
190
191         return false;
192 }