github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+incompatible/cmds/boot/systemboot/main.go (about) 1 // Copyright 2017-2019 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 "flag" 9 "log" 10 "os" 11 "os/exec" 12 "os/signal" 13 "strings" 14 "time" 15 16 "github.com/u-root/u-root/pkg/booter" 17 "github.com/u-root/u-root/pkg/ipmi" 18 "github.com/u-root/u-root/pkg/smbios" 19 ) 20 21 var ( 22 allowInteractive = flag.Bool("i", true, "Allow user to interrupt boot process and run commands") 23 doQuiet = flag.Bool("q", false, "Disable verbose output") 24 interval = flag.Int("I", 1, "Interval in seconds before looping to the next boot command") 25 noDefaultBoot = flag.Bool("nodefault", false, "Do not attempt default boot entries if regular ones fail") 26 ) 27 28 var defaultBootsequence = [][]string{ 29 {"fbnetboot", "-userclass", "linuxboot"}, 30 {"localboot", "-grub"}, 31 } 32 33 // Product list for running IPMI OEM commands 34 var productList = [2]string{"Tioga Pass", "Mono Lake"} 35 36 func isMatched(productName string) bool { 37 for _, v := range productList { 38 if strings.HasPrefix(productName, v) { 39 return true 40 } 41 } 42 return false 43 } 44 45 func getSystemProductName(si *smbios.Info) (string, error) { 46 t1, err := si.GetSystemInfo() 47 if err != nil { 48 log.Printf("Error getting System Information: %v", err) 49 return "", err 50 } 51 return t1.ProductName, nil 52 } 53 54 func getSystemFWVersion(si *smbios.Info) (string, error) { 55 t0, err := si.GetBIOSInfo() 56 if err != nil { 57 log.Printf("Error getting BIOS Information: %v", err) 58 return "", err 59 } 60 return t0.Version, nil 61 } 62 63 func runIPMICommands() { 64 ipmi, err := ipmi.Open(0) 65 if err != nil { 66 log.Printf("Failed to open ipmi device %v, watchdog may still be running", err) 67 return 68 } 69 defer ipmi.Close() 70 71 if err = ipmi.ShutoffWatchdog(); err != nil { 72 log.Printf("Failed to stop watchdog %v.", err) 73 } else { 74 log.Printf("Watchdog is stopped.") 75 } 76 77 // Below IPMI commands would require SMBIOS data 78 si, err := smbios.FromSysfs() 79 if err != nil { 80 log.Printf("Error reading SMBIOS info: %v", err) 81 return 82 } 83 84 if fwVersion, err := getSystemFWVersion(si); err == nil { 85 log.Printf("System firmware version: %s", fwVersion) 86 if err = ipmi.SetSystemFWVersion(fwVersion); err != nil { 87 log.Printf("Failed to set system firmware version to BMC %v.", err) 88 } 89 } 90 91 if productName, err := getSystemProductName(si); err == nil { 92 if isMatched(productName) { 93 log.Printf("Running OEM IPMI commands.") 94 } else { 95 log.Printf("No product name is matched for OEM commands.") 96 } 97 } 98 99 } 100 101 func main() { 102 flag.Parse() 103 104 log.Print(` 105 ____ _ _ _ 106 / ___| _ _ ___| |_ ___ _ __ ___ | |__ ___ ___ | |_ 107 \___ \| | | / __| __/ _ \ '_ ` + "`" + ` _ \| '_ \ / _ \ / _ \| __| 108 ___) | |_| \__ \ || __/ | | | | | |_) | (_) | (_) | |_ 109 |____/ \__, |___/\__\___|_| |_| |_|_.__/ \___/ \___/ \__| 110 |___/ 111 `) 112 runIPMICommands() 113 sleepInterval := time.Duration(*interval) * time.Second 114 if *allowInteractive { 115 log.Printf("**************************************************************************") 116 log.Print("Starting boot sequence, press CTRL-C within 5 seconds to drop into a shell") 117 log.Printf("**************************************************************************") 118 time.Sleep(5 * time.Second) 119 } else { 120 signal.Ignore() 121 } 122 123 // Get and show boot entries 124 bootEntries := booter.GetBootEntries() 125 log.Printf("BOOT ENTRIES:") 126 for _, entry := range bootEntries { 127 log.Printf(" %v) %+v", entry.Name, string(entry.Config)) 128 } 129 for _, entry := range bootEntries { 130 log.Printf("Trying boot entry %s: %s", entry.Name, string(entry.Config)) 131 if err := entry.Booter.Boot(); err != nil { 132 log.Printf("Warning: failed to boot with configuration: %+v", entry) 133 } 134 if !*doQuiet { 135 log.Printf("Sleeping %v before attempting next boot command", sleepInterval) 136 } 137 time.Sleep(sleepInterval) 138 } 139 140 // if boot entries failed, use the default boot sequence 141 log.Printf("Boot entries failed") 142 143 if !*noDefaultBoot { 144 log.Print("Falling back to the default boot sequence") 145 for { 146 for _, bootcmd := range defaultBootsequence { 147 if !*doQuiet { 148 bootcmd = append(bootcmd, "-d") 149 } 150 log.Printf("Running boot command: %v", bootcmd) 151 cmd := exec.Command(bootcmd[0], bootcmd[1:]...) 152 cmd.Stdout = os.Stdout 153 cmd.Stderr = os.Stderr 154 if err := cmd.Run(); err != nil { 155 log.Printf("Error executing %v: %v", cmd, err) 156 } 157 } 158 if !*doQuiet { 159 log.Printf("Sleeping %v before attempting next boot command", sleepInterval) 160 } 161 time.Sleep(sleepInterval) 162 } 163 } 164 }