Skip to content

Installing Windows from preseeds in QEMU #901

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 10 commits into
base: develop
Choose a base branch
from
22 changes: 19 additions & 3 deletions scripts/ci/qemu-run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ This is the QEMU wrapper script for the Dasharo Open Source Firmware Validation.
DIR working directory, defaults to current working directory
HDD2_PATH optional path of the second hard drive to connect to the machine if
ACTION "os" is used. Relative to DIR
BRIDGE if set, connects the machine to the local network via `br0` bridge
instead of doing address translation.

Example usage:
./$(basename $0) vnc firmware
Expand Down Expand Up @@ -133,8 +135,8 @@ if [ $# -ne 2 ]; then
usage
fi

QEMU_PARAMS_BASE="-machine q35,smm=on \
-global driver=cfi.pflash01,property=secure,value=on \
QEMU_PARAMS_BASE="-machine q35,smm=on -cpu Skylake-Client \
-global driver=cfi.pflash01,property=secure,value=off \
-drive if=pflash,format=raw,unit=0,file=${QEMU_FW_FILE} \
-global ICH9-LPC.disable_s3=1 \
-qmp unix:/tmp/qmp-socket,server,nowait \
Expand All @@ -154,9 +156,23 @@ QEMU_PARAMS_OS="-device ich9-intel-hda \
-object rng-random,id=rng0,filename=/dev/urandom \
-device virtio-rng-pci,max-bytes=1024,period=1000 \
-device virtio-net,netdev=vmnic \
-netdev user,id=vmnic,hostfwd=tcp::5222-:22 \
-drive file=${HDD_PATH},if=ide"

# Setting up a bridge interface for QEMU
# ip link add name br0 type bridge
# ip link set <interface> master br0
# ip addr flush dev <interface>
# ip link set br0 up
# ip addr add <interface_local_ip>/<mask> dev br0
# ip route add default via <gateway_ip>

if [[ -z ${BRIDGE} ]]; then
QEMU_PARAMS_OS+=" -netdev user,id=vmnic,hostfwd=tcp::5222-:22"
else
echo "Using bridged network $BRIDGE"
QEMU_PARAMS_OS+=" -netdev bridge,id=vmnic,br=$BRIDGE"
fi

if [[ -f ${HDD2_PATH} ]]; then
QEMU_PARAMS_OS+=" \
-drive file=${HDD2_PATH},if=ide"
Expand Down
68 changes: 68 additions & 0 deletions scripts/ci/setup_bridge.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/usr/bin/env bash

# SPDX-FileCopyrightText: 2025 3mdeb <[email protected]>
#
# SPDX-License-Identifier: Apache-2.0

INTERFACE=$1
DEL=$2
BR_NAME=br0

function print_help {
echo ""
echo "Usage: $0 <interface> [del]"
echo ""
echo "The script creates a bridged interface that will be connected"
echo "to a network of given <interface>. The given interface is"
echo "toggled down."
echo ""
echo "Use optional [del] option to delete the bridge and restore"
echo "the original interface"
echo ""
echo "Examples:"
echo " Set up bridge interface:"
echo " $0 enp0s1"
echo " Remove bridge and restore original interface:"
echo " $0 enp0s1 del"
}

if [[ -z $INTERFACE ]]; then
print_help
exit 1
fi

ip link show $INTERFACE &> /dev/null
if [[ $? -ne 0 ]]; then
print_help
exit 1
fi

if [[ $DEL == "del" ]]; then
ip link show $BR_NAME &> /dev/null
if [[ $? -ne 0 ]]; then
echo "Bridge interface $BR_NAME does not exist"
exit 0
fi

BR_IP=$(ip addr show $BR_NAME | awk '/inet / {print $2}')

echo "Deleting $BR_NAME IP: $BR_IP on $INTERFACE"

ip link del $BR_NAME
ip link set $INTERFACE up
else
ip link show $BR_NAME &> /dev/null
if [[ $? -eq 0 ]]; then
echo "Bridge interface $BR_NAME already exists"
exit 0
fi
BR_IP=$(ip addr show $INTERFACE | awk '/inet / {print $2}')

echo "Setting up interface $BR_NAME IP: $BR_IP on $INTERFACE"

ip link add name $BR_NAME type bridge
ip link set $INTERFACE master $BR_NAME
ip addr flush dev $INTERFACE
ip link set $BR_NAME up
ip addr add $BR_IP dev $BR_NAME
fi
256 changes: 256 additions & 0 deletions util/preseeds.robot
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
*** Settings ***
Library Collections
Library Dialogs
Library OperatingSystem
Library Process
Library String
Library Telnet timeout=30 seconds connection_timeout=120 seconds
Library SSHLibrary timeout=90 seconds
Library RequestsLibrary
# Library ../osfv-scripts/osfv_cli/src/osfv/rf/rte_robot.py
# TODO: maybe have a single file to include if we need to include the same
# stuff in all test cases
Resource ../variables.robot
Resource ../keywords.robot
Resource ../keys.robot
Resource ../keys-and-keywords/ubuntu-keywords.robot

Suite Setup Run Keywords
... Prepare Test Suite
# Test suite used to quickly flash disk images with preinstalled OSes.
# Two environment variables must be set prior to running it:
# - SOURCE_IMAGE
# - TARGET_DISK
# Optional:
# - CLONEZILLA_TTY
#
# Example usage:
# - Flash an image onto the device using ${RTE_IP}:
# SOURCE_IMAGE=1_windows_ubuntu TARGET_DISK=nvme0n1 ./scripts/run.sh util/preseeds.robot -- -t "Restore Disk*"
# - Launch clonezilla in manual mode over chosen serial console:
# CLONEZILLA_TTY=ttyUSB0 ./scripts/run.sh util/preseeds.robot -- -t "Manual Restore*"
# - Upload the disk image from the ${RTE_IP} device onto the disks NFS:
# ./scripts/run.sh util/preseeds -- -t "Upload Disk*"
# The image will be saved using the current date.
# Change the name on the NFS after uploading to make it stand out more


*** Variables ***
${CLONEZILLA_IPXE_SERVER}= http://192.168.10.217:8080
${DISKS_NFS_IP}= 192.168.10.217
${DISKS_NFS_PATH}= /srv/nfs/disk-images


*** Test Cases ***
Upload Disk Clonezilla
Power On
Boot Clonezilla
Configure Clonezilla
Upload Disk

Restore Disk Clonezilla
${source_image}= Get Envvar SOURCE_IMAGE
Set Suite Variable ${SOURCE_IMAGE} ${source_image}

${target_disk}= Get Envvar TARGET_DISK
Set Suite Variable ${TARGET_DISK} ${target_disk}

Power On
${ipxe_entered}= Run Keyword And Return Status Enter IPXE
IF not ${ipxe_entered} # It might just be disabled
Set UEFI Option NetworkBoot ${TRUE}
Power On
Enter IPXE
END
Execute Command In Terminal
... dhcp
... timeout=5m
IF "${CLONEZILLA_TTY}" == "${EMPTY}"
Write Bare Into Terminal chain ${CLONEZILLA_IPXE_SERVER}/boot.ipxe?image=${SOURCE_IMAGE}&disk=${TARGET_DISK}
ELSE
Write Bare Into Terminal
... chain ${CLONEZILLA_IPXE_SERVER}/boot.ipxe?image=${SOURCE_IMAGE}&disk=${TARGET_DISK}&tty=${CLONEZILLA_TTY}
END
Press Enter

# Wait for the restoration to finish
Set DUT Response Timeout 40m # More time might be needed, 40m is a guess
Enter Setup Menu Tianocore

Manual Restore Disk Clonezilla
${clonezilla_tty}= Get Envvar CLONEZILLA_TTY ${TRUE}
Set Suite Variable ${CLONEZILLA_TTY} ${clonezilla_tty}

Power On
${ipxe_entered}= Run Keyword And Return Status Enter IPXE
IF not ${ipxe_entered} # It might just be disabled
Set UEFI Option NetworkBoot ${TRUE}
Power On
Enter IPXE
END
Execute Command In Terminal
... dhcp
... timeout=5m

IF "${CLONEZILLA_TTY}" == "${EMPTY}"
Write Bare Into Terminal chain ${CLONEZILLA_IPXE_SERVER}/boot-manual.ipxe
ELSE
Write Bare Into Terminal chain ${CLONEZILLA_IPXE_SERVER}/boot-manual.ipxe?tty=${CLONEZILLA_TTY}
END
Press Enter

Log Clonezilla booted in manual mode. Continue manually. level=WARN
Execute Manual Step Clonezilla booted in manual mode. Continue manually.


*** Keywords ***
Get Envvar
[Tags] robot:private
[Arguments] ${name} ${optional}=${FALSE}
${status}= Run Keyword And Return Status Get Environment Variable ${name}
IF not (${optional} and ${status})
Log To Console Environment variable ${name} must be set.
Fail Environment variable ${name} is not set
ELSE IF ${status}
${var}= Get Environment Variable ${name}
RETURN ${var}
END
RETURN ${EMPTY}

Boot Clonezilla
[Tags] robot:private
${clonezilla_host}= %{CLONEZILLA_HOST}
${ipxe_entered}= Run Keyword And Return Status Enter IPXE
IF not ${ipxe_entered} # It might just be disabled
Set UEFI Option NetworkBoot ${TRUE}
Power On
Enter IPXE
END
Execute Command In Terminal
... dhcp
... timeout=5m
Write Bare Into Terminal chain ${clonezilla_host}/boot.ipxe
Press Enter

Configure Clonezilla
[Tags] robot:private
# Keyboard layout prompt
${screen}= Read From Terminal Until Keyboard configuration
# Select keep the default keyboard layout
Log To Console ${screen}
Press Enter

${screen}= Read From Terminal Until Start Clonezilla
Log To Console ${screen}
# Start clonezilla
${screen}= Read From Terminal Until <Cancel>
Log To Console ${screen}
# Select Start Clonezilla
Press Enter

${screen}= Read From Terminal Until Clonezilla - Opensource Clone System
Log To Console ${screen}
${screen}= Read From Terminal Until <Cancel>
Log To Console ${screen}
# Select device-image work with disks or partitions using images
Press Enter

# remote target of images
${screen}= Read From Terminal Until Mount Clonezilla image directory
Log To Console ${screen}
# Automatic NFS attaching doesn't work
Read From Terminal Until Enter command line prompt
Log To Console ${screen}
Press Key N Times 4 ${ARROW_DOWN}
Press Enter
Read From Terminal Until Press "Enter" to continue
Log To Console ${screen}
Press Enter

Set Prompt For Terminal root@debian:~#
Execute Command In Terminal mount -t nfs ${DISKS_NFS_IP}:${DISKS_NFS_PATH} /home/partimag
Execute Command In Terminal ls /home/partimag
Write Bare Into Terminal exit
Press Enter

# Choose Beginner mode - no need for advanced options
${screen}= Read From Terminal Until Clonezilla - Opensource Clone System
Log To Console ${screen}
${screen}= Read From Terminal Until Beginner
Log To Console ${screen}
Press Enter

Upload Disk
[Tags] robot:private
# Choose to save the whole disk not single partitions
${screen}= Read From Terminal Until savedisk
Log To Console ${screen}
Press Enter

${screen}= Read From Terminal Until Input a name for the saved image to use
Log To Console ${screen}
# Accept default image name
Press Enter

${screen}= Read From Terminal Until Choose local disk as source
Log To Console ${screen}
# Choose the first disk
Press Enter

${screen}= Read From Terminal Until Choose the compression option
Log To Console ${screen}
# default
Press Enter

${screen}= Read From Terminal Until Choose if you want to check and repair
Log To Console ${screen}
# dont check filesystems
Press Enter

${screen}= Read From Terminal Until do you want to check if the image is restorable
Log To Console ${screen}
# dont perform checks
Press Key N Times 1 ${ARROW_DOWN}
Press Enter

${screen}= Read From Terminal Until Do you want to encrypt the image
Log To Console ${screen}
# no encryption (default)
Press Enter

${screen}= Read From Terminal Until do not copy log files
Log To Console ${screen}
# do not save - the netbooted fs has no free space
Press Key N Times 1 ${ARROW_DOWN}
Press Enter

${screen}= Read From Terminal Until action to perform when everything is finished
Log To Console ${screen}
${screen}= Read From Terminal Until choose
Log To Console ${screen}
# will show a prompt for what to do after it finishes, will allow robot to
# detect if upload succeeded
Press Enter

${screen}= Read From Terminal Until Press "Enter" to continue
Log To Console ${screen}
Press Enter

${screen}= Read From Terminal Until Are you sure you want to continue
Log To Console ${screen}
Write Bare Into Terminal y
Press Enter

${screen}= Set Variable ${EMPTY}
Set DUT Response Timeout 30m
WHILE "Now you can choose to" not in """${screen}"""
Log To Console ${screen}
Press Enter
${screen}= Read From Terminal Until Regexp (Press "Enter" to continue)|(Now you can choose to:)
END

# Power off
Log To Console ${screen}
Press Key N Times 2 ${ARROW_UP}
Press Enter
Read From Terminal Until Will poweroff
Loading