Full Code of frederic/superbird-bulkcmd for AI

main 4b0a49abcbc7 cached
21 files
13.2 MB
9.6k tokens
1 requests
Download .txt
Repository: frederic/superbird-bulkcmd
Branch: main
Commit: 4b0a49abcbc7
Files: 21
Total size: 13.2 MB

Directory structure:
gitextract_hvi_s25o/

├── README.md
├── bin/
│   └── update
├── images/
│   ├── hacked_logo.img
│   ├── superbird.bootloader.img
│   ├── superbird.initrd-base.cpio
│   ├── superbird.initrd.img
│   └── superbird.kernel.img
├── initrd/
│   ├── S49usbgadget
│   └── init
└── scripts/
    ├── burn-mode.sh
    ├── disable-avb2.sh
    ├── dump.sh
    ├── enable-adb.sh.client
    ├── env.txt
    ├── extract-cpio.sh
    ├── hacked-bootlogo.sh
    ├── initrd.list
    ├── pack-initrd.sh
    ├── uart-shell.sh
    ├── uboot-continue.sh
    └── upload-kernel.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: README.md
================================================
# "NotABug" - [superbird-bulkcmd](https://github.com/frederic/superbird-bulkcmd)

[Spotify Car Thing](https://carthing.spotify.com/) (superbird) resources to access U-Boot shell over USB. Not a bug, it is a ["feature"](https://miro.medium.com/max/1200/1*KDfUqn6c66axcbsTPPWSpQ.jpeg).

![Hacked Car Thing](https://i.imgur.com/VRjOR5v.jpg)

*Note: this method has been tested on the factory firmware (device never used/updated : App Version 0.24.107 - OS Version 6.3.29), but should work on all firmware versions released as of this article's writing.*

# Disclaimer
You are solely responsible for any damage caused to your hardware/software/keys/DRM licences/warranty/data/cat/etc...

# Requirements
- A Car Thing (superbird) without USB password
- Either a USB A to C, or a C to C cable
- A PC running some flavor of 64-bit GNU Linux
- `libusb-dev` installed

# FAQ
Does this process void my warranty on this device?
- Probably, assume so.

Can I OTA afterwards?
- If you don't perform any persistent change, probably yes.
- But if you disable dm-verity and modify on-device partitions, OTA updates will fail, though given this device is EOL, we don't expect further OTA updates.

Can I still use stock features ?
- Yes! Perfectly normal and usable, this just enables root access and ADB.

Can I go back to stock after installing custom OS's or messing up the stock image?
- Theoretically, if you have a good eMMC dump, the U-Boot shell should allow you to restore the partitions. **But this has not been tested thoroughly!**

# Files
- /bin/: prebuilt set of required tools
  - [update](https://github.com/khadas/utils/blob/master/aml-flash-tool/tools/linux-x86/update): Client for the USB Burning protocol implemented in Amlogic bootloaders
- /images/: prebuilt images to upload via USB
  - [superbird.bl2.encrypted.bin](images/superbird.bl2.encrypted.bin) : dump of hardware partition *boot0* (mmcblk0boot0)
  - [superbird.bootloader.img](images/superbird.bootloader.img) : dump of user partition *bootloader* (mmcblk0p01)
  - [superbird.initrd-base.cpio](images/superbird.initrd-base.cpio) : created by provided script [extract-cpio.sh](scripts/extract-cpio.sh)
  - [superbird.initrd.img](images/superbird.initrd.img) : created by provided script [pack-initrd.sh](scripts/pack-initrd.sh)
  - [superbird.kernel.img](images/superbird.kernel.img) : zImage extracted from user partition *boot_a* (mmcblk0p12) + weird AML modifications reverted
- /initrd/: files to customize the initrd image
- /scripts/: scripts used to simplify interactions with the devices

# Guide : U-Boot shell over USB (*USB burning mode*)
1. Unplug the Car Thing from everything
2. Clone/Download this repo locally, and change your shell's directory to it & ensure you `libusb-dev` installed
3. Hold buttons 1 & 4 on the case, and plug the Car Thing into your PC via USB

The host should see a new USB device connection in `dmesg` like this one:
```text
usb 1-1: New USB device found, idVendor=1b8e, idProduct=c003, bcdDevice= 0.20
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-1: Product: GX-CHIP
usb 1-1: Manufacturer: Amlogic
```
4. Release the button once this device has been detected by host computer.
5. Execute script [scripts/burn-mode.sh](scripts/burn-mode.sh) to boot U-Boot in *USB burning mode*.
A new USB device appears on host side :
```
usb 1-1: New USB device found, idVendor=1b8e, idProduct=c003, bcdDevice= 0.07
usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
```
6. Execute the following commands to enable U-Boot shell at every boot.

**WARNING: This step modifies the *env* partition. Changes are persistent, so it shall be executed only once.**
```shell
./bin/update bulkcmd 'amlmmc env'
./bin/update bulkcmd 'setenv storeargs ${storeargs} run update\;'
./bin/update bulkcmd 'env save'
```
7. Reboot the device by unplugging and re-plugging the USB connection.

After this modification, the device always boots in *USB burning mode* (U-Boot shell over USB) when connected to USB host : you can execute U-Boot commands using the [update](bin/update) tool, but you can't see any output (unless you open the device to connect the UART interface).

*Note: if not connected to USB host, the device continues default boot sequence.*

## Boot kernel from USB to enable ADB access
Once the device in *USB burning mode*, the script [scripts/upload-kernel.sh](scripts/upload-kernel.sh) can upload a Linux kernel image and boot it.
The init-ramdisk includes an *initd* script that starts the ADB server.
System partition is not modified, so this is not persistent.

The ADB interface appears as a new USB device on the host:
```
usb 1-2: new high-speed USB device number 18 using xhci_hcd
usb 1-2: New USB device found, idVendor=18d1, idProduct=4e40, bcdDevice= 2.23
usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-2: Product: Superbird
usb 1-2: Manufacturer: Spotify
usb 1-2: SerialNumber: 123456
```

*Note: There is a script that is intended to be run from a UART shell included in scripts that will enable persistent ADB, but is not reccomended, as it will remove the abillity to OTA update. You can find that script [here](scripts/enable-adb.sh.client).*

# Explanation
When the Car Thing launched, it largely flew under most people's radar, and comically it wasn't until Spotify _deeply_ discounted it in late 2022, to $29.99 that it caught our eyes.

This device was designed to be a simple music selection device that mounts to your car dashboard or air-vents. It is unfortunately very underpowered, with a lower-end Amlogic chip, the S905D2, paired with 500 _MB_ of RAM - ouch.

When the device was discounted, I (Nolen) picked up a few units for security research, and messaged Fred shortly after starting to ask about collaborating on it - and comically he had independently already started.

To start, U-boot and Linux kernel source code for this device is [public](https://github.com/spsgsb/) but advertised nowhere by Spotify.

We discovered shortly into research, that holding buttons 1 & 4 on boot put the deivce into Amlogic's USB mode, where you can upload BL2 images! Sweet.

We were able to upload a signed BL2, and then from there, upload a signed BL33, which kicked us into Amlogic's Burn Mode.

From here we were able to execute U-Boot shell commands via Amlogic's `update` command, and the `bulkcmd` feature it houses.

At this point, it became clear UART would aid our efforts, and with some simple voltage sniffing and an educated guess, we discerned the UART has the following pin-out:
![Car Thing UART Pin-out](https://i.imgur.com/LpP9VgB.jpg)

For our development case, we wanted more persistent access to the UART pins, so we removed the sticker on the rear of the device, dissasembled, removed the rear heat-shield, and then filed out part of the case, as shown below
![Car Thing UART Setup](https://i.imgur.com/vpUnuvx.jpg)

Once we had UART console, we continued about, and crafted a method to enable a root shell over UART:
```
sudo update bulkcmd 'amlmmc env'
sudo update bulkcmd 'setenv initargs init=/sbin/pre-init'
sudo update bulkcmd 'setenv initargs ${initargs} ramoops.pstore_en=1'
sudo update bulkcmd 'setenv initargs ${initargs} ramoops.record_size=0x8000'
sudo update bulkcmd 'setenv initargs ${initargs} ramoops.console_size=0x4000'
sudo update bulkcmd 'setenv initargs ${initargs} rootfstype=ext4'
sudo update bulkcmd 'setenv initargs ${initargs} console=ttyS0,115200n8'
sudo update bulkcmd 'setenv initargs ${initargs} no_console_suspend'
sudo update bulkcmd 'setenv initargs ${initargs} earlycon=aml-uart,0xff803000'
sudo update bulkcmd 'setenv storeargs ${storeargs} setenv avb2 0\;'
sudo update bulkcmd 'setenv initargs ${initargs} ro root=/dev/mmcblk0p15'
sudo update bulkcmd 'env save'
```

This gave us a local root shell, but still required UART - we took note that the device happened to have `adbd` locally installed, but not running.

We realized it wasn't as simple as _just_ starting the daemon, we had to [disable](scripts/disable-avb2.sh) [Android Verified Boot](https://source.android.com/docs/security/features/verifiedboot), and configure the device's USB connection in an `init.d` script, as shown in [scripts/enable-adb.sh.client](scripts/enable-adb.sh.client).

At this point we had full u-boot access, as well as persistent ADB (root) access, we initially wanted to try to bring-up Android Automotive on the device, but 500 MB of RAM made Android near-impossible to port.

We also tried to get other GUI applications _cough_ maybe doom _cough_ running, but this device utilizes a QT feature called [EGLFS](https://doc.qt.io/qt-6/embedded-linux.html), which doesn't have a window management system like X11 or Wayland, so it is hard to get additional applications running on the device, but hey, maybe someone in the community can get it working using the access we're providing!

We ended up settling on using a modified init-ramdisk loaded via USB to simplify attaining root-access for the end-user. Hope you enjoy!

# Additional Scripts (for advanced use-cases)

## To Be Executed from U-Boot shell
- [scripts/dump.sh](scripts/dump.sh) : Dump eMMC over USB
- [scripts/uart-shell.sh](scripts/uart-shell.sh) : Modify *env* partition to enable Linux root shell over UART
(**note: Access to UART port requires to open the device**) - see the "Utilizing UART" section below for more information on that.
- [scripts/disable-avb2.sh](scripts/disable-avb2.sh) : Modify *env* partition to disable `AVB2` & `dm-verity`
- [scripts/uboot-continue.sh](scripts/uboot-continue.sh) : Exit U-Boot *USB Burning mode* and continue default boot sequence
- [scripts/hacked-bootlogo.sh](scripts/hacked-bootlogo.sh) : Modify the device's bootlogo to the one shown in the header of this writeup.

## Init-Ramdisk Customizations
- [scripts/extract-cpio.sh](scripts/extract-cpio.sh) : Extract files from system partition dump to create initrd image
- [scripts/pack-initrd.sh](scripts/pack-initrd.sh) : Pack custom initrd image

## To Be Executed from an ADB (root) Shell on Device
- [scripts/enable-adb.sh.client](scripts/enable-adb.sh.client) : Modify the local file-system to start the ADB daemon on each boot. This will remove the abillity to OTA update the device, and there are no factory images yet - *MAKE SURE YOU USE THE DUMP SCRIPT ABOVE BEFORE UTILIZING THIS.* To use, open the script, and copy paste each command into an existing ADB (root) shell, or push to the device (renaming to `.sh`), and execute it.

# Known Dangerous Actions
- Many developers may (as we did) think that the easiest path to running custom code on this device would be to use the provided burn-mode access to run `update bulkcmd fastboot` and then `fastboot flashing unlock` the device. *BE WARNED*, this bricked every device we tried it on. You will end up with a blank, black screen on boot, and we have yet to discern how to recover from this. This will be updated if this type of bricked device is recoverable.

# Disclosure Notes
- October 20, 2022 - Intitial notice sent to Spotify
- October 21, 2022 - Spotify responded on HackerOne stating that the product is unsupported, and end-of-life, and therefore no bugs would be accepted pertaining to the product

*Note: This writeup doesn't technically warrant disclosure, as it doesn't leverage any specific vulnerabillities, but instead chains together what we suspect to be unintentional access venues to gain root-access.*

# Credits
- Frédéric Basse (frederic) & Nolen Johnson (npjohnson): The "exploit", writeup, debugging/developing/theorizing the methodologies used.
- Sean Hoyt (deadman): The awesome hacked-logo image.

# Relevant Device Source Code
- U-Boot: [superbird-uboot](https://github.com/spsgsb/uboot/tree/buildroot-openlinux-201904-g12a)
- GNU/Linux: [superbird-linux](https://github.com/spsgsb/kernel-common)


================================================
FILE: images/superbird.kernel.img
================================================
[File too large to display: 13.1 MB]

================================================
FILE: initrd/S49usbgadget
================================================
mkdir -p /dev/usb-ffs
mkdir -p /dev/usb-ffs/adb
mount -t configfs none /sys/kernel/config/
mkdir -p /sys/kernel/config/usb_gadget/g1
echo 0x18d1 > /sys/kernel/config/usb_gadget/g1/idVendor
echo 0x4e40 > /sys/kernel/config/usb_gadget/g1/idProduct
echo 0x0223 > /sys/kernel/config/usb_gadget/g1/bcdDevice
echo 0x0200 > /sys/kernel/config/usb_gadget/g1/bcdUSB
mkdir -p /sys/kernel/config/usb_gadget/g1/strings/0x409
echo 123456 > /sys/kernel/config/usb_gadget/g1/strings/0x409/serialnumber
echo Spotify > /sys/kernel/config/usb_gadget/g1/strings/0x409/manufacturer
echo Superbird > /sys/kernel/config/usb_gadget/g1/strings/0x409/product
mkdir -p /sys/kernel/config/usb_gadget/g1/functions/ffs.adb
mkdir -p /sys/kernel/config/usb_gadget/g1/configs/b.1
mkdir -p /sys/kernel/config/usb_gadget/g1/configs/b.1/strings/0x409
echo 500 > /sys/kernel/config/usb_gadget/g1/configs/b.1/MaxPower
mount -t functionfs adb /dev/usb-ffs/adb
ln -s /sys/kernel/config/usb_gadget/g1/configs/b.1 /sys/kernel/config/usb_gadget/g1/os_desc/b.1
echo adb > /sys/kernel/config/usb_gadget/g1/configs/b.1/strings/0x409/configuration
ln -s /sys/kernel/config/usb_gadget/g1/functions/ffs.adb /sys/kernel/config/usb_gadget/g1/configs/b.1/f1
/usr/bin/adbd &
sleep 5s
echo ff400000.dwc2_a > /sys/kernel/config/usb_gadget/g1/UDC


================================================
FILE: initrd/init
================================================
#!/bin/sh
#Mount things needed by this script
/bin/mount -t sysfs sysfs /sys
/bin/mount -t devtmpfs devtmpfs /dev
/bin/mount -t proc proc /proc
echo Beginning init from initrd
#Create device nodes
mdev -s

#Function for parsing command line options with "=" in them
# get_opt("init=/sbin/init") will return "/sbin/init"
get_opt() {
    echo "$@" | cut -d "=" -f 2
}

#Defaults
slot_suffix="_a"
init="/sbin/pre-init"
root="/dev/system"
rootfstype=
kernel_version=
#Process command line options
for i in $(cat /proc/cmdline); do
    case $i in
        root\=*)
            root=$(get_opt $i)
            ;;
        rootfstype\=*)
            rootfstype=$(get_opt $i)
            ;;
        init\=*)
            init=$(get_opt $i)
            ;;
        androidboot.slot_suffix\=*)
            slot_suffix=$(get_opt $i)
            ;;
        kernel_version\=*)
            kernel_version=$(get_opt $i)
            ;;
    esac
done

#Mount the root device
root_ab=${root}${slot_suffix}
#Waiting for device to become ready
TimedOut=10000 #10*1000 milisecond
WaitedTime=0
while [ "$WaitedTime" -lt "$TimedOut" ]
do
    if [ -b "${root}" ]; then
        echo "${root} is ready now."
        break
    elif [ -b "${root_ab}" ]; then
        echo "${root_ab} is ready now."
        root=${root_ab}
        break
    fi
    sleep 0.1
    WaitedTime=$((WaitedTime+100))
    echo "${root} is not ready.  Waited for ${WaitedTime} milisecond"
done

if [ "${rootfstype}" != "" ]; then
    mount -t ${rootfstype} -o ro "${root}" /mnt
else
    mount -o ro "${root}" /mnt
fi

#Check if $init exists and is executable
if [[ -x "/mnt/${init}" ]] ; then
    #Unmount all other mounts so that the ram used by
    #the initramfs can be cleared after switch_root
    umount /sys /proc /dev

    #Overlay ADB script in initd scripts
    mount --bind /S49usbgadget /mnt/etc/init.d/S49usbgadget

    #Switch to the new root and execute init
    /bin/mount -t devtmpfs devtmpfs /mnt/dev
    exec 0</mnt/dev/console
    exec 1>/mnt/dev/console
    exec 2>/mnt/dev/console
    exec switch_root -c /dev/console /mnt "${init}"
fi

#This will only be run if the exec above failed
echo "Failed to switch root, dropping to a shell"
exec /sbin/init "$@"


================================================
FILE: scripts/burn-mode.sh
================================================
#!/bin/sh
# Boot U-Boot in 'USB Burning' mode
DIR=$(dirname $(realpath $0))
UPDTOOL=$DIR/../bin/update

$UPDTOOL write $DIR/../images/superbird.bl2.encrypted.bin 0xfffa0000
$UPDTOOL run 0xfffa0000
$UPDTOOL bl2_boot $DIR/../images/superbird.bootloader.img


================================================
FILE: scripts/disable-avb2.sh
================================================
#!/bin/sh
# Disable AVB2 & dm-verity
# Define system_b (/dev/mmcblk0p15) as root partition (change to /dev/mmcblk0p14 for system_a).
# WARNING : This disables A/B boot mechanism.

DIR=$(dirname $(realpath $0))
UPDTOOL=$DIR/../bin/update

$UPDTOOL bulkcmd 'amlmmc env'
$UPDTOOL bulkcmd 'setenv storeargs ${storeargs} setenv avb2 0\;'
$UPDTOOL bulkcmd 'setenv initargs ${initargs} ro root=/dev/mmcblk0p15'
$UPDTOOL bulkcmd 'env save'

================================================
FILE: scripts/dump.sh
================================================
#!/bin/bash
DIR=$(dirname "$(realpath "$0")")
UPDTOOL=$DIR/../bin/update

OUTPATH="$DIR/../dump"
mkdir -p "$OUTPATH"

$UPDTOOL bulkcmd "amlmmc part 1"
$UPDTOOL mread store bootloader normal 0x400000 "$OUTPATH/bootloader.dump"
$UPDTOOL mread store env normal 0x800000 "$OUTPATH/env.dump"
$UPDTOOL mread store fip_a normal 0x400000 "$OUTPATH/fip_a.dump"
$UPDTOOL mread store fip_b normal 0x400000 "$OUTPATH/fip_b.dump"
$UPDTOOL mread store logo normal 0x800000 "$OUTPATH/logo.dump"
$UPDTOOL mread store dtbo_a normal 0x400000 "$OUTPATH/dtbo_a.dump"
$UPDTOOL mread store dtbo_b normal 0x400000 "$OUTPATH/dtbo_b.dump"
$UPDTOOL mread store vbmeta_a normal 0x100000 "$OUTPATH/vbmeta_a.dump"
$UPDTOOL mread store vbmeta_b normal 0x100000 "$OUTPATH/vbmeta_b.dump"
$UPDTOOL mread store boot_a normal 0x1000000 "$OUTPATH/boot_a.dump"
$UPDTOOL mread store boot_b normal 0x1000000 "$OUTPATH/boot_b.dump"
$UPDTOOL mread store misc normal 0x800000 "$OUTPATH/misc.dump"
$UPDTOOL mread store settings normal 0x10000000 "$OUTPATH/settings.dump"
$UPDTOOL mread store system_a normal 0x2040B000 "$OUTPATH/system_a.dump"
$UPDTOOL mread store system_b normal 0x2040B000 "$OUTPATH/system_b.dump"
$UPDTOOL mread store data normal 0x889EA000 "$OUTPATH/data.dump" # if this command fails, try 0x859EA000 instead. Thanks bishopdynamics (issue #2 @ GitHub)


================================================
FILE: scripts/enable-adb.sh.client
================================================
# Note, you must run disable-avb2.sh first!
mount -o remount,rw /
echo "mkdir -p /dev/usb-ffs">/etc/init.d/S49usbgadget
echo "mkdir -p /dev/usb-ffs/adb">>/etc/init.d/S49usbgadget
echo "mount -t configfs none /sys/kernel/config/">>/etc/init.d/S49usbgadget
echo "mkdir -p /sys/kernel/config/usb_gadget/g1">>/etc/init.d/S49usbgadget
echo "echo 0x18d1 > /sys/kernel/config/usb_gadget/g1/idVendor">>/etc/init.d/S49usbgadget
echo "echo 0x4e40 > /sys/kernel/config/usb_gadget/g1/idProduct">>/etc/init.d/S49usbgadget
echo "echo 0x0223 > /sys/kernel/config/usb_gadget/g1/bcdDevice">>/etc/init.d/S49usbgadget
echo "echo 0x0200 > /sys/kernel/config/usb_gadget/g1/bcdUSB">>/etc/init.d/S49usbgadget
echo "mkdir -p /sys/kernel/config/usb_gadget/g1/strings/0x409">>/etc/init.d/S49usbgadget
echo "echo 123456 > /sys/kernel/config/usb_gadget/g1/strings/0x409/serialnumber">>/etc/init.d/S49usbgadget
echo "echo Spotify > /sys/kernel/config/usb_gadget/g1/strings/0x409/manufacturer">>/etc/init.d/S49usbgadget
echo "echo Superbird > /sys/kernel/config/usb_gadget/g1/strings/0x409/product">>/etc/init.d/S49usbgadget
echo "mkdir -p /sys/kernel/config/usb_gadget/g1/functions/ffs.adb">>/etc/init.d/S49usbgadget
echo "mkdir -p /sys/kernel/config/usb_gadget/g1/configs/b.1">>/etc/init.d/S49usbgadget
echo "mkdir -p /sys/kernel/config/usb_gadget/g1/configs/b.1/strings/0x409">>/etc/init.d/S49usbgadget
echo "echo 500 > /sys/kernel/config/usb_gadget/g1/configs/b.1/MaxPower">>/etc/init.d/S49usbgadget
echo "mount -t functionfs adb /dev/usb-ffs/adb">>/etc/init.d/S49usbgadget
echo "ln -s /sys/kernel/config/usb_gadget/g1/configs/b.1 /sys/kernel/config/usb_gadget/g1/os_desc/b.1">>/etc/init.d/S49usbgadget
echo "echo adb > /sys/kernel/config/usb_gadget/g1/configs/b.1/strings/0x409/configuration">>/etc/init.d/S49usbgadget
echo "ln -s /sys/kernel/config/usb_gadget/g1/functions/ffs.adb /sys/kernel/config/usb_gadget/g1/configs/b.1/f1">>/etc/init.d/S49usbgadget
echo "/usr/bin/adbd &">>/etc/init.d/S49usbgadget
echo "sleep 5s">>/etc/init.d/S49usbgadget
echo "echo ff400000.dwc2_a > /sys/kernel/config/usb_gadget/g1/UDC">>/etc/init.d/S49usbgadget


================================================
FILE: scripts/env.txt
================================================
bootargs=rdinit=/init init=/sbin/pre-init ramoops.pstore_en=1 ramoops.record_size=0x8000 ramoops.console_size=0x4000 rootfstype=ext4 console=ttyS0,115200n8 no_console_suspend earlycon=aml-uart,0xff803000 root=/dev/system ro rootwait reboot_mode_android=normal logo=osd0,loaded,0x1f800000 fb_width=480 fb_height=800 vout=panel,enable panel_type=lcd_8 frac_rate_policy=1 osd_reverse=0 video_reverse=0 irq_check_en=0 androidboot.selinux=enforcing androidboot.firstboot=0 jtag=disable uboot_version=v1.0-57-gec3ec936c2 androidboot.hardware=amlogic androidboot.slot_suffix=_a

================================================
FILE: scripts/extract-cpio.sh
================================================
#!/bin/sh
# Extract base files from /system partition required to build an initramdisk.

DIR=$(dirname $(realpath $0))
SYSTEM_DIR=
CPIO_BASE_FILE=$DIR/../images/superbird.initrd-base.cpio

if [ -z "$SYSTEM_DIR" ] || [ ! -d "$SYSTEM_DIR" ]
then
echo 'Error: Set SYSTEM_DIR variable to path of mounted /system partition from the device.'
exit 1
else
cd $SYSTEM_DIR && cat $DIR/initrd.list | cpio --quiet -o -H newc > $CPIO_BASE_FILE
fi

================================================
FILE: scripts/hacked-bootlogo.sh
================================================
#!/bin/bash
DIR=$(dirname "$(realpath "$0")")
UPDTOOL=$DIR/../bin/update

$UPDTOOL bulkcmd "amlmmc part 1"
$UPDTOOL partition logo $DIR/../images/hacked_logo.img


================================================
FILE: scripts/initrd.list
================================================
.
./var
./var/lib
./var/lib/alsa
./var/lib/misc
./var/spool
./var/cache
./var/log
./var/lock
./var/run
./var/tmp
./var/www
./lib
./lib/arm-none-linux-gnueabihf
./lib/ld-2.30.so
./lib/ld-linux-armhf.so.3
./lib/libatomic.so.1
./lib/libatomic.so.1.2.0
./lib/libblkid.so.1
./lib/libblkid.so.1.1.0
./lib/libc-2.30.so
./lib/libcrypt-2.30.so
./lib/libcrypt.so.1
./lib/libc.so.6
./lib/libdl-2.30.so
./lib/libdl.so.2
./lib/libfdisk.so.1
./lib/libfdisk.so.1.1.0
./lib/libgcc_s.so.1
./lib/libm-2.30.so
./lib/libmount.so.1
./lib/libmount.so.1.1.0
./lib/libm.so.6
./lib/libnsl-2.30.so
./lib/libnsl.so.1
./lib/libnss_dns-2.30.so
./lib/libnss_dns.so.2
./lib/libnss_files-2.30.so
./lib/libnss_files.so.2
./lib/libpam.so.0
./lib/libpam.so.0.84.2
./lib/libpam_misc.so.0
./lib/libpam_misc.so.0.82.1
./lib/libpthread-2.30.so
./lib/libpthread.so.0
./lib/libresolv-2.30.so
./lib/libresolv.so.2
./lib/librt-2.30.so
./lib/librt.so.1
./lib/libsmartcols.so.1
./lib/libsmartcols.so.1.1.0
./lib/libutil-2.30.so
./lib/libutil.so.1
./lib/libuuid.so.1
./lib/libuuid.so.1.3.0
./mnt
./bin
./bin/mv
./bin/egrep
./bin/uname
./bin/dnsdomainname
./bin/login
./bin/linux32
./bin/gunzip
./bin/vi
./bin/sh
./bin/gzip
./bin/stty
./bin/sleep
./bin/mktemp
./bin/df
./bin/chgrp
./bin/sync
./bin/mt
./bin/echo
./bin/chown
./bin/pipe_progress
./bin/cat
./bin/fgrep
./bin/hostname
./bin/dd
./bin/linux64
./bin/more
./bin/mknod
./bin/getopt
./bin/zcat
./bin/setarch
./bin/printenv
./bin/rmdir
./bin/mountpoint
./bin/setserial
./bin/pidof
./bin/sed
./bin/tar
./bin/date
./bin/kill
./bin/netstat
./bin/run-parts
./bin/true
./bin/busybox
./bin/rm
./bin/ls
./bin/grep
./bin/pwd
./bin/fdflush
./bin/mkdir
./bin/chmod
./bin/ash
./bin/false
./bin/mount
./bin/ping
./bin/usleep
./bin/umount
./bin/cp
./bin/su
./bin/ln
./bin/dmesg
./bin/nice
./bin/dumpkmap
./bin/touch
./bin/ps
./bin/cpio
./bin/watch
./etc
./etc/resolv.conf
./etc/issue
./etc/mke2fs.conf
./etc/shadow
./etc/hostname
./etc/passwd
./etc/profile
./etc/group
./etc/services
./etc/network
./etc/network/if-post-down.d
./etc/network/if-up.d
./etc/network/if-pre-up.d
./etc/network/interfaces
./etc/network/if-down.d
./etc/ssl
./etc/mtab
./etc/hosts
./etc/os-release
./etc/init.d
./etc/init.d/rcK
./etc/init.d/rcS
./etc/fstab
./etc/inittab
./etc/protocols
./linuxrc
./opt
./root
./sys
./usr
./usr/lib
./usr/lib/arm-none-linux-gnueabihf
./usr/lib/libglib-2.0.so.0
./usr/lib/libe2p.so.2
./usr/lib/libext2fs.so
./usr/lib/libext2fs.so.2
./usr/lib/libglib-2.0.so
./usr/lib/libcom_err.so.2
./usr/lib/libcom_err.so
./usr/lib/libblkid.so
./usr/lib/libcom_err.so.2.1
./usr/lib/libe2p.so.2.3
./usr/lib/libe2p.so
./usr/lib/libext2fs.so.2.4
./usr/lib/libuuid.so
./usr/bin
./usr/bin/xzcat
./usr/bin/[[
./usr/bin/xz
./usr/bin/ipcs
./usr/bin/lsof
./usr/bin/install
./usr/bin/top
./usr/bin/setkeycodes
./usr/bin/uuencode
./usr/bin/sha512sum
./usr/bin/lzcat
./usr/bin/tee
./usr/bin/uudecode
./usr/bin/[
./usr/bin/find
./usr/bin/bzcat
./usr/bin/vlock
./usr/bin/id
./bin/chattr
./bin/lsattr
./usr/bin/last
./usr/bin/test
./usr/bin/crontab
./usr/bin/cksum
./usr/bin/dos2unix
./usr/bin/dc
./usr/bin/reset
./usr/bin/du
./usr/bin/head
./usr/bin/sha3sum
./usr/bin/ipcrm
./usr/bin/deallocvt
./usr/bin/passwd
./usr/bin/killall
./usr/bin/fold
./usr/bin/uniq
./usr/bin/sha256sum
./usr/bin/xargs
./usr/bin/chrt
./usr/bin/env
./usr/bin/eject
./usr/bin/dirname
./usr/bin/free
./usr/bin/readlink
./usr/bin/chvt
./usr/bin/lspci
./usr/bin/expr
./usr/bin/md5sum
./usr/bin/mkfifo
./usr/bin/less
./usr/bin/yes
./usr/bin/printf
./usr/bin/sort
./usr/bin/fuser
./usr/bin/nohup
./usr/bin/basename
./usr/bin/hexdump
./usr/bin/who
./usr/bin/setsid
./usr/bin/wc
./usr/bin/bunzip2
./usr/bin/cmp
./usr/bin/awk
./usr/bin/mesg
./usr/bin/unlzma
./usr/bin/clear
./usr/bin/pango-view
./usr/bin/microcom
./usr/bin/unix2dos
./usr/bin/seq
./usr/bin/logname
./usr/bin/whoami
./usr/bin/uptime
./usr/bin/ar
./usr/bin/lzma
./usr/bin/realpath
./usr/bin/logger
./usr/bin/unxz
./usr/bin/diff
./usr/bin/openvt
./usr/bin/sha1sum
./usr/bin/tail
./usr/bin/which
./usr/bin/hostid
./usr/bin/resize
./usr/bin/cut
./usr/bin/patch
./usr/bin/unzip
./usr/bin/strings
./usr/bin/renice
./usr/bin/od
./usr/bin/tty
./usr/bin/time
./usr/bin/lsusb
./usr/bin/tr
./usr/libexec
./usr/lib32
./usr/sbin
./sbin/filefrag
./sbin/e2label
./sbin/mke2fs
./sbin/mkfs.ext2
./usr/sbin/delgroup
./usr/sbin/fbset
./usr/sbin/deluser
./usr/sbin/rdate
./usr/sbin/killall5
./usr/sbin/addgroup
./sbin/fsck.ext4
./usr/sbin/loadfont
./sbin/e2freefrag
./usr/sbin/chroot
./sbin/mklost+found
./sbin/fsck
./sbin/mkfs.ext4
./usr/sbin/fdformat
./sbin/e2fsck
./sbin/e2undo
./sbin/badblocks
./usr/sbin/adduser
./sbin/tune2fs
./sbin/dumpe2fs
./sbin/logsave
./usr/sbin/readprofile
./usr/sbin/arping
./sbin/fsck.ext3
./sbin/mkfs.ext3
./usr/sbin/setlogcons
./sbin/fsck.ext2
./usr/sbin/crond
./lib32
./proc
./dev
./dev/pts
./dev/log
./sbin
./sbin/lsmod
./sbin/route
./sbin/ipaddr
./sbin/halt
./sbin/getty
./sbin/swapoff
./sbin/poweroff
./sbin/hdparm
./sbin/init
./sbin/blkid
./sbin/iproute
./sbin/modprobe
./sbin/loadkmap
./sbin/watchdog
./sbin/losetup
./sbin/syslogd
./sbin/reboot
./sbin/iptunnel
./sbin/vconfig
./sbin/runlevel
./sbin/sulogin
./sbin/rmmod
./sbin/ifdown
./sbin/ifconfig
./sbin/makedevs
./sbin/mkswap
./sbin/swapon
./sbin/start-stop-daemon
./sbin/ifup
./sbin/setconsole
./sbin/sysctl
./sbin/iplink
./sbin/ip
./sbin/devmem
./sbin/pivot_root
./sbin/nameif
./sbin/iprule
./sbin/insmod
./sbin/klogd
./sbin/freeramdisk
./sbin/hwclock
./sbin/switch_root
./sbin/mdev
./run
./media
./tmp


================================================
FILE: scripts/pack-initrd.sh
================================================
#!/bin/sh
# Pack the initrd image using base CPIO archive plus additional files from initrd/ directory
# mkimage tool is available in Debian package u-boot-tools
DIR=$(dirname $(realpath $0))
INITRD_DIR=$DIR/../initrd
CPIO_BASE_FILE=$DIR/../images/superbird.initrd-base.cpio
CPIO_FILE=$DIR/../images/superbird.initrd.cpio
INITRD_FILE=$DIR/../images/superbird.initrd.img

if [ ! -f "$CPIO_BASE_FILE" ]
then
echo "Error: File $CPIO_BASE_FILE must be extracted first using extract-cpio.sh script !"
exit 1
fi

mkdir -p $INITRD_DIR/dev
sudo mknod -m 0622 $INITRD_DIR/dev/console c 5 1

cp $CPIO_BASE_FILE $CPIO_FILE
cd $INITRD_DIR && find . | cpio -o -H newc --append -F $CPIO_FILE
cd -
gzip $CPIO_FILE
mkimage -n uInitrd -A arm64 -O linux -T ramdisk -C gzip -d $CPIO_FILE.gz $INITRD_FILE

================================================
FILE: scripts/uart-shell.sh
================================================
#!/bin/bash
DIR=$(dirname $(realpath $0))
UPDTOOL=$DIR/../bin/update

$UPDTOOL bulkcmd 'amlmmc env'
$UPDTOOL bulkcmd 'setenv initargs init=/sbin/pre-init'
$UPDTOOL bulkcmd 'setenv initargs ${initargs} ramoops.pstore_en=1'
$UPDTOOL bulkcmd 'setenv initargs ${initargs} ramoops.record_size=0x8000'
$UPDTOOL bulkcmd 'setenv initargs ${initargs} ramoops.console_size=0x4000'
$UPDTOOL bulkcmd 'setenv initargs ${initargs} rootfstype=ext4'
$UPDTOOL bulkcmd 'setenv initargs ${initargs} console=ttyS0,115200n8'
$UPDTOOL bulkcmd 'setenv initargs ${initargs} no_console_suspend'
$UPDTOOL bulkcmd 'setenv initargs ${initargs} earlycon=aml-uart,0xff803000'
$UPDTOOL bulkcmd 'env save'


================================================
FILE: scripts/uboot-continue.sh
================================================
#!/bin/sh
# Exit U-Boot 'USB Burning' mode and continue default boot
DIR=$(dirname $(realpath $0))
UPDTOOL=$DIR/../bin/update

$UPDTOOL bulkcmd 'mw.b 0x17f89754 1'


================================================
FILE: scripts/upload-kernel.sh
================================================
#!/bin/sh
# Upload & boot kernel/ramdisk when U-Boot is in 'USB Burning' mode
DIR=$(dirname $(realpath $0))
UPDTOOL=$DIR/../bin/update
KERNEL=$DIR/../images/superbird.kernel.img
KERNEL_ADDR=0x01080000
INITRD=$DIR/../images/superbird.initrd.img
INITRD_ADDR=0x13000000
ENV=$DIR/env.txt
ENV_ADDR=0x13000000
ENV_SIZE=`printf "0x%x" $(stat -c %s $ENV)`

$UPDTOOL bulkcmd "amlmmc env"
$UPDTOOL write $ENV $ENV_ADDR
$UPDTOOL bulkcmd "env import -t $ENV_ADDR $ENV_SIZE"
$UPDTOOL write $KERNEL $KERNEL_ADDR
$UPDTOOL write $INITRD $INITRD_ADDR
echo 'Booting...'
$UPDTOOL bulkcmd "booti $KERNEL_ADDR $INITRD_ADDR"
Download .txt
gitextract_hvi_s25o/

├── README.md
├── bin/
│   └── update
├── images/
│   ├── hacked_logo.img
│   ├── superbird.bootloader.img
│   ├── superbird.initrd-base.cpio
│   ├── superbird.initrd.img
│   └── superbird.kernel.img
├── initrd/
│   ├── S49usbgadget
│   └── init
└── scripts/
    ├── burn-mode.sh
    ├── disable-avb2.sh
    ├── dump.sh
    ├── enable-adb.sh.client
    ├── env.txt
    ├── extract-cpio.sh
    ├── hacked-bootlogo.sh
    ├── initrd.list
    ├── pack-initrd.sh
    ├── uart-shell.sh
    ├── uboot-continue.sh
    └── upload-kernel.sh
Condensed preview — 21 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (30K chars).
[
  {
    "path": "README.md",
    "chars": 11867,
    "preview": "# \"NotABug\" - [superbird-bulkcmd](https://github.com/frederic/superbird-bulkcmd)\n\n[Spotify Car Thing](https://carthing.s"
  },
  {
    "path": "initrd/S49usbgadget",
    "chars": 1292,
    "preview": "mkdir -p /dev/usb-ffs\nmkdir -p /dev/usb-ffs/adb\nmount -t configfs none /sys/kernel/config/\nmkdir -p /sys/kernel/config/u"
  },
  {
    "path": "initrd/init",
    "chars": 2219,
    "preview": "#!/bin/sh\n#Mount things needed by this script\n/bin/mount -t sysfs sysfs /sys\n/bin/mount -t devtmpfs devtmpfs /dev\n/bin/m"
  },
  {
    "path": "scripts/burn-mode.sh",
    "chars": 255,
    "preview": "#!/bin/sh\n# Boot U-Boot in 'USB Burning' mode\nDIR=$(dirname $(realpath $0))\nUPDTOOL=$DIR/../bin/update\n\n$UPDTOOL write $"
  },
  {
    "path": "scripts/disable-avb2.sh",
    "chars": 431,
    "preview": "#!/bin/sh\n# Disable AVB2 & dm-verity\n# Define system_b (/dev/mmcblk0p15) as root partition (change to /dev/mmcblk0p14 fo"
  },
  {
    "path": "scripts/dump.sh",
    "chars": 1330,
    "preview": "#!/bin/bash\nDIR=$(dirname \"$(realpath \"$0\")\")\nUPDTOOL=$DIR/../bin/update\n\nOUTPATH=\"$DIR/../dump\"\nmkdir -p \"$OUTPATH\"\n\n$U"
  },
  {
    "path": "scripts/enable-adb.sh.client",
    "chars": 2116,
    "preview": "# Note, you must run disable-avb2.sh first!\nmount -o remount,rw /\necho \"mkdir -p /dev/usb-ffs\">/etc/init.d/S49usbgadget\n"
  },
  {
    "path": "scripts/env.txt",
    "chars": 570,
    "preview": "bootargs=rdinit=/init init=/sbin/pre-init ramoops.pstore_en=1 ramoops.record_size=0x8000 ramoops.console_size=0x4000 roo"
  },
  {
    "path": "scripts/extract-cpio.sh",
    "chars": 433,
    "preview": "#!/bin/sh\n# Extract base files from /system partition required to build an initramdisk.\n\nDIR=$(dirname $(realpath $0))\nS"
  },
  {
    "path": "scripts/hacked-bootlogo.sh",
    "chars": 162,
    "preview": "#!/bin/bash\nDIR=$(dirname \"$(realpath \"$0\")\")\nUPDTOOL=$DIR/../bin/update\n\n$UPDTOOL bulkcmd \"amlmmc part 1\"\n$UPDTOOL part"
  },
  {
    "path": "scripts/initrd.list",
    "chars": 5485,
    "preview": ".\n./var\n./var/lib\n./var/lib/alsa\n./var/lib/misc\n./var/spool\n./var/cache\n./var/log\n./var/lock\n./var/run\n./var/tmp\n./var/w"
  },
  {
    "path": "scripts/pack-initrd.sh",
    "chars": 784,
    "preview": "#!/bin/sh\n# Pack the initrd image using base CPIO archive plus additional files from initrd/ directory\n# mkimage tool is"
  },
  {
    "path": "scripts/uart-shell.sh",
    "chars": 674,
    "preview": "#!/bin/bash\nDIR=$(dirname $(realpath $0))\nUPDTOOL=$DIR/../bin/update\n\n$UPDTOOL bulkcmd 'amlmmc env'\n$UPDTOOL bulkcmd 'se"
  },
  {
    "path": "scripts/uboot-continue.sh",
    "chars": 164,
    "preview": "#!/bin/sh\n# Exit U-Boot 'USB Burning' mode and continue default boot\nDIR=$(dirname $(realpath $0))\nUPDTOOL=$DIR/../bin/u"
  },
  {
    "path": "scripts/upload-kernel.sh",
    "chars": 603,
    "preview": "#!/bin/sh\n# Upload & boot kernel/ramdisk when U-Boot is in 'USB Burning' mode\nDIR=$(dirname $(realpath $0))\nUPDTOOL=$DIR"
  }
]

// ... and 6 more files (download for full content)

About this extraction

This page contains the full source code of the frederic/superbird-bulkcmd GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 21 files (13.2 MB), approximately 9.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!