0%

qemu启动Linux内核

Linux 内核编译

准备Linux kernel 源码

下载地址:

https://www.kernel.org/

1
2
3
xz -d linux-5.10.12.tar.xz
tar xvf linux-5.10.12.tar
cd linux-5.10.12
安装依赖
1
2
3
4
5
6
7
sudo apt-get install build-essential
sudo apt-get install libelf-dev
sudo apt-get install libncurses-dev
sudo apt-get install flex
sudo apt-get install bison
sudo apt install kernel-package build-essential libncurses5-dev fakeroot
sudo apt install libssl-dev
编译源码
1
2
make menuconfig
make bzImage -j8

make menuconfig 配置kernel编译参数,可根据自己的需求进行设置,ramfs 一般是默认开启的,后面通过qemu运行需要使用到这个。

内存分为不同的类型,这里编译的是x86_64 bzImage

内核的不同类型

bzImage是vmlinuz经过gzip压缩后的文件,适用于大内核

vmlinux是未压缩的内核

vmlinuz是vmlinux的压缩文件。

vmlinux 是ELF文件,即编译出来的最原始的文件。

vmlinuz应该是由ELF文件vmlinux经过OBJCOPY后,并经过压缩后的文件

zImage是vmlinuz经过gzip压缩后的文件,适用于小内核

BusyBox编译

在内核加载时,需要为内核准备文件系统,以及各种基本的工具。而BusyBox整合了很多常用的Linux工具。

准备busybox源码

下载地址: https://busybox.net/

1
2
tar -xvjf busybox-1.32.1.tar.bz2
cd busybox-1.32.1
编译源码
1
2
make menuconfig
make install -j 8

make menuconfig 对busybox编译参数进行设置,类似于linux kernel设置。由于我们前面编译的linux kernel只有一个内核文件,并且linux 程序执行的所需的依赖库,我们暂时是不打算装的,因此在编译busybox时,我们选择将busybox编译为一个静态二进制文件。

设置的路径如下:

1
2
3
Settings—>
Build Options—>
Build Busybox as a static binary(no shared libs)

make install -j 8 在执行后,会在当前目录生成_install 目录,这个目录里面包含busybox所有工具。我们可以看到,比如bin 目录中的程序,除了busybox外都是链接到busybox的软链。具体的调用都是busybox通过argv[0]来识别到调用名,在busybox内部来调用的。

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main( int argc, char *argv[] )
{
int i;
for (i = 0 ; i < argc ; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}

制作文件系统

补全目录

进入busybox的_install目录,补充完linux缺失的目录和文件

1
2
3
4
5
mkdir root dev etc bin sbin mnt sys proc lib home tmp var usr
mkdir usr/sbin usr/bin usr/lib usr/modules
mkdir mnt/usb mnt/nfs mnt/etc mnt/etc/init.d
mkdir lib/modules
chmod 1777 tmp
创建设备文件

进入dev目录执行:

1
2
sudo mknod -m 660 console c 5 1
sudo mknod -m 660 null c 1 3
配置磁盘分区

进入etc目录,创建并编辑fstab文件,输入以下内容

1
2
3
4
proc    /proc   proc    defaults    0   0
none /tmp ramfs defaults 0 0
mdev /dev ramfs defaults 0 0
sysfs /sys sysfs defaults 0 0
配置初始化操作

在etc下创建init.d目录,并在init.d目录下编辑rcS文件且加上可执行权限,输入以下内容

1
2
#! /bin/sh
/bin/mount -a

在etc下编辑inittab,输入以下内容

1
2
3
4
5
6
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/bin/umount -a -r
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff –a
打包文件系统

在_install目录下:

1
find . | cpio -o --format=newc > ./rootfs.img

这个时候会生成rootfs.img 文件

Qemu 编译及运行

我自己在ubuntu20.04上通过sudo apt-get install qemu 安装qemu,显示安装成功了,但是却找不到相关文件,因此后面是源码安装的。

准备源码

源码地址:https://www.qemu.org/

1
2
3
xz -d qemu-5.2.0.tar.xz
tar xvf qemu-5.2.0.tar.xz
cd qemu-5.2.0
编译安装
1
2
3
./configure 
make
sudo make install

./configure 后面可以指定安装路径,默然qemu会安装到/usr/local/bin中:

1
./configure  --prefix=/usr/bin/qemu --localstatedir=/var --sysconfdir=/etc
加载并运行linux
1
qemu-system-x86_64 -kernel ./bzImage -initrd  ./rootfs.img -nographic -append "console=ttyS0"

Linux 启动

TODO : 启动分析

参考

https://www.sunxiaokong.xyz/2020-01-14/lzx-linuxkernel-qemuinit/ 试了博主的方式,会提示physical kaslr disabled 而无法启动内核

https://gist.github.com/chrisdone/02e165a0004be33734ac2334f215380e