# Building my custom initramfs

## Zucca

I'm planning to write a small script for creation of my custom initramfs.

But what's the best way to pre-test it? In a chroot?

----------

## Hu

What kind of testing do you want?  If you have ready access to run a virtual machine, that might give you a more faithful test environment.  This may not be appropriate if you need to test how the initramfs handles devices that are difficult to expose to the VM.

----------

## Zucca

I'd need to test how the initramfs initscript (linuxrc) does work and if all the dependencies are met.

I understand that the kernel module loading part needs to be done in virtual environment, but all the rest should work in chroot... I think.

But could I load the current running kernel in qemu and pass my newly creted initramfs to it? I've never done so. But I think from technical stand point it should be possible. I'm just not 100% sure.

I use btrfs filesystems on all my setups so I only need btrfs related things in initramfs to mount real root.

My hardware is pretty basic consumer hardware so no exotic parts (except maybe for the InfiniBnad, but that's not needed in initramfs phase anyway).

----------

## Hu

You probably can pass your current kernel, if it supports an initramfs.  Such support is optional, and you may have excluded it.

----------

## szatox

Zucca, the thing that always gave me the most trouble was getting it to actually start init, so that's one thing. You can't really test it in any other way than trying to boot it.

Once I had this done, I came up with a little cheat that let me avoid rebuilding the archive over and over and over and over again: I just put a stub init script in the initramfs, which would download the actual init script from tftp.

At this point I could update the script and just reboot the VM

 *Quote:*   

> But could I load the current running kernel in qemu and pass my newly creted initramfs to it? I've never done so

 qemu supports direct kernel boot option.

This mode does require a disk image it can prepend the kernel and initramfs to, but the content of that disk is irrelevant. I suppose you could even get away with /dev/null.

Make sure you have the necessary hardware drives builtin and not compiled as modules. It's not strictly required, but it does make life much easier.

----------

## Zucca

After reading some bits and pieces, I came up with this oneliner:

```
xargs -ra /etc/portage/sets/initramfs-internal qlist | egrep '/s?bin/' | xargs lddtree --copy-to-tree /usr/src/initramfs/
```

The portage set @initramfs-internal contains all the packages I think I need inside initramfs.

Then the hardest part of creating the linuxrc/init script...

----------

## szatox

Busybox can act as the init (pid 1).

If you let it be the master, it will start /etc/init.d/rcS as the "helper" program, so this is where there interesting stuf happens. Mount /proc and /dev and figure the rest out from interactive shell.

Talking of which, busybox init will start a bunch  of agettys according to /etc/inittab, which is more convenient than making your script PID 1 and dropping to shell from there.

----------

## Zucca

Since this topic somewhat derailed I changed its title.

I'm trying now to test extract the cpio archive... I used --no-absolute-filenames when creating the archive to be able to extract the files into a directory rather than to the root of my filesystem.

I get errors that don't make any sense like cpio: libncursesw.so.6.2: Cannot symlink to ‘lib64/libncursesw.so.6’: No such file or directory

If any of you know what causes this, please explain. :P Meanwhile I'll try to rtfm and solve this...

EDIT: If I pass --dereference upon creating the archive I get: cpio: lib64/libblkid.so.1: Cannot open: No such file or directory

----------

## szatox

I don't think --no-absolute-filenames is necessary. never used it myself, it was just 

find . | cpio -o -H newc | gzip > initramfs.gz (or bzip2. Couldn't find the correct params to xz, kernel's builtin decompressor is somewhat limited)

and 

gzip -cd initramfs.gz | cpio -i

Are you sure you actually put the libraries into your cpio and not just the symlinks?

Are those messages errors or warnings? Links should be created even if target files didn't exist.

----------

## Zucca

Yup. While creating --no-absolute-filenames is not needed.

But while extracting --make-directories with --directory solves the problem.

I can now start to perform some test inside chroot. :)

----------

## Zucca

Well... I'm testing my initramfs now by extracting the archive and chrooting into it.

However commands outside busybox don't work.

What is going on?

```
# chroot initramfs busybox sh

/ # ls /bin/

[              date           gunzip         md5sum         pkill          showkey        umount

[[             dd             gzip           mesg           pmap           shred          uname

ar             deallocvt      hd             microcom       printenv       shuf           uncompress

arch           df             head           minips         printf         sleep          unexpand

ash            diff           hexdump        mkdir          ps             softlimit      uniq

awk            dirname        hexedit        mkfifo         pscan          sort           unit

base64         dmesg          hostname       mknod          pstree         split          unix2dos

basename       dnsdomainname  id             mkpasswd       pwd            ssl_client     unlink

bb             dos2unix       install        mktemp         pwdx           stat           unlzma

bbconfig       du             ionice         more           readlink       strings        unlzop

bbsh           dumpkmap       iostat         mount          realpath       stty           unshare

bc             dumpleases     ipcrm          mountpoint     renice         su             unxz

blkdiscard     echo           ipcs           mpstat         reset          sum            unzip

bunzip2        ed             kbd_mode       mt             resize         svc            uptime

busybox        egrep          kill           mv             resume         svok           users

bzcat          eject          killall        nano           rev            sync           usleep

bzip2          env            last           nc             rm             tac            vi

cal            envdir         less           netcat         rmdir          tail           vlock

cat            envuidgid      link           netstat        rnano          tar            volname

chattr         expand         linux32        nice           rx             tee            w

chgrp          expr           linux64        nl             script         telnet         wall

chmod          factor         ln             nmeter         scriptreplay   test           watch

chown          fallocate      login          nohup          sed            tftp           wc

chpst          false          lpq            nproc          seq            time           wget

chrt           fatattr        lpr            nsenter        setarch        timeout        which

chvt           fdflush        ls             nslookup       setfattr       top            who

cksum          fgconsole      lsattr         nuke           setkeycodes    touch          whoami

clear          fgrep          lsof           openvt         setpriv        tr             whois

cmp            find           lspci          passwd         setserial      traceroute     xargs

comm           flock          lsscsi         paste          setsid         traceroute6    xxd

conspy         free           lsusb          patch          setuidgid      true           xz

cp             fsync          lzcat          pgrep          sh             truncate       xzcat

cpio           fuser          lzma           pidof          sha1sum        ts             yes

cryptpw        getopt         lzop           ping           sha256sum      tty            zcat

cttyhack       grep           lzopcat        ping6          sha3sum        ttysize

cut            groups         man            pipe_progress  sha512sum      udhcpc6

/ # /bin/nano

sh: /bin/nano: not found
```

----------

## GDH-gentoo

 *Zucca wrote:*   

> However commands outside busybox don't work.
> 
> What is going on?
> 
> ```
> ...

 

Were they linked to static libraries (including the libc)? If no, are the required shared libraries and dynamic linker present in the initramfs? If you are not sure, use the file command on the initramfs' nano binary outside the chroot.

----------

## NeddySeagoon

Zucca,

You need all the bts in the right places too.

```
$ ldd /bin/bash 

   linux-vdso.so.1 (0x00007ffc1c7f7000)

   libreadline.so.8 => /lib64/libreadline.so.8 (0x00007fadcce22000)

   libc.so.6 => /lib64/libc.so.6 (0x00007fadccc61000)

   libtinfow.so.6 => /lib64/libtinfow.so.6 (0x00007fadccc23000)

   /lib64/ld-linux-x86-64.so.2 (0x00007fadccf80000)

```

The kernel has a script to make the initrd.

```
/usr/src/linux usr/gen_init_cpio /root/initrd/initramfs_list > /boot/initramfs_static
```

where  /root/initrd/initramfs_list describes everfthing that is to go into the initramfs.

I've always used files from the live filesystem but that's not such a good idea as things change. I won't do that again as it wakes it impossible to tweak the init script is years to come.

Did you bind mount all the pseudo filesystems into the chroot?

----------

## Goverp

Or you can use my script to generate the initramfs_list

----------

## Zucca

Thanks guys. :)

While you were commenting I realized that my problem was with symlinks.

Now it works.

I made preliminary script for building my own initramfs.

```
#!/usr/bin/bash

packagelist="/etc/portage/sets/initramfs-internal"

extrafilesdir="/etc/initramfs"

cpiocmd="cpio --create"

{

        xargs -ra "$packagelist" qlist | egrep '/s?bin/' | xargs lddtree --list 2> /dev/null | while read f

        do

                while [ -L "$f" ]

                # We have a symlink to handle

                do

                        echo "$f"

                        l="$(readlink "$f")"

                        if [ "${l:0:1}" != "/" ]

                        then

                                # Link target is a relative path.

                                # Get the absolute path so that cpio can store it.

                                f="$(realpath --no-symlinks "$(dirname "$f")/$l")"

                        fi

                done

                echo "$f"

        done | awk '!seen[$1]++' | tee /tmp/initcpio.lst | $cpiocmd

        find "$extrafilesdir" -depth -printf '%P\n' | $cpiocmd --directory "$extrafilesdir"

} | pigz --stdout -9 > /tmp/initramfs.cpio.gz
```

Now I can customize 'init' script inside the initramfs by editing /etc/initrtamfs/init.

I may add busybox back eventually, but for now this is the quick and dirty way.

----------

## Zucca

 *NeddySeagoon wrote:*   

> The kernel has a script to make the initrd.
> 
> ```
> /usr/src/linux usr/gen_init_cpio /root/initrd/initramfs_list > /boot/initramfs_static
> ```
> ...

 That script seems to be absent on sys-kernel/gentoo-kernel. :\

I tried to search it before.

goverp, your script look really comprehensive, but still gives user many choices. Nice.

GDH-gentoo, dynamically linked. My script pulls the files from the running system.

Although I thought of running emerge to compile static binaries into the root of initramfs, but since I have them already and it was only a matter of gathering all the libraries... I went that way.

----------

## Zucca

I almost completely rewrote my script. There was (an obvious) problem with including files from s?bin -directories when the file isn't a binary recognized by ldd (a shell script).

I managed to keep the code fairly small, which is my target.

My second targets are to make it "dumb" (more UNIX like). It will have three goals:read a list of files from the current running system, process each file using ldd and then add the required libraries to the list too

copy each file as-is into cpio archive

do the same for "extra files" (this includes module and firmare files)

This way one could leave the first list completely empty, but have all the required files in the extra files directory. I'm thinking emerging the required packages and using the "extra files" directory as root directory. I'll look into that maybe when I'm finished with this.

----------

## Goverp

If anyone's interested, I've updated my script to generate the initramfs_list.

It's a bit cleaner, some bugs in path handling are fixed, the output is in a more sensible order, and you can now tell it to include /etc/fstab and mountpoints for selected filesystem types (e.g. "ext4,vfat"), which is useful if you want to be able to "mount -a" or just issue "mount <mountpoint>" in an init script.  Since in my world the initramfs is built at kernel make time, it automatically gets an up-to-date fstab.

----------

## Buffoon

Don't forget Tetris, guys.

----------

## halcon

 *Goverp wrote:*   

> If anyone's interested, I've updated my script to generate the initramfs_list.

 

Thank you for that script. It is useful and beatiful  :Smile: 

I have a question:

```
      case "$library" in

      *=\>*)

         # ...

      */*)

         # ...

      linux-*)

         # ...
```

And I see, for example, such output:

```
ldd /usr/sbin/haveged 2>/dev/null

        linux-vdso.so.1 (0x00007ffcc6e58000)

        libhavege.so.2 => /usr/lib64/libhavege.so.2 (0x00007fd1a8e31000)

        libc.so.6 => /lib64/libc.so.6 (0x00007fd1a8c71000)

        /lib64/ld-linux-x86-64.so.2 (0x00007fd1a8e74000)
```

As far as I understand, for the second case, there can be only [[:space:]] before /. Which bash pattern is corresponding to that rule? Something like [[:space:]]+/* ...

EDIT

Also... My script version has a separate ldd call before the loop, so:

```
      __ldd_result="$(ldd "${__binary}" 2>/dev/null)" || true

      while read -r __line ; do

         case "${__line}" in

         *=\>*)

            __linker_dep="${__line#*=> }"

            __linker_dep="${__linker_dep% (*}"

            # ...

            ;;

         */*)

            __linker_dep="${__line% (*}"

            # ...

            ;;

         *linux-*)

            # Kernel-provided - nothing needed

            ;;

         *)

            exit_err_1 "Unknown line pattern in __ldd_result (${__line})"

            ;;

         esac

      done < <( echo "${__ldd_result}" )
```

^^ And I had to add * before linux-*, otherwise lines like that with linux-vdso.so.1 were caught as an error (Unknown line pattern)

EDIT

Finally, I've chosen this:

```
      __ldd_result="$(ldd "${__binary}" 2>/dev/null)" || true

      while read -r __line ; do

         __clean="$(echo ${__line} | sed -r 's/^[[:space:]]*//')"

         if [[ "${__clean}" =~ =\> ]]; then

            __linker_dep="${__clean#*=> }"

            __linker_dep="${__linker_dep% (*}"

            # ...

         elif [[ "${__clean}" =~ ^/ ]]; then

            __linker_dep="${__clean% (*}"

            # ...

         elif [[ ! "${__clean}" =~ ^linux- ]]; then

            exit_err_1 "Unknown line pattern in __ldd_result (${__clean})"

         fi

      done < <( echo "${__ldd_result}" )
```

----------

## Goverp

 *halcon wrote:*   

> ...
> 
> As far as I understand, for the second case, there can be only [[:space:]] before /. Which bash pattern is corresponding to that rule? Something like [[:space:]]+/* ...
> 
> 

 

I was coding for dash, in which case the possibilities for patterns in the case statement (and elsewhere), are much restricted.  A character class such as [0-9] matches only one character; there are no regex things like [0-9]+, that merely matches [0-9][+] in regex terms.  And there's no [:space:] category, you'd have to write [ \t] (except \t isn't allowed there) and so forth.

So the one that matches is the rather too powerful */*).

Dash coding is AFAIK effectively upwards-compatible with Bash

----------

## halcon

 *Goverp wrote:*   

> I was coding for dash, in which case the possibilities for patterns in the case statement (and elsewhere), are much restricted.  A character class such as [0-9] matches only one character; there are no regex things like [0-9]+, that merely matches [0-9][+] in regex terms.

 

I've found that there is nearly the same picture in bash - case statement doesn't support regexes, but only globbing. This is why I've chosen to use if statements.

----------

## Goverp

Perhaps it should be looking for "*.so.[0-9]* ".  I'll give it a try.

EDIT no, my code, at least, should parse the library stuff a bit smarter:

```
# Changed to parse the ldd lines at read time rather than messy parse later

                ldd "$path" 2>/dev/null | while read -r soname arrow file _

                do

                        library="${soname%%.so.*}"

                        if      [ "$library" = "linux-vdso" ]

                        then    continue        # Nothing to do, it's part of the kernel

                        elif    [ "$arrow" = "=>" ] && [ -f "$file" ]

                        then    listFile "$file"

                        elif    [ -f "$soname" ]

                        then    listFile "$soname"

                        else    error "Unexpected ldd $path output $soname $arrow $file"

                        fi

                done
```

I'll put the changes into my version in the wiki (and while I'm there, remove the ill-considered /etc/fstab thing)

----------

## Zucca

I've managed to create quite small busybox -based initramfs image, which is just a single cpio file (instead of many).

Now I'd need to create some sort of function for resuming from hibernate. You guys have any samples to show?

Something strange is still happening with dynamic binaries... When trying to run one I only get sh: <binary name> not found -type of messages. All the libraries are there so I don't quite know what's going on. I need to continue tests inside a chroot.

----------

## NeddySeagoon

Zucca,

The binaries are not in the right path?

The linker can't find them?

The permissions are not correct. I think only x matters as there is only a root user in the initrd.

----------

## Zucca

```
# chroot initrd/ /bin/busybox sh

/ # bash

sh: bash: not found

/ # /bin/bash

sh: /bin/bash: not found

/ # stat /bin/bas

basename  bash

/ # stat /bin/bash

  File: /bin/bash

  Size: 827992          Blocks: 1624       IO Block: 4096   regular file

Device: 28h/40d Inode: 97706       Links: 1

Access: (0755/-rwxr-xr-x)  Uid: (    0/ UNKNOWN)   Gid: (    0/ UNKNOWN)

Access: 2021-03-28 16:52:00.385988414 +0000

Modify: 2021-03-28 16:50:11.651991816 +0000

Change: 2021-03-28 16:50:11.651991816 +0000
```

So now I can "only" use busybox internals. It seems to be a linking problem, since busybox is build with USE="static".

----------

## Hu

That error can happen if the dynamic loader is not found as expected.  When you copied in the shared libraries (like libc), did you also copy in the dynamic loader?  What is the output of readelf -l /bin/bash?  Is the program interpreter that is shown in that output available at the shown path, in the initramfs?  The dynamic loader will be mentioned in ldd output, but unusually, will not have an arrow in its line.

```
$ ldd /bin/bash

        linux-vdso.so.1 (0x00007fff5e1c7000)

        libreadline.so.8 => /lib64/libreadline.so.8 (0x00007e5a85378000)

        libc.so.6 => /lib64/libc.so.6 (0x00007e5a851bc000)

        libtinfo.so.6 => /lib64/libtinfo.so.6 (0x00007e5a8517f000)

        /lib64/ld-linux-x86-64.so.2 (0x00007e5a854bf000)
```

As for resume, that depends on how you are hibernating.  Are you using the in-kernel hibernate support?  Do you hibernate to an unencrypted swap partition, or to something more complicated?

----------

## Zucca

 *Hu wrote:*   

> That error can happen if the dynamic loader is not found as expected.

 Solved! :) Thanks.

I had a bug in my script which did leave the loader out.

As for the hibernate method, I use the default one that is provided by systemd+gentoo-kernel+dracut... on this particular laptop.

I need to rtfm about those hibernation methods. Then amybe choose what's better for my setup.

I have not even set hibernation support on my OpenRC based desktop, but I intend to do as I get this working.

----------

## Goverp

 *Zucca wrote:*   

> ...Something strange is still happening with dynamic binaries... When trying to run one I only get sh: <binary name> not found -type of messages. All the libraries are there so I don't quite know what's going on. I need to continue tests inside a chroot.

 

busybox --install ?  or $PATH wrong?

----------

## Hu

Although it may require some minor kernel configuration changes to enable, I find it very convenient to use qemu to test a new initramfs, since I can boot a throw-away VM from the test kernel + test initramfs, and if I don't like how they work, just exit the VM, rebuild them on the host, and start another one.  Once I like how they work, then I commit to rebooting the real machine with that setup.

----------

## Zucca

 *Goverp wrote:*   

> busybox --install ?  or $PATH wrong?

 Nope. busybox was the one which worked. ;)

Anyway. I found something quite valuable (for me at least) when creating sh scripts (for busybox): https://www.etalabs.net/sh_tricks.html

----------

## Goverp

Ooh, thanks for the link to the tricks.  I'd found a few the hard way.

----------

## Zucca

Found another: https://github.com/dylanaraps/pure-sh-bible

----------

## Zucca

Well I hit the wall.

I wanted to test embedding some manual pages to the initramfs.

busybox's "man" alone isn't enough. So I tracked what is needed, but then... /usr/bin/groff. Looks like it's c++ binary. Needs c++ standard library. My script does include it automatically (along with symlinks).

But I still get 

```
# groff --help

groff: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory
```

Outside of the chroot I can double-check 

```
# ldd /usr/bin/groff

        linux-vdso.so.1 (0x00007ffc4bff3000)

        libstdc++.so.6 => /usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/libstdc++.so.6 (0x00007fa588497000)

        libm.so.6 => /lib64/libm.so.6 (0x00007fa588354000)

        libgcc_s.so.1 => /usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/libgcc_s.so.1 (0x00007fa58833a000)

        libc.so.6 => /lib64/libc.so.6 (0x00007fa58817f000)

        /lib64/ld-linux-x86-64.so.2 (0x00007fa5886a9000)
```

 that I do have all the required files.

I also tried to look for clues from then environment, but no. I'm against a wall in a dead end. Help?

And, yes, groff works outside the chroot.

Side question: Why on earth does reading a simple compressed man page need so complex system?

----------

## Goverp

No help, but I also get problems trying to run cgdisk from busybox because it can't open libstdc++.so.6

I'll be glad if someone knows why

----------

## GDH-gentoo

 *Zucca wrote:*   

> But I still get 
> 
> ```
> # groff --help
> 
> ...

 Where is libstdc++ installed in the initramfs? Does the initramfs have /etc/ld.so.conf?

 *Zucca wrote:*   

> Side question: Why on earth does reading a simple compressed man page need so complex system?

 Parsing the roff format, I guess.

----------

## Zucca

 *GDH-gentoo wrote:*   

> Where is libstdc++ installed in the initramfs?

 In the same directory path as in the installed system.

 *GDH-gentoo wrote:*   

> Does the initramfs have /etc/ld.so.conf?

 ... nope. :| So I guess C++ programs need a "pointing hand"?

 *GDH-gentoo wrote:*   

>  *Zucca wrote:*   Side question: Why on earth does reading a simple compressed man page need so complex system? Parsing the roff format, I guess.

 I tried to search more sane solution. I only found man-lite from sourceforge, and it does not have any files. Also the developer planned to write it in lua...

----------

## GDH-gentoo

 *Zucca wrote:*   

>  *GDH-gentoo wrote:*   Where is libstdc++ installed in the initramfs? In the same directory path as in the installed system.
> 
>  *GDH-gentoo wrote:*   Does the initramfs have /etc/ld.so.conf? ... nope.  So I guess C++ programs need a "pointing hand"?

 

If you replicate Gentoo's setup in the initramfs, I think you need at least an /etc/ld.so.conf naming the directory that contains libstdc++ (see man ldconfig). Gentoo puts it in a place that is not searched by default by the dynamic linker. On purpose, to support the slotting of sys-devel/gcc and eselect gcc. The initramfs does not need that mechanism, so you could just stick libstdc++ in /lib64.

You are using a script to create the initramfs, though, so it is probably easier to include a suitable ld.so.conf rather than making libstdc++ a special case.

EDIT to add: It might be worse, I'm not sure now if the dynamic linker just uses /etc/ld.so.cache (generated by ldconfig), without parsing /etc/ld.so.conf. Which would make sense for efficiency reasons.

EDIT #2: ldconfig -r <directory of the initramfs> will create the initramfs' /etc/ld.so.cache from <directory of the initramfs>/etc/ld.so.conf.

----------

## Zucca

Thanks! I'll bookmark your answer. I decided to give up on including man pages as reading them needs too much crud. I'd better off to write a parser myself (probably in busybox awk)...

Actually I was surprised how complex the system is. When it only would needFind the man page file under /usr/man/man[1-9]Autodetect if it's compressed and uncompress it if needed.Parse the actual manpageOptionally send the formatted page to a pager.Oh well...

I made a rather hacky initramfs for my laptop. I managed to get its size to 1.44MiB compressed (Still quite huge. One whole floppy! :P).

Then if emergency shell is activated, then mount a certain partition which contains another cpio. Extracting it will give a lot of other tools which are not normally needed when booting. ;) This way a normal boot will still be fast.

If I wanted to make this even more realiable, then I'd need to place the secondary cpio at certain physical location on the hard drive. Then by using, for example, dd fetch the cpio data without mounting the actual partition. But for now this fits my needs pretty well.

One problem I have with the emergency shell, is that backspace works but doesn't move the cursor and erase the last character.

It's usually been an incorrect TERM, which I have set as "linux" since all this happens on virtual console.

I start emergency bash by executing

```
setsid cttyhack /bin/bash -l
```

 busybox sh instead works as expected.

I'm also tempted to compile busybox as static binary but with musl or ulibc... I know it's probably not worth it, but this is Gentoo. ;)

----------

## GDH-gentoo

 *Zucca wrote:*   

> I managed to get its size to 1.44MiB compressed (Still quite huge. One whole floppy! ).
> 
> [...]
> 
> I'm also tempted to compile busybox as static binary but with musl or ulibc... I know it's probably not worth it, but this is Gentoo. 

 

My setup doesn't need an initramfs, but I did that (manually) as a learning experience, and in case one day I do need one. Except that I used dynamic linking; I wanted to use that initramfs as a base for adding more programs eventually, which would then share the libc. The size goes down to 516KiB (compressed with gzip)  :Smile: 

```
$ du -h /boot/initramfs-musl.cpio.gz

516K   /boot/initramfs-musl.cpio.gz
```

Inside the initramfs (/mnt would be the mountpoint for the real root filesystem):

```
# ls -lh / /bin /lib

/:

drwxr-xr-x    2 0        0              0 Apr  4 14:58 bin

drwxr-xr-x    8 0        0           2.3K Apr  4 15:18 dev

-rwxr-xr-x    1 0        0            339 Apr  4 14:57 init

drwxr-xr-x    2 0        0              0 Apr  4 14:58 lib

drwxr-xr-x   21 0        0           4.0K Mar 28 22:58 mnt

dr-xr-xr-x   98 0        0              0 Apr  4 15:18 proc

drwx------    2 0        0              0 Mar 21 00:10 root

dr-xr-xr-x   12 0        0              0 Apr  4 15:18 sys

/bin:

-rwxr-xr-x    1 0        0         223.1K Mar 28 18:58 busybox

lrwxrwxrwx    1 0        0              7 Apr  4 14:58 sh -> busybox

/lib:

lrwxrwxrwx    1 0        0              7 Apr  4 14:58 ld-musl-x86_64.so.1 -> libc.so

-rwxr-xr-x    1 0        0         694.4K Mar 27 19:57 libc.so
```

BusyBox was configured with only a reduced number of applets.

```
# busybox --help

BusyBox v1.32.1 (2021-03-27 17:35:05 -03) multi-call binary.

BusyBox is copyrighted by many authors between 1998-2015.

Licensed under GPLv2. See source distribution for detailed

copyright notices.

Usage: busybox [function [arguments]...]

   or: busybox --list[-full]

   or: busybox --install [-s] [DIR]

   or: function [arguments]...

   BusyBox is a multi-call binary that combines many common Unix

   utilities into a single executable.  The shell in this build

   is configured to run built-in utilities without $PATH search.

   You don't need to install a link to busybox for each utility.

   To run external program, use full path (/sbin/ip instead of ip).

Currently defined functions:

   ash, bb, bbsh, blkid, busybox, cat, chroot, cp, df, dmesg, du, env, false, fuser, grep,

   kill, ln, ls, lsof, mkdir, mkfifo, mknod, more, mount, mv, ps, readahead, rm, rmdir, sh,

   sleep, switch_root, true, umount
```

----------

## Zucca

 *GDH-gentoo wrote:*   

> I wanted to use that initramfs as a base for adding more programs eventually, which would then share the libc. The size goes down to 516KiB (compressed with gzip) 
> 
> ```
> $ du -h /boot/initramfs-musl.cpio.gz
> 
> ...

 Nice.  :Shocked: 

I'll get into that after I have finished all the other initramfs stuff going on.

Next I'll dig deep into resuming from hibernate...

I've seen some examples of how it's done. But I need to test that out on a real hardware, my laptop.

The example on the wiki looks odd. It first mounts root (ro at least) and then resumes from hibernate. I would do that in reverse order.

My two other machines don't have real swap at all. Zram devices only. The other one would benefit from hibernating, the other maybe don't. I need to see if it's possible to have swap on those.

----------

## Hu

 *Zucca wrote:*   

> The example on the wiki looks odd. It first mounts root (ro at least) and then resumes from hibernate. I would do that in reverse order.

 You must be one of those people who doesn't like random filesystem corruption.  :Wink:   Yes, the Wiki is exactly wrong on this point.  As you say, and as said in the kernel documentation, when resuming from hibernation, the system must not mount, even as read-only, any filesystems that the hibernated image had mounted.  Such mounts may, or may not, write to the underlying filesystem, such as by replaying the journal.  Any such writes place the resumed system in an undefined state.

----------

## Zucca

I edited the script on the wiki.

I moved the resuming part. It's now before rootfs mounting.

I felt this was important to do asap.

I may later edit it with comments mentioning about the importance of order of execution.

----------

## Zucca

Now that I have a pretty well working system using a custom initramfs, I'll share what I've done.

The tool I use to create the cpio: https://github.com/Zuccace/mkirfs

An init script which boots my laptop: https://wiki.gentoo.org/wiki/User:Zucca/initramfs/init_scripts

The init script expects that user specifies emergency partition (on kernel command line) where an extra cpio resides. I'll change that to optional next time I edit it.

----------

