ipod6g: Prevent booting into OF if it does not support LBA48 and drive needs it

Early 6th gen ipods (80GB and 160GB "fat") are limited to LBA28
which results in a hard upper limit of 128GiB on the storage size.
The later 120GB model also shares this limitation.  These are identified
by HwVr of 0x00130000 and 0x00130100, respectively.

The final revision of the iPod Classic series (160GB "thin") does not
have this limitation, and can be identified by a HwVr of 0x00130200 or
0x00130300.

This is strictly an issue with Apple's stock firmware, and not the
hardware, and Rockbox will happily utilize the full capabiltiies of any
installed storage device.  Unfortunately, if you boot into the stock
Apple firmware, said firmware will destructively trash the partition
table and filesystem.

Consequently, the Rockbox bootloader will now check if the installed
drive requires LBA48, making sure the flashed firmware also supports
LBA48.  If not, we will disallow booting into the OF (including disk mode)
altogether.  This check can be overridden by holding down LEFT, at which
point you get to keep all the pieces.

Note: While Apple never released firmware without these limitaitons on
the older models, there is a way to update to update these to the newer
firmware.  This requires altering the stored HwVr, so it is safe to use
the HwVr as a proxy for the installe firmware capabilities.

Change-Id: Icdd5754f2a3d38c6de67fc7565fabc7aa20f19b3
This commit is contained in:
Solomon Peachy 2025-11-17 10:46:37 -05:00
parent eeb8a893f1
commit ad6cc2f099

View file

@ -64,6 +64,7 @@
#define ERR_RB 0 #define ERR_RB 0
#define ERR_OF 1 #define ERR_OF 1
#define ERR_STORAGE 2 #define ERR_STORAGE 2
#define ERR_LBA28 3
/* Safety measure - maximum allowed firmware image size. /* Safety measure - maximum allowed firmware image size.
The largest known current (October 2009) firmware is about 6.2MB so The largest known current (October 2009) firmware is about 6.2MB so
@ -166,6 +167,10 @@ void fatal_error(int err)
printf("Hold MENU+SELECT to reboot"); printf("Hold MENU+SELECT to reboot");
printf("and enter Rockbox firmware"); printf("and enter Rockbox firmware");
break; break;
case ERR_LBA28:
printf("Hold MENU+SELECT to reboot");
printf("and LEFT if you are REALLY sure");
break;
} }
#if (CONFIG_STORAGE & STORAGE_ATA) #if (CONFIG_STORAGE & STORAGE_ATA)
@ -883,11 +888,35 @@ void main(void)
/* We wait until HDD spins up to check for hold button */ /* We wait until HDD spins up to check for hold button */
if (button_hold()) { if (button_hold()) {
bool lba48 = false;
struct SysCfg syscfg;
const ssize_t result = syscfg_read(&syscfg);
if (result != -1) {
const size_t syscfg_num_entries = MIN(syscfg.header.num_entries, SYSCFG_MAX_ENTRIES);
for (size_t i = 0; i < syscfg_num_entries; i++) {
const struct SysCfgEntry* entry = &syscfg.entries[i];
const uint32_t* data32 = (uint32_t *)entry->data;
if (entry->tag == SYSCFG_TAG_HWVR) {
lba48 = (data32[1] >= 0x130200);
break;
}
}
int btn = button_read_device();
struct storage_info sinfo;
storage_get_info(0, &sinfo);
if (sinfo.num_sectors < (1 << 28) || lba48 || btn & BUTTON_LEFT) {
printf("Executing OF..."); printf("Executing OF...");
#if (CONFIG_STORAGE & STORAGE_ATA) #if (CONFIG_STORAGE & STORAGE_ATA)
ata_sleepnow(); ata_sleepnow();
#endif #endif
rc = kernel_launch_onb(); rc = kernel_launch_onb();
} else {
printf("OF does not support LBA48");
fatal_error(ERR_LBA28);
}
}
} }
} }