blob: 050ef30fc57c1e92f8eae810f036e70285d96b4c [file]
#!/bin/bash
# bios-helper.sh will be system dependent either TTF or non-TTF.
# It is selected/installed during build time based on whether it
# supports OOB msvfud updates.
source /usr/libexec/bios-helper.sh
##############################################################
# Initialize BIOS Staged/Activated Version/State during bootup
#
# Staged Version:
# - Verify the staged version/state in the metadata and
# compare it against the actual image.
#
# Activated Version:
# - Use the bios_validator output version to update the BIOS
# active version. This make sure the active version is not stale.
#
# Staged State:
# - The BIOS state is set to UPDATED if the bios_validator output is valid.
# If not, it will be set to CORRUPTED
#
# Return:
# 0 if staged/active version/active is updated, nonzero otherwise
############################################################
bios_init(){
local bios_version_file="$1"
# Staged Version:
#
# Validate the secondary partition via CR51
# if metadata stage version matches stage partition version
# - No changes, return 0
# if metadata version does not matches stage partition version
# - make the metadata state verison equal to stage partition version
# - if stage partition version is invalid
# - mark state as CORRUPTED
# - else, Mark state as STAGED
flashupdate verify_staging --config bios > /dev/null 2>&1
# Activated Version:
final_state="CORRUPTED"
active_version="$(cat ${bios_version_file})"
if [[ "$?" == "0" ]]; then
flashupdate update_version --config bios "${active_version}" primary
final_state="UPDATED"
else
flashupdate update_version --config bios "0.0.0.0" primary
fi
# Check to see if we want to force_powercycle to retry BIOS update
retry_bios_update "${active_version}"
flashupdate update_state --config bios "${final_state}"
}
##################################################
# [Deprecated] Use bios_init directly instead
#
# Initialize BIOS Staged Version/State during bootup
#
# Verify the staged version/state in the metadata and
# compare it against the actual image.
#
# Return:
# 0 if staged version/active is updated, nonzero otherwise
##################################################
bios_init_stage(){
# Validate the secondary partition via CR51
# if metadata stage version matches stage partition version
# - No changes, return 0
# if metadata version does not matches stage partition version
# - make the metadata state verison equal to stage partition version
# - if stage partition version is invalid
# - mark state as CORRUPTED
# - else, Mark state as STAGED
flashupdate verify_staging --config bios || return $?
# Check the BIOS status to see if it is ACTIVATED.
# the state will only be ACTIVATED after a powercycle when the expected BIOS update failed.
local state="$(flashupdate info --config bios --stage_state --clean_output)"
if [[ "${state}" == "ACTIVATED" ]]; then
systemctl start gbmc-psu-hardreset.target
fi
}
##################################################
# [Deprecated] Use bios_init directly instead
#
# Initialize BIOS Active Version/State during bootup
#
# Use the bios_validate output version to update the BIOS
# active version. This make sure the active version is not stale.
# The BIOS state is set to UPDATED to indicate that the version in
# $bios_version_file is the running BIOS version.
#
# Return:
# 0 if active version/active is updated, nonzero otherwise
##################################################
bios_init_active(){
local bios_version_file="$1"
active_version="$(cat ${bios_version_file})"
if [[ "$?" == "0" ]]; then
flashupdate update_version --config bios "${active_version}" primary
flashupdate update_state --config bios UPDATED
else
flashupdate update_version --config bios "0.0.0.0" primary
flashupdate update_state --config bios CORRUPTED
return 1
fi
}
##################################################
# Check if the BIOS update is required
# Return:
# 0 if we should update the BIOS, nonzero otherwise
##################################################
need_bios_update(){
# Check to see if BIOS status is ACTIVATED.
# Check staged BIOS version and if it differs from running version.
local state="$(flashupdate info --config bios --stage_state --clean_output)"
if [[ "${state}" != "ACTIVATED" ]]; then
return 1
fi
local active_version="$(flashupdate info --config bios --active_version --clean_output)"
local staged_version="$(flashupdate info --config bios --staged_version --clean_output)"
if [[ "${active_version}" == "${staged_version}" ]]; then
# At this point, the state is ACTIVATED and should be UPDATED instead if
# staged/activated version is the same.
echo "Does not need to update BIOS. Mark as UPDATED state"
flashupdate update_state --config bios UPDATED
return 1
fi
return 0
}
#########################################################
# Flash the BIOS EEPROM, if a staged image is on the BMC
# Return:
# 0 if success, non-zero if error
#########################################################
bios_update(){
local state="$(flashupdate info --config bios --stage_state --clean_output)"
if [[ "${state}" != "ACTIVATED" ]]; then
return 0
fi
# The staged index points to the secondary partition that was last
# staged.
local staged_index="$(flashupdate info --config bios --staged_index --clean_output)"
# Verify the staging partition
# Set the state to `CORRUPTED` if we cannot fetch the staged image
# With RAM based BIOS update, the staged image will not be available after
# powercycle. If BIOS update retry is triggered, it will loop forever.
flashupdate verify_staging --config bios || \
return $?
host_poweroff.sh || return $?
# Host is off. BMC should keep the mux.
# Update the BIOS state to UPDATED
# Write to the primary flash only if the staged_index matches what
# we expected the staged partition is.
flashupdate copy_partition --config bios "secondary/${staged_index}" \
primary --keep_mux
# Only BIOS validation errors will set the state to `CORRUPTED`
# Flash write failure will enable retries.
local status=$?
if [[ "${status}" == "1" ]]; then
# Flashupdate has a logical error
# The BIOS update is not expected, reset the BIOS stage state.
flashupdate invalidate --config bios primary
return ${status}
fi
if [[ "${status}" != "0" ]]; then
echo "Failed to update the BIOS"
return ${status}
fi
echo "Updated the BIOS"
}
##################################################
# Read the BIOS active or staged version
#
# Print out the active/staged version
# Return:
# 0 if reading the BIOS version was successful, nonzero otherwise
##################################################
bios_version(){
local vtype="$1"
local state="$(flashupdate info --config bios --stage_state --clean_output)"
# The active/staged version is not guaranteed to be valid if the state
# is CORRUPTED
if [[ "${state}" == "CORRUPTED" ]]; then
echo ""
return 0
fi
if [[ "${vtype}" == "active" ]]; then
# Fetch the active version from the metadata
# Active version is assumed to be always valid and no need to
# verify again
flashupdate info --config bios --active_version --clean_output
else
# Verifing the Staged version to make sure the BIOS update
# stage/version is correct. State need to be STAGED to be considered
# valid for BIOS activate package.
flashupdate verify_staging --config bios || (echo ""; return 0)
# Fetch the staged version from the metadata
flashupdate info --config bios --staged_version --clean_output
fi
}
##################################################
# Check if the BIOS activation is required
# Return:
# 0 if we should activate the BIOS, nonzero otherwise
##################################################
need_bios_activation(){
local active_version="$(flashupdate info --config bios --active_version --clean_output)"
local staged_version="$(flashupdate info --config bios --staged_version --clean_output)"
if [[ "${active_version}" == "${staged_version}" ]]; then
flashupdate update_state --config bios "UPDATED"
return 1
fi
return 0
}
##################################################
# Activate the BIOS Stage Partition
#
# Update the BIOS Status to ACTIVATED if it is STAGED.
# Skip if it is already ACTIVATED
#
# Return:
# 0 if the Stage partition was Actived, nonzero otherwise
##################################################
bios_activate(){
# Only active the BIOS if the staged/activated version are different.
need_bios_activation || return 0
local image="${1:-missing_image}"
state="$(flashupdate info --config bios --stage_state --clean_output)"
if [[ "${state}" == "ACTIVATED" ]]; then
return 0
fi
if [[ "${state}" != "STAGED" && "${image}" != "missing_image" ]]; then
echo "Stage to RAM before trying to activate again"
bios_stage "ram" "${image}" && bios_activate_only
return $?
fi
flashupdate update_state --config bios "ACTIVATED"
}
bios_activate_only(){
# Only active the BIOS if the staged/activated version are different.
need_bios_activation || return 0
state="$(flashupdate info --config bios --stage_state --clean_output)"
if [[ "${state}" == "ACTIVATED" ]]; then
return 0
fi
if [[ "${state}" != "STAGED" ]]; then
return 1
fi
flashupdate update_state --config bios "ACTIVATED"
}
##################################################
# Stage the BIOS Stage Partition
#
# Write the BIOS image to stage partition and mark the BIOS
# state as STAGED if the write is successful.
# Skip if it is already STAGED or ACTIVATED
#
# Return:
# 0 if the Staged partition was activated, nonzero otherwise
##################################################
bios_stage(){
local update_type="$1"
local image="$2"
# Need to skip the third arg because we used to pass path for the image
# to staged in. That is not used anymore, however, that will disable eMMC
# staging on older BIOS packages.
local try_emmc="${4:-true}"
# stage_index=1 means the update method is non-volatile memory based
stage_index=1
if [[ "${update_type}" == "ram" ]];
then
# Update the BIOS state to RAM based update and update the staged version.
# Use the secondary storage region that is linked to $BURN_IMAGE.
# Create empty file with image size.
stage_index=0
# eMMC Available. Try to stage to persistent region instead.
[[ "${try_emmc}" == "true" ]] && \
SYSTEMD_IGNORE_CHROOT=1 systemctl status emmc-available.target \
&& stage_index=1
fi
# Stage the BIOS to the BMC Secondary Storage
# Writing to the secondary parition automatically updates the BIOS
# State to STAGED after succefully staging the BIOS
if ! flashupdate write --config bios "${image}" "secondary/${stage_index}" ;
then
echo "bios image verify failure. Staging BIOS image failed."
if [[ "${stage_index}" != "0" ]];
then
echo "Currently targeting persistent staging... trying RAM based update instead."
bios_stage "ram" "${image}" "skip_arg" "false"
return
fi
rm -f "${image}"
return 1
fi
rm -f "${image}"
}