]> Git Repo - J-u-boot.git/blame - common/spl/spl_ymodem.c
common: Remove <common.h> and add needed includes
[J-u-boot.git] / common / spl / spl_ymodem.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
24de357a
MP
2/*
3 * (C) Copyright 2000-2004
4 * Wolfgang Denk, DENX Software Engineering, [email protected].
5 *
6 * (C) Copyright 2011
7 * Texas Instruments, <www.ti.com>
8 *
9 * Matt Porter <[email protected]>
24de357a 10 */
0c670fc1 11#include <gzip.h>
4d72caa5 12#include <image.h>
f7ae49fc 13#include <log.h>
47f7bcae 14#include <spl.h>
24de357a
MP
15#include <xyzModem.h>
16#include <asm/u-boot.h>
b08c8c48 17#include <linux/libfdt.h>
24de357a
MP
18
19#define BUF_SIZE 1024
20
fa715193
LV
21/*
22 * Information required to load image using ymodem.
23 *
24 * @image_read: Now of bytes read from the image.
25 * @buf: pointer to the previous read block.
26 */
27struct ymodem_fit_info {
28 int image_read;
29 char *buf;
30};
31
24de357a
MP
32static int getcymodem(void) {
33 if (tstc())
c670aeee 34 return (getchar());
24de357a
MP
35 return -1;
36}
37
fa715193
LV
38static ulong ymodem_read_fit(struct spl_load_info *load, ulong offset,
39 ulong size, void *addr)
40{
095764e3 41 int res, err, buf_offset;
fa715193
LV
42 struct ymodem_fit_info *info = load->priv;
43 char *buf = info->buf;
c1335e2c 44 ulong copy_size = size;
fa715193
LV
45
46 while (info->image_read < offset) {
47 res = xyzModem_stream_read(buf, BUF_SIZE, &err);
48 if (res <= 0)
9d6ee3e2
AD
49 break;
50
fa715193
LV
51 info->image_read += res;
52 }
53
54 if (info->image_read > offset) {
55 res = info->image_read - offset;
095764e3
LV
56 if (info->image_read % BUF_SIZE)
57 buf_offset = (info->image_read % BUF_SIZE);
58 else
59 buf_offset = BUF_SIZE;
c1335e2c
VR
60
61 if (res > copy_size) {
62 memcpy(addr, &buf[buf_offset - res], copy_size);
63 goto done;
64 }
095764e3 65 memcpy(addr, &buf[buf_offset - res], res);
fa715193 66 addr = addr + res;
c1335e2c 67 copy_size -= res;
fa715193
LV
68 }
69
70 while (info->image_read < offset + size) {
71 res = xyzModem_stream_read(buf, BUF_SIZE, &err);
72 if (res <= 0)
9d6ee3e2 73 break;
fa715193 74
fa715193 75 info->image_read += res;
c1335e2c
VR
76 if (res > copy_size) {
77 memcpy(addr, buf, copy_size);
78 goto done;
79 }
80 memcpy(addr, buf, res);
fa715193 81 addr += res;
c1335e2c 82 copy_size -= res;
fa715193
LV
83 }
84
c1335e2c 85done:
fa715193
LV
86 return size;
87}
88
e413033d
AD
89int spl_ymodem_load_image(struct spl_image_info *spl_image,
90 struct spl_boot_device *bootdev)
24de357a 91{
92e5cb80 92 ulong size = 0;
24de357a
MP
93 int err;
94 int res;
95 int ret;
96 connection_info_t info;
97 char buf[BUF_SIZE];
f3543e69 98 struct legacy_img_hdr *ih = NULL;
24de357a
MP
99 ulong addr = 0;
100
101 info.mode = xyzModem_ymodem;
102 ret = xyzModem_stream_open(&info, &err);
fa715193
LV
103 if (ret) {
104 printf("spl: ymodem err - %s\n", xyzModem_error(err));
105 return ret;
106 }
107
108 res = xyzModem_stream_read(buf, BUF_SIZE, &err);
109 if (res <= 0)
110 goto end_stream;
111
792dd570 112 if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) &&
f3543e69 113 image_get_magic((struct legacy_img_hdr *)buf) == FDT_MAGIC) {
792dd570 114 addr = CONFIG_SYS_LOAD_ADDR;
f3543e69 115 ih = (struct legacy_img_hdr *)addr;
792dd570
MV
116
117 memcpy((void *)addr, buf, res);
118 size += res;
119 addr += res;
120
121 while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) {
122 memcpy((void *)addr, buf, res);
123 size += res;
124 addr += res;
125 }
126
2e0429bc 127 ret = spl_parse_image_header(spl_image, bootdev, ih);
792dd570
MV
128 if (ret)
129 return ret;
130 } else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
f3543e69 131 image_get_magic((struct legacy_img_hdr *)buf) == FDT_MAGIC) {
fa715193
LV
132 struct spl_load_info load;
133 struct ymodem_fit_info info;
134
135 debug("Found FIT\n");
fa715193 136 load.priv = (void *)&info;
5271e359 137 spl_set_bl_len(&load, 1);
fa715193
LV
138 info.buf = buf;
139 info.image_read = BUF_SIZE;
140 load.read = ymodem_read_fit;
f4d7d859 141 ret = spl_load_simple_fit(spl_image, &load, 0, (void *)buf);
fa715193 142 size = info.image_read;
24de357a 143
fa715193
LV
144 while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0)
145 size += res;
146 } else {
f3543e69 147 ih = (struct legacy_img_hdr *)buf;
2e0429bc 148 ret = spl_parse_image_header(spl_image, bootdev, ih);
fa715193 149 if (ret)
6d8dbe48 150 goto end_stream;
92e5cb80
MV
151#ifdef CONFIG_SPL_GZIP
152 if (ih->ih_comp == IH_COMP_GZIP)
153 addr = CONFIG_SYS_LOAD_ADDR;
154 else
155#endif
156 addr = spl_image->load_addr;
fa715193 157 memcpy((void *)addr, buf, res);
f3543e69 158 ih = (struct legacy_img_hdr *)addr;
fa715193
LV
159 size += res;
160 addr += res;
161
162 while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) {
163 memcpy((void *)addr, buf, res);
24de357a
MP
164 size += res;
165 addr += res;
24de357a 166 }
24de357a
MP
167 }
168
fa715193 169end_stream:
24de357a
MP
170 xyzModem_stream_close(&err);
171 xyzModem_stream_terminate(false, &getcymodem);
172
92e5cb80 173 printf("Loaded %lu bytes\n", size);
6d8dbe48 174
d574c19b
MV
175#ifdef CONFIG_SPL_GZIP
176 if (!(IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
f3543e69 177 image_get_magic((struct legacy_img_hdr *)buf) == FDT_MAGIC) &&
d574c19b
MV
178 (ih->ih_comp == IH_COMP_GZIP)) {
179 if (gunzip((void *)(spl_image->load_addr + sizeof(*ih)),
180 CONFIG_SYS_BOOTM_LEN,
181 (void *)(CONFIG_SYS_LOAD_ADDR + sizeof(*ih)),
182 &size)) {
183 puts("Uncompressing error\n");
184 return -EIO;
185 }
186 }
187#endif
188
6d8dbe48 189 return ret;
24de357a 190}
ebc4ef61 191SPL_LOAD_IMAGE_METHOD("UART", 0, BOOT_DEVICE_UART, spl_ymodem_load_image);
This page took 0.476937 seconds and 4 git commands to generate.