From 30c2bc3cb62af52f0aea9ce347923b0649fb7928 Mon Sep 17 00:00:00 2001 From: Artem Chernyshev Date: Wed, 26 May 2021 17:42:03 +0300 Subject: [PATCH] feat: mark MBR bootable Similar to bec914ffdda42abcfe642bc2cdfc9fcda56a74ee but make it optional instead. Signed-off-by: Artem Chernyshev --- blockdevice/partition/gpt/gpt.go | 28 +++++++++++++++++++--------- blockdevice/partition/gpt/options.go | 10 ++++++++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/blockdevice/partition/gpt/gpt.go b/blockdevice/partition/gpt/gpt.go index 6084a5d..b66e20d 100644 --- a/blockdevice/partition/gpt/gpt.go +++ b/blockdevice/partition/gpt/gpt.go @@ -41,10 +41,11 @@ func (outOfSpaceError) OutOfSpaceError() {} // GPT represents the GUID Partition Table. type GPT struct { - f *os.File - l *lba.LBA - h *Header - e *Partitions + f *os.File + l *lba.LBA + h *Header + e *Partitions + markMBRBootable bool } // Open attempts to open a partition table on f. @@ -117,10 +118,11 @@ func New(f *os.File, setters ...Option) (g *GPT, err error) { h.GUUID = guuid g = &GPT{ - f: f, - l: l, - h: h, - e: &Partitions{h: h, devname: f.Name()}, + f: f, + l: l, + h: h, + e: &Partitions{h: h, devname: f.Name()}, + markMBRBootable: opts.MarkMBRBootable, } return g, nil @@ -344,6 +346,7 @@ func (g *GPT) Repair() error { // - https://en.wikipedia.org/wiki/GUID_Partition_Table#Protective_MBR_(LBA_0) // - https://www.syslinux.org/wiki/index.php?title=Doc/gpt // - https://en.wikipedia.org/wiki/Master_boot_record +// - http://www.rodsbooks.com/gdisk/bios.html func (g *GPT) newPMBR(h *Header) ([]byte, error) { p, err := g.l.ReadAt(0, 0, 512) if err != nil { @@ -355,7 +358,14 @@ func (g *GPT) newPMBR(h *Header) ([]byte, error) { // PMBR protective entry. b := p[446 : 446+16] - b[0] = 0x00 + + if g.markMBRBootable { + // Some BIOSes in legacy mode won't boot from a disk unless there is at least one + // partition in the MBR marked bootable. Mark this partition as bootable. + b[0] = 0x80 + } else { + b[0] = 0x00 + } // Partition type: EFI data partition. b[4] = 0xee diff --git a/blockdevice/partition/gpt/options.go b/blockdevice/partition/gpt/options.go index bfa0286..041de35 100644 --- a/blockdevice/partition/gpt/options.go +++ b/blockdevice/partition/gpt/options.go @@ -9,6 +9,7 @@ import "fmt" // Options is the functional options struct. type Options struct { PartitionEntriesStartLBA uint64 + MarkMBRBootable bool } // Option is the functional option func. @@ -27,6 +28,15 @@ func WithPartitionEntriesStartLBA(o uint64) Option { } } +// WithMarkMBRBootable marks MBR partition as bootable. +func WithMarkMBRBootable(value bool) Option { + return func(args *Options) error { + args.MarkMBRBootable = value + + return nil + } +} + // NewDefaultOptions initializes an `Options` struct with default values. func NewDefaultOptions(setters ...Option) (*Options, error) { opts := &Options{