pyamlboot / simply explained A guide, not a flashing app
LESS JARGON. MORE PICTURES.

A little Python.
A whole new start.

How does a computer put new software on a TV box? Meet pyamlboot: the messenger that helps an Amlogic chip load small helpers, then write firmware to storage.

A computer reads a firmware package and sends commands and bytes over USB to a TV box. A temporary helper in RAM writes persistent eMMC storage.
THE 10-SECOND VERSION The PC delivers. The box’s bootloader does the actual storage work. Open full-size ↗

This is an explanation, not a success report. No board was connected or flashed for this guide. Your exact .img was not available at the supplied home-directory path, so its contents, selected protocol and AM6+ compatibility are unknown. Nothing on this website accesses USB or runs a shell command.

02 / THE INGREDIENTS

One file. Many moving parts.

Think of an Amlogic burning image as a delivery crate—not a photograph, and not necessarily a raw copy of a disk.

An upgrade image contains a header and index, platform instructions, temporary DDR and U-Boot loaders, partition payloads, verification material and sometimes an aml/usb_flow marker.
Item names are examples of package roles. They are not an inventory of your uninspected image. Tap or click any diagram to open it full-size.
A / THE MAP

Where things go

conf/platform supplies addresses and settings used by the classic route. The image index tells Python where each item starts and how large it is.

B / THE HELPERS

How to get started

USB/DDR and USB/UBOOT are boot-stage payloads. Secure variants may use _ENC. They must match the hardware and its security requirements.

C / THE DELIVERY

What stays on the box

PARTITION/… items supply persistent firmware. Separate VERIFY/… items can tell the loader how to check a written item.

“Encrypted” in a filename is not a diagnosis. Python does not infer secure-boot state from this name. It queries the device on the chosen path and selects appropriate payloads. It does not magically decrypt arbitrary images, sign firmware or bypass a chip’s trusted keys.
03 / UNDER THE HOOD

A stack of small jobs.

The name pyamlboot refers to the project, a Python package, and a low-level module. Here is who actually does what.

ubt.py uses amlimage.py to read the package, then dispatches to optimus.py or adnl.py. Optimus uses the low-level pyamlboot module and USB backend adapter. ADNL uses PyUSB directly. Both ultimately reach libusb, the operating system, USB and the device loader.
The two protocol engines share the image reader, but do not share an identical transport path.

What has to exist outside Python?

PC SIDE

PyUSB → libusb → your OS

PyUSB is the Python USB interface. libusb is native host software underneath it. The operating system also needs permission to access the device. Installing Python packages alone does not guarantee a working USB backend.

In this checkout, the classic adapter tries libusb0 on Linux; ADNL lets PyUSB choose its default backend. “Install libusb” is not a guarantee that both routes are configured.

DEVICE SIDE

Matching loaders + matching firmware

The chip’s built-in ROM starts the conversation. Downloaded loaders prepare memory and provide storage commands. The firmware must fit the AM6+, not just another box with a related chip.

This Python route does not load the Windows vendor DLLs or execute the recovered vendor Lua. A marker called usb_flow selects Python code; it is not run as a Lua script here.

Booting ≠ flashing. Scripts such as boot-g12.py load boot software; ubt.py orchestrates persistent firmware writing. G12B USB-boot support alone is not proof of end-to-end AM6+ flashing support. The checkout’s setup.py does not install ubt.py as a command, so this example is a source-checkout workflow.
04 / READ THE REQUEST

Your command, translated.

“Open this package, prepare storage with normal erase policy, flash its selected route, then request a reboot.”

EXPLANATION ONLY · NOT A DRY RUN
python ubt.py \
  --img ~/A_UGOOS/sbx_ugoos_am6_encrypted_atv_54_21/sbx_ugoos_am6_encrypted_atv_54_21.img \
  --wipe normal \
  --reset

Shown for understanding—not a recommendation to run before validation.

python ubt.py

Start the coordinator

Assumes your working directory is pyamlboot/ in the source checkout and python is Python 3. Imports and dependencies must work before argument parsing can finish.

--img … .img

Open the delivery crate

Your shell expands the unquoted ~ to your home folder. Python opens the file for binary reading, then parses its header and item index. The full image is not necessarily loaded into RAM at once.

--wipe normal

Request erase code 1

normal → 1, no → 0, all → 3. The selected engine passes that number to the device’s storage-initialization command. Normal is destructive; it does not mean “keep my apps.”

--reset

Request a reboot at the end

Classic: burn_complete 1. ADNL: reboot. This happens only if execution reaches the final step; it does not certify that Android will boot successfully.

Two easily missed details. Your command supplies no --password, so a locked classic USB interface may stop it. It also omits --no-erase-bootloader: the classic plan therefore includes an early, conditional old-bootloader erase/reset step. This is separate from --wipe normal.

Use ordinary spaces and put each backslash directly before the newline. A space after a backslash breaks shell line continuation. The command above normalizes the formatting of the supplied example.

ubt.py asks whether the package contains aml/usb_flow. If absent it calls do_optimus_burn with all parsed arguments. If present it calls do_adnl_burn with reset, wipe value and the image. This is package-marker selection, not device auto-detection.
Source: ubt.py → main(). The AM6+ is a classic-route candidate, but the actual branch cannot be established from the filename.
05 / FOLLOW THE BYTES

From a file to a fresh start.

Choose a route to explore. This changes the explanation only—it does not inspect an image or connect to anything.

    The classic route at a glance

    Classic plan: parse and build plan, optional early password and old bootloader erase, password and security check, load BL2 and U-Boot into RAM when needed, reconnect, low_power, disk_initial 1, transfer items in package order and verify flagged items, save_setting, burn_complete 1. Early bootloader erase and storage initialization can destroy data.
    The early bootloader operation can already alter storage. There is no universally safe “everything before disk_initial” boundary.

    Three helpers, like a relay team

    ROM / IPL: built into the chip, can accept initial boot code.
    BL2 / SPL: prepares memory and helps load later boot software.
    U-Boot / TPL: provides the commands that write firmware storage.

    The program identifies the current stage. A device already in a later stage may skip some downloads. This is not a promise that every connected board is accepted.

    Temporary is not permanent

    A USB/UBOOT loader runs as a temporary helper. A PARTITION/bootloader item, if present, is firmware written to persistent storage. Similar names, different jobs.

    A loader running successfully from RAM does not prove the on-storage firmware or the next Android boot is correct.

    RAM is a temporary workbench containing downloaded helpers. eMMC is persistent storage containing boot firmware, Android partitions and user data. U-Boot bridges USB transfers to storage commands. Reset loses temporary RAM state but preserves changes made to eMMC.
    Storage commands are executed by device-side software. Host intent and actual erase scope are not the same thing.
    What does one classic partition transfer look like?

    BurnStepDownloadMedia first tells the loader the destination, the item’s normal or sparse format, and its encoded size. A sparse image is a compact recipe for blocks, not a ZIP archive; the loader understands how to expand it.

    For each classic item: send download destination format size, send chunks of up to 64 KiB with acknowledgement and limited retries, check download get_status, then send verify arguments only if the item verification flag is set.

    For dtb/meson1, the destination is mem dtb; for PARTITION/… it is store <name>. The loop sends up to 64 KiB per chunk. It expects an OK!! acknowledgement and handles busy replies and limited resend attempts. Transfer status and optional device-side verification are separate checks.

    Verification uses text from the matching VERIFY/<name> item. It is not a universal host-side readback of every partition. A missing required verification item can fail late. Source: BurnStepDownloadMedia.

    06 / REALITY CHECK

    A plausible path. Not a green light.

    The S922X/G12B family is relevant to pyamlboot. That does not establish compatibility with this AM6+, its security configuration, or this particular image.

    Four gates before a flashing claim: inspect exact image, identify exact device and security, validate the transfer implementation, and test recovery plus final boot. None of these gates is certified by this website.
    These are recommended validation gates, not checks that ubt.py automatically performs.
    KNOWN LIMITS

    Do not mistake parsing for validation

    The inspected image reader checks magic and format version but does not fully validate CRC, all item bounds, overlaps or malformed counts. Some reads rely on assertions. A package opening successfully is not a safety certificate.

    The classic SPL constructor accepts only platform value 0x0811. A matching chip family alone does not get past that gate.

    NO ROLLBACK

    A failed flash can leave a partial result

    An erase or write may have completed before a timeout or exception. Stopping the PC program does not undo device-side changes. A successful transfer log does not prove the box boots.

    “Normal” erase is intended to exclude reserved key data in the documented classic loader policy, but actual behaviour depends on the loader and layout. It is not a backup or a promise to preserve DRM, settings or user data.

    Before any hardware write

    • Obtain trusted firmware specifically for the AM6+ hardware revision; distinguish a USB-burning image from a recovery/OTA ZIP.
    • Inspect the image’s marker, platform settings, loader variants, partition formats and verification material offline.
    • Identify the actual USB stage and security/password requirements with a deliberately read-only procedure. “USB helper” commands are not automatically read-only.
    • Resolve relevant parser/transfer defects and test with malformed/short inputs before trusting the tool with storage.
    • Have a device-appropriate backup and recovery plan, stable power and a confirmed upgrade-mode USB connection. Do not substitute VIM3 firmware.

    This is not a full setup or recovery tutorial. No --dry-run exists in the inspected ubt.py, and its image-loading path is not a comprehensive preflight. No buttons here execute the example command.

    A SMALL TRANSLATION DESK

    Big words, small meanings.

    Firmware
    The low-level and operating-system software prepared for this particular box.
    Flash / burn
    Write persistent storage. It does not mean the box is physically burning.
    SoC
    System-on-chip: the main processor and many supporting functions in one chip.
    RAM / DDR
    The temporary workbench. A DDR loader helps get that memory ready.
    eMMC
    The box’s built-in persistent storage; closer to a disk than to RAM.
    Partition
    A named region of storage with a particular purpose, such as boot or system.
    Bootloader
    Software that prepares hardware and starts the next stage; some versions also accept flashing commands.
    Secure boot
    A device trust policy that can require approved boot software. It is not implied by a filename.
    Re-enumeration
    A USB device disappears and comes back as boot software changes. The host must find it again.
    Checksum
    A numerical check for data consistency. Transfer checks are not proof of authenticity or successful boot.
    07 / KEEP US HONEST

    Where the explanation comes from.

    Source inspection, not observed execution. Diagrams are original explanatory drawings, not screenshots or captured device traces.

    Read in code

    Arguments, dispatch rule, class structure and command ordering in this local checkout.

    Conditional explanation

    Stage/security branches and image items depend on real inputs. The step explorer illustrates them.

    Not established

    Your image contents, AM6+ compatibility, actual erase scope, runtime behaviour and final boot.

    Snapshot: local pyamlboot base commit d2857f4, with uncommitted changes in adnl.py. The explorer describes the files inspected for this guide, not an assertion about all upstream versions. Existing fix branches/PRs are not assumed to be cumulatively applied.