blob: c65465b479aa599d49d478eddee0fba66eacbde6 [file] [log] [blame]
b.liuced8dd02024-06-28 13:28:29 +08001#include <stdio.h>
2#include <inttypes.h>
3#include <string.h>
4
5#include "aboot-tiny.h"
6#include "jacana_firmware.h"
7#include "jacana_pvt.h"
8
9/*---------------------------------------------------------------------------*/
10static int
11firmware_read_next_to_cache(firmware_handle_t *firmware)
12{
13 size_t size = firmware->end_ptr - firmware->read_ptr;
14 memmove(firmware->read_ptr - firmware->read_sz, firmware->read_ptr, size);
15 firmware->read_ptr -= firmware->read_sz;
16 firmware->end_ptr -= firmware->read_sz;
17 size_t remainder = firmware->end - firmware->start;
18 if(remainder > 0) {
19 size_t size = remainder > firmware->read_sz ? firmware->read_sz : remainder;
20 int len = jacana_firmware_raw_read(firmware->priv, firmware->start,
21 (uint8_t *)firmware->middle_ptr, size);
22 if(len < 0) {
23 return -1;
24 }
25 firmware->start += len;
26 firmware->end_ptr += len;
27 }
28
29 return 0;
30}
31/*---------------------------------------------------------------------------*/
32int
33jacana_firmware_open(firmware_handle_t *firmware, void *priv)
34{
35 firmware->priv = priv;
36 firmware->start = 0;
37 firmware->end = jacana_firmware_raw_get_total_size(priv);
38
39 firmware->data = aboot_tiny_mem_alloc(MAX_READ_CACHE_SZ * 2);
40 if(!firmware->data) {
41 aboot_tiny_log_printf("Failed: can not alloc data buf\n");
42 return -1;
43 }
44
45 firmware->read_sz = MAX_READ_CACHE_SZ;
46 firmware->middle_ptr = (char *)firmware->data + firmware->read_sz;
47 firmware->end_ptr = firmware->middle_ptr + firmware->read_sz;
48 firmware->read_ptr = firmware->end_ptr;
49 if(firmware_read_next_to_cache(firmware) < 0) {
50 goto failed;
51 }
52
53 char cmd_line[ABOOT_COMMAND_SZ];
54 char magic[9];
55 uint32_t size;
56 int num;
57
58 if(jacana_firmware_read_line(firmware, cmd_line) <= 0) {
59 aboot_tiny_log_printf("Failed: can not read a cmd line\n");
60 goto failed;
61 }
62 num = sscanf(cmd_line, "%08s%" SCNx32, magic, &size);
63 if(num != 2 || size > firmware->end) {
64 aboot_tiny_log_printf("Failed: cmd line format error\n");
65 goto failed;
66 }
67 firmware->end = (size_t)size;
68 if(strcmp(magic, "!JACANA!")) {
69 aboot_tiny_log_printf("Magic error: not a valid firmware\n");
70 goto failed;
71 }
72
73 return 0;
74
75failed:
76 aboot_tiny_mem_free(firmware->data);
77 firmware->data = NULL;
78 return -1;
79}
80/*---------------------------------------------------------------------------*/
81int
82jacana_firmware_read_line(firmware_handle_t *firmware, char *line)
83{
84 while(1) {
85 if(firmware->read_ptr < firmware->middle_ptr) {
86 const char *p = (const char *)strchr(firmware->read_ptr, '\n');
87 if(!p || p >= firmware->end_ptr) {
88 return -1;
89 }
90 int len = p - firmware->read_ptr + 1;
91 memcpy(line, firmware->read_ptr, len);
92 line[len] = '\0';
93 firmware->read_ptr += len;
94 if(firmware->read_ptr == firmware->end_ptr) {
95 /* firmware download finished, prepare for continue with pvt */
96 void *priv = jacana_pvt_raw_open();
97 if(!priv) {
98 return -1;
99 }
100 jacana_firmware_raw_close(firmware->priv);
101 jacana_firmware_close(firmware);
102 if(jacana_pvt_open(firmware, priv) < 0) {
103 return -1;
104 }
105 aboot_tiny_firmware_read_line = jacana_pvt_read_line;
106 aboot_tiny_firmware_read_data = jacana_pvt_read_data;
107 }
108 if(line[0] == '\n') {
109 continue;
110 } else {
111 line[len - 1] = '\0'; /* replace '\n' to '\0' */
112 return len - 1;
113 }
114 } else {
115 /* read_ptr >= middle_ptr */
116 if(firmware_read_next_to_cache(firmware) < 0) {
117 return -1;
118 }
119 }
120 }
121}
122/*---------------------------------------------------------------------------*/
123int
124jacana_firmware_read_data(firmware_handle_t *firmware, uint8_t *data, size_t size)
125{
126 while(1) {
127 if(firmware->read_ptr == firmware->end_ptr) {
128 return 0;
129 }
130
131 if(firmware->read_ptr < firmware->middle_ptr) {
132 size_t remainder = firmware->middle_ptr - firmware->read_ptr;
133 if(remainder < size) {
134 size = remainder;
135 }
136 memcpy(data, firmware->read_ptr, size);
137 firmware->read_ptr += size;
138 return size;
139 } else {
140 /* read_ptr >= middle_ptr */
141 if(firmware_read_next_to_cache(firmware) < 0) {
142 return -1;
143 }
144 }
145 }
146}
147/*---------------------------------------------------------------------------*/
148void
149jacana_firmware_close(firmware_handle_t *firmware)
150{
151 firmware->priv = NULL;
152 firmware->start = 0;
153 firmware->end = 0;
154 if(firmware->data) {
155 aboot_tiny_mem_free(firmware->data);
156 firmware->data = NULL;
157 }
158 firmware->read_sz = 0;
159 firmware->read_ptr = NULL;
160 firmware->middle_ptr = NULL;
161 firmware->end_ptr = NULL;
162}
163/*---------------------------------------------------------------------------*/