code.flowtr.dev/mirrors/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  }