Add support for the Zelda variant

This commit is contained in:
Konrad Beckmann 2021-11-14 15:06:48 +01:00
parent 72d2aa74c7
commit 441d74b5d8
33 changed files with 262 additions and 219 deletions

View File

@ -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

View File

@ -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!"

View File

@ -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"

View File

@ -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

View File

@ -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)"

View File

@ -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)

View File

@ -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.

View File

@ -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!"

View File

@ -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

View File

@ -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]

View File

@ -1,2 +0,0 @@
source [find openocd/interface_rpi.cfg]
source [find openocd/flash.cfg]

View File

@ -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]

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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
}

4
openocd/target_mario.cfg Normal file
View File

@ -0,0 +1,4 @@
set TARGET "mario"
set SPIFLASH_SIZE 1048576
set ITCM_OFFSET 0x00
set ITCM_LENGTH 1300

4
openocd/target_zelda.cfg Normal file
View File

@ -0,0 +1,4 @@
set TARGET "zelda"
set SPIFLASH_SIZE 4194304
set ITCM_OFFSET 0x20
set ITCM_LENGTH 1300

Binary file not shown.

View File

@ -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)

View File

@ -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)

21
restore_only_external_flash.sh Executable file
View File

@ -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)"

View File

@ -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

View File

@ -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

View File

@ -1 +1 @@
eea70bb171afece163fb4b293c5364ddb90637ae backups/flash_backup_checksummed.bin
eea70bb171afece163fb4b293c5364ddb90637ae backups/flash_backup_checksummed_mario.bin

View File

@ -0,0 +1 @@
1c1c0ed66d07324e560dcd9e86a322ec5e4c1e96 backups/flash_backup_checksummed_zelda.bin

View File

@ -1 +1 @@
efa04c387ad7b40549e15799b471a6e1cd234c76 backups/internal_flash_backup.bin
efa04c387ad7b40549e15799b471a6e1cd234c76 backups/internal_flash_backup_mario.bin

View File

@ -0,0 +1 @@
ac14bcea6e4ff68c88fd2302c021025a2fb47940 backups/internal_flash_backup_zelda.bin

View File

@ -1 +0,0 @@
ca71a54c0a22cca5c6ee129faee9f99f3a346ca0 backups/itcm_backup.bin

View File

@ -0,0 +1 @@
ca71a54c0a22cca5c6ee129faee9f99f3a346ca0 backups/itcm_backup_mario.bin

View File

@ -0,0 +1 @@
2f70156235ffd871599facf64457040d549353b4 backups/itcm_backup_zelda.bin