Boot without extracting initramfs to memory?

Kernels, Network, and Services configuration
Post Reply
Message
Author
Fierelier
Posts: 11
Joined: 2019-08-27 13:14
Has thanked: 5 times

Boot without extracting initramfs to memory?

#1 Post by Fierelier »

Hello forums,

I've been searching quite hard for a solution to take a bit of a different approach to loading the initramfs for legacy systems. The issue is that the distro will not boot on much less than 256mb because the initramfs is too big.

Is there a way to establish swap first, or to load initramfs by mounting it instead of extracting, or can I even just load loose files? I don't want to compile my own kernel. But I'm fine with making my own initramfs, if required.

I use GRUB to boot, if that's of any help. I'm sure it's possible somehow but I haven't found anything that can accomplish it.

lindi
Posts: 44
Joined: 2022-07-12 14:10
Been thanked: 6 times

Re: Boot without extracting initramfs to memory?

#2 Post by lindi »

Easiest solution is probably to remove extra kernel modules from the initramfs and compress the rest with "xz -9". You can use "lsmod" to see what modules you actually need. Using MODULES=list in /etc/initramfs-tools/initramfs.conf you can include only modules listed in /etc/initramfs-tools/modules.

You can use xz to compress the modules in /lib. If you regenerate the initramfs it will then include those compressed versions. Note that you should not change the file extension. The kernel will automatically decompress XZ as CONFIG_DECOMPRESS_XZ=y is set in debian kernels if you use something like:

Code: Select all

for i in $(find /lib/modules -name "*.ko"); do
    if [ "$(file "$i"|grep ELF)" != "" ]; then
        xz -v -1 $i
        mv $i.xz $i
    fi
done
There is probably a way to keep the files in /lib intact and run xz only when generating the initramfs but that will of course slow down initramfs generation quite a lot as xz -9 is slow.

L_V
Posts: 1477
Joined: 2007-03-19 09:04
Been thanked: 10 times

Re: Boot without extracting initramfs to memory?

#3 Post by L_V »

I use MODULES=dep

Code: Select all

/etc/initramfs-tools/initramfs.conf

# MODULES: [ most | netboot | dep | list ]
MODULES=dep

Code: Select all

update-initramfs -u

Code: Select all

ls -sh /boot/initrd.img-5.17.0-1-amd64
14M /boot/initrd.img-5.17.0-1-amd64

Default gzip compression can be changed to xv.

Code: Select all

/etc/initramfs-tools/initramfs.conf
# COMPRESS: [ gzip | bzip2 | lz4 | lzma | lzop | xz ]
COMPRESS=xz

Fierelier
Posts: 11
Joined: 2019-08-27 13:14
Has thanked: 5 times

Re: Boot without extracting initramfs to memory?

#4 Post by Fierelier »

It's much better now. The OS boots on 128MB (for now)! Thank you!

I've compressed the modules like @lindi suggested (with -9 instead of -1, as speed is of no concern), and I've also done COMPRESS=xz like @L_V said. Though I doubt COMPRESS=xz will do much -- As far as I understand, the initramfs is decompressed into memory, and that decompression in itself requires some memory to happen, I will test that a little later. No compression could be best in this case, if I'm right.

Unfortunately, I can't just do MODULES=dep -- To give a bit more detail, I'm making my own distro with Devuan, and that involves making an ISO. I might make another initramfs with this option sourced from a VM for really desperate systems (as long as sd* devices are there, it should be okay for most systems, I reckon?), and offer it as an extra option in GRUB.

I'm open to more suggestions if anyone has them, especially if there is some way to boot an initramfs (or something like it) without extracting it into memory at all, that would be super amazing.

hamishm
Posts: 26
Joined: 2022-07-06 10:28
Has thanked: 2 times
Been thanked: 1 time

Re: Boot without extracting initramfs to memory?

#5 Post by hamishm »

If you build the drivers in to the kernel (intead of building them as modules) then you don't need an initramfs at all. You just need hardware drivers and the file system for your root file system. If all your targets for example use SATA with AHCI and ext4 then you don't need much at all.

In the beginning we loaded the kernel from the first floppy disk, then swapped it for the root floppy. The kernel only contained the ext2 file system and the floppy disk driver, and whatever else we could fit on a single disk.

User avatar
Head_on_a_Stick
Posts: 13992
Joined: 2014-06-01 17:46
Location: /dev/chair
Has thanked: 51 times
Been thanked: 77 times

Re: Boot without extracting initramfs to memory?

#6 Post by Head_on_a_Stick »

Fierelier wrote: 2022-08-16 03:02 No compression could be best in this case
^ This. Unfortunately there doesn't seem to be "none" (or "cat") listed as a compression option in the man page but you could try it. Or perhaps lindi will point me to the source code :D
Fierelier wrote: 2022-08-16 03:02Unfortunately, I can't just do MODULES=dep
I just load the modules I know are needed to pivot_root. Here's my Arch configuration:

Code: Select all

archie:~$ dec /etc/mkinitcpio.conf                           
MODULES=(amdgpu nvme btrfs)
BINARIES=()
FILES=()
HOOKS=(base)
COMPRESSION="cat"
archie:~$
The amdgpu module is only needed for early KMS so you could probably manage with just nvme, sata & the filesystem module.

EDIT: and remember to disable Busybox, that should save a few MiB.
Il semble que la perfection soit atteinte non quand il n'y a plus rien à ajouter, mais quand il n'y a plus rien à retrancher.

lindi
Posts: 44
Joined: 2022-07-12 14:10
Been thanked: 6 times

Re: Boot without extracting initramfs to memory?

#7 Post by lindi »

Head_on_a_Stick wrote: 2022-08-16 05:45 ^ This. Unfortunately there doesn't seem to be "none" (or "cat") listed as a compression option in the man page but you could try it. Or perhaps lindi will point me to the source code :D
Hehe, I guess you can use any binary that is found in PATH that accepts the "-c" parameter. So you could put a wrapper script in /usr/local/bin. However, are you sure that this is actually helpful? You would think that when the data is being decompressed both compressed and decompressed versions exist in the memory at the same time so it actually would be helpful to have the initramfs (cpio archive) be compressed.
Head_on_a_Stick wrote: 2022-08-16 05:45 I just load the modules I know are needed to pivot_root. Here's my Arch configuration:
Speaking of source code references, at least on my system the /init inside the initramfs runs run-init from the klibc-utils package. If you check the source code you can see that it actually does not use pivot_root at all, only vanilla chroot:

https://sources.debian.org/src/klibc/2. ... l=170#L158

User avatar
Head_on_a_Stick
Posts: 13992
Joined: 2014-06-01 17:46
Location: /dev/chair
Has thanked: 51 times
Been thanked: 77 times

Re: Boot without extracting initramfs to memory?

#8 Post by Head_on_a_Stick »

lindi wrote: 2022-08-16 08:04are you sure that this is actually helpful?
I have no idea, I just thought it would be useful for the OP to check.
lindi wrote: 2022-08-16 08:04it actually does not use pivot_root at all, only vanilla chroot
Fascinating, thanks for the info. And welcome to the forums btw. Your expert presence here is very much appreciated.

And for the OP here's a link from one of the Arch developers about minifying the initramfs:

http://blog.falconindy.com/articles/opt ... tcpio.html

The information pertains to Arch but can be easily adapted to Debian.
Il semble que la perfection soit atteinte non quand il n'y a plus rien à ajouter, mais quand il n'y a plus rien à retrancher.

Fierelier
Posts: 11
Joined: 2019-08-27 13:14
Has thanked: 5 times

Re: Boot without extracting initramfs to memory?

#9 Post by Fierelier »

Alright, I did some testing.

/usr/bin/wdvn-cat:

Code: Select all

#!/bin/sh
cat "$2"
This script ignores the -c flag, so cat can be used. I set COMPRESS to wdvn-cat. Unfortunately, it cannot be in /usr/local/bin, since update-initramfs doesn't seem to use $PATH.

I'm also using @lindi's script, on both xz and cat initramfs images, with a few changes. Named /usr/local/bin/update-initramfs, so it is used every time the initramfs is updated:

Code: Select all

#!/bin/bash
set -e
>&2 echo "Compressing modules ..."
for i in $(find /lib/modules -name "*.ko"); do
    if [ "$(file "$i"|grep ELF)" != "" ]; then
        >&2 echo "> $i ..."
        xz -1 $i
        mv $i.xz $i
    fi
done
/usr/sbin/update-initramfs $*
exit $?
In my testing, the cat initramfs booted at 116M minimum and the xz initramfs at 105M. So it seems like @L_V and @lindi were right, and compressing your initramfs image definitely lowers memory usage.

I will experiment around with making a super minimal initramfs, as @Head_on_a_Stick suggested in the next few days. I have a bit of a headache and I'm starting to get a little burnt out from looking at terminals and waiting :wink:

EDIT: When using -9 instead of -1 in the script, and

Code: Select all

DISABLE_FAT=true
DISABLE_FUSE=true
DISABLE_NTFS=true
DISABLE_USB=true
MINIMAL=true
in the live-boot config, it boots on 97M of RAM, with the xz compressed initramfs. As this is will be an initramfs for legacy systems, USB boot is not as important.

Fierelier
Posts: 11
Joined: 2019-08-27 13:14
Has thanked: 5 times

Re: Boot without extracting initramfs to memory?

#10 Post by Fierelier »

Alright, I have decided this is good enough. Thanks everyone!

p.H
Posts: 2676
Joined: 2017-09-17 07:12
Has thanked: 3 times
Been thanked: 61 times

Re: Boot without extracting initramfs to memory?

#11 Post by p.H »

hamishm wrote: 2022-08-16 05:28 If you build the drivers in to the kernel (intead of building them as modules) then you don't need an initramfs at all.
Not quite. You still need an initramfs when the root filesystem is defined by UUID or LABEL, is on software RAID, LVM, LUKS encryption...because all these require userspace programs.

Clarification about the initramfs:
The initramfs image file is a compressed cpio archive.
At boot time, the boot loader loads the kernel and the initramfs images into memory.
The kernel mounts a special tmpfs instance (rootfs) on / and extracts the contents of the initramfs into it (just like tar -x extracts a tarball), and frees the memory which contains the initramfs image.
The kernel executes /init.
In a normal system, /init mounts the real root filesystem on /, deletes everything in the rootfs and executes /sbin/init.

Post Reply