diff options
author | Solomon Peachy <pizza@shaftnet.org> | 2024-11-02 09:41:26 -0400 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2024-11-02 13:50:53 -0400 |
commit | a8c52b1bfb8fd4333cffc6a1d9eff830bd35dba5 (patch) | |
tree | dd705ebe8cb88a7cce98ee97a9f83342a5492c80 /firmware | |
parent | 209aeff5b147e051a8841f64e64f5d0c04646349 (diff) | |
download | rockbox-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.c | 75 | ||||
-rw-r--r-- | firmware/export/disk.h | 4 |
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 |
113 | static 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 | |||
118 | static uint16_t disk_sector_multiplier[NUM_DRIVES] = | ||
114 | { [0 ... NUM_DRIVES-1] = 1 }; | 119 | { [0 ... NUM_DRIVES-1] = 1 }; |
115 | 120 | ||
116 | int disk_get_sector_multiplier(IF_MD_NONVOID(int drive)) | 121 | int 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? | ||
134 | static uint16_t disk_log_sector_size[NUM_DRIVES] = | ||
135 | { [0 ... NUM_DRIVES-1] = SECTOR_SIZE }; /* Updated from STORAGE_INFO */ | ||
136 | int 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 | ||
153 | int 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 | |||
128 | bool disk_init(IF_MD_NONVOID(int drive)) | 160 | bool 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)) | |||
213 | reload: | 268 | reload: |
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); | |||
47 | int disk_unmount_all(void); | 47 | int disk_unmount_all(void); |
48 | int disk_unmount(int drive); | 48 | int 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 |
52 | int disk_get_sector_multiplier(IF_MD_NONVOID(int drive)); | 52 | int disk_get_sector_multiplier(IF_MD_NONVOID(int drive)); |
53 | #endif | 53 | #endif |
54 | /* The size of the drive's smallest addressible unit */ | ||
55 | int disk_get_log_sector_size(IF_MD_NONVOID(int drive)); | ||
54 | 56 | ||
55 | bool disk_present(IF_MD_NONVOID(int drive)); | 57 | bool disk_present(IF_MD_NONVOID(int drive)); |
56 | 58 | ||