gopkg.in/hugelgupf/u-root.v9@v9.0.0-20180831063832-3f6f1057f09b/cmds/boot2/boot.go (about) 1 // Copyright 2017-2018 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 main 6 7 import ( 8 "errors" 9 "flag" 10 "fmt" 11 "log" 12 "strconv" 13 14 "github.com/u-root/u-root/pkg/diskboot" 15 "github.com/u-root/u-root/pkg/kexec" 16 "github.com/u-root/u-root/pkg/mount" 17 ) 18 19 var ( 20 v = flag.Bool("v", false, "Print debug messages") 21 verbose = func(string, ...interface{}) {} 22 dryrun = flag.Bool("dryrun", false, "Only print out kexec commands") 23 24 devGlob = flag.String("dev", "/sys/class/block/*", "Device glob") 25 sDeviceIndex = flag.String("d", "", "Device index") 26 sConfigIndex = flag.String("c", "", "Config index") 27 sEntryIndex = flag.String("n", "", "Entry index") 28 appendCmdline = flag.String("append", "", "Additional kernel params") 29 30 devices []*diskboot.Device 31 ) 32 33 func getDevice() (*diskboot.Device, error) { 34 devices = diskboot.FindDevices(*devGlob) 35 if len(devices) == 0 { 36 return nil, errors.New("No devices found") 37 } 38 39 verbose("Got devices: %#v", devices) 40 var err error 41 deviceIndex := 0 42 if len(devices) > 1 { 43 if *sDeviceIndex == "" { 44 for i, device := range devices { 45 log.Printf("Device #%v: path: %v type: %v", 46 i, device.DevPath, device.Fstype) 47 } 48 return nil, errors.New("Multiple devices found - must specify a device index") 49 } 50 if deviceIndex, err = strconv.Atoi(*sDeviceIndex); err != nil || 51 deviceIndex < 0 || deviceIndex >= len(devices) { 52 return nil, fmt.Errorf("invalid device index %q", *sDeviceIndex) 53 } 54 } 55 return devices[deviceIndex], nil 56 } 57 58 func getConfig(device *diskboot.Device) (*diskboot.Config, error) { 59 configs := device.Configs 60 if len(configs) == 0 { 61 return nil, errors.New("No config found") 62 } 63 64 verbose("Got configs: %#v", configs) 65 var err error 66 configIndex := 0 67 if len(configs) > 1 { 68 if *sConfigIndex == "" { 69 for i, config := range configs { 70 log.Printf("Config #%v: path: %v", i, config.ConfigPath) 71 } 72 return nil, errors.New("Multiple configs found - must specify a config index") 73 } 74 if configIndex, err = strconv.Atoi(*sConfigIndex); err != nil || 75 configIndex < 0 || configIndex >= len(configs) { 76 return nil, fmt.Errorf("invalid config index %q", *sConfigIndex) 77 } 78 } 79 return configs[configIndex], nil 80 } 81 82 func getEntry(config *diskboot.Config) (*diskboot.Entry, error) { 83 verbose("Got entries: %#v", config.Entries) 84 var err error 85 entryIndex := 0 86 if *sEntryIndex != "" { 87 if entryIndex, err = strconv.Atoi(*sEntryIndex); err != nil || 88 entryIndex < 0 || entryIndex >= len(config.Entries) { 89 return nil, fmt.Errorf("invalid entry index %q", *sEntryIndex) 90 } 91 } else if config.DefaultEntry >= 0 { 92 entryIndex = config.DefaultEntry 93 } else { 94 for i, entry := range config.Entries { 95 log.Printf("Entry #%v: %#v", i, entry) 96 } 97 return nil, errors.New("No entry specified") 98 } 99 return &config.Entries[entryIndex], nil 100 } 101 102 func bootEntry(config *diskboot.Config, entry *diskboot.Entry) error { 103 verbose("Booting entry: %v", entry) 104 err := entry.KexecLoad(config.MountPath, *appendCmdline, *dryrun) 105 if err != nil { 106 return fmt.Errorf("wrror doing kexec load: %v", err) 107 } 108 109 if *dryrun { 110 return nil 111 } 112 113 err = kexec.Reboot() 114 if err != nil { 115 return fmt.Errorf("error doing kexec reboot: %v", err) 116 } 117 return nil 118 } 119 120 func cleanDevices() { 121 for _, device := range devices { 122 if err := mount.Unmount(device.MountPath, true, false); err != nil { 123 log.Printf("Error unmounting device %v: %v", device.DevPath, err) 124 } 125 } 126 } 127 128 func main() { 129 flag.Parse() 130 if *v { 131 verbose = log.Printf 132 } 133 defer cleanDevices() 134 135 device, err := getDevice() 136 if err != nil { 137 log.Panic(err) 138 } 139 config, err := getConfig(device) 140 if err != nil { 141 log.Panic(err) 142 } 143 entry, err := getEntry(config) 144 if err != nil { 145 log.Panic(err) 146 } 147 if err := bootEntry(config, entry); err != nil { 148 log.Panic(err) 149 } 150 }