summaryrefslogtreecommitdiff
path: root/firmware/common
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/common')
-rw-r--r--firmware/common/devicedata.c88
-rw-r--r--firmware/common/disk.c20
-rw-r--r--firmware/common/disk_cache.c8
-rw-r--r--firmware/common/pathfuncs.c66
-rw-r--r--firmware/common/rb-loader.c8
5 files changed, 169 insertions, 21 deletions
diff --git a/firmware/common/devicedata.c b/firmware/common/devicedata.c
new file mode 100644
index 0000000000..75fe79d7fa
--- /dev/null
+++ b/firmware/common/devicedata.c
@@ -0,0 +1,88 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2024 by William Wilgus
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#include "devicedata.h"
22#include "crc32.h"
23#include <stddef.h>
24#include <string.h>
25#include "debug.h"
26
27#ifndef BOOTLOADER
28void verify_device_data(void) INIT_ATTR;
29void verify_device_data(void)
30{
31 DEBUGF("%s", __func__);
32 /* verify payload with checksum */
33 uint32_t crc = crc_32(device_data.payload, device_data.length, 0xffffffff);
34 if (crc == device_data.crc)
35 return; /* return if data is valid */
36
37 /* Write the default if data is invalid */
38 memset(device_data.payload, 0xff, DEVICE_DATA_PAYLOAD_SIZE); /* Invalid data */
39 device_data.length = DEVICE_DATA_PAYLOAD_SIZE;
40 device_data.crc = crc_32(device_data.payload, device_data.length, 0xffffffff);
41
42}
43
44/******************************************************************************/
45#endif /* ndef BOOTLOADER ******************************************************/
46/******************************************************************************/
47
48#if defined(HAVE_DEVICEDATA)
49void __attribute__((weak)) fill_devicedata(struct device_data_t *data)
50{
51 memset(data->payload, 0xff, data->length);
52}
53#endif
54
55/* Write bootdata into location in FIRMWARE marked by magic header
56 * Assumes buffer is already loaded with the firmware image
57 * We just need to find the location and write data into the
58 * payload region along with the crc for later verification and use.
59 * Returns payload len on success,
60 * On error returns false
61 */
62bool write_devicedata(unsigned char* buf, int len)
63{
64 int search_len = MIN(len, DEVICE_DATA_SEARCH_SIZE) - sizeof(struct device_data_t);
65
66 /* search for decvice data header prior to search_len */
67 for(int i = 0; i < search_len; i++)
68 {
69 struct device_data_t *data = (struct device_data_t *)&buf[i];
70 if (data->magic[0] != DEVICE_DATA_MAGIC0 ||
71 data->magic[1] != DEVICE_DATA_MAGIC1)
72 continue;
73
74 /* Ignore it if the length extends past the end of the buffer. */
75 int data_len = offsetof(struct device_data_t, payload) + data->length;
76 if (i + data_len > len)
77 continue;
78
79 fill_devicedata(data);
80
81 /* Calculate payload CRC */
82 data->crc = crc_32(data->payload, data->length, 0xffffffff);
83 return true;
84 }
85
86 return false;
87}
88
diff --git a/firmware/common/disk.c b/firmware/common/disk.c
index 9b6454c9a2..576eede143 100644
--- a/firmware/common/disk.c
+++ b/firmware/common/disk.c
@@ -172,6 +172,8 @@ bool disk_init(IF_MD_NONVOID(int drive))
172 } 172 }
173 } 173 }
174 174
175 // XXX backup GPT header at final LBA of drive...
176
175 while (is_gpt) { 177 while (is_gpt) {
176 /* Re-start partition parsing using GPT */ 178 /* Re-start partition parsing using GPT */
177 uint64_t part_lba; 179 uint64_t part_lba;
@@ -243,20 +245,24 @@ reload:
243 goto skip; /* Any flag makes us ignore this */ 245 goto skip; /* Any flag makes us ignore this */
244 } 246 }
245 tmp = BYTES2INT64(pptr, 32); /* FIRST LBA */ 247 tmp = BYTES2INT64(pptr, 32); /* FIRST LBA */
246 if (tmp > UINT32_MAX) { // XXX revisit when we resize struct partinfo! 248#ifndef STORAGE_64BIT_SECTOR
247 DEBUGF("GPT: partition starts after 2GiB mark\n"); 249 if (tmp > UINT32_MAX) {
250 DEBUGF("GPT: partition starts after 2TiB mark\n");
248 goto skip; 251 goto skip;
249 } 252 }
253#endif
250 if (tmp < 34) { 254 if (tmp < 34) {
251 DEBUGF("GPT: Invalid start LBA\n"); 255 DEBUGF("GPT: Invalid start LBA\n");
252 goto skip; 256 goto skip;
253 } 257 }
254 pinfo[part].start = tmp; 258 pinfo[part].start = tmp;
255 tmp = BYTES2INT64(pptr, 40); /* LAST LBA */ 259 tmp = BYTES2INT64(pptr, 40); /* LAST LBA */
256 if (tmp > UINT32_MAX) { // XXX revisit when we resize struct partinfo! 260#ifndef STORAGE_64BIT_SECTOR
257 DEBUGF("GPT: partition ends after 2GiB mark\n"); 261 if (tmp > UINT32_MAX) {
262 DEBUGF("GPT: partition ends after 2TiB mark\n");
258 goto skip; 263 goto skip;
259 } 264 }
265#endif
260 if (tmp <= pinfo[part].start) { 266 if (tmp <= pinfo[part].start) {
261 DEBUGF("GPT: Invalid end LBA\n"); 267 DEBUGF("GPT: Invalid end LBA\n");
262 goto skip; 268 goto skip;
@@ -264,7 +270,7 @@ reload:
264 pinfo[part].size = tmp - pinfo[part].start + 1; 270 pinfo[part].size = tmp - pinfo[part].start + 1;
265 pinfo[part].type = PARTITION_TYPE_FAT32_LBA; 271 pinfo[part].type = PARTITION_TYPE_FAT32_LBA;
266 272
267 DEBUGF("GPart%d: start: %08lx size: %08lx\n", 273 DEBUGF("GPart%d: start: %016lx size: %016lx\n",
268 part,pinfo[part].start,pinfo[part].size); 274 part,pinfo[part].start,pinfo[part].size);
269 part++; 275 part++;
270 276
@@ -499,13 +505,13 @@ unsigned int volume_get_cluster_size(IF_MV_NONVOID(int volume))
499 return clustersize; 505 return clustersize;
500} 506}
501 507
502void volume_size(IF_MV(int volume,) unsigned long *sizep, unsigned long *freep) 508void volume_size(IF_MV(int volume,) sector_t *sizep, sector_t *freep)
503{ 509{
504 disk_reader_lock(); 510 disk_reader_lock();
505 511
506 if (!CHECK_VOL(volume) || !fat_size(IF_MV(volume,) sizep, freep)) 512 if (!CHECK_VOL(volume) || !fat_size(IF_MV(volume,) sizep, freep))
507 { 513 {
508 if (freep) *sizep = 0; 514 if (sizep) *sizep = 0;
509 if (freep) *freep = 0; 515 if (freep) *freep = 0;
510 } 516 }
511 517
diff --git a/firmware/common/disk_cache.c b/firmware/common/disk_cache.c
index 9e4dee6a91..74c4d5f35b 100644
--- a/firmware/common/disk_cache.c
+++ b/firmware/common/disk_cache.c
@@ -71,12 +71,12 @@ struct disk_cache_entry
71#ifdef HAVE_MULTIVOLUME 71#ifdef HAVE_MULTIVOLUME
72 unsigned char volume; /* volume of sector */ 72 unsigned char volume; /* volume of sector */
73#endif 73#endif
74 unsigned long sector; /* cached disk sector number */ 74 sector_t sector; /* cached disk sector number */
75}; 75};
76 76
77BITARRAY_TYPE_DECLARE(cache_map_entry_t, cache_map, DC_NUM_ENTRIES) 77BITARRAY_TYPE_DECLARE(cache_map_entry_t, cache_map, DC_NUM_ENTRIES)
78 78
79static inline unsigned int map_sector(unsigned long sector) 79static inline unsigned int map_sector(sector_t sector)
80{ 80{
81 /* keep sector hash simple for now */ 81 /* keep sector hash simple for now */
82 return sector % DC_MAP_NUM_ENTRIES; 82 return sector % DC_MAP_NUM_ENTRIES;
@@ -172,7 +172,7 @@ static inline void cache_discard_entry(struct disk_cache_entry *dce,
172/* search the cache for the specified sector, returning a buffer, either 172/* search the cache for the specified sector, returning a buffer, either
173 to the specified sector, if it exists, or a new/evicted entry that must 173 to the specified sector, if it exists, or a new/evicted entry that must
174 be filled */ 174 be filled */
175void * dc_cache_probe(IF_MV(int volume,) unsigned long sector, 175void * dc_cache_probe(IF_MV(int volume,) sector_t sector,
176 unsigned int *flagsp) 176 unsigned int *flagsp)
177{ 177{
178 unsigned int mapnum = map_sector(sector); 178 unsigned int mapnum = map_sector(sector);
@@ -200,7 +200,7 @@ void * dc_cache_probe(IF_MV(int volume,) unsigned long sector,
200 if (old_flags) 200 if (old_flags)
201 { 201 {
202 int old_volume = IF_MV_VOL(dce->volume); 202 int old_volume = IF_MV_VOL(dce->volume);
203 unsigned long sector = dce->sector; 203 sector_t sector = dce->sector;
204 unsigned int old_mapnum = map_sector(sector); 204 unsigned int old_mapnum = map_sector(sector);
205 205
206 if (old_flags & DCE_DIRTY) 206 if (old_flags & DCE_DIRTY)
diff --git a/firmware/common/pathfuncs.c b/firmware/common/pathfuncs.c
index db3abe6940..b5e5ecb0cf 100644
--- a/firmware/common/pathfuncs.c
+++ b/firmware/common/pathfuncs.c
@@ -24,10 +24,14 @@
24#include "pathfuncs.h" 24#include "pathfuncs.h"
25#include "string-extra.h" 25#include "string-extra.h"
26#include <stdio.h> 26#include <stdio.h>
27#include "file_internal.h"
28#include "debug.h"
27 29
28#ifdef HAVE_MULTIVOLUME 30#ifdef HAVE_MULTIVOLUME
29#include "storage.h" 31#include "storage.h"
30 32
33static char vol_dec_strings[NUM_VOLUMES][ALIGN_UP(VOL_MAX_LEN+2, 4)] = {{0}};
34
31enum storage_name_dec_indexes 35enum storage_name_dec_indexes
32{ 36{
33#if (CONFIG_STORAGE & STORAGE_ATA) 37#if (CONFIG_STORAGE & STORAGE_ATA)
@@ -106,6 +110,54 @@ static const unsigned char storage_dec_indexes[STORAGE_NUM_TYPES+1] =
106#endif 110#endif
107}; 111};
108 112
113/* builds a list of drive/volume specifiers <volstr#> */
114void init_volume_names(void)
115{
116 DEBUGF("%s: ", __func__);
117 FOR_EACH_VOLUME(-1, volume)
118 {
119 const char *voldec = "";
120 char *buffer = vol_dec_strings[volume];
121
122 int type = storage_driver_type(volume_drive(volume));
123 if (type < 0 || type > STORAGE_NUM_TYPES)
124 type = STORAGE_NUM_TYPES;
125 voldec = storage_dec_names[storage_dec_indexes[type]];
126 snprintf(buffer, VOL_MAX_LEN + 1, "%c%s%d%c",
127 VOL_START_TOK, voldec, volume, VOL_END_TOK);
128 DEBUGF("vol<%d> = %s ", volume, buffer);
129 }
130 DEBUGF("\n");
131}
132
133#include <stdio.h>
134
135int path_get_volume_id(const char *name)
136{
137 int v = -1;
138
139 if (!name || *name != VOL_START_TOK)
140 goto bail;
141
142 do {
143 switch (*name)
144 {
145 case '0' ... '9': /* digit; parse volume number */
146 v = (v * 10 + *name - '0') % VOL_NUM_MAX;
147 break;
148 case '\0':
149 case PATH_SEPCH: /* no closing bracket; no volume */
150 v = -1;
151 goto bail;
152 default: /* something else; reset volume */
153 v = 0;
154 }
155 } while (*++name != VOL_END_TOK); /* found end token? */
156
157bail:
158 return v;
159}
160
109/* Returns on which volume this is and sets *nameptr to the portion of the 161/* Returns on which volume this is and sets *nameptr to the portion of the
110 * path after the volume specifier, which could be the null if the path is 162 * path after the volume specifier, which could be the null if the path is
111 * just a volume root. If *nameptr > name, then a volume specifier was 163 * just a volume root. If *nameptr > name, then a volume specifier was
@@ -203,7 +255,8 @@ int path_strip_last_volume(const char *name, const char **nameptr, bool greedy)
203} 255}
204 256
205/* Returns the volume specifier decorated with the storage type name. 257/* Returns the volume specifier decorated with the storage type name.
206 * Assumes the supplied buffer size is at least {VOL_MAX_LEN}+1. 258 * Assumes the supplied buffer size is at least {VOL_MAX_LEN}+1,
259 * vol_dec_strings has been initialized by init_volume_names().
207 */ 260 */
208int get_volume_name(int volume, char *buffer) 261int get_volume_name(int volume, char *buffer)
209{ 262{
@@ -218,17 +271,12 @@ int get_volume_name(int volume, char *buffer)
218 271
219 volume %= VOL_NUM_MAX; /* as path parser would have it */ 272 volume %= VOL_NUM_MAX; /* as path parser would have it */
220 273
221 int type = storage_driver_type(volume_drive(volume)); 274 return strlcpy(buffer, vol_dec_strings[volume], VOL_MAX_LEN + 1);
222 if (type < 0 || type > STORAGE_NUM_TYPES)
223 type = STORAGE_NUM_TYPES;
224
225 const char *voldec = storage_dec_names[storage_dec_indexes[type]];
226 return snprintf(buffer, VOL_MAX_LEN + 1, "%c%s%d%c",
227 VOL_START_TOK, voldec, volume, VOL_END_TOK);
228} 275}
229 276
230/* Returns volume name formatted with the root. Assumes buffer size is at 277/* Returns volume name formatted with the root. Assumes buffer size is at
231 * least {VOL_MAX_LEN}+2 */ 278 * least {VOL_MAX_LEN}+2, vol_dec_strings has been initialized by init_volume_names().
279 */
232int make_volume_root(int volume, char *buffer) 280int make_volume_root(int volume, char *buffer)
233{ 281{
234 char *t = buffer; 282 char *t = buffer;
diff --git a/firmware/common/rb-loader.c b/firmware/common/rb-loader.c
index 61d8b1ddd2..2f5e06e165 100644
--- a/firmware/common/rb-loader.c
+++ b/firmware/common/rb-loader.c
@@ -30,6 +30,9 @@
30#include "multiboot.h" 30#include "multiboot.h"
31#endif 31#endif
32 32
33#ifdef HAVE_DEVICEDATA
34#include "devicedata.h"
35#endif
33/* loads a firmware file from supplied filename 36/* loads a firmware file from supplied filename
34 * file opened, checks firmware size and checksum 37 * file opened, checks firmware size and checksum
35 * if no error, firmware loaded to supplied buffer 38 * if no error, firmware loaded to supplied buffer
@@ -118,7 +121,6 @@ int load_firmware(unsigned char* buf, const char* firmware, int buffer_size)
118 /* if ret is valid breaks from loop to continue loading */ 121 /* if ret is valid breaks from loop to continue loading */
119 } 122 }
120#endif 123#endif
121
122 if (ret < 0) /* Check default volume, no valid firmware file loaded yet */ 124 if (ret < 0) /* Check default volume, no valid firmware file loaded yet */
123 { 125 {
124 /* First check in BOOTDIR */ 126 /* First check in BOOTDIR */
@@ -141,5 +143,9 @@ int load_firmware(unsigned char* buf, const char* firmware, int buffer_size)
141 else /* full path passed ROLO etc.*/ 143 else /* full path passed ROLO etc.*/
142 ret = load_firmware_filename(buf, firmware, buffer_size); 144 ret = load_firmware_filename(buf, firmware, buffer_size);
143 145
146#ifdef HAVE_DEVICEDATA
147 write_devicedata(buf, ret);
148#endif
149
144 return ret; 150 return ret;
145} 151}