github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+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 }