Skip to content

Instantly share code, notes, and snippets.

@roman-yepishev
Last active February 5, 2026 00:17
Show Gist options
  • Select an option

  • Save roman-yepishev/737dfda3a0a853fe730286d3ce49fccd to your computer and use it in GitHub Desktop.

Select an option

Save roman-yepishev/737dfda3a0a853fe730286d3ce49fccd to your computer and use it in GitHub Desktop.
SanDisk Clip Sport Recovery Mini-HOWTO

Warning

I can only confirm that this works on SanDisk Clip Sport devices. You might be able to use that guide for other devices based on ATJ212X SoCs, but you are on your own.

This guide instructs you to run unverified code from arbitrary GitHub repositories, including as root. You should use a system that you aren't afraid to brick. You can use a VM with USB pass-through, though I YOLO'd this on a physical machine.

This guide will erase your data on the SanDisk Clip Sport, if that device is functional, so if you want to backup the data, (which you may or may not be able to use later) see the Backup section.

Audience

Owners of SanDisk Clip Sport devices which are failing to boot when connected to the USB cable and who have access to a Linux system, since that's the only system I can verify these steps on.

The symptoms of failed SanDisk Clip Sport that this guide might resolve are:

  1. When connected to the computer "SanDisk" logo appears and gets stuck, lsusb shows ID 10d6:10d6 Actions Semiconductor Co., Ltd

  2. When connected to the computer, the device boots into the OS, but immediately reboots after rescanning the media.

  3. You attempted to re-flash the devices using tools in https://github.com/nfd/atj2127decrypt/blob/master/dfu/actions_adfu_upgrade.py and now your device does not even show in lsusb.

Note, that if your device boots into a screen that says "FW Updating ... Don't Disconnect" you can still try using this guide, but it is possible that your device has a physical damage causing the device to switch to the DFU mode.

Boot Process Description

This is my best guess of the process, derived from LLM-assisted translation of US212A Application Design Guide at https://github.com/Suber/PD196_ATJ2127/tree/maint/Doc.

SanDisk Clip Sport SOC is Actions ATJ2127, a MIPS CPU which has a Boot ROM, and it boots from a NAND chip on SanDisk devices.

When power is supplied to the chip, it:

  1. Starts a Boot ROM. The screen and USB is off at this point. The ROM likely initializes the flash just enough for it to be readable, looks for a minimal Stage 1 bootloader - MBREC with a correct checksum. If the bootloader is not found, it enters a Device Firmware Update (DFU) mode and shows up to the host computer as vendor_id=10d6, product_id=10d6 USB device. If MBREC is found, it proceeds to Stage 1.
  2. Starts MBREC, which does additional initialization of the hardware and looks for BREC with a correct checksum, Stage 2 bootloader. If it does not find BREC, the boot halts and does not go back to DFU.
  3. Starts BREC - it must have information about the specific NAND chip it is running as in its header, to know how to completely intialize NAND, that information comes from a specific place within flash_id.bin shipped with the firmware upgrade. BREC also contains welcome.bin code which displays the "SanDisk" logo and reacts to Volume Up + Volume Down keypress on boot with USB connected. If it detects those keys pressed, it switches into the DFU mode, showing "FW Upgrading ... Don't Disconnect" screen.
  4. Starts the firmware running μC/OS-II operating system.

Getting to the Device Firmware Update (DFU) mode

If your device can get to the DFU by pressing Volume Up/Volume Down when inserting the USB cable, you're done with this step.

If not, you will need to remove the SD card if it is plugged in and open the device. It is held by clips all around. The back separates from the colorful bezel, but you need a thin plastic prying tool. The NAND chip is housed in a TSOP-48 package. You will want to bridge two IO pins with a small screwdriver to prevent NAND from communicating with the CPU and plug the USB cable in. I bridged pins 29 & 30 and got the device into the DFU mode. At this point your system should detect a new 10d6:10d6 device which you should see with lsusb.

If you can't get to the DFU mode, this guide will not help you, sorry.

Getting the software

You need:

  1. A linux machine (I have a Fedora box)
  2. A MIPS cross-compiler (gcc-mips64-linux-gnu package on Fedora) for actions_flash payloads, libusb1-devel and python3-libusb1 packages.
  3. upgrade.hex from SanDisk - https://support-en.sandisk.com/app/answers/detailweb/a_id/43274/~/how-to-update-clip-sport-mp3-player-firmware-to-1.43
  4. atjboottool from RockBox to unpack the software (https://github.com/Rockbox/rockbox/blob/master/utils/atj2137/atjboottool/)
  5. Reverse-engineered flash toolkit which will give us adfus.bin and nandread.bin (https://github.com/ilyakurdyukov/actions_flash). Do not use it for flashing raw files as raw files need to be patched with device-specific flash information before upload.
  6. Reverse-engineered flasher from https://github.com/nfd/atj2127decrypt.

Build Software

$ dnf install gcc-mips64-linux-gnu libusb1-devel libusb1-devel

1. actions_flash

payload/adfus.bin: make -C payload NAME=adfus CC="mips64-linux-gnu-gcc -mabi=32 -EL" OBJCOPY=mips64-linux-gnu-objcopy

actions_dump: make - needs the following patch to actually dump NAND to the disk if we need to create a backup.

diff --git a/actions_dump.c b/actions_dump.c
index 0aec729..6413d81 100644
--- a/actions_dump.c
+++ b/actions_dump.c
@@ -845,7 +845,7 @@ static void dump_nand(usbio_t *io, nandread_t *x,
 	unsigned i, psize = x->psize;
 	FILE *fo = NULL;
 
-	if (fo) {
+	if (fn) {
 		fo = fopen(fn, "wb");
 		if (!fo) ERR_EXIT("fopen(wb) failed\n");
 	} else if (!print_tags) return;

2. rockbox atjboottool

git clone https://github.com/Rockbox/rockbox.git --depth=1
make -C rockbox/utils/atj2137/atjboottool

The binary to use will be at rockbox/utils/atj2137/atjboottool/atjboottool.

Prepare the firmware

You have two options for decrypting and unpacking the firmare:

  • A reverse-engineered atj2127decrypt/decrypt which must be compiled in 32 bit mode - (CFLAGS= += -m32, LDFLAGS += -m32) but writes "adfu_info.json".
  • A decryptor from rockbox (atjboottool), rename the files to lowercase and write adfu_info.json yourself. This guide uses the second one, since you don't need to install 32-bit libraries.

1. atjboottool

Unpack:

$ # upgrade.hex should be in the current directory
$ mkdir atj2127_fw
$ rockbox/utils/atj2137/atjboottool/atjboottool -o atj2127_fw.afi upgrade.hex
$ rockbox/utils/atj2137/atjboottool/atjboottool --afi -o atj2127_fw/ atj2127_fw.afi

Move files to lowercase as that's what the flasher expects:

$ cd atj2127_fw
$ for filename in *.*; do lowercase=${filename,,}; mv $filename $lowercase; done

Plant the adfu_info.json that atj2127decrypt/dfu scripts need. fwimage.premerged: true tells the flasher that it needs to use the combined firmware image. brec.premerged: true tells the flasher not to attempt compiling brec from a separate welcome.bin and the resources. Since our goal is to flash a well known complete build from the manufacturer, we are using pre-merged binaries.

$ cat > adfu_info.json <<EOF
{
"brec":{
	"premerged": true
},
"fwimage":{
	"premerged": true,
	"premerged_filename": "fwimage.fw"
}
}
EOF

2. Add ADFU Server (adfus.bin)

Copy the compiled adfus.bin from actions_flash:

$ cp path/to/actions_flash/payload/adfus.bin atj2127_fw/

Backup (optional)

You will need to be in DFU mode for this to work, and your MBREC must be intact. If you flashed MBREC without NAND info, and you get an error from actions_flash, then you can technically alter the list of partitions the flasher will use to avoid writing the firmware, writing only mbrec and brec, this will have to be an exercise to the reader. The goal of this guide is to get the device back to the factory state.

Raw NAND

The page size is 16384 bytes (0x4000)

This is an example for 8GB device.

FLASH_SIZE_IN_GB=8
sudo ./actions_flash/actions_dump \
  chip 2127 \
  simple_switch 0xbfc18000 actions_flash/payload/adfus.bin \
  read_nand actions_flash/payload/nandread.bin 0 $(($FLASH_SIZE_IN_GB * 1024 * 1024 * 1024 / 16384)) nand.bin

This will be slow.

Later you can use binwalk or photorec to extract the data. Since I had nothing of importance on my device, I did not attempt to recover the whole FAT32 filesystem, but I confirmed that photorec recovered MP3 files.

Flashing

1. Get the device into the DFU mode.

Press Volume Up and Volume Down buttons together while inserting the USB cable. Confirm with lsusb that a device 10d6:10d6 appeared. If it did not appear, see the DFU description at the start of the page.

2. Run the flasher

You can set up udev rules to run it as your own user but this is beyond the scope of this HOWTO.

Run the flasher from atj2127decrypt, providing the path to the unpacked firmware with adfus.bin and adfu_info.json in it.

$ sudo python3 dfu/actions_adfu_upgrade.py  path/to/atj2127_fw

3. Done

If your device does not reboot, unplug and plug it back. It should now show SanDisk logo and animation.

The device might complain that the internal filesystem is damaged and reboot for recovery. That filesystem message refers to the music storage area which will be wiped clean by the device itself. You might want to format the device.

References

I am extremely grateful to folks who published their tools, as without those repositories this guide would not exist.

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