Skip to content

mount: probe VBR for GPT entries with unrecognized type GUIDs#33

Closed
crux161 wants to merge 1 commit into
DarkMatterCore:devfrom
crux161:gpt-unrecognized-vbr-probe
Closed

mount: probe VBR for GPT entries with unrecognized type GUIDs#33
crux161 wants to merge 1 commit into
DarkMatterCore:devfrom
crux161:gpt-unrecognized-vbr-probe

Conversation

@crux161

@crux161 crux161 commented May 29, 2026

Copy link
Copy Markdown

Summary

usbHsFsMountParseGuidPartitionTableEntry() only inspects Microsoft Basic Data and Linux Filesystem Data GPT entries, so standard filesystems placed behind other type GUIDs are skipped. For example, the Windows Recovery Environment partition created by Windows Setup uses type GUID DE94BBA4-06D1-4D40-A16A-BFD50179D6AC yet contains an NTFS volume.

This adds a fall-through branch that probes the VBR (and, on GPL builds, the EXT superblock) for any entry whose type GUID is non-empty and wasn't handled by the dedicated branches.

LBA bounds check

A GPT entry's LBA span is validated against lun_ctx->block_count at the top of the function, before any branch issues a read. Some drives leave uninitialized/garbage entries in the partition array (e.g. a type GUID 0xF4-filled with lba_start == 0xF4F4F4F4F4F4F4F4); without validation those entries cause reads at out-of-range LBAs, which on flaky BOT drives produce an Invalid CSW, force a mass-storage reset, and can drop the drive off the bus.

Testing

Built BUILD_TYPE=gpl (release + debug) for Switch (devkitA64) and exercised with the debug build on real hardware. exFAT/NTFS volumes are detected; out-of-range garbage entries are skipped without touching the device.

Resubmitting against dev per your note; supersedes #32.

Only Microsoft Basic Data and Linux Filesystem Data GPT partition
entries are currently inspected, so standard filesystems placed behind
other type GUIDs are skipped. For example, the Windows Recovery
Environment partition created by Windows Setup uses type GUID
DE94BBA4-06D1-4D40-A16A-BFD50179D6AC yet holds an NTFS volume.

Probe the VBR (and, on GPL builds, the EXT superblock) for any entry
whose type GUID is non-empty and was not handled by the dedicated
branches.

A GPT entry's LBA span is also validated against the logical unit's
block_count at the top of the function, before any branch issues a
read. This guards every branch against uninitialized/garbage partition
array entries (e.g. a type GUID 0xF4-filled with lba_start ==
0xF4F4F4F4F4F4F4F4) whose reads would target out-of-range LBAs and can
stall flaky USB drives, force a BOT mass-storage reset and drop them
off the bus.
@crux161 crux161 force-pushed the gpt-unrecognized-vbr-probe branch from 8f526d3 to 4d41bd3 Compare May 29, 2026 23:48
Comment thread source/usbhsfs_mount.c
Comment on lines +719 to +721
/* This filters out uninitialized/garbage partition array entries (e.g. a type GUID 0xF4-filled with an */
/* lba_start of 0xF4F4F4F4F4F4F4F4), whose reads would target absurd LBAs that can stall flaky USB drives, */
/* force a BOT reset and knock them off the bus. */

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section of the comment block isn't really necessary here. It is more closely related to the extra memcmp call you're adding.

@crux161

crux161 commented May 29, 2026

Copy link
Copy Markdown
Author

You're right, and thanks for catching it — that comment was misleading. It described what the branch probes for but never mentioned that the g_emptyPartitionGuid comparison is what skips unused (all-zero GUID) entries, so it read as though we probe every GUID unconditionally.

I've reworded it to state up front that we only reach this branch for entries whose type GUID is non-empty and unrecognised, while all-zero (empty) entries are skipped, and pushed the update. Appreciate the careful review.

@DarkMatterCore

Copy link
Copy Markdown
Owner

I was mistaken before, you're actually just looking for anything that doesn't match a zeroed-out GUID. Which is, well, pretty much any other GUID out there we're not already covering. In fact, the extra memcmp call isn't even needed -- you can get away with what you want to do by just using a plain else keyword.

However, there's a critical problem with this approach: hidden partition GUIDs were skipped on purpose back when I originally worked on this compilation unit. They're not mounted simply because, well, they're hidden. The same thing applies to very specific GUIDs that are tied to very specific purposes, like WinRE recovery partition GUIDs.

Perhaps it'd be better to provide a new opt-in configuration value for the library that enables partition probing on unsupported GUIDs. Then you'd just have to check if this configuration element is enabled on the final else if condition.

@DarkMatterCore

Copy link
Copy Markdown
Owner

I was mistaken before, you're actually just looking for anything that doesn't match a zeroed-out GUID. Which is, well, pretty much any other GUID out there we're not already covering. In fact, the extra memcmp call isn't even needed -- you can get away with what you want to do by just using a plain else keyword.

However, there's a critical problem with this approach: hidden partition GUIDs were skipped on purpose back when I originally worked on this compilation unit. They're not mounted simply because, well, they're hidden. The same thing applies to very specific GUIDs that are tied to very specific purposes, like WinRE recovery partition GUIDs.

Perhaps it'd be better to provide a new opt-in configuration value for the library that enables partition probing on unsupported GUIDs. Then you'd just have to check if this configuration element is enabled on the final else if condition.

I went ahead and implemented this myself in b648495. I kept your boundary checks in this commit, thanks for bringing that up.

However, I still believe the unsupported GUID behavior should not be enabled by default -- it must be consciously and explicitly enabled by library users themselves. We don't want people ruining partitions they shouldn't be messing with in the first place.

As such, I'm closing this PR. Feel free to reopen and/or open new PRs if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request good first issue Good for newcomers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants