Get started

Unlock your PF1007L and get root ADB

On this page

This guide is for owners of a PF1007L photo frame who can use a Linux shell and PowerShell. When you finish, the frame boots normally but accepts root ADB connections, and you have a verified backup of its storage. No soldering, and you never open the case.

Do this guide first. After it, go to Build the kiosk and set up a frame. Provisioning also needs a running server, which you set up with Install the frame server. The server does not depend on this guide, so you can do it before or after.

Before you start

Warning

This can brick the frame. You write to its storage. Follow the backup step before any write, and check each write the way the guide says.

  • The backup holds the frame's private credentials. The image of the storage includes the vendor's device certificate. Keep backups/ out of Git, and never upload or share it. The repository's .gitignore already ignores it.
  • Root ADB has no password. After this guide, anyone who can reach the frame's network port 5555 has full control. Provisioning shows how to restrict it with ADB_ALLOW.
  • Only the January 2026 firmware was tested. The one-sector ADB method was verified on firmware AEEZO/astar_m86_8723cs:6.0.1/MOB30R/20260113:eng/test-keys. Other firmware may store files in different places. The patch is made from your own backup, so it adapts, but nothing here is verified on other builds. If tools/derive-sector.sh stops with an error, stop and do not guess.
  • Only modify hardware you own.

What you need

  • A PF1007L frame, with its USB-C cable. The frame takes power from USB.
  • Windows 10 or 11 with WSL2 (Ubuntu 22.04 or later). The scripts call powershell.exe and PowerShell disk commands, so this guide does not work on a plain Linux machine without changes.
  • usbipd-win 4 or later on Windows.
  • A microSD card, any size. Its contents survive. The guide changes only bytes 8 KiB to 16 KiB.
  • About 16 GB of free disk space for the backup, and patience. The backup takes about 90 minutes.

In this guide, WSL means a shell in your Linux distribution. PowerShell means an Administrator PowerShell on Windows. <repo> means the folder holding this repository, written the way Windows sees it.

Note

The .ps1 scripts write backups\ next to themselves and read patch\ there. If your clone lives inside the WSL file system, the Windows path looks like \\wsl.localhost\Ubuntu\home\you\frame. Writing a 15 GB image over that path is slow. Cloning to a Windows drive such as /mnt/d/frame gives both sides the same fast folder. Neither layout has been compared.

The map

Nine steps. The backup in step 6 is not optional, and nothing writes to the frame's storage before it.

flowchart TD
    A["1. Set up your computer"] --> B["2. Build U-Boot"]
    B --> C["3. Get fel-sdboot.sunxi"]
    C --> D["4. Make the FEL card"]
    D --> E["5. Show the frame's storage to Windows"]
    E --> F["6. Back up and verify the storage"]
    F -->|"backup verified"| G["7. Make the patch from your backup"]
    G --> H["8. Apply the patch"]
    H --> I["9. First boot with ADB"]
    F -.->|"not verified"| X["Stop. Do not write anything."]

Each step ends with a You are here box. If what you see does not match, stop and use If something goes wrong.

Step 1: Set up your computer

  1. In WSL, install the tools:

    sudo apt install -y sunxi-tools adb e2fsprogs fdisk
    
  2. Allow your user to talk to the frame in FEL mode (the Allwinner USB recovery mode):

    echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1f3a", ATTR{idProduct}=="efe8", MODE="0666"' | sudo tee /etc/udev/rules.d/61-sunxi-fel.rules
    sudo udevadm control --reload
    
  3. In PowerShell, tell usbipd it may share the frame's two USB identities with WSL automatically:

    usbipd policy add --effect Allow --operation AutoBind --hardware-id 1f3a:efe8
    usbipd policy add --effect Allow --operation AutoBind --hardware-id 1f3a:1001
    

    1f3a:efe8 is FEL mode. 1f3a:1001 is Android with ADB on.

  4. In PowerShell, stop Windows from mounting the frame's partitions. First note the current value so you can restore it later:

    Get-StorageSetting | Select NewDiskPolicy
    Set-StorageSetting -NewDiskPolicy OfflineAll
    

    Write down the value the first command prints. You put it back in When you finish.

  5. Copy .env.example to .env in the repository root. You fill in USBIP_BUSID in step 5. Provisioning explains every key.

    cp .env.example .env
    

You are here

Your computer has the tools, the udev rule and the usbipd policy. Windows no longer mounts new disks automatically. Nothing has touched the frame.

Step 2: Build U-Boot

The frame's storage is not visible to your PC while Android runs. You temporarily boot a small program called U-Boot that shows the storage as a USB disk. The repository holds the patch for it but no binaries, so you build them.

The build needs an ARM cross-compiler.

  1. Install the build tools (Debian or Ubuntu package names):

    sudo apt install -y gcc-arm-linux-gnueabihf bison flex swig device-tree-compiler \
      python3-pyelftools python3-setuptools libgnutls28-dev uuid-dev git make
    

    The python3- packages are U-Boot's own build dependencies. Project code uses no Python.

  2. Build it, using a work directory outside the repository:

    uboot/build.sh ~/frame-uboot-build
    

The script clones U-Boot v2025.01, applies the patch and writes u-boot-sunxi-with-spl.bin and sunxi-spl-ck5.bin into uboot/. It prints their SHA-256 hashes. The first run needs network access to source.denx.de. See uboot/README.md for what the patch changes.

Note

The build is not bit-for-bit reproducible. The binaries embed a build timestamp, so two builds from the same source have different hashes.

You are here

uboot/ holds u-boot-sunxi-with-spl.bin and sunxi-spl-ck5.bin, and the script printed a SHA-256 for each.

Step 3: Get fel-sdboot.sunxi

fel-sdboot.sunxi is a tiny boot program that puts the frame into FEL mode and keeps it there. It comes from linux-sunxi/sunxi-tools. Its license differs from this repository's, so it is not included.

  1. Get the file from the sunxi-tools repository. If the repository does not hold a ready-made copy, build it. The on-device programs are not built by default, and need an ARM bare-metal compiler (arm-none-eabi-gcc). Install it the same way as the U-Boot tools in step 2:

    git clone https://github.com/linux-sunxi/sunxi-tools ~/sunxi-tools
    make -C ~/sunxi-tools target-tools CROSS_COMPILE=arm-none-eabi-
    

    Not verified

    This build command was not checked. The linux-sunxi wiki page on sunxi-tools describes fel-sdboot.

  2. Copy the file to uboot/fel-sdboot.sunxi.

  3. Check its SHA-256:

    sha256sum uboot/fel-sdboot.sunxi
    

    write-sd.ps1 accepts only this hash, the one the procedure was tested with:

    19db8994363b1464a1de82e1c90ab63c5a985d1c96b57403d039d69bfff39f14
    

    If your hash differs, the script stops with fel-sdboot.sunxi hash mismatch. A different build of sunxi-tools produces a different file. Check that your file is the real fel-sdboot from the upstream source, then edit $ImageSha at the top of write-sd.ps1 to your hash. Do not skip the check.

You are here

uboot/fel-sdboot.sunxi exists, and its hash is either the one above or a hash you checked against upstream and wrote into write-sd.ps1.

Step 4: Make the FEL card

The frame's boot ROM looks at the microSD slot before the internal storage. With this card in the slot, pressing RESET puts the frame into FEL mode and keeps it there. Pressing RESET alone also enters FEL, but it times out after a second or two, which is too short for this procedure.

  1. Put the microSD card in your PC.

  2. In PowerShell, find the card:

    Get-Disk
    

    Note its Number and its exact Size in bytes. Check this twice. The script writes to the disk number you give it.

  3. Write the file:

    powershell -ExecutionPolicy Bypass -File <repo>\write-sd.ps1 -DiskNumber <number> -ExpectSize <size in bytes>
    

    The script refuses to run unless the disk is a USB disk of exactly that size. It first backs up the card's first 16 MiB to backups\sd-<size>-first-16MiB.bin, writes the file at the 8 KiB offset, and reads it back. You see OK: fel-sdboot.sunxi written at offset 8192 and verified.

  4. Put the card in the frame's microSD slot.

From now on: RESET with the card in enters FEL mode (1f3a:efe8). RESET with the card removed boots Android normally.

You are here

The script printed OK: fel-sdboot.sunxi written at offset 8192 and verified. and the card is in the frame.

Step 5: Show the frame's storage to Windows

  1. Plug the frame's USB-C port directly into your PC, not through a hub.

  2. In PowerShell, find the frame's bus ID:

    usbipd list
    

    The frame is 1f3a:efe8 if it is in FEL mode. Press the RESET pinhole with the card in if it is not.

  3. Put the bus ID in .env:

    USBIP_BUSID=<bus id from usbipd list>
    

    A bus ID looks like 1-13. The script refuses anything else.

  4. In WSL, run:

    scripts/boot-ums.sh
    
  5. Press the frame's RESET button.

The script waits up to 30 minutes for FEL mode and attaches the frame to WSL. It runs a first DRAM set-up pass, because the first memory set-up after power-on fails and the second succeeds. Then it loads U-Boot. U-Boot shows the storage as a USB disk named Linux UMS disk 0. The script ends with eMMC visible to Windows and a table with a disk number and size.

Rules for this step:

  • Never attach 1f3a:1010 (U-Boot's disk) with usbipd. The disk drops and does not recover. Never run usbipd attach --auto-attach on this bus ID.
  • Cancel every "format this disk" prompt. The partition table mislabels the Android data partition as FAT32.
  • If the disk disappears, U-Boot returns to FEL mode on its own, or its 16 second watchdog resets the frame into FEL mode. Run scripts/boot-ums.sh again. Press RESET only if FEL does not answer.

You are here

The script printed eMMC visible to Windows and a table with a disk number and a size of 15758000128. Windows shows the disk offline. You have not written anything to it.

Step 6: Back up the storage

Warning

Do not go on until the backup is verified.

In PowerShell, while the disk is up:

powershell -ExecutionPolicy Bypass -File <repo>\backup-emmc.ps1

The script marks the disk read-only, writes backups\emmc-full.img, then reads the whole disk a second time and compares the SHA-256 of both passes. At about 5.7 MB/s, each pass takes around 45 minutes. It ends with OK: ... verified by two independent reads. and writes backups\emmc-full.img.sha256.

The script expects a 15,758,000,128 byte disk, the size of the tested unit. If yours differs, pass -ExpectSize <bytes>.

If the second pass is interrupted, run verify-backup.ps1 instead. It compares the image with the disk up to the user-data partition (about 2 GB, 7 minutes). If the disk drops, run it again with -Start <byte offset> from the last progress line:

powershell -ExecutionPolicy Bypass -File <repo>\verify-backup.ps1

Then check the system partition read-only in WSL. Expect only the message padding at end of inode bitmap, which is normal for Android images:

fdisk -l backups/emmc-full.img

Find the start sector of partition 7 (system), then:

dd if=backups/emmc-full.img of=system.img bs=512 skip=<start sector> count=<sectors>
e2fsck -fn system.img
rm system.img

You are here

backups\emmc-full.img and backups\emmc-full.img.sha256 exist, the script printed OK: ... verified by two independent reads. (or verify-backup.ps1 passed), and e2fsck -fn found nothing but padding at end of inode bitmap. Copy backups/ somewhere private. Do not continue without this.

Step 7: Make the patch from your backup

Android decides whether to turn ADB on from one line in /system/build.prop: persist.sys.usb.config=mass_storage. The patch changes mass_storage to adb, followed by a newline and #padding. The file stays the same length and no file-system structures change.

tools/derive-sector.sh finds that one 512-byte sector in your own backup and writes the original and patched copies to patch/.

  1. In WSL, run:

    tools/derive-sector.sh
    

    It reads backups/emmc-full.img by default. Pass another image path as an argument. If the system partition is not number 7, set SYSTEM_PART=<number>.

  2. Check the output. You expect something like:

    bytes changed (expect up to 12): 12
    sector <n>, in-sector offset <m>; wrote patch/sector-{number.txt,orig.bin,adb.bin}
    

    If the script prints 'persist.sys.usb.config=mass_storage' not found, the line is already patched or your firmware differs. Stop.

  3. Confirm the data partition has no override. A file at /property/persist.sys.usb.config on the data partition would beat build.prop. On the tested firmware, the data partition starts at byte 2,235,564,032 (sector 4,366,336):

    debugfs -R 'stat /property/persist.sys.usb.config' 'backups/emmc-full.img?offset=2235564032'
    

    You expect File not found. The ?offset= form needs e2fsprogs 1.43 or later. On other firmware, take the start of the last partition from fdisk -l.

You are here

patch/ holds sector-number.txt, sector-orig.bin and sector-adb.bin, and the data partition has no override file.

Step 8: Apply the patch

With the storage still showing as a disk, in PowerShell:

powershell -ExecutionPolicy Bypass -File <repo>\patch-sector.ps1

The script:

  • refuses to write unless the live sector is identical to patch\sector-orig.bin,
  • writes the 512-byte sector,
  • reads it back and compares it,
  • marks the disk read-only again.

It ends with OK: sector <n> now holds the ADB-enabled build.prop line, verified by readback. If the sector is already patched it says so and does nothing.

If your disk is not 15,758,000,128 bytes, pass -ExpectSize <bytes>.

To put the stock sector back later, run the same command with -Restore while U-Boot shows the disk.

You are here

The script printed OK: sector <n> now holds the ADB-enabled build.prop line, verified by readback. The frame's storage differs from the backup by one sector.

Step 9: First boot with ADB

  1. Take the microSD card out of the frame.

  2. Press RESET. The frame boots Android as usual, with the stock home app.

  3. In PowerShell, find the frame. It now reports 1f3a:1001:

    usbipd list
    usbipd attach --wsl --busid <bus id>
    
  4. In WSL:

    adb devices
    adb shell id
    

You see the frame in adb devices, and adb shell id prints uid=0(root). ADB asks for no authorization. You are done unlocking.

Keep the microSD card. It is your way back into FEL mode.

You are here

adb shell id prints uid=0(root). The frame is unlocked. The backup is safe. Next you build the kiosk.

When you finish

  • Put Windows back to the disk policy you wrote down in step 1. Use the value the first command printed:

    Set-StorageSetting -NewDiskPolicy <the value you noted>
    
  • Keep backups/ and patch/ private and backed up. Do not add them to Git.

  • Keep the FEL microSD card. You use it for any later recovery.

If something goes wrong

  • Frame will not enter FEL mode. Check that the card is in, and that usbipd list shows 1f3a:efe8. Press RESET again.
  • boot-ums.sh says warm-up SPL did not return. Press RESET to restart FEL, and run the script again.
  • boot-ums.sh says eMMC disk did not appear in Windows. Check that Windows has not set the disk offline for another reason, then run the script again.
  • boot-ums.sh says timeout. It waited 30 minutes without seeing FEL. Check the card, the cable, and that the frame is not plugged into a hub.
  • A write script says it expected exactly one disk. U-Boot's disk is not up, or its size differs from the default. Pass -ExpectSize.
  • patch-sector.ps1 says the sector does not match. Do not force it. Check that patch/ was made from this frame's own backup.
  • Undo the ADB change. Show the disk with scripts/boot-ums.sh, then run patch-sector.ps1 -Restore.
  • The frame will not boot after a write. Follow step 4 of The frame does not boot. It restores your backup.
  • adb devices shows nothing. Run usbipd list, find the frame (1f3a:1001), and attach it again.

More recovery steps, including a frame that does not boot and a lost PIN, are in Troubleshooting and recovery.

Next: Install the frame server, if you have not already. Then Build the kiosk and set up a frame.