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