summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2024-11-02 09:41:26 -0400
committerSolomon Peachy <pizza@shaftnet.org>2024-11-02 13:50:53 -0400
commita8c52b1bfb8fd4333cffc6a1d9eff830bd35dba5 (patch)
treedd705ebe8cb88a7cce98ee97a9f83342a5492c80 /firmware
parent209aeff5b147e051a8841f64e64f5d0c04646349 (diff)
downloadrockbox-a8c52b1bfb8fd4333cffc6a1d9eff830bd35dba5.tar.gz
rockbox-a8c52b1bfb8fd4333cffc6a1d9eff830bd35dba5.zip
disk: Support a non-fixed (logical) SECTOR_SIZE
This allows a single build to support ATA drives with (eg) 512B and 4K logical sector sizes. This is needed because ATA drives are user- replaceable and we don't know what could get plugged in. * Add disk_get_log_sector_size() API (no-op for non-ATA storage) * Mostly a no-op if MAX_LOG_SECTOR_SIZE is not enabled * Sanity-check that storage's logical sector size is not larger than what we're built for NOTE: Other layers (eg ATA, FAT, etc) still need to be made aware of this. Change-Id: Id6183ef0573cb0778fa9a91302e600c3e710eebd
Diffstat (limited to 'firmware')
-rw-r--r--firmware/common/disk.c75
-rw-r--r--firmware/export/disk.h4
2 files changed, 68 insertions, 11 deletions
diff --git a/firmware/common/disk.c b/firmware/common/disk.c
index bef04037ad..9c78411957 100644
--- a/firmware/common/disk.c
+++ b/firmware/common/disk.c
@@ -29,6 +29,7 @@
29#include "dir.h" 29#include "dir.h"
30#include "rb_namespace.h" 30#include "rb_namespace.h"
31#include "disk.h" 31#include "disk.h"
32#include "panic.h"
32 33
33#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) && !defined(BOOTLOADER) 34#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) && !defined(BOOTLOADER)
34#include "bootdata.h" 35#include "bootdata.h"
@@ -110,7 +111,11 @@ static void init_volume(struct volumeinfo *vi, int drive, int part)
110} 111}
111 112
112#ifdef MAX_LOG_SECTOR_SIZE 113#ifdef MAX_LOG_SECTOR_SIZE
113static int disk_sector_multiplier[NUM_DRIVES] = 114#if !(CONFIG_STORAGE & STORAGE_ATA)
115#error "MAX_LOG_SECTOR_SIZE only supported for STORAGE_ATA"
116#endif
117
118static uint16_t disk_sector_multiplier[NUM_DRIVES] =
114 { [0 ... NUM_DRIVES-1] = 1 }; 119 { [0 ... NUM_DRIVES-1] = 1 };
115 120
116int disk_get_sector_multiplier(IF_MD_NONVOID(int drive)) 121int disk_get_sector_multiplier(IF_MD_NONVOID(int drive))
@@ -125,6 +130,33 @@ int disk_get_sector_multiplier(IF_MD_NONVOID(int drive))
125} 130}
126#endif /* MAX_LOG_SECTOR_SIZE */ 131#endif /* MAX_LOG_SECTOR_SIZE */
127 132
133#if (CONFIG_STORAGE & STORAGE_ATA) // XXX make this more generic?
134static uint16_t disk_log_sector_size[NUM_DRIVES] =
135 { [0 ... NUM_DRIVES-1] = SECTOR_SIZE }; /* Updated from STORAGE_INFO */
136int disk_get_log_sector_size(IF_MD_NONVOID(int drive))
137{
138 if (!CHECK_DRV(drive))
139 return 0;
140
141 disk_reader_lock();
142 int size = disk_log_sector_size[IF_MD_DRV(drive)];
143 disk_reader_unlock();
144 return size;
145}
146#ifdef HAVE_MULTIDRIVE
147#define LOG_SECTOR_SIZE(__drive) disk_log_sector_size[__drive]
148#else
149#define LOG_SECTOR_SIZE(__drive) disk_log_sector_size[0]
150#endif /* HAVE_MULTIDRIVE */
151#else /* !STORAGE_ATA */
152#define LOG_SECTOR_SIZE(__drive) SECTOR_SIZE
153int disk_get_log_sector_size(IF_MD_NONVOID(int drive))
154{
155 IF_MD((void)drive);
156 return SECTOR_SIZE;
157}
158#endif /* !CONFIG_STORAGE & STORAGE_ATA */
159
128bool disk_init(IF_MD_NONVOID(int drive)) 160bool disk_init(IF_MD_NONVOID(int drive))
129{ 161{
130 if (!CHECK_DRV(drive)) 162 if (!CHECK_DRV(drive))
@@ -134,7 +166,30 @@ bool disk_init(IF_MD_NONVOID(int drive))
134 if (!sector) 166 if (!sector)
135 return false; 167 return false;
136 168
137 memset(sector, 0, SECTOR_SIZE); 169#if (CONFIG_STORAGE & STORAGE_ATA)
170 /* Query logical sector size */
171 struct storage_info *info = (struct storage_info*) sector;
172 storage_get_info(IF_MD_DRV(drive), info);
173 disk_writer_lock();
174#ifdef MAX_LOG_SECTOR_SIZE
175 disk_log_sector_size[IF_MD_DRV(drive)] = info->sector_size;
176#endif
177 disk_writer_unlock();
178
179#ifdef MAX_LOG_SECTOR_SIZE
180 if (info->sector_size > MAX_LOG_SECTOR_SIZE) {
181 panicf("Unsupported logical sector size: %d",
182 info->sector_size);
183 }
184#else
185 if (info->sector_size != SECTOR_SIZE) {
186 panicf("Unsupported logical sector size: %d",
187 info->sector_size);
188 }
189#endif
190#endif /* CONFIG_STORAGE & STORAGE_ATA */
191
192 memset(sector, 0, LOG_SECTOR_SIZE(drive));
138 storage_read_sectors(IF_MD(drive,) 0, 1, sector); 193 storage_read_sectors(IF_MD(drive,) 0, 1, sector);
139 194
140 bool init = false; 195 bool init = false;
@@ -213,11 +268,11 @@ bool disk_init(IF_MD_NONVOID(int drive))
213reload: 268reload:
214 storage_read_sectors(IF_MD(drive,) part_lba, 1, sector); 269 storage_read_sectors(IF_MD(drive,) part_lba, 1, sector);
215 uint8_t *pptr = ptr; 270 uint8_t *pptr = ptr;
216 while (part < MAX_PARTITIONS_PER_DRIVE && part_entries) { 271 while (part < MAX_PARTITIONS_PER_DRIVE && part_entries) {
217 if (pptr - ptr >= SECTOR_SIZE) { 272 if (pptr - ptr >= LOG_SECTOR_SIZE(drive)) {
218 part_lba++; 273 part_lba++;
219 goto reload; 274 goto reload;
220 } 275 }
221 276
222 /* Parse GPT entry. We only care about the "General Data" type, ie: 277 /* Parse GPT entry. We only care about the "General Data" type, ie:
223 EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 278 EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
@@ -337,7 +392,7 @@ int disk_mount(int drive)
337 if (!fat_mount(IF_MV(volume,) IF_MD(drive,) 0)) 392 if (!fat_mount(IF_MV(volume,) IF_MD(drive,) 0))
338 { 393 {
339#ifdef MAX_LOG_SECTOR_SIZE 394#ifdef MAX_LOG_SECTOR_SIZE
340 disk_sector_multiplier[drive] = fat_get_bytes_per_sector(IF_MV(volume)) / SECTOR_SIZE; 395 disk_sector_multiplier[drive] = fat_get_bytes_per_sector(IF_MV(volume)) / LOG_SECTOR_SIZE(drive);
341#endif 396#endif
342 mounted = 1; 397 mounted = 1;
343 init_volume(&volumes[volume], drive, 0); 398 init_volume(&volumes[volume], drive, 0);
@@ -353,10 +408,10 @@ int disk_mount(int drive)
353 if (pinfo[i].type == 0 || pinfo[i].type == 5) 408 if (pinfo[i].type == 0 || pinfo[i].type == 5)
354 continue; /* skip free/extended partitions */ 409 continue; /* skip free/extended partitions */
355 410
356 DEBUGF("Trying to mount partition %d.\n", i); 411 DEBUGF("Trying to mount partition %d.\n", i);
357 412
358#ifdef MAX_LOG_SECTOR_SIZE 413#ifdef MAX_LOG_SECTOR_SIZE
359 for (int j = 1; j <= (MAX_LOG_SECTOR_SIZE/SECTOR_SIZE); j <<= 1) 414 for (int j = 1; j <= (MAX_LOG_SECTOR_SIZE/LOG_SECTOR_SIZE(drive)); j <<= 1)
360 { 415 {
361 if (!fat_mount(IF_MV(volume,) IF_MD(drive,) pinfo[i].start * j)) 416 if (!fat_mount(IF_MV(volume,) IF_MD(drive,) pinfo[i].start * j))
362 { 417 {
diff --git a/firmware/export/disk.h b/firmware/export/disk.h
index a19e011170..4f11438b1b 100644
--- a/firmware/export/disk.h
+++ b/firmware/export/disk.h
@@ -47,10 +47,12 @@ int disk_mount(int drive);
47int disk_unmount_all(void); 47int disk_unmount_all(void);
48int disk_unmount(int drive); 48int disk_unmount(int drive);
49 49
50/* The number of 512-byte sectors in a "logical" sector. Needed for ipod 5.5G */ 50/* Used when the drive's logical sector size is smaller than the sector size used by the partition table and filesystem. Notably needed for ipod 5.5G/6G. */
51#ifdef MAX_LOG_SECTOR_SIZE 51#ifdef MAX_LOG_SECTOR_SIZE
52int disk_get_sector_multiplier(IF_MD_NONVOID(int drive)); 52int disk_get_sector_multiplier(IF_MD_NONVOID(int drive));
53#endif 53#endif
54/* The size of the drive's smallest addressible unit */
55int disk_get_log_sector_size(IF_MD_NONVOID(int drive));
54 56
55bool disk_present(IF_MD_NONVOID(int drive)); 57bool disk_present(IF_MD_NONVOID(int drive));
56 58