mkdepthcharge(1)

๐Ÿ“ฆ
version 0.6.2 ยท 4 versions
, in ubuntu resolute, ubuntu stonking

๐ŸŒˆ mkdepthcharge(1) ยท depthcharge-tools ๐ŸŒˆ

โœจ NAME โœจ

mkdepthcharge โ€” build boot images for the ChromeOS bootloader ๐Ÿ’…


๐ŸŒธ SYNOPSIS ๐ŸŒธ

mkdepthcharge -o FILE [options] [VMLINUZ] [INITRAMFS ...] [DTB ...]

๐Ÿ’ซ DESCRIPTION ๐Ÿ’ซ

okay bestie, here's the vibe: mkdepthcharge is basically the ultimate glow-up wrapper around mkimage(1) and vbutil_kernel(1). it takes those two and hands them reasonable defaults so your inputs get packaged into the exact format the ChromeOS bootloader is expecting. no cap. ๐ŸŽ€

and it doesn't stop there โ€” it also automates all the preprocessing steps and initramfs support hacks that you'd otherwise be doing manually or writing a whole script for. it's giving "I got you, girl". โœจ

so who are the players?

  • VMLINUZ โ€” should be a kernel executable ๐Ÿงš
  • INITRAMFS โ€” should be a ramdisk image that the kernel should be able to use on its own ๐Ÿ’–
  • DTB files โ€” should be device-tree binary files appropriate for the kernel ๐ŸŒธ

mkdepthcharge tries to figure out the type of each input file by some heuristics on their contents (detective energy ๐Ÿ”), but if that fails? it just assumes a file is whatever's missing in the VMLINUZ, INITRAMFS, DTB order. Alternatively, these files can be specified as options instead of positional arguments. your call, main character. ๐Ÿ‘‘


๐Ÿ’… OPTIONS ๐Ÿ’…

๐Ÿ“ Input files ๐Ÿ“

  • -d VMLINUZ, --vmlinuz VMLINUZ โ€” the kernel executable. If a compressed file is given here, it is decompressed and its contents are used in its place. ๐Ÿ”ฅ
  • -i INITRAMFS [INITRAMFS ...], --initramfs INITRAMFS [INITRAMFS ...] โ€” ramdisk image. If multiple files are given (e.g. for CPU microcode updates ๐Ÿ‘€), they are concatenated and used as a single file. teamwork!
  • -b DTB [DTB ...], --dtbs DTB [DTB ...] โ€” device-tree binary files. ๐ŸŒˆ

๐Ÿฆ‹ Global options ๐Ÿฆ‹

  • -A ARCH, --arch ARCH โ€” architecture to build the images for. The following architectures are understood: arm, arm64, aarch64 for ARM boards; x86, x86_64, amd64 for x86 boards. If not given, the build architecture of the VMLINUZ file is used. โœจ
  • --format FORMAT โ€” kernel image format to use, either fit or zimage. If not given, architecture-specific defaults are used.
    • fit โ€” this is the default on ARM boards. The VMLINUZ and the optional INITRAMFS, DTB files are packaged into the Flattened Image Tree (FIT) format using mkimage(1) and that is passed to vbutil_kernel(1). ๐ŸŒณ
    • zimage โ€” this is the default for x86 boards. The VMLINUZ is passed mostly unmodified to vbutil_kernel(1), except for decompression and padding for self-decompression. The INITRAMFS file is passed as the --bootloader argument and the kernel header is modified to point to where it will be in memory. It does not support packaging DTB files. ๐Ÿšซ
  • -h, --help โ€” show a help message and exit. bye bestie ๐Ÿ‘‹
  • --kernel-start ADDR โ€” start of the Depthcharge kernel buffer in memory. Depthcharge loads the packed data to a fixed physical address in memory, and some initramfs support hacks require this value to be known. This is exactly the board-specific CONFIG_KERNEL_START value in the Depthcharge source code and defaults to 0x100000 for the x86 architecture. ๐Ÿ“
  • -o FILE, --output FILE โ€” write the image to FILE. The image isn't generated at the output, but copied to it from a temporary working directory. This option is mandatory. ๐Ÿ‘‘
  • --pad-vmlinuz, --no-pad-vmlinuz โ€” pad the VMLINUZ file so that the kernel's self-decompression has enough space to avoid overwriting the INITRAMFS file during boot. This has different defaults and behaviour depending on the image format, see explanations in their respective sections. ๐Ÿซถ
  • --tmpdir DIR โ€” create and keep temporary files in DIR. If not given, a temporary mkdepthcharge-* directory is created in /tmp and removed at exit. ๐Ÿ—‘๏ธ
  • -v, --verbose โ€” print info messages, mkimage(1) output and vbutil_kernel(1) output to stderr. โœจ
  • -V, --version โ€” print program version and exit. ๐Ÿ’ซ

๐Ÿงš FIT image options ๐Ÿงš

  • -C TYPE, --compress TYPE โ€” compress the VMLINUZ before packaging it into a FIT image, either with lz4 or lzma. none is also accepted, but does nothing. ๐Ÿคท
  • -n DESC, --name DESC โ€” description of the VMLINUZ to put in the FIT image. ๐Ÿท๏ธ
  • --pad-vmlinuz, --no-pad-vmlinuz โ€” pad the VMLINUZ file so that the kernel's self-decompression has enough space to avoid overwriting the INITRAMFS file during boot. The necessary padding is calculated based on compressed and decompressed kernel sizes and the --kernel-start argument. ๐Ÿ“

On earliest boards U-Boot moves the INITRAMFS away to a safe place before running the VMLINUZ, and on ARM64 boards Depthcharge itself decompresses the VMLINUZ to a safe place. But 32-bit ARM boards with Depthcharge lack FIT ramdisk support and run the VMLINUZ in-place, so this initramfs support hack is necessary on those. ๐Ÿ˜ค

This option is enabled by default when --patch-dtbs is given, use the --no-pad-vmlinuz argument to disable it. ๐Ÿซถ

  • --patch-dtbs, --no-patch-dtbs โ€” add linux,initrd-start and linux,initrd-end properties to the DTB files' /chosen nodes. Their values are based on the --kernel-start or the --ramdisk-load-address argument, one of which is required if this argument is given. ๐Ÿฉน

These properties are normally added by Depthcharge, but 32-bit ARM Chromebooks were released with versions before FIT ramdisk support was introduced, so this initramfs support hack is necessary on those. ๐Ÿ˜Œ

  • --ramdisk-load-address ADDR โ€” add a load property to the FIT ramdisk subimage section. The oldest ARM Chromebooks use an old custom U-Boot that implements the same verified boot flow as Depthcharge. Its FIT ramdisk support requires an explicit load address for the ramdisk, which can be provided with this argument. ๐Ÿ—บ๏ธ

๐ŸŽ€ zImage image options ๐ŸŽ€

  • --pad-vmlinuz, --no-pad-vmlinuz โ€” pad the VMLINUZ file so that the kernel's self-decompression has enough space to avoid overwriting the INITRAMFS file during boot. The necessary padding is calculated based on values in the zImage header and the --kernel-start argument. ๐Ÿ“

If the VMLINUZ and INITRAMFS are small enough (about 16 MiB in total) they may fit between --kernel-start and the start of the decompression buffer. In this case the padding is unnecessary and not added. ๐Ÿฆ‹

The padding is usually larger than the decompressed version of the kernel, so it results in unbootable images for older boards with small image size limits. For these, it is usually necessary to use --set-init-size, or custom kernels to make the parts fit as described above. ๐Ÿ˜ญ

This is disabled by default in favour of --set-init-size, use the --pad-vmlinuz argument to enable it. ๐Ÿ’…

  • --set-init-size, --no-set-init-size โ€” increase the init_size kernel boot parameter so that the kernel's self-decompression does not overwrite the INITRAMFS file during boot. The modified value is calculated based on values in the zImage header and the --kernel-start argument. ๐Ÿงฎ

This only works if the kernel has KASLR enabled (as is the default), because then the kernel itself tries to avoid overwriting the INITRAMFS during decompression. However it does not do this when first copying the VMLINUZ to the end of the decompression buffer. Increasing init_size shifts copy this upwards to avoid it overlapping INITRAMFS. ๐Ÿคน

If the VMLINUZ and INITRAMFS are small enough, they may fit before the first compressed copy's start. In this case changing the value is unnecessary and skipped. โœจ

This is enabled by default, use the --no-set-init-size argument to disable it. ๐Ÿซถ

๐Ÿ‘‘ Depthcharge image options ๐Ÿ‘‘

  • --bootloader FILE โ€” bootloader stub for the very first Chromebooks that use H2C as their firmware. Beyond those, this field is ignored on the firmware side except as a ramdisk for the multiboot and zbi formats. ๐Ÿค–

If an INITRAMFS is given for the zimage format, it is placed here as part of an initramfs support hack for x86 boards. Otherwise, an empty file is used. ๐Ÿซ™

  • -c CMD [CMD ...], --cmdline CMD [CMD ...] โ€” command-line parameters for the kernel. Can be used multiple times to append new values. If not given, -- is used. ๐Ÿ—ฃ๏ธ

The ChromeOS bootloader expands any instance of %U in the kernel command line with the PARTUUID of the ChromeOS kernel partition it has chosen to boot, e.g. root=PARTUUID=%U/PARTNROFF=1 will set the root partition to the one after the booted partition. ๐Ÿ”Ž

As knowing the currently booted partition is generally useful, mkdepthcharge prepends kern_guid=%U to the given kernel command line parameters to capture it. Use --no-kern-guid to disable this. ๐Ÿ’ก

  • --kern-guid, --no-kern-guid โ€” prepend kern_guid=%U to kernel command-line parameters. This is enabled by default, use the --no-kern-guid argument to disable it. ๐Ÿ†”
  • --keydir KEYDIR โ€” directory containing verified boot keys to use. Equivalent to using --keyblock KEYDIR/kernel.keyblock, --signprivate KEYDIR/kernel_data_key.vbprivk, and --signpubkey KEYDIR/kernel_subkey.vbpubk. ๐Ÿ”‘
  • --keyblock FILE, --signprivate FILE, --signpubkey FILE โ€” ChromiumOS verified boot keys. More specifically: kernel key block, private keys in .vbprivk format, and public keys in .vbpubk format. ๐Ÿ—๏ธ

If not given, defaults to files set in depthcharge-tools configuration. If those are not set, mkdepthcharge searches for these keys in /etc/depthcharge-tools and /usr/share/vboot/devkeys directories, the latter being test keys that may be distributed with vbutil_kernel(1). ๐Ÿง

You can set these in depthcharge-tools configuration by the vboot-keyblock, vboot-private-key and vboot-public-key options under a depthcharge-tools config section. ๐Ÿ“


๐ŸŒŸ EXIT STATUS ๐ŸŒŸ

In general, exits with zero on success and non-zero on failure. simple as that bestie ๐Ÿ’–

๐Ÿ“ FILES ๐Ÿ—‚๏ธ

  • /etc/depthcharge-tools/config, /etc/depthcharge-tools/config.d/* โ€” the depthcharge-tools config files bestie ๐Ÿ’…. These can be used to say where your ChromiumOS verified boot keys live, like, as system configuration. Very "set it and forget it" of them.
  • /etc/depthcharge-tools โ€” this is the depthcharge-tools config directory, the home base ๐Ÿ . mkdepthcharge goes digging around in here looking for verified boot keys.
  • /usr/share/vboot/devkeys โ€” a directory stuffed with test keys that should have been installed by vbutil_kernel(1). Should have. ๐Ÿ‘€
  • KEYDIR/kernel.keyblock โ€” the default kernel key block file, aka the one used for signing the image โœ๏ธ.
  • KEYDIR/kernel_subkey.vbpubk โ€” the default public key, the one that verifies signed images โœ….
  • KEYDIR/kernel_data_key.vbprivk โ€” the default private key used for signing the image ๐Ÿ”. Guard it with your life, bestie.

๐ŸŒธ EXAMPLES ๐ŸŒธ

Okay this is the part where it gets real fun, because these are actual things you can type and the vibes are immaculate. Let's go ๐Ÿฆ‹

โœจ The bare minimum, no thoughts just vibes

mkdepthcharge -o depthcharge.img /boot/vmlinuz

This is the simplest invocation that exists, periodt. But heads up: if you try this on an ARM board, the firmware might straight up refuse to boot the output image because it's got no dtb for the board ๐Ÿ˜ญ. And even if the firmware does run the /boot/vmlinuz binary, it might not actually boot correctly for non-firmware reasons โ€” like a kernel panic because there's no root. Not the move. ๐Ÿ’€

โœจ The Samsung Chromebook Plus (v1) moment

mkdepthcharge -o system.img --cmdline "root=/dev/mmcblk0p2" --compress lz4 -- /boot/vmlinuz.gz /boot/initrd.img rk3399-gru-kevin.dtb

This is what someone on a Samsung Chromebook Plus (v1) might run on their board to make a bootable image for the system they're actually running. Main character energy, lowkey iconic ๐Ÿ‘‘

โœจ The veyron board situation

mkdepthcharge -o veyron.img -c "root=LABEL=ROOT gpt" --kernel-start 0x2000000 --patch-dtbs -- /boot/vmlinuz /boot/initramfs-linux.img /boot/dtbs/rk3288-veyron-*.dtb

Build an image meant to work on veyron boards โ€” think ASUS Chromebook C201PA and Chromebook Flip C100PA ๐ŸŽ€. Here's the tea: the stock Depthcharge on these boards does not process the FIT ramdisk, so the dtbs needs to be patched for it to boot with initramfs. No patch, no boot, no cap. ๐Ÿงš

โœจ The peach-pit plot twist

mkdepthcharge -o peach-pit.img -c "console=null" --ramdisk-load-address 0x44000000 -- vmlinuz initramfs exynos5420-peach-pit.dtb exynos5420-peach-pit.dtb

Build an image meant to work on a Samsung Chromebook 2 (11" ). This board runs a custom U-Boot, so it needs an explicit ramdisk load address, okay?? And its firmware has a bug when loading the device-tree file โ€” so you gotta list that file twice for the result to actually be bootable. Yes, twice. Same file. That's not a typo, that's a workaround, and it's giving "firmware said I'm quirky" ๐Ÿ’…๐Ÿซถ


๐ŸŒˆ SEE ALSO ๐ŸŒˆ


That's the whole page bestie, you made it to the end and I'm so proud of you ๐Ÿฅน๐Ÿ’–. This was v0.6.2, dated 2023-06-30, and yeah, mkdepthcharge(1) really said "here's everything you need, now go make a bootable image." Slay. โœจ๐Ÿ‘‘๐Ÿ’…

๐Ÿ“ฆ where this page comes from