xref: /rk3399_rockchip-uboot/common/spl/spl_ymodem.c (revision fa715193c083bbde4985c4ff1e49e288ec29763a)
147f7bcaeSTom Rini /*
247f7bcaeSTom Rini  * (C) Copyright 2000-2004
347f7bcaeSTom Rini  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
447f7bcaeSTom Rini  *
547f7bcaeSTom Rini  * (C) Copyright 2011
647f7bcaeSTom Rini  * Texas Instruments, <www.ti.com>
747f7bcaeSTom Rini  *
847f7bcaeSTom Rini  * Matt Porter <mporter@ti.com>
947f7bcaeSTom Rini  *
101a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
1147f7bcaeSTom Rini  */
1247f7bcaeSTom Rini #include <common.h>
1347f7bcaeSTom Rini #include <spl.h>
1447f7bcaeSTom Rini #include <xyzModem.h>
1547f7bcaeSTom Rini #include <asm/u-boot.h>
1647f7bcaeSTom Rini #include <asm/utils.h>
17*fa715193SLokesh Vutla #include <libfdt.h>
1847f7bcaeSTom Rini 
1947f7bcaeSTom Rini #define BUF_SIZE 1024
2047f7bcaeSTom Rini 
21*fa715193SLokesh Vutla /*
22*fa715193SLokesh Vutla  * Information required to load image using ymodem.
23*fa715193SLokesh Vutla  *
24*fa715193SLokesh Vutla  * @image_read: Now of bytes read from the image.
25*fa715193SLokesh Vutla  * @buf: pointer to the previous read block.
26*fa715193SLokesh Vutla  */
27*fa715193SLokesh Vutla struct ymodem_fit_info {
28*fa715193SLokesh Vutla 	int image_read;
29*fa715193SLokesh Vutla 	char *buf;
30*fa715193SLokesh Vutla };
31*fa715193SLokesh Vutla 
3247f7bcaeSTom Rini static int getcymodem(void) {
3347f7bcaeSTom Rini 	if (tstc())
3447f7bcaeSTom Rini 		return (getc());
3547f7bcaeSTom Rini 	return -1;
3647f7bcaeSTom Rini }
3747f7bcaeSTom Rini 
38*fa715193SLokesh Vutla static ulong ymodem_read_fit(struct spl_load_info *load, ulong offset,
39*fa715193SLokesh Vutla 			     ulong size, void *addr)
40*fa715193SLokesh Vutla {
41*fa715193SLokesh Vutla 	int res, err;
42*fa715193SLokesh Vutla 	struct ymodem_fit_info *info = load->priv;
43*fa715193SLokesh Vutla 	char *buf = info->buf;
44*fa715193SLokesh Vutla 
45*fa715193SLokesh Vutla 	while (info->image_read < offset) {
46*fa715193SLokesh Vutla 		res = xyzModem_stream_read(buf, BUF_SIZE, &err);
47*fa715193SLokesh Vutla 		if (res <= 0)
48*fa715193SLokesh Vutla 			return res;
49*fa715193SLokesh Vutla 		info->image_read += res;
50*fa715193SLokesh Vutla 	}
51*fa715193SLokesh Vutla 
52*fa715193SLokesh Vutla 	if (info->image_read > offset) {
53*fa715193SLokesh Vutla 		res = info->image_read - offset;
54*fa715193SLokesh Vutla 		memcpy(addr, &buf[BUF_SIZE - res], res);
55*fa715193SLokesh Vutla 		addr = addr + res;
56*fa715193SLokesh Vutla 	}
57*fa715193SLokesh Vutla 
58*fa715193SLokesh Vutla 	while (info->image_read < offset + size) {
59*fa715193SLokesh Vutla 		res = xyzModem_stream_read(buf, BUF_SIZE, &err);
60*fa715193SLokesh Vutla 		if (res <= 0)
61*fa715193SLokesh Vutla 			return res;
62*fa715193SLokesh Vutla 
63*fa715193SLokesh Vutla 		memcpy(addr, buf, res);
64*fa715193SLokesh Vutla 		info->image_read += res;
65*fa715193SLokesh Vutla 		addr += res;
66*fa715193SLokesh Vutla 	}
67*fa715193SLokesh Vutla 
68*fa715193SLokesh Vutla 	return size;
69*fa715193SLokesh Vutla }
70*fa715193SLokesh Vutla 
7136afd451SNikita Kiryanov int spl_ymodem_load_image(void)
7247f7bcaeSTom Rini {
7347f7bcaeSTom Rini 	int size = 0;
7447f7bcaeSTom Rini 	int err;
7547f7bcaeSTom Rini 	int res;
7647f7bcaeSTom Rini 	int ret;
7747f7bcaeSTom Rini 	connection_info_t info;
7847f7bcaeSTom Rini 	char buf[BUF_SIZE];
7947f7bcaeSTom Rini 	ulong addr = 0;
8047f7bcaeSTom Rini 
8147f7bcaeSTom Rini 	info.mode = xyzModem_ymodem;
8247f7bcaeSTom Rini 	ret = xyzModem_stream_open(&info, &err);
83*fa715193SLokesh Vutla 	if (ret) {
8447f7bcaeSTom Rini 		printf("spl: ymodem err - %s\n", xyzModem_error(err));
8536afd451SNikita Kiryanov 		return ret;
8647f7bcaeSTom Rini 	}
8747f7bcaeSTom Rini 
88*fa715193SLokesh Vutla 	res = xyzModem_stream_read(buf, BUF_SIZE, &err);
89*fa715193SLokesh Vutla 	if (res <= 0)
90*fa715193SLokesh Vutla 		goto end_stream;
91*fa715193SLokesh Vutla 
92*fa715193SLokesh Vutla 	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
93*fa715193SLokesh Vutla 	    image_get_magic((struct image_header *)buf) == FDT_MAGIC) {
94*fa715193SLokesh Vutla 		struct spl_load_info load;
95*fa715193SLokesh Vutla 		struct ymodem_fit_info info;
96*fa715193SLokesh Vutla 
97*fa715193SLokesh Vutla 		debug("Found FIT\n");
98*fa715193SLokesh Vutla 		load.dev = NULL;
99*fa715193SLokesh Vutla 		load.priv = (void *)&info;
100*fa715193SLokesh Vutla 		load.filename = NULL;
101*fa715193SLokesh Vutla 		load.bl_len = 1;
102*fa715193SLokesh Vutla 		info.buf = buf;
103*fa715193SLokesh Vutla 		info.image_read = BUF_SIZE;
104*fa715193SLokesh Vutla 		load.read = ymodem_read_fit;
105*fa715193SLokesh Vutla 		ret =  spl_load_simple_fit(&load, 0, (void *)buf);
106*fa715193SLokesh Vutla 		size = info.image_read;
107*fa715193SLokesh Vutla 
108*fa715193SLokesh Vutla 		while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0)
109*fa715193SLokesh Vutla 			size += res;
110*fa715193SLokesh Vutla 	} else {
111*fa715193SLokesh Vutla 		spl_parse_image_header((struct image_header *)buf);
112*fa715193SLokesh Vutla 		ret = spl_parse_image_header((struct image_header *)buf);
113*fa715193SLokesh Vutla 		if (ret)
114*fa715193SLokesh Vutla 			return ret;
115*fa715193SLokesh Vutla 		addr = spl_image.load_addr;
116*fa715193SLokesh Vutla 		memcpy((void *)addr, buf, res);
117*fa715193SLokesh Vutla 		size += res;
118*fa715193SLokesh Vutla 		addr += res;
119*fa715193SLokesh Vutla 
120*fa715193SLokesh Vutla 		while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) {
121*fa715193SLokesh Vutla 			memcpy((void *)addr, buf, res);
122*fa715193SLokesh Vutla 			size += res;
123*fa715193SLokesh Vutla 			addr += res;
124*fa715193SLokesh Vutla 		}
125*fa715193SLokesh Vutla 	}
126*fa715193SLokesh Vutla 
127*fa715193SLokesh Vutla end_stream:
12847f7bcaeSTom Rini 	xyzModem_stream_close(&err);
12947f7bcaeSTom Rini 	xyzModem_stream_terminate(false, &getcymodem);
13047f7bcaeSTom Rini 
13147f7bcaeSTom Rini 	printf("Loaded %d bytes\n", size);
13236afd451SNikita Kiryanov 	return 0;
13347f7bcaeSTom Rini }
134