I'm in an embedded linux environment with busybox. I've read through several posts trying to learn how to use switch_root. I tried this:
exec switch_root -c /dev/console /mnt/newroot /bin/busybox init
The switch_root
help prints and I am presented with a new login:
[root@buildroot ~]# exec switch_root -c /dev/console /mnt/newroot /bin/busybox init
BusyBox v1.21.0 (2015-04-24 18:14:40 MDT) multi-call binary.
busybox init
Usage: switch_root [-c /dev/console] NEW_ROOT NEW_INIT [ARGS]root /bin/busybox in
Free initramfs and switch to another root fs:
chroot to NEW_ROOT, delete all in /, move NEW_ROOT to /,
execute NEW_INIT. PID must be 1. NEW_ROOT must be a mountpoint.
-c DEV Reopen stdio to DEV after switch
Welcome to Buildroot
buildroot login:
When I login, newroot has not been loaded, old one is still there. Is this because I am running this command directly from command line and not from some kind of init script?
I read in this article and found they perform other steps before running switch_root
:
mount --move /sys /newroot/sys
mount --move /proc /newroot/proc
mount --move /dev /newroot/dev
First off, this confuses me. Why would I want to run these commands before running switch_root
? Does switch_root
not do this for me?
Anyways, I went ahead and tried running them first and then running my switch_root
command. However, this hoses things up entirely:
[root@buildroot /]# switch_root -c /dev/console /mnt/newroot /bin/busybox init
BusyBox v1.21.0 (2015-04-24 18:14:40 MDT) multi-call binary.
Usage: switch_root [-c /dev/console] NEW_ROOT NEW_INIT [ARGS]
Free initramfs and switch to another root fs:
chroot to NEW_ROOT, delete all in /, move NEW_ROOT to /,
execute NEW_INIT. PID must be 1. NEW_ROOT must be a mountpoint.
-c DEV Reopen stdio to DEV after switch
can't open /dev/ttyS0: No such file or directoryole /mnt/newroot /bin/busybox init
can't open /dev/ttyS0: No such file or directory
can't open /dev/ttyS0: No such file or directory
can't open /dev/ttyS0: No such file or directory
can't open /dev/ttyS0: No such file or directory
can't open /dev/ttyS0: No such file or directory
can't open /dev/ttyS0: No such file or directory
... message continues to repeat ...
So it looks like because I've moved the mount for dev that when my init runs and trys to put the getty on my serial port it can't find it? Confusion........
Am I missing something fundamental about switch_root
here? Or some simply command line modifications required?
First, as its helptext says switch_root
has to be executed as PID 1.
Therefore it needs to be called by an initscript using exec
.
Second, moving the tmpfilesystems manually is (as you saw) a bad idea.
The error you get is because your console (/dev/ttyS0
) was moved away with your mount --move
call.
switch_root
will delete those mounts automatically.
Therefore your second init (which is called by switch_root
) needs to mount them again.
Third, here's a short version of the init script I'm using within my initramfs which should help you:
#!/bin/sh
ROOT="/mnt/.root"
ROOT_DEV="/dev/sdb2"
echo "init from initramfs"
# mount temporary filesystems
mount -n -t devtmpfs devtmpfs /dev
mount -n -t proc proc /proc
mount -n -t sysfs sysfs /sys
mount -n -t tmpfs tmpfs /run
# mount new root
[ -d ${ROOT} ] || mkdir -p ${ROOT}
mount ${ROOT_DEV} ${ROOT}
# switch to new rootfs and exec init
cd ${ROOT}
exec switch_root . "/sbin/init" "$@"
Hope this helps.