github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/boot/localboot/localboot.go (about)

     1  // Copyright 2020 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package localboot contains helper functions for booting off local disks.
     6  package localboot
     7  
     8  import (
     9  	"context"
    10  	"fmt"
    11  	"io/ioutil"
    12  	"os"
    13  	"path/filepath"
    14  
    15  	"github.com/u-root/u-root/pkg/boot"
    16  	"github.com/u-root/u-root/pkg/boot/bls"
    17  	"github.com/u-root/u-root/pkg/boot/esxi"
    18  	"github.com/u-root/u-root/pkg/boot/grub"
    19  	"github.com/u-root/u-root/pkg/boot/syslinux"
    20  	"github.com/u-root/u-root/pkg/mount"
    21  	"github.com/u-root/u-root/pkg/mount/block"
    22  	"github.com/u-root/u-root/pkg/ulog"
    23  )
    24  
    25  // parse treats device as a block device with a file system.
    26  func parse(l ulog.Logger, device *block.BlockDev, mountDir string) []boot.OSImage {
    27  	imgs, err := bls.ScanBLSEntries(l, mountDir)
    28  	if err != nil {
    29  		l.Printf("No systemd-boot BootLoaderSpec configs found on %s, trying another format...: %v", device, err)
    30  	}
    31  
    32  	grubImgs, err := grub.ParseLocalConfig(context.Background(), mountDir)
    33  	if err != nil {
    34  		l.Printf("No GRUB configs found on %s, trying another format...: %v", device, err)
    35  	}
    36  	imgs = append(imgs, grubImgs...)
    37  
    38  	syslinuxImgs, err := syslinux.ParseLocalConfig(context.Background(), mountDir)
    39  	if err != nil {
    40  		l.Printf("No syslinux configs found on %s: %v", device, err)
    41  	}
    42  	imgs = append(imgs, syslinuxImgs...)
    43  
    44  	return imgs
    45  }
    46  
    47  // parseUnmounted treats device as unmounted, with or without partitions.
    48  func parseUnmounted(l ulog.Logger, device *block.BlockDev) ([]boot.OSImage, []*mount.MountPoint) {
    49  	// This will try to mount device partition 5 and 6.
    50  	imgs, mps, err := esxi.LoadDisk(device.DevicePath())
    51  	if err != nil {
    52  		l.Printf("No ESXi disk configs found on %s: %v", device, err)
    53  	}
    54  
    55  	// This tries to mount the device itself, in case it's an installer CD.
    56  	img, mp, err := esxi.LoadCDROM(device.DevicePath())
    57  	if err != nil {
    58  		l.Printf("No ESXi CDROM configs found on %s: %v", device, err)
    59  	}
    60  	if img != nil {
    61  		imgs = append(imgs, img)
    62  		mps = append(mps, mp)
    63  	}
    64  	// Convert from *MultibootImage to OSImage.
    65  	var images []boot.OSImage
    66  	for _, i := range imgs {
    67  		images = append(images, i)
    68  	}
    69  	return images, mps
    70  }
    71  
    72  // Localboot tries to boot from any local filesystem by parsing grub configuration
    73  func Localboot(l ulog.Logger, blockDevs block.BlockDevices) ([]boot.OSImage, []*mount.MountPoint, error) {
    74  	mountPoints, err := ioutil.TempDir("", "u-root-boot")
    75  	if err != nil {
    76  		return nil, nil, fmt.Errorf("cannot create tmpdir: %v", err)
    77  	}
    78  
    79  	var images []boot.OSImage
    80  	var mps []*mount.MountPoint
    81  	for _, device := range blockDevs {
    82  		imgs, mmps := parseUnmounted(l, device)
    83  		if len(imgs) > 0 {
    84  			images = append(images, imgs...)
    85  			mps = append(mps, mmps...)
    86  		} else {
    87  			dir := filepath.Join(mountPoints, device.Name)
    88  
    89  			os.MkdirAll(dir, 0777)
    90  			mp, err := device.Mount(dir, mount.ReadOnly)
    91  			if err != nil {
    92  				os.RemoveAll(dir)
    93  				continue
    94  			}
    95  
    96  			imgs = parse(l, device, dir)
    97  			images = append(images, imgs...)
    98  			mps = append(mps, mp)
    99  		}
   100  	}
   101  	return images, mps, nil
   102  }