View previous topic :: View next topic |
Author |
Message |
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3345 Location: Rasi, Finland
|
Posted: Thu Feb 04, 2021 11:20 am Post subject: Building my custom initramfs |
|
|
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? _________________ ..: Zucca :..
Gentoo IRC channels reside on Libera.Chat.
--
Quote: | I am NaN! I am a man! |
Last edited by Zucca on Sat Feb 06, 2021 4:01 pm; edited 1 time in total |
|
Back to top |
|
|
Hu Moderator
Joined: 06 Mar 2007 Posts: 21635
|
Posted: Thu Feb 04, 2021 7:26 pm Post subject: |
|
|
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. |
|
Back to top |
|
|
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3345 Location: Rasi, Finland
|
Posted: Thu Feb 04, 2021 8:05 pm Post subject: |
|
|
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). _________________ ..: Zucca :..
Gentoo IRC channels reside on Libera.Chat.
--
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
|
Hu Moderator
Joined: 06 Mar 2007 Posts: 21635
|
Posted: Thu Feb 04, 2021 8:36 pm Post subject: |
|
|
You probably can pass your current kernel, if it supports an initramfs. Such support is optional, and you may have excluded it. |
|
Back to top |
|
|
szatox Advocate
Joined: 27 Aug 2013 Posts: 3137
|
Posted: Thu Feb 04, 2021 11:04 pm Post subject: |
|
|
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. |
|
Back to top |
|
|
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3345 Location: Rasi, Finland
|
Posted: Fri Feb 05, 2021 11:28 am Post subject: |
|
|
After reading some bits and pieces, I came up with this oneliner: Code: | 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... _________________ ..: Zucca :..
Gentoo IRC channels reside on Libera.Chat.
--
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
|
szatox Advocate
Joined: 27 Aug 2013 Posts: 3137
|
Posted: Fri Feb 05, 2021 6:21 pm Post subject: |
|
|
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. |
|
Back to top |
|
|
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3345 Location: Rasi, Finland
|
Posted: Sat Feb 06, 2021 4:13 pm Post subject: |
|
|
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 _________________ ..: Zucca :..
Gentoo IRC channels reside on Libera.Chat.
--
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
|
szatox Advocate
Joined: 27 Aug 2013 Posts: 3137
|
Posted: Sat Feb 06, 2021 4:21 pm Post subject: |
|
|
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. |
|
Back to top |
|
|
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3345 Location: Rasi, Finland
|
Posted: Sat Feb 06, 2021 4:29 pm Post subject: |
|
|
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 :..
Gentoo IRC channels reside on Libera.Chat.
--
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
|
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3345 Location: Rasi, Finland
|
Posted: Tue Feb 09, 2021 8:55 am Post subject: I can only run busybox providede commands |
|
|
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?
Code: | # 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 |
_________________ ..: Zucca :..
Gentoo IRC channels reside on Libera.Chat.
--
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
|
GDH-gentoo Veteran
Joined: 20 Jul 2019 Posts: 1530 Location: South America
|
Posted: Tue Feb 09, 2021 2:00 pm Post subject: Re: I can only run busybox providede commands |
|
|
Zucca wrote: | However commands outside busybox don't work.
What is going on?
Code: | # chroot initramfs busybox sh
...
/ # /bin/nano
sh: /bin/nano: not found |
|
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. |
|
Back to top |
|
|
NeddySeagoon Administrator
Joined: 05 Jul 2003 Posts: 54237 Location: 56N 3W
|
Posted: Tue Feb 09, 2021 2:19 pm Post subject: |
|
|
Zucca,
You need all the bts in the right places too.
Code: | $ 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.
Code: | /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? _________________ Regards,
NeddySeagoon
Computer users fall into two groups:-
those that do backups
those that have never had a hard drive fail. |
|
Back to top |
|
|
Goverp Advocate
Joined: 07 Mar 2007 Posts: 2008
|
|
Back to top |
|
|
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3345 Location: Rasi, Finland
|
Posted: Tue Feb 09, 2021 4:30 pm Post subject: |
|
|
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.
Code: | #!/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 :..
Gentoo IRC channels reside on Libera.Chat.
--
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
|
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3345 Location: Rasi, Finland
|
Posted: Tue Feb 09, 2021 4:39 pm Post subject: |
|
|
NeddySeagoon wrote: | The kernel has a script to make the initrd.
Code: | /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? | 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 :..
Gentoo IRC channels reside on Libera.Chat.
--
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
|
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3345 Location: Rasi, Finland
|
Posted: Wed Feb 10, 2021 7:40 am Post subject: |
|
|
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. _________________ ..: Zucca :..
Gentoo IRC channels reside on Libera.Chat.
--
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
|
Goverp Advocate
Joined: 07 Mar 2007 Posts: 2008
|
Posted: Sun Mar 14, 2021 4:02 pm Post subject: |
|
|
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. _________________ Greybeard |
|
Back to top |
|
|
Buffoon Veteran
Joined: 17 Jun 2015 Posts: 1369 Location: EU or US
|
Posted: Sun Mar 14, 2021 4:05 pm Post subject: |
|
|
Don't forget Tetris, guys. _________________ Life is a tragedy for those who feel and a comedy for those who think. |
|
Back to top |
|
|
halcon l33t
Joined: 15 Dec 2019 Posts: 629
|
Posted: Fri Mar 26, 2021 8:02 pm Post subject: |
|
|
Thank you for that script. It is useful and beatiful
I have a question:
Code: | case "$library" in
*=\>*)
# ...
*/*)
# ...
linux-*)
# ... |
And I see, for example, such output:
Code: | 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:
Code: | __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:
Code: | __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}" ) |
_________________ A wife asks her husband, a programmer:
- Could you please go shopping for me and buy one carton of milk, and if they have eggs, get 6?
He comes back with 6 cartons of milk.
- Why did you buy 6 cartons of milk?
- They had eggs. |
|
Back to top |
|
|
Goverp Advocate
Joined: 07 Mar 2007 Posts: 2008
|
Posted: Sat Mar 27, 2021 10:18 am Post subject: |
|
|
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 _________________ Greybeard |
|
Back to top |
|
|
halcon l33t
Joined: 15 Dec 2019 Posts: 629
|
Posted: Sat Mar 27, 2021 2:03 pm Post subject: |
|
|
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. _________________ A wife asks her husband, a programmer:
- Could you please go shopping for me and buy one carton of milk, and if they have eggs, get 6?
He comes back with 6 cartons of milk.
- Why did you buy 6 cartons of milk?
- They had eggs. |
|
Back to top |
|
|
Goverp Advocate
Joined: 07 Mar 2007 Posts: 2008
|
Posted: Sun Mar 28, 2021 11:20 am Post subject: |
|
|
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:
Code: | # 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) _________________ Greybeard |
|
Back to top |
|
|
Zucca Moderator
Joined: 14 Jun 2007 Posts: 3345 Location: Rasi, Finland
|
Posted: Sun Mar 28, 2021 3:53 pm Post subject: |
|
|
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. _________________ ..: Zucca :..
Gentoo IRC channels reside on Libera.Chat.
--
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
|
NeddySeagoon Administrator
Joined: 05 Jul 2003 Posts: 54237 Location: 56N 3W
|
Posted: Sun Mar 28, 2021 3:57 pm Post subject: |
|
|
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. _________________ Regards,
NeddySeagoon
Computer users fall into two groups:-
those that do backups
those that have never had a hard drive fail. |
|
Back to top |
|
|
|