Skip to content

Instantly share code, notes, and snippets.

@loopyd
Last active July 7, 2024 20:59
Show Gist options
  • Save loopyd/284fd6ad5f8325bc293895396a6a126f to your computer and use it in GitHub Desktop.
Save loopyd/284fd6ad5f8325bc293895396a6a126f to your computer and use it in GitHub Desktop.
[bash] EzRkFlash - Easy Rockchip flashing tool (rkdevtool) wrapper.
#!/bin/bash
shopt -s extglob dotglob
IMAGE_PATH=${IMAGE_PATH:-}
LOADER_PATH=${LOADER_PATH:-}
FLASH_OFFSET=${FLASH_OFFSET:-0}
ERASE_EMMC_SIZE=${ERASE_EMMC_SIZE:-0}
WAIT_DEVICE=${WAIT_DEVICE:-false}
WAIT_DEVICE_TIMEOUT=${WAIT_DEVICE_TIMEOUT:-30}
AUTO_REBOOT=${AUTO_REBOOT:-false}
CARGS=("$@")
ACTION=""
# block non-root execution
if [ "$(id -u)" -ne 0 ]; then
echo "This script must be run as root" 1>&2
exit 1
fi
# trap exit signals with function
function error_trap() {
local LASTEXITCODE=$?
if [ $LASTEXITCODE -ne 0 ]; then
echo "Script exited with status code: $LASTEXITCODE" 1>&2
exit $LASTEXITCODE
fi
exit 0
}
trap error_trap ERR SIGINT SIGTERM SIGHUP SIGQUIT SIGTSTP EXIT
# check if shell command exists
function shell_cmd_exists() {
local cmd=$1
if [ -z "$cmd" ]; then
echo "E: Command not provided" 1>&2
return 2
fi
command -v $cmd >/dev/null 2>&1 || {
return 1
}
return 0
}
# check if the device is connected
function is_device_connected() {
if ! rkdeveloptool ld 2>&1 | grep -q "Maskrom"; then
return 1
fi
return 0
}
# test if the device is connected
function test_device() {
printf "Testing device..."
if rkdeveloptool td 2>&1 | grep -q "failed"; then
printf "Failed\n"
return 1
fi
printf "OK\n"
return 0
}
function check_chip() {
printf "Checking chip info..."
if rkdeveloptool rci 2>&1 | grep -q "failed"; then
printf "Failed\n"
return 1
fi
printf "OK\n"
return 0
}
function read_flash_info() {
printf "Reading flash info..."
if rkdeveloptool rfi | grep -q "failed"; then
printf "Failed\n"
return 1
fi
printf "OK\n"
return 0
}
# Sideload loader bin
function sideload_loader() {
local loader=$1
if [ ! -f "$loader" ]; then
echo "Loader file not found" >&2
return 1
fi
printf "Sideload bootloader..."
eval "rkdeveloptool db ${loader} >/dev/null 2>&1 " || {
printf "Failed\n"
return 1
}
printf "OK\n"
test_device || return $?
check_chip || return $?
read_flash_info || return $?
return 0
}
# Clear the emmc with zero image
function erase_emmc() {
local size
size=$1
tmpfile=$(mktemp -f /tmp/zero.img.XXXXXX)
printf "Creating zero image..."
eval "dd if=/dev/zero of=${tmpfile} bs=1M count=${size} >/dev/null 2>&1 " || {
printf "Failed\n"
return 1
}
printf "OK\n"
printf "Erasing emmc..."
eval "rkdeveloptool wl 0 ${tmpfile} >/dev/null 2>&1" || {
printf "Failed\n"
return 1
}
rm -f $tmpfile || {
printf "Failed\n"
return 1
}
printf "OK\n"
return 0
}
# Reboot the device
function reboot_device() {
printf "Rebooting device..."
eval "rkdeveloptool rd >/dev/null 2>&1" || {
printf "Failed\n"
return 1
}
printf "OK\n"
return 0
}
# Flash the image
function flash_image() {
local image=$1
if [ ! -f "$image" ]; then
echo "Image file not found" 1>&2
return 1
fi
shift 1
local offset
offset=$1
if [ -z "$offset" ]; then
echo "W: Offset not provided, using 0" 1>&2
offset=0
fi
eval "rkdeveloptool wl 0 $image" || {
echo "Failed to write image" 1>&2
return 1
}
return 0
}
# Wait for device to connect
function wait_connect() {
local timeout
timeout=$1
if [ -z "$timeout" ]; then
echo "W: Timeout not provided, using 30 seconds" 1>&2
timeout=30
fi
while [ $timeout -gt 0 ]; do
printf "Waiting for device to connect (%d seconds) \r" $timeout
if is_device_connected; then
return 0
fi
sleep 1
timeout=$((timeout - 1))
done
return 1
}
# Print program usage information
function usage() {
case $1 in
flash)
echo "EzRkFlash - Rockchip Flashing Tool (v1.0)"
echo "by: loopyd <loopyd@github.com> (GPL3.0 permassive - 2024)"
echo ""
echo "Usage: $0 flash [OPTIONS]"
echo ""
echo "Flash Options:"
echo " -i, --image <path> Path to the image file"
echo " -l, --loader <path> Path to the loader file"
echo " -o, --offset <offset> Offset to write the image"
echo ""
echo "Device Options:"
echo " -w, --wait-device Wait for device to connect"
echo " -t, --timeout <time> Timeout to wait for device"
echo " -r, --reboot Reboot device after flashing"
;;
erase)
echo "Usage: $0 erase [OPTIONS]"
echo ""
echo "Erase Options:"
echo " -e, --erase-emmc-size <size> Size in MB to erase"
echo ""
echo "Device Options:"
echo " -w, --wait-device Wait for device to connect"
echo " -t, --timeout <time> Timeout to wait for device"
echo " -r, --reboot Reboot device after erasing"
;;
*)
echo "Usage: $0 <action> [OPTIONS]" 1>&2
echo ""
echo "Tool Actions:"
echo " flash Flash the image"
echo " erase Erase the emmc"
;;
esac
exit 1
}
# Parse command line arguments
function parse_args() {
local ARGS=($*)
if [ ${#ARGS} -lt 2 ]; then
echo "E: No arguments provided" 1>&2
usage
fi
ACTION=${ARGS[0]}
if [ -z "$ACTION" ]; then
echo "E: No action provided" 1>&2
usage
fi
ARGS=(${ARGS[@]:1})
case "$ACTION" in
flash)
while [ ${#ARGS[@]} -gt 0 ]; do
case ${ARGS[0]} in
-h | --help)
usage $ACTION
;;
-i | --image)
IMAGE_PATH=${ARGS[1]}
ARGS=(${ARGS[@]:2})
;;
-l | --loader)
LOADER_PATH=${ARGS[1]}
ARGS=(${ARGS[@]:2})
;;
-o | --offset)
FLASH_OFFSET=${ARGS[1]}
ARGS=(${ARGS[@]:2})
;;
-w | --wait-device)
WAIT_DEVICE=true
ARGS=(${ARGS[@]:1})
;;
-t | --timeout)
WAIT_DEVICE_TIMEOUT=${ARGS[1]}
ARGS=(${ARGS[@]:2})
;;
-r | --reboot)
AUTO_REBOOT=true
ARGS=(${ARGS[@]:1})
;;
*)
echo "E: Unknown argument: ${ARGS[0]}" 1>&2
usage $ACTION
;;
esac
done
;;
erase)
while [ ${#ARGS[@]} -gt 0 ]; do
case ${ARGS[0]} in
-h | --help)
usage $ACTION
;;
-e | --erase-emmc-size)
ERASE_EMMC_SIZE=${ARGS[1]}
ARGS=(${ARGS[@]:2})
;;
-w | --wait-device)
WAIT_DEVICE=true
ARGS=(${ARGS[@]:1})
;;
-t | --timeout)
WAIT_DEVICE_TIMEOUT=${ARGS[1]}
ARGS=(${ARGS[@]:2})
;;
-r | --reboot)
AUTO_REBOOT=true
ARGS=(${ARGS[@]:1})
;;
*)
echo "E: Unknown argument: ${ARGS[0]}" 1>&2
usage $ACTION
;;
esac
done
;;
*)
echo "E: Unknown action: $ACTION" 1>&2
usage
;;
esac
}
### Main
parse_args ${CARGS[*]}
case "$ACTION" in
flash)
if [ -z "$IMAGE_PATH" ]; then
echo "E: Image path not provided" 1>&2
usage $ACTION
fi
if [ -z "$LOADER_PATH" ]; then
echo "E: Loader path not provided" 1>&2
usage $ACTION
fi
if ! shell_cmd_exists rkdeveloptool; then
echo "E: rkdeveloptool not found on PATH, please compile/install it." 1>&2
exit 1
fi
echo "Flash Parameters:"
echo " Sideload loader: $LOADER_PATH"
echo " Image: $IMAGE_PATH"
echo " Byte Offset: $FLASH_OFFSET"
if [ "$WAIT_DEVICE" = true ]; then
wait_connect $WAIT_DEVICE_TIMEOUT || {
echo "E: Maskrom Device not connected" 1>&2
exit 1
}
else
if ! is_device_connected; then
echo "E: Maskrom Device not connected" 1>&2
exit 1
fi
fi
sideload_loader $LOADER_PATH || exit $?
flash_image $IMAGE_PATH || exit $?
if [ "$AUTO_REBOOT" = true ]; then
reboot_device || exit $?
fi
;;
erase)
if [ $ERASE_EMMC_SIZE -eq 0 ]; then
echo "Erase size not provided" 1>&2
usage $ACTION
fi
if ! shell_cmd_exists rkdeveloptool; then
echo "E: rkdeveloptool not found on PATH, please compile/install it." 1>&2
exit 1
fi
echo "Erase Parameters:"
echo " Erase size: $ERASE_EMMC_SIZE"
if [ "$WAIT_DEVICE" = true ]; then
wait_connect $WAIT_DEVICE_TIMEOUT || {
echo "E: Maskrom Device did not connect within the specified timeframe." 1>&2
exit 1
}
else
if ! is_device_connected; then
echo "E: Maskrom Device not connected" 1>&2
exit 1
fi
fi
erase_emmc $ERASE_EMMC_SIZE || exit $?
if [ "$AUTO_REBOOT" = true ]; then
reboot_device || exit $?
fi
;;
*)
usage
;;
esac
@loopyd
Copy link
Author

loopyd commented Jul 7, 2024

EzRkFlash

Version 1.0.0

This tool allows you to flash custom ROM to Rockchip devices using rkdevtool in linux.

It was written to offer easier solution in Linux over RkDevtool in Windows.

This post reserved for future updates

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment