summaryrefslogtreecommitdiff
path: root/make
blob: 9ce479c898cb2f218820d2cc9175caaf4e094894 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/bin/sh

#[ -n "$compressor" ] || compressor="lz4 --best --favor-decSpeed -l"
[ -n "$compressor" ] || compressor="zstd -19 -c -T0"
#[ -n "$compressor" ] || compressor="xz -c --check=crc32 --x86 --lzma2=preset=9e"

toppid=$$
die() {
    fmt=$1
    shift
    printf "error building initramfs: $fmt\n" "$@" >&2
    kill "$toppid"
    trap '' EXIT
    exit 1
}

# generate a cpio entry for a command
gen_cmd() {
    cmd=$1
    cmdp="$(command -v "$cmd")" || die 'command not found: %s' "$cmd"
    # ignore builtins
    [ "$cmd" != "$cmdp" ] || return
    printf 'file %s %s 0755 0 0\n' "$cmdp" "$cmdp"
    ldd "$cmdp" | grep / | while read line; do
        tmp=${line% *}
        lib=/${tmp#*/}
        # don't bother with ld.so.conf
        printf 'file /lib64/%s %s 0755 0 0\n' "${lib##*/}" "$lib"
    done
}

# generate the main file list
gen_cpio_list() {
    sed -e '/^#/d' cpio_list.txt
    while read insmod mod args; do
        if [ "$insmod" = insmod ]; then
            printf 'file %s %s 0644 0 0\n' "$mod" "$mod"
        fi
    done < modules.sh
    gen_cmd e2fsck
    gen_cmd dropbear
    # cryptsetup argon2 uses pthread_cancel, glibc dlopens libgcc_s.so.1
    # ldd will find the correct libgcc_s.so.1 based on ld.so.conf
    export LD_PRELOAD=libgcc_s.so.1
    gen_cmd cryptsetup
    # LD_PRELOAD unset at end of subshell
}

# filter the list and insert parent directory entries
gen_dir_ents() {
    while read type target args; do
        # re-print the original entry
        printf '%s %s %s\n' "$type" "$target" "$args"
        # print the necessary directory entries. duplicates will be
        # filtered by sort -u later
        while [ "${target%/*}" != '' ]; do
            target=${target%/*}
            printf 'dir %s 0755 0 0\n' "$target"
        done
    done
}

# filter the list and generate the make dependency file
gen_depfile() {
    deps='cpio_list.txt make'
    while read type target source args; do
        # re-print the original entry
        printf '%s %s %s %s\n' "$type" "$target" "$source" "$args"
        # accumulate the dependencies in a list to avoid make bugs.
        # there will be no duplicates since the list was previously sorted
        if [ "$type" != file ]; then
            continue
        fi
        case "$source" in
            /dev/*) continue
        esac
        deps="$deps $source"
        # avoid "No rule to make target" when deps disappear
        echo "$source:" >&3
    done
    echo "initramfs.img: $deps" >&3
}

if ! [ -e cpio_list.txt ] || ! [ -e gen_init_cpio ]; then
    cd "${0%/*}"
fi

trap 'test -L initramfs.img || test -f initramfs.img && rm -f initramfs.img; exit 1' HUP INT QUIT TERM EXIT

gen_cpio_list | \
gen_dir_ents | \
sort -u | \
gen_depfile 3>initramfs.d | \
./gen_init_cpio -t 0 - | \
$compressor > initramfs.img

trap '' EXIT