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).