]>
Commit | Line | Data |
---|---|---|
24de357a MP |
1 | /* |
2 | * (C) Copyright 2000-2004 | |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | * | |
5 | * (C) Copyright 2011 | |
6 | * Texas Instruments, <www.ti.com> | |
7 | * | |
8 | * Matt Porter <mporter@ti.com> | |
9 | * | |
1a459660 | 10 | * SPDX-License-Identifier: GPL-2.0+ |
24de357a MP |
11 | */ |
12 | #include <common.h> | |
47f7bcae | 13 | #include <spl.h> |
24de357a MP |
14 | #include <xyzModem.h> |
15 | #include <asm/u-boot.h> | |
16 | #include <asm/utils.h> | |
fa715193 | 17 | #include <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 | */ | |
27 | struct ymodem_fit_info { | |
28 | int image_read; | |
29 | char *buf; | |
30 | }; | |
31 | ||
24de357a MP |
32 | static int getcymodem(void) { |
33 | if (tstc()) | |
34 | return (getc()); | |
35 | return -1; | |
36 | } | |
37 | ||
fa715193 LV |
38 | static ulong ymodem_read_fit(struct spl_load_info *load, ulong offset, |
39 | ulong size, void *addr) | |
40 | { | |
41 | int res, err; | |
42 | struct ymodem_fit_info *info = load->priv; | |
43 | char *buf = info->buf; | |
44 | ||
45 | while (info->image_read < offset) { | |
46 | res = xyzModem_stream_read(buf, BUF_SIZE, &err); | |
47 | if (res <= 0) | |
48 | return res; | |
49 | info->image_read += res; | |
50 | } | |
51 | ||
52 | if (info->image_read > offset) { | |
53 | res = info->image_read - offset; | |
54 | memcpy(addr, &buf[BUF_SIZE - res], res); | |
55 | addr = addr + res; | |
56 | } | |
57 | ||
58 | while (info->image_read < offset + size) { | |
59 | res = xyzModem_stream_read(buf, BUF_SIZE, &err); | |
60 | if (res <= 0) | |
61 | return res; | |
62 | ||
63 | memcpy(addr, buf, res); | |
64 | info->image_read += res; | |
65 | addr += res; | |
66 | } | |
67 | ||
68 | return size; | |
69 | } | |
70 | ||
2a2ee2ac SG |
71 | static int spl_ymodem_load_image(struct spl_image_info *spl_image, |
72 | struct spl_boot_device *bootdev) | |
24de357a MP |
73 | { |
74 | int size = 0; | |
75 | int err; | |
76 | int res; | |
77 | int ret; | |
78 | connection_info_t info; | |
79 | char buf[BUF_SIZE]; | |
24de357a MP |
80 | ulong addr = 0; |
81 | ||
82 | info.mode = xyzModem_ymodem; | |
83 | ret = xyzModem_stream_open(&info, &err); | |
fa715193 LV |
84 | if (ret) { |
85 | printf("spl: ymodem err - %s\n", xyzModem_error(err)); | |
86 | return ret; | |
87 | } | |
88 | ||
89 | res = xyzModem_stream_read(buf, BUF_SIZE, &err); | |
90 | if (res <= 0) | |
91 | goto end_stream; | |
92 | ||
93 | if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && | |
94 | image_get_magic((struct image_header *)buf) == FDT_MAGIC) { | |
95 | struct spl_load_info load; | |
96 | struct ymodem_fit_info info; | |
97 | ||
98 | debug("Found FIT\n"); | |
99 | load.dev = NULL; | |
100 | load.priv = (void *)&info; | |
101 | load.filename = NULL; | |
102 | load.bl_len = 1; | |
103 | info.buf = buf; | |
104 | info.image_read = BUF_SIZE; | |
105 | load.read = ymodem_read_fit; | |
f4d7d859 | 106 | ret = spl_load_simple_fit(spl_image, &load, 0, (void *)buf); |
fa715193 | 107 | size = info.image_read; |
24de357a | 108 | |
fa715193 LV |
109 | while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) |
110 | size += res; | |
111 | } else { | |
2a2ee2ac | 112 | ret = spl_parse_image_header(spl_image, |
71316c1d | 113 | (struct image_header *)buf); |
fa715193 LV |
114 | if (ret) |
115 | return ret; | |
2a2ee2ac | 116 | addr = spl_image->load_addr; |
fa715193 LV |
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); | |
24de357a MP |
123 | size += res; |
124 | addr += res; | |
24de357a | 125 | } |
24de357a MP |
126 | } |
127 | ||
fa715193 | 128 | end_stream: |
24de357a MP |
129 | xyzModem_stream_close(&err); |
130 | xyzModem_stream_terminate(false, &getcymodem); | |
131 | ||
132 | printf("Loaded %d bytes\n", size); | |
36afd451 | 133 | return 0; |
24de357a | 134 | } |
ebc4ef61 | 135 | SPL_LOAD_IMAGE_METHOD("UART", 0, BOOT_DEVICE_UART, spl_ymodem_load_image); |