Page MenuHomeFreeBSD

Add support for legacy 512-byte block size MBRs on 4K block size disks
Needs RevisionPublic

Authored by hselasky on Feb 19 2019, 10:18 AM.

Details

Reviewers
imp
phk
cem
Summary

When using MBRs for booting on a 4K block size disk, the BIOS should emulate 512 byte block size for the disk.
In order for the operating system to understand such MBRs a new SYSCTL has been added, kern.geom.part.mbr.enforce_512bbs, which basically translate the MBR partition offsets and sizes accordingly. This option works for both reading and writing MBRs.

This option allows FreeBSD to boot on an intel based MAC with 4K block size SSDs.

Diff Detail

Repository
rS FreeBSD src repository
Lint
Lint Skipped
Unit
Unit Tests Skipped
Build Status
Buildable 22609

Event Timeline

hselasky created this revision.Feb 19 2019, 10:18 AM
hselasky updated this revision to Diff 54075.Feb 19 2019, 6:29 PM
hselasky edited the summary of this revision. (Show Details)
cem added a subscriber: cem.Feb 19 2019, 9:27 PM
cem added inline comments.
sys/geom/geom_io.c
1009–1010

It seems a bit dubious to transparently RMW all GEOM IOs? Granted, nothing previously enforced length % cp->provider->sectorsize == 0.

sys/geom/part/g_part_bsd.c
51

s/512/DEV_BSIZE/ ?

Won't this universally be 512 (disklabel is only ~270 bytes)? You could instead _Static_assert(sizeof(disklabel) <= DEV_BSIZE).

64–67

It seems like this should be a property of a GEOM_PART_BSD rather than a global sysctl.

404

I would suggest doing a native sector read here and just referencing the desired portion instead.

sys/geom/part/g_part_mbr.c
62–65

Same suggestion as for GEOM_PART_BSD (property of the geom instance, not a global sysctl).

397

Set but not used variable?

639

I'd move the read-modify-write of the non-native 512 byte sub-sector out to here (or a RMW-specific subroutine).

I'm not sure I understand the point of this. No matter what the GEOM is doing, the BIOS INT call interface doesn't support 4KB sectors...?

I'm not sure I understand the point of this. No matter what the GEOM is doing, the BIOS INT call interface doesn't support 4KB sectors...?

The point is that GEOM will use 4KB based LBA addresses as a basis when setting up the MBR and BSD tables, while the loaders and boot code think those addresses and lengths are 512 byte based. This causes the wrong disk locations to be used and so the loader eventually crashes failing the get into kernel mode.

Yes, BIOS INT call will treat the 4KB device like if it was 512 byte based and hide the fact we are using multiples of 4KB disk access. This was observed by at least Apple's BIOS.

Yes, BIOS INT call will treat the 4KB device like if it was 512 byte based and hide the fact we are using multiples of 4KB disk access. This was observed by at least Apple's BIOS.

That might be something unique to Apple's CSM then. I've used the CSM which is part of the AMI UEFI implementation (branded "Aptio"), and it has never performed firmware-level 512b emulation -- AF-4Kn drives were unbootable, period.

hselasky marked 2 inline comments as done.Feb 20 2019, 8:19 AM
hselasky added inline comments.
sys/geom/part/g_part_bsd.c
64–67

@phk : Can you help with this?

404

It becomes quite more code. I'd rather have this factored out.

sys/geom/part/g_part_mbr.c
639

I was thinking these routines were not that frequently used, that it doesn't matter?

hselasky updated this revision to Diff 54127.Feb 20 2019, 8:20 AM

Address comments from @cem

Yes, BIOS INT call will treat the 4KB device like if it was 512 byte based and hide the fact we are using multiples of 4KB disk access. This was observed by at least Apple's BIOS.

That might be something unique to Apple's CSM then. I've used the CSM which is part of the AMI UEFI implementation (branded "Aptio"), and it has never performed firmware-level 512b emulation -- AF-4Kn drives were unbootable, period.

I did not manage to boot in UEFI mode on Apple. Only the regular BIOS mode works for me.

cem requested changes to this revision.Feb 20 2019, 11:33 PM
cem added inline comments.
sys/geom/part/g_part_bsd.c
64–67

For an example of how this might be done, check out g_part_ctlreq. That might set some flag on the partition via modify. It is plumbed through individual g_parts via the G_PART_MODIFY op. Something like that.

You could always inject it via ioctl (g_part_ioctl), but that is usually uglier.

404

It seems like it would add 2-3 lines, no?

sys/geom/part/g_part_mbr.c
639

They're used by ~64 different GEOM modules, none of which had potential RMW semantics before this change. I think this in particular is a blocking issue. (Also easy to overcome.)

This revision now requires changes to proceed.Feb 20 2019, 11:33 PM
hselasky added inline comments.Feb 21 2019, 9:09 AM
sys/geom/part/g_part_bsd.c
64–67

How can I have system read support for such partitions then? It is not only about writing those partitions, but also about reading them during boot.

cem added inline comments.Feb 23 2019, 12:42 AM
sys/geom/part/g_part_bsd.c
64–67

The property can either be explicitly encoded as a flag or other on-disk record, or be inferred at probe by the condition table->sectorsize == 512 && pp->sectorsize != table->sectorsize.

(The ugly style of this geom makes it difficult to determine the on-disk structure, but if you don't find a better place, there seems to be plenty of room for flags in e.g., gpt_entries, which gets 16 bits on disk but has a hardcoded maximal value of 20 decimal.)

I think there may be some benefit to inferring the property rather than requiring the explicit flag; e.g., 512 disk images splatted directly onto 4Kn disks.