diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2252078
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*.qcow2
+*.img
+initrd*
+uki.efi*
+vmlinuz*
diff --git a/README.md b/README.md
index 9a373ad..4ba9f01 100644
--- a/README.md
+++ b/README.md
@@ -589,6 +589,16 @@ you proceed to [step 4](#verify-itts-client-version).
```
+#### 9.1. Event log and measurements
+
+One of the key components remote attestation is based on is the runtime measurement values (stored in RTMRs
+registers for each TD by the TDX module). These RTMR values are computed from the digests of the entries of
+the TD boot event log.
+
+If you want to inspect the event log and RTMR values, you can use the program `tdeventlog` available in the guest.
+And furthermore, to see how the boot chain can impact the contents and the size of the boot event log, please take a look at
+the [boot methods section](guest-tools/direct-boot/README.md).
+
## 10. Build Packages from Source
diff --git a/guest-tools/direct-boot/README.md b/guest-tools/direct-boot/README.md
new file mode 100644
index 0000000..2beaf8e
--- /dev/null
+++ b/guest-tools/direct-boot/README.md
@@ -0,0 +1,140 @@
+# TD Boot Methods
+
+This folder contains scripts and instructions to boot a TD using the [direct
+boot](https://qemu-project.gitlab.io/qemu/system/linuxboot.html) method.
+
+The direct boot method is an alternative to the boot method that is being used by `tdvirsh`
+to run TDs.
+We will refer to the `tdvirsh` boot method as the `indirect boot` method.
+With the `indirect boot` method, the boot chain involves following components:
+- TDVF (virtual UEFI firmware)
+- SHIM
+- Grub
+- Kernel + Initrd
+
+The `direct boot` will skip `SHIM` and `Grub` in the boot chain by providing the `Kernel`
+and `Initrd` directly to `qemu`. Per consequence, the boot chain involves these components:
+- TDVF (virtual UEFI firmware)
+- Kernel + Initrd
+
+The boot chain structure is important for remote attestation since it impacts the size of
+the event log journal. Indeed, each component in the boot chain generates a set of entries of the event
+log journal. The more components we have in the boot chain, the more event logs we will have and the harder
+is the verification of the correctness of the measurement values.
+
+For `direct boot`, we would like to investigate 2 ways of passing `kernel` and `initrd` to `qemu`:
+- Separately using `-kernel` and `-initrd` arguments
+- Bundled together as part of an [Unified Kernel Image](https://uapi-group.org/specifications/specs/unified_kernel_image/)
+
+### Prerequisites
+
+To later perform direct boot with the two direct boot variants, we need to generate following files:
+
+1. TD Guest Image
+
+The boot scripts need a guest image as the final rootfs to boot into.
+
+To generate this guest image, please refer to the section [Create TD Image](../../README.md#create-td-image).
+
+NOTE: The credentials necessary for login into the TD guest can also be found in this section.
+
+2. Kernel, initrd and UKI
+
+NOTE: the provided instructions are for `24.04` guest.
+ Please replace `24.04` by `24.10` if you want to work with `oracular` TD guest.
+
+```
+$ cd guest-tools/image
+$ ./create-td-uki.sh tdx-guest-ubuntu-24.04-generic.qcow2
+```
+
+This script will generate 3 files:
+- `vmlinuz-24.04` : the kernel of the guest image
+- `initrd.img-24.04` : the initrd of the guest image
+- `uki.efi-24.04` : the Unified Kernel Image that bundles together the kernel and the initrd
+
+### Direct boot
+
+```
+$ cd guest-tools/direct-boot
+$ ./boot_direct.sh 24.04
+```
+
+Once you are in the guest console, you can see the event log journal by:
+
+```
+$ tdeventlog
+```
+
+Example output:
+
+```
+root@tdx-guest:~# tdeventlog
+==== TDX Event Log Entry - 0 [0x7FBEF000] ====
+RTMR : 0
+Type : 3 (EV_NO_ACTION)
+Length : 65
+Algorithms Number : 1
+ Algorithms[0xC] Size: 384
+RAW DATA: ----------------------------------------------
+7FBEF000 01 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 ................
+7FBEF010 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 00 ............!...
+7FBEF020 53 70 65 63 20 49 44 20 45 76 65 6E 74 30 33 00 Spec ID Event03.
+7FBEF030 00 00 00 00 00 02 00 02 01 00 00 00 0C 00 30 00 ..............0.
+7FBEF040 00 .
+RAW DATA: ----------------------------------------------
+
+...
+...
+
+==== TDX Event Log Entry - 19 [0x7FBEF77F] ====
+RTMR : 1
+Type : 0x80000007 (EV_EFI_ACTION)
+Length : 95
+Algorithms ID : 12 (TPM_ALG_SHA384)
+Digest[0] : 214b0bef1379756011344877743fdc2a5382bac6e70362d624ccf3f654407c1b4badf7d8f9295dd3dabdef65b27677e0
+RAW DATA: ----------------------------------------------
+7FBEF77F 02 00 00 00 07 00 00 80 01 00 00 00 0C 00 21 4B ..............!K
+7FBEF78F 0B EF 13 79 75 60 11 34 48 77 74 3F DC 2A 53 82 ...yu`.4Hwt?.*S.
+7FBEF79F BA C6 E7 03 62 D6 24 CC F3 F6 54 40 7C 1B 4B AD ....b.$...T@|.K.
+7FBEF7AF F7 D8 F9 29 5D D3 DA BD EF 65 B2 76 77 E0 1D 00 ...)]....e.vw...
+7FBEF7BF 00 00 45 78 69 74 20 42 6F 6F 74 20 53 65 72 76 ..Exit Boot Serv
+7FBEF7CF 69 63 65 73 20 49 6E 76 6F 63 61 74 69 6F 6E ices Invocation
+RAW DATA: ----------------------------------------------
+
+==== TDX Event Log Entry - 20 [0x7FBEF7DE] ====
+RTMR : 1
+Type : 0x80000007 (EV_EFI_ACTION)
+Length : 106
+Algorithms ID : 12 (TPM_ALG_SHA384)
+Digest[0] : 0a2e01c85deae718a530ad8c6d20a84009babe6c8989269e950d8cf440c6e997695e64d455c4174a652cd080f6230b74
+RAW DATA: ----------------------------------------------
+7FBEF7DE 02 00 00 00 07 00 00 80 01 00 00 00 0C 00 0A 2E ................
+7FBEF7EE 01 C8 5D EA E7 18 A5 30 AD 8C 6D 20 A8 40 09 BA ..]....0..m .@..
+7FBEF7FE BE 6C 89 89 26 9E 95 0D 8C F4 40 C6 E9 97 69 5E .l..&.....@...i^
+7FBEF80E 64 D4 55 C4 17 4A 65 2C D0 80 F6 23 0B 74 28 00 d.U..Je,...#.t(.
+7FBEF81E 00 00 45 78 69 74 20 42 6F 6F 74 20 53 65 72 76 ..Exit Boot Serv
+7FBEF82E 69 63 65 73 20 52 65 74 75 72 6E 65 64 20 77 69 ices Returned wi
+7FBEF83E 74 68 20 53 75 63 63 65 73 73 th Success
+RAW DATA: ----------------------------------------------
+
+
+==== Replayed RTMR values from event log ====
+rtmr_0 : a40d9875d5a7477e2d14201a27fc2aef21d9e6243ffe483262d2212cf518fd249fb0956d5d3ba30e6dca6d839c8e6212
+rtmr_1 : 8584f2ccb76201a023e8dc30ed918e40650fa96fc5c5802d78cda055a1ef8d65a0845d1ced5bb9601ed0060a5bcf8802
+rtmr_2 : 82abbec34b50b6784bd9edc785fdbfd2e49d05acbb0f1ae58c011f057b64bb6532cac5b9146bdb245992118d55d90013
+rtmr_3 : 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+```
+
+### Direct boot with UKI
+
+Another way to do direct boot is to use the [Unified Kernel Image](https://uapi-group.org/specifications/specs/unified_kernel_image/).
+UKI leads to better UEFI Secure Boot support, better supporting TPM measurements and confidential computing, and a more robust boot process.
+
+```
+$ cd guest-tools/direct-boot
+$ ./boot_uki.sh 24.04
+```
+
+Once you are in the guest console, you can see the event log journal by using `tdeventlog` as explained in the previous section.
+
diff --git a/guest-tools/direct-boot/boot_direct.sh b/guest-tools/direct-boot/boot_direct.sh
new file mode 100755
index 0000000..40db710
--- /dev/null
+++ b/guest-tools/direct-boot/boot_direct.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+# This file is part of Canonical's TDX repository which includes tools
+# to setup and configure a confidential computing environment
+# based on Intel TDX technology.
+# See the LICENSE file in the repository for the license text.
+
+# Copyright 2024 Canonical Ltd.
+# SPDX-License-Identifier: GPL-3.0-only
+
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3,
+# as published by the Free Software Foundation.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranties
+# of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+
+UBUNTU_VERSION=$1
+if [[ -z "${UBUNTU_VERSION}" ]]; then
+ echo "Usage: $0 <24.04|24.10>"
+ exit 1
+fi
+
+PROCESS_NAME=td
+TDVF_FIRMWARE=/usr/share/ovmf/OVMF.fd
+
+KERNEL_FILE=$(realpath ${SCRIPT_DIR}/../image/vmlinuz-${UBUNTU_VERSION})
+INITRD_FILE=$(realpath ${SCRIPT_DIR}/../image/initrd.img-${UBUNTU_VERSION})
+TD_IMG=$(realpath ${SCRIPT_DIR}/../image/tdx-guest-ubuntu-${UBUNTU_VERSION}-generic.qcow2)
+
+if [[ ! -f "${KERNEL_FILE}" ]]; then
+ echo "Missing kernel file: ${KERNEL_FILE}
+ You can use guest-tools/image/create-td-uki.sh to generate it"
+ exit 1
+fi
+
+if [[ ! -f "${INITRD_FILE}" ]]; then
+ echo "Missing initrd file: ${INITRD_FILE}
+ You can use guest-tools/image/create-td-uki.sh to generate it"
+ exit 1
+fi
+
+if [[ ! -f "${TD_IMG}" ]]; then
+ echo "Missing guest image file: ${TD_IMG}
+ You can use guest-tools/image/create-td-image.sh to generate it"
+ exit 1
+fi
+
+set -e
+
+qemu-system-x86_64 -accel kvm \
+ -m 2G -smp 16 \
+ -name ${PROCESS_NAME},process=${PROCESS_NAME},debug-threads=on \
+ -cpu host \
+ -object '{"qom-type":"tdx-guest","id":"tdx","quote-generation-socket":{"type": "vsock", "cid":"2","port":"4050"}}' \
+ -machine q35,kernel_irqchip=split,confidential-guest-support=tdx,hpet=off \
+ -bios ${TDVF_FIRMWARE} \
+ -nographic \
+ -nodefaults \
+ -kernel ${KERNEL_FILE} \
+ -initrd ${INITRD_FILE} \
+ -append "root=/dev/sda1 console=ttyS0" \
+ -hda ${TD_IMG} \
+ -serial stdio \
+ -pidfile /tmp/tdx-demo-td-pid.pid
diff --git a/guest-tools/direct-boot/boot_uki.sh b/guest-tools/direct-boot/boot_uki.sh
new file mode 100755
index 0000000..e8d811a
--- /dev/null
+++ b/guest-tools/direct-boot/boot_uki.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+
+# This file is part of Canonical's TDX repository which includes tools
+# to setup and configure a confidential computing environment
+# based on Intel TDX technology.
+# See the LICENSE file in the repository for the license text.
+
+# Copyright 2024 Canonical Ltd.
+# SPDX-License-Identifier: GPL-3.0-only
+
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3,
+# as published by the Free Software Foundation.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranties
+# of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+
+UBUNTU_VERSION=$1
+
+if [[ -z "${UBUNTU_VERSION}" ]]; then
+ echo "Usage: $0 <24.04|24.10>"
+ exit 1
+fi
+
+UKI_FILE=$(realpath ${SCRIPT_DIR}/../image/uki.efi-${UBUNTU_VERSION})
+TD_IMG=$(realpath ${SCRIPT_DIR}/../image/tdx-guest-ubuntu-${UBUNTU_VERSION}-generic.qcow2)
+
+usage() {
+ cat < /dev/null
+
+PROCESS_NAME=td
+TDVF_FIRMWARE=/usr/share/ovmf/OVMF.fd
+ROOTFS_DIR=${SCRIPT_DIR}/uki_rootfs
+
+# sanity check
+if [[ ! -f "${UKI_FILE}" ]] || [[ ! -f "${TD_IMG}" ]]; then
+ usage
+ exit 1
+fi
+
+set -e
+
+# Since the uki kernel is designed to be started by UEFI directly,
+# it has to reside in the EFI partition, because without additional
+# drivers UEFI can only read VFAT.
+mkdir -p ${ROOTFS_DIR}/efi/boot
+cp -f ${UKI_FILE} ${ROOTFS_DIR}/efi/boot/bootx64.efi
+
+qemu-system-x86_64 -accel kvm \
+ -m 2G -smp 16 \
+ -name ${PROCESS_NAME},process=${PROCESS_NAME},debug-threads=on \
+ -cpu host \
+ -object '{"qom-type":"tdx-guest","id":"tdx","quote-generation-socket":{"type": "vsock", "cid":"2","port":"4050"}}' \
+ -machine q35,kernel_irqchip=split,confidential-guest-support=tdx,hpet=off \
+ -bios ${TDVF_FIRMWARE} \
+ -nographic \
+ -nodefaults \
+ -hda fat:rw:${ROOTFS_DIR} \
+ -hdb ${TD_IMG} \
+ -serial stdio \
+ -pidfile /tmp/tdx-demo-td-pid.pid
diff --git a/guest-tools/image/create-td-image.sh b/guest-tools/image/create-td-image.sh
index cec1de7..efa2d0a 100755
--- a/guest-tools/image/create-td-image.sh
+++ b/guest-tools/image/create-td-image.sh
@@ -305,6 +305,7 @@ setup_guest_image() {
--copy-in ${SCRIPT_DIR}/../../setup-tdx-common:/tmp/tdx \
--copy-in ${SCRIPT_DIR}/../../setup-tdx-config:/tmp/tdx \
--copy-in ${SCRIPT_DIR}/../../attestation/:/tmp/tdx \
+ --copy-in ${SCRIPT_DIR}/../../tests/lib/tdx-tools/:/tmp/tdx \
--run-command "/tmp/tdx/setup.sh"
if [ $? -eq 0 ]; then
ok "Run setup scripts inside the guest image"
diff --git a/guest-tools/image/create-td-uki.sh b/guest-tools/image/create-td-uki.sh
new file mode 100755
index 0000000..37717f8
--- /dev/null
+++ b/guest-tools/image/create-td-uki.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+# This file is part of Canonical's TDX repository which includes tools
+# to setup and configure a confidential computing environment
+# based on Intel TDX technology.
+# See the LICENSE file in the repository for the license text.
+
+# Copyright 2024 Canonical Ltd.
+# SPDX-License-Identifier: GPL-3.0-only
+
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3,
+# as published by the Free Software Foundation.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranties
+# of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+
+# This script will create a UKI (Unified Kernel Image) from the guest image
+
+SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
+
+TMP_GUEST_IMG="${SCRIPT_DIR}/tdx-guest-tmp.qcow2"
+TMP_GUEST_FOLDER="${SCRIPT_DIR}/tdx-guest-tmp/"
+
+TD_GUEST_IMG=$1
+if [[ -z "${TD_GUEST_IMG}" ]]; then
+ echo "Usage : $0 "
+ exit 1
+fi
+
+if [ "$EUID" -eq 0 ]
+ then echo "Please do not run as root"
+ exit
+fi
+
+cleanup() {
+ echo "cleanup ..."
+ umount ${TMP_GUEST_FOLDER} &> /dev/null
+ rm -rf ${TMP_GUEST_FOLDER}
+ rm -f ${TMP_GUEST_IMG}
+}
+
+trap "cleanup" EXIT
+
+cleanup
+
+set -e
+
+# create an overlay image with guest image as a backing image
+qemu-img create -f qcow2 -b ${TD_GUEST_IMG} -F qcow2 ${TMP_GUEST_IMG}
+
+# virt-customize does in-place customization and use host kernel
+# we have to give the create-uki script the guest image kernel
+virt-customize -a ${TMP_GUEST_IMG} \
+ --mkdir /tmp/tdx/ \
+ --copy-in ${SCRIPT_DIR}/create-uki.sh:/tmp/tdx/ \
+ --run-command "/tmp/tdx/create-uki.sh"
+
+# retrieve files
+mkdir -p ${TMP_GUEST_FOLDER} && guestmount -a ${TMP_GUEST_IMG} -i --ro ${TMP_GUEST_FOLDER}
+
+cp ${TMP_GUEST_FOLDER}/uki.efi* ./
+cp ${TMP_GUEST_FOLDER}/vmlinuz* ./
+cp ${TMP_GUEST_FOLDER}/initrd* ./
diff --git a/guest-tools/image/create-uki.sh b/guest-tools/image/create-uki.sh
new file mode 100755
index 0000000..18e01f5
--- /dev/null
+++ b/guest-tools/image/create-uki.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+# This file is part of Canonical's TDX repository which includes tools
+# to setup and configure a confidential computing environment
+# based on Intel TDX technology.
+# See the LICENSE file in the repository for the license text.
+
+# Copyright 2024 Canonical Ltd.
+# SPDX-License-Identifier: GPL-3.0-only
+
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3,
+# as published by the Free Software Foundation.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranties
+# of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+
+# This script will create a UKI (Unified Kernel Image) using
+# systemd-ukify, update-initramfs
+
+# if this script is executed with virt-customize, $(uname -r)
+# will give the kernel version on host, so this information
+# we have to look for it from /boot/
+KERNEL_VER=$(find /boot/vmlinuz-*-generic 2>&1 | \
+ /usr/lib/grub/grub-sort-version -r 2>&1 | \
+ gawk 'match($0 , /^\/boot\/vmlinuz-(.*)/, a) {print a[1];exit}')
+
+UBUNTU_VERSION=$(lsb_release -rs)
+
+if [[ -z "${KERNEL_VER}" ]]; then
+ echo "Cannot detect kernel version"
+ exit 1
+fi
+
+echo "Creating the UKI with kernel ${KERNEL_VER}"
+
+# the kernel commandline to put in the UKI
+KERNEL_CMDLINE="console=tty1 console=ttyS0 root=/dev/sdb1"
+
+# use systemd-ukify to generate UKI
+sudo apt install -y systemd-ukify systemd-boot-efi
+
+# use update-initramfs
+# add kernel moules:
+# - tdx_guest
+echo tdx_guest | sudo tee -a /etc/initramfs-tools/modules
+sudo update-initramfs -c -k ${KERNEL_VER}
+
+# copy the initrd
+sudo cp /boot/initrd.img-${KERNEL_VER} initrd.img-${UBUNTU_VERSION}
+
+# copy the kernel
+sudo cp /boot/vmlinuz-${KERNEL_VER} ./vmlinuz-${UBUNTU_VERSION}
+sudo chmod a+rw vmlinuz-${KERNEL_VER}
+
+ukify build --linux=./vmlinuz-${UBUNTU_VERSION} \
+ --cmdline "${KERNEL_CMDLINE}" \
+ --initrd=initrd.img-${UBUNTU_VERSION} \
+ --output uki.efi-${UBUNTU_VERSION} \
+ --os-release '@/etc/os-release' \
+ --uname ${KERNEL_VER}
diff --git a/guest-tools/image/setup.sh b/guest-tools/image/setup.sh
index 59f90b8..b481ba2 100755
--- a/guest-tools/image/setup.sh
+++ b/guest-tools/image/setup.sh
@@ -36,4 +36,8 @@ rm -f /etc/ssh/sshd_config.d/60-cloudimg-settings.conf
# Enable TDX
/tmp/tdx/setup-tdx-guest.sh
+# Install tools
+cd /tmp/tdx/tdx-tools/
+python3 -m pip install --break-system-packages ./
+
rm -rf /tmp/tdx || true