Skip to content

Commit

Permalink
Add windows launcher for x86_64
Browse files Browse the repository at this point in the history
Signed-off-by: Yuri Nesterov <[email protected]>
  • Loading branch information
nesteroff authored and jenninikko committed Jul 17, 2023
1 parent 010d8b7 commit 97126ac
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 71 deletions.
73 changes: 60 additions & 13 deletions docs/src/research/run_win_vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,88 @@

# Running Windows 11 in VM on Ghaf

You can run Windows 11 in a VM on Ghaf with NVIDIA Jetson Orin AGX. This method uses [QEMU](https://www.qemu.org/) as VMM. For information on how to build and run a Ghaf image for NVIDIA Jetson Orin AGX, see [Build and Run](../ref_impl/build_and_run.md#ghaf-image-for-nvidia-jetson-orin-agx).

You can run Windows 11 in a VM on Ghaf with NVIDIA Jetson Orin AGX (ARM64) or Generic x86 device. This method uses [QEMU](https://www.qemu.org/) as VMM. For information on how to build and run a Ghaf image, see [Build and Run](../ref_impl/build_and_run.md).

## Getting Windows 11 Image

1. Use your Microsoft account to join the [Windows Insider Program](https://insider.windows.com/en-us/register) to be able to install Windows Insider Preview Builds.
2. On the *Windows 11 on Arm Insider Preview* page, select the `Windows 11 Client Arm64 Insider Preview (Canary) - Build 25324` build and the language to download a VHDX image file for ARM64.
3. Copy *Windows11_InsiderPreview_Client_ARM64_en-us_25324.VHDX* to an external USB drive. Connect the USB drive to the NVIDIA device with the latest version of Ghaf installed, and mount it to some folder.
1. Depending on the device:
* For Generic x86, download Windows 11 ISO ([Win11_22H2_English_x64v2.iso](https://www.microsoft.com/software-download/windows11)) from the Microsoft website.
* For NVIDIA Jetson Orin AGX (ARM64), use your Microsoft account to join the [Windows Insider Program](https://insider.windows.com/en-us/register). On the Windows 11 on Arm Insider Preview page, select the `Windows 11 Client Arm64 Insider Preview (Canary) - Build 25324` build and the language to download a VHDX image file.
2. Copy the image to an external USB drive. Connect the USB drive to the device with the latest version of Ghaf installed, and mount it to some folder.

```
sudo mkdir /mnt
sudo mount /dev/sda /mnt
```
> **WARNING:** Make sure to use a fresh VHDX image file which has not been booted on some other environment before.
> **WARNING:** [For NVIDIA Jetson Orin AGX] Make sure to use a fresh VHDX image file that was not booted in another environment before.
## Running Windows 11 in VM
#### Running Windows 11 in VM on ARM64 Device (NVIDIA Jetson Orin AGX)

1. In Weston terminal, go to the directory with the VHDX image and run the VM using the following Ghaf script:
1. In the Weston terminal, go to the directory with the Windows 11 image and run the VM without sudo and as a non-root user using the following Ghaf script:

```
cd /mnt
windows-launcher ./Windows11_InsiderPreview_Client_ARM64_en-us_25324.VHDX
```

> **WARNING:** Do not use **sudo** or the root user to run windows-launcher.
2. Windows 11 requires Internet access to finish the setup. To boot the VM without an Internet connection, open cmd with Shift+F10 and type `OOBE\BYPASSNRO`. After the configuration restart click “I don’t have internet“ to skip the Internet connection step and continue the installation.

> TIP: If after pressing Shift+F10 the command window is not displayed, try to switch between opened windows by using Alt+Tab.
#### Running Windows 11 in VM on Generic x86 Device

On x86_64 device Windows 11 VM can be launched with either an ISO image or QCOW2.

- For an ISO image, the script creates an empty QCOW2 image in the same directory which is used as a system disk in the VM.
- After installing Windows 11, run the script for the QCOW2 image.

1. In the Weston terminal, go to the directory with the Windows 11 image and run the VM without sudo and as a non-root user using the following Ghaf script:

```
cd /mnt
windows-launcher ./Win11_22H2_English_x64v2.iso
```

2. When the VM starts booting press any key to boot from a CD.
3. In order to bypass Windows 11 system requirements, open cmd with Shift+F10 and type `regedit`. In HKEY_LOCAL_MACHINE\SYSTEM\Setup, right-click New > Key and type LabConfig. For this key create two DWORD (32-bit) parameters:
* Name: `BypassTPMCheck`, value `1`.
* Name: `BypassSecureBootCheck`, value `1`.

> TIP: [For Ghaf running on a laptop] If after pressing Shift+F10 the command window is not displayed, try again with the Fn key (Shift+Fn+F10) or switch between opened windows by using Alt+Tab.
4. Install Windows 11 in the VM.
5. Windows 11 requires Internet access to finish the setup. To boot the VM without an Internet connection, open cmd with Shift+F10 and type `OOBE\BYPASSNRO`. After the configuration restart click “I don’t have internet“ to skip the Internet connection step and continue the installation.
6. After the installation is completed the script is launched with the QCOW2 image:

```
windows-launcher ./win11.qcow2
```

## Using UI to Launch Windows 11 VM

Alternatively, you can launch the Windows 11 VM by clicking the corresponding icon in the Weston taskbar.
Instead of running Windows launcher from the command line it is possible to launch the Windows 11 VM by clicking the corresponding icon in the Weston taskbar.

When you click it for the first time, you will see a file selection dialog. Once Windows 11 image has been selected, it saves the path to the `~/.config/windows-launcher-ui.conf` configuration file and launches the VM. Next time, the VM will be immediately launched with one click.
When you click it for the first time, you will see a file selection dialog. Once Windows 11 image has been selected, it saves the path to the `~/.config/windows-launcher-ui.conf` configuration file and launches the VM. Next time, the VM will be immediately launched with one click.

2. You can pass additional parameter to QEMU after the image name. For example:
In order to use a different image instead of the saved one, delete the configuration file:

```
rm ~/.config/windows-launcher-ui.conf
```

## Passing Additional Parameters to QEMU

It is possible to pass additional parameters to QEMU when running Windows launcher from the command line.

NVIDIA Jetson Orin AGX (ARM64) example:

```
windows-launcher ./Windows11_InsiderPreview_Client_ARM64_en-us_25324.VHDX -serial stdio
```

3. Windows 11 requires Internet access to finish the setup. To boot the VM without an Internet connection, open cmd with Shift+F10 and type `OOBE\BYPASSNRO`. The VM will reboot and configuration will continue in offline mode.
Generic x86_64 example:

```
windows-launcher ./win11.qcow2 -serial stdio
```
2 changes: 1 addition & 1 deletion modules/windows-launcher/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ in {
ghaf.graphics.weston.launchers = [
{
path = "${windows-launcher}/bin/windows-launcher-ui";
icon = "${pkgs.gnome.adwaita-icon-theme}/share/icons/Adwaita/24x24/devices/computer.png";
icon = "${pkgs.gnome.adwaita-icon-theme}/share/icons/Adwaita/16x16/mimetypes/application-x-executable.png";
}
];
environment.systemPackages = [windows-launcher];
Expand Down
1 change: 1 addition & 0 deletions targets/generic-x86_64.nix
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
release.enable = variant == "release";
debug.enable = variant == "debug";
};
windows-launcher.enable = true;
};
}

Expand Down
5 changes: 1 addition & 4 deletions user-apps/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ in
pkgs = nixpkgs.legacyPackages.${system};
in {
gala-app = pkgs.callPackage ./gala {};
windows-launcher = pkgs.callPackage ./windows-launcher {};
};
}))

{
packages.aarch64-linux.windows-launcher = nixpkgs.legacyPackages.aarch64-linux.callPackage ./windows-launcher {};
}
]
162 changes: 109 additions & 53 deletions user-apps/windows-launcher/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,76 +4,131 @@
stdenvNoCC,
pkgs,
lib,
stdenv,
...
}: let
ovmfPrefix =
if stdenv.isx86_64
then "OVMF"
else if stdenv.isAarch64
then "AAVMF"
else throw "Unsupported architecture";
windowsLauncher =
pkgs.writeShellScript
"windows-launcher"
''
if [ $# -eq 0 ]; then
(''
IMG_FILE=$1
ISO_FILE=""
if [ $# -eq 0 ]; then
''
+ lib.optionalString stdenv.isAarch64 ''
echo "Usage: windows-launcher ./Windows11_InsiderPreview_Client_ARM64_en-us_25324.VHDX"
exit
fi
''
+ lib.optionalString stdenv.isx86_64 ''
echo "Usage: windows-launcher ./Win11_22H2_English_x64v2.iso or ./win11.qcow2"
''
+ ''
exit
fi
if [[ -z "''${WAYLAND_DISPLAY}" ]]; then
echo "Wayland display not found"
exit
fi
if [[ -z "''${WAYLAND_DISPLAY}" ]]; then
echo "Wayland display not found"
exit
fi
IMG_DIR="$(dirname "$1")"
AAVMF_VARS="$IMG_DIR/AAVMF_VARS.fd"
IMG_DIR="$(dirname "$IMG_FILE")"
OVMF_VARS="$IMG_DIR/${ovmfPrefix}_VARS.fd"
OVMF_CODE="$IMG_DIR/${ovmfPrefix}_CODE.fd"
if [ ! -f $AAVMF_VARS ]; then
cp ${pkgs.OVMF.fd}/FV/AAVMF_VARS.fd $AAVMF_VARS
chmod 644 $AAVMF_VARS
fi
if [ ! -f $OVMF_VARS ] || [ ! -f $OVMF_CODE ]; then
cp ${pkgs.OVMF.fd}/FV/${ovmfPrefix}_VARS.fd $OVMF_VARS
cp ${pkgs.OVMF.fd}/FV/${ovmfPrefix}_CODE.fd $OVMF_CODE
chmod 644 $OVMF_VARS
fi
''
+ lib.optionalString stdenv.isx86_64 ''
if [[ $1 == *.iso || $1 == *.ISO ]]; then
ISO_FILE=$1
IMG_FILE="$IMG_DIR/win11.qcow2"
if [ ! -f $IMG_FILE ]; then
${pkgs.qemu}/bin/qemu-img create -f qcow2 $IMG_FILE 64G
fi
fi
''
+ ''
QEMU_PARAMS=(
"-name \"Windows VM\""
"-cpu host"
"-enable-kvm"
"-smp 6"
"-m 8G"
"-drive file=$OVMF_CODE,format=raw,if=pflash,readonly=on"
"-drive file=$OVMF_VARS,format=raw,if=pflash"
"-vga none"
"-device ramfb"
"-device virtio-gpu-pci"
"-device qemu-xhci"
"-device usb-kbd"
"-device usb-tablet"
"-nic user,model=virtio"
''
+ lib.optionalString stdenv.isAarch64 ''
"-M virt,highmem=on,gic-version=max"
"-drive file=$IMG_FILE,format=vhdx,if=none,id=boot"
"-device usb-storage,drive=boot,serial=boot,bootindex=1"
)
''
+ lib.optionalString stdenv.isx86_64 ''
"-drive file=$IMG_FILE,format=qcow2,if=none,id=boot"
"-device nvme,drive=boot,serial=boot,bootindex=1"
)
${pkgs.qemu}/bin/qemu-system-aarch64 \
-name "Windows VM" \
-M virt,highmem=on,gic-version=max \
-cpu host \
-enable-kvm \
-smp 6 \
-m 12G \
-drive file=${pkgs.OVMF.fd}/FV/AAVMF_CODE.fd,format=raw,if=pflash,readonly=on \
-drive file=$AAVMF_VARS,format=raw,if=pflash \
-device ramfb \
-device virtio-gpu-pci \
-device qemu-xhci \
-device usb-kbd \
-device usb-tablet \
-drive file=$1,format=vhdx,if=none,id=boot \
-device usb-storage,drive=boot,serial=boot \
-nic user,model=virtio \
''${@:2}
'';
if [ ! -z "$ISO_FILE" ]; then
QEMU_PARAMS+=(
"-drive file=$ISO_FILE,media=cdrom,if=none,id=installcd"
"-device usb-storage,drive=installcd,bootindex=0"
)
fi
''
+ ''
eval "${pkgs.qemu}/bin/qemu-system-${stdenv.hostPlatform.qemuArch} ''${QEMU_PARAMS[@]} ''${@:2}"
'');
windowsLauncherUI =
pkgs.writeShellScript
"windows-launcher-ui"
''
if [[ -z "''${WAYLAND_DISPLAY}" ]]; then
echo "Wayland display not found"
exit
fi
(''
if [[ -z "''${WAYLAND_DISPLAY}" ]]; then
echo "Wayland display not found"
exit
fi
CONFIG=~/.config/windows-launcher-ui.conf
if [ -f "$CONFIG" ]; then
source $CONFIG
fi
CONFIG=~/.config/windows-launcher-ui.conf
if [ -f "$CONFIG" ]; then
source $CONFIG
fi
if [ ! -f "$FILE" ]; then
if [ ! -f "$FILE" ]; then
''
+ lib.optionalString stdenv.isAarch64 ''
FILE=`${pkgs.gnome.zenity}/bin/zenity --file-selection --title="Select Windows VM image (VHDX)"`
if [ ''$? -ne 0 ]; then
exit
else
echo FILE="$FILE" > "$CONFIG"
''
+ lib.optionalString stdenv.isx86_64 ''
FILE=`${pkgs.gnome.zenity}/bin/zenity --file-selection --title="Select Windows VM image (QCOW2 or ISO)"`
''
+ ''
if [ ''$? -ne 0 ]; then
exit
else
if [[ $FILE != *.iso && $FILE != *.ISO ]]; then
echo FILE="$FILE" > "$CONFIG"
fi
fi
fi
fi
if ! ${windowsLauncher} $FILE; then
${pkgs.gnome.zenity}/bin/zenity --error --text="Failed to run Windows VM: $?"
fi
'';
if ! ${windowsLauncher} $FILE; then
${pkgs.gnome.zenity}/bin/zenity --error --text="Failed to run Windows VM: $?"
fi
'');
in
stdenvNoCC.mkDerivation {
name = "windows-launcher";
Expand All @@ -89,8 +144,9 @@ in
'';

meta = with lib; {
description = "Helper scripts for launching Windows ARM64 virtual machines using QEMU";
description = "Helper scripts for launching Windows virtual machines using QEMU";
platforms = [
"x86_64-linux"
"aarch64-linux"
];
};
Expand Down

0 comments on commit 97126ac

Please sign in to comment.