You've already forked dts-scripts
mirror of
https://github.com/Dasharo/dts-scripts.git
synced 2026-03-06 15:01:22 -08:00
common-mock-func: set dmidecode to return 0 by default if test variable isn't defined this likely means that this value doesn't matter for test purposes. Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock-func: cbmem shouldn't exit in failure in normal check Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock-func: cbfstool: allow specifying fmap regions in binary Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> dts-functions: set_flashrom_update_params: don't use $1 directly It's hard to know exactly what this argument is for otherwise as this function isn't documented Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> deploy: don't use mktemp so profile arguments are always the same Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> dts-boot: create TEMP_DIR Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock: cbfstool: return 1 if not coreboot Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> cbfstool: don't mock when we check update binary config Except in some cases where we want to possibly test for identical config between update binary and current firmware. Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> dasharo-deploy: add 2>>ERR_LOG_FILE redirection Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock: cbmem: check if coreboot Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> dts-functions: download_keys: use 'mkdir -p' so it doesn't error out Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock: add cbmem_common_mock which returns error if not coreboot Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock: add msrtool and mei-amt-check common mock Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock: ifdtool: call original ifdtool if used with update binary Fixes situation on QEMU that results in user not being asked whether to continue flashing without ME even though we want to test with ME enabled Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock: flashrom: verify internal chip use Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock: add bootsplash presence mocking Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock: both flashrom and cbfstool allow writing over existing file Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock: bootsplash region might exist without custom bootsplash Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> check_if_me_disabled: Don't use mocked functions with 'grep -q' Otherwise grep will break pipe immediately after matching searched string which will result in mocked function being immediately stopped even before finishing. It also results in e.g. tool wrapper not writing used command to profile Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock: Add separate ME disabled and ME HAP disabled Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock: add cbfstool smmstore mocking Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> common-mock: simplify fuse mock Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> dts-functions: check_if_boot_guard_enabled: hide rdmsr output remove non-existent command, likely pasted by mistake Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com> include: hal: add cbfstool_add_firmware_section_mock Signed-off-by: Daniil Klimuk <daniil.klimuk@3mdeb.com> use dont_mock instead of cbfstool_add_firmware_section_mock Signed-off-by: Daniil Klimuk <daniil.klimuk@3mdeb.com> common-mock: rename regions to _regions Signed-off-by: Michał Iwanicki <michal.iwanicki@3mdeb.com>
278 lines
10 KiB
Bash
278 lines
10 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# SPDX-FileCopyrightText: 2024 3mdeb <contact@3mdeb.com>
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
# This is a Hardware Abstraction Layer for DTS. The goal of this layer -
|
|
# separate all hardware-related code from DTS code to improve readability,
|
|
# scalability and testing.
|
|
#
|
|
# For testing, every hardware-specific tool must utilize DTS_TESTING
|
|
# variable, which is declared in dts-environment and set by user. If DTS_TESTING
|
|
# is not "true" - HAL communicates with hardware and firmware via specific tools
|
|
# otherwise it uses mocking functions and tool_wrapper to emulate behaviour of
|
|
# some of the tools.
|
|
#
|
|
# Real HAL is placed in $DTS_HAL* (* means that, apart from common HAL funcs.
|
|
# there could be, in future, files with platform-specific HAL funcs) and the
|
|
# Tests HAL is placed in $DTS_MOCK* (* means that, apart from common mocks,
|
|
# there could be, in future, files with platform-specific mocking functions).
|
|
|
|
# shellcheck disable=SC2034
|
|
|
|
# shellcheck source=../../include/hal/common-mock-func.sh
|
|
source $DTS_MOCK_COMMON
|
|
|
|
# Set tools wrappers:
|
|
DASHARO_ECTOOL="tool_wrapper dasharo_ectool"
|
|
FLASHROM="tool_wrapper flashrom"
|
|
DMIDECODE="tool_wrapper dmidecode"
|
|
IFDTOOL="tool_wrapper ifdtool"
|
|
SETPCI="tool_wrapper setpci"
|
|
# Emulating to eliminate false negatives, because it might fail on QEMU:
|
|
CBMEM="tool_wrapper cbmem"
|
|
CBFSTOOL="tool_wrapper cbfstool"
|
|
# Emulating to eliminate false negatives, because it fails on QEMU:
|
|
SUPERIOTOOL="tool_wrapper superiotool"
|
|
# Emulating to eliminate false negatives, because it fails on QEMU:
|
|
ECTOOL="tool_wrapper ectool"
|
|
# Emulating to eliminate false negatives, because it fails on QEMU:
|
|
MSRTOOL="tool_wrapper msrtool"
|
|
# Emulating to eliminate false negatives, because it fails on QEMU:
|
|
MEI_AMT_CHECK="tool_wrapper mei-amt-check"
|
|
# Emulating to eliminate false negatives, because it fails on QEMU:
|
|
INTELMETOOL="tool_wrapper intelmetool"
|
|
# Emulating, so no to probe every time testing is done
|
|
HW_PROBE="tool_wrapper hw-probe"
|
|
DMESG="tool_wrapper dmesg"
|
|
DCU="tool_wrapper dcu"
|
|
FUTILITY="tool_wrapper futility"
|
|
IOTOOLS="tool_wrapper iotools"
|
|
FSREAD_TOOL="tool_wrapper fsread_tool"
|
|
CAP_UPD_TOOL="tool_wrapper cap_upd_tool"
|
|
LSCPU="tool_wrapper lscpu"
|
|
# System commands:
|
|
POWEROFF="tool_wrapper poweroff"
|
|
REBOOT="tool_wrapper reboot"
|
|
RDMSR="tool_wrapper rdmsr"
|
|
LSPCI="tool_wrapper lspci"
|
|
LSUSB="tool_wrapper lsusb"
|
|
|
|
################################################################################
|
|
# Tools wrapper.
|
|
################################################################################
|
|
tool_wrapper() {
|
|
# Usage: tool_wrapper TOOL_NAME MOCK_FUNC_NAME TOOL_ARGS
|
|
#
|
|
# TOOL_NAME: the name of the tool being wrapped
|
|
# MOCK_FUNC_NAME: the name of mocking function (optional, check comments
|
|
# below for more inf.)
|
|
# TOOL_ARGS: the arguments that the tool gets if being called, for example
|
|
# for dmidecode -s system-vendor it will be "-s system-vendor".
|
|
#
|
|
# This function is a bridge between common DTS logic and hardware-specific DTS
|
|
# logic or functions. There is two paths a call to this function can be
|
|
# redirected to: real HAL for running on real platform and Tests HAL for testing
|
|
# on QEMU (depends on whether the var. DTS_TESTING is set or not).
|
|
#
|
|
# The real HAL are the real tools e.g. cbfstool, etc.. The testing HAL are the
|
|
# mocking functions. There are several types of mocking functions, with every
|
|
# type having a specific name syntax:
|
|
#
|
|
# FUNCTIONNAME_mock(){...}: mocking functions specific for every platform, those
|
|
# are stored in $DTS_MOCK_PLATFORM file which is sourced at the beginning of
|
|
# this file.
|
|
# TOOLNAME_FUNCTIONNAME_mock(){...}: mocking functions common for all platforms
|
|
# but specific for some tool, those are stored in $DTS_MOCK_COMMON file, which
|
|
# is being sourced at the beginning of this file.
|
|
# TOOLNAME_common_mock(){...}: standard mocking functions for every tool that
|
|
# are common for all platforms, those are stored in $DTS_MOCK_COMMON file, which
|
|
# is being sourced at the beginning of this file.
|
|
# common_mock(){...}: common mocking function, in case we need to use mocking
|
|
# function for a tool but we do not care about its output.
|
|
#
|
|
# This tool wrapper should only be used with tools which communicate with
|
|
# hardware or firmware (read or write, etc.).
|
|
#
|
|
# TODO: this wrapper deals with arguments as well as with stdout, stderr, and $?
|
|
# redirection, but it does not read and redirect stdin (this is not used in any
|
|
# mocking functions or tools right now).
|
|
# Gets toolname, e.g. poweroff, dmidecode. etc.:
|
|
local _tool="$1"
|
|
# Gets mocking function name:
|
|
local _mock_func="$2"
|
|
# It checks if _mock_func contains smth with _mock at the end, if not -
|
|
# mocking function is not provided and some common mocking func. will be used
|
|
# instead:
|
|
if ! echo "$_mock_func" | grep "_mock" &>/dev/null; then
|
|
unset _mock_func
|
|
shift 1
|
|
else
|
|
shift 2
|
|
fi
|
|
# Other arguments for this function are the arguments which are sent to a tool
|
|
# e.g. -s system-vendor for dmidecode, etc.:
|
|
local _arguments=("$@")
|
|
|
|
if [ -n "$DTS_TESTING" ]; then
|
|
# This is the order of calling mocking functions:
|
|
# 1) dont_mock - use original command
|
|
# 2) FUNCTIONNAME_mock;
|
|
# 3) TOOLNAME_FUNCTIONNAME_mock;
|
|
# 4) TOOLNAME_common_mock;
|
|
# 5) common_mock - last resort.
|
|
if [ "$_mock_func" = "dont_mock" ]; then
|
|
dont_mock "$_tool" "${_arguments[@]}"
|
|
elif [ -n "$_mock_func" ] && type $_mock_func &>/dev/null; then
|
|
$_mock_func "${_arguments[@]}"
|
|
elif type ${_tool}_${_mock_func} &>/dev/null; then
|
|
${_tool}_${_mock_func} "${_arguments[@]}"
|
|
elif type ${_tool}_common_mock &>/dev/null; then
|
|
${_tool}_common_mock "${_arguments[@]}"
|
|
else
|
|
common_mock $_tool
|
|
fi
|
|
else
|
|
# If not testing - call tool with the arguments instead:
|
|
$_tool "${_arguments[@]}"
|
|
fi
|
|
# !! When modifying this function, make sure this is return value of wrapped
|
|
# tool (real of mocked)
|
|
ret=$?
|
|
echo "${_tool} ${_arguments[*]} $ret" >>/tmp/logs/profile
|
|
echo "${BASH_SOURCE[1]}:${FUNCNAME[1]}:${BASH_LINENO[0]} ${_tool} ${_arguments[*]} $ret" >>/tmp/logs/debug_profile
|
|
|
|
return $ret
|
|
}
|
|
|
|
################################################################################
|
|
# Other funcs.
|
|
################################################################################
|
|
check_for_opensource_firmware() {
|
|
echo "Checking for Open Source Embedded Controller firmware..."
|
|
$DASHARO_ECTOOL check_for_opensource_firm_mock info >/dev/null 2>>"$ERR_LOG_FILE"
|
|
|
|
return $?
|
|
}
|
|
|
|
fsread_tool() {
|
|
# This func is an abstraction for proper handling of fs hardware-specific (e.g.
|
|
# checking devtmpfs, or sysfs, or some other fs that changes its state due to
|
|
# changes in hardware and/or firmware) reads by tool_wrapper.
|
|
#
|
|
# This function does not have arguments in common understanding, it takes a
|
|
# command, that is reading smth from some fs, and its arguments as an only
|
|
# argument. E.g. if you want to check tty1 device presence:
|
|
#
|
|
# fsread_tool test -f /dev/tty1
|
|
local _command="$1"
|
|
shift
|
|
|
|
$_command "$@"
|
|
|
|
return $?
|
|
}
|
|
|
|
cap_upd_tool() {
|
|
# This func is an abstraction for proper handling of UEFI Capsule Update driver
|
|
# writing by the tool_wrapper. arguments: capsule update file path, e.g.:
|
|
#
|
|
# capsule_update_tool /tmp/firm.cap
|
|
local _capsule="$1"
|
|
|
|
cat "$_capsule" >"$CAP_UPD_DEVICE"
|
|
|
|
return $?
|
|
}
|
|
|
|
check_if_heci_present() {
|
|
# FIXME: what if HECI is not device 16.0?
|
|
$FSREAD_TOOL test -d /sys/class/pci_bus/0000:00/device/0000:00:16.0
|
|
|
|
return $?
|
|
}
|
|
|
|
check_me_op_mode() {
|
|
# Checks ME Current Operation Mode at offset 0x40 bits 19:16:
|
|
local _mode
|
|
|
|
_mode="$($SETPCI check_me_op_mode_mock -s 00:16.0 42.B 2>>"$ERR_LOG_FILE" | cut -c2-)"
|
|
|
|
echo "$_mode"
|
|
|
|
return 0
|
|
}
|
|
|
|
check_if_uefi() {
|
|
# Check if current firmware has UEFI payload. Returns 0 on success, otherwise
|
|
# returns 1.
|
|
grep -q 'UEFI' <(echo "${DASHARO_FLAVOR}") && return 0
|
|
# Additional check is useful sometimes:
|
|
$FSREAD_TOOL test -d "/sys/firmware/efi" && return 0
|
|
|
|
return 1
|
|
}
|
|
|
|
check_if_seabios() {
|
|
# Check if current firmware has SeaBIOS payload. Returns 0 on success,
|
|
# otherwise returns 1.
|
|
grep -q 'SeaBIOS' <(echo "${DASHARO_FLAVOR}") && return 0
|
|
# Additional check is useful sometimes:
|
|
tmp_rom="$TEMP_DIR/rom_seabios_check"
|
|
config="$TEMP_DIR/config"
|
|
# Get current firmware:
|
|
$FLASHROM flashrom_read_firm_mock -p "$PROGRAMMER_BIOS" ${FLASH_CHIP_SELECT} -r "$tmp_rom" >>"$FLASH_INFO_FILE" 2>>"$ERR_LOG_FILE"
|
|
|
|
if [ -f "$tmp_rom" ]; then
|
|
# extract config
|
|
$CBFSTOOL read_bios_conffile_mock "$tmp_rom" extract -n config -f "$config" >/dev/null 2>>"$ERR_LOG_FILE"
|
|
grep -q "CONFIG_PAYLOAD_SEABIOS=y" "$config" 2>>"${ERR_LOG_FILE}" && return 0
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
check_for_transition() {
|
|
# This function checks for possible transition for current hardware and
|
|
# firmware configuration flows and returns:
|
|
# * In case no transition flows sare available: return code 1 and empty
|
|
# stdout.
|
|
# * In case at least one transition flow is available: return code 0 and the
|
|
# transition flow name on stdout.
|
|
#
|
|
# Check the end of the function for stdout formatting.
|
|
local _is_uefi="false"
|
|
local _is_seabios="false"
|
|
local _transition_list=()
|
|
|
|
# The transition is only possible from Dasharo firmware:
|
|
check_if_dasharo || return 1
|
|
check_if_uefi && _is_uefi="true"
|
|
check_if_seabios && _is_seabios="true"
|
|
|
|
if [[ "$_is_uefi" == "true" ]]; then
|
|
# Dasharo (coreboot+UEFI) is installed, check possible transitions:
|
|
if [[ "$COREBOOT_UEFI_TO_SLIM_BOOTLOADER_UEFI_TRANSITION" == "true" ]]; then
|
|
_transition_list+=("Dasharo (coreboot+UEFI) to Dasharo (Slim Bootloader+UEFI)")
|
|
fi
|
|
fi
|
|
|
|
if [[ "$_is_seabios" == "true" ]]; then
|
|
# Dasharo (coreboot+SeaBIOS) is installed, check possible transitions:
|
|
if [[ "$COREBOOT_SEABIOS_TO_COREBOOT_UEFI_TRANSITION" == "true" ]]; then
|
|
_transition_list+=("Dasharo (coreboot+SeaBIOS) to Dasharo (coreboot+UEFI)")
|
|
fi
|
|
fi
|
|
|
|
# This loop will make this function return a string that contains a string
|
|
# that contains possible transitions separated by a new line, so it can be
|
|
# easily reconstructed back to an array with
|
|
# readarray -t transitions < <(check_for_transition)
|
|
for transition in "${_transition_list[@]}"; do
|
|
echo "$transition"
|
|
done
|
|
|
|
[[ -n "${_transition_list[*]}" ]] && return 0 || return 1
|
|
}
|