Files
dts-scripts/include/dts-functions.sh
2025-09-04 11:00:13 +02:00

1968 lines
71 KiB
Bash

#!/usr/bin/env bash
# SPDX-FileCopyrightText: 2024 3mdeb <contact@3mdeb.com>
#
# SPDX-License-Identifier: Apache-2.0
# shellcheck disable=SC2034
### Color functions:
function echo_green() {
echo -e "$GREEN""$1""$NORMAL"
}
function echo_red() {
echo -e "$RED""$1""$NORMAL"
}
function echo_yellow() {
echo -e "$YELLOW""$1""$NORMAL"
}
print_warning() {
echo_yellow "$1"
}
print_error() {
echo_red "$1"
}
print_ok() {
echo_green "$1"
}
check_if_dasharo() {
if [[ $BIOS_VENDOR == *$DASHARO_VENDOR* &&
$BIOS_VERSION == *$DASHARO_NAME* ||
"$SYSTEM_VENDOR" == "PC Engines" ]]; then
return 0
else
return 1
fi
}
check_if_ac() {
local _ac_file="/sys/class/power_supply/AC/online"
if ! $FSREAD_TOOL test -e "${_ac_file}"; then
# We want to silently skip if AC file is not there. Most likely this is
# not battery-powered device then.
return 0
fi
while true; do
ac_status=$($FSREAD_TOOL cat ${_ac_file})
if [ "$ac_status" -eq 1 ]; then
echo "AC adapter is connected. Continuing with firmware update."
return
else
print_warning "Warning: AC adapter must be connected before performing firmware update."
print_warning "Please connect the AC adapter and press 'C' to continue, or 'Q' to quit."
read -n 1 -r input
case $input in
[Cc])
echo "Checking AC status again..."
;;
[Qq])
echo "Quitting firmware update."
return 1
;;
*)
echo "Invalid input. Press 'C' to continue, or 'Q' to quit."
continue
;;
esac
fi
done
}
### Error checks
# instead of error exit in dasharo-deploy exit we need to reboot the platform
# in cases where there would be some problem with updating the platform
fum_exit() {
if [ "$FUM" == "fum" ]; then
print_error "Update cannot be performed"
print_warning "Starting bash session"
send_dts_logs ask
/bin/bash
fi
}
error_exit() {
_error_msg="$1"
local exit_code=1
if [ "$#" -eq 2 ]; then
exit_code=$2
fi
if [ -n "$_error_msg" ]; then
# Avoid printing empty line if no message was passed
print_error "$_error_msg"
fi
fum_exit
exit $exit_code
}
error_check() {
_error_code=$?
_error_msg="$1"
[ "$_error_code" -ne 0 ] && error_exit "$_error_msg : ($_error_code)"
}
function error_file_check {
if [ ! -f "$1" ]; then
print_error "$2"
fi
}
### Clevo-specific functions
# Method to access IT5570 IO Depth 2 registers
it5570_i2ec() {
# TODO: Use /dev/port instead of iotools
# Address high byte
$IOTOOLS io_write8 0x2e 0x2e
$IOTOOLS io_write8 0x2f 0x11
$IOTOOLS io_write8 0x2e 0x2f
$IOTOOLS io_write8 0x2f $(($2 >> 8 & 0xff))
# Address low byte
$IOTOOLS io_write8 0x2e 0x2e
$IOTOOLS io_write8 0x2f 0x10
$IOTOOLS io_write8 0x2e 0x2f
$IOTOOLS io_write8 0x2f $(($2 & 0xff))
# Data
$IOTOOLS io_write8 0x2e 0x2e
$IOTOOLS io_write8 0x2f 0x12
$IOTOOLS io_write8 0x2e 0x2f
case $1 in
"r")
$IOTOOLS io_read8 0x2f
;;
"w")
$IOTOOLS io_write8 0x2f "$3"
;;
esac
}
it5570_shutdown() {
# shut down using EC external watchdog reset
it5570_i2ec w 0x1f01 0x20
it5570_i2ec w 0x1f07 0x01
}
check_network_connection() {
if wget --spider cloud.3mdeb.com >/dev/null 2>>"$ERR_LOG_FILE"; then
return 0
else
return 1
fi
}
wait_for_network_connection() {
echo 'Waiting for network connection ...'
n="10"
while :; do
if check_network_connection; then
print_ok "Network connection have been established!"
return 0
fi
n=$((n - 1))
if [ "${n}" == "0" ]; then
print_error "Could not connect to network, please check network connection!"
return 1
fi
sleep 1
done
}
ask_for_model() {
local model=("$@")
if [ $# -lt 1 ]; then
BOARD_MODEL=""
return
fi
while :; do
echo "Choose your board model:"
echo " 0. None below"
for ((i = 0; i < $#; i++)); do
echo " $((i + 1)): ${model[$i]}"
done
echo
read -r -p "Enter an option: " OPTION
echo
if [ "$OPTION" -eq 0 ]; then
BOARD_MODEL=""
return
fi
if [ "$OPTION" -gt 0 ] && [ "$OPTION" -le $# ]; then
BOARD_MODEL="${model[$((OPTION - 1))]}"
return
fi
done
}
board_config() {
# This functions checks used platform and configure environment in case the
# platform is supported. The supported platforms are sorted by variables
# SYSTEM_VENDOR, SYSTEM_MODEL, and BOARD_MODEL in switch/case statements.
#
# Every platform uses some standard environment configuration variables
# described in dts-environment.sh file, these could be specified for a specific
# board or vendor or shared between some, some platforms may have their own env.
# var. as well.
#
# All the standard variables are explicitly declared in dts-environment.sh
# script and, if appropriate, set to default values. If a platform has its own
# configuration variables - it must declare them here, even if they are not
# set. This is made with a goal to limit global variables declaration to
# dts-environment.sh and board_config function.
# We download firmwares via network. At this point, the network connection
# must be up already.
wait_for_network_connection
echo "Downloading board configs repository"
mkdir -p "$BOARD_CONFIG_PATH"
curl -f -L -o "$BOARD_CONFIG_PATH.tar.gz" \
https://github.com/Dasharo/dts-configs/archive/${DTS_CONFIG_REF}.tar.gz >/dev/null 2>>"$ERR_LOG_FILE"
if [ $? -ne 0 ]; then
print_error "Failed to download configs."
return 1
fi
tar xf "$BOARD_CONFIG_PATH.tar.gz" -C "$BOARD_CONFIG_PATH" --strip-components=1
echo "Checking if board is Dasharo compatible."
case "$SYSTEM_VENDOR" in
"Notebook")
# Common settings for all Notebooks:
CAN_USE_FLASHROM="true"
HAVE_EC="true"
NEED_EC_RESET="true"
PLATFORM_SIGN_KEY="customer-keys/novacustom/novacustom-open-source-firmware-release-1.x-key.asc \
customer-keys/novacustom/dasharo-release-0.9.x-for-novacustom-signing-key.asc"
NEED_SMMSTORE_MIGRATION="true"
BUCKET_DPP_HEADS="dasharo-novacustom-heads"
case "$SYSTEM_MODEL" in
"NV4XMB,ME,MZ")
DASHARO_REL_NAME="novacustom_nv4x_tgl"
DASHARO_REL_VER="1.5.2"
CAN_INSTALL_BIOS="true"
COMPATIBLE_EC_FW_VERSION="2022-10-07_c662165"
if check_if_dasharo; then
# if v1.5.1 or older, flash the whole bios region
# TODO: Let DTS determine which parameters are suitable.
# FIXME: Can we ever get rid of that? We change so much in each release,
# that we almost always need to flash whole BIOS regions
# because of non-backward compatible or breaking changes.
compare_versions $DASHARO_VERSION 1.5.2
if [ $? -eq 1 ]; then
# For Dasharo version lesser than 1.5.2
NEED_BOOTSPLASH_MIGRATION="true"
FLASHROM_ADD_OPT_UPDATE_OVERRIDE="--ifd -i bios"
fi
fi
;;
"NS50_70MU")
DASHARO_REL_NAME="novacustom_ns5x_tgl"
DASHARO_REL_VER="1.5.2"
CAN_INSTALL_BIOS="true"
COMPATIBLE_EC_FW_VERSION="2022-08-31_cbff21b"
PROGRAMMER_EC="ite_ec:romsize=128K,autoload=disable"
if check_if_dasharo; then
# if v1.5.1 or older, flash the whole bios region
# TODO: Let DTS determine which parameters are suitable.
# FIXME: Can we ever get rid of that? We change so much in each release,
# that we almost always need to flash whole BIOS regions
# because of non-backward compatible or breaking changes.
compare_versions $DASHARO_VERSION 1.5.2
if [ $? -eq 1 ]; then
# For Dasharo version lesser than 1.5.2
NEED_BOOTSPLASH_MIGRATION="true"
FLASHROM_ADD_OPT_UPDATE_OVERRIDE="--ifd -i bios"
fi
fi
;;
"NS5x_NS7xPU")
DASHARO_REL_NAME="novacustom_ns5x_adl"
DASHARO_REL_VER="1.7.2"
COMPATIBLE_EC_FW_VERSION="2022-08-31_cbff21b"
if check_if_dasharo; then
# if v1.7.2 or older, flash the whole bios region
# TODO: Let DTS determine which parameters are suitable.
# FIXME: Can we ever get rid of that? We change so much in each release,
# that we almost always need to flash whole BIOS regions
# because of non-backward compatible or breaking changes.
compare_versions $DASHARO_VERSION 1.7.2
if [ $? -eq 1 ]; then
# For Dasharo version lesser than 1.7.2
NEED_BOOTSPLASH_MIGRATION="true"
FLASHROM_ADD_OPT_UPDATE_OVERRIDE="--ifd -i bios"
fi
fi
;;
"NV4xPZ")
if ! parse_and_verify_config "$SYSTEM_VENDOR" "$SYSTEM_MODEL" "$BOARD_MODEL"; then
return 1
fi
HEADS_LINK_DPP="${BUCKET_DPP_HEADS}/${DASHARO_REL_NAME}/v${HEADS_REL_VER_DPP}/${DASHARO_REL_NAME}_v${HEADS_REL_VER_DPP}_heads.rom"
if check_if_dasharo; then
# if v1.7.2 or older, flash the whole bios region
# TODO: Let DTS determine which parameters are suitable.
# FIXME: Can we ever get rid of that? We change so much in each release,
# that we almost always need to flash whole BIOS regions
# because of non-backward compatible or breaking changes.
compare_versions $DASHARO_VERSION 1.7.2
if [ $? -eq 1 ]; then
# For Dasharo version lesser than 1.7.2
NEED_BOOTSPLASH_MIGRATION="true"
FLASHROM_ADD_OPT_UPDATE_OVERRIDE="--ifd -i bios"
else
HAVE_HEADS_FW="true"
fi
if [ "$DASHARO_FLAVOR" == "Dasharo (coreboot+heads)" ]; then
HAVE_HEADS_FW="true"
fi
fi
;;
"V54x_6x_TU")
# Dasharo 0.9.0-rc10 and higher have board model in baseboard-version
if check_if_dasharo && compare_versions "$DASHARO_VERSION" 0.9.0-rc10; then
BOARD_MODEL="$($DMIDECODE dump_var_mock -s baseboard-version)"
elif ! $DASHARO_ECTOOL check_for_opensource_firm_mock info 2>>"$ERR_LOG_FILE"; then
ask_for_model V540TU V560TU
else
BOARD_MODEL=$($DASHARO_ECTOOL novacustom_check_sys_model_mock info | grep "board:" |
sed -r 's|.*novacustom/(.*)|\1|' | awk '{print toupper($1)}')
fi
# Common configuration for all V54x_6x_TU:
DASHARO_REL_VER="0.9.0"
COMPATIBLE_EC_FW_VERSION="2024-07-17_4ae73b9"
NEED_BOOTSPLASH_MIGRATION="true"
case $BOARD_MODEL in
"V540TU")
DASHARO_REL_NAME="novacustom_v54x_mtl"
FLASHROM_ADD_OPT_UPDATE_OVERRIDE="--ifd -i bios"
HAVE_HEADS_FW="true"
HEADS_REL_VER_DPP="0.9.0"
COMPATIBLE_HEADS_EC_FW_VERSION="2024-07-17_4ae73b9"
HEADS_SWITCH_FLASHROM_OPT_OVERRIDE="--ifd -i bios"
;;
"V560TU")
DASHARO_REL_NAME="novacustom_v56x_mtl"
FLASHROM_ADD_OPT_UPDATE_OVERRIDE="--ifd -i bios"
HAVE_HEADS_FW="true"
HEADS_REL_VER_DPP="0.9.0"
COMPATIBLE_HEADS_EC_FW_VERSION="2024-12-20_368e08e"
HEADS_SWITCH_FLASHROM_OPT_OVERRIDE="--ifd -i bios"
HEADS_EC_LINK_DPP="${BUCKET_DPP_HEADS}/${DASHARO_REL_NAME}/v${HEADS_REL_VER_DPP}/${DASHARO_REL_NAME}_ec_v${HEADS_REL_VER_DPP}.rom"
;;
*)
print_error "Board model $BOARD_MODEL is currently not supported"
return 1
;;
esac
HEADS_LINK_DPP="${BUCKET_DPP_HEADS}/${DASHARO_REL_NAME}/v${HEADS_REL_VER_DPP}/${DASHARO_REL_NAME}_v${HEADS_REL_VER_DPP}_heads.rom"
;;
"V5xTNC_TND_TNE")
if check_if_dasharo; then
BOARD_MODEL="$($DMIDECODE dump_var_mock -s baseboard-version)"
else
ask_for_model V540TNx V560TNx
fi
NEED_BOOTSPLASH_MIGRATION="true"
case $BOARD_MODEL in
"V540TNx")
DASHARO_REL_NAME="novacustom_v54x_mtl"
DASHARO_REL_VER="0.9.1"
COMPATIBLE_EC_FW_VERSION="2024-09-10_3786c8c"
FLASHROM_ADD_OPT_UPDATE_OVERRIDE="--ifd -i bios"
;;
"V560TNx")
DASHARO_REL_NAME="novacustom_v56x_mtl"
DASHARO_REL_VER="0.9.1"
COMPATIBLE_EC_FW_VERSION="2024-09-10_3786c8c"
FLASHROM_ADD_OPT_UPDATE_OVERRIDE="--ifd -i bios"
;;
*)
print_error "Board model $BOARD_MODEL is currently not supported"
return 1
;;
esac
;;
*)
print_error "Board model $SYSTEM_MODEL is currently not supported"
return 1
;;
esac
BIOS_LINK_COMM="$FW_STORE_URL/$DASHARO_REL_NAME/v$DASHARO_REL_VER/${DASHARO_REL_NAME}_v${DASHARO_REL_VER}.rom"
EC_LINK_COMM="$FW_STORE_URL/$DASHARO_REL_NAME/v$DASHARO_REL_VER/${DASHARO_REL_NAME}_ec_v${DASHARO_REL_VER}.rom"
;;
"NovaCustom" | "ASRock Industrial")
if ! parse_and_verify_config "$SYSTEM_VENDOR" "$SYSTEM_MODEL" "$BOARD_MODEL"; then
return 1
fi
BIOS_LINK_COMM="${FW_STORE_URL}/${DASHARO_REL_NAME}/uefi/v${DASHARO_REL_VER}/${DASHARO_REL_NAME}_v${DASHARO_REL_VER}.rom"
;;
"Micro-Star International Co., Ltd.")
BUCKET_DPP="dasharo-msi-uefi"
BUCKET_DPP_HEADS="dasharo-msi-heads"
case "$SYSTEM_MODEL" in
"MS-7D25")
# Common configuration for all MS-7D25:
DASHARO_REL_NAME="msi_ms7d25"
DASHARO_REL_VER="1.1.1"
DASHARO_REL_VER_DPP="1.1.4"
CAN_INSTALL_BIOS="true"
HAVE_HEADS_FW="true"
HEADS_REL_VER_DPP="0.9.0"
HEADS_SWITCH_FLASHROM_OPT_OVERRIDE="--ifd -i bios"
PLATFORM_SIGN_KEY="dasharo/msi_ms7d25/dasharo-release-1.x-compatible-with-msi-ms-7d25-signing-key.asc \
dasharo/msi_ms7d25/dasharo-release-0.x-compatible-with-msi-ms-7d25-signing-key.asc"
NEED_SMBIOS_MIGRATION="true"
NEED_SMMSTORE_MIGRATION="true"
NEED_ROMHOLE_MIGRATION="true"
# Add capsules:
DASHARO_REL_NAME_CAP="$DASHARO_REL_NAME"
DASHARO_REL_VER_DPP_CAP="$DASHARO_REL_VER_DPP"
DASHARO_SUPPORT_CAP_FROM="1.1.4"
# flash the whole bios region
# TODO: Let DTS determine which parameters are suitable.
# FIXME: Can we ever get rid of that? We change so much in each release,
# that we almost always need to flash whole BIOS region
# because of non-backward compatible or breaking changes.
NEED_BOOTSPLASH_MIGRATION="true"
FLASHROM_ADD_OPT_UPDATE_OVERRIDE="--ifd -i bios"
case "$BOARD_MODEL" in
"PRO Z690-A WIFI DDR4(MS-7D25)" | "PRO Z690-A DDR4(MS-7D25)")
BIOS_LINK_COMM="${FW_STORE_URL}/${DASHARO_REL_NAME}/v${DASHARO_REL_VER}/${DASHARO_REL_NAME}_v${DASHARO_REL_VER}_ddr4.rom"
BIOS_LINK_DPP="${BUCKET_DPP}/MS-7D25/v${DASHARO_REL_VER_DPP}/${DASHARO_REL_NAME}_v${DASHARO_REL_VER_DPP}_ddr4.rom"
BIOS_LINK_DPP_CAP="${BUCKET_DPP_HEADS}/MS-7D25/v${DASHARO_REL_VER_DPP_CAP}/${DASHARO_REL_NAME_CAP}_v${DASHARO_REL_VER_DPP_CAP}_ddr4.cap"
HEADS_LINK_DPP="${BUCKET_DPP_HEADS}/MS-7D25/v${HEADS_REL_VER_DPP}/${DASHARO_REL_NAME}_v${HEADS_REL_VER_DPP}_ddr4_heads.rom"
;;
"PRO Z690-A WIFI (MS-7D25)" | "PRO Z690-A (MS-7D25)")
BIOS_LINK_COMM="${FW_STORE_URL}/${DASHARO_REL_NAME}/v${DASHARO_REL_VER}/${DASHARO_REL_NAME}_v${DASHARO_REL_VER}_ddr5.rom"
BIOS_LINK_DPP="${BUCKET_DPP}/MS-7D25/v${DASHARO_REL_VER_DPP}/${DASHARO_REL_NAME}_v${DASHARO_REL_VER_DPP}_ddr5.rom"
BIOS_LINK_DPP_CAP="${BUCKET_DPP}/MS-7D25/v${DASHARO_REL_VER_DPP_CAP}/${DASHARO_REL_NAME_CAP}_v${DASHARO_REL_VER_DPP_CAP}_ddr5.cap"
HEADS_LINK_DPP="${BUCKET_DPP_HEADS}/MS-7D25/v${HEADS_REL_VER_DPP}/${DASHARO_REL_NAME}_v${HEADS_REL_VER_DPP}_ddr5_heads.rom"
;;
*)
print_error "Board model $BOARD_MODEL is currently not supported"
return 1
;;
esac
;;
"MS-7E06")
# Common configuration for all MS-7E06:
DASHARO_REL_NAME="msi_ms7e06"
#DASHARO_REL_VER=""
DASHARO_REL_VER_DPP="0.9.2"
CAN_INSTALL_BIOS="true"
HAVE_HEADS_FW="true"
HEADS_REL_VER_DPP="0.9.0"
HEADS_SWITCH_FLASHROM_OPT_OVERRIDE="--ifd -i bios"
PLATFORM_SIGN_KEY="dasharo/msi_ms7e06/dasharo-release-0.x-compatible-with-msi-ms-7e06-signing-key.asc"
NEED_SMMSTORE_MIGRATION="true"
NEED_ROMHOLE_MIGRATION="true"
# Add capsules:
DASHARO_REL_NAME_CAP="$DASHARO_REL_NAME"
DASHARO_REL_VER_DPP_CAP="$DASHARO_REL_VER_DPP"
DASHARO_SUPPORT_CAP_FROM="0.9.2"
# flash the whole bios region
# TODO: Let DTS determine which parameters are suitable.
# FIXME: Can we ever get rid of that? We change so much in each release,
# that we almost always need to flash whole BIOS region
# because of non-backward compatible or breaking changes.
NEED_BOOTSPLASH_MIGRATION="true"
FLASHROM_ADD_OPT_UPDATE_OVERRIDE="--ifd -i bios"
case "$BOARD_MODEL" in
"PRO Z790-P WIFI DDR4(MS-7E06)" | "PRO Z790-P DDR4(MS-7E06)" | "PRO Z790-P WIFI DDR4 (MS-7E06)" | "PRO Z790-P DDR4 (MS-7E06)")
#BIOS_LINK_COMM="$FW_STORE_URL/$DASHARO_REL_NAME/v$DASHARO_REL_VER/${DASHARO_REL_NAME}_v${DASHARO_REL_VER}_ddr4.rom"
BIOS_LINK_DPP="${BUCKET_DPP}/MS-7E06/v${DASHARO_REL_VER_DPP}/${DASHARO_REL_NAME}_v${DASHARO_REL_VER_DPP}_ddr4.rom"
BIOS_LINK_DPP_CAP="${BUCKET_DPP}/MS-7E06/v${DASHARO_REL_VER_DPP_CAP}/${DASHARO_REL_NAME_CAP}_v${DASHARO_REL_VER_DPP_CAP}_ddr4.cap"
HEADS_LINK_DPP="${BUCKET_DPP_HEADS}/MS-7E06/v${HEADS_REL_VER_DPP}/${DASHARO_REL_NAME}_v${HEADS_REL_VER_DPP}_ddr4_heads.rom"
PROGRAMMER_BIOS="internal:boardmismatch=force"
;;
"PRO Z790-P WIFI (MS-7E06)" | "PRO Z790-P (MS-7E06)")
#BIOS_LINK_COMM="$FW_STORE_URL/$DASHARO_REL_NAME/v$DASHARO_REL_VER/${DASHARO_REL_NAME}_v${DASHARO_REL_VER}_ddr5.rom"
BIOS_LINK_DPP="${BUCKET_DPP}/MS-7E06/v${DASHARO_REL_VER_DPP}/${DASHARO_REL_NAME}_v${DASHARO_REL_VER_DPP}_ddr5.rom"
BIOS_LINK_DPP_CAP="${BUCKET_DPP}/MS-7E06/v${DASHARO_REL_VER_DPP_CAP}/${DASHARO_REL_NAME_CAP}_v${DASHARO_REL_VER_DPP_CAP}_ddr5.cap"
HEADS_LINK_DPP="${BUCKET_DPP_HEADS}/MS-7E06/v${HEADS_REL_VER_DPP}/${DASHARO_REL_NAME}_v${HEADS_REL_VER_DPP}_ddr5_heads.rom"
;;
*)
print_error "Board model $BOARD_MODEL is currently not supported"
return 1
;;
esac
;;
*)
print_error "Board model $SYSTEM_MODEL is currently not supported"
return 1
;;
esac
;;
"Dell Inc.")
# Common configuration for all Dell releases:
BUCKET_DPP="dasharo-optiplex-uefi"
DASHARO_REL_NAME="dell_optiplex_7010_9010"
DASHARO_REL_VER_DPP="0.1.1"
BIOS_LINK_DPP="$BUCKET_DPP/v$DASHARO_REL_VER_DPP/${DASHARO_REL_NAME}_v$DASHARO_REL_VER_DPP.rom"
CAN_INSTALL_BIOS="true"
NEED_SMBIOS_MIGRATION="true"
NEED_BLOB_TRANSMISSION="true"
SINIT_ACM_FILENAME="SNB_IVB_SINIT_20190708_PW.bin"
SINIT_ACM_HASH_FILENAME="${SINIT_ACM_FILENAME}.sha256"
ACM_MIRROR_URL="https://dl.3mdeb.com/mirror/intel/acm"
SINIT_ACM_URL="${ACM_MIRROR_URL}/${SINIT_ACM_FILENAME}"
SINIT_ACM_HASH_URL="${ACM_MIRROR_URL}/${SINIT_ACM_HASH_FILENAME}"
SINIT_ACM="/tmp/${SINIT_ACM_FILENAME}"
FLASHROM_ADD_OPT_DEPLOY="--ifd -i bios"
FLASHROM_ADD_OPT_UPDATE="--fmap -i RW_SECTION_A"
case "$SYSTEM_MODEL" in
"OptiPlex 7010")
DBT_BIOS_UPDATE_FILENAME="/tmp/O7010A29.exe"
DBT_BIOS_UPDATE_URL="https://dl.dell.com/FOLDER05066036M/1/O7010A29.exe"
DBT_BIOS_UPDATE_HASH="ceb82586c67cd8d5933ac858c12e0cb52f6e0e4cb3249f964f1c0cfc06d16f52 $DBT_BIOS_UPDATE_FILENAME"
DBT_UEFI_IMAGE="/tmp/_O7010A29.exe.extracted/65C10"
SCH5545_FW="/tmp/_O7010A29.exe.extracted/65C10_output/pfsobject/section-7ec6c2b0-3fe3-42a0-a316-22dd0517c1e8/volume-0x50000/file-d386beb8-4b54-4e69-94f5-06091f67e0d3/section0.raw"
ACM_BIN="/tmp/_O7010A29.exe.extracted/65C10_output/pfsobject/section-7ec6c2b0-3fe3-42a0-a316-22dd0517c1e8/volume-0x500000/file-2d27c618-7dcd-41f5-bb10-21166be7e143/object-0.raw"
;;
"OptiPlex 9010")
DBT_BIOS_UPDATE_FILENAME="/tmp/O9010A30.exe"
DBT_BIOS_UPDATE_URL="https://dl.dell.com/FOLDER05066009M/1/O9010A30.exe"
DBT_BIOS_UPDATE_HASH="b11952f43d0ad66f3ce79558b8c5dd43f30866158ed8348e3b2dae1bbb07701b $DBT_BIOS_UPDATE_FILENAME"
DBT_UEFI_IMAGE="/tmp/_O9010A30.exe.extracted/65C10"
SCH5545_FW="/tmp/_O9010A30.exe.extracted/65C10_output/pfsobject/section-7ec6c2b0-3fe3-42a0-a316-22dd0517c1e8/volume-0x50000/file-d386beb8-4b54-4e69-94f5-06091f67e0d3/section0.raw"
ACM_BIN="/tmp/_O9010A30.exe.extracted/65C10_output/pfsobject/section-7ec6c2b0-3fe3-42a0-a316-22dd0517c1e8/volume-0x500000/file-2d27c618-7dcd-41f5-bb10-21166be7e143/object-0.raw"
;;
"Precision T1650")
# tested on Dasharo Firmware for OptiPlex 9010, will need to be
# enabled when build for T1650 exists
#
# DBT_BIOS_UPDATE_FILENAME="/tmp/T1650A28.exe"
# DBT_BIOS_UPDATE_URL="https://dl.dell.com/FOLDER05065992M/1/T1650A28.exe"
# DBT_BIOS_UPDATE_HASH="40a66210b8882f523885849c1d879e726dc58aa14718168b1e75f3e2caaa523b $DBT_BIOS_UPDATE_FILENAME"
# DBT_UEFI_IMAGE="/tmp/_T1650A28.exe.extracted/65C10"
# SCH5545_FW="/tmp/_T1650A28.exe.extracted/65C10_output/pfsobject/section-7ec6c2b0-3fe3-42a0-a316-22dd0517c1e8/volume-0x60000/file-d386beb8-4b54-4e69-94f5-06091f67e0d3/section0.raw"
# ACM_BIN="/tmp/_T1650A28.exe.extracted/65C10_output/pfsobject/section-7ec6c2b0-3fe3-42a0-a316-22dd0517c1e8/volume-0x500000/file-2d27c618-7dcd-41f5-bb10-21166be7e143/object-0.raw"
print_warning "Dasharo Firmware for Precision T1650 not available yet!"
print_error "Board model $SYSTEM_MODEL is currently not supported"
return 1
;;
*)
print_error "Board model $SYSTEM_MODEL is currently not supported"
return 1
;;
esac
;;
"ASUS")
case "$SYSTEM_MODEL" in
"KGPE-D16")
DASHARO_REL_NAME="asus_kgpe-d16"
DASHARO_REL_VER="0.4.0"
CAN_INSTALL_BIOS="true"
case "$FLASH_CHIP_SIZE" in
"2")
BIOS_HASH_LINK_COMM="65e5370e9ea6b8ae7cd6cc878a031a4ff3a8f5d36830ef39656b8e5a6e37e889 $BIOS_UPDATE_FILE"
BIOS_LINK_COMM="$FW_STORE_URL/$DASHARO_REL_NAME/v$DASHARO_REL_VER/${DASHARO_REL_NAME}_v${DASHARO_REL_VER}_vboot_notpm.rom"
;;
"8")
BIOS_HASH_LINK_COMM="da4e6217d50f2ac199dcb9a927a0bc02aa4e792ed73c8c9bac8ba74fc787dbef $BIOS_UPDATE_FILE"
BIOS_LINK_COMM="$FW_STORE_URL/$DASHARO_REL_NAME/v$DASHARO_REL_VER/${DASHARO_REL_NAME}_v${DASHARO_REL_VER}_${FLASH_CHIP_SIZE}M_vboot_notpm.rom"
;;
"16")
BIOS_HASH_LINK_COMM="20055cf57185f149259706f58d5e9552a1589259c6617999c1ac7d8d3c960020 $BIOS_UPDATE_FILE"
BIOS_LINK_COMM="$FW_STORE_URL/$DASHARO_REL_NAME/v$DASHARO_REL_VER/${DASHARO_REL_NAME}_v${DASHARO_REL_VER}_${FLASH_CHIP_SIZE}M_vboot_notpm.rom"
;;
*)
print_error "Platform uses chipset with not supported size"
return 1
;;
esac
NEED_SMBIOS_MIGRATION="true"
;;
*)
print_error "Board model $SYSTEM_MODEL is currently not supported"
return 1
;;
esac
;;
"PC Engines")
if ! parse_and_verify_config "$SYSTEM_VENDOR" "$SYSTEM_MODEL" "$BOARD_MODEL"; then
return 1
fi
BIOS_LINK_DPP="${BUCKET_DPP}/v${DASHARO_REL_VER_DPP}/${DASHARO_REL_NAME}_v${DASHARO_REL_VER_DPP}.rom"
BIOS_LINK_DPP_SEABIOS="${BUCKET_DPP_SEABIOS}/pcengines_apu2/v${DASHARO_REL_VER_DPP_SEABIOS}/${DASHARO_REL_NAME}_seabios_v${DASHARO_REL_VER_DPP_SEABIOS}.rom"
;;
"HARDKERNEL")
case "$SYSTEM_MODEL" in
"ODROID-H4")
if ! parse_and_verify_config "$SYSTEM_VENDOR" "$SYSTEM_MODEL" "$BOARD_MODEL"; then
return 1
fi
;;
*)
print_error "Board model $SYSTEM_MODEL is currently not supported"
return 1
;;
esac
BIOS_LINK_DPP="$BUCKET_DPP/$DASHARO_REL_NAME/v$DASHARO_REL_VER_DPP/${DASHARO_REL_NAME}_v$DASHARO_REL_VER_DPP.rom"
# TODO: check if it really will be called "*_slimuefi_*.rom"
BIOS_LINK_DPP_SLIMUEFI="${BUCKET_DPP_SLIMUEFI}/${DASHARO_REL_NAME}/v${DASHARO_REL_VER_DPP_SLIMUEFI}/${DASHARO_REL_NAME}_v${DASHARO_REL_VER_DPP_SLIMUEFI}_slim_bootloader_uefi.rom"
;;
"QEMU" | "Emulation")
case "$SYSTEM_MODEL" in
*Q35*ICH9* | *q35*ich9*)
# Update type:
CAN_INSTALL_BIOS="true"
# Download and versioning variables:
DASHARO_REL_NAME_CAP="qemu_q35"
DASHARO_REL_VER_CAP="0.2.0"
DASHARO_SUPPORT_CAP_FROM="0.2.0"
# TODO: wait till the binaries will be uploaded to the server.
BIOS_LINK_COMM_CAP="${FW_STORE_URL}/${DASHARO_REL_NAME_CAP}/v${DASHARO_REL_VER_CAP}/"
;;
*)
print_error "Board model $SYSTEM_MODEL is currently not supported"
return 1
;;
esac
;;
"To Be Filled By O.E.M.")
print_error "Cannot determine board vendor"
return 1
;;
*)
print_error "Board vendor: $SYSTEM_VENDOR is currently not supported"
return 1
;;
esac
# Set some default values at the end:
[ -z "$BIOS_HASH_LINK_COMM" ] && BIOS_HASH_LINK_COMM="${BIOS_LINK_COMM}.sha256"
[ -z "$BIOS_SIGN_LINK_COMM" ] && BIOS_SIGN_LINK_COMM="${BIOS_HASH_LINK_COMM}.sig"
[ -z "$BIOS_HASH_LINK_DPP" ] && BIOS_HASH_LINK_DPP="${BIOS_LINK_DPP}.sha256"
[ -z "$BIOS_SIGN_LINK_DPP" ] && BIOS_SIGN_LINK_DPP="${BIOS_HASH_LINK_DPP}.sig"
[ -z "$BIOS_HASH_LINK_DPP_SEABIOS" ] && BIOS_HASH_LINK_DPP_SEABIOS="${BIOS_LINK_DPP_SEABIOS}.sha256"
[ -z "$BIOS_SIGN_LINK_DPP_SEABIOS" ] && BIOS_SIGN_LINK_DPP_SEABIOS="${BIOS_HASH_LINK_DPP_SEABIOS}.sig"
[ -z "$HEADS_HASH_LINK_DPP" ] && HEADS_HASH_LINK_DPP="${HEADS_LINK_DPP}.sha256"
[ -z "$HEADS_SIGN_LINK_DPP" ] && HEADS_SIGN_LINK_DPP="${HEADS_HASH_LINK_DPP}.sig"
[ -z "$BIOS_HASH_LINK_DPP_SLIMUEFI" ] && BIOS_HASH_LINK_DPP_SLIMUEFI="${BIOS_LINK_DPP_SLIMUEFI}.sha256"
[ -z "$BIOS_SIGN_LINK_DPP_SLIMUEFI" ] && BIOS_SIGN_LINK_DPP_SLIMUEFI="${BIOS_HASH_LINK_DPP_SLIMUEFI}.sig"
[ -z "$EC_HASH_LINK_COMM" ] && EC_HASH_LINK_COMM="${EC_LINK_COMM}.sha256"
[ -z "$EC_SIGN_LINK_COMM" ] && EC_SIGN_LINK_COMM="${EC_HASH_LINK_COMM}.sig"
[ -z "$EC_HASH_LINK_DPP" ] && EC_HASH_LINK_DPP="${EC_LINK_DPP}.sha256"
[ -z "$EC_SIGN_LINK_DPP" ] && EC_SIGN_LINK_DPP="${EC_HASH_LINK_DPP}.sig"
[ -z "$HEADS_EC_HASH_LINK_DPP" ] && HEADS_EC_HASH_LINK_DPP="${HEADS_EC_LINK_DPP}.sha256"
[ -z "$HEADS_EC_SIGN_LINK_DPP" ] && HEADS_EC_SIGN_LINK_DPP="${HEADS_EC_HASH_LINK_DPP}.sig"
# And for capsules as well:
[ -z "$BIOS_HASH_LINK_COMM_CAP" ] && BIOS_HASH_LINK_COMM_CAP="${BIOS_LINK_COMM_CAP}.sha256"
[ -z "$BIOS_SIGN_LINK_COMM_CAP" ] && BIOS_SIGN_LINK_COMM_CAP="${BIOS_HASH_LINK_COMM_CAP}.sig"
[ -z "$BIOS_HASH_LINK_DPP_CAP" ] && BIOS_HASH_LINK_DPP_CAP="${BIOS_LINK_DPP_CAP}.sha256"
[ -z "$BIOS_SIGN_LINK_DPP_CAP" ] && BIOS_SIGN_LINK_DPP_CAP="${BIOS_HASH_LINK_DPP_CAP}.sig"
[ -z "$EC_HASH_LINK_COMM_CAP" ] && EC_HASH_LINK_COMM_CAP="${EC_LINK_COMM_CAP}.sha256"
[ -z "$EC_SIGN_LINK_COMM_CAP" ] && EC_SIGN_LINK_COMM_CAP="${EC_HASH_LINK_COMM_CAP}.sig"
[ -z "$EC_HASH_LINK_DPP_CAP" ] && EC_HASH_LINK_DPP_CAP="${EC_LINK_DPP_CAP}.sha256"
[ -z "$EC_SIGN_LINK_DPP_CAP" ] && EC_SIGN_LINK_DPP_CAP="${EC_HASH_LINK_DPP_CAP}.sig"
rm -rf "$BOARD_CONFIG_PATH"
}
check_flash_lock() {
$FLASHROM check_flash_lock_mock -p "$PROGRAMMER_BIOS" ${FLASH_CHIP_SELECT} >/tmp/check_flash_lock 2>/tmp/check_flash_lock.err
# Check in flashrom output if lock is enabled
grep -q 'PR0: Warning:.* is read-only\|SMM protection is enabled' /tmp/check_flash_lock.err
if [ $? -eq 0 ]; then
print_warning "Flash lock enabled, please go into BIOS setup / Dasharo System Features / Dasharo\r
\rSecurity Options and enable access to flash with flashrom.\r\n
\rYou can learn more about this on: https://docs.dasharo.com/dasharo-menu-docs/dasharo-system-features/#dasharo-security-options"
exit 1
fi
}
check_flash_chip() {
echo "Gathering flash chip and chipset information..."
$FLASHROM flash_chip_name_mock -p "$PROGRAMMER_BIOS" --flash-name >>"$FLASH_INFO_FILE" 2>>"$ERR_LOG_FILE"
if [ $? -eq 0 ]; then
echo -n "Flash information: "
tail -n1 "$FLASH_INFO_FILE"
FLASH_CHIP_SIZE=$(($($FLASHROM flash_chip_size_mock -p "$PROGRAMMER_BIOS" --flash-size 2>>"$ERR_LOG_FILE" | tail -n1) / 1024 / 1024))
echo -n "Flash size: "
echo ${FLASH_CHIP_SIZE}M
else
for flash_name in $FLASH_CHIP_LIST; do
$FLASHROM flash_chip_name_mock -p "$PROGRAMMER_BIOS" -c "$flash_name" --flash-name >>"$FLASH_INFO_FILE" 2>>"$ERR_LOG_FILE"
if [ $? -eq 0 ]; then
echo "Chipset found"
tail -n1 "$FLASH_INFO_FILE"
FLASH_CHIP_SELECT="-c ${flash_name}"
FLASH_CHIP_SIZE=$(($($FLASHROM flash_chip_size_mock -p "$PROGRAMMER_BIOS" ${FLASH_CHIP_SELECT} --flash-size 2>>"$ERR_LOG_FILE" | tail -n1) / 1024 / 1024))
echo "Chipset size"
echo ${FLASH_CHIP_SIZE}M
break
fi
done
if [ -z "$FLASH_CHIP_SELECT" ]; then
return 1
fi
fi
return 0
}
compare_versions() {
# return 1 if ver2 > ver1
# return 0 otherwise
local ver1=
local ver2=
local compare=
# convert version ending with '-rc<x>' to '-rc.<x>' where <x> is number
# as semantic versioning compares whole 'rc<x>' as alphanumeric identifier
# which results in rc2 > rc12. More information at https://semver.org/
ver1=$(sed -r "s/-rc([0-9]+)$/-rc.\1/" <<<"$1")
ver2=$(sed -r "s/-rc([0-9]+)$/-rc.\1/" <<<"$2")
# convert SeaBIOS versioning x.x.x.x to x.x.x-x so it can be used with semver
# checker. Also remove leading zeroes as it's not allowed in semver
# specification. In case x are only zeroes then leave only one zero
dot_to_dash='s/([0-9]+\.[0-9]+\.[0-9]+)\.([0-9]+)/\1-\2/'
leading_zeroes='s/(^|\.)0+(0|[1-9])/\1\2/g'
ver1=$(sed -r -e "$leading_zeroes" -e "$dot_to_dash" <<<"$ver1")
ver2=$(sed -r -e "$leading_zeroes" -e "$dot_to_dash" <<<"$ver2")
if ! python3 -m semver check "$ver1" || ! python3 -m semver check "$ver2"; then
error_exit "Incorrect version format"
fi
compare=$(python3 -m semver compare "$ver1" "$ver2")
if [ "$compare" -eq -1 ]; then
return 1
else
return 0
fi
}
download_bios() {
echo "Downloading Dasharo firmware..."
if [ "${BIOS_LINK}" == "${BIOS_LINK_COMM}" ] || [ "${BIOS_LINK}" == "${BIOS_LINK_COMM_CAP}" ]; then
curl -s -S -L -f "$BIOS_LINK" -o $BIOS_UPDATE_FILE 2>>"$ERR_LOG_FILE"
error_check "Cannot access $FW_STORE_URL while downloading binary. Please
check your internet connection"
curl -s -S -L -f "$BIOS_HASH_LINK" -o $BIOS_HASH_FILE 2>>"$ERR_LOG_FILE"
error_check "Cannot access $FW_STORE_URL while downloading signature. Please
check your internet connection"
curl -s -S -L -f "$BIOS_SIGN_LINK" -o $BIOS_SIGN_FILE 2>>"$ERR_LOG_FILE"
error_check "Cannot access $FW_STORE_URL while downloading signature. Please
check your internet connection"
else
mc get "${DPP_SERVER_USER_ALIAS}/$BIOS_LINK" "$BIOS_UPDATE_FILE" >/dev/null 2>>"$ERR_LOG_FILE"
error_check "Cannot access $FW_STORE_URL_DPP while downloading binary.
Please check your internet connection and credentials"
mc get "${DPP_SERVER_USER_ALIAS}/$BIOS_HASH_LINK" "$BIOS_HASH_FILE" >/dev/null 2>>"$ERR_LOG_FILE"
error_check "Cannot access $FW_STORE_URL_DPP while downloading signature.
Please check your internet connection and credentials"
mc get "${DPP_SERVER_USER_ALIAS}/$BIOS_SIGN_LINK" "$BIOS_SIGN_FILE" >/dev/null 2>>"$ERR_LOG_FILE"
error_check "Cannot access $FW_STORE_URL_DPP while downloading signature.
Please check your internet connection and credentials"
fi
}
download_ec() {
echo "Downloading Dasharo EC firmware..."
if [ "${EC_LINK}" == "${EC_LINK_COMM}" ]; then
curl -s -S -L -f "$EC_LINK" -o "$EC_UPDATE_FILE" 2>>"$ERR_LOG_FILE"
error_check "Cannot access $FW_STORE_URL while downloading binary. Please
check your internet connection"
curl -s -S -L -f "$EC_HASH_LINK" -o $EC_HASH_FILE 2>>"$ERR_LOG_FILE"
error_check "Cannot access $FW_STORE_URL while downloading signature. Please
check your internet connection"
curl -s -S -L -f "$EC_SIGN_LINK" -o $EC_SIGN_FILE 2>>"$ERR_LOG_FILE"
error_check "Cannot access $FW_STORE_URL while downloading signature. Please
check your internet connection"
else
mc get "${DPP_SERVER_USER_ALIAS}/${EC_LINK}" "$EC_UPDATE_FILE" >/dev/null 2>>"$ERR_LOG_FILE"
error_check "Cannot access $FW_STORE_URL_DPP while downloading binary. Please
check your internet connection and credentials"
mc get "${DPP_SERVER_USER_ALIAS}/${EC_HASH_LINK}" "$EC_HASH_FILE" >/dev/null 2>>"$ERR_LOG_FILE"
error_check "Cannot access $FW_STORE_URL_DPP while downloading signature. Please
check your internet connection and credentials"
mc get "${DPP_SERVER_USER_ALIAS}/${EC_SIGN_LINK}" "$EC_SIGN_FILE" >/dev/null 2>>"$ERR_LOG_FILE"
error_check "Cannot access $FW_STORE_URL_DPP while downloading signature. Please
check your internet connection and credentials"
fi
}
download_keys() {
mkdir -p $KEYS_DIR
wget -O $KEYS_DIR/recovery_key.vbpubk https://github.com/Dasharo/vboot/raw/dasharo/tests/devkeys/recovery_key.vbpubk >>$ERR_LOG_FILE 2>&1
wget -O $KEYS_DIR/firmware.keyblock https://github.com/Dasharo/vboot/raw/dasharo/tests/devkeys/firmware.keyblock >>$ERR_LOG_FILE 2>&1
wget -O $KEYS_DIR/firmware_data_key.vbprivk https://github.com/Dasharo/vboot/raw/dasharo/tests/devkeys/firmware_data_key.vbprivk >>$ERR_LOG_FILE 2>&1
wget -O $KEYS_DIR/kernel_subkey.vbpubk https://github.com/Dasharo/vboot/raw/dasharo/tests/devkeys/kernel_subkey.vbpubk >>$ERR_LOG_FILE 2>&1
wget -O $KEYS_DIR/root_key.vbpubk https://github.com/Dasharo/vboot/raw/dasharo/tests/devkeys/root_key.vbpubk >>$ERR_LOG_FILE 2>&1
}
get_signing_keys() {
local platform_keys=$PLATFORM_SIGN_KEY
echo -n "Getting platform specific GPG key... "
for key in $platform_keys; do
wget -q https://raw.githubusercontent.com/3mdeb/3mdeb-secpack/master/$key -O - | gpg --import - >>$ERR_LOG_FILE 2>&1
error_check "Cannot get $key key to verify signatures."
done
print_ok "Done"
}
verify_artifacts() {
# This function checks downloaded files, the files that are being downloaded
# should have hashes provided on the server too. The hashes will ben downloaded
# and the binaries will be verified upon them.
#
# In case of .rom files it will be enough but capsules have additional
# protection layer built in, the binaries they provide will be verified by
# drivers, so no need to implement it here.
local _update_file=""
local _hash_file=""
local _sign_file=""
local _name=""
local _sig_result=""
while [[ $# -gt 0 ]]; do
local _type="$1"
case $_type in
ec)
_update_file=$EC_UPDATE_FILE
_hash_file=$EC_HASH_FILE
_sign_file=$EC_SIGN_FILE
_name="Dasharo EC"
shift
;;
bios)
_update_file=$BIOS_UPDATE_FILE
_hash_file=$BIOS_HASH_FILE
_sign_file=$BIOS_SIGN_FILE
_name="Dasharo"
shift
;;
*)
error_exit "Unknown artifact type: $_type"
;;
esac
echo -n "Checking $_name firmware checksum... "
sha256sum --check <(echo "$(cat $_hash_file | cut -d ' ' -f 1)" $_update_file) >>$ERR_LOG_FILE 2>&1
error_check "Failed to verify $_name firmware checksum"
print_ok "Verified."
if [ -n "$PLATFORM_SIGN_KEY" ]; then
echo -n "Checking $_name firmware signature... "
_sig_result="$(cat $_hash_file | gpg --verify $_sign_file - >>$ERR_LOG_FILE 2>&1)"
error_check "Failed to verify $_name firmware signature.$'\n'$_sig_result"
print_ok "Verified."
fi
echo "$_sig_result"
done
return 0
}
check_intel_regions() {
FLASH_REGIONS=$($FLASHROM check_intel_regions_mock -p "$PROGRAMMER_BIOS" ${FLASH_CHIP_SELECT} 2>&1)
BOARD_HAS_FD_REGION=0
BOARD_FD_REGION_RW=0
BOARD_HAS_ME_REGION=0
BOARD_ME_REGION_RW=0
BOARD_ME_REGION_LOCKED=0
BOARD_HAS_GBE_REGION=0
BOARD_GBE_REGION_RW=0
BOARD_GBE_REGION_LOCKED=0
grep -q "Flash Descriptor region" <<<"$FLASH_REGIONS" && BOARD_HAS_FD_REGION=1
grep -qE "Flash Descriptor region.*read-write" <<<"$FLASH_REGIONS" && BOARD_FD_REGION_RW=1
grep -q "Management Engine region" <<<"$FLASH_REGIONS" && BOARD_HAS_ME_REGION=1
grep -qE "Management Engine region.*read-write" <<<"$FLASH_REGIONS" && BOARD_ME_REGION_RW=1
grep -qE "Management Engine region.*locked" <<<"$FLASH_REGIONS" && BOARD_ME_REGION_LOCKED=1
grep -q "Gigabit Ethernet region" <<<"$FLASH_REGIONS" && BOARD_HAS_GBE_REGION=1
grep -qE "Gigabit Ethernet region.*read-write" <<<"$FLASH_REGIONS" && BOARD_GBE_REGION_RW=1
grep -qE "Gigabit Ethernet region.*locked" <<<"$FLASH_REGIONS" && BOARD_GBE_REGION_LOCKED=1
}
check_blobs_in_binary() {
BINARY_HAS_FD=0
BINARY_HAS_ME=0
# If there is no descriptor, there is no ME as well, so skip the check
if [ $BOARD_HAS_FD_REGION -ne 0 ]; then
ME_OFFSET=$($IFDTOOL check_blobs_in_binary_mock -d $1 2>>"$ERR_LOG_FILE" | grep "Flash Region 2 (Intel ME):" | sed 's/Flash Region 2 (Intel ME)\://' | awk '{print $1;}')
# Check for IFD signature at offset 0 (old descriptors)
if [ "$(tail -c +0 $1 | head -c 4 | xxd -ps)" == "5aa5f00f" ]; then
BINARY_HAS_FD=1
fi
# Check for IFD signature at offset 16 (new descriptors)
if [ "$(tail -c +17 $1 | head -c 4 | xxd -ps)" == "5aa5f00f" ]; then
BINARY_HAS_FD=1
fi
# Check for ME FPT signature at ME offset + 16 (old ME)
if [ "$(tail -c +$((0x$ME_OFFSET + 17)) $1 | head -c 4 | tr -d '\0')" == "\$FPT" ]; then
BINARY_HAS_ME=1
fi
# Check for aa55 signature at ME offset + 4096 (new ME)
if [ "$(tail -c +$((0x$ME_OFFSET + 4097)) $1 | head -c 2 | xxd -ps)" == "aa55" ]; then
BINARY_HAS_ME=1
fi
fi
}
check_if_me_disabled() {
ME_DISABLED=0
if [ $BOARD_HAS_ME_REGION -eq 0 ]; then
# No ME region
ME_DISABLED=1
return
fi
if check_if_heci_present; then
ME_OPMODE="$(check_me_op_mode)"
if [ $ME_OPMODE == "0" ]; then
echo "ME is not disabled" >>$ERR_LOG_FILE
return
elif [ $ME_OPMODE == "2" ]; then
echo "ME is disabled (HAP/Debug Mode)" >>$ERR_LOG_FILE
ME_DISABLED=1
return
elif [ $ME_OPMODE == "3" ]; then
echo "ME is soft disabled (HECI)" >>$ERR_LOG_FILE
ME_DISABLED=1
return
elif [ $ME_OPMODE == "4" ]; then
echo "ME disabled by Security Override Jumper/FDOPS" >>$ERR_LOG_FILE
ME_DISABLED=1
return
elif [ $ME_OPMODE == "5" ]; then
echo "ME disabled by Security Override MEI Message/HMRFPO" >>$ERR_LOG_FILE
ME_DISABLED=1
return
elif [ $ME_OPMODE == "6" ]; then
echo "ME disabled by Security Override MEI Message/HMRFPO" >>$ERR_LOG_FILE
ME_DISABLED=1
return
elif [ $ME_OPMODE == "7" ]; then
echo "ME disabled (Enhanced Debug Mode) or runs Ignition FW" >>$ERR_LOG_FILE
ME_DISABLED=1
return
else
print_warning "Unknown ME operation mode, assuming enabled."
echo "Unknown ME operation mode, assuming enabled." >>$ERR_LOG_FILE
return
fi
else
# If we are running coreboot, check for status in logs
$CBMEM check_if_me_disabled_mock -1 |
grep "ME is disabled" &>/dev/null && ME_DISABLED=1 && return # HECI (soft) disabled
$CBMEM check_if_me_disabled_mock -1 |
grep "ME is HAP disabled" &>/dev/null && ME_DISABLED=1 && return # HAP disabled
# TODO: If proprietary BIOS, then also try to check SMBIOS for ME FWSTS
# BTW we could do the same in coreboot, expose FWSTS in SMBIOS before it
# gets disabled
print_warning "Can not determine if ME is disabled, assuming enabled."
echo "Can not determine if ME is disabled, assuming enabled." >>$ERR_LOG_FILE
fi
}
force_me_update() {
echo
print_warning "Flashing ME when not in disabled state may cause unexpected power management issues."
print_warning "Recovering from such state may require removal of AC power supply and resetting CMOS battery."
print_warning "Keeping an older version of ME may cause a CPU to perform less efficient, e.g. if upgraded the CPU to a newer generation."
print_warning "You have been warned."
while :; do
echo
read -r -p "Skip ME flashing and proceed with BIOS/firmware flashing/updating? (Y|n) " OPTION
echo
case ${OPTION} in
yes | y | Y | Yes | YES)
print_warning "Proceeding without ME flashing, because we were asked to."
break
;;
n | N)
error_exit "Cancelling flashing process..."
;;
*) ;;
esac
done
}
set_flashrom_update_params() {
local bios_update_file=$1
# Safe defaults which should always work
if [ $BOARD_HAS_FD_REGION -eq 0 ]; then
FLASHROM_ADD_OPT_UPDATE=""
else
FLASHROM_ADD_OPT_UPDATE="-N --ifd -i bios"
fi
BINARY_HAS_RW_B=1
# We need to read whole binary (or BIOS region), otherwise cbfstool will
# return different attributes for CBFS regions
echo "Checking flash layout."
$FLASHROM read_flash_layout_mock -p "$PROGRAMMER_BIOS" ${FLASH_CHIP_SELECT} ${FLASHROM_ADD_OPT_UPDATE} -r $BIOS_DUMP_FILE >/dev/null 2>>"$ERR_LOG_FILE"
if [ $? -eq 0 ] && [ -f "$BIOS_DUMP_FILE" ]; then
BOARD_FMAP_LAYOUT=$($CBFSTOOL layout_mock $BIOS_DUMP_FILE layout -w 2>>"$ERR_LOG_FILE")
BINARY_FMAP_LAYOUT=$($CBFSTOOL layout_mock "$bios_update_file" layout -w 2>>"$ERR_LOG_FILE")
diff <(echo "$BOARD_FMAP_LAYOUT") <(echo "$BINARY_FMAP_LAYOUT") >/dev/null 2>>"$ERR_LOG_FILE"
# If layout is identical, perform standard update using FMAP only
if [ $? -eq 0 ]; then
# Simply update RW_A fmap region if exists
grep -q "RW_SECTION_A" <<<$BINARY_FMAP_LAYOUT
if [ $? -eq 0 ]; then
FLASHROM_ADD_OPT_UPDATE="-N --fmap -i RW_SECTION_A -i WP_RO"
else
# RW_A does not exists, it means no vboot. Update COREBOOT region only
FLASHROM_ADD_OPT_UPDATE="-N --fmap -i COREBOOT"
fi
# If RW_B present, use this variable later to perform 2-step update
grep -q "RW_SECTION_B" <<<$BINARY_FMAP_LAYOUT && BINARY_HAS_RW_B=0
fi
else
print_warning "Could not read the FMAP region"
echo "Could not read the FMAP region" >>$ERR_LOG_FILE
fi
}
set_intel_regions_update_params() {
local fd_me_locked="no"
if [ $BOARD_HAS_FD_REGION -eq 0 ]; then
# No FD on board, so no further flashing
FLASHROM_ADD_OPT_REGIONS=""
else
# Safe defaults, only BIOS region and do not verify all regions,
# as some of them may not be readable. First argument is the initial
# params.
FLASHROM_ADD_OPT_REGIONS=$1
if [ $BINARY_HAS_FD -ne 0 ]; then
if [ $BOARD_FD_REGION_RW -ne 0 ]; then
# FD writable and the binary provides FD, safe to flash
FLASHROM_ADD_OPT_REGIONS+=" -i fd"
else
fd_me_locked="yes"
print_error "The firmware binary to be flashed contains Flash Descriptor (FD), but FD is not writable!"
print_warning "Proceeding without FD flashing, as it is not critical."
echo "The firmware binary contains Flash Descriptor (FD), but FD is not writable!" >>$ERR_LOG_FILE
fi
fi
if [ $BINARY_HAS_ME -ne 0 ]; then
if [ $BOARD_ME_REGION_RW -ne 0 ]; then
# ME writable and the binary provides ME, safe to flash if ME disabled
if [ $ME_DISABLED -eq 1 ]; then
FLASHROM_ADD_OPT_REGIONS+=" -i me"
else
echo "The firmware binary to be flashed contains Management Engine (ME), but ME is not disabled!" >>$ERR_LOG_FILE
print_error "The firmware binary contains Management Engine (ME), but ME is not disabled!"
force_me_update
fi
else
fd_me_locked="yes"
echo "The firmware binary to be flashed contains Management Engine (ME), but ME is not writable!" >>$ERR_LOG_FILE
print_error "The firmware binary contains Management Engine (ME), but ME is not writable!"
fi
fi
fi
if [ "$fd_me_locked" = "yes" ]; then
FLASHROM_ADD_OPT_REGIONS+=" -N"
print_warning "You can read more about issues with FD or ME on"
print_warning "https://docs.dasharo.com/guides/firmware-update/#known-issues"
fi
}
handle_fw_switching() {
local _can_switch_to_heads=$1
if [ "$_can_switch_to_heads" == "true" ] && [ "$DASHARO_FLAVOR" != "Dasharo (coreboot+heads)" ]; then
while :; do
echo
read -r -p "Would you like to switch to Dasharo heads firmware? (Y|n) " OPTION
echo
case ${OPTION} in
yes | y | Y | Yes | YES)
UPDATE_VERSION=$HEADS_REL_VER_DPP
FLASHROM_ADD_OPT_UPDATE_OVERRIDE=$HEADS_SWITCH_FLASHROM_OPT_OVERRIDE
BIOS_HASH_LINK="${HEADS_HASH_LINK_DPP}"
BIOS_SIGN_LINK="${HEADS_SIGN_LINK_DPP}"
BIOS_LINK="$HEADS_LINK_DPP"
# Check EC link additionally, not all platforms have Embedded Controllers:
if [ -n "$HEADS_EC_LINK_DPP" ]; then
EC_LINK=$HEADS_EC_LINK_DPP
EC_HASH_LINK=$HEADS_EC_HASH_LINK_DPP
EC_SIGN_LINK=$HEADS_EC_SIGN_LINK_DPP
if [ -n "$COMPATIBLE_HEADS_EC_FW_VERSION" ]; then
COMPATIBLE_EC_FW_VERSION="$COMPATIBLE_HEADS_EC_FW_VERSION"
fi
elif [ -n "$EC_LINK_DPP" ]; then
EC_LINK=$EC_LINK_DPP
EC_HASH_LINK=$EC_HASH_LINK_DPP
EC_SIGN_LINK=$EC_SIGN_LINK_DPP
elif [ -n "$EC_LINK_COMM" ]; then
EC_LINK=$EC_LINK_COMM
EC_HASH_LINK=$EC_HASH_LINK_COMM
EC_SIGN_LINK=$EC_SIGN_LINK_COMM
fi
export SWITCHING_TO="heads"
echo
echo "Switching to Dasharo heads firmware v$UPDATE_VERSION"
break
;;
n | N)
echo "Will not install Dasharo heads firmware. Proceeding with regular Dasharo firmware update."
return $CANCEL
;;
*) ;;
esac
done
elif [ -n "$DPP_IS_LOGGED" ] && [ -n "$HEADS_LINK_DPP" ]; then
local _heads_dpp=1
curl -sSfI -u "$USER_DETAILS" -H "$CLOUD_REQUEST" "$HEADS_LINK_DPP" -o /dev/null 2>>"$ERR_LOG_FILE"
_heads_dpp=$?
# We are on heads, offer switch back or perform update if DPP gives access to heads
if [ "$DASHARO_FLAVOR" == "Dasharo (coreboot+heads)" ]; then
while :; do
echo
print_warning 'If you are running heads firmware variant and want to update, say "n" here.'
print_warning 'You will be asked for heads update confirmation in a moment.'
print_warning 'Say "Y" only if you want to migrate from heads to UEFI firmware variant.'
read -r -p "Would you like to switch back to the regular (UEFI) Dasharo firmware variant? (Y|n) " OPTION
echo
case ${OPTION} in
yes | y | Y | Yes | YES)
echo
echo "Switching back to regular Dasharo firmware v$UPDATE_VERSION"
echo
FLASHROM_ADD_OPT_UPDATE_OVERRIDE=$HEADS_SWITCH_FLASHROM_OPT_OVERRIDE
export SWITCHING_TO="uefi"
break
;;
n | N)
if [ $_heads_dpp -ne 0 ]; then
error_exit "No update available for your machine"
fi
UPDATE_VERSION=$HEADS_REL_VER_DPP
compare_versions $DASHARO_VERSION $UPDATE_VERSION
if [ $? -ne 1 ]; then
error_exit "No update available for your machine" $CANCEL
fi
echo "Will not switch back to regular Dasharo firmware. Proceeding with Dasharo heads firmware update to $UPDATE_VERSION."
FLASHROM_ADD_OPT_UPDATE_OVERRIDE="--ifd -i bios"
BIOS_HASH_LINK="${HEADS_HASH_LINK_DPP}"
BIOS_SIGN_LINK="${HEADS_SIGN_LINK_DPP}"
BIOS_LINK="$HEADS_LINK_DPP"
# Check EC link additionally, not all platforms have Embedded Controllers:
if [ -n "$EC_LINK_DPP" ]; then
EC_LINK=$EC_LINK_DPP
EC_HASH_LINK=$EC_HASH_LINK_DPP
EC_SIGN_LINK=$EC_SIGN_LINK_DPP
elif [ -n "$EC_LINK_COMM" ]; then
EC_LINK=$EC_LINK_COMM
EC_HASH_LINK=$EC_HASH_LINK_COMM
EC_SIGN_LINK=$EC_SIGN_LINK_COMM
fi
break
;;
*) ;;
esac
done
fi
elif [ -z "$DPP_IS_LOGGED" ] && [ "$DASHARO_FLAVOR" == "Dasharo (coreboot+heads)" ]; then
# Not logged with DPP and we are on heads, offer switch back
compare_versions $DASHARO_VERSION $HEADS_REL_VER_DPP
if [ $? -eq 1 ]; then
print_warning "You are running heads firmware, but did not provide DPP credentials."
print_warning "There are updates available if you provide DPP credentials in main DTS menu."
fi
echo
echo "Latest available Dasharo version: $HEADS_REL_VER_DPP"
echo
while :; do
echo
read -r -p "Would you like to switch back to the regular Dasharo firmware? (Y|n) " OPTION
echo
case ${OPTION} in
yes | y | Y | Yes | YES)
echo
echo "Switching back to regular Dasharo firmware v$UPDATE_VERSION"
echo
FLASHROM_ADD_OPT_UPDATE_OVERRIDE=$HEADS_SWITCH_FLASHROM_OPT_OVERRIDE
export SWITCHING_TO="uefi"
break
;;
n | N)
print_warning "No update currently possible. Aborting update process..."
exit 0
break
;;
*) ;;
esac
done
else
if [ -z "$UPDATE_VERSION" ]; then
error_exit "No update available for your machine"
fi
compare_versions $DASHARO_VERSION $UPDATE_VERSION
if [ $? -ne 1 ]; then
error_exit "No update available for your machine" $CANCEL
fi
fi
}
sync_clocks() {
echo "Waiting for system clock to be synced ..."
chronyc waitsync 10 0 0 5 >/dev/null 2>>"$ERR_LOG_FILE"
if [[ $? -ne 0 ]]; then
print_warning "Failed to sync system clock with NTP server!"
print_warning "Some time critical tasks might fail!"
fi
}
print_disclaimer() {
echo -e \
"Please note that the report is not anonymous, but we will use it only for\r
backup and future improvement of the Dasharo product. Every log is encrypted\r
and sent over HTTPS, so security is assured.\r
If you still have doubts, you can skip HCL report generation.\r\n
What is inside the HCL report? We gather information about:\r
- PCI, Super I/O, GPIO, EC, audio, and Intel configuration,\r
- MSRs, CMOS NVRAM, CPU info, DIMMs, state of touchpad, SMBIOS and ACPI tables,\r
- Decoded BIOS information, full firmware image backup, kernel dmesg,\r
- IO ports, input bus types, and topology - including I2C and USB,\r
\r
You can find more info about HCL in docs.dasharo.com/glossary\r"
}
show_ram_inf() {
# Trace logging is quite slow due to creating timestamp for each line
# (calls 'date'). In QEMU this function results in 650 trace lines
# out of 800 for every UI refresh, which is noticeable
stop_trace_logging
# Get the data:
local data=""
data=$($DMIDECODE)
# Initialize an empty array to store the extracted values:
local -a memory_devices_array
# Parse the data to exclude fields "Locator" and "Part Number" and format to
# "Locator: Part Number":
while IFS= read -r line; do
# memory_device signals whether the line contains beginning of "Memory
# Device" dmidecode structure, if so - set to 1 and pars the structure, if
# the line contains "Handle" (the string every structure in dmidecode begins
# with) - set to 0:
if [[ $line =~ ^Handle ]]; then
memory_device=0
elif [[ $line =~ Memory\ Device ]]; then
memory_device=1
# Modify entry if "Memory Device" structure has been found
# (memory_device is set to 1) and either "Locator" or "Part Number"
# fields have been found:
elif [[ $memory_device -eq 1 && $line =~ Locator:\ |Part\ Number: ]]; then
# Extract a value of "Locator" field and then add a value of "Part Number"
# field but ignore "Bank Locator" field, cos it will be included by parent
# condition:
if [[ $line =~ Bank\ Locator ]]; then
continue # Ignore Bank Locator field.
elif [[ $line =~ Locator: ]]; then
entry="${line#*: }" # Extract the Locator value.
elif [[ $line =~ Part\ Number: ]]; then
entry+=": ${NORMAL}${line#*: }" # Concatenate Part Number value with
# Locator and add a colon with yellow
# color termination.
memory_devices_array+=("$entry")
fi
fi
done <<<"$data"
# Print the extracted values preformatted:
for entry in "${memory_devices_array[@]}"; do
echo -e "${BLUE}**${YELLOW} RAM ${entry}"
done
start_trace_logging
}
show_header() {
local _os_version
_os_version=$(grep "VERSION_ID" ${OS_VERSION_FILE} | cut -d "=" -f 2-)
printf "\ec"
echo -e "${NORMAL}\n Dasharo Tools Suite Script ${_os_version} ${NORMAL}"
echo -e "${NORMAL} (c) Dasharo <contact@dasharo.com> ${NORMAL}"
echo -e "${NORMAL} Report issues at: https://github.com/Dasharo/dasharo-issues ${NORMAL}"
}
show_hardsoft_inf() {
echo -e "${BLUE}*********************************************************${NORMAL}"
echo -e "${BLUE}**${NORMAL} HARDWARE INFORMATION ${NORMAL}"
echo -e "${BLUE}*********************************************************${NORMAL}"
echo -e "${BLUE}**${YELLOW} System Inf.: ${NORMAL}${SYSTEM_VENDOR} ${SYSTEM_MODEL}"
echo -e "${BLUE}**${YELLOW} Baseboard Inf.: ${NORMAL}${SYSTEM_VENDOR} ${BOARD_MODEL}"
echo -e "${BLUE}**${YELLOW} CPU Inf.: ${NORMAL}${CPU_VERSION}"
show_ram_inf
echo -e "${BLUE}*********************************************************${NORMAL}"
echo -e "${BLUE}**${NORMAL} FIRMWARE INFORMATION ${NORMAL}"
echo -e "${BLUE}*********************************************************${NORMAL}"
echo -e "${BLUE}**${YELLOW} BIOS Inf.: ${NORMAL}${BIOS_VENDOR} ${BIOS_VERSION}"
echo -e "${BLUE}*********************************************************${NORMAL}"
}
show_dpp_credentials() {
if [ -n "${DPP_IS_LOGGED}" ]; then
echo -e "${BLUE}**${NORMAL} DPP credentials ${NORMAL}"
echo -e "${BLUE}*********************************************************${NORMAL}"
if [ "${DISPLAY_CREDENTIALS}" == "true" ]; then
echo -e "${BLUE}**${YELLOW} Email: ${NORMAL}${DPP_EMAIL}"
echo -e "${BLUE}**${YELLOW} Password: ${NORMAL}${DPP_PASSWORD}"
else
echo -e "${BLUE}**${YELLOW} Email: ***************"
echo -e "${BLUE}**${YELLOW} Password: ***************"
fi
echo -e "${BLUE}*********************************************************${NORMAL}"
fi
}
show_ssh_info() {
if systemctl is-active sshd.service >/dev/null 2>>"$ERR_LOG_FILE"; then
local ip=""
ip=$(ip -br -f inet a show scope global | grep UP | awk '{ print $3 }' | tr '\n' ' ')
# Display "check your connection" in red color in IP field in case no IPV4
# address is assigned, otherwise display IP/PORT:
if [[ -z "$ip" ]]; then
echo -e "${BLUE}**${NORMAL} SSH status: ${GREEN}ON${NORMAL} IP: ${RED}check your connection${NORMAL}"
echo -e "${BLUE}*********************************************************${NORMAL}"
else
echo -e "${BLUE}**${NORMAL} SSH status: ${GREEN}ON${NORMAL} IP: ${ip}${NORMAL}"
echo -e "${BLUE}*********************************************************${NORMAL}"
fi
fi
}
show_main_menu() {
echo -e "${BLUE}**${YELLOW} ${HCL_REPORT_OPT})${BLUE} Dasharo HCL report${NORMAL}"
if check_if_dasharo; then
echo -e "${BLUE}**${YELLOW} ${DASHARO_FIRM_OPT})${BLUE} Update Dasharo Firmware${NORMAL}"
# flashrom does not support QEMU. TODO: this could be handled in a better way:
elif [ "${SYSTEM_VENDOR}" != "QEMU" ] && [ "${SYSTEM_VENDOR}" != "Emulation" ]; then
echo -e "${BLUE}**${YELLOW} ${DASHARO_FIRM_OPT})${BLUE} Install Dasharo Firmware${NORMAL}"
fi
# flashrom does not support QEMU. TODO: this could be handled in a better way:
if [ "${SYSTEM_VENDOR}" != "QEMU" ] && [ "${SYSTEM_VENDOR}" != "Emulation" ]; then
echo -e "${BLUE}**${YELLOW} ${REST_FIRM_OPT})${BLUE} Restore firmware from Dasharo HCL report${NORMAL}"
fi
if [ -n "${DPP_IS_LOGGED}" ]; then
echo -e "${BLUE}**${YELLOW} ${DPP_KEYS_OPT})${BLUE} Edit your DPP keys${NORMAL}"
else
echo -e "${BLUE}**${YELLOW} ${DPP_KEYS_OPT})${BLUE} Load your DPP keys${NORMAL}"
fi
if [ -f "${DPP_SUBMENU_JSON}" ]; then
echo -e "${BLUE}**${YELLOW} ${DPP_SUBMENU_OPT})${BLUE} DTS extensions${NORMAL}"
fi
if check_if_dasharo; then
echo -e "${BLUE}**${YELLOW} ${TRANSITION_OPT})${BLUE} Transition Dasharo Firmware${NORMAL}"
fi
}
main_menu_options() {
local OPTION=$1
local result
case ${OPTION} in
"${HCL_REPORT_OPT}")
print_disclaimer
read -p "Do you want to support Dasharo development by sending us logs with your hardware configuration? [N/y] "
case ${REPLY} in
yes | y | Y | Yes | YES)
export SEND_LOGS="true"
echo "Thank you for contributing to the Dasharo development!"
;;
*)
export SEND_LOGS="false"
echo "Logs will be saved in root directory."
echo "Please consider supporting Dasharo by sending the logs next time."
;;
esac
if [ "${SEND_LOGS}" == "true" ]; then
# DEPLOY_REPORT variable is used in dasharo-hcl-report to determine
# which logs should be printed in the terminal, in the future whole
# dts scripting should get some LOGLEVEL and maybe dumping working
# logs to file
export DEPLOY_REPORT="false"
wait_for_network_connection && ${CMD_DASHARO_HCL_REPORT} && LOGS_SENT="1"
else
export DEPLOY_REPORT="false"
${CMD_DASHARO_HCL_REPORT}
fi
read -p "Press Enter to continue."
return 0
;;
"${DASHARO_FIRM_OPT}")
if ! check_if_dasharo; then
# flashrom does not support QEMU, but installation depends on flashrom.
# TODO: this could be handled in a better way:
[ "${SYSTEM_VENDOR}" = "QEMU" ] || [ "${SYSTEM_VENDOR}" = "Emulation" ] && return 0
if wait_for_network_connection; then
echo "Preparing ..."
if [ -z "${LOGS_SENT}" ]; then
export SEND_LOGS="true"
export DEPLOY_REPORT="true"
if ! ${CMD_DASHARO_HCL_REPORT}; then
echo -e "Unable to connect to dl.dasharo.com for submitting the
\rHCL report. Please recheck your internet connection."
else
LOGS_SENT="1"
fi
fi
fi
if [ -n "${LOGS_SENT}" ]; then
${CMD_DASHARO_DEPLOY} install
result=$?
if [ "$result" -ne $OK ] && [ "$result" -ne $CANCEL ]; then
send_dts_logs ask && return 0
fi
fi
else
# TODO: This should be placed in dasharo-deploy:
# For NovaCustom TGL laptops with Dasharo version lower than 1.3.0,
# we shall run the ec_transition script instead. See:
# https://docs.dasharo.com/variants/novacustom_nv4x_tgl/releases/#v130-2022-10-18
if [ "$SYSTEM_VENDOR" = "Notebook" ]; then
case "$SYSTEM_MODEL" in
"NS50_70MU" | "NV4XMB,ME,MZ")
compare_versions $DASHARO_VERSION 1.3.0
if [ $? -eq 1 ]; then
# For Dasharo version lesser than 1.3.0
print_warning "Detected NovaCustom hardware with version < 1.3.0"
print_warning "Need to perform EC transition after which the platform will turn off"
print_warning "Then, please power it on and proceed with update again"
print_warning "EC transition procedure will start in 5 seconds"
sleep 5
${CMD_EC_TRANSITION}
error_check "Could not perform EC transition"
fi
# Continue with regular update process for Dasharo version
# greater or equal 1.3.0
;;
esac
fi
# Use regular update process for everything else
${CMD_DASHARO_DEPLOY} update
result=$?
if [ "$result" -ne $OK ] && [ "$result" -ne $CANCEL ]; then
send_dts_logs ask && return 0
fi
fi
read -p "Press Enter to continue."
return 0
;;
"${REST_FIRM_OPT}")
# flashrom does not support QEMU, but restore depends on flashrom.
# TODO: this could be handled in a better way:
[ "${SYSTEM_VENDOR}" = "QEMU" ] || [ "${SYSTEM_VENDOR}" = "Emulation" ] && return 0
if check_if_dasharo; then
if ! ${CMD_DASHARO_DEPLOY} restore; then
send_dts_logs ask && return 0
fi
fi
read -p "Press Enter to continue."
return 0
;;
"${DPP_KEYS_OPT}")
local _result
# Return if there was an issue when asking for credentials:
if ! get_dpp_creds; then
read -p "Press Enter to continue."
return 0
fi
# Try to log in using available DPP credentials, start loop over if login
# was not successful:
if ! login_to_dpp_server; then
echo "Cannot log in to DPP server."
read -p "Press Enter to continue"
return 0
fi
# Check for Dasharo Firmware for the current platform, continue to
# packages after checking:
check_for_dasharo_firmware
_result=$?
echo "Your credentials give access to:"
echo -n "Dasharo Pro Package (DPP): "
if [ $_result -eq 0 ]; then
# FIXME: what if credentials have access to
# firmware, but check_for_dasharo_firmware will not detect any platform?
# According to check_for_dasharo_firmware it will return 1 in both
# cases which means that we cannot detect such case.
print_ok "YES"
else
echo "NO"
fi
echo -n "DTS Extensions: "
if check_dts_extensions_access; then
print_ok "YES"
check_avail_dpp_packages && install_all_dpp_packages && parse_for_premium_submenu
else
echo "NO"
fi
read -p "Press Enter to continue."
return 0
;;
"${DPP_SUBMENU_OPT}")
[ -f "$DPP_SUBMENU_JSON" ] || return 0
export DPP_SUBMENU_ACTIVE="true"
return 0
;;
"${TRANSITION_OPT}")
# No transition, if there is no Dasharo firmware installed:
check_if_dasharo || return 0
${CMD_DASHARO_DEPLOY} transition
result=$?
if [ "$result" -ne $OK ] && [ "$result" -ne $CANCEL ]; then
send_dts_logs ask && return $OK
fi
read -p "Press Enter to continue."
return 0
;;
esac
return 1
}
show_footer() {
echo -e "${BLUE}*********************************************************${NORMAL}"
echo -ne "${RED}${REBOOT_OPT_UP}${NORMAL} to reboot ${NORMAL}"
echo -ne "${RED}${POWEROFF_OPT_UP}${NORMAL} to poweroff ${NORMAL}"
echo -e "${RED}${SHELL_OPT_UP}${NORMAL} to enter shell ${NORMAL}"
if systemctl is-active sshd.service >/dev/null 2>>"$ERR_LOG_FILE"; then
echo -ne "${RED}${SSH_OPT_UP}${NORMAL} to stop SSH server ${NORMAL}"
else
echo -ne "${RED}${SSH_OPT_UP}${NORMAL} to launch SSH server ${NORMAL}"
fi
if [ "${SEND_LOGS_ACTIVE}" == "true" ]; then
echo -e "${RED}${SEND_LOGS_OPT}${NORMAL} to disable sending DTS logs ${NORMAL}"
else
echo -e "${RED}${SEND_LOGS_OPT}${NORMAL} to enable sending DTS logs ${NORMAL}"
fi
if [ -n "${DPP_IS_LOGGED}" ]; then
if [ "${DISPLAY_CREDENTIALS}" == "true" ]; then
echo -e "${RED}${TOGGLE_DISP_CRED_OPT_UP}${NORMAL} to hide DPP credentials ${NORMAL}"
else
echo -e "${RED}${TOGGLE_DISP_CRED_OPT_UP}${NORMAL} to display DPP credentials ${NORMAL}"
fi
fi
echo -ne "${YELLOW}\nEnter an option:${NORMAL}"
}
footer_options() {
local OPTION=$1
case ${OPTION} in
"${SSH_OPT_UP}" | "${SSH_OPT_LOW}")
wait_for_network_connection || return 0
if systemctl is-active sshd.service >/dev/null 2>>"$ERR_LOG_FILE"; then
print_ok "Turning off the SSH server..."
systemctl stop sshd.service
else
print_warning "Starting SSH server!"
print_warning "Now you can log in into the system using root account."
print_warning "Stopping server will not drop all connected sessions."
systemctl start sshd.service
print_ok "Listening on IPs: $(ip -br -f inet a show scope global | grep UP | awk '{ print $3 }' | tr '\n' ' ')"
fi
read -p "Press Enter to continue."
return 0
;;
"${SHELL_OPT_UP}" | "${SHELL_OPT_LOW}")
clear
echo "Entering shell, to leave type exit and press Enter or press LCtrl+D"
echo ""
send_dts_logs
stop_logging
${CMD_SHELL}
start_logging
# If in submenu before going to shell - return to main menu after exiting
# shell:
unset DPP_SUBMENU_ACTIVE
;;
"${POWEROFF_OPT_UP}" | "${POWEROFF_OPT_LOW}")
send_dts_logs
${POWEROFF}
;;
"${REBOOT_OPT_UP}" | "${REBOOT_OPT_LOW}")
send_dts_logs
${REBOOT}
;;
"${SEND_LOGS_OPT}" | "${SEND_LOGS_OPT_LOW}")
if [ "${SEND_LOGS_ACTIVE}" == "true" ]; then
unset SEND_LOGS_ACTIVE
else
export SEND_LOGS_ACTIVE="true"
fi
;;
"${TOGGLE_DISP_CRED_OPT_UP}" | "${TOGGLE_DISP_CRED_OPT_LOW}")
if [ "${DISPLAY_CREDENTIALS}" == "true" ]; then
unset DISPLAY_CREDENTIALS
else
export DISPLAY_CREDENTIALS="true"
fi
;;
esac
return 1
}
send_dts_logs() {
local send_logs="false"
if [ "${SEND_LOGS_ACTIVE}" = "true" ]; then
send_logs="true"
elif [ "$1" = "ask" ] && ask_for_confirmation "Do you want to send console logs to 3mdeb?"; then
send_logs="true"
fi
if [ "$send_logs" = "true" ]; then
echo "Sending logs..."
log_dir=$(dmidecode -s system-manufacturer)_$(dmidecode -s system-product-name)_$(dmidecode -s bios-version)
uuid_string="$(cat /sys/class/net/"$(ip route show default | head -1 | awk '/default/ {print $5}')"/address)"
uuid_string+="_$(dmidecode -s system-product-name)"
uuid_string+="_$(dmidecode -s system-manufacturer)"
uuid=$(uuidgen -n @x500 -N $uuid_string -s)
log_dir+="_${uuid}_$(date +'%Y_%m_%d_%H_%M_%S_%N')"
log_dir="${log_dir// /_}"
log_dir="${log_dir//\//_}"
log_dir="${TMP_LOG_DIR}/${log_dir}"
mkdir -p $log_dir
cp ${DTS_LOG_FILE} $log_dir
cp ${DTS_VERBOSE_LOG_FILE} $log_dir
if [ -f ${ERR_LOG_FILE_REALPATH} ]; then
cp ${ERR_LOG_FILE_REALPATH} $log_dir
fi
if [ -f ${FLASHROM_LOG_FILE} ]; then
cp ${FLASHROM_LOG_FILE} $log_dir
fi
tar czf "${log_dir}.tar.gz" -C "$(dirname "$log_dir")" "$(basename "$log_dir")"
DPP_LOGS_BUCKET="dts-logs"
PUBLIC_LOGS_BUCKET="dts-logs-public"
if [ -f "${DPP_CREDENTIAL_FILE}" ]; then
DPP_EMAIL=$(sed -n '1p' <${DPP_CREDENTIAL_FILE} | tr -d '\n')
DPP_PASSWORD=$(sed -n '2p' <${DPP_CREDENTIAL_FILE} | tr -d '\n')
if [ -z "$DPP_EMAIL" ]; then
error_exit "DPP e-mail is empty"
fi
if [ -z "$(mc alias list | grep ${DPP_EMAIL})" ]; then
if ! mc alias set $DPP_SERVER_USER_ALIAS $DPP_SERVER_ADDRESS $DPP_EMAIL $DPP_PASSWORD >>$ERR_LOG_FILE 2>&1; then
error_exit "Cannot create MinIO alias for your DPP credentials"
fi
fi
LOGS_LINK="${DPP_LOGS_BUCKET}/${DPP_EMAIL}"
ALIAS=$DPP_SERVER_USER_ALIAS
else
ALIAS="public-hcl"
if [ -z "$(mc alias list | grep ${ALIAS})" ]; then
if ! mc alias set $ALIAS $DPP_SERVER_ADDRESS $BASE_HCL_USERNAME $BASE_HCL_PASSWORD >>$ERR_LOG_FILE 2>&1; then
error_exit "Cannot create MinIO alias"
fi
fi
LOGS_LINK="${PUBLIC_LOGS_BUCKET}"
fi
FULL_DTS_URL="https://cloud.3mdeb.com/index.php/s/"${BASE_DTS_LOGS_URL}
mc cp "$log_dir.tar.gz" "${ALIAS}/${LOGS_LINK}/"
if [ "$?" -ne "0" ]; then
echo "Failed to send logs to MinIO"
return 1
fi
fi
if [ "$1" = "ask" ]; then
read -p "Press Enter to continue."
fi
}
check_if_fused() {
local _file_path
_file_path="/sys/class/mei/mei0/fw_status"
local _file_content
local _hfsts6_value
local _line_number
local _hfsts6_binary
local _binary_length
local _padding
local _zeros
local _bit_30_value
if ! $FSREAD_TOOL test -f "$_file_path"; then
print_error "File not found: $_file_path"
return $CANCEL
fi
_file_content="$($FSREAD_TOOL cat $_file_path)"
_fsts6_value=""
_line_number=1
while IFS= read -r line; do
if [[ $_line_number -eq 6 ]]; then
_hfsts6_value="$line"
break
fi
((_line_number++))
done <<<"$_file_content"
if [[ -z "$_hfsts6_value" ]]; then
print_error "Failed to read HFSTS6 value"
exit 1
fi
_hfsts6_binary=$(echo "ibase=16; obase=2; $_hfsts6_value" | bc)
_binary_length=${#_hfsts6_binary}
# Add leading zeros
if [ $_binary_length -lt 32 ]; then
_padding=$((32 - $_binary_length))
_zeros=$(printf "%${_padding}s" | tr ' ' "0")
_hfsts6_binary=$_zeros$_hfsts6_binary
fi
_bit_30_value=${_hfsts6_binary:1:1}
if [ $_bit_30_value == 0 ]; then
return 1
else
return 0
fi
}
check_if_boot_guard_enabled() {
local _msr_hex
local _msr_binary
local _binary_length
local _padding
local _zeros
local _facb_fpf
local _verified_boot
# MSR cannot be read
if ! $RDMSR boot_guard_status_mock 0x13a -0 >/dev/null 2>"$ERR_LOG_FILE"; then
return 1
fi
_msr_hex=$($RDMSR boot_guard_status_mock 0x13a -0 | tr '[:lower:]' '[:upper:]')
_msr_binary=$(echo "ibase=16; obase=2; $_msr_hex" | bc)
_binary_length=${#_msr_binary}
if [ $_binary_length -lt 64 ]; then
_padding=$((64 - $_binary_length))
_zeros=$(printf "%${_padding}s" | tr ' ' "0")
_msr_binary=$_zeros$_msr_binary
fi
# Bit 4
_facb_fpf=${_msr_binary:59:1}
# Bit 6
_verified_boot=${_msr_binary:57:1}
if [ $_facb_fpf == 1 ] && [ $_verified_boot == 1 ]; then
return 0
fi
return 1
}
can_install_dasharo() {
if check_if_intel; then
if check_if_fused && check_if_boot_guard_enabled; then
return 1
fi
fi
return 0
}
check_if_intel() {
cpu_vendor=$(cat /proc/cpuinfo | grep "vendor_id" | head -n 1 | sed 's/.*: //')
if [ $cpu_vendor == "GenuineIntel" ]; then
return 0
fi
}
ask_for_confirmation() {
local text="$1"
while read -p "$text [n/y]: "; do
case ${REPLY} in
y | Y | yes | Yes | YES)
return 0
;;
n | N | no | No | NO)
return 1
;;
*) ;;
esac
done
}
parse_and_verify_config() {
# Arguments: the same as parse_config.
# Call parse_config and print error if it fails
local vendor="$1"
local system_model="$2"
local board_model="$3"
parse_config "$@"
local result=$?
if [ $result -eq 1 ]; then
print_error "Vendor $vendor is currently not supported!"
elif [ $result -eq 2 ]; then
print_error "System model $system_model is currently not supported!"
elif [ $result -eq 3 ]; then
print_error "Board model $board_model is currently now supported"
fi
return $result
}
parse_config() {
local vendor="$1"
local system_model="$2"
local board_model="$3"
# The JSONs names in configs directory the same as values in vendor variable
# but lowercase and spaces replaced with _
json_file="$BOARD_CONFIG_PATH/configs/$(echo "$vendor" | tr '[:upper:]' '[:lower:]' | sed 's/ /_/g').json"
# Parse common variables for vendor
# This finds all keys other than `models` and maps them to bash variables.
# The variable names are converted to lowercase.
#
# to_entries[] | select(.key != "models")
# Converts JSON input from:
# "key1": "value"
# "key2": "value"
# "models": {
# "key3": "value"
# }
# To:
# "key1": "value"
# "key2": "value"
#
# "\(.key | ascii_upcase)=\"\(.value|tostring)\"
# Changes: "key1": "value" to: KEY1="value"
# shellcheck disable=SC2046
output=$(jq -r 'to_entries[] | select(.key != "models") | "\(.key | ascii_upcase)=\"\(.value|tostring)\""' $json_file 2>>"$ERR_LOG_FILE")
if [ -z "$output" ]; then
return 1
fi
eval "$output"
# Parse system model-specific variables
# This finds all keys in `models[$SYSTEM_MODEL]` other than `board_models`
# and assigns variables just like in the previous call
#
# --arg m $(echo "$system_model" ...) stores the lowercase value of
# $system_model in the "$m" jq variable. That variable is then used to access
# models[$system_model] (.models[$m])
# Disabling warning "Quote this to prevent word splitting" to avoid mixing
# quotes
# shellcheck disable=SC2046
output=$(jq -r --arg m "$(echo "$system_model" | tr '[:upper:]' '[:lower:]')" '
.models[$m]
| to_entries[]
| select(.key != "board_models")
| "\(.key | ascii_upcase)=\"\(.value|tostring)\""
' $json_file 2>>"$ERR_LOG_FILE")
if [ -z "$output" ]; then
return 2
fi
eval "$output"
# If separate BOARD_MODEL values exist, parse the variables
# This looks for `models[$SYSTEM_MODEL].board_models[$BOARD_MODEL]`. Some
# boards have different variable values for different board models.
#
# If .models[$m].board_models[$b] does not exist, the eval will not
# create any new variables
# shellcheck disable=SC2046
has_key=$(jq -r --arg m "$(echo "$system_model" | tr '[:upper:]' '[:lower:]')" '
.models[$m] | has("board_models")
' $json_file)
if [ "$has_key" == "true" ]; then
# shellcheck disable=SC2046
output=$(jq -r --arg m "$(echo "$system_model" | tr '[:upper:]' '[:lower:]')" --arg b "$(echo "$board_model" | tr '[:upper:]' '[:lower:]')" '
.models[$m].board_models[$b]
| to_entries[]
| "\(.key | ascii_upcase)=\"\(.value|tostring)\""
' $json_file 2>>"$ERR_LOG_FILE")
if [ -z "$output" ]; then
return 3
fi
eval "$output"
fi
return 0
}