2 * cmd_tizendown.c -- Tizen Downloader
4 * Copyright (C) 2020 Marek Szyprowski <m.szyprowski@samsung.com>
7 * SPDX-License-Identifier: GPL-2.0+
11 #include <bootstage.h>
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 */
25 #define DOWNLOAD_ADDR 0x40000000
28 #define TRANSFER_SIZE SZ_128M
33 #define HASHES_PER_LINE 64 /* Number of "loading" hashes per line */
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[] = {
46 "ramdisk-recovery.img"
48 #elif defined(CONFIG_TARGET_ODROID_XU3) || defined(CONFIG_TARGET_TIZEN)
49 static char *g_update_image_names[] = {
60 #error "Tizen Download is not supported for this board"
63 #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_HOST_ETHER) && !defined(CONFIG_DM_ETH)
64 extern char usb_started;
66 static void do_usb_ether_start(void)
68 bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start");
72 bootstage_mark_name(BOOTSTAGE_ID_ETH_START, "eth_start");
77 static int do_nfs_to_dfu(char *file, char *name)
79 int cnt = 0, alt = dfu_get_alt(name);
80 struct dfu_entity *de;
81 uint done = 0, wdone = 0;
83 void *buf = (void *)DOWNLOAD_ADDR;
84 int buf_size = TRANSFER_SIZE;
87 printf("DFU entity for file %s not found\n", name);
90 de = dfu_get_entity(alt);
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);
103 int write_size = min_t(int, dfu_get_buf_size(),
106 ret = dfu_write(de, buf + wdone, write_size, cnt++);
110 if (cnt % HASHES_PER_LINE == 0)
112 } while (wdone < net_boot_file_size);
115 done += net_boot_file_size;
116 } while (net_boot_file_size == buf_size);
118 ret = dfu_flush(de, buf, 0, cnt);
122 printk("DFU entity write failed\n");
128 static int do_usb_to_dfu(char *file, char *name)
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;
135 void *buf = (void *)DOWNLOAD_ADDR;
136 int buf_size = TRANSFER_SIZE;
141 printf("DFU entity for file %s not found\n", name);
146 if (fs_set_blk_dev("usb", fsdev, FS_TYPE_ANY)) {
148 if (fs_set_blk_dev("usb", fsdev, FS_TYPE_ANY)) {
149 printf("Unsupported USB block device..\n");
154 ret = fs_size(file, &size);
156 printf("File usb%s%s not found\n", fsdev, file);
160 chunk_count = 1 + size / buf_size;
161 de = dfu_get_entity(alt);
164 printf("Reading %s, chunk %d/%d (offset %u) ...\n", file,
165 ++chunk, chunk_count, done);
167 if (fs_set_blk_dev("usb", fsdev, FS_TYPE_ANY)) {
168 printf("%d: Unknown block device..\n", __LINE__);
172 ret = fs_read(file, (unsigned long)buf, done, buf_size, &size);
174 printf("Failed to read %s file %lld.\n", file, size);
181 int write_size = min_t(int, dfu_get_buf_size(),
183 ret = dfu_write(de, buf + wdone, write_size, cnt++);
187 if (cnt % HASHES_PER_LINE == 0)
189 } while (wdone < size);
193 } while (size == buf_size);
195 ret = dfu_flush(de, buf, 0, cnt);
199 printk("DFU entity write failed\n");
206 static int do_tizen_down(char *path, char *file, int (*func)(char *, char *))
208 char src_path[LEN_BUF];
213 int done_bytes[ARRAY_SIZE(g_update_image_names)];
214 char *done_images[ARRAY_SIZE(g_update_image_names)];
220 images = g_update_image_names;
221 image_count = ARRAY_SIZE(g_update_image_names);
224 #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_HOST_ETHER) && !defined(CONFIG_DM_ETH)
226 do_usb_ether_start();
229 ret = dfu_init_env_entities("mmc", "0");
231 printf("DFU init entities failed\n");
235 for (i = 0; i < image_count; i++) {
236 char *file_name = images[i];
239 snprintf(src_path, LEN_BUF, "%s/%s", path, file_name);
240 size = func(src_path, file_name);
243 done_images[done_count] = file_name;
244 done_bytes[done_count] = size;
247 printf("SKIP %s\n", src_path);
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");
258 return CMD_RET_SUCCESS;
261 int do_nfs_down(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
263 puts("TIZEN \"NFS\" Downloader\n");
267 return do_tizen_down(argv[1], NULL, do_nfs_to_dfu);
269 return do_tizen_down(argv[1], argv[2], do_nfs_to_dfu);
271 return CMD_RET_USAGE;
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"
283 "(e.g) nfsdown 192.168.0.1:/nfs [rootfs.img]\n"
286 int do_usb_down(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
288 puts("TIZEN \"USB\" Downloader\n");
292 return do_tizen_down("/updateTizen", NULL, do_usb_to_dfu);
294 return do_tizen_down("/updateTizen", argv[1], do_usb_to_dfu);
296 return CMD_RET_USAGE;
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"