summaryrefslogtreecommitdiff
path: root/lib/x1000-installer/src/xf_package.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/x1000-installer/src/xf_package.c')
-rw-r--r--lib/x1000-installer/src/xf_package.c261
1 files changed, 0 insertions, 261 deletions
diff --git a/lib/x1000-installer/src/xf_package.c b/lib/x1000-installer/src/xf_package.c
deleted file mode 100644
index fb107aef72..0000000000
--- a/lib/x1000-installer/src/xf_package.c
+++ /dev/null
@@ -1,261 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "xf_package.h"
23#include "xf_error.h"
24#include "pathfuncs.h"
25#include "file.h"
26#include "core_alloc.h"
27#include "md5.h"
28#include "system.h"
29#include <stdbool.h>
30#include <string.h>
31
32#ifdef ROCKBOX
33# include "microtar-rockbox.h"
34#else
35# include "microtar-stdio.h"
36#endif
37
38#define METADATA_SIZE 4096 /* size of the metadata buffer */
39#define MAX_MAP_SIZE 32 /* maximum number of map entries */
40
41static int pkg_alloc(struct xf_package* pkg)
42{
43 memset(pkg, 0, sizeof(*pkg));
44
45 /* calculate allocation size */
46 size_t alloc_size = 0;
47 alloc_size += ALIGN_UP_P2(sizeof(mtar_t), 3);
48 alloc_size += ALIGN_UP_P2(sizeof(struct xf_map) * MAX_MAP_SIZE, 3);
49 alloc_size += ALIGN_UP_P2(METADATA_SIZE, 3);
50 alloc_size += 7; /* for alignment */
51
52 pkg->alloc_handle = core_alloc_ex("xf_package", alloc_size, &buflib_ops_locked);
53 if(pkg->alloc_handle < 0)
54 return XF_E_OUT_OF_MEMORY;
55
56 /* distribute memory */
57 uint8_t* buf = (uint8_t*)core_get_data(pkg->alloc_handle);
58 memset(buf, 0, alloc_size);
59 ALIGN_BUFFER(buf, alloc_size, 8);
60
61 pkg->tar = (mtar_t*)buf;
62 buf += ALIGN_UP_P2(sizeof(mtar_t), 3);
63
64 pkg->map = (struct xf_map*)buf;
65 buf += ALIGN_UP_P2(sizeof(struct xf_map) * MAX_MAP_SIZE, 3);
66
67 pkg->metadata = (char*)buf;
68 buf += ALIGN_UP_P2(METADATA_SIZE, 3);
69
70 return XF_E_SUCCESS;
71}
72
73static int read_meta_line_cb(int n, char* buf, void* arg)
74{
75 struct xf_package* pkg = (struct xf_package*)arg;
76 size_t length = strlen(buf);
77
78 /* skip blank lines and the first line (it's reserved for old format) */
79 if(n == 0 || length == 0)
80 return 0;
81
82 /* metadata lines require an '=' sign to separate key and value */
83 if(!strchr(buf, '='))
84 return XF_E_SYNTAX_ERROR;
85
86 /* we need space to copy the key-value pair plus a null terminator */
87 if(length + 1 >= METADATA_SIZE - pkg->metadata_len)
88 return XF_E_BUF_OVERFLOW;
89
90 memcpy(&pkg->metadata[pkg->metadata_len], buf, length + 1);
91 pkg->metadata_len += length + 1;
92 return 0;
93}
94
95static int pkg_read_meta(struct xf_package* pkg)
96{
97 struct xf_stream stream;
98 int rc = xf_open_tar(pkg->tar, "bootloader-info.txt", &stream);
99 if(rc)
100 return XF_E_CANNOT_OPEN_FILE;
101
102 char buf[200];
103 rc = xf_stream_read_lines(&stream, buf, sizeof(buf), read_meta_line_cb, pkg);
104 xf_stream_close(&stream);
105 return rc;
106}
107
108static int pkg_read_map(struct xf_package* pkg,
109 const struct xf_map* dflt_map, int dflt_map_size)
110{
111 /* Attempt to load and parse the map file */
112 struct xf_stream stream;
113 int rc = xf_open_tar(pkg->tar, "flashmap.txt", &stream);
114
115 /* If the flash map is absent but a default map has been provided,
116 * then the update is in the old fixed format. */
117 if(rc == MTAR_ENOTFOUND && dflt_map) {
118 if(dflt_map_size > MAX_MAP_SIZE)
119 return XF_E_INVALID_PARAMETER;
120
121 for(int i = 0; i < dflt_map_size; ++i) {
122 pkg->map[i] = dflt_map[i];
123 pkg->map[i].flags &= ~(XF_MAP_HAS_MD5 | XF_MAP_HAS_FILE_LENGTH);
124 }
125
126 pkg->map_size = dflt_map_size;
127 return XF_E_SUCCESS;
128 }
129
130 if(rc != MTAR_ESUCCESS)
131 return XF_E_CANNOT_OPEN_FILE;
132
133 rc = xf_map_parse(&stream, pkg->map, MAX_MAP_SIZE);
134 if(rc < 0)
135 goto err;
136
137 /* Sort the map; reject it if there is any overlap. */
138 pkg->map_size = rc;
139 if(xf_map_sort(pkg->map, pkg->map_size)) {
140 rc = XF_E_INVALID_PARAMETER;
141 goto err;
142 }
143
144 /* All packages in the 'new' format are required to have MD5 sums. */
145 for(int i = 0; i < pkg->map_size; ++i) {
146 if(!(pkg->map[i].flags & XF_MAP_HAS_MD5) ||
147 !(pkg->map[i].flags & XF_MAP_HAS_FILE_LENGTH)) {
148 rc = XF_E_VERIFY_FAILED;
149 goto err;
150 }
151 }
152
153 rc = XF_E_SUCCESS;
154
155 err:
156 xf_stream_close(&stream);
157 return rc;
158}
159
160static int pkg_verify(struct xf_package* pkg)
161{
162 struct xf_stream stream;
163 md5_context ctx;
164 uint8_t buffer[128];
165
166 for(int i = 0; i < pkg->map_size; ++i) {
167 /* At a bare minimum, check that the file exists. */
168 int rc = xf_open_tar(pkg->tar, pkg->map[i].name, &stream);
169 if(rc)
170 return XF_E_VERIFY_FAILED;
171
172 /* Also check that it isn't bigger than the update region.
173 * That would normally indicate a problem. */
174 off_t streamsize = xf_stream_get_size(&stream);
175 if(streamsize > (off_t)pkg->map[i].length) {
176 rc = XF_E_VERIFY_FAILED;
177 goto err;
178 }
179
180 /* Check against the listed file length. */
181 if(pkg->map[i].flags & XF_MAP_HAS_FILE_LENGTH) {
182 if(streamsize != (off_t)pkg->map[i].file_length) {
183 rc = XF_E_VERIFY_FAILED;
184 goto err;
185 }
186 }
187
188 /* Check the MD5 sum if we have it. */
189 if(pkg->map[i].flags & XF_MAP_HAS_MD5) {
190 md5_starts(&ctx);
191 while(1) {
192 ssize_t n = xf_stream_read(&stream, buffer, sizeof(buffer));
193 if(n < 0) {
194 rc = XF_E_IO;
195 goto err;
196 }
197
198 md5_update(&ctx, buffer, n);
199 if((size_t)n < sizeof(buffer))
200 break;
201 }
202
203 md5_finish(&ctx, buffer);
204 if(memcpy(buffer, pkg->map[i].md5, 16)) {
205 rc = XF_E_VERIFY_FAILED;
206 goto err;
207 }
208 }
209
210 err:
211 xf_stream_close(&stream);
212 if(rc)
213 return rc;
214 }
215
216 /* All files passed verification */
217 return XF_E_SUCCESS;
218}
219
220int xf_package_open_ex(struct xf_package* pkg, const char* file,
221 const struct xf_map* dflt_map, int dflt_map_size)
222{
223 int rc = pkg_alloc(pkg);
224 if(rc)
225 return rc;
226
227#ifdef ROCKBOX
228 rc = mtar_open(pkg->tar, file, O_RDONLY);
229#else
230 rc = mtar_open(pkg->tar, file, "r");
231#endif
232 if(rc != MTAR_ESUCCESS) {
233 rc = XF_E_CANNOT_OPEN_FILE;
234 goto err;
235 }
236
237 rc = pkg_read_meta(pkg);
238 if(rc)
239 goto err;
240
241 rc = pkg_read_map(pkg, dflt_map, dflt_map_size);
242 if(rc)
243 goto err;
244
245 rc = pkg_verify(pkg);
246 if(rc)
247 goto err;
248
249 err:
250 if(rc)
251 xf_package_close(pkg);
252 return rc;
253}
254
255void xf_package_close(struct xf_package* pkg)
256{
257 if(mtar_is_open(pkg->tar))
258 mtar_close(pkg->tar);
259
260 pkg->alloc_handle = core_free(pkg->alloc_handle);
261}