github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/README.md (about)

     1  # u-root
     2  
     3  [![Build Status](https://circleci.com/gh/u-root/u-root/tree/main.png?style=shield&circle-token=8d9396e32f76f82bf4257b60b414743e57734244)](https://circleci.com/gh/u-root/u-root/tree/main)
     4  [![codecov](https://codecov.io/gh/u-root/u-root/branch/main/graph/badge.svg?token=1qjHT02oCB)](https://codecov.io/gh/u-root/u-root)
     5  [![Go Report Card](https://goreportcard.com/badge/github.com/u-root/u-root)](https://goreportcard.com/report/github.com/u-root/u-root)
     6  [![CodeQL](https://github.com/u-root/u-root/workflows/CodeQL/badge.svg)](https://github.com/u-root/u-root/actions?query=workflow%3ACodeQL)
     7  [![GoDoc](https://godoc.org/github.com/u-root/u-root?status.svg)](https://godoc.org/github.com/u-root/u-root)
     8  [![Slack](https://slack.osfw.dev/badge.svg)](https://slack.osfw.dev)
     9  [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://github.com/u-root/u-root/blob/main/LICENSE)
    10  
    11  
    12  # Description
    13  
    14  u-root embodies four different projects.
    15  
    16  *   Go versions of many standard Linux tools, such as [ls](cmds/core/ls/ls.go),
    17      [cp](cmds/core/cp/cp.go), or [shutdown](cmds/core/shutdown/shutdown_linux.go). See
    18      [cmds/core](cmds/core) for most of these.
    19  
    20  *   A way to compile many Go programs into a single binary with
    21      [busybox mode](pkg/bb/README.md).
    22  
    23  *   A way to create initramfs (an archive of files) to use with Linux kernels.
    24  
    25  *   Go bootloaders that use `kexec` to boot Linux or multiboot kernels such as
    26      ESXi, Xen, or tboot. They are meant to be used with
    27      [LinuxBoot](https://www.linuxboot.org). With that, parsers for
    28      [GRUB config files](pkg/boot/grub) or
    29      [syslinux config files](pkg/boot/syslinux) are to make transition to
    30      LinuxBoot easier.
    31  
    32  # Usage
    33  
    34  Make sure your Go version is >=1.19.
    35  
    36  Download and install u-root either via git:
    37  
    38  ```shell
    39  git clone https://github.com/u-root/u-root
    40  cd u-root
    41  go build
    42  ```
    43  
    44  The resulting binary will the be placed where `go build` was invoked
    45  
    46  Or install directly with go:
    47  
    48  ```shell
    49  go install github.com/u-root/u-root
    50  ```
    51  
    52  **Note: The `u-root` command will end up in `$GOPATH/bin/u-root`, so you may
    53  need to add `$GOPATH/bin` to your `$PATH`.**
    54  
    55  You can now use the u-root command to build an initramfs. Here are some examples
    56  with $UROOT_PATH being the path to where the u-root sources are on the disk
    57  (explicitly specifiying this is only necessary if not runnig u-root inside the
    58  root of the repository):
    59  
    60  ```shell
    61  # Build an initramfs of all the Go cmds in ./cmds/core/... (default)
    62  u-root
    63  
    64  # Build an initramfs of all the Go cmds in ./cmds/core/...
    65  # But running the command outside of the repository root
    66  (cd /tmp && GBB_PATH=$UROOT_PATH u-root)
    67  
    68  # Generate an archive with bootloaders
    69  #
    70  # core and boot are templates that expand to sets of commands
    71  u-root core boot
    72  
    73  # Generate an archive with only these given commands
    74  u-root ./cmds/core/{init,ls,ip,dhclient,wget,cat,elvish}
    75  
    76  # Generate an archive with all of the core tools with some exceptions
    77  u-root core -cmds/core/{ls,losetup}
    78  
    79  # Generate an archive with a tool outside of u-root
    80  git clone https://github.com/u-root/cpu
    81  u-root ./cmds/core/{init,ls,elvish} ./cpu/cmds/cpud
    82  
    83  # Generate an archive with a tool outside of u-root, in any PWD
    84  (cd /tmp && GBB_PATH=$UROOT_PATH:$CPU_PATH u-root ./cmds/core/{init,ls,elvish} ./cmds/cpud)
    85  ```
    86  
    87  The default set of packages included is all packages in
    88  `github.com/u-root/u-root/cmds/core/...`.
    89  
    90  You can build the initramfs built by u-root into the kernel via the
    91  `CONFIG_INITRAMFS_SOURCE` config variable or you can load it separately via an
    92  option in for example Grub or the QEMU command line or coreboot config variable.
    93  
    94  `GBB_PATH` is a place that u-root will look for commands. Each colon-separated
    95  `GBB_PATH` element is concatenated with patterns from the command-line and
    96  checked for existence. For example:
    97  
    98  ```shell
    99  GBB_PATH=$HOME/u-root:$HOME/u-bmc u-root \
   100      cmds/core/init \
   101      cmds/core/elvish \
   102      cmd/socreset
   103  
   104  # matches:
   105  #   $HOME/u-root/cmds/core/init
   106  #   $HOME/u-root/cmds/core/elvish
   107  #   $HOME/u-bmc/cmd/socreset
   108  ```
   109  
   110  ## Extra Files
   111  
   112  You may also include additional files in the initramfs using the `-files` flag.
   113  If you add binaries with `-files` are listed, their ldd dependencies will be
   114  included as well. As example for Debian, you want to add two kernel modules for
   115  testing, executing your currently booted kernel:
   116  
   117  > NOTE: these files will be placed in the `$HOME` dir in the initramfs.
   118  
   119  ```shell
   120  u-root -files "$HOME/hello.ko $HOME/hello2.ko"
   121  qemu-system-x86_64 -kernel /boot/vmlinuz-$(uname -r) -initrd /tmp/initramfs.linux_amd64.cpio
   122  ```
   123  
   124  To specify the location in the initramfs, use `<sourcefile>:<destinationfile>`.
   125  For example:
   126  
   127  ```shell
   128  u-root -files "root-fs/usr/bin/runc:usr/bin/run"
   129  ```
   130  
   131  ## Init and Uinit
   132  
   133  u-root has a very simple (exchangable) init system controlled by the `-initcmd`
   134  and `-uinitcmd` command-line flags.
   135  
   136  *   `-initcmd` determines what `/init` is symlinked to. `-initcmd` may be a
   137      u-root command name or a symlink target.
   138  *   `-uinitcmd` is run by the default u-root [init](cmds/core/init) after some
   139      basic file system setup. There is no default, users should optionally supply
   140      their own. `-uinitcmd` may be a u-root command name with arguments or a
   141      symlink target with arguments.
   142  *   After running a uinit (if there is one), [init](cmds/core/init) will start a
   143      shell determined by the `-defaultsh` argument.
   144  
   145  We expect most users to keep their `-initcmd` as [init](cmds/core/init), but to
   146  supply their own uinit for additional initialization or to immediately load
   147  another operating system.
   148  
   149  All three command-line args accept both a u-root command name or a target
   150  symlink path. **Only `-uinitcmd` accepts command-line arguments, however.** For
   151  example,
   152  
   153  ```bash
   154  u-root -uinitcmd="echo Go Gopher" ./cmds/core/{init,echo,elvish}
   155  
   156  cpio -ivt < /tmp/initramfs.linux_amd64.cpio
   157  # ...
   158  # lrwxrwxrwx   0 root     root           12 Dec 31  1969 bin/uinit -> ../bbin/echo
   159  # lrwxrwxrwx   0 root     root            9 Dec 31  1969 init -> bbin/init
   160  
   161  qemu-system-x86_64 -kernel $KERNEL -initrd /tmp/initramfs.linux_amd64.cpio -nographic -append "console=ttyS0"
   162  # ...
   163  # [    0.848021] Freeing unused kernel memory: 896K
   164  # 2020/05/01 04:04:39 Welcome to u-root!
   165  #                              _
   166  #   _   _      _ __ ___   ___ | |_
   167  #  | | | |____| '__/ _ \ / _ \| __|
   168  #  | |_| |____| | | (_) | (_) | |_
   169  #   \__,_|    |_|  \___/ \___/ \__|
   170  #
   171  # Go Gopher
   172  # ~/>
   173  ```
   174  Passing command line arguments like above is equivalent to passing the arguments to uinit via a flags file in `/etc/uinit.flags`, see [Extra Files](#extra-files).
   175  
   176  Additionally, you can pass arguments to uinit via the `uroot.uinitargs` kernel parameters, for example:
   177  
   178  ```bash
   179  u-root -uinitcmd="echo Gopher" ./cmds/core/{init,echo,elvish}
   180  
   181  cpio -ivt < /tmp/initramfs.linux_amd64.cpio
   182  # ...
   183  # lrwxrwxrwx   0 root     root           12 Dec 31  1969 bin/uinit -> ../bbin/echo
   184  # lrwxrwxrwx   0 root     root            9 Dec 31  1969 init -> bbin/init
   185  
   186  qemu-system-x86_64 -kernel $KERNEL -initrd /tmp/initramfs.linux_amd64.cpio -nographic -append "console=ttyS0 uroot.uinitargs=Go"
   187  # ...
   188  # [    0.848021] Freeing unused kernel memory: 896K
   189  # 2020/05/01 04:04:39 Welcome to u-root!
   190  #                              _
   191  #   _   _      _ __ ___   ___ | |_
   192  #  | | | |____| '__/ _ \ / _ \| __|
   193  #  | |_| |____| | | (_) | (_) | |_
   194  #   \__,_|    |_|  \___/ \___/ \__|
   195  #
   196  # Go Gopher
   197  # ~/>
   198  ```
   199  Note the order of the passed arguments in the above example.
   200  
   201  
   202  The command you name must be present in the command set. The following will *not
   203  work*:
   204  
   205  ```bash
   206  u-root -uinitcmd="echo Go Gopher" ./cmds/core/{init,elvish}
   207  # 2020/04/30 21:05:57 could not create symlink from "bin/uinit" to "echo": command or path "echo" not included in u-root build: specify -uinitcmd="" to ignore this error and build without a uinit
   208  ```
   209  
   210  You can also refer to non-u-root-commands; they will be added as symlinks. We
   211  don't presume to know whether your symlink target is correct or not.
   212  
   213  This will build, but not work unless you add a /bin/foobar to the initramfs.
   214  
   215  ```bash
   216  u-root -uinitcmd="/bin/foobar Go Gopher" ./cmds/core/{init,elvish}
   217  ```
   218  
   219  This will boot the same as the above.
   220  
   221  ```bash
   222  u-root -uinitcmd="/bin/foobar Go Gopher" -files /bin/echo:bin/foobar ./cmds/core/{init,elvish}
   223  ```
   224  
   225  This will bypass the regular u-root init and just launch a shell:
   226  
   227  ```bash
   228  u-root -initcmd=elvish ./cmds/core/{elvish,ls}
   229  
   230  cpio -ivt < /tmp/initramfs.linux_amd64.cpio
   231  # ...
   232  # lrwxrwxrwx   0 root     root            9 Dec 31  1969 init -> bbin/elvish
   233  
   234  qemu-system-x86_64 -kernel $KERNEL -initrd /tmp/initramfs.linux_amd64.cpio -nographic -append "console=ttyS0"
   235  # ...
   236  # [    0.848021] Freeing unused kernel memory: 896K
   237  # failed to put myself in foreground: ioctl: inappropriate ioctl for device
   238  # ~/>
   239  ```
   240  
   241  (It fails to do that because some initialization is missing when the shell is
   242  started without a proper init.)
   243  
   244  ## Cross Compilation (targeting different architectures and OSes)
   245  
   246  Cross-OS and -architecture compilation comes for free with Go. In fact, every PR
   247  to the u-root repo is built against the following architectures: amd64, x86
   248  (i.e. 32bit), mipsle, armv7, arm64, and ppc64le.
   249  
   250  Further, we run integration tests on linux/amd64, freebsd/amd64 and linux/arm64,
   251  using several CI systems. If you need to add another CI system, processor or OS,
   252  please let us know.
   253  
   254  To cross compile for an ARM, on Linux:
   255  
   256  ```shell
   257  GOARCH=arm u-root
   258  ```
   259  
   260  If you are on OSX, and wish to build for Linux on AMD64:
   261  
   262  ```shell
   263  GOOS=linux GOARCH=amd64 u-root
   264  ```
   265  
   266  ## Testing in QEMU
   267  
   268  A good way to test the initramfs generated by u-root is with qemu:
   269  
   270  ```shell
   271  qemu-system-x86_64 -nographic -kernel path/to/kernel -initrd /tmp/initramfs.linux_amd64.cpio
   272  ```
   273  
   274  Note that you do not have to build a special kernel on your own, it is
   275  sufficient to use an existing one. Usually you can find one in `/boot`.
   276  
   277  If you quickly need to obtain a kernel, for example, when you are on a non-Linux
   278  system, you can assemble a URL to download one through Arch Linux's
   279  [iPXE menu file](https://www.archlinux.org/releng/netboot/archlinux.ipxe). It
   280  would download from `${mirrorurl}iso/${release}/arch/boot/x86_64/vmlinuz-linux`, so
   281  just search for a mirror URL you prefer and a release version, for example,
   282  `http://mirror.rackspace.com/archlinux/iso/2022.05.01/arch/boot/x86_64/vmlinuz-linux`.
   283  
   284  ### Framebuffer
   285  
   286  For framebuffer support, append a VESA mode via the `vga` kernel parameter:
   287  
   288  ```shell
   289  qemu-system-x86_64 \
   290    -kernel path/to/kernel \
   291    -initrd /tmp/initramfs.linux_amd64.cpio \
   292    -append "vga=786"
   293  ```
   294  
   295  For a list of modes, refer to the
   296  [Linux kernel documentation](https://github.com/torvalds/linux/blob/master/Documentation/fb/vesafb.rst#how-to-use-it).
   297  
   298  ### Entropy / Random Number Generator
   299  
   300  Some utilities, e.g., `dhclient`, require entropy to be present. For a speedy
   301  virtualized random number generator, the kernel should have the following:
   302  
   303  ```shell
   304  CONFIG_VIRTIO_PCI=y
   305  CONFIG_HW_RANDOM_VIRTIO=y
   306  CONFIG_CRYPTO_DEV_VIRTIO=y
   307  ```
   308  
   309  Then you can run your kernel in QEMU with a `virtio-rng-pci` device:
   310  
   311  ```shell
   312  qemu-system-x86_64 \
   313      -device virtio-rng-pci \
   314      -kernel vmlinuz \
   315      -initrd /tmp/initramfs.linux_amd64.cpio
   316  ```
   317  
   318  In addition, you can pass your host's RNG:
   319  
   320  ```shell
   321  qemu-system-x86_64 \
   322      -object rng-random,filename=/dev/urandom,id=rng0 \
   323      -device virtio-rng-pci,rng=rng0 \
   324      -kernel vmlinuz \
   325      -initrd /tmp/initramfs.linux_amd64.cpio
   326  ```
   327  
   328  ## u-root with Go package paths
   329  
   330  For Go package paths to be usable, the path passed to `u-root` must be in the
   331  go.mod of the working directory or one of its parents. This is mostly useful for
   332  repositories making programmatic use of u-root's APIs.
   333  
   334  ```sh
   335  cd ./u-root
   336  
   337  # In u-root's directory itself, github.com/u-root/u-root is resolvable. There is
   338  # a go.mod here that can refer to u-root.
   339  u-root github.com/u-root/u-root/cmds/core/...
   340  u-root github.com/u-root/u-root/cmds/core/*
   341  u-root github.com/u-root/u-root/cmds/core/i*
   342  ```
   343  
   344  To depend on commands outside of ones own repository, the easiest way to depend
   345  on Go commands is the following:
   346  
   347  ```sh
   348  TMPDIR=$(mktemp -d)
   349  cd $TMPDIR
   350  go mod init foobar
   351  ```
   352  
   353  Create a file with some unused build tag like this to create dependencies on
   354  commands:
   355  
   356  ```go
   357  //go:build tools
   358  
   359  package something
   360  
   361  import (
   362          "github.com/u-root/u-root/cmds/core/ip"
   363          "github.com/u-root/u-root/cmds/core/init"
   364          "github.com/hugelgupf/p9/cmd/p9ufs"
   365  )
   366  ```
   367  
   368  The unused build tag keeps it from being compiled, but its existence forces `go
   369  mod tidy` to add these dependencies to `go.mod`:
   370  
   371  ```sh
   372  go mod tidy
   373  
   374  u-root \
   375    github.com/u-root/u-root/cmds/core/ip \
   376    github.com/u-root/u-root/cmds/core/init \
   377    github.com/hugelgupf/p9/cmd/p9ufs
   378  ```
   379  
   380  ## SystemBoot
   381  
   382  SystemBoot is a set of bootloaders written in Go. It is meant to be a
   383  distribution for LinuxBoot to create a system firmware + bootloader. All of
   384  these use `kexec` to boot. The commands are in [cmds/boot](cmds/boot).
   385  
   386  *   `pxeboot`: a network boot client that uses DHCP and HTTP or TFTP to get a
   387      boot configuration which can be parsed as PXELinux or iPXE configuration
   388      files to get a boot program.
   389  
   390  *   `boot`: finds all bootable kernels on local disk, shows a menu, and boots
   391      them. Supports (basic) GRUB, (basic) syslinux, (non-EFI) BootLoaderSpec, and
   392      ESXi configurations.
   393  
   394  *   `fbnetboot`: a network boot client that uses DHCP and HTTP to get a boot
   395      program based on Linux, and boots it. To be merged with `pxeboot`.
   396  
   397  *   `localboot`: a tool that finds bootable kernel configurations on the local
   398      disks and boots them.
   399  
   400  *   `systemboot`: a wrapper around `fbnetboot` and `localboot` that just mimicks
   401      a BIOS/UEFI BDS behaviour, by looping between network booting and local
   402      booting. Use `-uinitcmd` argument to the u-root build tool to make it the
   403      boot program.
   404  
   405  This project started as a loose collection of programs in u-root by various
   406  LinuxBoot contributors, as well as a personal experiment by
   407  [Andrea Barberio](https://github.com/insomniacslk) that has since been merged
   408  in. It is now an effort of a broader community and graduated to a real project
   409  for system firmwares.
   410  
   411  More detailed information about the build process for a full LinuxBoot firmware
   412  image using u-root/systemboot and coreboot can be found in the
   413  [LinuxBoot book](https://github.com/linuxboot/book) chapter about
   414  [LinuxBoot using coreboot, u-root and systemboot](https://github.com/linuxboot/book/blob/master/coreboot.u-root.systemboot/README.md).
   415  
   416  You can build systemboot like this:
   417  
   418  ```shell
   419  u-root -uinitcmd=systemboot core ./cmds/boot/{systemboot,localboot,fbnetboot}
   420  ```
   421  
   422  ## Compression
   423  
   424  You can compress the initramfs. However, for xz compression, the kernel has some
   425  restrictions on the compression options and it is suggested to align the file to
   426  512 byte boundaries:
   427  
   428  ```shell
   429  xz --check=crc32 -9 --lzma2=dict=1MiB \
   430     --stdout /tmp/initramfs.linux_amd64.cpio \
   431     | dd conv=sync bs=512 \
   432     of=/tmp/initramfs.linux_amd64.cpio.xz
   433  ```
   434  
   435  ## Getting Packages of TinyCore
   436  
   437  Using the `tcz` command included in u-root, you can install tinycore linux
   438  packages for things you want.
   439  
   440  You can use QEMU NAT to allow you to fetch packages. Let's suppose, for example,
   441  you want bash. Once u-root is running, you can do this:
   442  
   443  ```shell
   444  % tcz bash
   445  ```
   446  
   447  The tcz command computes and fetches all dependencies. If you can't get to
   448  tinycorelinux.net, or you want package fetching to be faster, you can run your
   449  own server for tinycore packages.
   450  
   451  You can do this to get a local server using the u-root srvfiles command:
   452  
   453  ```shell
   454  % srvfiles -p 80 -d path-to-local-tinycore-packages
   455  ```
   456  
   457  Of course you have to fetch all those packages first somehow :-)
   458  
   459  ## Build an Embeddable U-root
   460  
   461  You can build this environment into a kernel as an initramfs, and further embed
   462  that into firmware as a coreboot payload.
   463  
   464  In the kernel and coreboot case, you need to configure ethernet. We have a
   465  `dhclient` command that works for both ipv4 and ipv6. Since v6 does not yet work
   466  that well for most people, a typical invocation looks like this:
   467  
   468  ```shell
   469  % dhclient -ipv4 -ipv6=false
   470  ```
   471  
   472  Or, on newer linux kernels (> 4.x) boot with ip=dhcp in the command line,
   473  assuming your kernel is configured to work that way.
   474  
   475  ## Build Modes
   476  
   477  u-root can create an initramfs in two different modes, specified by `-build`:
   478  
   479  *   `bb`/`gbb` mode: One busybox-like binary comprising all the Go tools you ask to
   480      include. See [here for how it works](pkg/bb/README.md).
   481  
   482      In this mode, u-root copies and rewrites the source of the tools you asked
   483      to include to be able to compile everything into one busybox-like binary.
   484  
   485  *   `binary` mode: each specified binary is compiled separately and all binaries
   486      are added to the initramfs.
   487  
   488  ## Updating Dependencies
   489  
   490  ```shell
   491  go get -u
   492  go mod tidy
   493  go mod vendor
   494  ```
   495  
   496  ## Building without network access
   497  
   498  Go modules require network access. If you need to make a repeatable build with
   499  no network access, make sure that your code is under `$GOPATH` and the
   500  environment variable `GO111MODULE` is set to `off`. This is:
   501  
   502  1. Pick a location for your off-network build, it can be anywhere and
   503  the directory does not need to exist ahead of time:
   504  
   505  ```shell
   506  export GOPATH=$(mktemp -d)
   507  
   508  ```
   509  
   510  2. Fetch the code, you can use `git`, `go get` or even a release file, just
   511  make sure that the code ends in: `${GOPATH}/src/github.com/u-root/u-root` E.g:
   512  
   513  ```shell
   514  mkdir -p ${GOPATH}/src/github.com/u-root/
   515  cd ${GOPATH}/src/github.com/u-root/
   516  git clone https://github.com/u-root/u-root.git
   517  cd u-root
   518  ```
   519  
   520  Or simply:
   521  
   522  ```shell
   523  GO111MODULE=off go get github.com/u-root/u-root
   524  cd $GOPATH/src/github.com/u-root/u-root
   525  ```
   526  
   527  3. Build u-root and use it normally:
   528  
   529  ```shell
   530  GO111MODULE=off GOPROXY=off go build
   531  GO111MODULE=off GOPROXY=off ./u-root
   532  ```
   533  
   534  # Hardware
   535  
   536  If you want to see u-root on real hardware, this
   537  [board](https://www.pcengines.ch/apu2.htm) is a good start.
   538  
   539  # Contributions
   540  
   541  For information about contributing, including how we sign off commits, please
   542  see [CONTRIBUTING.md](CONTRIBUTING.md).
   543  
   544  Improving existing commands (e.g., additional currently unsupported flags) is
   545  very welcome. In this case it is not even required to build an initramfs, just
   546  enter the `cmds/` directory and start coding. A list of commands that are on the
   547  roadmap can be found [here](roadmap.md).