Browse Source

增加uefi启动 (#101)

* 增加uefi启动

* 修改脚本

* uefi修改

* 删除错误的注释

* 修正写入磁盘镜像的脚本

* 修改X86_64为x86_64

Co-authored-by: longjin <[email protected]>
YJwu2023 2 years ago
parent
commit
7f439c5ddb
6 changed files with 172 additions and 36 deletions
  1. 16 4
      Makefile
  2. BIN
      tools/arch/x86_64/OVMF.fd
  3. 6 1
      tools/bootstrap.sh
  4. 67 5
      tools/create_hdd_image.sh
  5. 36 19
      tools/run-qemu.sh
  6. 47 7
      tools/write_disk_image.sh

+ 16 - 4
Makefile

@@ -66,12 +66,18 @@ gdb:
 
 # 写入磁盘镜像
 write_diskimage:
-	sudo sh -c "cd tools && bash $(ROOT_PATH)/tools/write_disk_image.sh && cd .."
+	sudo sh -c "cd tools && bash $(ROOT_PATH)/tools/write_disk_image.sh --bios=legacy && cd .."
 
+# 写入磁盘镜像(uefi)
+write_diskimage-uefi:
+	sudo sh -c "cd tools && bash $(ROOT_PATH)/tools/write_disk_image.sh --bios=uefi && cd .."
 # 不编译,直接启动QEMU
 qemu:
-	sh -c "cd tools && bash run-qemu.sh && cd .."
-
+	sh -c "cd tools && bash run-qemu.sh --bios=legacy && cd .."
+# 不编译,直接启动QEMU(UEFI)
+qemu-uefi:
+	sh -c "cd tools && bash run-qemu.sh --bios=uefi && cd .."
+	
 # 编译并写入磁盘镜像
 build:
 	$(MAKE) all -j $(NPROCS)
@@ -81,7 +87,13 @@ build:
 docker:
 	@echo "使用docker构建"
 	sudo bash tools/build_in_docker.sh || exit 1
-
+	
+# uefi方式启动
+run-uefi:
+	$(MAKE) all -j $(NPROCS)
+	$(MAKE) write_diskimage-uefi || exit 1
+	$(MAKE) qemu-uefi
+	
 # 编译并启动QEMU
 run:
 	$(MAKE) all -j $(NPROCS)

BIN
tools/arch/x86_64/OVMF.fd


+ 6 - 1
tools/bootstrap.sh

@@ -176,4 +176,9 @@ fi
 # 创建磁盘镜像
 bash create_hdd_image.sh
 
-congratulations
+# 解决kvm权限问题
+USR=$USER
+sudo adduser $USR kvm
+sudo chowm $USR /dev/kvm
+
+congratulations

+ 67 - 5
tools/create_hdd_image.sh

@@ -1,9 +1,18 @@
-echo "Creating virtual disk image..."
-
-# 创建一至少为32MB磁盘镜像(类型选择raw)
-qemu-img create -f raw disk.img 32M
+########################################################################
+# 这是一个用于创建磁盘镜像的脚本
+# 用法:./create_hdd_image.sh -P MBR/GPT
+# 要创建一个MBR分区表的磁盘镜像,请这样运行它: bash create_hdd_image.sh -P MBR
+# 要创建一个GPT分区表的磁盘镜像,请这样运行它: bash create_hdd_image.sh -P GPT
+# 请注意,这个脚本需要root权限
+# 请注意,运行这个脚本之前,需要在您的计算机上安装qemu-img和fdisk,以及parted
+# 
+# 这个脚本会在当前目录下创建一个名为disk.img的文件,这个文件就是磁盘镜像,
+#       在完成后,会将这个文件移动到bin目录下
+########################################################################
 
-# 使用fdisk把disk.img的分区表设置为MBR格式(下方的空行请勿删除)
+format_as_mbr() {
+    echo "Formatting as MBR..."
+   # 使用fdisk把disk.img的分区表设置为MBR格式(下方的空行请勿删除)
 fdisk disk.img << EOF
 o
 n
@@ -14,6 +23,59 @@ n
 w
 EOF
 
+}
+
+format_as_gpt() {
+    echo "Formatting as GPT..."
+sudo parted disk.img  << EOF
+mklabel gpt
+y
+mkpart
+p1
+FAT32
+0
+-1
+I
+set
+1
+boot
+on
+print
+q
+EOF
+}
+
+echo "Creating virtual disk image..."
+ARGS=`getopt -o P: -- "$@"`
+# 创建一至少为64MB磁盘镜像(类型选择raw)
+qemu-img create -f raw disk.img 64M
+#将规范化后的命令行参数分配至位置参数($1,$2,...)
+eval set -- "${ARGS}"
+#echo formatted parameters=[$@]
+#根据传入参数进行MBR/GPT分区
+case "$1" in
+    -P) 
+        if [ $2 == "MBR" ];
+        then 
+            format_as_mbr
+        elif [ $2 == "GPT" ];
+        then
+            format_as_gpt
+        else
+            echo "Invalid partition type: $2"
+            exit 1
+        fi
+        ;;
+    --)
+        # 如果没有传入参数-P,则默认为MBR分区
+        format_as_mbr
+        ;;
+    *)
+        echo "Invalid option: $1"
+        exit 1
+        ;;
+esac
+
 LOOP_DEVICE=$(sudo losetup -f --show -P disk.img) \
     || exit 1
 echo ${LOOP_DEVICE}p1

+ 36 - 19
tools/run-qemu.sh

@@ -1,36 +1,53 @@
 # 进行启动前检查
 flag_can_run=1
-
-
+ARGS=`getopt -o p -l bios: -- "$@"`
+eval set -- "${ARGS}"
+echo "$@"
 allflags=$(qemu-system-x86_64 -cpu help | awk '/flags/ {y=1; getline}; y {print}' | tr ' ' '\n' | grep -Ev "^$" | sed -r 's|^|+|' | tr '\n' ',' | sed -r "s|,$||")
 
 # 请根据自己的需要,在-d 后方加入所需的trace事件
 
 # 标准的trace events
-qemu_trace_std=cpu_reset,guest_errors,trace:check_exception,exec,cpu
+qemu_trace_std=cpu_reset,guest_errors,exec,cpu
 # 调试usb的trace
 qemu_trace_usb=trace:usb_xhci_reset,trace:usb_xhci_run,trace:usb_xhci_stop,trace:usb_xhci_irq_msi,trace:usb_xhci_irq_msix,trace:usb_xhci_port_reset,trace:msix_write_config,trace:usb_xhci_irq_msix,trace:usb_xhci_irq_msix_use,trace:usb_xhci_irq_msix_unuse,trace:usb_xhci_irq_msi,trace:usb_xhci_*
-
-
 qemu_accel=kvm
 if [ $(uname) == Darwin ]; then
     qemu_accel=hvf
 fi
 
+
+QEMU=qemu-system-x86_64
+QEMU_DISK_IMAGE="../bin/disk.img"
+QEMU_MEMORY="512M"
+QEMU_SMP="2,cores=2,threads=1,sockets=1"
+QEMU_MONITOR="stdio"
+QEMU_TRACE="${qemu_trace_std}"
+QEMU_CPU_FEATURES="IvyBridge,apic,x2apic,+fpu,check,${allflags}"
+QEMU_RTC_CLOCK="clock=host,base=localtime"
+QEMU_SERIAL="file:../serial_opt.txt"
+QEMU_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none"
+
+QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -net nic,model=virtio -usb -device qemu-xhci,id=xhci,p2=8,p3=4 -machine accel=${qemu_accel}"
+
+QEMU_ARGUMENT="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot order=d -monitor ${QEMU_MONITOR} -d ${qemu_trace_std} "
+
+QEMU_ARGUMENT+="-s -S -cpu ${QEMU_CPU_FEATURES} -rtc ${QEMU_RTC_CLOCK} -serial ${QEMU_SERIAL} -drive ${QEMU_DRIVE} ${QEMU_DEVICES}"
+
+
 if [ $flag_can_run -eq 1 ]; then
-    
-    qemu-system-x86_64 -d ../bin/disk.img -m 512M -smp 2,cores=2,threads=1,sockets=1 \
-    -boot order=d   \
-    -monitor stdio -d ${qemu_trace_std} \
-    -s -S -cpu IvyBridge,apic,x2apic,+fpu,check,${allflags} -rtc clock=host,base=localtime -serial file:../serial_opt.txt \
-    -drive id=disk,file=../bin/disk.img,if=none \
-    -device ahci,id=ahci \
-    -device ide-hd,drive=disk,bus=ahci.0    \
-    -net nic,model=virtio \
-    -usb    \
-    -device qemu-xhci,id=xhci,p2=8,p3=4 \
-    -machine accel=${qemu_accel}
-    
+    case "$1" in
+        --bios) 
+      case "$2" in
+              uefi) #uefi启动新增ovmf.fd固件
+              ${QEMU} -bios arch/X86_64/OVMF.fd ${QEMU_ARGUMENT}
+            ;;
+              legacy)
+              ${QEMU} ${QEMU_ARGUMENT}
+              ;;
+            esac       
+
+esac  
 else
   echo "不满足运行条件"
-fi
+fi

+ 47 - 7
tools/write_disk_image.sh

@@ -1,9 +1,21 @@
+###############################################
+# 该脚本用于将disk_mount目录下的文件写入到disk.img的第一个分区中,
+#       并在磁盘镜像中安装grub引导程序
+#
+# 用法:bash write_disk_image.sh --bios legacy/uefi
+# 如果之前创建的disk.img是MBR分区表,那么请这样运行它:bash write_disk_image.sh --bios legacy
+# 如果之前创建的disk.img是GPT分区表,那么请这样运行它:bash write_disk_image.sh --bios uefi
+###############################################
+
 ARCH="x86_64"
 # 内核映像
 root_folder=$(dirname $(pwd))
 kernel="${root_folder}/bin/kernel/kernel.elf"
 boot_folder="${root_folder}/bin/disk_mount/boot"
-
+mount_folder="${root_folder}/bin/disk_mount"
+ARGS=`getopt -o p -l bios: -- "$@"`
+eval set -- "${ARGS}"
+#echo formatted parameters=[$@]
 echo "开始写入磁盘镜像..."
 
 
@@ -23,7 +35,7 @@ bins[0]=${kernel}
 for file in ${bins[*]};do
 if [ ! -x $file ]; then
 echo "$file 不存在!"
-exit 1
+exit
 fi
 done
 
@@ -39,13 +51,28 @@ if [ ${ARCH} == "i386" ] || [ ${ARCH} == "x86_64" ]; then
     fi
 fi
 
-# 拷贝程序到硬盘
 # 判断是否存在硬盘镜像文件,如果不存在,就创建一个(docker模式下,由于镜像中缺少qemu-img不会创建)
 if [ ! -f "${root_folder}/bin/disk.img" ]; then
     echo "创建硬盘镜像文件..."
-    sudo bash ./create_hdd_image.sh || exit 1
+    case "$1" in
+        --bios) 
+        case "$2" in
+                uefi)
+            sudo bash ./create_hdd_image.sh -P GPT #GPT分区
+            ;;
+                legacy)
+            sudo bash ./create_hdd_image.sh -P MBR #MBR分区
+            ;;
+            esac       
+        ;;
+    *)
+        # 默认创建MBR分区
+        sudo bash ./create_hdd_image.sh -P MBR #MBR分区
+        ;;
+    esac
 fi
 
+# 拷贝程序到硬盘
 mkdir -p ${root_folder}/bin/disk_mount
 bash mount_virt_disk.sh || exit 1
 mkdir -p ${boot_folder}/grub
@@ -54,7 +81,6 @@ cp ${kernel} ${root_folder}/bin/disk_mount/boot
 mkdir -p ${root_folder}/bin/disk_mount/bin
 mkdir -p ${root_folder}/bin/disk_mount/dev
 mkdir -p ${root_folder}/bin/disk_mount/proc
-
 cp -r ${root_folder}/bin/user/* ${root_folder}/bin/disk_mount/bin
 touch ${root_folder}/bin/disk_mount/dev/keyboard.dev
 
@@ -73,8 +99,22 @@ fi
 # rm -rf ${iso_folder}
 LOOP_DEVICE=$(lsblk | grep disk_mount|sed 's/.*\(loop[0-9]*\)p1.*/\1/1g'|awk 'END{print $0}')
 echo $LOOP_DEVICE
-
-grub-install --target=i386-pc --boot-directory=${root_folder}/bin/disk_mount/boot/ /dev/$LOOP_DEVICE
+case "$1" in
+    --bios) 
+        case "$2" in
+                uefi) #uefi
+            grub-install --target=x86_64-efi  --efi-directory=${mount_folder}  --boot-directory=${boot_folder}  --removable
+            ;;
+                legacy) #传统bios
+            grub-install --target=i386-pc --boot-directory=${boot_folder} /dev/$LOOP_DEVICE
+            ;;
+        esac
+        ;;
+    *)
+    echo "参数错误"
+    ;;
+           
+esac
 
 sync
 bash umount_virt_disk.sh