gitlab.com/apertussolutions/u-root@v7.0.0+incompatible/cmds/core/kexec/kexec_linux.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  // 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  	"io"
    23  	"log"
    24  	"os"
    25  
    26  	flag "github.com/spf13/pflag"
    27  
    28  	"github.com/u-root/u-root/pkg/boot"
    29  	"github.com/u-root/u-root/pkg/boot/kexec"
    30  	"github.com/u-root/u-root/pkg/boot/multiboot"
    31  	"github.com/u-root/u-root/pkg/cmdline"
    32  	"github.com/u-root/u-root/pkg/uio"
    33  )
    34  
    35  type options struct {
    36  	cmdline      string
    37  	reuseCmdline bool
    38  	initramfs    string
    39  	load         bool
    40  	exec         bool
    41  	debug        bool
    42  	modules      []string
    43  }
    44  
    45  func registerFlags() *options {
    46  	o := &options{}
    47  	flag.StringVarP(&o.cmdline, "cmdline", "c", "", "Append to the kernel command line")
    48  	flag.StringVar(&o.cmdline, "append", "", "Append to the kernel command line")
    49  	flag.BoolVar(&o.reuseCmdline, "reuse-cmdline", false, "Use the kernel command line from running system")
    50  	flag.StringVarP(&o.initramfs, "initrd", "i", "", "Use file as the kernel's initial ramdisk")
    51  	flag.StringVar(&o.initramfs, "initramfs", "", "Use file as the kernel's initial ramdisk")
    52  	flag.BoolVarP(&o.load, "load", "l", false, "Load the new kernel into the current kernel")
    53  	flag.BoolVarP(&o.exec, "exec", "e", false, "Execute a currently loaded kernel")
    54  	flag.BoolVarP(&o.debug, "debug", "d", false, "Print debug info")
    55  	flag.StringArrayVar(&o.modules, "module", nil, `Load multiboot module with command line args (e.g --module="mod arg1")`)
    56  	return o
    57  }
    58  
    59  func main() {
    60  	opts := registerFlags()
    61  	flag.Parse()
    62  
    63  	if (!opts.exec && flag.NArg() == 0) || flag.NArg() > 1 {
    64  		flag.PrintDefaults()
    65  		log.Fatalf("usage: kexec [flags] kernelname OR kexec -e")
    66  	}
    67  
    68  	if opts.cmdline != "" && opts.reuseCmdline {
    69  		flag.PrintDefaults()
    70  		log.Fatalf("--reuse-cmdline and other command line options are mutually exclusive")
    71  	}
    72  
    73  	if !opts.load && !opts.exec {
    74  		opts.load = true
    75  		opts.exec = true
    76  	}
    77  
    78  	newCmdline := opts.cmdline
    79  	if opts.reuseCmdline {
    80  		procCmdLine := cmdline.NewCmdLine()
    81  		if procCmdLine.Err != nil {
    82  			log.Fatal("Couldn't read /proc/cmdline")
    83  		} else {
    84  			newCmdline = procCmdLine.Raw
    85  		}
    86  	}
    87  
    88  	if opts.load {
    89  		kernelpath := flag.Arg(0)
    90  		mbkernel, err := os.Open(kernelpath)
    91  		if err != nil {
    92  			log.Fatal(err)
    93  		}
    94  		defer mbkernel.Close()
    95  		var image boot.OSImage
    96  		if err := multiboot.Probe(mbkernel); err == nil {
    97  			image = &boot.MultibootImage{
    98  				Modules: multiboot.LazyOpenModules(opts.modules),
    99  				Kernel:  mbkernel,
   100  				Cmdline: newCmdline,
   101  			}
   102  		} else {
   103  			var i io.ReaderAt
   104  			if opts.initramfs != "" {
   105  				i = uio.NewLazyFile(opts.initramfs)
   106  			}
   107  			image = &boot.LinuxImage{
   108  				Kernel:  uio.NewLazyFile(kernelpath),
   109  				Initrd:  i,
   110  				Cmdline: newCmdline,
   111  			}
   112  		}
   113  		if err := image.Load(opts.debug); err != nil {
   114  			log.Fatal(err)
   115  		}
   116  	}
   117  
   118  	if opts.exec {
   119  		if err := kexec.Reboot(); err != nil {
   120  			log.Fatalf("%v", err)
   121  		}
   122  	}
   123  }