chimera-linux / cports

Chimera ports collection
BSD 2-Clause "Simplified" License
158 stars 93 forks source link

support uncompressing firmware in initramfs-tools before creating initrd #2060

Open nekopsykose opened 1 month ago

nekopsykose commented 1 month ago

mkinitramfs-tools already decompresses modules as it inserts them:

# decompress modules for boot speed, if possible
find "${DESTDIR}/${MODULESDIR}" -name '*.ko.*' | while read -r ko; do
    case "$ko" in
    *.xz)
        if ! command -v xz >/dev/null 2>&1; then
            break
        fi
        xz -d "${ko}"
        ;;
    *.zst)
        if ! command -v zstd >/dev/null 2>&1; then
            break
        fi
        zstd -q -d --rm "${ko}"
        ;;
    esac
done

this is useful because modules/fw are compressed with zstd -3, but the actual initrd uses something higher. but even without using something higher- it allows more intra-file compression if we decompress them first. so it's more space efficient to decompress them before inserting them and do the compression later.

it's also 'faster' because the whole initrd is decompressed at first and takes roughly the same time, but later there is no further decomp passes when loading stuff in the initrd (for inserting modules/firmware) since they're uncompressed, but this is probably maybe a <100ms difference on modern computers anyway

nekopsykose commented 1 month ago

some quick testing:

original initrd (zstd -11 -T0):

$ l
.rwxr-x--- 31M root root 1 second initrd.img-6.9.2-0-generic*

extracting it:

$ cpio -i <initrd.img-6.9.2-0-generic
kernel/x86/microcode/AuthenticAMD.bin: Can't create 'kernel/x86/microcode/AuthenticAMD.bin'
150 blocks
$ dd if=initrd.img-6.9.2-0-generic of=initrd.img bs=512 skip=150
60355+1 records in
60355+1 records out
30902216 bytes transferred in 0.026788 secs (1153565559 bytes/sec)
$ zstd -d -c < initrd.img > initrd.img.uncomp
$ mkdir initrd
$ cd initrd/
$ cpio -i < ../initrd.img.uncomp

quickly decompressing everything in it (this doesn't fix symlinks but that doesn't matter):

$ fd . -e zst -X zstd -d --rm

and then repacking it:

$ cd ..
$ find initrd -print0 | cpio -o --null -H newc > new-initrd
$ zstd -11 -T0 new-initrd 
new-initrd           : 21.30%   (   106 MiB =>   22.5 MiB, new-initrd.zst)
$ cat kernel/x86/microcode/AuthenticAMD.bin new-initrd.zst > new-initrd.zst.combined
$ l initrd.img-6.9.2-0-generic new-initrd.zst.combined 
.rw-r--r-- 31M demon demon 12 minutes initrd.img-6.9.2-0-generic
.rw-r--r-- 24M demon demon 9 seconds  new-initrd.zst.combined

as we can see it is 7MB smaller. this difference is purely because the .zst firmware files were decompressed and recompressed ourselves later with -11 as part of whole initrd.

the modules already do this, so this is purely for firmware. guess it needs symlink handling but should be pretty easy

nekopsykose commented 1 month ago

as we can see it is 7MB smaller.

and to be exact- the whole uncompressed firmware/ dir for me is 64mb, because of amdgpu. on other devices this is nowhere near as extreme a difference most likely