6

I have installed Arch Linux on a USB drive with full system encryption using LUKS. The Arch wiki as usual walked me through almost everything. The only issue I ran into was using setting up the hooks in mkinitcpio. The Arch wiki says that for a USB install the block hook must come immediately after the udev hook. The wiki also says for encryption that the encrypt hook must come before, but not necessarily immediately, the filesystem hook. Following these rules I first tried:

HOOKS="encrypt base udev block autodetect modconf filesystems keyboard fsck"

but it didn't work, so I moved encrypt to be later:

HOOKS="base udev block autodetect modconf encrypt filesystems keyboard fsck"

and it works fine. This leads to my question. What are the dependencies for the encrypt hook and where can I find details about hook dependencies?

12

Your hooks are all here:

% ls /usr/lib/initcpio/{hooks,install}
/usr/lib/initcpio/hooks:
btrfs        dmraid   keymap  mdadm    mhwd-fb  miso_loop_mnt  net     shutdown  udev  v86d
consolefont  encrypt  lvm2    memdisk  miso     miso_pxe_nbd   resume  sleep     usr

/usr/lib/initcpio/install:
autodetect  consolefont  fw        mdadm_udev  miso_loop_mnt  pata    sd-encrypt   sleep    usbinput
base        dmraid       keyboard  memdisk     miso_pxe_nbd   pcmcia  sd-lvm2      strip    usr
bcache      encrypt      keymap    mhwd-fb     mmc            resume  sd-shutdown  systemd  v86d
block       filesystems  lvm2      miso        modconf        sata    sd-vconsole  udev     virtio
btrfs       fsck         mdadm     miso_kms    net            scsi    shutdown     usb

They're all shell scripts:

% cat /usr/lib/initcpio/{hooks,install}/encrypt
#!/usr/bin/ash
run_hook() {
    modprobe -a -q dm-crypt >/dev/null 2>&1
    [ "${quiet}" = "y" ] && CSQUIET=">/dev/null"
    # Get keyfile if specified
    ckeyfile="/crypto_keyfile.bin"
    if [ -n "$cryptkey" ]; then
        IFS=: read ckdev ckarg1 ckarg2 <<EOF
...

This is stuff you already know - it's very familiar.

Basically if you want something to happen in early userspace, you need only load the necessary kernel modules and act accordingly - that's all any of these hooks are doing.

If you want to know what's going on in the initramfs image, just take a peek:

% lsinitcpio --help lsinitcpio 17 usage: lsinitcpio [action] [options] 
usage: lsinitcpio [action] [options] <initramfs>

  Actions:
   -a, --analyze        analyze contents of image
   -c, --config         show configuration file image was built with
   -l, --list           list contents of the image (default)
   -x, --extract        extract image to disk

  Options:
   -h, --help           display this help
   -n, --nocolor        disable colorized output
   -V, --version        display version information
   -v, --verbose        more verbose output

lsinitcpio is handy, but it's nothing more than a helper shell function - just like the rest of those. When you look into your disk image you'll notice that it's really nothing more than that - just a regular linux root image after all:

% mkdir /tmp/init ; cd $_
% lsinitcpio $(printf /boot/*.img | head -n1) | grep -Eo '^./[^/]*' | sort -u
./VERSION
./bin
./buildconfig
./config
./dev
./etc
./init
./init_functions
./lib
./lib64
./new_root
./proc
./run
./sbin
./sys
./tmp
./usr

You can extract it:

% lsinitcpio --extract $(printf /boot/*.img | head -n1)
% ls
dev
etc
new_root
proc
run
sys
tmp
usr
VERSION
bin
buildconfig
config
init
init_functions
lib
lib64
sbin

And poke around:

% cat ./init_functions
...
default_mount_handler() {
    if [ ! -b "$root" ]; then
        err "Unable to find root device '$root'."
        echo "You are being dropped to a recovery shell"
        echo "    Type 'exit' to try and continue booting"
        launch_interactive_shell
        msg "Trying to continue (this will most likely fail) ..."
    fi
    msg ":: mounting '$root' on real root"
    if ! mount ${fstype:+-t $fstype} -o ${rwopt:-ro}${rootflags:+,$rootflags} "$root" "$1"; then
        echo "You are now being dropped into an emergency shell."
        launch_interactive_shell
        msg "Trying to continue (this will most likely fail) ..."
    fi
}
...
| improve this answer | |
4

Your issue was that the hooks are executed in the order they are listed in the HOOKS line (which is just an array) in /etc/mkinitcpio.conf. Essentially, you were trying to run the encrypt script before the base hook, which provides the runtime necessities for booting1.

You can read about each of the hooks by issuing mkinitcpio -H $hook.

The Arch Wiki mkinitcpio page has a good explanation. You can also read each of the hooks in /usr/lib/initcpio/hooks/ to see what is actually being run.

The mkinitcpio developer for Arch, Dave Reisner, also has a good post on optimising mkinitcpio which has a more detailed explanation of how it all fits together.


1. The Archwiki mkinitcpio page does make clear that you should always include the base hook first, "unless you know what you are doing." Caveat lector...

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.