Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions include/dts-functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,80 @@ set_flashrom_update_params() {
fi
}

# Does combined check to assess whether the board has region and if its locked.
is_region_locked() {
local region="$1"
local has_var rw_var

# Uppercase
region="${region^^}"

has_var="BOARD_HAS_${region}_REGION"
rw_var="BOARD_${region}_REGION_RW"

[[ "${!has_var}" -eq 1 && "${!rw_var}" -eq 0 ]]
}

# Helper function to check whether a certain region is to be flashed.
# 0 if found, 1 otherwise.
flashrom_check_for_region() {
local region="$1"
local -n _args="$2"
local i

# Iterate only up to length-1 since we inspect pairs (i, i+1)
for ((i = 0; i < ${#_args[@]} - 1; i++)); do
if [[ "${_args[i]}" == "-i" && "${_args[i + 1]}" == "$region" ]]; then
return 0
fi
done

return 1
}

# Does a final check for all flashrom parameters if FD or ME are to be flashed
# and if they're locked. Decide whether we can proceed if any regions are locked.
flashrom_region_check() {
local -n args="$1"
local locked_regions=()
local region_list verb

# If switching to heads, always check the region, otherwise check region only
# if specified in params.
# The reason is we want to handle both "overwrites" form metadata as well as
# dynamically added params from set_intel_regions_update_params()
if { flashrom_check_for_region fd args || [[ "$SWITCHING_TO" == "heads" ]]; } &&
is_region_locked fd; then
locked_regions+=("FD")
fi

if { flashrom_check_for_region me args || [[ "$SWITCHING_TO" == "heads" ]]; } &&
is_region_locked me; then
locked_regions+=("ME")
fi

if [ "${#locked_regions[@]}" -eq 0 ]; then
return 0
fi

if [ "${#locked_regions[@]}" -eq 1 ]; then
region_list="${locked_regions[0]}"
verb="is"
else
region_list="${locked_regions[0]} and ${locked_regions[1]}"
verb="are"
fi

if [[ "$SWITCHING_TO" == "heads" ]]; then
print_error "Cannot proceed with heads update when $region_list $verb locked!"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add link to docs with information what should be done (if it doesn't exists then add it). Maybe: https://docs.dasharo.com/guides/firmware-update/#known-issues.
For MSI (locked FD): The following warnings appear when updating Dasharo: should be good enough.
For ME you could add generic: Make sure ME is set to HAP disabled. If this doesn't work then try with ME Soft Disabled.

print_error "Refer to: https://docs.dasharo.com/guides/firmware-update/#known-issues"
return 1
fi

print_warning "Proceeding without $region_list flashing, as it is not critical."
return 0
}

set_intel_regions_update_params() {
local fd_me_locked="no"
if [ $BOARD_HAS_FD_REGION -eq 0 ]; then
Expand Down
44 changes: 24 additions & 20 deletions scripts/dasharo-deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -880,9 +880,11 @@ deploy_firmware() {
local _mode
local _jobs=() # List of scheduled job indices
local _messages=() # List of error messages
# _job_args_<i> # List of flashrom params per job indice
# _job_args_<i> # List of flashrom params per job indice
# These are created dynamically in schedule_job() and referenced via nameref.
local _jobs_total=0
local _all_flashrom_args=() # An array for all flashrom args from all jobs
local n i # Loop iterators
_mode="$1"

# Helper function to schedule a flashrom job
Expand All @@ -909,23 +911,6 @@ deploy_firmware() {
args_ref=("$@")
}

# Helper function to check whether fd flashing is among arguments
# 0 if found, 1 otherwise.
check_for_fd() {
local -n _args="$1"
local i

# Scan argument array for the exact flashrom region selector "-i fd".
# Iterate only up to length-1 since we always inspect pairs (i, i+1).
for ((i = 0; i < ${#_args[@]} - 1; i++)); do
if [[ "${_args[i]}" == "-i" && "${_args[i + 1]}" == "fd" ]]; then
return 0
fi
done

return 1
}

if [ "$_mode" == "update" ]; then
echo "Updating Dasharo firmware..."
print_warning "This may take several minutes. Please be patient and do not"
Expand Down Expand Up @@ -1033,7 +1018,7 @@ deploy_firmware() {
# shellcheck disable=SC2178
local -n args_ref="_job_args_$i"

if check_for_fd args_ref; then
if flashrom_check_for_region fd args_ref; then
echo "Scheduling dedicated FD update..."
schedule_job "Failed to flash FD" \
-p "$PROGRAMMER_BIOS" \
Expand All @@ -1050,6 +1035,22 @@ deploy_firmware() {
fi
done

# Create array of all flashrom params to call flashrom_region_check only once
for n in "${!_jobs[@]}"; do
i="${_jobs[$n]}"
# _job_args_$i is a dynamically named (runtime-created) global array holding
# flashrom arguments for a single job.
# shellcheck disable=SC2178
local -n args_ref="_job_args_$i"

_all_flashrom_args+=("${args_ref[@]}")
done

# Last resort check before flashing
if ! flashrom_region_check _all_flashrom_args; then
return 1
fi

_jobs_total=${#_jobs[@]}

# Execute scheduled tasks
Expand Down Expand Up @@ -1245,7 +1246,10 @@ update_workflow() {
display_warning
fi

deploy_firmware update
# Check if update succeeded
if ! deploy_firmware update; then
return 1
fi

# TODO: Could it be placed somewhere else?
if [ ! -z "$SWITCHING_TO" ]; then
Expand Down