From 589643d12f41bd5d7e6a4d90829acd1f8fb0bf37 Mon Sep 17 00:00:00 2001 From: Srikanth Muppandam Date: Wed, 29 Apr 2026 16:22:24 +0530 Subject: [PATCH] test(system): add EFI variable validation Add a System testcase to validate EFI kernel config, efivar runtime availability, OsTrialBootStatus write and readback, and OsIndicationsSupported attribute and value checks. This helps catch regressions where EFI support is enabled in kernel config but EFI variable access or expected UEFI variable behavior is not functioning correctly on target. Signed-off-by: Srikanth Muppandam --- .../EFI_Variable_Validation.yaml | 15 + .../EFI_Variable_Validation_README.md | 84 ++++++ .../System/EFI_Variable_Validation/run.sh | 274 ++++++++++++++++++ 3 files changed, 373 insertions(+) create mode 100755 Runner/suites/System/EFI_Variable_Validation/EFI_Variable_Validation.yaml create mode 100644 Runner/suites/System/EFI_Variable_Validation/EFI_Variable_Validation_README.md create mode 100755 Runner/suites/System/EFI_Variable_Validation/run.sh diff --git a/Runner/suites/System/EFI_Variable_Validation/EFI_Variable_Validation.yaml b/Runner/suites/System/EFI_Variable_Validation/EFI_Variable_Validation.yaml new file mode 100755 index 00000000..6081b7eb --- /dev/null +++ b/Runner/suites/System/EFI_Variable_Validation/EFI_Variable_Validation.yaml @@ -0,0 +1,15 @@ +metadata: + name: EFI_Variable_Validation + format: Lava-Test Test Definition 1.0 + description: "Validate EFI kernel config, OsTrialBootStatus write read, and OsIndicationsSupported readback" + maintainer: + - "Qualcomm Linux Testkit" + +params: {} + +run: + steps: + - REPO_PATH=$PWD + - cd Runner/suites/System/EFI_Variable_Validation + - ./run.sh || true + - $REPO_PATH/Runner/utils/send-to-lava.sh EFI_Variable_Validation.res diff --git a/Runner/suites/System/EFI_Variable_Validation/EFI_Variable_Validation_README.md b/Runner/suites/System/EFI_Variable_Validation/EFI_Variable_Validation_README.md new file mode 100644 index 00000000..de1edcbb --- /dev/null +++ b/Runner/suites/System/EFI_Variable_Validation/EFI_Variable_Validation_README.md @@ -0,0 +1,84 @@ +# EFI_Variable_Validation + +Validates required EFI-related kernel configuration and EFI variable runtime behavior on the target. + +## What this test checks + +The test verifies that the following kernel configs are present with the exact expected values: + +- `CONFIG_EFI=y` +- `CONFIG_EFI_ESRT=y` +- `CONFIG_EFIVAR_FS=y` + +It also validates the EFI runtime path by checking: + +- `/sys/firmware/efi` +- `/sys/firmware/efi/efivars` +- EFI variable enumeration through `efivar -l` + +## EFI variable validation flow + +The test performs two variable checks. + +### 1. `OsTrialBootStatus` + +The test writes the following payload to: + +- `8be4df61-93ca-11d2-aa0d-00e098032b8c-OsTrialBootStatus` + +Payload written: + +- `01 77 01 00 00 00 00 00` + +The test then reads the variable back and validates: + +- GUID +- variable name +- attributes: + - `Non-Volatile` + - `Boot Service Access` + - `Runtime Service Access` +- payload bytes: + - `01 77 01 00 00 00 00 00` + +### 2. `OsIndicationsSupported` + +The test reads: + +- `8be4df61-93ca-11d2-aa0d-00e098032b8c-OsIndicationsSupported` + +The test validates: + +- GUID +- variable name +- attributes: + - `Boot Service Access` + - `Runtime Service Access` +- expected value: + - `04 00 00 00 00 00 00 00` + +## ESRT behavior + +The test checks that `CONFIG_EFI_ESRT=y` is enabled. + +If `/sys/firmware/efi/esrt` is not exposed by firmware, the test logs a warning rather than failing. This avoids false failures when kernel support is present but the firmware does not publish an ESRT table. + +## Result semantics + +- `PASS` when EFI kernel config, `OsTrialBootStatus` write or read validation, and `OsIndicationsSupported` attribute or value checks pass +- `FAIL` when a required config is missing, EFI runtime directories are unavailable, variable listing fails, write fails, readback fails, or attributes or values do not match the expected output +- `SKIP` when required userspace dependency `efivar` is not available + +## Output + +The test writes its final result to: + +- `EFI_Variable_Validation.res` + +It also stores temporary command output in: + +- `efi_vars.list` +- `efi_var_write.log` +- `efi_trial_boot_status_print.log` +- `efi_os_indications_supported_print.log` +- `efi_trial_boot_status.bin` diff --git a/Runner/suites/System/EFI_Variable_Validation/run.sh b/Runner/suites/System/EFI_Variable_Validation/run.sh new file mode 100755 index 00000000..d1244f86 --- /dev/null +++ b/Runner/suites/System/EFI_Variable_Validation/run.sh @@ -0,0 +1,274 @@ +#!/bin/sh +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: BSD-3-Clause + +SCRIPT_DIR="$( + cd "$(dirname "$0")" || exit 1 + pwd +)" +INIT_ENV="" +SEARCH="$SCRIPT_DIR" + +while [ "$SEARCH" != "/" ]; do + if [ -f "$SEARCH/init_env" ]; then + INIT_ENV="$SEARCH/init_env" + break + fi + SEARCH=$(dirname "$SEARCH") +done + +if [ -z "$INIT_ENV" ]; then + echo "[ERROR] Could not find init_env, starting at $SCRIPT_DIR" >&2 + exit 1 +fi + +if [ -z "${__INIT_ENV_LOADED:-}" ]; then + # shellcheck disable=SC1090 + . "$INIT_ENV" + __INIT_ENV_LOADED=1 +fi + +# shellcheck disable=SC1091 +. "$TOOLS/functestlib.sh" + +TESTNAME="EFI_Variable_Validation" +test_path="$(find_test_case_by_name "$TESTNAME")" || { + log_fail "$TESTNAME, test directory not found" + echo "$TESTNAME FAIL" > "./$TESTNAME.res" + exit 1 +} + +cd "$test_path" || exit 1 + +RES_FILE="./${TESTNAME}.res" +EFI_LIST_LOG="./efi_vars.list" +EFI_WRITE_LOG="./efi_var_write.log" +EFI_TRIAL_PRINT_LOG="./efi_trial_boot_status_print.log" +EFI_IND_PRINT_LOG="./efi_os_indications_supported_print.log" +EFI_DATA_FILE="./efi_trial_boot_status.bin" + +rm -f "$RES_FILE" \ + "$EFI_LIST_LOG" \ + "$EFI_WRITE_LOG" \ + "$EFI_TRIAL_PRINT_LOG" \ + "$EFI_IND_PRINT_LOG" \ + "$EFI_DATA_FILE" + +CONFIGS=" +CONFIG_EFI=y +CONFIG_EFI_ESRT=y +CONFIG_EFIVAR_FS=y +" + +EFI_GLOBAL_GUID="8be4df61-93ca-11d2-aa0d-00e098032b8c" +OS_TRIAL_BOOT_STATUS_VAR="${EFI_GLOBAL_GUID}-OsTrialBootStatus" +OS_INDICATIONS_SUPPORTED_VAR="${EFI_GLOBAL_GUID}-OsIndicationsSupported" + +write_trial_boot_status_payload() { + # 01 77 01 00 00 00 00 00 + : > "$EFI_DATA_FILE" || return 1 + printf '\001\167\001\000\000\000\000\000' > "$EFI_DATA_FILE" || return 1 + return 0 +} + +log_file_excerpt() { + log_prefix="$1" + log_file="$2" + log_lines="${3:-40}" + + sed -n "1,${log_lines}p" "$log_file" | while IFS= read -r line; do + [ -n "$line" ] || continue + log_info "[${log_prefix}] $line" + done +} + +require_grep_in_file() { + pattern="$1" + file_path="$2" + fail_msg="$3" + + if grep -Fq "$pattern" "$file_path"; then + return 0 + fi + + log_fail "$fail_msg" + return 1 +} + +require_hex_payload_in_file() { + file_path="$1" + expected_desc="$2" + + if grep -Eq '01[[:space:]]+77[[:space:]]+01[[:space:]]+00[[:space:]]+00[[:space:]]+00[[:space:]]+00[[:space:]]+00' "$file_path"; then + return 0 + fi + + log_fail "EFI variable payload does not match expected value, required ${expected_desc}" + return 1 +} + +require_os_indications_supported_value() { + file_path="$1" + + if grep -Eq '04[[:space:]]+00[[:space:]]+00[[:space:]]+00[[:space:]]+00[[:space:]]+00[[:space:]]+00[[:space:]]+00' "$file_path"; then + return 0 + fi + + log_fail "OsIndicationsSupported value does not match expected value, required 04 00 00 00 00 00 00 00" + return 1 +} + +log_info "-----------------------------------------------------------------------------------------" +log_info "------------------- Starting ${TESTNAME} Testcase ----------------------------" +log_info "==== Test Initialization ====" + +if ! CHECK_DEPS_NO_EXIT=1 check_dependencies efivar grep sed awk printf; then + log_skip "$TESTNAME SKIP, missing required dependencies" + echo "$TESTNAME SKIP" > "$RES_FILE" + exit 0 +fi + +log_info "Checking required EFI kernel configs" +if ! check_kernel_config "$CONFIGS"; then + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi + +log_info "Checking EFI runtime directory" +if [ ! -d /sys/firmware/efi ]; then + log_fail "/sys/firmware/efi is not present" + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +log_pass "/sys/firmware/efi is present" + +log_info "Checking efivarfs directory" +if [ ! -d /sys/firmware/efi/efivars ]; then + log_fail "/sys/firmware/efi/efivars is not present" + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +log_pass "/sys/firmware/efi/efivars is present" + +log_info "Checking ESRT runtime directory" +if [ -d /sys/firmware/efi/esrt ]; then + log_pass "/sys/firmware/efi/esrt is present" +else + log_warn "/sys/firmware/efi/esrt is not present, CONFIG_EFI_ESRT is enabled but firmware ESRT table is not exposed" +fi + +log_info "Listing EFI variables with efivar -l" +if ! efivar -l > "$EFI_LIST_LOG" 2>&1; then + log_fail "efivar -l failed" + log_file_excerpt "efivar-list" "$EFI_LIST_LOG" 40 + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi + +efi_var_count="$(grep -c '.' "$EFI_LIST_LOG" 2>/dev/null || echo 0)" +if [ "$efi_var_count" -le 0 ]; then + log_fail "efivar -l returned no EFI variables" + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +log_pass "efivar -l returned ${efi_var_count} EFI variables" + +log_info "Showing first EFI variables, capped at 20 lines" +log_file_excerpt "efi-var" "$EFI_LIST_LOG" 20 + +log_info "Preparing payload for ${OS_TRIAL_BOOT_STATUS_VAR}" +if ! write_trial_boot_status_payload; then + log_fail "Could not prepare OsTrialBootStatus payload file" + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi + +payload_size="$(wc -c < "$EFI_DATA_FILE" 2>/dev/null || echo 0)" +if [ "$payload_size" -ne 8 ]; then + log_fail "OsTrialBootStatus payload size is invalid, expected 8 bytes, got ${payload_size}" + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +log_pass "OsTrialBootStatus payload prepared, size ${payload_size} bytes" + +log_info "Writing EFI variable, ${OS_TRIAL_BOOT_STATUS_VAR}" +if ! efivar -n "$OS_TRIAL_BOOT_STATUS_VAR" -f "$EFI_DATA_FILE" -w > "$EFI_WRITE_LOG" 2>&1; then + log_fail "Write failed for ${OS_TRIAL_BOOT_STATUS_VAR}" + log_file_excerpt "efivar-write" "$EFI_WRITE_LOG" 40 + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +log_pass "Write succeeded for ${OS_TRIAL_BOOT_STATUS_VAR}" + +log_info "Printing EFI variable, ${OS_TRIAL_BOOT_STATUS_VAR}" +if ! efivar -n "$OS_TRIAL_BOOT_STATUS_VAR" -p > "$EFI_TRIAL_PRINT_LOG" 2>&1; then + log_fail "Print failed for ${OS_TRIAL_BOOT_STATUS_VAR}" + log_file_excerpt "efivar-trial-print" "$EFI_TRIAL_PRINT_LOG" 40 + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi + +log_file_excerpt "efivar-trial-print" "$EFI_TRIAL_PRINT_LOG" 40 + +if ! require_grep_in_file "GUID: ${EFI_GLOBAL_GUID}" "$EFI_TRIAL_PRINT_LOG" "OsTrialBootStatus GUID does not match expected value"; then + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +if ! require_grep_in_file 'Name: "OsTrialBootStatus"' "$EFI_TRIAL_PRINT_LOG" "OsTrialBootStatus name is missing in print output"; then + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +if ! require_grep_in_file "Non-Volatile" "$EFI_TRIAL_PRINT_LOG" "OsTrialBootStatus is missing Non-Volatile attribute"; then + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +if ! require_grep_in_file "Boot Service Access" "$EFI_TRIAL_PRINT_LOG" "OsTrialBootStatus is missing Boot Service Access attribute"; then + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +if ! require_grep_in_file "Runtime Service Access" "$EFI_TRIAL_PRINT_LOG" "OsTrialBootStatus is missing Runtime Service Access attribute"; then + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +if ! require_hex_payload_in_file "$EFI_TRIAL_PRINT_LOG" "01 77 01 00 00 00 00 00"; then + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +log_pass "OsTrialBootStatus attributes and payload match expected values" + +log_info "Printing EFI variable, ${OS_INDICATIONS_SUPPORTED_VAR}" +if ! efivar -n "$OS_INDICATIONS_SUPPORTED_VAR" -p > "$EFI_IND_PRINT_LOG" 2>&1; then + log_fail "Print failed for ${OS_INDICATIONS_SUPPORTED_VAR}" + log_file_excerpt "efivar-indications-print" "$EFI_IND_PRINT_LOG" 40 + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi + +log_file_excerpt "efivar-indications-print" "$EFI_IND_PRINT_LOG" 40 + +if ! require_grep_in_file "GUID: ${EFI_GLOBAL_GUID}" "$EFI_IND_PRINT_LOG" "OsIndicationsSupported GUID does not match expected value"; then + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +if ! require_grep_in_file 'Name: "OsIndicationsSupported"' "$EFI_IND_PRINT_LOG" "OsIndicationsSupported name is missing in print output"; then + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +if ! require_grep_in_file "Boot Service Access" "$EFI_IND_PRINT_LOG" "OsIndicationsSupported is missing Boot Service Access attribute"; then + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +if ! require_grep_in_file "Runtime Service Access" "$EFI_IND_PRINT_LOG" "OsIndicationsSupported is missing Runtime Service Access attribute"; then + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +if ! require_os_indications_supported_value "$EFI_IND_PRINT_LOG"; then + echo "$TESTNAME FAIL" > "$RES_FILE" + exit 0 +fi +log_pass "OsIndicationsSupported attributes and value match expected values" + +log_pass "$TESTNAME, EFI kernel config, write read validation, and EFI variable attribute checks passed" +echo "$TESTNAME PASS" > "$RES_FILE" +log_info "------------------- Completed ${TESTNAME} Testcase ----------------------------" +exit 0