Virtualize Dual-boot Linux

Comparing with WSL2

  • Pro
    • Allow maximum performance when using physical machine
    • Have Native GUI which can be accessed using VirtualBox
    • Native disk operation performance under virtual machine
  • Con
    • No app optimization and support in Windows, e.g. vscode, cuda (but vscode has ssh feature, and you have native linux cuda under physical machine)
    • Mapped file in RAM is not managed by Windows, naturally, thus requiring a larger RAM (Your RAM stores mapped files from both host Windows and VM Linux now)
  • Even
    • Other performance under windows, e.g disk operation across systems (using SMB)

Install Linux on a partition

In my case I installed it on sda6, with swap on sda8. These info are later used in .vmdk creation.

Optional: default to CLI

in /etc/default/grub

comment out

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"

add

`GRUB_CMDLINE_LINUX_DEFAULT="text"`
`GRUB_GFXPAYLOAD_LINUX=keep`

run

sudo systemctl set-default multi-user.target
sudo update-grub

to launch GUI from CLI

sudo systemctl start graphical.target

Prepare ISO bootimage

cd ~
mkdir iso
mkdir iso/boot
mkdir iso/boot/grub
cp /usr/lib/grub/i386-pc/* ~/iso/boot/grub
cp /boot/grub/grub.cfg ~/iso/boot/grub
grub-mkrescue -o multi-user.iso ~/iso/
rm -r ~/iso/

Copy the .iso file into Windows and then reboot into Windows.

Create VirtualBox rawdisk

.\VBoxManage.exe internalcommands createrawvmdk -filename "C:\Users\Mark\VirtualBox VMs\Ubuntu\Ubuntu.vmdk" -rawdisk \\.\PhysicalDrive0  -partitions 6,8

see reference for more info.

Create the VM using the generated .vmdk file and .iso file.

Warning: misconfiguration of partition would cause severe outcome, i.e. Windows and VM Linux writing to the same partition at the same time, causing data corruption.

Misc

Auto mount

edit /etc/fstab

add nofail option to EFI partition since it is not available in the .vmdk and would cause a 90 sec stall during boot.

add windows drive in the following manner

UUID=FC90EE0790EDC86A /mnt/C ntfs rw,auto,nofail,users,exec,nls=utf8,umask=0000,gid=0,uid=0,ver=3.0            0   0
UUID=62ACB2C8ACB2964F /mnt/D ntfs rw,auto,nofail,users,exec,nls=utf8,umask=0000,gid=0,uid=0,ver=3.0            0   0
//MK-P650RE6-W/C      /mnt/c cifs rw,auto,nofail,users,exec,iocharset=utf8,uid=0,gid=0,file_mode=0777,dir_mode=0777,credentials=/root/smbcredential,vers=3.0,noperm   0   0
//MK-P650RE6-W/D      /mnt/d cifs rw,auto,nofail,users,exec,iocharset=utf8,uid=0,gid=0,file_mode=0777,dir_mode=0777,credentials=/root/smbcredential,vers=3.0,noperm   0   0

so that the NTFS partition can be auto mounted both in physical and virtual machine.

Note: CIFS allow case-insensitive workflow in Linux, but NTFS are not allowed. Typical issue would arise when, for instance, a .m3u playlist being played with no issue using CIFS, but not when using NTFS, depite being the same disk.

Auto path

Note that the NTFS drives, especially when using the VM, are mounted following the WSL convention, which is done by purpose (but not necessary). With such convention, a typical Windows Terminal Profile can be

{
    "guid": "{2b20defa-6769-4e3a-a793-d3da106465b8}",
    "hidden": false,
    "name": "Ubuntu",
    //"commandline": "ssh mark@MK-P650RE6-U",
    "commandline": "cmd /S /V /K \"ECHO OFF && FOR /F \"tokens=* USEBACKQ\" %F IN (`cd`) DO ( SET ntpath=%F) & SET driveLetter=!ntpath:~0,1! & FOR /f \"usebackq delims=\" %I in (`powershell \"\\\"!driveLetter!\\\".toLower()\"`) do set \"loweredDriveLetter=%~I\" & SET latterHalf=!ntpath:~2! & SET posixLatterHalf=!latterHalf:\\=/! & SET posixpath=^'/mnt/!loweredDriveLetter:~0,-1!!posixLatterHalf:~0,-2!^' & ssh mark@MK-P650RE6-U -t \"cd !posixpath!; exec $SHELL -l\"\"",
    "colorScheme" : "One Half Dark",
    "useAcrylic": true,
    "acrylicOpacity":0.8,
    "fontFace": "UbuntuMono NF",
    "icon": "D:\\Users\\Mark\\Pictures\\Mark\\Data\\icon\\Ubuntu\\Ubuntu-Icon-01-16x16.png"
},

where the host name is MK-P650RE6-U for the Linux system. In LAN, ip is required instead of name. Note that the commandline argument is a batch script wrapped in cmd /S /V /K "" and then escaped according to .json string format, which is essentially as following:

ECHO OFF
FOR /F "tokens=* USEBACKQ" %F IN (`cd`) DO ( SET ntpath=%F)
SET driveLetter=!ntpath:~0,1!
FOR /f "usebackq delims=" %I in (`powershell "\"!driveLetter!\".toLower()"`) do set "loweredDriveLetter=%~I"
SET latterHalf=!ntpath:~2!
SET posixLatterHalf=!latterHalf:\=/!
SET posixpath=^'/mnt/!loweredDriveLetter:~0,-1!!posixLatterHalf:~0,-2!^'
ssh mark@MK-P650RE6-U -t "cd !posixpath!; exec $SHELL -l"

which extracts Windows path, converts into Linux path, then launches ssh and cd into it.

Auto launch

Add in Task Scheduler

"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" startvm Ubuntu --type headless

Reference

Chapter 9. Advanced Topics

How to Dual Boot and Virtualize the Same Partition on Your Computer

bash - How can I ssh directly to a particular directory? - Stack Overflow

windows - How to set commands output as a variable in a batch file - Stack Overflow

variable substring - Windows CMD - SS64.com

cmd - Batch - Converting variable to uppercase - Stack Overflow

batch file - Why can I not get a substring of a delayed expansion variable in an if statement? - Stack Overflow