Add support for the Zelda variant
This commit is contained in:
parent
72d2aa74c7
commit
441d74b5d8
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
source config.sh placeHolder
|
||||
source config.sh $@
|
||||
|
||||
echo "Running sanity checks..."
|
||||
if ! ${OPENOCD} -v >/dev/null 2>&1; then
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
source config.sh $1
|
||||
source config.sh $@
|
||||
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "Usage: backup_flash.sh <Adapter: jlink or stlink or rpi>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -f backups/flash_backup.bin; then
|
||||
echo "Already have a backup in backups/flash_backup.bin, refusing to overwrite."
|
||||
if test -f backups/flash_backup_$TARGET.bin; then
|
||||
echo "Already have a backup in backups/flash_backup_$TARGET.bin, refusing to overwrite."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -16,32 +11,37 @@ echo "Make sure your Game & Watch is turned on and in the time screen. Press ret
|
|||
read -n 1
|
||||
|
||||
echo "Attempting to dump flash using adapter ${ADAPTER}."
|
||||
echo "Running OpenOCD... (This will take roughly 30 seconds, your Game and Watch screen will blink in between.)"
|
||||
if ! ${OPENOCD} -f openocd/flash_"${ADAPTER}".cfg >>logs/2_openocd.log 2>&1; then
|
||||
echo "Running OpenOCD... (This can take up to a few minutes.)"
|
||||
if ! ${OPENOCD} \
|
||||
-f "openocd/target_${TARGET}.cfg" \
|
||||
-f "openocd/interface_${ADAPTER}.cfg" \
|
||||
-f "openocd/flash.cfg" >> logs/2_openocd.log 2>&1; then
|
||||
echo "Failed to dump SPI flash from device. Verify debug connection and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Validating ITCM dump..."
|
||||
if ! shasum --check shasums/itcm_backup.bin.sha1 >/dev/null 2>&1; then
|
||||
if ! shasum --check shasums/itcm_backup_${TARGET}.bin.sha1 >/dev/null 2>&1; then
|
||||
echo "Failed to correctly dump ITCM. Restart Game & Watch and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
echo "Extracting checksummed part..."
|
||||
if ! dd if=backups/flash_backup.bin of=backups/flash_backup_checksummed.bin count=1040384 bs=1 >/dev/null 2>&1; then
|
||||
echo "Failed to access flash_backup.bin"
|
||||
echo dd if=backups/flash_backup_${TARGET}.bin of=backups/flash_backup_checksummed_${TARGET}.bin bs=16 skip=${SPIFLASH_SKIP_16} count=${SPIFLASH_COUNT_16}
|
||||
|
||||
if ! dd if=backups/flash_backup_${TARGET}.bin of=backups/flash_backup_checksummed_${TARGET}.bin bs=16 skip=${SPIFLASH_SKIP_16} count=${SPIFLASH_COUNT_16} >/dev/null 2>&1; then
|
||||
echo "Failed to access flash_backup_${TARGET}.bin"
|
||||
echo "Verify openocd works correctly"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Validating checksum..."
|
||||
if ! shasum --check shasums/flash_backup_checksummed.bin.sha1 >/dev/null 2>&1; then
|
||||
echo "Failed to verify checksum. Try again."
|
||||
if ! shasum --check shasums/flash_backup_checksummed_${TARGET}.bin.sha1 >/dev/null 2>&1; then
|
||||
echo "Failed to verify checksum of the external flash. Try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm backups/flash_backup_checksummed.bin
|
||||
rm -f backups/flash_backup_checksummed_${TARGET}.bin
|
||||
|
||||
echo "Looks good! Successfully backed up the (encrypted) SPI flash to flash_backup.bin!"
|
||||
echo "Looks good! Successfully backed up the (encrypted) SPI flash to backups/flash_backup_${TARGET}.bin!"
|
||||
|
|
|
@ -2,27 +2,27 @@
|
|||
|
||||
set -e
|
||||
|
||||
source config.sh $1
|
||||
source config.sh $@
|
||||
|
||||
if test -f backups/internal_flash_backup.bin; then
|
||||
echo "Already have a backup in backups/internal_flash_backup.bin, refusing to overwrite."
|
||||
if test -f backups/internal_flash_backup_${TARGET}.bin; then
|
||||
echo "Already have a backup in backups/internal_flash_backup_${TARGET}.bin, refusing to overwrite."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! dd if=backups/flash_backup.bin of=backups/flash_backup_checksummed.bin count=1016 bs=1024 >/dev/null 2>&1; then
|
||||
echo "Failed to access flash_backup.bin"
|
||||
if ! dd if=backups/flash_backup_${TARGET}.bin of=backups/flash_backup_checksummed_${TARGET}.bin bs=16 skip=${SPIFLASH_SKIP_16} count=${SPIFLASH_COUNT_16} >/dev/null 2>&1; then
|
||||
echo "Failed to access flash_backup_${TARGET}.bin"
|
||||
echo "Please run ./2_backup_flash.sh again"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! shasum --check shasums/flash_backup_checksummed.bin.sha1 >/dev/null 2>&1; then
|
||||
if ! shasum --check shasums/flash_backup_checksummed_${TARGET}.bin.sha1 >/dev/null 2>&1; then
|
||||
echo "*** External flash backup does not verify correctly ***"
|
||||
echo "Please run ./2_backup_flash.sh again"
|
||||
rm backups/flash_backup_checksummed.bin
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm backups/flash_backup_checksummed.bin
|
||||
rm -f backups/flash_backup_checksummed_${TARGET}.bin
|
||||
|
||||
echo "This step will overwrite the contents of the SPI flash chip that we backed up in step 2."
|
||||
echo "It will be restored in step 5. Continue? (y/N)"
|
||||
|
@ -34,44 +34,53 @@ then
|
|||
fi
|
||||
|
||||
echo "Generating encrypted flash image from backed up data..."
|
||||
if ! python3 python/tcm_encrypt.py backups/flash_backup.bin backups/itcm_backup.bin payload/payload.bin new_flash_image.bin; then
|
||||
if ! python3 python/tcm_encrypt.py \
|
||||
backups/flash_backup_${TARGET}.bin \
|
||||
${FLASH_OFFSET} \
|
||||
backups/itcm_backup_${TARGET}.bin \
|
||||
payload/payload.bin \
|
||||
new_flash_image.bin; then
|
||||
echo "Failed to build encrypted flash image."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
echo "Running flashloader..."
|
||||
|
||||
if ! ./scripts/flashloader.sh $ADAPTER new_flash_image.bin; then
|
||||
echo "Flashloader failed, check debug connection and try again."
|
||||
echo "Programming payload to SPI flash..."
|
||||
if ! ${OPENOCD} -f "openocd/target_${TARGET}.cfg" -f "openocd/interface_${ADAPTER}.cfg" \
|
||||
-c "init;" \
|
||||
-c "halt;" \
|
||||
-c "program new_flash_image.bin 0x90000000 verify;" \
|
||||
-c "exit;" >>logs/3_openocd.log 2>&1; then
|
||||
echo "Writing payload to SPI flash failed. Check debug connection and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Flash successfully flashed. Now do the following procedure:"
|
||||
echo "Flash successfully programmed. Now do the following procedure:"
|
||||
echo "- Disconnect power from the device"
|
||||
echo "- Power it again"
|
||||
echo "- Press and hold the power button"
|
||||
echo "- Press return (while still holding the power button)!"
|
||||
echo "- Press the power button on the device"
|
||||
echo "- The LCD should show a blue screen"
|
||||
echo "- If it's not blue, you can try pressing the Time button on the device"
|
||||
echo "- Press return"
|
||||
|
||||
|
||||
read -n 1
|
||||
|
||||
echo "Dumping internal flash..."
|
||||
if ! ${OPENOCD} -f openocd/interface_"${ADAPTER}".cfg \
|
||||
if ! ${OPENOCD} -f "openocd/interface_${ADAPTER}.cfg" \
|
||||
-c "init;" \
|
||||
-c "halt;" \
|
||||
-c "dump_image backups/internal_flash_backup.bin 0x24000000 131072" \
|
||||
-c "dump_image backups/internal_flash_backup_${TARGET}.bin 0x24000000 131072" \
|
||||
-c "exit;" >>logs/3_openocd.log 2>&1; then
|
||||
echo "Dumping internal flash failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Verifying internal flash backup..."
|
||||
if ! shasum --check shasums/internal_flash_backup.bin.sha1 >/dev/null 2>&1; then
|
||||
if ! shasum --check shasums/internal_flash_backup_${TARGET}.bin.sha1 >/dev/null 2>&1; then
|
||||
echo "The backup of the internal flash failed. Please try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm new_flash_image.bin
|
||||
rm -f new_flash_image.bin
|
||||
|
||||
echo "Device backed up successfully"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
source config.sh $1
|
||||
source config.sh $@
|
||||
|
||||
echo "Unlocking your device will erase its internal flash. Even though your backup"
|
||||
echo "is validated, this still can go wrong. Are you sure? (y/N)"
|
||||
|
@ -12,13 +12,13 @@ then
|
|||
fi
|
||||
|
||||
echo "Validating internal flash backup before proceeding..."
|
||||
if ! shasum --check shasums/internal_flash_backup.bin.sha1 >/dev/null 2>&1; then
|
||||
if ! shasum --check shasums/internal_flash_backup_${TARGET}.bin.sha1 >/dev/null 2>&1; then
|
||||
echo "Backup is not valid. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Unlocking device... (Takes up to 30 seconds.)"
|
||||
if ! ${OPENOCD} -f openocd/interface_"${ADAPTER}".cfg \
|
||||
if ! ${OPENOCD} -f "openocd/interface_${ADAPTER}.cfg" \
|
||||
-c "init;" \
|
||||
-c "halt;" \
|
||||
-f openocd/rdp0.cfg >>logs/4_openocd.log 2>&1; then
|
||||
|
|
44
5_restore.sh
44
5_restore.sh
|
@ -1,36 +1,48 @@
|
|||
#!/bin/bash
|
||||
|
||||
source config.sh $1
|
||||
source config.sh $@
|
||||
|
||||
if ! test -f backups/internal_flash_backup.bin; then
|
||||
echo "No backup of internal flash found in backups/internal_flash_backup.bin"
|
||||
if [[ $TARGET == "mario" ]] && \
|
||||
test -f backups/flash_backup.bin && test -f backups/internal_flash_backup.bin && \
|
||||
! test -f backups/flash_backup_$TARGET.bin && ! test -f backups/internal_flash_backup_$TARGET.bin \
|
||||
; then
|
||||
echo "Discovered mario backups with old names. Renaming files to the new format."
|
||||
mv backups/flash_backup.bin backups/flash_backup_$TARGET.bin
|
||||
mv backups/internal_flash_backup.bin backups/internal_flash_backup_$TARGET.bin
|
||||
fi
|
||||
|
||||
if ! test -f backups/internal_flash_backup_$TARGET.bin; then
|
||||
echo "No backup of internal flash found in backups/internal_flash_backup_$TARGET.bin"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! test -f backups/flash_backup.bin; then
|
||||
echo "No backup of SPI flash found in backups/flash_backup.bin"
|
||||
if ! test -f backups/flash_backup_$TARGET.bin; then
|
||||
echo "No backup of SPI flash found in backups/flash_backup_$TARGET.bin"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Ok, restoring original firmware! (We will not lock the device, so you won't have to repeat this procedure!)"
|
||||
|
||||
|
||||
echo "Restoring internal flash..."
|
||||
if ! ${OPENOCD} -f openocd/interface_"${ADAPTER}".cfg \
|
||||
echo "Restoring SPI flash..."
|
||||
if ! ${OPENOCD} -f "openocd/target_${TARGET}.cfg" -f "openocd/interface_${ADAPTER}.cfg" \
|
||||
-c "init;" \
|
||||
-c "halt;" \
|
||||
-c "program backups/internal_flash_backup.bin 0x08000000 verify;" \
|
||||
-c "program backups/flash_backup_${TARGET}.bin 0x90000000 verify;" \
|
||||
-c "exit;" >>logs/5_openocd.log 2>&1; then
|
||||
echo "Restoring SPI flash failed. Check debug connection and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
echo "Restoring internal flash..."
|
||||
if ! ${OPENOCD} -f "openocd/target_${TARGET}.cfg" -f "openocd/interface_${ADAPTER}.cfg" \
|
||||
-c "init;" \
|
||||
-c "halt;" \
|
||||
-c "program backups/internal_flash_backup_${TARGET}.bin 0x08000000 verify;" \
|
||||
-c "exit;" >>logs/5_openocd.log 2>&1; then
|
||||
echo "Restoring internal flash failed. Check debug connection and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
echo "Restoring SPI flash..."
|
||||
if ! ./scripts/flashloader.sh $ADAPTER backups/flash_backup.bin; then
|
||||
echo "Restoring SPI flash failed. Check debug connection and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Success, your device should be running the original firmware again!"
|
||||
echo "(You should power-cycle the device now)"
|
||||
|
|
13
README.md
13
README.md
|
@ -1,6 +1,6 @@
|
|||
# Game and Watch Backup and Restore tools
|
||||
|
||||
This repository contains pre-built tools for backing up & restoring the original Game and Watch firmware.
|
||||
This repository contains pre-built tools for backing up & restoring the original Game and Watch firmware. Both the Mario and Zelda variants are supported.
|
||||
|
||||
What you'll need:
|
||||
- A Game & Watch in original state
|
||||
|
@ -27,6 +27,8 @@ Please note that we recommend either a (full-size, not mini) J-Link/J-Link Edu,
|
|||
|
||||
When connecting the debugger ensure that at least SWDIO, SWDCLK and GND are connected. Do *not* under any circumstances connect 3.3V to the VDD connection. If your debug probe (for example ST-Link clones) does not have a VTREF connector, just leave VDD unconnected. Connecting 3.3V to VDD will likely destroy your SPI flash.
|
||||
|
||||
The debug connector of the Zelda variant shares pinout with the Mario variant, but has two extra connections (PB3 and N/C). The small triangle points to pin 1.
|
||||
|
||||
### Supported Debuggers
|
||||
|
||||
Please either use an official ST-Link (not one of the small USB stick clones) or a full-size J-Link. Others might work, a lot of them do not work with the 1.9V logic levels used on the Game and Watch.
|
||||
|
@ -108,7 +110,7 @@ Your device was not modified by the scripts, so it should just continue to work
|
|||
Step 3 will change the internal flash of the device. If this step fails it will leave your device in a bricked state. To recover from it run:
|
||||
|
||||
```
|
||||
./scripts/flashloader.sh <stlink or jlink or rpi> ./backups/flash_backup.bin
|
||||
./restore_only_external_flash.sh <stlink or jlink or rpi> <mario or zelda>
|
||||
```
|
||||
|
||||
If the script can't connect to the device, press & hold down power on the device while running flashloader & try to FULLY powercycle the target between attempts.
|
||||
|
@ -131,10 +133,3 @@ Other channels:
|
|||
- *#replacement-pcb* In here we discuss the possibilities and development of replacement PCBs for the Game and Watch.
|
||||
- [game-and-watch-hacking wiki](https://github.com/ghidraninja/game-and-watch-hacking/wiki) A reference wiki all things hacking the Game & Watch. Including internals.
|
||||
|
||||
|
||||
## Sources for binaries
|
||||
|
||||
The binaries in firmware/ are based on:
|
||||
|
||||
- [flashloader](https://github.com/ghidraninja/game-and-watch-flashloader)
|
||||
- [flashdumper](https://github.com/ghidraninja/game-and-watch-flashdumper)
|
||||
|
|
35
config.sh
35
config.sh
|
@ -7,12 +7,39 @@ if [[ -z ${OPENOCD} ]]; then
|
|||
exit 2
|
||||
fi
|
||||
|
||||
helptext() {
|
||||
echo "Usage: $0 <Adapter: jlink or stlink or rpi> <mario or zelda>"
|
||||
}
|
||||
|
||||
OPENOCD_VERSION=$(${OPENOCD} -v 2> >(cut -f 4 -d" " ) |head -1)
|
||||
ADAPTER=$1
|
||||
TARGET=$2
|
||||
|
||||
mkdir -p logs backups
|
||||
if [[ $TARGET == "mario" ]]; then
|
||||
SPIFLASH_SKIP_16=0
|
||||
SPIFLASH_COUNT_16=$(( 0xfe000 / 16 ))
|
||||
FLASH_OFFSET=0
|
||||
elif [[ $TARGET == "zelda" ]]; then
|
||||
# 0x0000_0000 - 0x0000_008f volatile area
|
||||
# 0x0000_1000 - 0x0000_108f volatile area
|
||||
# 0x0000_2000 - 0x0000_2b1f volatile area
|
||||
# 0x0000_4000 - 0x0000_4b1f volatile area
|
||||
# 0x0000_6000 - 0x0000_6b1f volatile area
|
||||
# 0x0000_8000 - 0x0000_8b1f volatile area
|
||||
# 0x0002_0000 - 0x0032_549f ROM area
|
||||
# 0x003e_0000 - 0x0040_0000 volatile area
|
||||
|
||||
if [[ $# -ne 1 ]] && [[ ! "$0" =~ .*"config.sh" ]]; then
|
||||
echo "Usage: $0 <Adapter: jlink or stlink or rpi>"
|
||||
exit 1
|
||||
SPIFLASH_SKIP_16=$(( 0x20000 / 16 ))
|
||||
SPIFLASH_COUNT_16=$(( (0x3254a0 - 0x20000) / 16 ))
|
||||
FLASH_OFFSET=$(( 0x30c3a8 ))
|
||||
else
|
||||
helptext
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $# -ne 2 ]] && [[ ! "$0" =~ .*"config.sh" ]]; then
|
||||
helptext
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p logs backups
|
Binary file not shown.
Binary file not shown.
|
@ -1,22 +1,17 @@
|
|||
#!/bin/bash
|
||||
|
||||
source config.sh $1
|
||||
source config.sh $@
|
||||
|
||||
echo "Installing on internal flash..."
|
||||
if ! ${OPENOCD} -f openocd/interface_"${ADAPTER}".cfg \
|
||||
-c "init;" \
|
||||
-c "halt;" \
|
||||
-c "program prebuilt/gw_retrogo_nes.elf;" \
|
||||
-c "program prebuilt/gw_retrogo_nes_extflash.bin 0x90000000"
|
||||
-c "exit;" >>logs/5_openocd.log 2>&1; then
|
||||
echo "Installing on flash failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
echo "Installing data on SPI flash..."
|
||||
if ! ./scripts/flashloader.sh $ADAPTER prebuilt/gw_retrogo_nes_extflash.bin; then
|
||||
echo "Installing on SPI flash failed. Check debug connection and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Success!"
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
init
|
||||
echo "Dump ITCM area"
|
||||
dump_image backups/itcm_backup.bin 0x0 1300
|
||||
echo "Reset and halt"
|
||||
reset halt
|
||||
echo "Load image"
|
||||
load_image firmware/flash_dumper.elf
|
||||
reset halt
|
||||
sleep 1000
|
||||
echo "Set stack pointer"
|
||||
reg sp [mrw 0x20000000]
|
||||
reg pc [mrw 0x20000004]
|
||||
echo "Continuing, wait ca. 10 seconds"
|
||||
resume
|
||||
sleep 10000
|
||||
|
||||
halt
|
||||
echo "Dumping"
|
||||
dump_image backups/flash_backup.bin 0x24000000 1048576
|
||||
echo "Done!"
|
||||
exit
|
||||
|
||||
echo ""
|
||||
echo "Dump ITCM area: backups/itcm_backup_${TARGET}.bin ${ITCM_OFFSET} ${ITCM_LENGTH}"
|
||||
echo ""
|
||||
dump_image backups/itcm_backup_${TARGET}.bin ${ITCM_OFFSET} ${ITCM_LENGTH}
|
||||
|
||||
echo ""
|
||||
echo "Reset and halt"
|
||||
echo ""
|
||||
reset halt
|
||||
|
||||
echo ""
|
||||
echo "Starting to dump the external flash..."
|
||||
echo ""
|
||||
dump_image backups/flash_backup_${TARGET}.bin 0x90000000 ${SPIFLASH_SIZE}
|
||||
|
||||
echo ""
|
||||
echo "External flash dumped!"
|
||||
echo ""
|
||||
exit
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
# Use this script to upload flash dumper using a JLink
|
||||
|
||||
source [find openocd/interface_jlink.cfg]
|
||||
source [find openocd/flash.cfg]
|
|
@ -1,2 +0,0 @@
|
|||
source [find openocd/interface_rpi.cfg]
|
||||
source [find openocd/flash.cfg]
|
|
@ -1,4 +0,0 @@
|
|||
# Use this script to upload flash dumper using an STLink
|
||||
|
||||
source [find openocd/interface_stlink.cfg]
|
||||
source [find openocd/flash.cfg]
|
|
@ -1,4 +1,4 @@
|
|||
source [find interface/jlink.cfg]
|
||||
adapter speed 500
|
||||
transport select swd
|
||||
source [find target/stm32h7x.cfg]
|
||||
source [find openocd/stm32h7x_spiflash.cfg]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
source [find interface/sysfsgpio-raspberrypi.cfg]
|
||||
source [find openocd/rpi.cfg]
|
||||
transport select swd
|
||||
source [find target/stm32h7x.cfg]
|
||||
source [find openocd/stm32h7x_spiflash.cfg]
|
||||
reset_config none
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
source [find interface/stlink.cfg]
|
||||
adapter speed 500
|
||||
transport select hla_swd
|
||||
source [find target/stm32h7x.cfg]
|
||||
source [find openocd/stm32h7x_spiflash.cfg]
|
||||
|
||||
reset_config none
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
# Nintendo Game & Watch: Super Mario Bros. and Zelda
|
||||
|
||||
set OCTOSPI1 1
|
||||
set OCTOSPI2 0
|
||||
|
||||
source [find target/stm32h7x.cfg]
|
||||
|
||||
# HXA-001 QSPI initialization
|
||||
# Based on https://forums.pimoroni.com/t/accessing-external-flash-from-openocd/12558
|
||||
# With contributions by https://github.com/jan2642 and https://github.com/GMMan
|
||||
proc hxa-001_qspi_init { } {
|
||||
echo "Initializing Octo-SPI interface"
|
||||
|
||||
# PB01: OCTOSPIM_P1_IO0, PD12: OCTOSPIM_P1_IO1, PE02: OCTOSPIM_P1_IO2,
|
||||
# PA01: OCTOSPIM_P1_IO3, PB02: OCTOSPIM_P1_CLK, PE11: OCTOSPIM_P1_NCS,
|
||||
# PD01: 1.8V power
|
||||
|
||||
# Enable GPIO clocks
|
||||
mmw 0x58024540 0x0000001b 0x00000000 ;# RCC_AHB4ENR |= GPIOAEN | GPIOBEN | GPIODEN | GPIOEEN
|
||||
# Enable Octo-SPI clocks
|
||||
mmw 0x58024534 0x00204000 0x00000000 ;# RCC_AHB3ENR |= OCTOSPI1EN | OCTOSPIMEN (enable clocks)
|
||||
sleep 1 ;# Wait for clock startup
|
||||
|
||||
# Set GPIO ports (push-pull, no pull)
|
||||
# Port A: PA01:AF09:V
|
||||
mmw 0x58020000 0x00000000 0x00000004 ;# GPIOA_MODER
|
||||
mmw 0x58020008 0x0000000c 0x00000000 ;# GPIOA_OSPEEDR
|
||||
mmw 0x58020020 0x00000090 0x00000000 ;# GPIOA_AFRL
|
||||
# Port B: PB01:AF11:V PB02:AF09:V
|
||||
mmw 0x58020400 0x00000000 0x00000014 ;# GPIOB_MODER
|
||||
mmw 0x58020408 0x0000003c 0x00000000 ;# GPIOB_OSPEEDR
|
||||
mmw 0x58020420 0x000009b0 0x00000000 ;# GPIOB_AFRL
|
||||
# Port D: PD01:OP:L PD12:AF09:V
|
||||
mmw 0x58020c00 0x00000000 0x01000008 ;# GPIOD_MODER
|
||||
mmw 0x58020c08 0x03000000 0x00000000 ;# GPIOD_OSPEEDR
|
||||
mmw 0x58020c24 0x00090000 0x00000000 ;# GPIOD_AFRH
|
||||
# Port E: PE02:AF09:V PE11:AF11:V
|
||||
mmw 0x58021000 0x00000000 0x00400010 ;# GPIOE_MODER
|
||||
mmw 0x58021008 0x00c00030 0x00000000 ;# GPIOE_OSPEEDR
|
||||
mmw 0x58021020 0x00000900 0x00000000 ;# GPIOE_AFRL
|
||||
mmw 0x58021024 0x0000b000 0x00000000 ;# GPIOE_AFRH
|
||||
|
||||
# Reset Octo-SPI
|
||||
mmw 0x5802447c 0x00204000 0x00000000 ;# RCC_AHB3RSTR |= OCTOSPIMRST | OCTOSPI1RST
|
||||
# Take Octo-SPI out of reset
|
||||
mmw 0x5802447c 0x00000000 0x00204000 ;# RCC_AHB3RSTR &= ~(OCTOSPIMRST | OCTOSPI1RST)
|
||||
|
||||
# Turn on 1.8v power
|
||||
mww 0x58020c18 0x00010000 ;# GPIOD_BSRR |= BR1
|
||||
|
||||
# Set up Octo-SPI interface
|
||||
mww 0x52005000 0x00000400 ;# OCTOSPI_CR: FMODE=0x0, FTHRES=0x04
|
||||
mww 0x52005008 0x011B0208 ;# OCTOSPI_DCR1: MTYP=0x1, DEVSIZE=0x1B, CSHT=0x2, DLYBYP=0x1
|
||||
mww 0x5200500c 0x00000002 ;# OCTOSPI_DCR2: PRESCALER=0x02
|
||||
mmw 0x52005000 0x00000001 0x00000000 ;# OCTOSPI_CR: EN=0x1
|
||||
|
||||
# reset the Macronix flash
|
||||
mww 0x52005100 0x00000001 ;# OCTOSPI_CCR: no data, no address, no alternate bytes, instruction on a single line
|
||||
# indirect write mode without data, address and alternate bytes causes the following commands to be sent immediately
|
||||
mww 0x52005110 0x00000066 ;# OCTOSPI_IR: Reset-Enable (RSTEN)
|
||||
sleep 1
|
||||
mww 0x52005110 0x00000099 ;# OCTOSPI_IR: Reset (RST)
|
||||
sleep 20 ;# wait for the flash to come out of reset
|
||||
|
||||
mmw 0x52005000 0x30000000 0x00000001 ;# OCTOSPI_CR |= FMODE=0x3, &= ~EN
|
||||
# OCTOSPI1: memory-mapped 1-line read mode with 3-byte addresses
|
||||
mww 0x52005100 0x01002101 ;# OCTOSPI_CCR: DMODE=0x1, ABMODE=0x0, ADSIZE=0x2, ADMODE=0x1, ISIZE=0x0, IMODE=0x1
|
||||
mww 0x52005110 0x00000003 ;# OCTOSPI_IR: INSTR=READ
|
||||
mmw 0x52005000 0x00000001 0x00000000 ;# OCTOSPI_CR |= EN
|
||||
|
||||
flash probe 1 ;# load configuration from CR, TCR, CCR, IR register values
|
||||
}
|
||||
|
||||
$_CHIPNAME.cpu0 configure -event reset-end {
|
||||
flash probe 0
|
||||
hxa-001_qspi_init
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
set TARGET "mario"
|
||||
set SPIFLASH_SIZE 1048576
|
||||
set ITCM_OFFSET 0x00
|
||||
set ITCM_LENGTH 1300
|
|
@ -0,0 +1,4 @@
|
|||
set TARGET "zelda"
|
||||
set SPIFLASH_SIZE 4194304
|
||||
set ITCM_OFFSET 0x20
|
||||
set ITCM_LENGTH 1300
|
Binary file not shown.
|
@ -1,12 +1,12 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
parser = argparse.ArgumentParser(description='')
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('flash_image', nargs=1, type=argparse.FileType('rb'))
|
||||
parser.add_argument('tcm_ram_image', nargs=1, type=argparse.FileType('rb'))
|
||||
parser.add_argument('flash_offset', nargs=1, type=int)
|
||||
parser.add_argument('itcm_image', nargs=1, type=argparse.FileType('rb'))
|
||||
parser.add_argument('code', nargs=1, type=argparse.FileType('rb'))
|
||||
parser.add_argument('flash_out', nargs=1, type=argparse.FileType('wb'))
|
||||
args = parser.parse_args()
|
||||
|
@ -20,16 +20,16 @@ def xor(b1, b2):
|
|||
|
||||
|
||||
flash_image = args.flash_image[0].read()
|
||||
tcm_ram_image = args.tcm_ram_image[0].read()
|
||||
itcm_image = args.itcm_image[0].read()
|
||||
code = args.code[0].read()
|
||||
|
||||
|
||||
xor_image = xor(tcm_ram_image[:len(code)], flash_image)
|
||||
|
||||
xor_image = xor(itcm_image[:len(code)], flash_image[args.flash_offset[0]:args.flash_offset[0]+len(code)])
|
||||
|
||||
new_flash_part = xor(code, xor_image)
|
||||
flash_end = flash_image[len(code):]
|
||||
flash_end = flash_image[args.flash_offset[0] + len(code):]
|
||||
|
||||
if (args.flash_offset[0] > 0):
|
||||
args.flash_out[0].write(flash_image[:args.flash_offset[0]])
|
||||
|
||||
args.flash_out[0].write(new_flash_part)
|
||||
args.flash_out[0].write(flash_end)
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
parser = argparse.ArgumentParser(description='')
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('flash_image', nargs=1, type=argparse.FileType('rb'))
|
||||
parser.add_argument('tcm_ram_image', nargs=1, type=argparse.FileType('rb'))
|
||||
parser.add_argument('code', nargs=1, type=argparse.FileType('rb'))
|
||||
parser.add_argument('flash_out', nargs=1, type=argparse.FileType('wb'))
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
def xor(b1, b2):
|
||||
result = bytearray()
|
||||
for b1, b2 in zip(b1, b2):
|
||||
result.append(b1 ^ b2)
|
||||
return result
|
||||
|
||||
|
||||
flash_image = args.flash_image[0].read()
|
||||
tcm_ram_image = args.tcm_ram_image[0].read()
|
||||
code = args.code[0].read()
|
||||
|
||||
|
||||
xor_image = xor(tcm_ram_image[:len(code)], flash_image)
|
||||
|
||||
|
||||
new_flash_part = xor(code, xor_image)
|
||||
flash_end = flash_image[len(code):]
|
||||
|
||||
|
||||
args.flash_out[0].write(new_flash_part)
|
||||
args.flash_out[0].write(flash_end)
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
|
||||
source config.sh $@
|
||||
|
||||
if ! test -f backups/flash_backup_$TARGET.bin; then
|
||||
echo "No backup of SPI flash found in backups/flash_backup_$TARGET.bin"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Restoring SPI flash..."
|
||||
if ! ${OPENOCD} -f "openocd/target_${TARGET}.cfg" -f "openocd/interface_${ADAPTER}.cfg" \
|
||||
-c "init;" \
|
||||
-c "reset halt;" \
|
||||
-c "program backups/flash_backup_${TARGET}.bin 0x90000000 verify;" \
|
||||
-c "exit;" >>logs/5_openocd.log 2>&1; then
|
||||
echo "Restoring SPI flash failed. Check debug connection and try again."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Success, your device should be running the original firmware again!"
|
||||
echo "(You should power-cycle the device now)"
|
|
@ -1,62 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
source config.sh $1
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
ELF=firmware/flash_programmer.elf
|
||||
ADDRESS=0
|
||||
SIZE=$((1024 * 1024))
|
||||
MAGIC="0xdeadbeef"
|
||||
ERASE=1
|
||||
IMAGE=$2
|
||||
objdump=${OBJDUMP:-arm-none-eabi-objdump}
|
||||
|
||||
function get_symbol {
|
||||
name=$1
|
||||
objdump_cmd="${objdump} -t ${ELF}"
|
||||
size=$(${objdump_cmd} | grep " $name" | cut -d " " -f1 | tr 'a-f' 'A-F')
|
||||
printf "$((16#${size}))\n"
|
||||
}
|
||||
|
||||
VAR_program_size=$(printf '0x%08x\n' $(get_symbol "program_size"))
|
||||
VAR_program_address=$(printf '0x%08x\n' $(get_symbol "program_address"))
|
||||
VAR_program_magic=$(printf '0x%08x\n' $(get_symbol "program_magic"))
|
||||
VAR_program_done=$(printf '0x%08x\n' $(get_symbol "program_done"))
|
||||
VAR_program_erase=$(printf '0x%08x\n' $(get_symbol "program_erase"))
|
||||
|
||||
|
||||
if ! ${OPENOCD} -f openocd/interface_"${ADAPTER}".cfg \
|
||||
-c "init;" \
|
||||
-c "echo \"Resetting device\";" \
|
||||
-c "echo \"Programming ELF\";" \
|
||||
-c "load_image ${ELF};" \
|
||||
-c "reset halt;" \
|
||||
-c "sleep 100;" \
|
||||
-c "echo \"Loading image into RAM\";" \
|
||||
-c "load_image ${IMAGE} 0x24000000;" \
|
||||
-c "mww ${VAR_program_size} ${SIZE}" \
|
||||
-c "mww ${VAR_program_address} ${ADDRESS}" \
|
||||
-c "mww ${VAR_program_magic} ${MAGIC}" \
|
||||
-c "mww ${VAR_program_erase} ${ERASE}" \
|
||||
-c "reg sp [mrw 0x20000000];" \
|
||||
-c "reg pc [mrw 0x20000004];" \
|
||||
-c "echo \"Starting flash process\";" \
|
||||
-c "resume; exit;" >>logs/flashloader.log 2>&1; then
|
||||
echo "Loading failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
echo "Loaded flashloader, flashing SPI, please wait."
|
||||
|
||||
echo " (If this takes more than 2 minutes something went wrong.)"
|
||||
echo " (If the screen blinks rapidly, something went wrong.)"
|
||||
echo " (If the screen blinks slowly, everything worked but the script didn't detect it)"
|
||||
while true; do
|
||||
DONE_MAGIC=$(${OPENOCD} -f openocd/interface_${ADAPTER}.cfg -c "init; mdw ${VAR_program_done}" -c "exit;" 2>&1 | grep ${VAR_program_done} | cut -d" " -f2)
|
||||
if [[ "$DONE_MAGIC" == "cafef00d" ]]; then
|
||||
echo "Done!"
|
||||
break;
|
||||
fi
|
||||
sleep 1
|
||||
done
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
source config.sh $1
|
||||
source config.sh $@
|
||||
|
||||
echo "This will lock your device! Are you sure? (y/N)"
|
||||
read -n 1 -r
|
||||
|
@ -11,13 +11,13 @@ then
|
|||
fi
|
||||
|
||||
echo "Validating internal flash backup before proceeding..."
|
||||
if ! shasum --check shasums/internal_flash_backup.bin.sha1 >/dev/null 2>&1; then
|
||||
if ! shasum --check shasums/internal_flash_backup_$TARGET.bin.sha1 >/dev/null 2>&1; then
|
||||
echo "Backup is not valid. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Locking device... (Takes up to 30 seconds.)"
|
||||
if ! ${OPENOCD} -f openocd/interface_"${ADAPTER}".cfg \
|
||||
echo "Locking device... (Takes up to 30 seconds.)"
|
||||
if ! ${OPENOCD} -f "openocd/interface_${ADAPTER}.cfg" \
|
||||
-c "init;" \
|
||||
-c "halt;" \
|
||||
-f openocd/rdp1.cfg >>logs/rdp1_openocd.log 2>&1; then
|
||||
|
|
|
@ -1 +1 @@
|
|||
eea70bb171afece163fb4b293c5364ddb90637ae backups/flash_backup_checksummed.bin
|
||||
eea70bb171afece163fb4b293c5364ddb90637ae backups/flash_backup_checksummed_mario.bin
|
|
@ -0,0 +1 @@
|
|||
1c1c0ed66d07324e560dcd9e86a322ec5e4c1e96 backups/flash_backup_checksummed_zelda.bin
|
|
@ -1 +1 @@
|
|||
efa04c387ad7b40549e15799b471a6e1cd234c76 backups/internal_flash_backup.bin
|
||||
efa04c387ad7b40549e15799b471a6e1cd234c76 backups/internal_flash_backup_mario.bin
|
|
@ -0,0 +1 @@
|
|||
ac14bcea6e4ff68c88fd2302c021025a2fb47940 backups/internal_flash_backup_zelda.bin
|
|
@ -1 +0,0 @@
|
|||
ca71a54c0a22cca5c6ee129faee9f99f3a346ca0 backups/itcm_backup.bin
|
|
@ -0,0 +1 @@
|
|||
ca71a54c0a22cca5c6ee129faee9f99f3a346ca0 backups/itcm_backup_mario.bin
|
|
@ -0,0 +1 @@
|
|||
2f70156235ffd871599facf64457040d549353b4 backups/itcm_backup_zelda.bin
|
Loading…
Reference in New Issue