- 由 虚拟的现实创建于7月 12, 2024 需要 3 分钟阅读时间
环境搭建
以 ubuntu 系统为例
sudo apt-get install -y qemu-kvm kpartx bsdmainutils
制作启动文件
disk.img = mbr+rootfs。创建100M启动文件,用来模拟后续的物理磁盘
dd if=/dev/zero of=./disk.img bs=1M count=100 echo "n p 1 w " | fdisk disk.img
通过命令hd(hexdump)命令可以查看前512字节(后面作为mbr结构)的内容:
可以看到 disk.img 的前512字节末尾为 0x55 0xAA (存储时低位在前,高位在后,因此也就是0xAA55,表明为mbr,且为活跃状态),另从00 20 21 00 83 be 32 0c 00 08 00 00 00 00 18 03 00为第一个磁盘分区项,用于描述该分区的相关信息也在mbr中。
制作rootfs根文件系统
将 disk.img 的第一个分区格式化为ext4文件系统:
sudo losetup /dev/loop0 disk.img sudo kpartx -av /dev/loop0 sudo mkfs.ext4 /dev/mapper/loop0p1
- 将 disk.img 关联到/dev/loop0设备,这样linux操作系统可以将disk.img当作块设备(磁盘)来进行操作
- 将 disk.img 的分区生成设备到/dev/mapper中,这里第一个分区即为/dev/mapper/loop0p1
- 将 disk.img 的第一个分区格式化为ext4文件系统
挂载第一分区,开始制作rootfs根文件系统:
sudo mkdir /mnt/rootfs sudo mount /dev/mapper/loop0p1 /mnt/rootfs # 这样便可以对第一个分区的文件系统进行文件目录等操作了
编译busybox
这里选择动态编译,后续的网络ping静态编译会出bug
mkdir busybox cd busybox wget https://busybox.net/downloads/busybox-1.29.3.tar.bz2 --no-check-certificate tar -xjf busybox-1.29.3.tar.bz2 cd busybox-1.29.3 make menuconfig make make install ldd bin/ping
因为是动态编译,需要将查看 bin 和 sbin 下的命令需要什么动态.so文件,使用 ldd 指令查看即可
sudo mkdir /mnt/rootfs/lib sudo cp -r /lib/i386-linux-gnu /mnt/rootfs/lib/ sudo cp -r /lib/ld-linux.so.2 /mnt/rootfs/lib/ sudo cp -r _install/* /mnt/rootfs/
根据上面的操作,我们已经有个rootfs根文件系统了,该rootfs根文件系统安装在第一分区
安装 grub2 bootloader 第一阶段,MBR引导
sudo grub-install --root-directory=/mnt/rootfs/ /dev/loop0
- 将 grub2 bootloader程序安装到 disk.im g的 mbr 中(前512字节的代码内容),以及将 grub 启动过程中需要的一些驱动文件安装到根目录 rootfs下的 boot/grub 目录下,之类会报错,可以忽略
通过查看
hd disk.img -n 512
可以看到前面的内容已经不再全是0,而且也能通过右边字符看到一些grub的描述,可以知道grub将bootloader的代码安装到了disk.img的mbr中:
拷贝vmlinuz和initrd
告知 vmlinuz 和 initrd.img 的位置信息给 grub2:
有 mbr 的 bootloader 程序,我们也已经为磁盘 disk.img 的第一个分区划分了存储容量,并且文件系统格式为 ext4 和制作成了 rootfs 根文件系统。而 grub2 bootloader 程序是能够识别 ext4 文件系统,因此其能够知道第一个分区到底存储了什么内容,因此只需要将 vmlinuz 和 initrd.img 存放到第一分区,grub2 bootloader是有能力读取到这两个文件的。
cd /mnt/rootfs sudo cp -r /boot/vmlinuz-3.5.0-17-generic ./boot/ sudo cp -r /boot/initrd.img-3.5.0-17-generic ./boot/ cd boot sudo ln -svf vmlinuz-3.5.0-17-generic vmlinuz sudo ln -svf initrd.img-3.5.0-17-generic initrd
创建其他依赖目录
cd /mnt/rootfs sudo mkdir dev proc run etc root sys
测试grub
这样disk.img启动文件便制作完成,使用qemu启动:
qemu-system-x86_64 -m 1024M -drive format=raw,file=disk.img
启动界面会到达 grub 命令行模式,虽然 grub 能够识别 ext4 文件系统,但是并没有告诉它具体的 vmlinuz 和 initrd.img 的路径,因此通过手动方式来告知 grub 这两个位置
其中set root是告知 grub 路径 /vmlinuz和 /initrd所在的磁盘分区,这里hd0,msdos1表示第一块磁盘的第一个分区即 disk.img 的第一个分区,set prefix是告知 grub 后续的命令和驱动的目录位置在哪,如这里的 linux 命令和 initrd 命令
最后执行启动boot即可
ls set root=(hd0,msdos1) set prefix=(hd0,msdos1)/boot/grub linux /boot/vmlinuz root=/dev/sda1 initrd /boot/initrd
grub 启动菜单 grub.cfg
cd /mnt/rootfs sudo cat > boot/grub/grub.cfg << EOF set timeout=5 set default=0 menuentry 'Linux, busybox, root=/dev/sda1' { linux /boot/vmlinuz root=/dev/sda1 initrd /boot/initrd } menuentry 'Reboot' { reboot } menuentry 'Shutdown' { halt } EOF
卸载 disk.img
sudo umount /dev/mapper/loop0p1 sudo dmsetup remove /dev/mapper/loop0p1 sudo losetup -d /dev/loop0
- 卸载 disk.img 的第一分区
- 删除 disk.img 第一分区所生成的设备
- 取消 disk.img 关联到/dev/loop0设备
- 无标签
添加评论