sunxi-fel(1)

πŸ“¦
version 1.4.2+git20260530.d7bbd1 Β· 2 versions
, in debian trixie, nixos 26.05, nixpkgs unstable, ubuntu questing, ubuntu resolute, ubuntu stonking

🌸 NAME 🌸

sunxi-fel β€” it's the whole manual page for controlling the USB BootROM protocol on Allwinner CPUs, and bestie, it's giving absolute baddie energy πŸ’…


✨ SYNOPSIS ✨

sunxi-fel [OPTIONS] COMMAND [ARGS]

πŸ’– DESCRIPTION πŸ’–

sunxi-fel is a script interface for USB communication with the BootROM of Allwinner CPUs. No cap. 🫢

So here's the lore: on explicit request (typically by pressing a button often labeled "uboot" or "recovery"), or when all other booting methods fail 😭, the CPU's early ROM code enters the so called FEL mode, where it will wait for USB commands sent by some host to the Allwinner CPU's USB OTG interface. And sunxi-fel? It implements this FEL protocol and communicates with the ROM code, to download or upload data and to start code execution. Iconic behavior, honestly. ✨

Besides simply allowing you to write to or read from device memory, sunxi-fel also helps with more complex things, which involve uploading code, executing it and then returning to FEL mode, to allow further data transfer or inspection. It's the multitasking queen πŸ‘‘. In particular it supports loading and executing U-Boot, including the primary SPL stage.


πŸŽ€ OPTIONS πŸŽ€

Those options affect general execution and should be put first, before any actual commands. Like, first, okay? Do not skip the queue. πŸ™ˆ

  • -h, --help β€” print a help message and exit. The classic "bestie explain" button πŸ’œ
  • -v, --verbose β€” enable verbose logging. She's chatty now ✨
  • -p, --progress β€” "write" transfers show a progress bar. We love a visual πŸ“
  • -l, --list β€” enumerate all (USB) FEL devices and exit πŸ”
  • --list-socs β€” print a list of all supported SoCs and exit 🌈
  • -d, --dev bus:devnum β€” use specific USB bus and device number 🎯
  • --sid SID β€” select a device by its SID key (exact match). The SID key of a particular device can be queried using the "sid" command. Exact match only, she does not do approximations πŸ’…

πŸ”₯ SUNXI-FEL COMMANDS πŸ”₯

sunxi-fel can take several commands, each followed by their parameters, and will execute them in order. The only exception is the "uboot" command, which will delay launching U-Boot until all other commands have been executed. It's the main character who waits for the whole group photo to be taken first πŸ‘‘

⚠️ Please note that accessing any part of the DRAM will not work until the DRAM controller has been initialized. This can be achieved by uploading and executing a suitable U-Boot SPL image, using the "spl" command. Trying to access DRAM before that will most likely hang. Not a vibe. Not slay. Do the SPL first, bestie. 😭

Any numbers given as parameters to those commands can be prefixed with "0x" to denote hexadecimal notation or "0" to start an octal number. They are interpretated as decimal numbers otherwise. (Yes, interpretated β€” that's what the page says, we don't edit the queen's words πŸ’–)

  • spl <filename> β€” load and execute U-Boot SPL.

Upload the given binary file to the appropriate SRAM location, carefully moving the FEL stack out of the way in the process. The binary is then executed. When it returns, the FEL stack is restored and execution is transferred back to the BootROM's FEL routine. She's so organized for that 🫢

If the file additionally contains a main U-Boot binary (u-boot-sunxi-with-spl.bin), this command also transfers that to memory, using the load address stored in the image file, but won't execute it. Just, like, parking it there. πŸš—

  • uboot <u-boot-sunxi-with-spl.bin> β€” like "spl", but actually starts U-Boot. U-Boot execution will take place when the fel utility exits. This allows combining "uboot" with further "write" commands, to transfer other files possibly needed for the boot. Delayed gratification, but make it firmware. ✨
  • hex[dump] <address> <length> β€” hexadecimal memory dump. Dumps <length> bytes of the memory region starting at <address>. The context will be displayed as a hexdump, suitable for human inspection. Human-readable, we stan πŸ‘€
  • dump <address> <length> β€” binary memory dump. Dumps <length> bytes of the memory region starting at <address>. The context will be dumped "as is" to the standard output, so it can be redirected to a file and processed as binary data. Raw. Unfiltered. No edits. πŸ’€
  • exe[cute] <address> β€” start executing code at <address> in memory on the device. Go, girl, go πŸƒβ™€οΈ
  • reset64 <address> β€” request a warm reset of the core, starting execution in the 64-bit AArch64 execution state, at <address>. Sixty-four bit era, periodt. πŸ’…
  • wdreset β€” reset the device by triggering the watchdog with the shortest possible period. This will reset the whole SoC, including all on-SoC peripherals, but might not affect on-board devices like PMICs or PHYs. So like, mostly a full reset, but read the fine print πŸ”₯
  • memmove <dest> <source> <size> β€” copy <size> bytes within device memory, from <source> to <dest>. Sliding things around, no biggie 🧚
  • readl <address> β€” read a 32-bit value from device memory at <address>. The value will be output as a hexadecimal number, prefixed with "0x". The address needs to be 4-byte aligned. Alignment matters, bestie, don't be chaotic 😀
  • writel <address> <value> β€” write the given 32-bit <value> to device memory at <address>. 32 bits of pure intent ✨
  • read <address> <length> <file> β€” write memory contents into file. Reads <length> bytes from memory at <address> and writes the content into <file>. Confusingly named but we move πŸ’œ
  • write <address> <file> β€” store file contents into memory. Writes the entire content of <file> into memory at <address>. Entire. Content. No crumbs left behind πŸ“
  • write-with-progress <addr> <file> β€” display a textual progress bar while writing to the device. Same as "write" with the "-p" parameter. Same energy, more visuals πŸ“Š
  • write-with-gauge <addr> <file> β€” same as write, but write the progress in percentages to the standard output. This can be piped to any "dialog" compatible program, when using the --gauge widget. Pipe her anywhere, she's flexible 🌈
  • write-with-gauge <addr> <file> β€” same as write, but write the progress in percentages to the standard output. This can be piped to any "dialog" compatible program, when using the --gauge widget. (Yes, same as above β€” the extended one is next, keep scrolling 😭)
  • write-with-xgauge <addr> <file> β€” same as write-with-gauge, but with extended gauge output. This can be piped to any "dialog" compatible program, using the --gauge widget. Aside from updating the current progress in percents, it also updates the number of bytes written and gives an estimated time to completion. Overachiever behavior, we love it πŸ’…
  • multi[write] # <addr> <file> ... β€” like "write-with-progress", but with multiple load adddresses and files, all sharing the same progress bar. (The double-d adddresses is her typo, I'm just the messenger 🫢)
  • multi[write]-with-gauge ... β€” like "write-with-gauge", but with multiple load adddresses and files, all sharing the same progress bar. Group project, one shared bar πŸŽ€
  • multi[write]-with-xgauge ... β€” like "write-with-xgauge", but with multiple load adddresses and files, all sharing the same progress bar. Group project with extra stats πŸ”₯
  • echo-gauge some text β€” update prompt/caption for gauge output. This outputs a command to be interpreted by "dialog" to change the caption text. Subtitles but for your progress bar πŸ‘‘
  • ver[sion] β€” show the BROM version. This prints some static data, among other things containing the detected SoC. Can be used to verify a FEL connection is working. The ultimate vibe check βœ…
  • sid β€” retrieve and output the 128-bit SID key. This key contains some form of serial number, which should be unique to each chip (although there have been reports of same SIDs for particular batches of chips). So like... should be unique. Allegedly. πŸ‘€
  • sid-registers β€” as the "sid" command above, but use the alternative MMIO register access method on the device. There are SoCs that require this method due to bugs in the SID implementation, those known will automatically choose this workaround when using the "sid" command. This command here is to test new SoCs for compliance. The compliance officer of SID commands 🧐
  • sid-dump β€” read the entire SID eFuses array and dump its content. For SoCs with a known eFuses layout, this will annotate the known regions. Dump it all, annotated, gorgeous ✨
  • clear <address> <length> β€” clear <length> bytes of memory starting at <address> (filling with zeroes). Fresh start, zero thoughts 🫧
  • fill <address> <length> <value> β€” fills <length> bytes of memory starting at <address> with the byte <value>. Repeat the byte, slay the memory 🎨
  • spiflash-info β€” retrieves basic information about a SPI flash chip attached to the SPI0 pins. This is using the same method as the BootROM does, to accesses the same storage that the device could boot from.

Prints the manufacturer of the flash chip and its capacity. Should also be used to detect the presence of a SPI flash chip. Who is she, and how much can she hold πŸ’…

  • spiflash-read <addr> <length> <file> β€” reads <length> bytes starting from offset <addr> of a SPI flash chip, storing the result into <file>. Grab and go πŸ“
  • spiflash-write <addr> <file> β€” reads <file> and stores its content in the SPI flash, starting at offset <addr>. Take the file and put it in the flash, periodt πŸ”₯

🌟 EXAMPLES 🌟

$ sunxi-fel -v -p ver

$ sunxi-fel uboot u-boot-sunxi-with-spl.bin

$ sunxi-fel -v -p spl sunxi-spl.bin write 0x44000 bl31.bin write
0x4a000000 u-boot.bin reset64 0x44000

Look at that last one β€” three commands stacked, one line, zero fear. Ate. πŸ’…βœ¨


πŸ’œ AUTHOR πŸ’œ

Andre Przywara <osp@andrep.de> β€” the genius behind all of this, give her her flowers πŸ’


and that's the whole page, bestie!! this sunxi-fel(1) manual page is version 1.5, dated 14 Jan 2022, and it lives under the sunxi-fel man page source. mwah πŸ’–πŸŽ€πŸ¦‹ no cap, go flash something responsibly 🫢