github.com/jlowellwofford/u-root@v1.0.0/u-root.go (about) 1 // Copyright 2015-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 "flag" 9 "fmt" 10 "io/ioutil" 11 "log" 12 "os" 13 14 "github.com/u-root/u-root/pkg/golang" 15 "github.com/u-root/u-root/pkg/uroot" 16 ) 17 18 // multiFlag is used for flags that support multiple invocations, e.g. -files 19 type multiFlag []string 20 21 func (m *multiFlag) String() string { 22 return fmt.Sprint(*m) 23 } 24 25 func (m *multiFlag) Set(value string) error { 26 *m = append(*m, value) 27 return nil 28 } 29 30 // Flags for u-root builder. 31 var ( 32 build, format, tmpDir, base, outputPath *string 33 initCmd *string 34 defaultShell *string 35 useExistingInit *bool 36 extraFiles multiFlag 37 templates = map[string][]string{ 38 "all": { 39 "cmds/*", 40 }, 41 // Core should be things you don't want to live without. 42 "core": { 43 "cmds/ansi", 44 "cmds/boot", 45 "cmds/cat", 46 "cmds/cbmem", 47 "cmds/chmod", 48 "cmds/chroot", 49 "cmds/cmp", 50 "cmds/console", 51 "cmds/cp", 52 "cmds/cpio", 53 "cmds/date", 54 "cmds/dd", 55 "cmds/df", 56 "cmds/dhclient", 57 "cmds/dirname", 58 "cmds/dmesg", 59 "cmds/echo", 60 "cmds/false", 61 "cmds/field", 62 "cmds/find", 63 "cmds/free", 64 "cmds/freq", 65 "cmds/gpgv", 66 "cmds/gpt", 67 "cmds/grep", 68 "cmds/gzip", 69 "cmds/hexdump", 70 "cmds/hostname", 71 "cmds/id", 72 "cmds/init", 73 "cmds/insmod", 74 "cmds/installcommand", 75 "cmds/io", 76 "cmds/ip", 77 "cmds/kexec", 78 "cmds/kill", 79 "cmds/lddfiles", 80 "cmds/ln", 81 "cmds/losetup", 82 "cmds/ls", 83 "cmds/lsmod", 84 "cmds/mkdir", 85 "cmds/mkfifo", 86 "cmds/mknod", 87 "cmds/modprobe", 88 "cmds/mount", 89 "cmds/msr", 90 "cmds/mv", 91 "cmds/netcat", 92 "cmds/ntpdate", 93 "cmds/pci", 94 "cmds/ping", 95 "cmds/printenv", 96 "cmds/ps", 97 "cmds/pwd", 98 "cmds/pxeboot", 99 "cmds/readlink", 100 "cmds/rm", 101 "cmds/rmmod", 102 "cmds/rsdp", 103 "cmds/rush", 104 "cmds/seq", 105 "cmds/shutdown", 106 "cmds/sleep", 107 "cmds/sort", 108 "cmds/stty", 109 "cmds/switch_root", 110 "cmds/sync", 111 "cmds/tail", 112 "cmds/tee", 113 "cmds/true", 114 "cmds/truncate", 115 "cmds/umount", 116 "cmds/uname", 117 "cmds/uniq", 118 "cmds/unshare", 119 "cmds/validate", 120 "cmds/vboot", 121 "cmds/wc", 122 "cmds/wget", 123 "cmds/which", 124 }, 125 // Minimal should be things you can't live without. 126 "minimal": { 127 "cmds/cat", 128 "cmds/chmod", 129 "cmds/cmp", 130 "cmds/console", 131 "cmds/cp", 132 "cmds/date", 133 "cmds/dd", 134 "cmds/df", 135 "cmds/dhclient", 136 "cmds/dmesg", 137 "cmds/echo", 138 "cmds/find", 139 "cmds/free", 140 "cmds/gpgv", 141 "cmds/grep", 142 "cmds/gzip", 143 "cmds/hostname", 144 "cmds/id", 145 "cmds/init", 146 "cmds/insmod", 147 "cmds/io", 148 "cmds/ip", 149 "cmds/kexec", 150 "cmds/kill", 151 "cmds/ln", 152 "cmds/losetup", 153 "cmds/ls", 154 "cmds/lsmod", 155 "cmds/mkdir", 156 "cmds/mknod", 157 "cmds/modprobe", 158 "cmds/mount", 159 "cmds/msr", 160 "cmds/mv", 161 "cmds/pci", 162 "cmds/ping", 163 "cmds/printenv", 164 "cmds/ps", 165 "cmds/pwd", 166 "cmds/readlink", 167 "cmds/rm", 168 "cmds/rmmod", 169 "cmds/rush", 170 "cmds/seq", 171 "cmds/shutdown", 172 "cmds/sleep", 173 "cmds/sync", 174 "cmds/tail", 175 "cmds/tee", 176 "cmds/truncate", 177 "cmds/umount", 178 "cmds/uname", 179 "cmds/unshare", 180 "cmds/wc", 181 "cmds/wget", 182 "cmds/which", 183 }, 184 // coreboot-app minimal environment 185 "coreboot-app": { 186 "cmds/cbmem", 187 "cmds/chroot", 188 "cmds/insmod", 189 "cmds/modprobe", 190 "cmds/rmmod", 191 "cmds/sshd", 192 "cmds/switch_root", 193 }, 194 } 195 ) 196 197 func init() { 198 build = flag.String("build", "source", "u-root build format (e.g. bb or source).") 199 format = flag.String("format", "cpio", "Archival format.") 200 201 tmpDir = flag.String("tmpdir", "", "Temporary directory to put binaries in.") 202 203 base = flag.String("base", "", "Base archive to add files to.") 204 useExistingInit = flag.Bool("useinit", false, "Use existing init from base archive (only if --base was specified).") 205 outputPath = flag.String("o", "", "Path to output initramfs file.") 206 207 initCmd = flag.String("initcmd", "init", "Symlink target for /init. Can be an absolute path or a u-root command name.") 208 defaultShell = flag.String("defaultsh", "rush", "Default shell. Can be an absolute path or a u-root command name.") 209 210 flag.Var(&extraFiles, "files", "Additional files, directories, and binaries (with their ldd dependencies) to add to archive. Can be speficified multiple times.") 211 } 212 213 func main() { 214 flag.Parse() 215 216 // Main is in a separate functions so defers run on return. 217 if err := Main(); err != nil { 218 log.Fatal(err) 219 } 220 log.Printf("Successfully wrote initramfs.") 221 } 222 223 // Main is a separate function so defers are run on return, which they wouldn't 224 // on exit. 225 func Main() error { 226 env := golang.Default() 227 if env.CgoEnabled { 228 log.Printf("Disabling CGO for u-root...") 229 env.CgoEnabled = false 230 } 231 log.Printf("Build environment: %s", env) 232 if env.GOOS != "linux" { 233 log.Printf("GOOS is not linux. Did you mean to set GOOS=linux?") 234 } 235 236 builder, err := uroot.GetBuilder(*build) 237 if err != nil { 238 return err 239 } 240 archiver, err := uroot.GetArchiver(*format) 241 if err != nil { 242 return err 243 } 244 245 tempDir := *tmpDir 246 if tempDir == "" { 247 var err error 248 tempDir, err = ioutil.TempDir("", "u-root") 249 if err != nil { 250 return err 251 } 252 defer os.RemoveAll(tempDir) 253 } else if _, err := os.Stat(tempDir); os.IsNotExist(err) { 254 if err := os.MkdirAll(tempDir, 0755); err != nil { 255 return fmt.Errorf("temporary directory %q did not exist; tried to mkdir but failed: %v", tempDir, err) 256 } 257 } 258 259 // Resolve globs into package imports. 260 // 261 // Currently allowed formats: 262 // Go package imports; e.g. github.com/u-root/u-root/cmds/ls (must be in $GOPATH) 263 // Paths to Go package directories; e.g. $GOPATH/src/github.com/u-root/u-root/cmds/* 264 var pkgs []string 265 for _, a := range flag.Args() { 266 p, ok := templates[a] 267 if !ok { 268 pkgs = append(pkgs, a) 269 continue 270 } 271 pkgs = append(pkgs, p...) 272 } 273 if len(pkgs) == 0 { 274 var err error 275 pkgs, err = uroot.DefaultPackageImports(env) 276 if err != nil { 277 return err 278 } 279 } 280 281 // Open the target initramfs file. 282 w, err := archiver.OpenWriter(*outputPath, env.GOOS, env.GOARCH) 283 if err != nil { 284 return err 285 } 286 287 var baseFile uroot.ArchiveReader 288 if *base != "" { 289 bf, err := os.Open(*base) 290 if err != nil { 291 return err 292 } 293 defer bf.Close() 294 baseFile = archiver.Reader(bf) 295 } 296 297 opts := uroot.Opts{ 298 Env: env, 299 // The command-line tool only allows specifying one build mode 300 // right now. 301 Commands: []uroot.Commands{ 302 { 303 Builder: builder, 304 Packages: pkgs, 305 }, 306 }, 307 Archiver: archiver, 308 TempDir: tempDir, 309 ExtraFiles: extraFiles, 310 OutputFile: w, 311 BaseArchive: baseFile, 312 UseExistingInit: *useExistingInit, 313 InitCmd: *initCmd, 314 DefaultShell: *defaultShell, 315 } 316 return uroot.CreateInitramfs(opts) 317 }