sycamore: cleanup

This commit is contained in:
Nicholas Andrew 2026-09-11 06:18:44 -04:00
commit aa2db917a4
6 changed files with 184 additions and 320 deletions

16
.gitignore vendored Normal file
View file

@ -0,0 +1,16 @@
# Local development / bring-up backups
*.before-*
*.bak
*.orig
*.old
*.rej
*.tmp
*.swp
*~
# Editor / desktop junk
.DS_Store
Thumbs.db
# Local scratch files
tab

View file

@ -94,9 +94,9 @@ TW_HAS_NO_RECOVERY_PARTITION := true
BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE := true
BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true
BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT := true
# Optional A-Team dual-boot layout.
# Default: metadata / userdata
# DUALBOOT=Y: metadata2 / userdata2
# Optional A-Team slotted dual-boot layout.
# Default: metadata / userdata without slot selection.
# DUALBOOT=Y: metadata / userdata use slotselect via recovery-dualboot.fstab.
ifeq ($(strip $(DUALBOOT)),Y)
TARGET_RECOVERY_FSTAB := $(DEVICE_PATH)/recovery-dualboot.fstab
else
@ -110,6 +110,33 @@ endif
# - present the exact production XT2575-4 vendor identity before Microtrust starts
BOARD_RECOVERY_IMAGE_PREPARE = test -n "$(TARGET_RECOVERY_ROOT_OUT)" && \
rm -rf -- "$(TARGET_RECOVERY_ROOT_OUT)/lib/modules" && \
if [ "$(strip $(NODECRYPT))" = "Y" ]; then \
rm -f -- \
"$(TARGET_RECOVERY_ROOT_OUT)/init.recovery.crypto.rc" \
"$(TARGET_RECOVERY_ROOT_OUT)/system/bin/sycamore_keystore2_stage.sh" \
"$(TARGET_RECOVERY_ROOT_OUT)/system/etc/init/zz_sycamore_keystore2.rc" \
"$(TARGET_RECOVERY_ROOT_OUT)/system/etc/vintf/manifest.xml" \
"$(TARGET_RECOVERY_ROOT_OUT)/system/etc/vintf/manifest/android.system.keystore2-service.xml" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/manifest.xml" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/etc/vintf/manifest/android.hardware.security.keymint-service.beanpod.xml" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/etc/vintf/manifest/android.hardware.security.secureclock-service.beanpod.xml" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/etc/vintf/manifest/android.hardware.security.sharedsecret-service.beanpod.xml" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/etc/vintf/manifest/android.hardware.gatekeeper@1.0-service.xml" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/bin/hw/android.hardware.security.keymint@2.0-service.beanpod" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/bin/hw/android.hardware.gatekeeper@1.0-service" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/bin/teei_daemon" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/lib64/hw/android.hardware.gatekeeper@1.0-impl.so" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/lib64/hw/gatekeeper.beanpod.so" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/lib64/hw/libSoftGatekeeper.so" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/lib64/android.hardware.security.keymint-V2-ndk.so" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/lib64/android.hardware.gatekeeper@1.0.so" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/lib64/libteei_daemon_vfs.so" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/lib64/lib_android_keymaster_keymint_utils.so" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/lib64/libkeymaster_messages.so" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/lib64/libkeymaster_portable.so" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/lib64/libkeymint.so" \
"$(TARGET_RECOVERY_ROOT_OUT)/vendor/lib64/libpuresoftkeymasterdevice.so"; \
fi && \
sed -i \
-e 's/^ro.product.vendor.device=sycamore_row_5G$$/ro.product.vendor.device=XT2575-4/' \
-e 's/^ro.product.vendor.name=twrp_sycamore_row_5G$$/ro.product.vendor.name=XT2575-4/' \
@ -150,12 +177,14 @@ TW_USB_STORAGE := false
TW_EXCLUDE_APEX := true
# Stock FBE v2 with metadata encryption.
ifneq ($(strip $(NODECRYPT)),Y)
TW_INCLUDE_CRYPTO := true
TW_INCLUDE_CRYPTO_FBE := true
TW_INCLUDE_FBE_METADATA_DECRYPT := true
endif
BOARD_USES_METADATA_PARTITION := true
# Bring-up/debug essentials; no missing-dependency escape hatch.
# Recovery utilities and diagnostics.
TARGET_USES_LOGD := true
TWRP_INCLUDE_LOGCAT := true
TW_INCLUDE_REPACKTOOLS := true

204
README.md
View file

@ -1,83 +1,149 @@
Device configuration for Motorola Moto Pad 2026 (codenamed "sycamore_row_5G")
=========================================
# TWRP for Motorola Moto Pad 2026
The Motorola Moto Pad 2026 / XT2575-4 (codenamed _"sycamore_row_5G"_) is an Android tablet from Motorola Mobility based on the MediaTek MT8755 platform.
Device tree for building Team Win Recovery Project for the Motorola Moto Pad 2026 / XT2575-4, codenamed `sycamore_row_5G`.
This device tree is intended for building Team Win Recovery Project (TWRP).
The device uses the MediaTek MT8755 SoC on the MT6835 Android platform and stores recovery in a version 4 `vendor_boot` image.
## Device specifications
Basic | Spec Sheet
-------:|:-------------------------
Model | Motorola XT2575-4
Codename | sycamore_row_5G
SoC | MediaTek MT8755 (MT6835 platform)
CPU | 64-bit ARM, Cortex-A76 / Cortex-A55
GPU | ARM Mali
Shipped Android Version | Android 15
Tested Stock Firmware | Android 16 / ZUI 17.5
Storage | UFS
Display | 2560 x 1600 pixels, 90 Hz
Partition Scheme | A/B, Virtual A/B, Dynamic Partitions
Encryption | File-Based Encryption (FBE v2) with metadata encryption
Filesystem | F2FS userdata, EROFS/EXT4 dynamic partitions
Recovery Layout | TWRP recovery ramdisk stored in `vendor_boot`
Vendor Boot Header | Version 4
| Component | Specification |
|---|---|
| Model | Motorola XT2575-4 |
| Codename | `sycamore_row_5G` |
| SoC | MediaTek MT8755 |
| Android platform | MT6835 |
| Architecture | ARM64 |
| CPU | Cortex-A76 / Cortex-A55 |
| GPU | ARM Mali |
| Shipping Android version | Android 15 |
| Tested firmware | Android 16 / ZUI 17.5 |
| Storage | UFS |
| Display | 2560 x 1600, 90 Hz |
| Partition scheme | A/B, Virtual A/B, dynamic partitions |
| Userdata | F2FS |
| Dynamic partitions | EROFS / EXT4 |
| Encryption | FBE v2 with metadata encryption |
| Recovery location | `vendor_boot` |
| Vendor boot header | Version 4 |
## Device picture
## Working
![Motorola Moto Pad (2026)](https://fdn2.gsmarena.com/vv/bigpic/motorola-moto-pad-2026-.jpg)
- Display and touch
- ADB
- Dynamic partitions
- A/B slot handling
- Fastbootd
- EROFS, F2FS and EXT4
- exFAT and NTFS removable-storage support
- External SD card
- Stock PLATFORM vendor ramdisk preservation
- TWRP RECOVERY vendor ramdisk fragment
- Android 16 FBE v2 decryption
- Metadata encryption
- PIN/password protected userdata decryption
- Decrypted `/data/media`
- MediaTek / Microtrust TEE
- KeyMint
- Gatekeeper
- Keystore2
- SELinux enforcing
- MTP
- Vibration
- Thermal sensor support
## Validation remaining
A final hardware-validation pass should cover:
- Backup and restore using internal storage
- Backup and restore using removable storage
- ADB sideload
- ZIP flashing
- Image flashing from the TWRP UI
- Wipe and format operations
- Partition mount and backup lists
- USB-OTG devices
- Battery reporting
- Brightness control
- Date and time handling
- Screenshots
- Power-off and all reboot targets
- Advanced recovery functions
## Building
Place this tree at:
```text
device/motorola/sycamore_row_5G
```
Build with:
```bash
source build/envsetup.sh
lunch twrp_sycamore_row_5G-eng
m vendorbootimage -j$(nproc)
```
Output:
```text
out/target/product/sycamore_row_5G/vendor_boot.img
```
`ALLOW_MISSING_DEPENDENCIES` is not required by this tree.
## Dual-boot variant
The normal build uses the standard `metadata` and `userdata` partitions.
The optional A-Team dual-boot configuration keeps the canonical `metadata` and `userdata` block names, but enables `slotselect` for `/metadata` and `/data` and uses the matching dual-boot PLATFORM vendor ramdisk:
```bash
export DUALBOOT=Y
source build/envsetup.sh
lunch twrp_sycamore_row_5G-eng
m vendorbootimage -j$(nproc)
```
Only use the dual-boot image on a device configured for the corresponding slotted dual-boot layout.
## NODECRYPT development variant
A recovery build without the device-specific crypto stack can be produced with:
```bash
export NODECRYPT=Y
source build/envsetup.sh
lunch twrp_sycamore_row_5G-eng
m vendorbootimage -j$(nproc)
```
`NODECRYPT=Y` is intended for bring-up and troubleshooting. It omits the KeyMint, Gatekeeper, Keystore2 and Microtrust components required for normal userdata decryption.
When switching between normal, `DUALBOOT=Y`, and `NODECRYPT=Y` configurations, clean the product output first to prevent artifacts from another configuration being reused.
## Implementation notes
Recovery is stored in `vendor_boot` using the Android vendor boot header version 4 layout.
The stock PLATFORM vendor ramdisk is preserved rather than reconstructed. TWRP is supplied as the RECOVERY vendor ramdisk fragment.
This preserves the production MediaTek module layout and early-boot environment while allowing TWRP to provide the recovery userspace.
The tree also contains the device-specific components required for Android 16 FBE decryption through the MediaTek / Microtrust trusted execution environment.
## Device reference
[Motorola Moto Pad (2026) - GSMArena](https://www.gsmarena.com/motorola_moto_pad_(2026)-14582.php)
# Status
## Credits
Current state of features:
- Team Win Recovery Project
- Motorola / Lenovo
- MediaTek
- A-Team Digital Solutions
- BOBtheBlinker
- Correct screen/recovery size
- Working touch and display
- ADB
- Support EROFS/F2FS/EXT4/exFAT/NTFS
- External SD card support
- Dynamic partition support
- A/B slot handling
- `vendor_boot` v4 support
- Stock PLATFORM vendor ramdisk preserved
- TWRP RECOVERY vendor ramdisk fragment
- Decrypt `/data` with user PIN/password
- Decrypted `/data/media`
- Metadata encryption
- KeyMint service
- Gatekeeper service
- Keystore2 service
- MediaTek/Microtrust TEE
- MTP export
- SELinux enforcing
- Vibrate and set vibration
Still to validate before final release:
- Backup/restore to/from internal/external storage and ADB
- ADB sideload
- Poweroff and all reboot targets
- Flashing zip/images from the TWRP UI
- All important partitions listed in wipe/mount/backup lists
- Input devices via USB-OTG
- Correct date/time configuration
- Battery level reporting
- Brightness adjustment
- Screenshot
- Advanced recovery features
# Building
```bash
export ALLOW_MISSING_DEPENDENCIES=true
source build/envsetup.sh
lunch twrp_sycamore_row_5G-eng
mka vendorbootimage -j$(nproc --all)
```
**Copyright (C) 2026 BOBtheBlinker | A-Team Digital Solutions**
Copyright (C) 2026 BOBtheBlinker / A-Team Digital Solutions

View file

@ -1,112 +0,0 @@
# Sycamore stock-vs-TWRP vendor_boot fragment audit
Date: 2026-08-27
## Inputs
- Factory: `/home/nicholas/Downloads/sycamore-twrp-info/vendor_boot_a.img`
- SHA-256: `e542af82e8bb153faa96a44ec480548b21ac99abf7ca26ffca0eafcc9b6a9fe`
- Hardware-tested V14: `/home/nicholas/Downloads/sycamore-twrp-info/first-hardware-boot/fbe-a16-v14-wrapped-first/vendor_boot.img`
- SHA-256: `d657365e5c14ba0bc1e93e9fc0ec38acb18f935e222d1bae66377011b96b9d15`
- Current untested output: `out/target/product/sycamore_row_5G/vendor_boot.img`
- SHA-256: `eb3388b6da20ce487976e40ff1a30ca8ee488680f01aeaaedb483e0aed555d18`
All images are exactly 67,108,864 bytes.
## Common header and retained sections
The local AOSP `unpack_bootimg.py` reports these identical values for all three:
- magic: `VNDRBOOT`
- header version: 4
- header size: 2,128
- page size: 4,096
- kernel load address: `0x40000000`
- ramdisk load address: `0x66f00000`
- tags load address: `0x47c80000`
- DTB load address: `0x47c80000`
- vendor cmdline: `bootopt=64S3,32N2,64N2`
- product name: empty
- bootconfig: empty (0 bytes; SHA-256 of empty content
`e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`)
- DTB: 192,119 bytes; SHA-256
`0e93b71aacf707a5fbb7a58eff73995b92d766a31a98d8d70e91f548c9e1d5af`
## Factory fragment table
| Index | Name | Type | Table offset | Image offset | Compressed size | Compression | board_id |
|---:|---|---|---:|---:|---:|---|---|
| 0 | empty | PLATFORM (1) | 0 | 4,096 | 27,422,144 | LZ4 legacy | 16 zero words |
Compressed payload SHA-256:
`06738f638a745075511c571347c5511331dda16b84d1ee88cda160c2dc7ebb14`
Uncompressed CPIO: 67,875,584 bytes; SHA-256
`cdf1d9fd1658989a4c198ca889802660f3a2d52a8fc527e40013c35da917642c`
Factory total vendor ramdisk size is 27,422,144 bytes. Its table is 108 bytes
with one entry. There is no RECOVERY entry and no DLKM entry.
## Hardware-tested V14 fragment table
| Index | Name | Type | Table offset | Image offset | Compressed size | Compression | board_id | Compressed SHA-256 | Uncompressed size | Uncompressed SHA-256 |
|---:|---|---|---:|---:|---:|---|---|---|---:|---|
| 0 | empty | PLATFORM (1) | 0 | 4,096 | 27,422,144 | LZ4 legacy | 16 zero words | `06738f638a745075511c571347c5511331dda16b84d1ee88cda160c2dc7ebb14` | 67,875,584 | `cdf1d9fd1658989a4c198ca889802660f3a2d52a8fc527e40013c35da917642c` |
| 1 | `recovery` | RECOVERY (2) | 27,422,144 | 27,426,240 | 31,391,394 | LZ4 legacy | 16 zero words | `ae0c2ab5adba18a2a5bdaa79760b4d8aa474bd2de9f82ba25a1a343e6d810467` | 69,037,312 | `9c3945cd24333659f8aea5bc78a01bd5d9c4762603ad4a943be4cb62a874d01f` |
Total vendor ramdisk size is 58,813,538 bytes. Its table is 216 bytes with
two entries, ordered PLATFORM then RECOVERY.
## Current output fragment table
| Index | Name | Type | Table offset | Image offset | Compressed size | Compression | board_id | Compressed SHA-256 | Uncompressed size | Uncompressed SHA-256 |
|---:|---|---|---:|---:|---:|---|---|---|---:|---|
| 0 | empty | PLATFORM (1) | 0 | 4,096 | 27,422,144 | LZ4 legacy | 16 zero words | `06738f638a745075511c571347c5511331dda16b84d1ee88cda160c2dc7ebb14` | 67,875,584 | `cdf1d9fd1658989a4c198ca889802660f3a2d52a8fc527e40013c35da917642c` |
| 1 | `recovery` | RECOVERY (2) | 27,422,144 | 27,426,240 | 31,677,990 | LZ4 legacy | 16 zero words | `b4e9de040d9d1c4e78a4fa8ab056a6bb7a42fafff6f99303f08fb43c54aa76ca` | 69,607,424 | `a1401628c4ca65d2fe1ab267e049d40c5e3a0c4d91187ad44d14b46808d2c001` |
Total vendor ramdisk size is 59,100,134 bytes. Its table is 216 bytes with
two entries, ordered PLATFORM then RECOVERY.
## Differential conclusion
- **A. Stock multi-fragment:** NO. It has a valid v4 table but only one entry.
- **B. Stock PLATFORM:** entry 0, unnamed, type 1.
- **C. Stock RECOVERY:** none. Stock recovery content is contained in PLATFORM.
- **D. Stock PLATFORM preserved by TWRP:** YES, byte-for-byte in both V14 and
current output, for both compressed and uncompressed payloads.
- **E. Stock non-recovery fragment regenerated/replaced:** NO. PLATFORM is the
only stock fragment and is exact. Stock has no DLKM or other fragment.
The hybrid principle is already implemented by
`tools/assemble_vendor_boot.sh`: the exact stock PLATFORM archive is entry 0 and
the generated TWRP ramdisk is appended as entry 1/RECOVERY. A new “hybrid” build
would not change this variable. PLATFORM preservation is therefore **PROVEN**
and is not a remaining explanation for the V14 cmd `0x18` failure.
The required aggregate/table changes are limited to total ramdisk size, table
size/count, downstream aligned section positions, and the AVB hash/footer.
V14 and current output retain the stock DTB, cmdline, bootconfig, core header
values, fragment-0 metadata, and fragment-0 bytes.
## Dynamic-partition corroboration
Read-only live recovery inspection showed liblp/TWRP preparing logical
partitions from `super` and mapping:
- `odm_dlkm_a` -> `dm-0`
- `product_a` -> `dm-1`
- `system_a` -> `dm-2`
- `system_b` -> `dm-3`
- `system_dlkm_a` -> `dm-4`
- `system_ext_a` -> `dm-5`
- `vendor_a` -> `dm-6`
- `vendor_dlkm_a` -> `dm-7`
The active-slot convenience links resolve `system`, `system_ext`, `product`,
`vendor`, `vendor_dlkm`, `odm_dlkm`, and `system_dlkm` to those mapper nodes.
Any resulting `/dev/block/by-name/<logical>` links are runtime-created links to
`dm-*`, not physical GPT partitions. The existing `recovery.fstab` correctly
uses `logical,first_stage_mount`; no invented physical by-name paths are needed.
No image was built, flashed, booted, or otherwise written to hardware during
this audit.

View file

@ -1,139 +0,0 @@
# Sycamore vendor_boot module-list pathname collision
## Architecture
Sycamore uses vendor_boot header v4. The device-specific assembler preserves the
factory Android 16 PLATFORM fragment byte-for-byte as table entry 0, then appends the
generated TWRP ramdisk as entry 1, type RECOVERY, named `recovery`. Both fragments use
legacy LZ4. PLATFORM contains the stock recovery/module infrastructure: all 203 `.ko`
files and `modules.alias`, `modules.dep`, `modules.load`, `modules.load.recovery`, and
`modules.softdep` under `/lib/modules`.
The early device tree copied the five metadata files into TWRP's recovery root as
well. Consequently the RECOVERY archive contained duplicate canonical paths, despite
containing no `.ko` payloads. Because RECOVERY follows PLATFORM, a boot chain that
extracts both archives presents the later copy at those paths.
## Isolation methodology and hardware evidence
Compressed size, expanded size, compression ratio, payload data, entry count, and
general CPIO structure were separately controlled. A deterministic pathname-only
bisection retained neutral file payloads while restoring original V20.5 paths in
archive order.
- `RESTORE-PREFIX-0029`: normal Android boot PASS
- `RESTORE-PREFIX-0030`: normal Android boot FAIL
Those images differ only by restoring entry 30 to
`lib/modules/modules.dep`. Replacing its neutral 25,966-byte payload with the exact
stock dependency database produced `MODULES-DEP-STOCKPAYLOAD-CONTROL`, which PASSed.
This verifies that the canonical RECOVERY path reaches the normal first-stage module
consumer and that a valid payload removes the synthetic control failure.
The real V20.5 PLATFORM and RECOVERY `modules.dep` are identical, so that file was
not the real-image cause. The actual differing metadata was `modules.load`:
- stock normal: 179 entries, 3,020 bytes, SHA-256
`1e9fe08beeb555147fbb39483f5fb4126046427bfa5432aa049cc4efa30b2f05`
- V20.5 RECOVERY: 199 entries, 3,351 bytes, SHA-256
`1b61df29e9b0f9aef57fd5d7503779903f24fcf2a962d4f19bed166ae8b85d2b`
The recovery list adds 24 modules and omits four relative to stock normal. Starting
from exact real V20.5 and replacing only the RECOVERY `modules.load` payload with the
stock normal payload produced `REAL-V20.5-STOCK-NORMAL-MODULES-LOAD`; normal Android
boot PASSed.
## Conclusions
**VERIFIED:** the differing RECOVERY `/lib/modules/modules.load` is sufficient to
cause real V20.5 normal-Android boot failure.
**STRONG INFERENCE:** the later RECOVERY pathname shadows PLATFORM before normal
first-stage `libmodprobe` consumes `/lib/modules/modules.load`.
**UNKNOWN:** the exact proprietary LK/vendor-ramdisk fragment selection or extraction
implementation that exposes a type-2 RECOVERY path during normal boot.
## Implementation rationale
The device assembler filters `lib/modules/**` only from the generated RECOVERY
archive. It does not modify the checked-out recovery staging tree, kernel modules,
generic TWRP/AOSP code, or the pristine PLATFORM fragment. PLATFORM remains the
single authoritative provider for both normal and recovery module metadata and all
203 module payloads.
Hardcoding a second stock-normal `modules.load` in RECOVERY would repair the observed
collision but preserve unnecessary duplicate metadata and invite future drift.
Removing the duplicate RECOVERY tree instead preserves the factory pairing of module
payloads and metadata, including `modules.load.recovery` for recovery first stage.
The canonical AOSP `m vendorbootimage` path does not invoke the standalone
`tools/assemble_vendor_boot.sh`. `BoardConfig.mk` therefore sets
`BOARD_RECOVERY_IMAGE_PREPARE` to remove the staged RECOVERY `lib/modules` directory
after device-root population and before `mkbootfs`. The standalone assembler applies
the same filter to its temporary archive root. Source prebuilts remain available for
forensics, while both assembly paths emit the same no-duplicate architecture.
## Recovery runtime confirmation
The hardware-validated `V20.5-NO-RECOVERY-LIB-MODULES` image booted TWRP. In that
running recovery, all five `/lib/modules` metadata hashes exactly matched pristine
PLATFORM:
```text
modules.alias 47aa8d900c4bfe1a94f3fee6f405b5d674e33b806ac0fdbf02d17dc283f4ef55
modules.dep 190915e985dc55ac4177914f17f5691eb486f0ae4891eca92b9cc8ee5f004fc4
modules.load 1e9fe08beeb555147fbb39483f5fb4126046427bfa5432aa049cc4efa30b2f05
modules.load.recovery f7a08319941624be65fcd12e7682b244dcdc7df079a7bf448415768e2641949e
modules.softdep 68b8d79bf7bdf36216f722f07ebc265fed0741025b376e3899b568dd31ecf641
```
**VERIFIED:** with RECOVERY `lib/modules/**` absent, recovery receives the pristine
PLATFORM metadata; PLATFORM `modules.load.recovery` is visible in running TWRP; and
the PLATFORM module tree successfully serves both normal Android and recovery.
## Canonical build integration
The canonical `m vendorbootimage -j8` path was traced through
`build/make/core/Makefile`: device recovery files are copied into
`TARGET_RECOVERY_ROOT_OUT`, `BOARD_RECOVERY_IMAGE_PREPARE` runs, then `mkbootfs` and
legacy LZ4 create the RECOVERY fragment. The standard vendor_boot rule combines it
with `BOARD_PREBUILT_VENDOR_RAMDISK` and the DTB before adding AVB.
The successful canonical build emitted no RECOVERY `lib/modules/**` paths and retained
the exact PLATFORM and DTB hashes. Its artifact SHA-256 is
`7aa012d093e53922cd97100d083f0ae5fc34ecbcbe5bdef4f84c67d11843d7d0`.
## Final canonical hardware validation — CLOSED
The canonical artifact booted both targets successfully:
- normal Android: PASS; `sys.boot_completed=1`
- TWRP: PASS; ADB recovery, GUI/touch and storage functional
- effective `modules.load.recovery`: 197 lines
- `/proc/modules`: populated
- no `Failed to load kernel modules`
- no `Module .* not in dependency file`
Runtime hashes of all five effective metadata files again exactly matched pristine
PLATFORM.
Final classification:
- **VERIFIED:** duplicate RECOVERY module metadata affected normal first-stage boot;
the differing RECOVERY `modules.load` was sufficient to cause V20.5's failure;
removing RECOVERY `lib/modules/**` restores normal boot; the canonical
`m vendorbootimage` integration works on hardware; recovery receives pristine
PLATFORM metadata and loads modules successfully; both Android and TWRP boot.
- **STRONG INFERENCE:** proprietary boot handling overlays or shadows later RECOVERY
paths over PLATFORM before first-stage `libmodprobe` consumes them.
- **UNKNOWN:** the exact proprietary LK implementation.
**Investigation status: CLOSED.** Do not alter this implementation without new
contradictory evidence.
Persistent detailed evidence:
- `/home/nicholas/Downloads/sycamore-twrp-info/MODULES_DEP_NORMAL_BOOT_ANALYSIS.md`
- `/home/nicholas/Downloads/sycamore-twrp-info/MODULES_LOAD_NORMAL_BOOT_ANALYSIS.md`
- `/home/nicholas/Downloads/sycamore-twrp-info/normal-boot-name-controls/`

View file

@ -61,6 +61,7 @@ PRODUCT_COPY_FILES += \
$(DEVICE_PATH)/recovery/root/vendor/etc/vintf/manifest/android.hardware.security.sharedsecret-service.beanpod.xml:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/etc/vintf/manifest/android.hardware.security.sharedsecret-service.beanpod.xml \
$(DEVICE_PATH)/recovery/root/vendor/etc/vintf/manifest/android.hardware.gatekeeper@1.0-service.xml:$(TARGET_COPY_OUT_RECOVERY)/root/vendor/etc/vintf/manifest/android.hardware.gatekeeper@1.0-service.xml
ifneq ($(strip $(NODECRYPT)),Y)
PRODUCT_PACKAGES += \
sycamore_gatekeeper_impl \
sycamore_gatekeeper_hidl \
@ -82,7 +83,8 @@ PRODUCT_PACKAGES += \
sycamore_tee_common \
sycamore_tee_imsg_log \
sycamore_tee_vfs \
sycamore_teei_daemon \
sycamore_teei_daemon
endif
PRODUCT_VENDOR_PROPERTIES += \
ro.vendor.mtk_ufs_support=1 \
@ -99,8 +101,10 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/recovery/root/system/etc/init/zz_sycamore_hwservicemanager.rc:$(TARGET_COPY_OUT_RECOVERY)/root/system/etc/init/zz_sycamore_hwservicemanager.rc
# Device-side Keystore2 database staging for Android 16 FBE.
ifneq ($(strip $(NODECRYPT)),Y)
PRODUCT_COPY_FILES += \
$(DEVICE_PATH)/recovery/root/system/bin/sycamore_keystore2_stage.sh:$(TARGET_COPY_OUT_RECOVERY)/root/system/bin/sycamore_keystore2_stage.sh
endif
# Stock MT8755 generic ADC thermal provider.
# Recovery needs this for charger/flash/wifi/USB/board NTC thermal zones;