| 1 | =======================
|
| 2 | Early userspace support
|
| 3 | =======================
|
| 4 |
|
| 5 | Last update: 2004-12-20 tlh
|
| 6 |
|
| 7 |
|
| 8 | "Early userspace" is a set of libraries and programs that provide
|
| 9 | various pieces of functionality that are important enough to be
|
| 10 | available while a Linux kernel is coming up, but that don't need to be
|
| 11 | run inside the kernel itself.
|
| 12 |
|
| 13 | It consists of several major infrastructure components:
|
| 14 |
|
| 15 | - gen_init_cpio, a program that builds a cpio-format archive
|
| 16 | containing a root filesystem image. This archive is compressed, and
|
| 17 | the compressed image is linked into the kernel image.
|
| 18 | - initramfs, a chunk of code that unpacks the compressed cpio image
|
| 19 | midway through the kernel boot process.
|
| 20 | - klibc, a userspace C library, currently packaged separately, that is
|
| 21 | optimized for correctness and small size.
|
| 22 |
|
| 23 | The cpio file format used by initramfs is the "newc" (aka "cpio -H newc")
|
| 24 | format, and is documented in the file "buffer-format.txt". There are
|
| 25 | two ways to add an early userspace image: specify an existing cpio
|
| 26 | archive to be used as the image or have the kernel build process build
|
| 27 | the image from specifications.
|
| 28 |
|
| 29 | CPIO ARCHIVE method
|
| 30 | -------------------
|
| 31 |
|
| 32 | You can create a cpio archive that contains the early userspace image.
|
| 33 | Your cpio archive should be specified in CONFIG_INITRAMFS_SOURCE and it
|
| 34 | will be used directly. Only a single cpio file may be specified in
|
| 35 | CONFIG_INITRAMFS_SOURCE and directory and file names are not allowed in
|
| 36 | combination with a cpio archive.
|
| 37 |
|
| 38 | IMAGE BUILDING method
|
| 39 | ---------------------
|
| 40 |
|
| 41 | The kernel build process can also build an early userspace image from
|
| 42 | source parts rather than supplying a cpio archive. This method provides
|
| 43 | a way to create images with root-owned files even though the image was
|
| 44 | built by an unprivileged user.
|
| 45 |
|
| 46 | The image is specified as one or more sources in
|
| 47 | CONFIG_INITRAMFS_SOURCE. Sources can be either directories or files -
|
| 48 | cpio archives are *not* allowed when building from sources.
|
| 49 |
|
| 50 | A source directory will have it and all of its contents packaged. The
|
| 51 | specified directory name will be mapped to '/'. When packaging a
|
| 52 | directory, limited user and group ID translation can be performed.
|
| 53 | INITRAMFS_ROOT_UID can be set to a user ID that needs to be mapped to
|
| 54 | user root (0). INITRAMFS_ROOT_GID can be set to a group ID that needs
|
| 55 | to be mapped to group root (0).
|
| 56 |
|
| 57 | A source file must be directives in the format required by the
|
| 58 | usr/gen_init_cpio utility (run 'usr/gen_init_cpio -h' to get the
|
| 59 | file format). The directives in the file will be passed directly to
|
| 60 | usr/gen_init_cpio.
|
| 61 |
|
| 62 | When a combination of directories and files are specified then the
|
| 63 | initramfs image will be an aggregate of all of them. In this way a user
|
| 64 | can create a 'root-image' directory and install all files into it.
|
| 65 | Because device-special files cannot be created by a unprivileged user,
|
| 66 | special files can be listed in a 'root-files' file. Both 'root-image'
|
| 67 | and 'root-files' can be listed in CONFIG_INITRAMFS_SOURCE and a complete
|
| 68 | early userspace image can be built by an unprivileged user.
|
| 69 |
|
| 70 | As a technical note, when directories and files are specified, the
|
| 71 | entire CONFIG_INITRAMFS_SOURCE is passed to
|
| 72 | usr/gen_initramfs.sh. This means that CONFIG_INITRAMFS_SOURCE
|
| 73 | can really be interpreted as any legal argument to
|
| 74 | gen_initramfs.sh. If a directory is specified as an argument then
|
| 75 | the contents are scanned, uid/gid translation is performed, and
|
| 76 | usr/gen_init_cpio file directives are output. If a file is
|
| 77 | specified as an argument to usr/gen_initramfs.sh then the
|
| 78 | contents of the file are simply copied to the output. All of the output
|
| 79 | directives from directory scanning and file contents copying are
|
| 80 | processed by usr/gen_init_cpio.
|
| 81 |
|
| 82 | See also 'usr/gen_initramfs.sh -h'.
|
| 83 |
|
| 84 | Where's this all leading?
|
| 85 | =========================
|
| 86 |
|
| 87 | The klibc distribution contains some of the necessary software to make
|
| 88 | early userspace useful. The klibc distribution is currently
|
| 89 | maintained separately from the kernel.
|
| 90 |
|
| 91 | You can obtain somewhat infrequent snapshots of klibc from
|
| 92 | https://www.kernel.org/pub/linux/libs/klibc/
|
| 93 |
|
| 94 | For active users, you are better off using the klibc git
|
| 95 | repository, at https://git.kernel.org/?p=libs/klibc/klibc.git
|
| 96 |
|
| 97 | The standalone klibc distribution currently provides three components,
|
| 98 | in addition to the klibc library:
|
| 99 |
|
| 100 | - ipconfig, a program that configures network interfaces. It can
|
| 101 | configure them statically, or use DHCP to obtain information
|
| 102 | dynamically (aka "IP autoconfiguration").
|
| 103 | - nfsmount, a program that can mount an NFS filesystem.
|
| 104 | - kinit, the "glue" that uses ipconfig and nfsmount to replace the old
|
| 105 | support for IP autoconfig, mount a filesystem over NFS, and continue
|
| 106 | system boot using that filesystem as root.
|
| 107 |
|
| 108 | kinit is built as a single statically linked binary to save space.
|
| 109 |
|
| 110 | Eventually, several more chunks of kernel functionality will hopefully
|
| 111 | move to early userspace:
|
| 112 |
|
| 113 | - Almost all of init/do_mounts* (the beginning of this is already in
|
| 114 | place)
|
| 115 | - ACPI table parsing
|
| 116 | - Insert unwieldy subsystem that doesn't really need to be in kernel
|
| 117 | space here
|
| 118 |
|
| 119 | If kinit doesn't meet your current needs and you've got bytes to burn,
|
| 120 | the klibc distribution includes a small Bourne-compatible shell (ash)
|
| 121 | and a number of other utilities, so you can replace kinit and build
|
| 122 | custom initramfs images that meet your needs exactly.
|
| 123 |
|
| 124 | For questions and help, you can sign up for the early userspace
|
| 125 | mailing list at https://www.zytor.com/mailman/listinfo/klibc
|
| 126 |
|
| 127 | How does it work?
|
| 128 | =================
|
| 129 |
|
| 130 | The kernel has currently 3 ways to mount the root filesystem:
|
| 131 |
|
| 132 | a) all required device and filesystem drivers compiled into the kernel, no
|
| 133 | initrd. init/main.c:init() will call prepare_namespace() to mount the
|
| 134 | final root filesystem, based on the root= option and optional init= to run
|
| 135 | some other init binary than listed at the end of init/main.c:init().
|
| 136 |
|
| 137 | b) some device and filesystem drivers built as modules and stored in an
|
| 138 | initrd. The initrd must contain a binary '/linuxrc' which is supposed to
|
| 139 | load these driver modules. It is also possible to mount the final root
|
| 140 | filesystem via linuxrc and use the pivot_root syscall. The initrd is
|
| 141 | mounted and executed via prepare_namespace().
|
| 142 |
|
| 143 | c) using initramfs. The call to prepare_namespace() must be skipped.
|
| 144 | This means that a binary must do all the work. Said binary can be stored
|
| 145 | into initramfs either via modifying usr/gen_init_cpio.c or via the new
|
| 146 | initrd format, an cpio archive. It must be called "/init". This binary
|
| 147 | is responsible to do all the things prepare_namespace() would do.
|
| 148 |
|
| 149 | To maintain backwards compatibility, the /init binary will only run if it
|
| 150 | comes via an initramfs cpio archive. If this is not the case,
|
| 151 | init/main.c:init() will run prepare_namespace() to mount the final root
|
| 152 | and exec one of the predefined init binaries.
|
| 153 |
|
| 154 | Bryan O'Sullivan <[email protected]>
|