gopkg.in/hugelgupf/u-root.v9@v9.0.0-20180831063832-3f6f1057f09b/cmds/kexec/kexec_linux.go (about)

     1  // Copyright 2015-2017 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  // kexec executes a new kernel over the running kernel (u-root).
     6  //
     7  // Synopsis:
     8  //     kexec [--initrd=FILE] [--command-line=STRING] [-l] [-e] [KERNELIMAGE]
     9  //
    10  // Description:
    11  //		 Loads a kernel for later execution.
    12  //
    13  // Options:
    14  //     --cmdline=STRING or -c=STRING: Set the kernel command line
    15  //     --reuse-commandline:           Use the kernel command line from running system
    16  //     --i=FILE or --initrd=FILE:     Use file as the kernel's initial ramdisk
    17  //     -l or --load:                  Load the new kernel into the current kernel
    18  //     -e or --exec:		      Execute a currently loaded kernel
    19  package main
    20  
    21  import (
    22  	"log"
    23  	"os"
    24  
    25  	flag "github.com/spf13/pflag"
    26  	"github.com/u-root/u-root/pkg/cmdline"
    27  	"github.com/u-root/u-root/pkg/kexec"
    28  )
    29  
    30  type options struct {
    31  	cmdline      string
    32  	reuseCmdline bool
    33  	initramfs    string
    34  	load         bool
    35  	exec         bool
    36  }
    37  
    38  func registerFlags() *options {
    39  	o := &options{}
    40  	flag.StringVarP(&o.cmdline, "cmdline", "c", "", "Set the kernel command line")
    41  	flag.BoolVar(&o.reuseCmdline, "reuse-cmdline", false, "Use the kernel command line from running system")
    42  	flag.StringVarP(&o.initramfs, "initrd", "i", "", "Use file as the kernel's initial ramdisk")
    43  	flag.BoolVarP(&o.load, "load", "l", false, "Load the new kernel into the current kernel")
    44  	flag.BoolVarP(&o.exec, "exec", "e", false, "Execute a currently loaded kernel")
    45  	return o
    46  }
    47  
    48  func main() {
    49  	opts := registerFlags()
    50  	flag.Parse()
    51  
    52  	if (opts.exec == false && flag.NArg() == 0) || flag.NArg() > 1 {
    53  		flag.PrintDefaults()
    54  		log.Fatalf("usage: kexec [flags] kernelname OR kexec -e")
    55  	}
    56  
    57  	if opts.cmdline != "" && opts.reuseCmdline {
    58  		flag.PrintDefaults()
    59  		log.Fatalf("--reuse-cmdline and other command line options are mutually exclusive")
    60  	}
    61  
    62  	if opts.load == false && opts.exec == false {
    63  		opts.load = true
    64  		opts.exec = true
    65  	}
    66  
    67  	newCmdLine := opts.cmdline
    68  	if opts.reuseCmdline {
    69  		procCmdLine := cmdline.NewCmdLine()
    70  		if procCmdLine.Err != nil {
    71  			log.Fatal("Couldn't read /proc/cmdline")
    72  		} else {
    73  			newCmdLine = procCmdLine.Raw
    74  		}
    75  	}
    76  
    77  	if opts.load {
    78  		kernelpath := flag.Args()[0]
    79  		log.Printf("Loading %s for kernel\n", kernelpath)
    80  
    81  		kernel, err := os.OpenFile(kernelpath, os.O_RDONLY, 0)
    82  		if err != nil {
    83  			log.Fatalf("open(%q): %v", kernelpath, err)
    84  		}
    85  		defer kernel.Close()
    86  
    87  		var ramfs *os.File
    88  		if opts.initramfs != "" {
    89  			ramfs, err = os.OpenFile(opts.initramfs, os.O_RDONLY, 0)
    90  			if err != nil {
    91  				log.Fatalf("open(%q): %v", opts.initramfs, err)
    92  			}
    93  			defer ramfs.Close()
    94  		}
    95  
    96  		if err := kexec.FileLoad(kernel, ramfs, newCmdLine); err != nil {
    97  			log.Fatalf("%v", err)
    98  		}
    99  	}
   100  
   101  	if opts.exec {
   102  		if err := kexec.Reboot(); err != nil {
   103  			log.Fatalf("%v", err)
   104  		}
   105  	}
   106  }