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