学习Linux-01启动
ref: https://jyywiki.cn/OS/2024/lect18.md
src: wget -r -np -nH –cut-dirs=2 -R “index.html*” “https://jyywiki.cn/os-demos/virtualization/linux/"
1. 折腾的原因总结
- linux 启动过程中报错不是那么准确,例如:执行的二进制(init)缺少了 .so,会报错 exec init failed: no such file.
- 例如 virtio_blk 之类的驱动,需要自己在 initramfs 中自己加载。
2. 使用的环境
kali 2024.4
- kernel 6.11.2-amd64
- initrd.img 6.11.2-amd64 (被我替换了静态编译的 busybox)
不能使用 cpio 等命令解压,看起来是多个文件直接拼接起来的一个文件(使用 binwalk 能够看到),直接使用 cpio 会只能解出来里面的第一个文件; 如果需要提取完整的内容,需要使用 unmkinitramfsqemu-system-x86_64 10.0.2
3. Makefile 和 init 脚本
- Makefile (unmkinitramfs 的部分没有写在里面,手动执行的)
# Requires statically linked busybox in $PATH
INIT := /init
IMG := build/disk.img
MOUNT := $(shell mktemp -d)
K := $(shell uname -r)
all: initramfs fsroot
initramfs:
# Copy kernel and busybox from the host system
@mkdir -p build/initramfs/bin
sudo bash -c "cp /boot/vmlinuz-$K build/vmlinuz && chmod 666 build/vmlinuz"
cp init build/initramfs/
chmod 777 build/initramfs/init
# Pack build/initramfs as gzipped cpio archives
cd build/initramfs && find . | cpio -H newc -o | gzip > ../initramfs.cpio.gz
fsroot:
mkdir -p fsroot/lib/modules
chmod 777 fsroot/etc/init.d/rcS
cp $$(find /lib/modules/$K/ -name e1000.ko.xz) fsroot/lib/modules/
dd if=/dev/zero of=$(IMG) bs=1M count=64
mkfs.ext4 -F $(IMG)
sudo mount $(IMG) $(MOUNT)
cd fsroot && sudo cp -r * $(MOUNT)
sudo umount $(MOUNT)
chmod 777 $(IMG)
run:
# Run QEMU with the installed kernel and generated initramfs
qemu-system-x86_64 \
-nographic \
-drive file=$(IMG),format=raw,index=0,media=disk,if=virtio \
-netdev user,id=net0,hostfwd=tcp:127.0.0.1:8080-:8080 -device e1000,netdev=net0 \
-kernel build/vmlinuz \
-initrd build/initramfs.cpio.gz \
-machine accel=kvm:tcg \
-m 2048 \
-append "console=ttyS0 quiet root=/dev/vda rdinit=$(INIT) debug" \
clean:
rm -rf build fsroot/lib/modules
.PHONY: initramfs run clean fsroot
- init
#!/bin/busybox sh
# At this point, we only have:
# /bin/busybox - the binary
# /dev/console - the console device
/bin/busybox ls
/bin/busybox echo start_init
BB=/bin/busybox
# Delete this file
# (Yes, we can do this on UNIX! The file is "removed"
# after the last reference, the fd, is gone.)
$BB rm /init
# $BB find / -type f
$BB echo "Unlimited power!!"
# $BB poweroff -f
# ----------------------------------------------------
# "Create" command-line tools by making symbolic links
# try: busybox --list
# for cmd in $($BB --list); do
# $BB ln -s $BB /bin/$cmd
# done
# Mount procfs and sysfs
mkdir -p /proc && mount -t proc none /proc
mkdir -p /sys && mount -t sysfs none /sys
modprobe virtio_blk
# Create devices
mknod /dev/random c 1 8
mknod /dev/urandom c 1 9
mknod /dev/null c 1 3
mknod /dev/tty c 4 1
mknod /dev/vda b 254 0
echo -e "\033[31mInit OK; launch a shell (initramfs).\033[0m"
#busybox sh
# Display a countdown
echo -e "\n\n"
# echo -e "\033[31mSwitch root in...\033[0m"
# for sec in $(seq 3 -1 1); do
# echo $sec; sleep 1
# done
# Switch root to /newroot (a real file system)
N=/newroot
mkdir -p $N
mount -t ext4 /dev/vda $N
chmod 777 $N
mkdir -p $N/bin
chmod 777 $N/bin
cp $BB $N/bin/
cp $BB /init
cp $BB /$N/init
ls / -l
ls $N -l
ls $N/bin -l
busybox sh
exec switch_root /newroot/ /init
- fsroot/init
#!/bin/busybox sh
# Now, "/" is the virtual disk--for real
# systems, we expect installed binaries.
BB=/bin/busybox
$BB echo "init"
for cmd in $($BB --list); do
$BB ln -s $BB /bin/$cmd
done
mkdir -p /proc && mount -t proc none /proc
mkdir -p /sys && mount -t sysfs none /sys
mkdir -p /tmp && mount -t tmpfs none /tmp
mkdir -p /dev
mknod /dev/random c 1 8
mknod /dev/urandom c 1 9
mknod /dev/null c 1 3
mknod /dev/tty c 4 1
mknod /dev/vda b 254 0
# Configure network
insmod /lib/modules/e1000.ko.xz
ip link set lo up
ip link set eth0 up
ip addr add 10.0.2.15 dev eth0
ip route add 10.0.2.0/24 dev eth0
# Prepare the terminal
echo -e "\033[31mGoodbye, QEMU Console!\033[0m"
echo -e "\033[H\033[2J" >/dev/tty
echo -e "JYY's minimal Linux" >/dev/tty
# Switch to terminal
setsid /bin/sh </dev/tty >/dev/tty 2>&1
sync
poweroff -f