gitlab.com/apertussolutions/u-root@v7.0.0+incompatible/cmds/core/init/init_linux.go (about)

     1  // Copyright 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  	"io/ioutil"
     9  	"log"
    10  	"os"
    11  	"os/exec"
    12  	"path/filepath"
    13  	"strconv"
    14  	"strings"
    15  	"syscall"
    16  
    17  	"github.com/u-root/u-root/pkg/cmdline"
    18  	"github.com/u-root/u-root/pkg/kmodule"
    19  	"github.com/u-root/u-root/pkg/libinit"
    20  	"github.com/u-root/u-root/pkg/uflag"
    21  	"github.com/u-root/u-root/pkg/ulog"
    22  )
    23  
    24  // installModules installs kernel modules (.ko files) from /lib/modules.
    25  // Useful for modules that need to be loaded for boot (ie a network
    26  // driver needed for netboot)
    27  func installModules() {
    28  	modulePattern := "/lib/modules/*.ko"
    29  	files, err := filepath.Glob(modulePattern)
    30  	if err != nil {
    31  		log.Printf("installModules: %v", err)
    32  		return
    33  	}
    34  	if len(files) == 0 {
    35  		// Since it is common for users to not have modules, no need to error or
    36  		// print if there are none to install
    37  		return
    38  	}
    39  
    40  	for _, filename := range files {
    41  		f, err := os.Open(filename)
    42  		if err != nil {
    43  			log.Printf("installModules: can't open %q: %v", filename, err)
    44  			continue
    45  		}
    46  		// Module flags are passed to the command line in the form modulename.flag=val
    47  		// And must be passed to FileInit as flag=val to be installed properly
    48  		moduleName := strings.TrimSuffix(filepath.Base(filename), filepath.Ext(filename))
    49  		flags := cmdline.FlagsForModule(moduleName)
    50  		err = kmodule.FileInit(f, flags, 0)
    51  		f.Close()
    52  		if err != nil {
    53  			log.Printf("installModules: can't install %q: %v", filename, err)
    54  		}
    55  	}
    56  }
    57  
    58  func quiet() {
    59  	if !*verbose {
    60  		// Only messages more severe than "notice" are printed.
    61  		if err := ulog.KernelLog.SetConsoleLogLevel(ulog.KLogNotice); err != nil {
    62  			log.Printf("Could not set log level: %v", err)
    63  		}
    64  	}
    65  }
    66  
    67  func osInitGo() *initCmds {
    68  	// Turn off job control when test mode is on.
    69  	ctty := libinit.WithTTYControl(!*test)
    70  
    71  	// Install modules before exec-ing into user mode below
    72  	installModules()
    73  
    74  	// systemd is "special". If we are supposed to run systemd, we're
    75  	// going to exec, and if we're going to exec, we're done here.
    76  	// systemd uber alles.
    77  	initFlags := cmdline.GetInitFlagMap()
    78  
    79  	// systemd gets upset when it discovers it isn't really process 1, so
    80  	// we can't start it in its own namespace. I just love systemd.
    81  	systemd, present := initFlags["systemd"]
    82  	systemdEnabled, boolErr := strconv.ParseBool(systemd)
    83  	if present && boolErr == nil && systemdEnabled {
    84  		if err := syscall.Exec("/inito", []string{"/inito"}, os.Environ()); err != nil {
    85  			log.Printf("Lucky you, systemd failed: %v", err)
    86  		}
    87  	}
    88  
    89  	// Allows passing args to uinit via kernel parameters, for example:
    90  	//
    91  	// uroot.uinitargs="-v --foobar"
    92  	//
    93  	// We also allow passing args to uinit via a flags file in
    94  	// /etc/uinit.flags.
    95  	args := cmdline.GetUinitArgs()
    96  	if contents, err := ioutil.ReadFile("/etc/uinit.flags"); err == nil {
    97  		args = append(args, uflag.FileToArgv(string(contents))...)
    98  	}
    99  	uinitArgs := libinit.WithArguments(args...)
   100  
   101  	return &initCmds{
   102  		cmds: []*exec.Cmd{
   103  			// inito is (optionally) created by the u-root command when the
   104  			// u-root initramfs is merged with an existing initramfs that
   105  			// has a /init. The name inito means "original /init" There may
   106  			// be an inito if we are building on an existing initramfs. All
   107  			// initos need their own pid space.
   108  			libinit.Command("/inito", libinit.WithCloneFlags(syscall.CLONE_NEWPID), ctty),
   109  
   110  			libinit.Command("/bbin/uinit", ctty, uinitArgs),
   111  			libinit.Command("/bin/uinit", ctty, uinitArgs),
   112  			libinit.Command("/buildbin/uinit", ctty, uinitArgs),
   113  
   114  			libinit.Command("/bin/defaultsh", ctty),
   115  			libinit.Command("/bin/sh", ctty),
   116  		},
   117  	}
   118  
   119  }