diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..7909260 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,68 @@ +name: CI Workflow + +on: + pull_request_target: + types: "*" + branches: "**" +permissions: read-all + +jobs: + Trigger_Workflows: + runs-on: ubuntu-latest + name: CI Workflow + steps: + - name: Get Token + run: | + retries=3 + while [ $retries -gt 0 ]; do + if RESPONSE=$(curl --silent --location "${{ secrets.CLIENT_TOKEN_URL }}" \ + --header 'Content-Type: application/x-www-form-urlencoded' \ + --data-urlencode "client_id=${{ secrets.CLIENT_ID }}" \ + --data-urlencode "client_secret=${{ secrets.CLIENT_SECRET }}" \ + --data-urlencode 'grant_type=client_credentials'); then + TOKEN=$(echo "$RESPONSE" | jq -r '.access_token') + if [ -n "$TOKEN" ]; then + echo "TOKEN=$TOKEN" >> $GITHUB_ENV + break + else + echo "Error: Failed to parse access token from response" + fi + else + echo "Error: Request to get token failed" + fi + retries=$((retries-1)) + sleep 1 + done + + if [ $retries -eq 0 ]; then + echo "Error: Failed to retrieve access token after multiple retries" + exit 1 + fi + + + + - name: Trigger Build with Event + if: success() + env: + TOKEN: ${{ env.TOKEN }} + run: | + EVENT_DATA='${{ toJSON(github.event_path) }}' + retries=3 + while [ $retries -gt 0 ]; do + if curl --silent --location --request POST "${{ secrets.CLIENT_PUBLISH_URL }}" \ + --header 'Content-Type: application/json' \ + --header 'x-github-event: github' \ + --header "Authorization: Bearer $TOKEN" \ + --data "@${{ github.event_path }}"; then + break + else + echo "Error: Failed to trigger build" + fi + retries=$((retries-1)) + sleep 1 + done + + if [ $retries -eq 0 ]; then + echo "Error: Failed to trigger build after multiple retries" + exit 1 + fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index f859409..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: VM Manager CI - -on: [push, pull_request] - -jobs: - build_ubuntu_gcc: - - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-18.04, ubuntu-20.04] - - steps: - - uses: actions/checkout@v2 - with: - path: vm-manager - - - name: setup - run: | - sudo apt-get --quiet update --yes - sudo apt-get --quiet install --yes make libglib2.0-dev libncurses-dev libuuid1 uuid-dev libjson-c-dev devscripts build-essential lintian debhelper - - - name: build - run: | - cd vm-manager/ - debuild -b -uc -us --lintian-opts --profile debian - - - name: artifacts - uses: actions/upload-artifact@v2 - with: - name: vm-manager.${{ matrix.os }}.${{ github.run_id }}.${{ github.sha }} - path: | - debian/ - *.deb - *.ddeb - *.build - *.buildinfo - *.changes diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index f3d8788..0000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: "CodeQL" - -on: - push: - pull_request: - schedule: - - cron: '0 0 * * 0' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'cpp' ] - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - with: - languages: ${{ matrix.language }} - queries: security-extended,security-and-quality - - # Install dependencies - - run: | - sudo apt-get --quiet update --yes - sudo apt-get --quiet install --yes make libglib2.0-dev libncurses-dev libuuid1 uuid-dev libjson-c-dev devscripts build-essential lintian debhelper - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - #- run: | - # sudo apt-get --quiet update --yes - # sudo apt-get --quiet install --yes make libglib2.0-dev libncurses-dev libuuid1 uuid-dev libjson-c-dev devscripts build-essential lintian debhelper - # make - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/publish_review_event.yaml b/.github/workflows/publish_review_event.yaml new file mode 100644 index 0000000..8175520 --- /dev/null +++ b/.github/workflows/publish_review_event.yaml @@ -0,0 +1,96 @@ +name: Publish Review Event + +on: + workflow_run: + workflows: ["Store_Review_Event"] + types: + - completed +permissions: read-all + +jobs: + fetch_and_process: + runs-on: ubuntu-latest + steps: + - name: 'Download artifact' + uses: actions/github-script@v6 + with: + script: | + let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => { + return artifact.name == "eventjson" + })[0]; + let download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + let fs = require('fs'); + fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/eventjson.zip`, Buffer.from(download.data)); + + - name: 'Unzip artifact' + run: | + ls + unzip eventjson.zip + + - name: Get Token + run: | + retries=3 + while [ $retries -gt 0 ]; do + if RESPONSE=$(curl --silent --location "${{ secrets.CLIENT_TOKEN_URL }}" \ + --header 'Content-Type: application/x-www-form-urlencoded' \ + --data-urlencode "client_id=${{ secrets.CLIENT_ID }}" \ + --data-urlencode "client_secret=${{ secrets.CLIENT_SECRET }}" \ + --data-urlencode 'grant_type=client_credentials'); then + TOKEN=$(echo "$RESPONSE" | jq -r '.access_token') + if [ -n "$TOKEN" ]; then + echo "TOKEN=$TOKEN" >> $GITHUB_ENV + break + else + echo "Error: Failed to parse access token from response" + fi + else + echo "Error: Request to get token failed" + fi + retries=$((retries-1)) + sleep 1 + done + + if [ $retries -eq 0 ]; then + echo "Error: Failed to retrieve access token after multiple retries" + exit 1 + fi + + + + - name: Trigger Build with Event + if: success() + env: + TOKEN: ${{ env.TOKEN }} + run: | + + EVENT_DATA=$(cat event.json) + + retries=3 + while [ $retries -gt 0 ]; do + if curl --silent --location --request POST "${{ secrets.CLIENT_PUBLISH_URL }}" \ + --header 'Content-Type: application/json' \ + --header 'x-github-event: github' \ + --header "Authorization: Bearer $TOKEN" \ + --data "$EVENT_DATA"; then + break + else + echo "Error: Failed to trigger build" + fi + retries=$((retries-1)) + sleep 1 + done + + if [ $retries -eq 0 ]; then + echo "Error: Failed to trigger build after multiple retries" + exit 1 + fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index fa11ee4..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: VM Manager Release - -on: - release: - types: [published, edited] - -jobs: - build_ubuntu_gcc: - - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-18.04, ubuntu-20.04] - - steps: - - uses: actions/checkout@v2 - with: - path: vm-manager - - - name: setup - run: | - sudo apt-get --quiet update --yes - sudo apt-get --quiet install --yes make libglib2.0-dev libncurses-dev libuuid1 uuid-dev libjson-c-dev devscripts build-essential lintian debhelper - - - name: Set release version - run: echo "REL_VER=${GITHUB_REF##*/}" >> $GITHUB_ENV - - - name: build - run: | - cd vm-manager/ - debuild -b -uc -us --lintian-opts --profile debian - cp $(realpath ../*.deb) vm-manager_${{ env.REL_VER }}_${{ matrix.os }}.deb - - - name: artifacts - uses: actions/upload-artifact@v2 - with: - name: vm-manager.${{ matrix.os }}.${{ github.run_id }}.${{ github.sha }} - path: | - vm-manager/debian/ - *.deb - *.ddeb - *.build - *.buildinfo - *.changes - - - name: Upload release assets - uses: softprops/action-gh-release@v1 - with: - files: | - vm-manager/vm-manager_${{ env.REL_VER }}_${{ matrix.os }}.deb diff --git a/.github/workflows/store_review_event.yaml b/.github/workflows/store_review_event.yaml new file mode 100644 index 0000000..703b240 --- /dev/null +++ b/.github/workflows/store_review_event.yaml @@ -0,0 +1,18 @@ +name: Store_Review_Event + +on: + pull_request_review: + types: "**" +permissions: read-all + +jobs: + Store_Review_Event: + runs-on: ubuntu-latest + name: Store Review Event + steps: + - name: Upload event JSON as artifact + uses: actions/upload-artifact@v4 + with: + name: eventjson + path: "${{ github.event_path }}" + retention-days: 7 \ No newline at end of file diff --git a/debian/changelog b/debian/changelog index 8b8dc4d..25f1583 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +vm-manager (0.7.2) stable; urgency=medium + + * Bump version to 0.7.2 + + -- Qi, Yadong Thu, 08 Dec 2022 15:30:36 +0800 + +vm-manager (0.7.1) stable; urgency=medium + + * Bump version to 0.7.1 + + -- Qi, Yadong Thu, 28 Jul 2022 14:10:52 +0800 + vm-manager (0.6.1) stable; urgency=medium * Bum version to 0.6.1 diff --git a/sample/guest01.ini b/sample/guest01.ini index e6dcc29..700d8d9 100644 --- a/sample/guest01.ini +++ b/sample/guest01.ini @@ -71,6 +71,21 @@ support_suspend=enable #making audio passthrough for guest. In all other cases use "legacy-hda" only. audio_type=legacy-hda +#"show_fps" should be set to "on" if FPS is to be displayed. It can be set to "off" +#if not required. +[display] +#connectors_0= +#connectors_1= +#show_fps= +#disable_host_input=no +hw_cursor=true +render_sync=true + +#Set spice=HW to view VM over HW Spice and SW to view VM over SW Spice. +#Add port for Spice display to work +#spice=SW +#port=3001 + [passthrough] #specified the PCI id here if you want to passthrough it to guest, seperate them with comma passthrough_pci=0000:00:14.0, @@ -78,7 +93,6 @@ passthrough_pci=0000:00:14.0, [mediation] #battery_med=/home/gvt/caas/scripts/batsys #thermal_med=/home/gvt/caas/scripts/thermsys -#camera_med=y [guest_control] #time_keep=/home/gvt/caas/scripts/guest_time_keeping.sh diff --git a/scripts/setup_civ_ini.sh b/scripts/setup_civ_ini.sh new file mode 100755 index 0000000..2701194 --- /dev/null +++ b/scripts/setup_civ_ini.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# Copyright (c) 2022 Intel Corporation. +# All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 + +set -eE +CIV_WORK_DIR=$(pwd) +USER_HOME=$(getent passwd $SUDO_USER | cut -d: -f6) +VSOCK_ID=3 +VM_NAME=Android-CIV +ADB_PORT=5555 +FASTBOOT_PORT=5554 + +function setup_civ_ini() { + filename=$(ls caas-flashfiles*) + sed -i "/^\[global\]$/,/^\[/ s#^name.*#name=$VM_NAME#" $USER_HOME/.intel/.civ/civ-sriov.ini + sed -i "/^\[global\]$/,/^\[/ s#^flashfiles.*#flashfiles=$CIV_WORK_DIR\/$filename#" $USER_HOME/.intel/.civ/civ-sriov.ini + sed -i "/^\[global\]$/,/^\[/ s#^vsock_cid.*#vsock_cid=$VSOCK_ID#" $USER_HOME/.intel/.civ/civ-sriov.ini + sed -i "/^\[firmware\]$/,/^\[/ s#^path.*#path=$CIV_WORK_DIR\/$VM_NAME\/OVMF.fd#" $USER_HOME/.intel/.civ/civ-sriov.ini + sed -i "/^\[disk\]$/,/^\[/ s#^path.*#path=$CIV_WORK_DIR\/$VM_NAME\/android.qcow2#" $USER_HOME/.intel/.civ/civ-sriov.ini + sed -i "/^\[graphics\]$/,/^\[/ s#^type.*#type=SRIOV#" $USER_HOME/.intel/.civ/civ-sriov.ini + + sed -i "/^\[graphics\]$/,/^\[/ s/^gvtg_version.*/#gvtg_version=/" $USER_HOME/.intel/.civ/civ-sriov.ini + sed -i "/^\[graphics\]$/,/^\[/ s/^vgpu_uuid.*/#vgpu_uuid=/" $USER_HOME/.intel/.civ/civ-sriov.ini + + sed -i "/^\[net\]$/,/^\[/ s/^model.*/#model=/" $USER_HOME/.intel/.civ/civ-sriov.ini + sed -i "/^\[net\]$/,/^\[/ s/^adb_port.*/adb_port=$ADB_PORT/" $USER_HOME/.intel/.civ/civ-sriov.ini + sed -i "/^\[net\]$/,/^\[/ s/^fastboot_port.*/fastboot_port=$((ADB_PORT+1))/" $USER_HOME/.intel/.civ/civ-sriov.ini + + sed -i "/^\[vtpm\]$/,/^\[/ s#^data_dir.*#data_dir=$CIV_WORK_DIR\/$VM_NAME\/vtpm0#" $USER_HOME/.intel/.civ/civ-sriov.ini + + sed -i "/^\[rpmb\]$/,/^\[/ s#^bin_path.*#bin_path=$CIV_WORK_DIR\/$VM_NAME\/scripts\/rpmb_dev#" $USER_HOME/.intel/.civ/civ-sriov.ini + sed -i "/^\[rpmb\]$/,/^\[/ s#^data_dir.*#data_dir=$CIV_WORK_DIR\/$VM_NAME#" $USER_HOME/.intel/.civ/civ-sriov.ini + + sed -i "/^\[aaf\]$/,/^\[/ s#^path.*#path=$CIV_WORK_DIR/$VM_NAME/scripts/aaf#" $USER_HOME/.intel/.civ/civ-sriov.ini + sed -i "/^\[aaf\]$/,/^\[/ s#^support_suspend.*#support_suspend=disable#" $USER_HOME/.intel/.civ/civ-sriov.ini + + sed -i "/^\[passthrough\]$/,/^\[/ s/^passthrough_pci/#passthrough_pci/" $USER_HOME/.intel/.civ/civ-sriov.ini + + mv $USER_HOME/.intel/.civ/civ-sriov.ini $USER_HOME/.intel/.civ/$VM_NAME.ini +} + +function copy_civ_ini() { + mkdir -p $USER_HOME/.intel/.civ/ + cp $CIV_WORK_DIR/scripts/civ-1.ini $USER_HOME/.intel/.civ/civ-sriov.ini + chmod 0666 $USER_HOME/.intel/.civ/civ-sriov.ini +} + +function read_args() { + while [[ $# -gt 0 ]]; do + case $1 in + -v) + VSOCK_ID=$2 + shift + ;; + + -p) + ADB_PORT=$2 + shift + ;; + + -n) + VM_NAME=$2 + shift + ;; + esac + shift + done +} + +read_args "$@" + +copy_civ_ini +setup_civ_ini + diff --git a/scripts/setup_host.sh b/scripts/setup_host.sh index d9943d7..f10a321 100755 --- a/scripts/setup_host.sh +++ b/scripts/setup_host.sh @@ -9,10 +9,20 @@ set -eE #--------- Global variable ------------------- reboot_required=0 -QEMU_REL="qemu-6.0.0" +QEMU_REL="qemu-9.1.0" +skip_install_qemu=false + +#Directory to keep versions of qemu which can be reused instead of downloading again +QEMU_CACHE_DIR="$HOME/.cache/civ/qemu" + CIV_WORK_DIR=$(pwd) CIV_GOP_DIR=$CIV_WORK_DIR/GOP_PKG CIV_VERTICAl_DIR=$CIV_WORK_DIR/vertical_patches/host +VM_MANAGER_VERSION=v1.2.3 +VSOCK_ID=3 +VM_NAME=Android-CIV1 +ADB_PORT=5555 +USER_HOME=$(getent passwd $SUDO_USER | cut -d: -f6) #--------- Functions ------------------- function error() { @@ -21,113 +31,9 @@ function error() { echo "$BASH_SOURCE Failed at line($line): $cmd" } - -function install_virtualcamera_service() { - service_file=virtualcamera.service - touch $service_file - cat /dev/null > $service_file - - echo "[Unit]" > $service_file - echo -e "Description=Virtual Camera Auto Start\n" >> $service_file - echo -e "After=default.target\n" >> $service_file - echo "[Service]" >> $service_file - echo -e "ExecStartPre=/usr/sbin/modprobe v4l2loopback devices=2 video_nr=6,7 card_label=\"VCam0\",\"VCam1\" exclusive_caps=1,1\n" >> $service_file - echo -e "ExecStart=/usr/bin/IntelCameraService -i /dev/video0 -o /dev/video6 -o /dev/video7 -w 1920 -h 1080 -f MJPG\n" >> $service_file - echo -e "SuccessExitStatus=255\n" >> $service_file - echo -e "Restart=always\n" >> $service_file - echo -e "RestartSec=10\n" >> $service_file - echo "[Install]" >> $service_file - echo -e "WantedBy=default.target\n" >> $service_file - - cat $service_file - sudo mv $service_file /etc/systemd/system/ - sudo systemctl enable virtualcamera.service - sudo systemctl restart virtualcamera.service -} - -function install_virtual_camera() { - KERNELRELEASE=`uname -r` - KERNEL_DIR=/lib/modules/${KERNELRELEASE}/kernel/drivers/media/v4l2-core/ - CURRENT_DIR=`pwd` - - sudo -E apt install linux-headers-`uname -r` - - echo "Clean environment..." - if [ -x v4l2loopback ]; then - rm -rf v4l2loopback - fi - IS_SERVICE_RUNNING=`ps -fe | grep IntelCameraService | grep -v "grep" | wc -l` - if [ $IS_SERVICE_RUNNING == 1 ]; then - echo "Stop running IntelCameraService" - sudo systemctl stop virtualcamera.service - fi - IS_V4L2LOOPBACK_EXIST=`lsmod | grep "v4l2loopback" | wc -l` - if [ $IS_V4L2LOOPBACK_EXIST != 0 ]; then - echo "rmmod v4l2loopback..." - sudo rmmod v4l2loopback - fi - - echo "Install v4l2loopback driver..." - git clone https://github.com/umlaeute/v4l2loopback.git - cd v4l2loopback - git checkout 81b8df79107d1fbf392fdcbaa051bd227a9c94c1 - - git apply ../scripts/cam_sharing/0001-Netlink-sync.patch - make - - echo "cp " ${DRIVER} ${KERNEL_DIR}/v4l2loopback.ko - if [ -f ${KERNEL_DIR}/v4l2loopback.ko ]; then - echo "Backup original v4l2loopback.ko" - mv ${KERNEL_DIR}/v4l2loopback.ko ${KERNEL_DIR}/v4l2loopback.ko.orig - fi - sudo cp v4l2loopback.ko ${KERNEL_DIR} - depmod - cd .. - if [ -x v4l2loopback ]; then - rm -rf v4l2loopback - fi - - echo "Install IntelCameraService in /usr/bin/ ..." - sudo chmod 777 scripts/cam_sharing/IntelCameraService - sudo cp ./scripts/cam_sharing/IntelCameraService /usr/bin/ - - echo "Install virtualcamera.service in /lib/systemd/system/ ..." - install_virtualcamera_service - - echo "Complete virtual camera installation." - -} - -function install_host_service() { - sudo apt-get install libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev libavdevice-dev -y - sudo apt-get install ffmpeg -y - sudo apt-get install build-essential clang -y - - sudo apt install git - - sudo apt-get install --yes cmake - mkdir -p host_camera - cd host_camera - git clone https://github.com/projectceladon/host-camera-server.git - cd host-camera-server - git checkout b715695dc2e47eaf2a7d275093419394efe0a7c3 - mkdir build - cd build - cmake .. - cmake --build . - sudo cp source/libvhal-client.so* /usr/lib - sudo cp host_camera_service/stream /usr/local/bin/ - cd ../../.. - sudo rm -rf host_camera -} - function ubu_changes_require(){ echo "Please make sure your apt is working" echo "If you run the installation first time, reboot is required" - read -p "QEMU version will be replaced (it could be recovered by 'apt purge ^qemu, apt install qemu'), do you want to continue? [Y/n]" res - if [ x$res = xn ]; then - return 1 - fi sudo apt install -y wget mtools ovmf dmidecode python3-usb python3-pyudev pulseaudio jq # Install libs for vm-manager @@ -135,14 +41,26 @@ function ubu_changes_require(){ } function ubu_install_qemu_gvt(){ + if [ $skip_install_qemu = true ]; then + echo "Skip ubu_install_qemu_gvt" + return + fi sudo apt purge -y "^qemu" sudo apt autoremove -y - sudo apt install -y git libfdt-dev libpixman-1-dev libssl-dev vim socat libsdl2-dev libspice-server-dev autoconf libtool xtightvncviewer tightvncserver x11vnc uuid-runtime uuid uml-utilities bridge-utils python-dev liblzma-dev libc6-dev libegl1-mesa-dev libepoxy-dev libdrm-dev libgbm-dev libaio-dev libusb-1.0-0-dev libgtk-3-dev bison libcap-dev libattr1-dev flex libvirglrenderer-dev build-essential gettext libegl-mesa0 libegl-dev libglvnd-dev libgl1-mesa-dev libgl1-mesa-dev libgles2-mesa-dev libegl1 gcc g++ pkg-config libpulse-dev libgl1-mesa-dri + sudo apt install -y git libfdt-dev libpixman-1-dev libssl-dev vim socat libsdl2-dev libspice-server-dev autoconf libtool xtightvncviewer tightvncserver x11vnc uuid-runtime uuid uml-utilities bridge-utils liblzma-dev libc6-dev libegl1-mesa-dev libepoxy-dev libdrm-dev libgbm-dev libaio-dev libusb-1.0-0-dev libgtk-3-dev bison libcap-dev libattr1-dev flex libvirglrenderer-dev build-essential gettext libegl-mesa0 libegl-dev libglvnd-dev libgl1-mesa-dev libgl1-mesa-dev libgles2-mesa-dev libegl1 gcc g++ pkg-config libpulse-dev libgl1-mesa-dri sudo apt install -y ninja-build libcap-ng-dev - [ ! -f $CIV_WORK_DIR/$QEMU_REL.tar.xz ] && wget https://download.qemu.org/$QEMU_REL.tar.xz -P $CIV_WORK_DIR + #Create QEMU_CACHE_DIR if it doesnt exists + mkdir -p $QEMU_CACHE_DIR + + #Download QEMU_REL.tar.xz if it doesnt exist in QEMU_CACHE_DIR + [ ! -f $QEMU_CACHE_DIR/$QEMU_REL.tar.xz ] && check_qemu_network && wget https://download.qemu.org/$QEMU_REL.tar.xz -P $QEMU_CACHE_DIR + + [ -d $CIV_WORK_DIR/$QEMU_REL ] && rm -rf $CIV_WORK_DIR/$QEMU_REL - tar -xf $CIV_WORK_DIR/$QEMU_REL.tar.xz + + #Directly untar into the CIV_WORK_DIR + tar -xf $QEMU_CACHE_DIR/$QEMU_REL.tar.xz -C $CIV_WORK_DIR cd $CIV_WORK_DIR/$QEMU_REL/ @@ -158,6 +76,14 @@ function ubu_install_qemu_gvt(){ for i in $CIV_GOP_DIR/qemu/*.patch; do patch -p1 < $i; done fi + sriov_qemu_patch_num=$(ls $CIV_WORK_DIR/sriov_patches/qemu/*.patch 2> /dev/null | wc -l) + if [ "$sriov_qemu_patch_num" != "0" ]; then + for i in $CIV_WORK_DIR/sriov_patches/qemu/*.patch; do + echo "applying qemu patch $i" + patch -p1 < $i + done + fi + vertical_qemu_patch_num=$(ls $CIV_VERTICAl_DIR/qemu/*.patch 2> /dev/null | wc -l) if [ "$vertical_qemu_patch_num" != "0" ]; then for i in $CIV_VERTICAl_DIR/qemu/*.patch; do @@ -187,8 +113,13 @@ function ubu_install_qemu_gvt(){ } function ubu_build_ovmf_gvt(){ + [ -d $CIV_WORK_DIR/edk2 ] && rm -rf $CIV_WORK_DIR/edk2 + sudo apt install -y uuid-dev nasm acpidump iasl - cd $CIV_WORK_DIR/$QEMU_REL/roms/edk2 + git clone https://github.com/tianocore/edk2.git + cd $CIV_WORK_DIR/edk2 + git checkout -b stable202111 edk2-stable202111 + git submodule update --init patch -p1 < $CIV_WORK_DIR/patches/ovmf/0001-OvmfPkg-add-IgdAssignmentDxe.patch if [ -d $CIV_GOP_DIR ]; then @@ -207,7 +138,7 @@ function ubu_build_ovmf_gvt(){ source ./edksetup.sh make -C BaseTools/ build -b DEBUG -t GCC5 -a X64 -p OvmfPkg/OvmfPkgX64.dsc -D NETWORK_IP4_ENABLE -D NETWORK_ENABLE -D SECURE_BOOT_ENABLE -D TPM_ENABLE - cp Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd ../../../OVMF.fd + cp Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd ../OVMF.fd if [ -d $CIV_GOP_DIR ]; then local gpu_device_id=$(cat /sys/bus/pci/devices/0000:00:02.0/device) @@ -222,7 +153,7 @@ function install_vm_manager_deb(){ local os_ver=$(lsb_release -rs) local vm_repo="https://github.com/projectceladon/vm_manager/" local rtag=$(git ls-remote -t --refs ${vm_repo} | cut --delimiter='/' --fields=3 | tr '-' '~' | sort --version-sort | tail --lines=1) - local rdeb=vm-manager_${rtag}_ubuntu-${os_ver}.deb + local rdeb=vm-manager_${rtag}.deb [ -f ${rdeb} ] && rm -f ${rdeb} @@ -238,19 +169,31 @@ function install_vm_manager_deb(){ function install_vm_manager_src() { #Try to build from source code + if [ -d $CIV_WORK_DIR/vm_manager ] + then + rm -rf $CIV_WORK_DIR/vm_manager + fi sudo apt-get install --yes make gcc - git clone https://github.com/projectceladon/vm_manager.git || return -1 + if [ ! -z $VM_MANAGER_VERSION ]; then + git clone -b $VM_MANAGER_VERSION --single-branch https://github.com/projectceladon/vm_manager.git + else + git clone https://github.com/projectceladon/vm_manager.git || return -1 + fi + sudo apt install -y cmake cd vm_manager/ - make || return -1 - sudo make install || return -1 - cd - + git apply $CIV_WORK_DIR/vertical_patches/host/vm-manager/*.patch + mkdir build && cd build + cmake -DCMAKE_BUILD_TYPE=Release .. + cmake --build . --config Release + cp src/vm-manager /usr/bin/ + cd $CIV_WORK_DIR rm -rf vm_manager/ } function install_vm_manager() { sudo apt-get update sudo apt-get install --yes libglib2.0-dev libncurses-dev libuuid1 uuid-dev libjson-c-dev wget lsb-release git - install_vm_manager_deb || install_vm_manager_src + install_vm_manager_src if [ "$?" -ne 0 ]; then echo "Failed to install vm-manager!" echo "Please download and install mannually from: https://github.com/projectceladon/vm_manager/releases/latest" @@ -258,40 +201,20 @@ function install_vm_manager() { } function ubu_enable_host_gvt(){ - if [[ ! `cat /etc/default/grub` =~ "i915.enable_gvt=1 intel_iommu=on i915.force_probe=*" ]]; then - read -p "The grub entry in '/etc/default/grub' will be updated for enabling GVT-g and GVT-d, do you want to continue? [Y/n]" res - if [ x$res = xn ]; then - exit 0 - fi - sed -i "s/GRUB_CMDLINE_LINUX=\"/GRUB_CMDLINE_LINUX=\"i915.enable_gvt=1 intel_iommu=on i915.force_probe=*/g" /etc/default/grub - update-grub - echo -e "\nkvmgt\nvfio-iommu-type1\nvfio-mdev\n" >> /etc/initramfs-tools/modules - update-initramfs -u -k all + if [[ ! `cat /etc/default/grub` =~ "i915.enable_guc="(0x)?0*"7" ]] && + [[ ! `cat /etc/default/grub` =~ "i915.enable_gvt=1" ]]; then - reboot_required=1 - fi -} - -function ubu_enable_host_sriov(){ - if [[ ! `cat /etc/default/grub` =~ "i915.enable_guc=0x7" ]]; then - read -p "The grub entry in '/etc/default/grub' will be updated for enabling SRIOV, do you want to continue? [Y/n]" res - if [ x$res = xn ]; then - exit 0 + if [[ ! `cat /etc/default/grub` =~ "intel_iommu=on i915.force_probe=*" ]]; then + sed -i "s/GRUB_CMDLINE_LINUX=\"/GRUB_CMDLINE_LINUX=\"intel_iommu=on i915.force_probe=* /g" /etc/default/grub fi - sed -i "s/GRUB_CMDLINE_LINUX=\"/GRUB_CMDLINE_LINUX=\"i915.enable_guc=0x7 udmabuf.list_limit=8192 /g" /etc/default/grub + sed -i "s/GRUB_CMDLINE_LINUX=\"/GRUB_CMDLINE_LINUX=\"i915.enable_gvt=1 /g" /etc/default/grub update-grub echo -e "\nkvmgt\nvfio-iommu-type1\nvfio-mdev\n" >> /etc/initramfs-tools/modules update-initramfs -u -k all - # Switch to Xorg for Ubuntu 21.04 - if [[ $(lsb_release -rs) == "21.04" ]]; then - sed -i "s/\#WaylandEnable=false/WaylandEnable=false/g" /etc/gdm3/custom.conf - fi - reboot_required=1 - fi } @@ -320,6 +243,11 @@ function ubu_update_fw(){ reboot_required=1 } +function setup_remote_infer() { + $CIV_WORK_DIR/scripts/setup_rinfer_host.sh + reboot_required=1 +} + function check_os() { local version=`cat /proc/version` @@ -330,6 +258,17 @@ function check_os() { } function check_network(){ + #Check if you are able to access external website without actually downloading it + wget --timeout=3 --tries=1 -q --spider https://github.com + if [ $? -ne 0 ]; then + echo "access https://github.com failed!" + echo "please make sure network is working" + return -1 + fi +} + +#Check Connection specifically with qemu network only if QEMU_REL.tar.xz needs to be downloaded as it doesnt exist in QEMU_CACHE_DIR +function check_qemu_network(){ wget --timeout=3 --tries=1 https://download.qemu.org/ -q -O /dev/null if [ $? -ne 0 ]; then echo "access https://download.qemu.org failed!" @@ -349,14 +288,28 @@ function check_kernel_version() { fi } +function check_sriov_setup() { + input="$CIV_WORK_DIR/sriov_setup_ubuntu.log" + sriov_setup_success=0 + + if [ -f "$input" ]; then + while read -r line + do + if [[ $line == "Success" ]]; then + sriov_setup_success=1 + fi + done < "$input" + fi + + if [ $sriov_setup_success == 0 ]; then + echo "E: Please ensure SRIOV has been setup successfully first" + exit + fi +} + function ask_reboot(){ if [ $reboot_required -eq 1 ];then - read -p "Reboot is required, do you want to reboot it NOW? [y/N]" res - if [ x$res = xy ]; then - reboot - else - echo "Please reboot system later to take effect" - fi + echo "Please reboot system to take effect" fi } @@ -467,33 +420,35 @@ function setup_sof() { } function ubu_install_swtpm() { - TPMS_VER=v0.9.0 - TPMS_LIB=libtpms-0.9.0 - SWTPM_VER=v0.7.0 - SWTPM=swtpm-0.7.0 - - #install libtpms - apt-get -y install automake autoconf gawk - [ ! -f $TPMS_VER.tar.gz ] && wget https://github.com/stefanberger/libtpms/archive/$TPMS_VER.tar.gz -P $CIV_WORK_DIR - [ -d $CIV_WORK_DIR/$TPMS_LIB ] && rm -rf $CIV_WORK_DIR/$TPMS_LIB - tar zxvf $CIV_WORK_DIR/$TPMS_VER.tar.gz - cd $CIV_WORK_DIR/$TPMS_LIB - ./autogen.sh --with-tpm2 --with-openssl --prefix=/usr - make -j24 - make -j24 check - make install - cd - + #install libtpms and swtpm + sudo apt-get -y install libtpms-dev swtpm + + #update apparmor profile usr.bin.swtpm + sed -i "s/#include /include /g" /etc/apparmor.d/usr.bin.swtpm + sed -i "s/#include /include /g" /etc/apparmor.d/usr.bin.swtpm + sed -i "s/#include /include \n include /g" /etc/apparmor.d/usr.bin.swtpm + sed -i "s/#include /include /g" /etc/apparmor.d/usr.bin.swtpm + + #update local apparmor profile usr.bin.swtpm + local_swtpm_profile=("owner /home/**/vtpm0/.lock wk," + "owner /home/**/vtpm0/swtpm-sock w," + "owner /home/**/vtpm0/TMP2-00.permall rw," + "owner /home/**/vtpm0/tpm2-00.permall rw,") + + for rule in "${local_swtpm_profile[@]}"; do + if [[ ! `cat /etc/apparmor.d/local/usr.bin.swtpm` =~ "$rule" ]]; then + echo -e "$rule" | sudo tee -a /etc/apparmor.d/local/usr.bin.swtpm + fi + done + #load profile + sudo apparmor_parser -r /etc/apparmor.d/usr.bin.swtpm - #install swtpm - apt-get -y install net-tools libseccomp-dev libtasn1-6-dev libgnutls28-dev expect libjson-glib-dev - [ ! -f $SWTPM_VER.tar.gz ] && wget https://github.com/stefanberger/swtpm/archive/$SWTPM_VER.tar.gz -P $CIV_WORK_DIR - [ -d $CIV_WORK_DIR/$SWTPM ] && rm -rf $CIV_WORK_DIR/$SWTPM - tar zxvf $CIV_WORK_DIR/$SWTPM_VER.tar.gz - cd $CIV_WORK_DIR/$SWTPM - ./autogen.sh --with-openssl --prefix=/usr - make -j24 - make install - cd - +} + +function ubu_install_libssl() { + sudo add-apt-repository -y 'deb http://security.ubuntu.com/ubuntu focal-security main' + sudo apt-get -y install libssl1.1 + sudo add-apt-repository -y --remove 'deb http://security.ubuntu.com/ubuntu focal-security main' } function ubu_update_bt_fw() { @@ -552,23 +507,27 @@ function ubu_update_wifi_fw(){ function set_sleep_inhibitor() { sudo apt-get -y install python3-pip - sudo pip3 install -U sleep-inhibitor - sudo sed -i 's/\/usr\/bin\/%p/\/usr\/local\/bin\/%p/' /usr/local/share/sleep-inhibitor/sleep-inhibitor.service + sudo apt install -y pipx + pipx ensurepath + sudo pipx install sleep-inhibitor + + pythonversion="$(pip3 --version | grep -Po '^.*\(\K[^\)]*' | grep -Po '^.*\ \K[^\\n]*')" + sudo sed -i 's/\/usr\/bin\/%p/\/usr\/local\/bin\/%p/' /root/.local/share/pipx/venvs/sleep-inhibitor/lib/python$pythonversion/site-packages/sleep_inhibitor/sleep-inhibitor.service #Download the plugin if not already sudo echo "#! /bin/sh if adb get-state 1>/dev/null 2>&1 then state=\$(adb shell dumpsys power | grep -oE 'WAKE_LOCK') - if echo \"\$state\" | grep 'WAKE_LOCK'; then + if echo \"\$state\" | grep 'WAKE_LOCK'; then exit 254 else exit 0 fi else exit 0 -fi" > /usr/local/share/sleep-inhibitor/plugins/is-wakelock-active - sudo chmod a+x /usr/local/share/sleep-inhibitor/plugins/is-wakelock-active - sudo cp /usr/local/share/sleep-inhibitor/sleep-inhibitor.conf /etc/. +fi" > /root/.local/share/pipx/venvs/sleep-inhibitor/lib/python$pythonversion/site-packages/sleep_inhibitor/plugins/is-wakelock-active + sudo chmod a+x /root/.local/share/pipx/venvs/sleep-inhibitor/lib/python$pythonversion/site-packages/sleep_inhibitor/plugins/is-wakelock-active + sudo cp /root/.local/share/pipx/venvs/sleep-inhibitor/lib/python$pythonversion/site-packages/sleep_inhibitor/sleep-inhibitor.conf /etc/. sudo echo "plugins: #Inhibit sleep if wakelock is held - path: is-wakelock-active @@ -576,7 +535,7 @@ fi" > /usr/local/share/sleep-inhibitor/plugins/is-wakelock-active what: sleep period: 0.01" > /etc/sleep-inhibitor.conf sudo sed -i 's/#*HandleSuspendKey=\w*/HandleSuspendKey=suspend/' /etc/systemd/logind.conf - sudo cp /usr/local/share/sleep-inhibitor/sleep-inhibitor.service /etc/systemd/system/. + sudo cp /root/.local/share/pipx/venvs/sleep-inhibitor/lib/python$pythonversion/site-packages/sleep_inhibitor/sleep-inhibitor.service /etc/systemd/system/. reboot_required=1 } @@ -586,6 +545,7 @@ function show_help() { printf "\t-h show this help message\n" printf "\t-u specify Host OS's UI, support \"headless\" and \"GUI\" eg. \"-u headless\" or \"-u GUI\"\n" printf "\t--auto-start auto start CiV guest when Host boot up.\n" + printf "\t-i enable remote inferencing\n" } function parse_arg() { @@ -611,15 +571,28 @@ function parse_arg() { shift ;; + -n) + VM_NAME=$2 + shift + ;; + -t) start_thermal_daemon || return -1 ;; + -i) + setup_remote_infer || return -1 + ;; + --auto-start) install_auto_start_service "$2" || return -1 shift ;; + --bsp) + skip_install_qemu=true + ;; + -?*) echo "Error: Invalid option $1" show_help @@ -634,6 +607,41 @@ function parse_arg() { done } +function setup_civ_ini() { + $CIV_WORK_DIR/scripts/setup_civ_ini.sh -v $1 -p $2 -n $3 +} + +function create_vm_dir() { + if [ -d $CIV_WORK_DIR/$VM_NAME ] + then + echo "Folder with name $VM_NAME already present. Delete and create new folder? Please enter yes/no" + read input + if [ $input = "yes" ]; then + rm -rf $CIV_WORK_DIR/$VM_NAME + else + exit + fi + fi + echo "Creating Dir: $CIV_WORK_DIR/$VM_NAME" + mkdir $CIV_WORK_DIR/$VM_NAME +} + +function copy_files_for_vm() { + echo "Copying file: $CIV_WORK_DIR/$VM_NAME" + mkdir -p $CIV_WORK_DIR/$VM_NAME/scripts/aaf + + req_files=("$CIV_WORK_DIR/OVMF.fd" + "$CIV_WORK_DIR/scripts/rpmb_dev") + for file in ${req_files[@]}; do + if [ ! -f $file ]; then + echo "Error: $file file is missing" + exit -1 + fi + done + + cp $CIV_WORK_DIR/OVMF.fd $CIV_WORK_DIR/$VM_NAME/ + cp $CIV_WORK_DIR/scripts/rpmb_dev $CIV_WORK_DIR/$VM_NAME/scripts/ +} #------------- main processes ------------- @@ -644,21 +652,21 @@ parse_arg "$@" check_os check_network check_kernel_version +check_sriov_setup ubu_changes_require -install_host_service -install_virtual_camera - ubu_install_qemu_gvt ubu_build_ovmf_gvt ubu_enable_host_gvt -ubu_enable_host_sriov -ubu_update_fw - install_vm_manager +create_vm_dir +setup_civ_ini $VSOCK_ID $ADB_PORT $VM_NAME +copy_files_for_vm + prepare_required_scripts ubu_install_swtpm +ubu_install_libssl ubu_update_bt_fw set_sleep_inhibitor diff --git a/scripts/setup_multi_civ_vm.sh b/scripts/setup_multi_civ_vm.sh new file mode 100755 index 0000000..3b5b14e --- /dev/null +++ b/scripts/setup_multi_civ_vm.sh @@ -0,0 +1,137 @@ +#!/bin/bash + +# Copyright (c) 2023 Intel Corporation. +# All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 + +set -eE + +#--------- Global variable ------------------- +CIV_DIR=$(pwd) +USER_HOME=$(getent passwd $SUDO_USER | cut -d: -f6) +VM_NAME=Android-CIV +NUMBER_OF_VM=1 +ADB_PORT=5555 +INITIAL_VM_NUM=1 +SETUP_HOST_DONE=false + +function copy_files_for_vm_flashing() { + mkdir -p $CIV_DIR/$3/scripts/aaf + + req_files=("$CIV_DIR/OVMF.fd" + "$CIV_DIR/scripts/rpmb_dev") + for file in ${req_files[@]}; do + if [ ! -f $file ]; then + echo "Error: $file file is missing" + exit -1 + fi + done + + cp $CIV_DIR/OVMF.fd $CIV_DIR/$3/ + cp $CIV_DIR/scripts/rpmb_dev $CIV_DIR/$3/scripts/ +} + +function create_vm_dirs() { + mkdir $CIV_DIR/$3 + $CIV_DIR/scripts/setup_civ_ini.sh -v $1 -p $2 -n $3 +} + + +function create_vms() { + create_vm_dirs $1 $2 $3 + copy_files_for_vm_flashing $1 $2 $3 +} + +function setup_files() { + echo "Creating setup for VMs" + if [ -d $USER_HOME/.intel/.civ ] + then + SETUP_HOST_DONE=true + fi + + new_dir=$CIV_DIR/$VM_NAME + if [ -n "$(ls -d ${new_dir}? 2> /dev/null )" ]; then + dir_arr=$(ls -d ${new_dir}?) + directories=( $dir_arr ) + last_vm=${directories[-1]} + final_vm_name="${last_vm##*/}" + last_character=${final_vm_name: -1} + last_character=$((last_character+1)) + INITIAL_VM_NUM=$last_character + fi + + for (( i=$INITIAL_VM_NUM; i<$NUMBER_OF_VM+$INITIAL_VM_NUM; i++ )) + do + if [ $SETUP_HOST_DONE = false ]; then + echo "Error: Please ensure setup_host.sh has been run successfully first" + exit -1 + else + create_vms $((i+2)) $((ADB_PORT+((i-1)*2))) ${VM_NAME}${i} + fi + done +} + +function copy_files_for_vm() { + if [ -f "$CIV_DIR/$VM_NAME$INITIAL_VM_NUM/android.qcow2" ]; then + cp $CIV_DIR/$VM_NAME$INITIAL_VM_NUM/android.qcow2 $CIV_DIR/$VM_NAME$1 + else + echo "android.qcow2 missing. Please run setup_host.sh, start_flash_usb.sh and try again" + exit + fi + + if [ -d "$CIV_DIR/$VM_NAME$INITIAL_VM_NUM/vtpm0" ]; then + cp -r $CIV_DIR/$VM_NAME$INITIAL_VM_NUM/vtpm0 $CIV_DIR/$VM_NAME$1 + else + echo "vtpm0 missing. Please run setup_host.sh, start_flash_usb.sh and try again" + exit + fi +} + +function flash_vms() { + echo "Flashing VMs" + if [ -f caas-flashfiles-*.zip ]; then + ./scripts/start_flash_usb.sh caas-flashfiles-*.zip --display-off -n $VM_NAME$INITIAL_VM_NUM + else + echo "flashfiles missing. Please download and unzip the package correctly." + exit -1 + fi + + for (( i=$INITIAL_VM_NUM+1; i<$NUMBER_OF_VM+$INITIAL_VM_NUM; i++ )) + do + copy_files_for_vm $i + echo "Flashed ${VM_NAME}${i}" + done +} + +function show_help() { + printf "Creates CIV guests under folder Android-CIVx, where x is the guest number.\n" + printf "Usage: \n" + printf "$(basename "$0") [-c] \n" + printf "Options:\n" + printf "\t-h show this help message\n" + printf "\t-c specify number of Android guests to be newly created. Default is 1.\n" +} + +function parse_args() { + while [[ $# -gt 0 ]]; do + case $1 in + -c) + NUMBER_OF_VM=$2 + shift + ;; + + -h|-\?|--help) + show_help + exit + ;; + + esac + shift + done +} + +parse_args "$@" +setup_files +flash_vms +echo "Done: \"$(realpath $0) $@\"" diff --git a/scripts/start_flash_usb.sh b/scripts/start_flash_usb.sh index df2f88d..7e78ab7 100755 --- a/scripts/start_flash_usb.sh +++ b/scripts/start_flash_usb.sh @@ -5,9 +5,23 @@ # # SPDX-License-Identifier: Apache-2.0 -WORK_DIR=$PWD +WORK_DIR=$PWD/Android-CIV1 -[ $# -lt 1 ] && echo "Usage: $0 caas-flashfiles-eng-.zip" && exit -1 +function parse_args() { + while [[ $# -gt 0 ]]; do + case $1 in + -n) + WORK_DIR=$PWD/$2 + shift + ;; + esac + shift + done +} + +parse_args "$@" + +[ $# -lt 1 ] && echo "Usage: $0 [caas-flashfiles-.zip] [caas-flashfile-.iso] [caas-flashfile-.iso.zip]" && exit -1 if [ -f android.qcow2 ] then @@ -36,30 +50,39 @@ done if [ "$support_dedicated_data" = true ] then - qemu-img create -f qcow2 android.qcow2 8500M + qemu-img create -f qcow2 $WORK_DIR/android.qcow2 8500M else - qemu-img create -f qcow2 android.qcow2 32G + qemu-img create -f qcow2 $WORK_DIR/android.qcow2 32G fi -[ -d "./flashfiles_decompress" ] && rm -rf "./flashfiles_decompress" -mkdir ./flashfiles_decompress -unzip $1 -d ./flashfiles_decompress - -G_size=$((1<<32)) -for i in `ls ./flashfiles_decompress`;do - if [ -f "./flashfiles_decompress/"$i ] && [ "`grep $i ./flashfiles_decompress/installer.cmd`" ]; then - size=$(stat -c %s "./flashfiles_decompress/"$i) - if [[ $size -gt $G_size ]]; then - echo "Split $i due to its size bigger than 4G\n" - split --bytes=$((G_size-1)) --numeric-suffixes "./flashfiles_decompress/"$i "./flashfiles_decompress/"$i.part - rm "./flashfiles_decompress/"$i - fi - fi -done +decompress=flashfiles_decompress +zip_file=$(file $1 | grep -i "Zip archive data") +if [[ $zip_file != "" ]]; then + rm -rf "$decompress" && mkdir $decompress + unzip $1 -d $decompress -dd if=/dev/zero of=./flash.vfat bs=63M count=160 -mkfs.vfat ./flash.vfat -mcopy -i flash.vfat flashfiles_decompress/* :: + if [[ -f $decompress/boot.img ]]; then + G_size=$((1<<32)) + for i in `ls $decompress`; do + size=$(stat -c %s "$decompress/"$i) + if [[ $size -gt $G_size ]]; then + echo "Split $i due to its size bigger than 4G" + split --bytes=$((G_size-1)) --numeric-suffixes "$decompress/"$i "$decompress/"$i.part + rm "$decompress/"$i + fi + done + + dd if=/dev/zero of=./flash.vfat bs=63M count=160 + mkfs.vfat ./flash.vfat + mcopy -i flash.vfat $decompress/* :: + + virt_disk=flash.vfat + else + virt_disk=$decompress/`ls $decompress` + fi +else + virt_disk=$1 +fi if [ "$support_dedicated_data" = true ] then @@ -90,10 +113,10 @@ qemu-system-x86_64 \ -chardev socket,id=charserial0,path=./kernel-console,server=on,wait=off \ -device isa-serial,chardev=charserial0,id=serial0 \ -device qemu-xhci,id=xhci,addr=0x5 \ - -drive file=./flash.vfat,id=udisk1,format=raw,if=none \ + -drive file=$virt_disk,id=udisk1,format=raw,if=none \ -device usb-storage,drive=udisk1,bus=xhci.0 \ -device virtio-scsi-pci,id=scsi0,addr=0x8 \ - -drive file=./android.qcow2,if=none,format=qcow2,id=scsidisk1 \ + -drive file=$WORK_DIR/android.qcow2,if=none,format=qcow2,id=scsidisk1 \ -device scsi-hd,drive=scsidisk1,bus=scsi0.0 \ -drive file=$ovmf_file,format=raw,if=pflash \ -no-reboot \ @@ -103,4 +126,14 @@ qemu-system-x86_64 \ -tpmdev emulator,id=tpm0,chardev=chrtpm \ -device tpm-crb,tpmdev=tpm0 \ +if [ -f $WORK_DIR/../OVMF.fd ] ; then + if [ "$(md5sum $WORK_DIR/../OVMF.fd|awk '{print $1}')" != "$(md5sum $WORK_DIR/OVMF.fd|awk '{print $1}')" ]; then + cp $WORK_DIR/../OVMF.fd $WORK_DIR/ + else + echo "CheckSum matches skipping" + fi +else + echo "Error OVMF.fd file is missing" +fi + echo "Flashing is completed" diff --git a/src/guest/aaf.c b/src/guest/aaf.c index c76bcbf..a1c4eb2 100644 --- a/src/guest/aaf.c +++ b/src/guest/aaf.c @@ -25,7 +25,8 @@ static const char *gpu_type[] = { [AAF_GPU_TYPE_VIRTIO] = "gpu-type:virtio", [AAF_GPU_TYPE_GVTG] = "gpu-type:gvtg", - [AAF_GPU_TYPE_GVTD] = "gpu-type:gvtd" + [AAF_GPU_TYPE_GVTD] = "gpu-type:gvtd", + [AAF_GPU_TYPE_SRIOV] = "gpu-type:sriov" }; static const char *suspend_support[] = { @@ -111,7 +112,7 @@ int set_aaf_option(aaf_config_opt_t opt, unsigned int sub) aaf_config_array[AAF_CONFIG_AUDIO] = audio_type[sub]; break; case AAF_CONFIG_GPU_TYPE: - if (sub > AAF_GPU_TYPE_GVTD) + if (sub > AAF_GPU_TYPE_SRIOV) return -1; aaf_config_array[AAF_CONFIG_GPU_TYPE] = gpu_type[sub]; break; diff --git a/src/guest/flash.c b/src/guest/flash.c index e1874eb..bc53f4c 100644 --- a/src/guest/flash.c +++ b/src/guest/flash.c @@ -110,7 +110,7 @@ static int create_vusb(GKeyFile *gkf) } snprintf(cmd, MAX_CMDLINE_LEN, "dd if=/dev/zero of="VUSB_FLASH_DISK" bs=%ld count=%ld", - DD_BS, (total_images_size + DD_BS - 1)/DD_BS); + DD_BS, (total_images_size + DD_BS + 2 GIGABYTE - 1)/DD_BS); printf("%s\n", cmd); if (system(cmd)) return -1; diff --git a/src/guest/guest.c b/src/guest/guest.c index 4d2bcf4..2cc8e68 100644 --- a/src/guest/guest.c +++ b/src/guest/guest.c @@ -32,7 +32,7 @@ keyfile_group_t g_group[] = { { "vtpm", { "bin_path", "data_dir", NULL } }, { "rpmb", { "bin_path", "data_dir", NULL } }, { "passthrough", { "passthrough_pci", NULL}}, - { "mediation", { "battery_med", "thermal_med", "camera_med",NULL }}, + { "mediation", { "battery_med", "thermal_med", NULL }}, { "aaf", { "path", "support_suspend", "audio_type", NULL } }, { "guest_control", { "time_keep", "pm_control", NULL }}, { "extra", { "cmd", "service", NULL } }, diff --git a/src/guest/start.c b/src/guest/start.c index 2f05c19..df1e9e4 100644 --- a/src/guest/start.c +++ b/src/guest/start.c @@ -63,6 +63,8 @@ static int get_uid() { #define PT_LEN 16 static char *pci_pt_record[PT_MAX] = { 0 }; static int pci_count = 0; +static int MAX_NUM_GUEST = 7; +static char qmp_pwr_socket[MAX_PATH] = { 0 }; static int create_vgpu(GKeyFile *gkf) { @@ -373,10 +375,11 @@ static int setup_hugepages(GKeyFile *gkf) static int set_available_vf(void) { int fd = 0; - int total_vfs = 0; + int total_vfs = 0, numvfs = 0; int dev_id = 0; ssize_t n = 0; char buf[64] = { 0 }; + char timeout_file[64] = { 0 }; int i; int ret = 0; @@ -404,63 +407,97 @@ static int set_available_vf(void) } close(fd); total_vfs = strtoul(buf, NULL, 10); - /* Limit total VFs to conserve memory */ - total_vfs = total_vfs > 4 ? 4 : total_vfs; - memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf), "%d", total_vfs); - - if (write_to_file(INTEL_GPU_DEV_PATH"/sriov_drivers_autoprobe", "0")) { - fprintf(stderr, "Unable to de-probe sriov drivers"); + if (total_vfs == 0) { + fprintf(stderr, "Error: total number of supported VFs is 0"); return -1; } - if (write_to_file("/sys/class/drm/card0/device/sriov_numvfs", buf)) { - fprintf(stderr, "Unable to de-probe sriov drivers"); - return -1; - } + fd = open("/sys/class/drm/card0/device/sriov_numvfs", O_RDONLY); + if (fd == -1) { + fprintf(stderr, "open /sys/class/drm/card0/device/sriov_numvfs, errno=%d\n", errno); + return 0; + } - if (write_to_file(INTEL_GPU_DEV_PATH"/sriov_drivers_autoprobe", "1")) { - fprintf(stderr, "Unable to auto-probe sriov drivers"); - return -1; - } + n = read(fd, buf, sizeof(buf)); + if (n == -1) { + fprintf(stderr, "read /sys/class/drm/card0/device//sriov_numvfs failed, errno=%d\n", errno); + close(fd); + return 0; + } + close(fd); + numvfs = strtoul(buf, NULL, 10); - /* Get device ID */ - fd = open(INTEL_GPU_DEV_PATH"/device", O_RDONLY); - if (fd == -1) { - fprintf(stderr, "open %s failed, errno=%d\n", INTEL_GPU_DEV_PATH"/device", errno); - return -1; - } + if (numvfs == 0) { + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf), "%d", total_vfs); - n = read(fd, buf, sizeof(buf)); - if (n == -1) { - fprintf(stderr, "read %s failed, errno=%d\n", INTEL_GPU_DEV_PATH"/device", errno); - close(fd); - return -1; - } - close(fd); - dev_id = strtol(buf, NULL, 16); + if (write_to_file(INTEL_GPU_DEV_PATH"/sriov_drivers_autoprobe", "0")) { + fprintf(stderr, "Unable to de-probe sriov drivers"); + return -1; + } + if (write_to_file("/sys/class/drm/card0/device/sriov_numvfs", buf)) { + fprintf(stderr, "Unable to de-probe sriov drivers"); + return -1; + } - memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf), "8086 %x", dev_id); + if (write_to_file(INTEL_GPU_DEV_PATH"/sriov_drivers_autoprobe", "1")) { + fprintf(stderr, "Unable to auto-probe sriov drivers"); + return -1; + } - /* Create new vfio id for GPU */ - ret = write_to_file(PCI_DRIVER_PATH"vfio-pci/new_id", buf); - if (ret == EEXIST) { - if (write_to_file("/sys/bus/pci/drivers/vfio-pci/remove_id", buf)) { - fprintf(stderr, "Cannot remove original GPU vfio id\n"); + /* Get device ID */ + fd = open(INTEL_GPU_DEV_PATH"/device", O_RDONLY); + if (fd == -1) { + fprintf(stderr, "open %s failed, errno=%d\n", INTEL_GPU_DEV_PATH"/device", errno); return -1; } - if (write_to_file(PCI_DRIVER_PATH"vfio-pci/new_id", buf)) { - fprintf(stderr, "Cannot add new GPU vfio id\n"); + + n = read(fd, buf, sizeof(buf)); + if (n == -1) { + fprintf(stderr, "read %s failed, errno=%d\n", INTEL_GPU_DEV_PATH"/device", errno); + close(fd); + return -1; + } + close(fd); + dev_id = strtol(buf, NULL, 16); + + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf), "8086 %x", dev_id); + + /* Create new vfio id for GPU */ + ret = write_to_file(PCI_DRIVER_PATH"vfio-pci/new_id", buf); + if (ret == EEXIST) { + if (write_to_file("/sys/bus/pci/drivers/vfio-pci/remove_id", buf)) { + fprintf(stderr, "Cannot remove original GPU vfio id\n"); + return -1; + } + if (write_to_file(PCI_DRIVER_PATH"vfio-pci/new_id", buf)) { + fprintf(stderr, "Cannot add new GPU vfio id\n"); + return -1; + } + } else if (ret != 0) { return -1; } - } else if (ret != 0) { - return -1; } - for (i = 1; i < total_vfs; i++) { + fd = open("/sys/class/drm/card0/device/sriov_numvfs", O_RDONLY); + if (fd == -1) { + fprintf(stderr, "open /sys/class/drm/card0/device/sriov_numvfs, errno=%d\n", errno); + return 0; + } + + n = read(fd, buf, sizeof(buf)); + if (n == -1) { + fprintf(stderr, "read /sys/class/drm/card0/device//sriov_numvfs failed, errno=%d\n", errno); + close(fd); + return 0; + } + close(fd); + numvfs = strtoul(buf, NULL, 10); + + for (i = 1; i < numvfs; i++) { memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf), "/sys/bus/pci/devices/0000:00:02.%d/enable", i); fd = open(buf, O_RDONLY); @@ -478,6 +515,13 @@ static int set_available_vf(void) } close(fd); if (strtol(buf, NULL, 10) == 0) { + //Configure timeout values + snprintf(timeout_file, sizeof(timeout_file), "/sys/class/drm/card0/iov/vf%d/gt/preempt_timeout_us", i); + snprintf(buf, sizeof(buf), "%d", 50000); + write_to_file(timeout_file, buf); + snprintf(timeout_file, sizeof(timeout_file), "/sys/class/drm/card0/iov/vf%d/gt/exec_quantum_ms", i); + snprintf(buf, sizeof(buf), "%d", 25); + write_to_file(timeout_file, buf); return i; } } @@ -552,6 +596,13 @@ static void cleanup_passthrough(void) { } } +static void cleanup_pwr_ctrl() { + //cleanup qmp power control socket on exit + if(access(qmp_pwr_socket, F_OK) == 0) { + remove(qmp_pwr_socket); + } +} + static int check_soundcard_on_host(){ int ret = system("cat /proc/asound/cards | grep sof"); return ret; @@ -570,6 +621,7 @@ static void cleanup(int num, int removed_sof_tgl_snd_module) cleanup_child_proc(); cleanup_rpmb(); cleanup_passthrough(); + cleanup_pwr_ctrl(); if(removed_sof_tgl_snd_module) insert_sof_tgl_snd_module(); @@ -761,10 +813,6 @@ static int run_thermal_mediation_daemon(char *path) { return execute_cmd(path, NULL, 0, 1); } -static int run_camera_mediation_daemon(char *path) { - return execute_cmd(path, NULL, 0, 1); -} - static int run_guest_timekeep(char *path, char *p, size_t size, char *pipe_name) { int cx = 0; const char *pipe = pipe_name ? pipe_name : "qmp-time-keep-pipe"; @@ -856,6 +904,25 @@ static void strip_duplicate(gchar *val, const gchar *inner_cmd) g_free(to_split); } +static void set_pwr_ctrl(char * qmp_cmd) { + for(int avail = 0; avail < MAX_NUM_GUEST; avail++) { + char *num; + asprintf(&num, "%d", avail); + strcpy(qmp_pwr_socket, "/tmp/qmp-pwr-socket-"); + if (strlen(num) < (sizeof(qmp_pwr_socket) - strlen(qmp_pwr_socket))) { + strncat(qmp_pwr_socket, num, (sizeof(qmp_pwr_socket) - strlen(num) -1)); + } + if(access(qmp_pwr_socket, F_OK) != 0) { + snprintf(qmp_cmd, MAX_CMDLINE_LEN, " -qmp unix:%s,%s", qmp_pwr_socket, "server,nowait"); + break; + } + } + if (strcmp(qmp_cmd, "") == 0) { + printf("E: No power control socket available"); + exit(1); + } +} + int start_guest(char *name) { int ret = 0; @@ -906,6 +973,11 @@ int start_guest(char *name) cx = snprintf(p, size, " -qmp unix:%s/.%s"CIV_GUEST_QMP_SUFFIX",server,nowait", civ_config_path, qname); p += cx; size -= cx; + char qmp_sock[MAX_CMDLINE_LEN] = { 0 }; + set_pwr_ctrl(qmp_sock); + cx = snprintf(p, size, "%s", qmp_sock); + p += cx; size -= cx; + val = g_key_file_get_string(gkf, g->name, g->key[GLOB_VSOCK_CID], NULL); if (val) { cx = snprintf(p, size, " -device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=%s,bus=pcie.0,addr=0x4", val); @@ -1036,7 +1108,7 @@ int start_guest(char *name) } else if (strcmp(val, VGPU_OPTS_SRIOV_STR) == 0) { if (setup_sriov(gkf, &p, &size)) return -1; - set_aaf_option(AAF_CONFIG_GPU_TYPE, AAF_GPU_TYPE_VIRTIO); + set_aaf_option(AAF_CONFIG_GPU_TYPE, AAF_GPU_TYPE_SRIOV); } else { g_warning("Invalid Graphics config\n"); return -1; @@ -1157,11 +1229,6 @@ int start_guest(char *name) if (val != NULL && (strcmp("", val) != 0)) run_thermal_mediation_daemon(val); - val = g_key_file_get_string(gkf, g->name, g->key[CAMERA_MED], NULL); - if (val != NULL && (strcasecmp("y", val) == 0)) { - run_camera_mediation_daemon("/usr/local/bin/stream"); - } - /* run guest pm */ g = &g_group[GROUP_GUEST_SERVICE]; @@ -1211,7 +1278,7 @@ int start_guest(char *name) cx = snprintf(p, size, "%s", fixed_cmd); p += cx; size -= cx; - run_vtpm_daemon(); + run_vtpm_daemon(); cleanup_rpmb(); run_rpmb_daemon(); diff --git a/src/include/guest/aaf.h b/src/include/guest/aaf.h index 4a49dd7..f00510f 100644 --- a/src/include/guest/aaf.h +++ b/src/include/guest/aaf.h @@ -28,7 +28,8 @@ enum { enum { AAF_GPU_TYPE_VIRTIO = 0, AAF_GPU_TYPE_GVTG, - AAF_GPU_TYPE_GVTD + AAF_GPU_TYPE_GVTD, + AAF_GPU_TYPE_SRIOV }; int set_aaf_path(const char *bin_path); diff --git a/src/include/guest/guest.h b/src/include/guest/guest.h index 0165d9a..a943296 100644 --- a/src/include/guest/guest.h +++ b/src/include/guest/guest.h @@ -197,7 +197,6 @@ enum { /* Sub key of group mediation */ BATTERY_MED = 0, THERMAL_MED, - CAMERA_MED, /* Sub key of group aaf */ AAF_PATH = 0, diff --git a/src/vm_manager.c b/src/vm_manager.c index 9410f04..6f22fea 100644 --- a/src/vm_manager.c +++ b/src/vm_manager.c @@ -20,8 +20,8 @@ #include "vm_manager.h" #define VERSION_MAJOR 0 -#define VERSION_MINOR 6 -#define VERSION_MICRO 1 +#define VERSION_MINOR 7 +#define VERSION_MICRO 2 #define VERSION xstr(VERSION_MAJOR)"."xstr(VERSION_MINOR)"."xstr(VERSION_MICRO)