1
0
Fork 0
forked from len0rd/rockbox

disk: GPT lookup code now supports virtual logical sector sizes

GPT superblocks are located at sector 1 and max_sector-1. If the system
uses a "virtual" sector that's larger than the drive's logical sector,
we need to map those virtual sector numbers to the drive's logical
sector.

If DEFAULT_VIRT_SECTOR_SIZE is defined, try that multiplier as well
as the standard multiplier of 1.

It's not practical to try every intermediate value so instead, if
DEFAULT_VIRT_SECTOR_SIZE is defined, try that as well as the standard
multiplier of 1.

This still leaves a handful of targets that don't set DEFAULT_VIRT
but do set MAX_VIRT.

Change-Id: I3accffcb97436b043836e072bfc620318a9b1230
This commit is contained in:
Solomon Peachy 2025-04-30 21:30:03 -04:00
parent 64de7aa8d2
commit 400ae7cb22

View file

@ -168,6 +168,11 @@ bool disk_init(IF_MD_NONVOID(int drive))
/* Query logical sector size */ /* Query logical sector size */
struct storage_info *info = (struct storage_info*) sector; struct storage_info *info = (struct storage_info*) sector;
storage_get_info(IF_MD_DRV(drive), info); storage_get_info(IF_MD_DRV(drive), info);
sector_t num_sectors = info->num_sectors;
#ifdef DEFAULT_VIRT_SECTOR_SIZE
unsigned int sector_size = info->sector_size;
#endif
#if (CONFIG_STORAGE & STORAGE_ATA) #if (CONFIG_STORAGE & STORAGE_ATA)
disk_writer_lock(); disk_writer_lock();
#ifdef MAX_VARIABLE_LOG_SECTOR #ifdef MAX_VARIABLE_LOG_SECTOR
@ -216,8 +221,7 @@ bool disk_init(IF_MD_NONVOID(int drive))
i,pinfo[i].type,pinfo[i].start,pinfo[i].size); i,pinfo[i].type,pinfo[i].start,pinfo[i].size);
/* extended? */ /* extended? */
if ( pinfo[i].type == 5 ) if ( pinfo[i].type == 0x05 || pinfo[i].type == 0x0f ) {
{
/* not handled yet */ /* not handled yet */
} }
@ -229,24 +233,36 @@ bool disk_init(IF_MD_NONVOID(int drive))
while (is_gpt) { while (is_gpt) {
/* Re-start partition parsing using GPT */ /* Re-start partition parsing using GPT */
uint64_t part_lba; uint64_t part_lba;
uint32_t part_entries;
uint32_t part_entry_size; uint32_t part_entry_size;
uint32_t part_entries = 0;
unsigned char* ptr = sector; unsigned char* ptr = sector;
// XXX this doesn't take into account virtual sector size... ugh. #ifdef DEFAULT_VIRT_SECTOR_SIZE
storage_read_sectors(IF_MD(drive,) 1, 1, sector); sector_t try_gpt[4] = { 1, num_sectors - 1,
DEFAULT_VIRT_SECTOR_SIZE / sector_size,
(num_sectors / (DEFAULT_VIRT_SECTOR_SIZE / sector_size)) - 1
};
part_lba = BYTES2INT64(ptr, 0); #else
if (part_lba != 0x5452415020494645ULL) { sector_t try_gpt[2] = { 1, num_sectors - 1 };
/* Try backup GPT header at final LBA of drive */ #endif
// XXX this doesn't take into account virtual sector size... ugh.
storage_read_sectors(IF_MD(drive,) info->num_sectors-1, 1, sector); for (unsigned int i = 0 ; i < (sizeof(try_gpt) / sizeof(try_gpt[0])) ; i++) {
storage_read_sectors(IF_MD(drive,) try_gpt[i], 1, sector);
part_lba = BYTES2INT64(ptr, 0); part_lba = BYTES2INT64(ptr, 0);
if (part_lba != 0x5452415020494645ULL) { if (part_lba == 0x5452415020494645ULL) {
DEBUGF("GPT: Invalid signature\n"); part_entries = 1;
#ifdef MAX_VIRT_SECTOR_SIZE
if (i >= 2)
disk_sector_multiplier[IF_MD_DRV(drive)] = try_gpt[2]; // XXX use this later?
#endif
break; break;
} }
} }
if (!part_entries) {
DEBUGF("GPT: Invalid signature\n");
break;
}
part_entry_size = BYTES2INT32(ptr, 8); part_entry_size = BYTES2INT32(ptr, 8);
if (part_entry_size != 0x00010000) { if (part_entry_size != 0x00010000) {