samsung: tizen_amlogic: increase ramdisk size from 8M to 32M
[platform/kernel/u-boot.git] / cmd / tizendown.c
1 /*
2  * cmd_tizendown.c -- Tizen Downloader
3  *
4  * Copyright (C) 2020 Marek Szyprowski <m.szyprowski@samsung.com>
5  * All rights reserved.
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <malloc.h>
11 #include <bootstage.h>
12 #include <common.h>
13 #include <command.h>
14 #include <errno.h>
15 #include <memalign.h>
16 #include <net.h>
17 #include <usb.h>
18 #include <dfu.h>
19 #include <fs.h>
20
21 #ifdef CONFIG_SYS_SDRAM_BASE
22 #define DOWNLOAD_ADDR      (CONFIG_SYS_SDRAM_BASE + SZ_64K)
23 /* 64K shift to avoid 0 (NULL) DOWNLOAD_ADDR on RPi3/4 */
24 #else
25 #define DOWNLOAD_ADDR      0x40000000
26 #endif
27
28 #define TRANSFER_SIZE  SZ_128M
29
30 #define LEN_BUF                 128
31 #define LEN_NAME                32
32
33 #define HASHES_PER_LINE 64      /* Number of "loading" hashes per line  */
34
35 #if defined(CONFIG_TARGET_RPI_3) || \
36     defined(CONFIG_TARGET_RPI_4) || \
37     defined(CONFIG_TARGET_RPI_3_32B) || \
38     defined(CONFIG_TARGET_RPI_4_32B)
39 static char *g_update_image_names[] = {
40         "boot.img",
41         "rootfs.img",
42         "system-data.img",
43         "user.img",
44         "modules.img",
45         "ramdisk.img",
46         "ramdisk-recovery.img"
47 };
48 #elif defined(CONFIG_TARGET_ODROID_XU3) || defined(CONFIG_TARGET_TIZEN)
49 static char *g_update_image_names[] = {
50         "u-boot-mmc.bin",
51         "params.bin",
52         "boot.img",
53         "rootfs.img",
54         "system-data.img",
55         "user.img",
56         "modules.img",
57         "ramdisk.img"
58 };
59 #else
60 #error "Tizen Download is not supported for this board"
61 #endif
62
63 #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_HOST_ETHER) && !defined(CONFIG_DM_ETH)
64 extern char usb_started;
65
66 static void do_usb_ether_start(void)
67 {
68         bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start");
69         if (usb_init() < 0)
70                 return;
71
72         bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
73         usb_host_eth_scan(1);
74 }
75 #endif
76
77 static int do_nfs_to_dfu(char *file, char *name)
78 {
79         int cnt = 0, alt = dfu_get_alt(name);
80         struct dfu_entity *de;
81         uint done = 0, wdone = 0;
82         int ret;
83         void *buf = (void *)DOWNLOAD_ADDR;
84         int buf_size = TRANSFER_SIZE;
85
86         if (alt < 0) {
87                 printf("DFU entity for file %s not found\n", name);
88                 return -1;
89         }
90         de = dfu_get_entity(alt);
91
92         do {
93                 printf("Downloading %s, offset %u...\n", file, done);
94                 ret = netboot_nfs((unsigned long)buf, file, done, buf_size);
95                 if (ret != CMD_RET_SUCCESS) {
96                         printf("NFS download of file %s failed!!\n", file);
97                         return -1;
98                 }
99
100                 puts("Writing: ");
101                 wdone = 0;
102                 do {
103                         int write_size = min_t(int, dfu_get_buf_size(),
104                                              net_boot_file_size);
105
106                         ret = dfu_write(de, buf + wdone, write_size, cnt++);
107                         if (ret)
108                                 goto done;
109                         wdone += write_size;
110                         if (cnt % HASHES_PER_LINE == 0)
111                                 puts("\n\t ");
112                 } while (wdone < net_boot_file_size);
113                 puts("\n");
114
115                 done += net_boot_file_size;
116         } while (net_boot_file_size == buf_size);
117
118         ret = dfu_flush(de, buf, 0, cnt);
119         puts("");
120 done:
121         if (ret) {
122                 printk("DFU entity write failed\n");
123                 return -1;
124         }
125         return (int)done;
126 }
127
128 static int do_usb_to_dfu(char *file, char *name)
129 {
130         int cnt = 0, alt = dfu_get_alt(name);
131         int chunk = 0, chunk_count;
132         struct dfu_entity *de;
133         uint done = 0, wdone = 0;
134         int ret;
135         void *buf = (void *)DOWNLOAD_ADDR;
136         int buf_size = TRANSFER_SIZE;
137         loff_t size = 0;
138         char *fsdev;
139
140         if (alt < 0) {
141                 printf("DFU entity for file %s not found\n", name);
142                 return -1;
143         }
144
145         fsdev = "0:1";
146         if (fs_set_blk_dev("usb", fsdev, FS_TYPE_ANY)) {
147                 fsdev = "0:0";
148                 if (fs_set_blk_dev("usb", fsdev, FS_TYPE_ANY)) {
149                         printf("Unsupported USB block device..\n");
150                         return -1;
151                 }
152         }
153
154         ret = fs_size(file, &size);
155         if (ret < 0) {
156                 printf("File usb%s%s not found\n", fsdev, file);
157                 return -1;
158         }
159
160         chunk_count = 1 + size / buf_size;
161         de = dfu_get_entity(alt);
162
163         do {
164                 printf("Reading %s, chunk %d/%d (offset %u) ...\n", file,
165                         ++chunk, chunk_count, done);
166
167                 if (fs_set_blk_dev("usb", fsdev, FS_TYPE_ANY)) {
168                         printf("%d: Unknown block device..\n", __LINE__);
169                         return -1;
170                 }
171
172                 ret = fs_read(file, (unsigned long)buf, done, buf_size, &size);
173                 if (ret < 0) {
174                         printf("Failed to read %s file %lld.\n", file, size);
175                         return -1;
176                 }
177
178                 puts("Writing: ");
179                 wdone = 0;
180                 do {
181                         int write_size = min_t(int, dfu_get_buf_size(),
182                                                size);
183                         ret = dfu_write(de, buf + wdone, write_size, cnt++);
184                         if (ret)
185                                 goto done;
186                         wdone += write_size;
187                         if (cnt % HASHES_PER_LINE == 0)
188                                 puts("\n\t ");
189                 } while (wdone < size);
190                 puts("\n");
191
192                 done += size;
193         } while (size == buf_size);
194
195         ret = dfu_flush(de, buf, 0, cnt);
196         puts("\n");
197 done:
198         if (ret) {
199                 printk("DFU entity write failed\n");
200                 return -1;
201         }
202         return (int)done;
203 }
204
205
206 static int do_tizen_down(char *path, char *file, int (*func)(char *, char *))
207 {
208         char src_path[LEN_BUF];
209         int i, ret = 0;
210         char **images;
211         int image_count;
212         int done_count = 0;
213         int done_bytes[ARRAY_SIZE(g_update_image_names)];
214         char *done_images[ARRAY_SIZE(g_update_image_names)];
215
216         if (file) {
217                 images = &file;
218                 image_count = 1;
219         } else {
220                 images = g_update_image_names;
221                 image_count = ARRAY_SIZE(g_update_image_names);
222         }
223
224 #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_HOST_ETHER) && !defined(CONFIG_DM_ETH)
225         if (!usb_started)
226                 do_usb_ether_start();
227 #endif
228
229         ret = dfu_init_env_entities("mmc", "0");
230         if (ret) {
231                 printf("DFU init entities failed\n");
232                 return ret;
233         }
234
235         for (i = 0; i < image_count; i++) {
236                 char *file_name = images[i];
237                 int size;
238
239                 snprintf(src_path, LEN_BUF, "%s/%s", path, file_name);
240                 size = func(src_path, file_name);
241
242                 if (size > 0) {
243                         done_images[done_count] = file_name;
244                         done_bytes[done_count] = size;
245                         done_count++;
246                 } else {
247                         printf("SKIP %s\n", src_path);
248                 }
249         }
250
251         dfu_free_entities();
252
253         puts("########################################\n");
254         for (i = 0; i < done_count; i++)
255                 printf("%20s -\t%10d Bytes\n", done_images[i], done_bytes[i]);
256         puts("########################################\n");
257
258         return CMD_RET_SUCCESS;
259 }
260
261 int do_nfs_down(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
262 {
263         puts("TIZEN \"NFS\" Downloader\n");
264
265         switch (argc) {
266         case 2:
267                 return do_tizen_down(argv[1], NULL, do_nfs_to_dfu);
268         case 3:
269                 return do_tizen_down(argv[1], argv[2], do_nfs_to_dfu);
270         default:
271                 return CMD_RET_USAGE;
272         }
273 }
274
275 U_BOOT_CMD(nfsdown, CONFIG_SYS_MAXARGS, 1, do_nfs_down,
276            "TIZEN \"NFS\" downloader",
277            "nfsdown [<IP_ADDR>:]<IMG_PATH> [image file name]\n"
278            "  - device firmware upgrade via nfs for Tizen\n"
279            "    fusing images from <IP_ADDR>:<IMG_PATH> to MMC.\n"
280            "  - required to set env for ipaddr, serverip, gatewayip,\n"
281            "    and netmask.\n"
282            "\n"
283            "(e.g) nfsdown 192.168.0.1:/nfs [rootfs.img]\n"
284 );
285
286 int do_usb_down(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
287 {
288         puts("TIZEN \"USB\" Downloader\n");
289
290         switch (argc) {
291         case 1:
292                 return do_tizen_down("/updateTizen", NULL, do_usb_to_dfu);
293         case 2:
294                 return do_tizen_down("/updateTizen", argv[1], do_usb_to_dfu);
295         default:
296                 return CMD_RET_USAGE;
297         }
298 }
299
300 U_BOOT_CMD(usbdown, CONFIG_SYS_MAXARGS, 1, do_usb_down,
301            "TIZEN \"USB\" downloader",
302            "usbdown [image file name]\n"
303            "  - device firmware upgrade via USB mass-storage for Tizen\n"
304            "    fusing images from \"updateTizen\" USB directory to MMC.\n"
305            "  - \"updateTizen\" directory has to be on the first partition\n"
306            "    of the USB storage\n"
307            "(e.g) tizendown [rootfs.img]\n\n"
308 );