build/extensions/rkdevflash.sh

186 lines
8.7 KiB
Bash

#
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2023 Ricardo Pardini <ricardo@pardini.net>
# This file is a part of the Armbian Build Framework https://github.com/armbian/build/
#
# This adds the required host-side dependencies, clones and builds rkdeveloptool.
# When build is done, it enters a loop to wait for the device to be connected.
# When the device is connected, it check if device is in Maskrom or Loader mode.
# If in Markrom mode: use the ROCKUSB_BLOB to init Loader mode.
# If in Loader mode: it flashes the device with the produced image.
# It then resets the device via rkdeveloptool rd.
enable_extension "rkbin-tools" # which brings in the needed loader binaries for Maskrom -> Loader mode
function add_host_dependencies__rkdevflash() {
display_alert "Preparing rkdevflash host-side dependencies" "${EXTENSION}" "info"
declare -g EXTRA_BUILD_DEPS="${EXTRA_BUILD_DEPS} libudev-dev libusb-1.0-0-dev dh-autoreconf build-essential" # @TODO: convert to array later
}
function extension_finish_config__900_rkdevflash() {
display_alert "Preparing rkdevflash extension" "${EXTENSION}" "info"
declare -g -r rkdeveloptool_dir="${SRC}/cache/sources/rkdeveloptool"
declare -g -r rkdeveloptool_bin_path="${rkdeveloptool_dir}/rkdeveloptool"
# if under docker, exit_with_error; we can't get at the USB needed for rkdeveloptool.
if [[ "${ARMBIAN_RUNNING_IN_CONTAINER}" == "yes" ]]; then
exit_with_error "rkdevflash: running under Docker is not supported. rkdeveloptool requires direct access to the host USB devices."
fi
# Determine the SPL Loader to be used. This could be better done in board/family file config.
declare -g rkdeveloptool_spl_loader_blob="${ROCKUSB_BLOB:-"undetermined"}"
if [[ "${rkdeveloptool_spl_loader_blob}" == "undetermined"* ]]; then
exit_with_error "rkdevflash: ROCKUSB_BLOB is unset, unsupported LINUXFAMILY '${LINUXFAMILY}'?"
fi
declare -g -r rkdeveloptool_spl_loader_blob="${rkdeveloptool_spl_loader_blob}"
declare -g -r rkdeveloptool_spl_loader_blob_path="${SRC}/cache/sources/rkbin-tools/${rkdeveloptool_spl_loader_blob}"
}
function host_dependencies_ready__rkdevflash() {
display_alert "Preparing rkdevflash for usage" "${EXTENSION}" "info"
if [[ ! -f "${rkdeveloptool_bin_path}" ]]; then
display_alert "rkdeveloptool not found, building it" "${EXTENSION}" "info"
build_rkdeveloptool
fi
fetch_sources_tools__rkbin_tools # explicit call to extension method; we need the rkbins early.
if [[ ! -f "${rkdeveloptool_spl_loader_blob_path}" ]]; then
exit_with_error "rkdevflash: SPL loader blob not found: '${rkdeveloptool_spl_loader_blob_path}'"
fi
check_rkdeveloptool # logs the version of rkdeveloptool
display_alert "rkdevflash using RockUSB loader blob" "${EXTENSION} :: ${rkdeveloptool_spl_loader_blob}" "info"
declare rkdeveloptool_is_device_connected="no" rkdeveloptool_device_id="" rkdeveloptool_device_mode=""
list_devices_rkdeveloptool # early listing of devices at the start of build; gives early recompense if you have a device connected.
}
function post_build_image_write__rkdevflash() {
: "${built_image_file:?built_image_file is not set}" # check built_image_file is set
display_alert "Starting flash process" "${EXTENSION} :: ${built_image_file}" "info"
flash_image_rkdeveloptool "${built_image_file}"
}
function wait_for_connected_device_rkdeveloptool() {
display_alert "Waiting for device to be connected" "${EXTENSION}" "info"
rkdeveloptool_is_device_connected="no" rkdeveloptool_device_id="" rkdeveloptool_device_mode=""
list_devices_rkdeveloptool
declare -i counter=0
while [[ "${rkdeveloptool_is_device_connected}" != "yes" ]]; do
counter+=1
display_alert "Waiting for rkdeveloptool device to be connected (loop ${counter})" "${EXTENSION}" "debug"
sleep 1
list_devices_rkdeveloptool
done
}
function flash_image_rkdeveloptool() {
if [[ ! -f "${1}" ]]; then
exit_with_error "rkdevflash: Image file not found: '${1}'"
fi
display_alert "Flashing image" "${EXTENSION} :: ${1}" "info"
declare rkdeveloptool_is_device_connected="no" rkdeveloptool_device_id="" rkdeveloptool_device_mode=""
wait_for_connected_device_rkdeveloptool
while [[ "${rkdeveloptool_device_mode}" != "Loader" ]]; do
wait_for_connected_device_rkdeveloptool
if [[ "${rkdeveloptool_device_mode}" == "Maskrom" ]]; then
display_alert "Loading SPL RockUSB loader" "${EXTENSION} :: ${rkdeveloptool_spl_loader_blob}" "info"
declare loader_worked="no"
timeout 10 "${rkdeveloptool_bin_path}" db "${rkdeveloptool_spl_loader_blob_path}" && loader_worked="yes" || true
if [[ "${loader_worked}" != "yes" ]]; then
display_alert "rkdevflash: Failed to load SPL RockUSB loader. Timeout? Please reset the Rockchip device (again) into recovery..." "${EXTENSION}" "wrn"
sleep 5
else
display_alert "RockUSB Loader deployed" "${EXTENSION}" "cachehit"
break # break out of the loop. once loaded, the spl_loader does change stuff to Loader mode; only u-boot rockusb/"download mode" does that.
fi
fi
done
wait_for_connected_device_rkdeveloptool
display_alert "Flashing image" "${EXTENSION} :: ${1}" "info"
"${rkdeveloptool_bin_path}" wl 0x0 "${1}"
display_alert "Restarting device after flash" "${EXTENSION}" "ext"
"${rkdeveloptool_bin_path}" rd
}
function list_devices_rkdeveloptool() {
rkdeveloptool_is_device_connected="no" # outer scope
rkdeveloptool_device_id="undetermined" # outer scope
rkdeveloptool_device_mode="not_present" # outer scope
display_alert "Listing rkdeveloptool devices" "${EXTENSION}" "debug"
if ! "${rkdeveloptool_bin_path}" ld &> /dev/null; then
display_alert "No rkdeveloptool device found." "${EXTENSION}" ""
display_alert "Use an USB-C cable to connect the Rockchip device to this host." "${EXTENSION}" ""
display_alert "Power on the Rockchip device and put it in recovery mode." "${EXTENSION}" ""
display_alert "For example, click & hold Recovery button and then click Reset button once." "${EXTENSION}" ""
display_alert "This is try number ${counter:-"0"}" "${EXTENSION}" ""
else
# Some device is connected, run again and parse the id and mode.
declare rkdeveloptool_ld_output
rkdeveloptool_ld_output="$("${rkdeveloptool_bin_path}" ld || echo -n none)"
if [[ "${rkdeveloptool_ld_output}" == *"none"* ]]; then
return 0
fi
rkdeveloptool_is_device_connected="yes"
# cleanup the output, rk messes it up so badly it hurts
rkdeveloptool_ld_output="$(echo "${rkdeveloptool_ld_output}" | tr -d '\r')" # cleanup
rkdeveloptool_ld_output="$(echo "${rkdeveloptool_ld_output}" | head -1 | xargs echo -n)" # cleanup
rkdeveloptool_device_id="$(echo "${rkdeveloptool_ld_output}" | cut -d' ' -f2)" # 2/3 column
rkdeveloptool_device_mode="$(echo "${rkdeveloptool_ld_output}" | cut -d' ' -f3)" # 3/3 column
display_alert "rkdeveloptool ld output" "${EXTENSION} :: '${rkdeveloptool_ld_output}'" "debug"
display_alert "rkdeveloptool device detected" "${EXTENSION} :: device '${rkdeveloptool_device_id}'" "info"
display_alert "rkdeveloptool device mode" "${EXTENSION} :: mode '${rkdeveloptool_device_mode}'" "info"
fi
return 0
}
function build_rkdeveloptool() {
# Clone rkdeveloptool
#fetch_from_repo "https://github.com/rockchip-linux/rkdeveloptool" "rkdeveloptool" "branch:master" # pristine rk
fetch_from_repo "https://github.com/radxa/rkdeveloptool.git" "rkdeveloptool" "branch:master" # Radxa's fork has fixes
# Build rkdeveloptool
pushd "${rkdeveloptool_dir}" &> /dev/null || exit_with_error "Fail to cd to rkdeveloptool: ${rkdeveloptool_dir}"
# Patch `-Werror` out of Makefile so it builds with a warning. It still works.
# sed -i -e 's/-Werror //' Makefile.am || exit_with_error "Fail to patch Makefile.am" # Not needed with Radxa's fork
run_host_command_logged pipetty aclocal
run_host_command_logged pipetty autoreconf -i
run_host_command_logged pipetty autoheader
run_host_command_logged pipetty automake --add-missing
run_host_command_logged pipetty ./configure
run_host_command_logged pipetty make -j$(nproc)
run_host_command_logged pipetty ls -la "${rkdeveloptool_bin_path}"
popd &> /dev/null || exit_with_error "Fail to cd back to armbian-build"
}
function check_rkdeveloptool() {
declare rkdevtool_version="undetermined"
rkdevtool_version="$("${rkdeveloptool_bin_path}" --version)"
rkdevtool_version="$(echo "${rkdevtool_version}" | tr -dc '[:print:]' | xargs echo -n)" # cleanup, rk emits a carriage return we don't want
display_alert "rkdeveloptool version" "${EXTENSION} :: '${rkdevtool_version}'" ""
# as a courtesy to the user, install a symlink into /usr/local/bin, so rkdeveloptool can be called by itself as well
if [[ -f /usr/local/bin/rkdeveloptool ]]; then
run_host_command_logged rm -f /usr/local/bin/rkdeveloptool
fi
run_host_command_logged sudo ln -sf "${rkdeveloptool_bin_path}" /usr/local/bin/rkdeveloptool
}