mirror of
https://github.com/ghidraninja/game-and-watch-flashloader.git
synced 2025-12-17 01:16:08 +01:00
137 lines
3.3 KiB
Bash
Executable File
137 lines
3.3 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
NC='\033[0m'
|
|
|
|
function echo_green() {
|
|
echo -e "${GREEN}${@}${NC}"
|
|
}
|
|
|
|
function echo_red() {
|
|
echo -e "${RED}${@}${NC}"
|
|
}
|
|
|
|
if [[ "$VERBOSE" == "1" ]]; then
|
|
set -ex
|
|
else
|
|
set -e
|
|
fi
|
|
|
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
|
ELF=${DIR}/build/gw_base.elf
|
|
|
|
if [[ $# -lt 1 ]]; then
|
|
echo "Usage: flash_multi.sh <binary to flash> [address=0] [chip_erase=0]"
|
|
echo ""
|
|
echo "address: The address to start writing to in the flash. Default is 0."
|
|
echo "chip_erase: Forces the use of chip erase. Will erase the whole chip,"
|
|
echo " but may be faster for large flash chips."
|
|
echo ""
|
|
echo "Note! This will cut the binary in 1M chunks and flash them to address and onwards"
|
|
exit
|
|
fi
|
|
|
|
IMAGE="$1"
|
|
ADDRESS=0
|
|
if [[ $# -gt 1 ]]; then
|
|
ADDRESS=$2
|
|
fi
|
|
|
|
CHIP_ERASE=0
|
|
if [[ $# -gt 2 ]]; then
|
|
CHIP_ERASE=$3
|
|
fi
|
|
|
|
# stat on macOS has different flags
|
|
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
FILESIZE=$(stat -f%z "${IMAGE}")
|
|
else
|
|
FILESIZE=$(stat -c%s "${IMAGE}")
|
|
fi
|
|
|
|
CHUNKS=$(( (FILESIZE + 1024 * 1024 - 1) / (1024 * 1024) ))
|
|
SIZE=$((FILESIZE))
|
|
SECTOR_SIZE=$(( 4 * 1024 ))
|
|
ERASE_BYTES=0
|
|
|
|
ERASE=1
|
|
i=0
|
|
while [[ $SIZE -gt 0 ]]; do
|
|
ADDRESS_HEX=$(printf "0x%08x" $(( ADDRESS + i * 1024 * 1024 )))
|
|
if [[ $SIZE -gt $((1024*1024)) ]]; then
|
|
CHUNK_SIZE=$((1024*1024))
|
|
else
|
|
CHUNK_SIZE=${SIZE}
|
|
fi
|
|
SIZE_HEX=$(printf "0x%08x" ${CHUNK_SIZE})
|
|
|
|
TMPFILE=$(mktemp /tmp/flash_chunk.XXXXXX)
|
|
if [[ ! -e $TMPFILE ]]; then
|
|
echo "Can't create tempfile!"
|
|
exit 1
|
|
fi
|
|
|
|
echo_green "Preparing chunk $((i + 1)) / ${CHUNKS} in file ${TMPFILE}"
|
|
dd if="${IMAGE}" of="${TMPFILE}" bs=1024 count=$(( (CHUNK_SIZE + 1023) / 1024 )) skip=$(( i * 1024 )) 2> /dev/null
|
|
|
|
if [[ $CHUNK_SIZE -le 8 ]]; then
|
|
echo "Chunk size <= 8 bytes, padding with zeros"
|
|
dd if=/dev/zero of=${TMPFILE} bs=1 count=$(( 9 - CHUNK_SIZE )) seek=${CHUNK_SIZE} 2> /dev/null
|
|
fi
|
|
|
|
echo_green "Flashing!"
|
|
if [[ $CHIP_ERASE == 1 ]]; then
|
|
ERASE_BYTES=0
|
|
else
|
|
ERASE_BYTES=$(( (( SIZE + SECTOR_SIZE - 1 ) / SECTOR_SIZE) * SECTOR_SIZE ))
|
|
fi
|
|
|
|
# Try to flash 3 times, give up after that.
|
|
COUNT=3
|
|
for RETRY_COUNT in $(seq $COUNT); do
|
|
if [[ $RETRY_COUNT -gt 1 ]]; then
|
|
echo_red "Flashing chunk $i failed... power cycle unit and retry? (y/n)"
|
|
read -n 1 -r
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
echo "Aborted."
|
|
exit 1
|
|
fi
|
|
|
|
echo ""
|
|
echo "Retry count $RETRY_COUNT/3"
|
|
fi
|
|
|
|
${DIR}/flash.sh ${TMPFILE} ${ADDRESS_HEX} ${SIZE_HEX} ${ERASE} ${ERASE_BYTES} && break
|
|
done
|
|
|
|
if [[ $RETRY_COUNT -eq 3 ]]; then
|
|
echo ""
|
|
echo ""
|
|
echo_red "Programming of the external flash FAILED after 3 tries."
|
|
echo_red "Please check your debugger and wires connecting to the target."
|
|
echo ""
|
|
echo ""
|
|
exit 1
|
|
else
|
|
echo ""
|
|
echo ""
|
|
echo_green "Programming of chunk $((i + 1)) / ${CHUNKS} succeeded."
|
|
echo ""
|
|
echo ""
|
|
fi
|
|
|
|
# Skip erase the following iterations
|
|
ERASE=0
|
|
ERASE_BYTES=0
|
|
|
|
rm -f ${TMPFILE}
|
|
|
|
SIZE=$(( SIZE - 1024*1024 ))
|
|
i=$(( i + 1 ))
|
|
done
|
|
|
|
echo_green "Programming of the external flash succeeded."
|
|
echo ""
|
|
echo ""
|