diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/common/bootdata.c | 15 | ||||
-rw-r--r-- | firmware/common/multiboot.c | 15 | ||||
-rw-r--r-- | firmware/export/bootdata.h | 6 | ||||
-rw-r--r-- | firmware/include/dircache_redirect.h | 43 | ||||
-rw-r--r-- | firmware/rolo.c | 21 |
5 files changed, 89 insertions, 11 deletions
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 | ||
45 | static bool verify_boot_data_v1(void) INIT_ATTR; | ||
46 | static 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 | |||
45 | struct verify_bd_entry | 59 | struct verify_bd_entry |
46 | { | 60 | { |
47 | int version; | 61 | int version; |
@@ -50,6 +64,7 @@ struct verify_bd_entry | |||
50 | 64 | ||
51 | static const struct verify_bd_entry verify_bd[] INITDATA_ATTR = { | 65 | static 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 | ||
55 | void verify_boot_data(void) | 70 | void 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 | ||
38 | static 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) | ||
140 | static 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 | |||
139 | static inline void volume_onmount_internal(IF_MV_NONVOID(int volume)) | 174 | static 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) |