bishopdynamics / superbird-tool

Cross-Platform Spotify Car Thing (superbird) hacking toolkit
133 stars 8 forks source link

A few ideas on optimising the dump/restore processes and enabling ADB #13

Open fonix232 opened 7 months ago

fonix232 commented 7 months ago

After going through the code, and the dump/restore/ADB process a handful of times, I've gathered a few ideas on optimising the processes:

1. Device Dumping

While it is great to have full partition dumps, due to the speed limit imposed by the lack of mread in pyamlboot, it's not the best way forward to dump both A/B partitions and userdata as well.

My proposal to fix this is to make the dumping logic a bit smarter:

  1. First step should be dumping env and parsing it to TXT
  2. Then dumping other non-A/B partitions (bootloader, logo, misc, settings)
  3. Reading out the active slot from env
  4. Dumping boot/dtbo/fip/system/vbmeta of the selected slot
  5. Ignoring data partition (it is unnecessary for a working dump

This altogether would reduce dump sizes by:

Making the dumping process from 4GB to ~863MB, while also reducing the dumping time from nearly two hours (or in my case, since on macOS the maximum bandwidth seems to be around 94kBps, from around 12 hours!) to around 30 minutes (or, in my case, "only" 3 hours).

Therefore, a future dump would look like this:

firmware_dump/
├─ boot.dump
├─ bootloader.dump
├─ dtbo.dump
├─ env.dump (and/or  env.txt)
├─ fip.dump
├─ logo.dump
├─ misc.dump
├─ vbmeta.dump
├─ system.ext2 (or system.dump)
├─ settings.ext4 (or settings.dump)

This also reduces duplicate/unnecessary data, as well as personally identifying stuff (I've seen a few people in the community share their dumps with a full data partition dump, containing their phone MAC addresses, etc.).

2. Device restoration

Similarly to the above approach, restoration could be optimised by not restoring all partitions, instead:

  1. Taking the input dump (and using the old method if an old style dump is found)
  2. Reading out the active slot from env
  3. Writing non-A/B partitions (incl. env)
  4. Writing the A/B partition dumps into the right slot
  5. Writing zeroed out data to the inactive slot ( + optionally data, if the user chooses a "wipe" option - or possibly just wiping data's partition headers)

As by the looks of it, Android's A/B tooling is used, the handling of the inactive slot partitions is automatic - upon receiving an update, if an invalid/faulty partition (in our case, zeroed out) is detected, the current slot's appropriate partition is copied over before the OTA delta patch is applied. This means that zeroing out these partitions is perfectly fine.

This would similarly reduce the time needed to restore a device (especially since the nulling can be done by writing zeros to the memory once, then issuing the copy command from the same memory region again and again, speeding up things) as number 1 above.

3. ADB process

This is where you'll hate me. The current ADB process uses a prebuilt boot.img with ADB enabled. This poses a number of compatibility issues, as Spotify, to date, is issuing firmware updates to the CarThing, often patching the kernel/initrd, which can sometimes cause boot issues.

Therefore I'd like to propose a more dynamic approach to enabling ADB, by integrating mkbootimg and possibly abootimg into the process. Instead of booting a prepared boot.img, the ADB option should:

  1. Pull env and get current boot slot
  2. Pull boot_{activeSlot} and save locally
  3. Unpack the newly pulled boot.img
  4. Apply ADB enabling patch (and anything else if needed)
  5. Build patched boot.img
  6. Push that to the device (either write to eMMC or boot directly, dealer's choice)