blob: 166128f73868743a8ca80f3ddbf34d538d662ff9 [file] [log] [blame]
b.liuced8dd02024-06-28 13:28:29 +08001#include <string.h>
2
3#include "aboot-tiny.h"
4#include "jacana_pvt.h"
5
6/*---------------------------------------------------------------------------*/
7static const char *jacana_pvt_cmd_resp[] = {
8 "getvar:max-download-size", /* 0 */
9 "OKAY\t%08x", /* 1 */
10 "download:%08x", /* 2 */
11 "DATA%08x", /* 3 */
12 "OKAY", /* 4 */
13 "flash:pvt", /* 5 */
14 "OKAY" /* 6 */
15};
16/*---------------------------------------------------------------------------*/
17static int
18pvt_read_next_to_cache(firmware_handle_t *firmware)
19{
20 size_t size = firmware->end_ptr - firmware->read_ptr;
21 memmove(firmware->read_ptr - firmware->read_sz, firmware->read_ptr, size);
22 firmware->read_ptr -= firmware->read_sz;
23 firmware->end_ptr -= firmware->read_sz;
24 size_t remainder = firmware->end - firmware->start;
25 if(remainder > 0) {
26 size_t size = remainder > firmware->read_sz ? firmware->read_sz : remainder;
27 int len = jacana_pvt_raw_read(firmware->priv, firmware->start,
28 (uint8_t *)firmware->middle_ptr, size);
29 if(len < 0) {
30 return -1;
31 }
32 firmware->start += len;
33 firmware->end_ptr += len;
34 }
35
36 return 0;
37}
38/*---------------------------------------------------------------------------*/
39int
40jacana_pvt_open(firmware_handle_t *firmware, void *priv)
41{
42 firmware->priv = priv;
43 firmware->start = 0;
44 firmware->end = jacana_pvt_raw_get_total_size(priv);
45
46 pvt_info_t *pvt_info = (pvt_info_t *)firmware->pvt_info;
47 pvt_info->max_download_size = aboot_tiny_get_max_download_size();
48 if(pvt_info->max_download_size > 8192) {
49 pvt_info->max_download_size = 8192;
50 }
51 pvt_info->offset = 0;
52 pvt_info->state = 0;
53
54 firmware->data = aboot_tiny_mem_alloc(MAX_READ_CACHE_SZ * 2);
55 if(!firmware->data) {
56 aboot_tiny_log_printf("Failed: can not alloc data buf\n");
57 return -1;
58 }
59
60 firmware->read_sz = MAX_READ_CACHE_SZ;
61 firmware->middle_ptr = (char *)firmware->data + firmware->read_sz;
62 firmware->end_ptr = firmware->middle_ptr + firmware->read_sz;
63 firmware->read_ptr = firmware->end_ptr;
64 if(pvt_read_next_to_cache(firmware) < 0) {
65 aboot_tiny_mem_free(firmware->data);
66 firmware->data = NULL;
67 return -1;
68 }
69
70 sparse_file_t *sparse_file = &pvt_info->sparse_file;
71 size_t remainder = firmware->end - firmware->start;
72 size_t size = (pvt_info->max_download_size
73 - SPARSE_FILE_HEADER_SIZE
74 - SPARSE_FILE_FOOTER_SIZE) & ~(SPARSE_BLOCK_SZ - 1);
75 if(remainder < size) {
76 size = remainder;
77 }
78
79 sparse_file_new(sparse_file, pvt_info->offset, size, firmware->end);
80 pvt_info->offset += size;
81
82 return 0;
83}
84/*---------------------------------------------------------------------------*/
85int
86jacana_pvt_read_line(firmware_handle_t *firmware, char *line)
87{
88 pvt_info_t *pvt_info = (pvt_info_t *)firmware->pvt_info;
89 sparse_file_t *sparse_file = &pvt_info->sparse_file;
90
91 switch(pvt_info->state) {
92 case 0:
93 case 4:
94 case 5:
95 case 6:
96 strcpy(line,jacana_pvt_cmd_resp[pvt_info->state]);
97 break;
98
99 case 1:
100 sprintf(line, jacana_pvt_cmd_resp[pvt_info->state],
101 pvt_info->max_download_size);
102 break;
103 case 2:
104 case 3:
105 sprintf(line, jacana_pvt_cmd_resp[pvt_info->state],
106 sparse_file->header_size
107 + sparse_file->data_size
108 + sparse_file->fill_size
109 + sparse_file->footer_size);
110 break;
111
112 case 7: /* pvt command sequence finished */
113 if(firmware->start < firmware->end) {
114 pvt_info->state = 0;
115
116 size_t remainder = firmware->end - firmware->start;
117 size_t size = (pvt_info->max_download_size
118 - SPARSE_FILE_HEADER_SIZE
119 - SPARSE_FILE_FOOTER_SIZE) & ~(SPARSE_BLOCK_SZ - 1);
120 if(remainder < size) {
121 size = remainder;
122 }
123 sparse_file_new(sparse_file, pvt_info->offset, size, firmware->end);
124 pvt_info->offset += size;
125 return jacana_pvt_read_line(firmware, line);
126 } else {
127 if(pvt_info->offset < firmware->end) {
128 /* remainder data in cache */
129 pvt_info->state = 0;
130 size_t size = firmware->end - pvt_info->offset;
131 sparse_file_new(sparse_file, pvt_info->offset, size, firmware->end);
132 pvt_info->offset += size;
133 return jacana_pvt_read_line(firmware, line);
134 } else {
135 /* all finished */
136 return 0;
137 }
138 }
139
140 default:
141 return -1;
142 }
143 pvt_info->state++;
144
145 return strlen(line);
146}
147/*---------------------------------------------------------------------------*/
148int
149jacana_pvt_read_data(firmware_handle_t *firmware, uint8_t *data, size_t size)
150{
151 pvt_info_t *pvt_info = (pvt_info_t *)firmware->pvt_info;
152 sparse_file_t *sparse_file = &pvt_info->sparse_file;
153
154 if(sparse_file->header_size) {
155 if(sparse_file->header_size > size) {
156 /* should not happen */
157 return -1;
158 } else {
159 size = sparse_file->header_size;
160 memcpy(data, sparse_file->header, size);
161 sparse_file->header_size = 0;
162 return size;
163 }
164 }
165
166 if(sparse_file->footer_size == 0) {
167 /* should not happen */
168 return -1;
169 }
170
171 if(sparse_file->data_size == 0) {
172 if(sparse_file->fill_size) {
173 if(size > sparse_file->fill_size) {
174 size = sparse_file->fill_size;
175 }
176 memset(data, 0, size);
177 sparse_file->fill_size -= size;
178 return size;
179 } else if(sparse_file->footer_size > size) {
180 /* should not happen */
181 return -1;
182 } else {
183 /* footer_size <= size */
184 size = sparse_file->footer_size;
185 memcpy(data, sparse_file->footer, size);
186 sparse_file->footer_size = 0;
187 return size;
188 }
189 }
190
191 if(sparse_file->data_size < size) {
192 size = sparse_file->data_size;
193 }
194
195 while(1) {
196 if(firmware->read_ptr == firmware->end_ptr) {
197 /* should not happen */
198 return -1;
199 }
200 if(firmware->read_ptr < firmware->middle_ptr) {
201 size_t remainder = firmware->middle_ptr - firmware->read_ptr;
202 if(remainder < size) {
203 size = remainder;
204 }
205 memcpy(data, firmware->read_ptr, size);
206 firmware->read_ptr += size;
207 break;
208 } else {
209 /* read_ptr >= middle_ptr */
210 if(pvt_read_next_to_cache(firmware) < 0) {
211 return -1;
212 }
213 }
214 }
215
216 sparse_file->data_size -= size;
217
218 return size;
219}
220/*---------------------------------------------------------------------------*/
221void
222jacana_pvt_close(firmware_handle_t *firmware)
223{
224 firmware->priv = NULL;
225 firmware->start = 0;
226 firmware->end = 0;
227
228 if(firmware->data) {
229 aboot_tiny_mem_free(firmware->data);
230 firmware->data = NULL;
231 }
232 firmware->read_sz = 0;
233 firmware->read_ptr = NULL;
234 firmware->middle_ptr = NULL;
235 firmware->end_ptr = NULL;
236
237 pvt_info_t *pvt_info = (pvt_info_t *)firmware->pvt_info;
238 pvt_info->max_download_size = 0;
239 pvt_info->state = 0;
240
241 sparse_file_t *sparse_file = &pvt_info->sparse_file;
242 memset(sparse_file->header, 0, SPARSE_FILE_HEADER_SIZE);
243 sparse_file->header_size = 0;
244 sparse_file->data_size = 0;
245}
246/*---------------------------------------------------------------------------*/