summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/debug_menu.c11
-rw-r--r--firmware/common/bootdata.c15
-rw-r--r--firmware/common/multiboot.c15
-rw-r--r--firmware/export/bootdata.h6
-rw-r--r--firmware/include/dircache_redirect.h43
-rw-r--r--firmware/rolo.c21
6 files changed, 99 insertions, 12 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index 5e2451e41b..36927dd890 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -2546,7 +2546,16 @@ static bool dbg_boot_data(void)
2546 { 2546 {
2547 simplelist_addline("Boot data valid"); 2547 simplelist_addline("Boot data valid");
2548 simplelist_addline("Version: %d", (int)boot_data.version); 2548 simplelist_addline("Version: %d", (int)boot_data.version);
2549 simplelist_addline("Boot volume: %d", (int)boot_data.boot_volume); 2549
2550 if (boot_data.version == 0)
2551 {
2552 simplelist_addline("Boot volume: %d", (int)boot_data._boot_volume);
2553 }
2554 else if (boot_data.version == 1)
2555 {
2556 simplelist_addline("Boot drive: %d", (int)boot_data.boot_drive);
2557 simplelist_addline("Boot partition: %d", (int)boot_data.boot_partition);
2558 }
2550 } 2559 }
2551 2560
2552 simplelist_addline("Bootdata RAW:"); 2561 simplelist_addline("Bootdata RAW:");
diff --git a/firmware/common/bootdata.c b/firmware/common/bootdata.c
index fa74c5fe91..224a48d0c1 100644
--- a/firmware/common/bootdata.c
+++ b/firmware/common/bootdata.c
@@ -42,6 +42,20 @@ static bool verify_boot_data_v0(void)
42 return true; 42 return true;
43} 43}
44 44
45static bool verify_boot_data_v1(void) INIT_ATTR;
46static bool verify_boot_data_v1(void)
47{
48 /* validate protocol version */
49 if (boot_data.version != 1)
50 return false;
51
52 /* validate length */
53 if (boot_data.length != 4)
54 return false;
55
56 return true;
57}
58
45struct verify_bd_entry 59struct verify_bd_entry
46{ 60{
47 int version; 61 int version;
@@ -50,6 +64,7 @@ struct verify_bd_entry
50 64
51static const struct verify_bd_entry verify_bd[] INITDATA_ATTR = { 65static const struct verify_bd_entry verify_bd[] INITDATA_ATTR = {
52 { 0, verify_boot_data_v0 }, 66 { 0, verify_boot_data_v0 },
67 { 1, verify_boot_data_v1 },
53}; 68};
54 69
55void verify_boot_data(void) 70void verify_boot_data(void)
diff --git a/firmware/common/multiboot.c b/firmware/common/multiboot.c
index c292aa1c30..8d6573d2dd 100644
--- a/firmware/common/multiboot.c
+++ b/firmware/common/multiboot.c
@@ -23,6 +23,7 @@
23#include "crc32.h" 23#include "crc32.h"
24#include "loader_strerror.h" 24#include "loader_strerror.h"
25#include "file.h" 25#include "file.h"
26#include "disk.h"
26#include <string.h> 27#include <string.h>
27#include <stdio.h> 28#include <stdio.h>
28 29
@@ -30,10 +31,20 @@ static void write_bootdata_v0(struct boot_data_t *data, unsigned int boot_volume
30{ 31{
31 memset(data->payload, data->length, 0); 32 memset(data->payload, data->length, 0);
32 33
33 data->boot_volume = boot_volume; 34 data->_boot_volume = boot_volume;
34 data->version = 0; 35 data->version = 0;
35} 36}
36 37
38static void write_bootdata_v1(struct boot_data_t *data, unsigned int boot_volume)
39{
40 memset(data->payload, data->length, 0);
41
42 data->_boot_volume = 0xff;
43 data->version = 1;
44 data->boot_drive = volume_drive(boot_volume);
45 data->boot_partition = volume_partition(boot_volume);
46}
47
37/* Write bootdata into location in FIRMWARE marked by magic header 48/* Write bootdata into location in FIRMWARE marked by magic header
38 * Assumes buffer is already loaded with the firmware image 49 * Assumes buffer is already loaded with the firmware image
39 * We just need to find the location and write data into the 50 * We just need to find the location and write data into the
@@ -68,6 +79,8 @@ bool write_bootdata(unsigned char* buf, int len, unsigned int boot_volume)
68 /* Write boot data according to the selected protocol */ 79 /* Write boot data according to the selected protocol */
69 if (proto_version == 0) 80 if (proto_version == 0)
70 write_bootdata_v0(data, boot_volume); 81 write_bootdata_v0(data, boot_volume);
82 else if (proto_version == 1)
83 write_bootdata_v1(data, boot_volume);
71 else 84 else
72 break; 85 break;
73 86
diff --git a/firmware/export/bootdata.h b/firmware/export/bootdata.h
index 319f442511..2a6f96d22e 100644
--- a/firmware/export/bootdata.h
+++ b/firmware/export/bootdata.h
@@ -37,7 +37,7 @@
37 37
38#define BOOT_DATA_MAGIC0 ('r' | 'b' << 8 | 'm' << 16 | 'a' << 24) 38#define BOOT_DATA_MAGIC0 ('r' | 'b' << 8 | 'm' << 16 | 'a' << 24)
39#define BOOT_DATA_MAGIC1 ('g' | 'i' << 8 | 'c' << 16 | '!' << 24) 39#define BOOT_DATA_MAGIC1 ('g' | 'i' << 8 | 'c' << 16 | '!' << 24)
40#define BOOT_DATA_VERSION 0 40#define BOOT_DATA_VERSION 1
41 41
42/* maximum size of payload */ 42/* maximum size of payload */
43#define BOOT_DATA_PAYLOAD_SIZE 4 43#define BOOT_DATA_PAYLOAD_SIZE 4
@@ -59,8 +59,10 @@ struct boot_data_t
59 { 59 {
60 struct 60 struct
61 { 61 {
62 uint8_t boot_volume; 62 uint8_t _boot_volume; /* IGNORED */
63 uint8_t version; 63 uint8_t version;
64 uint8_t boot_drive;
65 uint8_t boot_partition;
64 }; 66 };
65 uint8_t payload[BOOT_DATA_PAYLOAD_SIZE]; 67 uint8_t payload[BOOT_DATA_PAYLOAD_SIZE];
66 }; 68 };
diff --git a/firmware/include/dircache_redirect.h b/firmware/include/dircache_redirect.h
index d4d72978c0..32e441c5b3 100644
--- a/firmware/include/dircache_redirect.h
+++ b/firmware/include/dircache_redirect.h
@@ -136,6 +136,41 @@ static inline void fileop_onsync_internal(struct filestr_base *stream)
136#endif 136#endif
137} 137}
138 138
139#if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) && !defined(BOOTLOADER)
140static inline bool multiboot_is_boot_volume(int volume)
141{
142 if (boot_data.version == 0)
143 {
144 /*
145 * Version 0 bootloaders just pass the volume number, but that's
146 * dynamically assigned and sometimes differs by the time we get
147 * into the firmware. So we can't rely on the volume passed by
148 * the bootloader.
149 */
150#if CONFIG_CPU == X1000
151 /* The affected X1000 players only have one drive to begin with */
152 return volume_drive(volume) == 0;
153#else
154 /* FIXME: Anything else that can get here is a Sansa. */
155 return volume_drive(volume) == boot_data.boot_volume ||
156 volume == boot_data.boot_volume;
157#endif
158 }
159
160 if (boot_data.version == 1)
161 {
162 /*
163 * Since version 1 the bootloader passes drive and partition
164 * number which unambiguously identifies the boot volume.
165 */
166 return volume_drive(volume) == boot_data.boot_drive &&
167 volume_partition(volume) == boot_data.boot_partition;
168 }
169
170 return false;
171}
172#endif
173
139static inline void volume_onmount_internal(IF_MV_NONVOID(int volume)) 174static inline void volume_onmount_internal(IF_MV_NONVOID(int volume))
140{ 175{
141#if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) && !defined(BOOTLOADER) 176#if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) && !defined(BOOTLOADER)
@@ -148,13 +183,7 @@ static inline void volume_onmount_internal(IF_MV_NONVOID(int volume))
148 /* we need to mount the drive before we can access it */ 183 /* we need to mount the drive before we can access it */
149 root_mount_path(path, 0); /* root could be different folder don't hide */ 184 root_mount_path(path, 0); /* root could be different folder don't hide */
150 185
151/*BUGFIX bootloader is less selective about which drives it will mount -- revisit */ 186 if (multiboot_is_boot_volume(IF_MV_VOL(volume)))
152#if defined(HAVE_MULTIDRIVE) && (NUM_VOLUMES_PER_DRIVE == 1)
153 if (volume_drive(volume) == boot_data.boot_volume
154 || volume == boot_data.boot_volume)
155#else
156 if (volume == boot_data.boot_volume) /* boot volume contained in uint8_t payload */
157#endif
158 { 187 {
159 int rtlen = get_redirect_dir(rtpath, sizeof(rtpath), volume, "", ""); 188 int rtlen = get_redirect_dir(rtpath, sizeof(rtpath), volume, "", "");
160 while (rtlen > 0 && rtpath[--rtlen] == PATH_SEPCH) 189 while (rtlen > 0 && rtpath[--rtlen] == PATH_SEPCH)
diff --git a/firmware/rolo.c b/firmware/rolo.c
index 1b37b6f771..f9b0cc9e61 100644
--- a/firmware/rolo.c
+++ b/firmware/rolo.c
@@ -253,7 +253,26 @@ int rolo_load(const char* filename)
253 /* write the bootdata as if rolo were the bootloader 253 /* write the bootdata as if rolo were the bootloader
254 * FIXME: this won't work for root redirect... */ 254 * FIXME: this won't work for root redirect... */
255 if (!strcmp(filename, BOOTDIR "/" BOOTFILE) && boot_data_valid) 255 if (!strcmp(filename, BOOTDIR "/" BOOTFILE) && boot_data_valid)
256 write_bootdata(filebuf, filebuf_size, boot_data.boot_volume); /* rb-loader.c */ 256 {
257 int volume = 0;
258
259 if (boot_data.version == 0)
260 volume = boot_data._boot_volume;
261 else if (boot_data.version == 1)
262 {
263 for (int i = 0; i < NUM_VOLUMES; ++i)
264 {
265 if (volume_drive(i) == boot_data.boot_drive &&
266 volume_partition(i) == boot_data.boot_partition)
267 {
268 volume = i;
269 break;
270 }
271 }
272 }
273
274 write_bootdata(filebuf, filebuf_size, volume);
275 }
257#endif 276#endif
258 277
259 if (err <= 0) 278 if (err <= 0)