note/virtualbox-local-boot

VirtualBox 启动本地硬盘上的另一个系统

有时候我不得不使用 Windows:比如宣传部的小伙伴给我发来一个 PSD 文件时,比如计算机基础老师突然布置 MS Office 作业时。虽然 Krita 已经部分支持 PSD 格式、LibreOffice fresh 已经能完美支持打开和编辑 MS Office 文件;但这毕竟是两种不同的工具,总归是有区别的:就算它能完美兼容,界面也是不同的,我无法参考老师发过来的教学视频操作。而我又不想频繁地重启,虚拟化启动本地系统这个功能对我来说就十分有用了。

首先展示一下我当前硬盘的分区情况车祸现场

Device         Start       End   Sectors   Size Type
/dev/sda1       2048   1026047   1024000   500M EFI System
/dev/sda2    1026048   1288191    262144   128M Microsoft reserved
/dev/sda3    1288192 259891199 258603008 123.3G Microsoft basic data
/dev/sda4  473669632 475377663   1708032   834M Windows recovery environment
/dev/sda5  475377664 497743871  22366208  10.7G Windows recovery environment
/dev/sda6  497745920 500117503   2371584   1.1G Windows recovery environment
/dev/sda7  259891200 473669631 213778432   102G Linux filesystem

Partition table entries are not in disk order.

让我解释一下这样恶心的分区是怎么造成的。/dev/sda2 是 Windows Boot Manager,Windows 用于启动自身的工具;/dev/sda3 是 Windows 系统所在分区;/dev/sda{4..6} 是戴尔电脑出厂自带的恢复工具和 Windows 镜像。/dev/sda7 是从 /dev/sda3 中压缩出来建立的分区,所以你会看到下面有 “分区表项与硬盘次序不同” 的提示。

然后我在 /dev/sda7 上建立了一个 lvm pv,Linux 系统是安装在 lvm 上的。如果你不知道 lvm 是啥也没关系,你只要知道 Linux 系统数据是在 /dev/sda7 里的就可以了。GRUB 是和 Linux 安装在一个分区里的,/dev/sda1 里的默认引导项是 GRUB。

从 Linux 启动 Windows

为了避免之后使用 root 权限启动 VirtualBox 图形界面,我们先给自己一个读写分区的权限。我们需要 EFI 分区、Windows Boot Manager 分区和 Windows 分区。

sudo setfacl -m "u:${USER}:rw" /dev/sda{1,2,3}

然后创建一个 VirtualBox 的硬盘映射文件:

sudo setfacl -m "u:${USER}:rw" /dev/sda
VBoxManage internalcommands createrawvmdk -filename windows.vmdk -rawdisk /dev/sda -partitions 1,2,3 -relative

然后启动 VirtualBox,按照正常步骤创建一个新的虚拟机,只不过在硬盘那里选择你刚刚创建的那个硬盘映射文件。

然后在虚拟机设置里找到系统 -> 开启 EFI,因为咱的硬盘是 GPT 分区表嘛。

3, 2, 1, 启动!

意料之中地翻车了🤣。

前面说过,我的 GRUB 是和 Linux 系统一起装在位于 /dev/sda7 的 lvm lv 上的,而我没有在映射文件中加入这个分区;所以 GRUB 无法顺利运行,这里运行的只是一个 EFI 文件而已。但我后来又发现即使加了这个分区也会显示同样的错误。

那还有啥办法?不用 GRUB 呗。虚拟机开机时飞速按下 F12 进入虚拟机的启动菜单,移动光标选择 Boot Maintenance Manager -> Boot From File,打开硬盘。找到 Windows Boot Manager 的 EFI 文件 /EFI/Microsoft/Boot/bootmgfw.efi,打开。

虽然不是很完美但目的已经达到了。之后还有几点要注意的:

注意事项

  • 重启宿主机后需要再运行一遍这条命令才能启动。

    sudo setfacl -m "u:${USER}:rw" /dev/sda{1,2,3}
  • 本地的 Windows 被虚拟启动后再次本地启动时,Windows 会认为引导出了问题而把默认引导项改为 Windows Boot Manager,然后 GRUB 的引导项就被覆盖了。在 Linux 下运行以下命令来修复:

    sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=grub

从 Windows 启动 Linux

其实这篇笔记的标题叫 “使用 VirtualBox 在 Linux 下启动本地硬盘上的 Windows” 更为合适一点,因为我并没有做到从 Windows 启动本地硬盘上的 Linux。

所用的命令其实和 Linux 一样,只是记得要用管理员权限运行:

"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" internalcommands createrawvmdk -filename linux.vmdk -rawdisk \\.\PhysicalDrive0 -partitions 1,7 -relative

然后用管理员权限打开 VirtualBox,创建虚拟机。但是启动虚拟机时 VirtualBox 报错了,报错内容具体是什么我忘记了,不过似乎是与文件系统有关的。MS 好像曾经建议过用户不要使用任何 Windows 程序访问 Ext4 分区,更何况我的 Linux 分区还用了 lvm 的。

后记

这个双十一我终于下定决心升级一下我的笔记本硬件了,256 GB 的硬盘显然是不够两个系统吃的了。好在我的笔记本有两个硬盘接口,新硬盘到了后我可能会将两个系统各自安装在单独的硬盘上。看来这篇笔记很快就会再次更新。

最近 Arch Linux 的变化也好大啊,base 包组被一个元包替代了。很多非官方的包也跟着炸成一团烟花。Arch Linux 安装的那篇文章哪天也得更新一下。

About Me