github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/kexecbin/kexecbin.go (about)

     1  // Copyright 2017-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 kexecbin offers a kexec API via a callout to kexec-tools.
     6  //
     7  // u-root's kexec implementation currently covers less use-cases than the one
     8  // from kexec-tools.  The user has to embed a kexecbin program in the
     9  // initramfs, and make it available in the PATH, then call the `KexecBin`
    10  // function.  Please note that adding an external kexec implementation will
    11  // increase the ramfs size more than the pure-Go implementation from u-root.
    12  package kexecbin
    13  
    14  import (
    15  	"os"
    16  	"os/exec"
    17  )
    18  
    19  var (
    20  	// DeviceTreePaths is the virtual fs path for accessing device-tree
    21  	// through Linux
    22  	DeviceTreePaths = []string{"/sys/firmware/fdt", "/proc/device-tree"}
    23  )
    24  
    25  // KexecBin uses kexec-tools binary and runtime architecture detection
    26  // to execute abritary files.
    27  func KexecBin(kernelFilePath string, kernelCommandline string, initrdFilePath string, dtFilePath string) error {
    28  	baseCmd, err := exec.LookPath("kexecbin")
    29  	if err != nil {
    30  		return err
    31  	}
    32  
    33  	var loadCommands []string
    34  	loadCommands = append(loadCommands, "-l")
    35  	loadCommands = append(loadCommands, kernelFilePath)
    36  
    37  	if kernelCommandline != "" {
    38  		loadCommands = append(loadCommands, "--command-line="+kernelCommandline)
    39  	} else {
    40  		loadCommands = append(loadCommands, "--reuse-cmdline")
    41  	}
    42  
    43  	if initrdFilePath != "" {
    44  		loadCommands = append(loadCommands, "--initrd="+initrdFilePath)
    45  	}
    46  
    47  	if dtFilePath != "" {
    48  		loadCommands = append(loadCommands, "--dtb="+dtFilePath)
    49  	} else {
    50  		for _, dtFilePath := range DeviceTreePaths {
    51  			if _, err := os.Stat(dtFilePath); err == nil {
    52  				loadCommands = append(loadCommands, "--dtb="+dtFilePath)
    53  				break
    54  			}
    55  		}
    56  	}
    57  
    58  	// Load data into physical non reserved memory regions
    59  	cmdLoad := exec.Command(baseCmd, loadCommands...)
    60  	if err := cmdLoad.Run(); err != nil {
    61  		return err
    62  	}
    63  
    64  	// Execute into new kernel
    65  	cmdExec := exec.Command(baseCmd, "-e")
    66  	return cmdExec.Run()
    67  }