Skip to content

Commit e21eb05

Browse files
authored
fix(region,glance,host-deployer): guest image support bios boot mode detect (#23376)
1 parent 30ca0f5 commit e21eb05

File tree

13 files changed

+205
-113
lines changed

13 files changed

+205
-113
lines changed

pkg/apis/image/consts.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ const (
6262
IMAGE_OS_VERSION = "os_version"
6363
IMAGE_DISK_FORMAT = "disk_format"
6464
IMAGE_UEFI_SUPPORT = "uefi_support"
65+
IMAGE_BIOS_SUPPORT = "bios_support"
6566
IMAGE_IS_LVM_PARTITION = "is_lvm_partition"
6667
IMAGE_IS_READONLY = "is_readonly"
6768
IMAGE_PARTITION_TYPE = "partition_type"

pkg/compute/models/guests.go

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,26 +1798,40 @@ func (manager *SGuestManager) validateCreateData(
17981798

17991799
if imageDiskFormat != "iso" {
18001800
var imgSupportUEFI *bool
1801+
var imgSupportBIOS *bool
18011802
if desc, ok := imgProperties[imageapi.IMAGE_UEFI_SUPPORT]; ok {
18021803
support := desc == "true"
18031804
imgSupportUEFI = &support
18041805
}
1806+
if biosDesc, ok := imgProperties[imageapi.IMAGE_BIOS_SUPPORT]; ok {
1807+
supportBIOS := biosDesc == "true"
1808+
imgSupportBIOS = &supportBIOS
1809+
}
1810+
// uefi is not support set default support bios
1811+
if imgSupportUEFI == nil || !*imgSupportUEFI {
1812+
supportBIOS := true
1813+
imgSupportBIOS = &supportBIOS
1814+
}
1815+
18051816
if input.OsArch == apis.OS_ARCH_AARCH64 {
18061817
// arm image supports UEFI by default
18071818
support := true
18081819
imgSupportUEFI = &support
18091820
}
1810-
switch {
1811-
case imgSupportUEFI != nil && *imgSupportUEFI:
1812-
if len(input.Bios) == 0 {
1813-
input.Bios = "UEFI"
1814-
} else if input.Bios != "UEFI" {
1815-
return nil, httperrors.NewInputParameterError("UEFI image requires UEFI boot mode")
1821+
switch input.Bios {
1822+
case "UEFI":
1823+
if imgSupportUEFI == nil || !*imgSupportUEFI {
1824+
return nil, httperrors.NewInputParameterError("UEFI boot mode requires UEFI image")
1825+
}
1826+
case "BIOS":
1827+
if imgSupportBIOS == nil || !*imgSupportBIOS {
1828+
return nil, httperrors.NewInputParameterError("BIOS boot mode requires BIOS image")
18161829
}
18171830
default:
1818-
// not UEFI image
1819-
if input.Bios == "UEFI" && len(imgProperties) != 0 {
1820-
return nil, httperrors.NewInputParameterError("UEFI boot mode requires UEFI image")
1831+
if imgSupportUEFI != nil && *imgSupportUEFI {
1832+
input.Bios = "UEFI"
1833+
} else {
1834+
input.Bios = "BIOS"
18211835
}
18221836
}
18231837
}

pkg/hostman/diskutils/deploy_iface/deployer.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type IDeployer interface {
3434
MountRootfs(readonly bool) (fsdriver.IRootFsDriver, error)
3535
UmountRootfs(fd fsdriver.IRootFsDriver) error
3636
DetectIsUEFISupport(rootfs fsdriver.IRootFsDriver) bool
37+
DetectIsBIOSSupport(rootfs fsdriver.IRootFsDriver) bool
3738

3839
DeployGuestfs(req *apis.DeployParams) (res *apis.DeployGuestFsResponse, err error)
3940
ResizeFs(req *apis.ResizeFsParams) (res *apis.Empty, err error)

pkg/hostman/diskutils/fsutils/fsutils.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
package fsutils
1616

1717
import (
18+
"bufio"
19+
"bytes"
1820
"fmt"
21+
"os"
1922
"regexp"
2023
"strconv"
2124
"strings"
@@ -547,6 +550,63 @@ func DetectIsUEFISupport(rootfs fsdriver.IRootFsDriver, partitions []fsdriver.ID
547550
return false
548551
}
549552

553+
func DetectIsBIOSSupport(partDev string, rootfs fsdriver.IRootFsDriver) bool {
554+
fi, err := os.OpenFile(partDev, os.O_RDONLY, 0444)
555+
if err != nil {
556+
log.Errorf("failed open partdev %s: %s", partDev, err)
557+
return false
558+
}
559+
defer fi.Close()
560+
561+
// read first sector
562+
sector := make([]byte, 512)
563+
n, err := fi.Read(sector)
564+
if err != nil || n != 512 {
565+
log.Errorf("failed read first sector %d %s: %s", n, partDev, err)
566+
return false
567+
}
568+
569+
bootSignature := sector[510:512]
570+
expectedSignature := []byte{0x55, 0xAA}
571+
log.Infof("Detect is bios support bootSignature: %x", bootSignature)
572+
if bootSignature[0] != expectedSignature[0] || bootSignature[1] != expectedSignature[1] {
573+
return false
574+
}
575+
partitionType := rootfs.GetPartition().GetPhysicalPartitionType()
576+
if partitionType == "mbr" {
577+
return true
578+
} else if partitionType == "gpt" {
579+
/*
580+
Number Start (sector) End (sector) Size Code Name
581+
1 227328 83886046 39.9 GiB 8300
582+
14 2048 10239 4.0 MiB EF02
583+
15 10240 227327 106.0 MiB EF00
584+
585+
# EF02 is BIOS Boot partition
586+
*/
587+
out, err := procutils.NewCommand("sgdisk", "-p", partDev).Output()
588+
if err != nil {
589+
log.Errorf("sgdisk -p %s failed: %s, %s", partDev, err, out)
590+
return false
591+
}
592+
re := regexp.MustCompile(`^\s*(\d+)\s+(\d+)\s+(\d+)\s+([\d\.]+\s+\w+)\s+(\w+)\s*(.*)$`)
593+
scanner := bufio.NewScanner(bytes.NewReader(out))
594+
for scanner.Scan() {
595+
line := scanner.Text()
596+
m := re.FindStringSubmatch(line)
597+
if m == nil {
598+
continue
599+
}
600+
code := m[5]
601+
if code == "EF02" {
602+
return true
603+
}
604+
}
605+
}
606+
607+
return false
608+
}
609+
550610
func MountRootfs(readonly bool, partitions []fsdriver.IDiskPartition) (fsdriver.IRootFsDriver, error) {
551611
errs := []error{}
552612
for i := 0; i < len(partitions); i++ {
@@ -706,6 +766,7 @@ func ProbeImageInfo(d deploy_iface.IDeployer) (*apis.ImageInfo, error) {
706766
// multi partition concurrent, so we need umount rootfs first
707767
imageInfo.IsUefiSupport = d.DetectIsUEFISupport(rootfs)
708768
imageInfo.PhysicalPartitionType = partition.GetPhysicalPartitionType()
769+
imageInfo.IsBiosSupport = d.DetectIsBIOSSupport(rootfs)
709770
log.Infof("ProbeImageInfo response %s", imageInfo)
710771
return imageInfo, nil
711772
}

pkg/hostman/diskutils/libguestfs/driver.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ func (d *SLibguestfsDriver) DetectIsUEFISupport(rootfs fsdriver.IRootFsDriver) b
256256
return fsutils.DetectIsUEFISupport(rootfs, d.GetPartitions())
257257
}
258258

259+
func (d *SLibguestfsDriver) DetectIsBIOSSupport(rootfs fsdriver.IRootFsDriver) bool {
260+
return fsutils.DetectIsBIOSSupport(d.nbddev, rootfs)
261+
}
262+
259263
func (d *SLibguestfsDriver) MountRootfs(readonly bool) (fsdriver.IRootFsDriver, error) {
260264
return fsutils.MountRootfs(readonly, d.GetPartitions())
261265
}

pkg/hostman/diskutils/nbd/driver.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,10 @@ func (d *NBDDriver) DetectIsUEFISupport(rootfs fsdriver.IRootFsDriver) bool {
267267
return fsutils.DetectIsUEFISupport(rootfs, d.GetPartitions())
268268
}
269269

270+
func (d *NBDDriver) DetectIsBIOSSupport(rootfs fsdriver.IRootFsDriver) bool {
271+
return fsutils.DetectIsBIOSSupport(d.nbdDev, rootfs)
272+
}
273+
270274
func (d *NBDDriver) MountRootfs(readonly bool) (fsdriver.IRootFsDriver, error) {
271275
return fsutils.MountRootfs(readonly, d.GetPartitions())
272276
}

pkg/hostman/diskutils/qemu_kvm/driver.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,10 @@ func (d *QemuKvmDriver) DetectIsUEFISupport(rootfs fsdriver.IRootFsDriver) bool
380380
return false
381381
}
382382

383+
func (d *QemuKvmDriver) DetectIsBIOSSupport(rootfs fsdriver.IRootFsDriver) bool {
384+
return false
385+
}
386+
383387
func (d *QemuKvmDriver) MountRootfs(readonly bool) (fsdriver.IRootFsDriver, error) {
384388
return nil, nil
385389
}

pkg/hostman/diskutils/qemu_kvm/local_driver.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ func (d *LocalDiskDriver) DetectIsUEFISupport(rootfs fsdriver.IRootFsDriver) boo
110110
return fsutils.DetectIsUEFISupport(rootfs, d.GetPartitions())
111111
}
112112

113+
func (d *LocalDiskDriver) DetectIsBIOSSupport(rootfs fsdriver.IRootFsDriver) bool {
114+
return fsutils.DetectIsBIOSSupport("/dev/sda", rootfs)
115+
}
116+
113117
func (d *LocalDiskDriver) MountRootfs(readonly bool) (fsdriver.IRootFsDriver, error) {
114118
return fsutils.MountRootfs(readonly, d.GetPartitions())
115119
}

pkg/hostman/guestfs/fsdriver/linux.go

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -752,27 +752,26 @@ func (l *sLinuxRootFs) DetectIsUEFISupport(part IDiskPartition) bool {
752752
// ref: https://wiki.archlinux.org/title/EFI_system_partition#Check_for_an_existing_partition
753753
// To confirm this is the ESP, mount it and check whether it contains a directory named EFI,
754754
// if it does this is definitely the ESP.
755-
efiDir := "/EFI"
756-
exits := part.Exists(efiDir, false)
757-
if !exits {
758-
return false
759-
}
760-
761755
hasEFIFirmware := false
762756

763-
l.dirWalk(part, efiDir, func(path string, isDir bool) bool {
764-
if isDir {
765-
return false
766-
}
767-
// check file is UEFI firmware
768-
if strings.HasSuffix(path, ".efi") {
769-
log.Infof("EFI firmware %s found", path)
770-
hasEFIFirmware = true
771-
return true
757+
for _, efiDir := range []string{"/EFI", "/efi"} {
758+
if !part.Exists(efiDir, false) {
759+
continue
772760
}
773-
// continue walk
774-
return false
775-
})
761+
l.dirWalk(part, efiDir, func(path string, isDir bool) bool {
762+
if isDir {
763+
return false
764+
}
765+
// check file is UEFI firmware
766+
if strings.HasSuffix(path, ".efi") {
767+
log.Infof("EFI firmware %s found", path)
768+
hasEFIFirmware = true
769+
return true
770+
}
771+
// continue walk
772+
return false
773+
})
774+
}
776775

777776
return hasEFIFirmware
778777
}

pkg/hostman/guestfs/kvmpart/kvmpart.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ func (p *SKVMGuestDiskPartition) GetPhysicalPartitionType() string {
7070
idxP := strings.LastIndexByte(dev, 'p')
7171
if idxP > 0 {
7272
dev = dev[:idxP]
73+
} else {
74+
dev = strings.TrimRight(dev, "0123456789")
7375
}
7476
cmd := fmt.Sprintf(`fdisk -l %s | grep "Disk.*label type:"`, dev)
7577
output, err := procutils.NewCommand("sh", "-c", cmd).Output()

0 commit comments

Comments
 (0)