从boot里偷一份内核,放到qemu里运行,把init换成自己的.
启动到initramfs后,尝试挂载sda,发现挂不上,看了眼dmesg发现Can’t open blockdev.
因为我虚拟的sda设备是Ext4文件系统,同时qemu用了Virtual IO.
而我从boot偷过来的kernel,是没Virtual IO和Ext4驱动的,他们以内核模块的方式被编译,我认为可以把当前系统里面的相关的内核模块一并拿到initramfs加载了,但是开考虑到相关Kernel Module还是有好几个依赖的,就没做(懒).
于是乎,我拉了个Linux内核并用LLVM直接编译了相关驱动进内核,配置直接从当前运行系统中的/proc/config.gz拿.
需要改的有:
1
2
3
4
5
6
7
| CONFIG_BLK_DEV=y
CONFIG_SCSI=y
CONFIG_SCSI_LOWLEVEL=y
CONFIG_SCSI_VIRTIO=y
CONFIG_VIRTIO_BLK=y
CONFIG_ATA=y
CONFIG_ATA_PIIX=y
|
顺带附上我的Makefile和INIT脚本:
Makefile#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| # 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-linux build/ && chmod 666 build/vmlinuz-linux"
cp bzImage build/vmlinuz-linux && chmod 666 build/vmlinuz-linux
chmod +x init && cp init build/initramfs/
cp $(shell which busybox) build/initramfs/bin/
# Pack build/initramfs as gzipped cpio archive
cd build/initramfs && \
find . -print0 \
| cpio --null -ov --format=newc \
| gzip -9 > ../initramfs.cpio.gz
fsroot:
mkdir -p fsroot/modules
cp e1000.ko fsroot/modules/
#
dd if=/dev/zero of=$(IMG) bs=1M count=64
mkfs.ext4 -F $(IMG)
sudo mount $(IMG) $(MOUNT)
cd fsroot && chmod +x ./init && sudo cp -r * $(MOUNT)
sudo umount $(MOUNT)
run:
# Run QEMU with the installed kernel and generated initramfs
qemu-system-x86_64 \
-serial mon:stdio -vga std \
-drive file=$(IMG),format=raw,index=0,media=disk \
-netdev user,id=net0,hostfwd=tcp:127.0.0.1:8080-:8080 -device e1000,netdev=net0 \
-kernel build/vmlinuz-linux \
-initrd build/initramfs.cpio.gz \
-machine accel=kvm:tcg \
-append "console=ttyS0 quiet rdinit=$(INIT)"
clean:
rm -rf build fsroot/modules
.PHONY: initramfs run clean fsroot
|
initramfs运行的INIT:#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
| #!/bin/busybox sh
# At this point, we only have:
# /bin/busybox - the binary
# /dev/console - the console device
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
# 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/sda b 8 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/sda $N
mkdir -p $N/bin
cp $BB $N/bin/
cp $BB /init
exec switch_root /newroot/ /init
|
switch_root 后运行的INIT:#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| #!/bin/busybox sh
# Now, "/" is the virtual disk--for real
# systems, we expect installed binaries.
BB=/bin/busybox
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/sda b 8 0
# Configure network
insmod /modules/e1000.ko
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
echo -e "Hello AyaSanae"
# 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
sh
# Switch to terminal
# setsid /bin/sh </dev/tty >/dev/tty 2>&1
#
# sync
# poweroff -f
|