nick.breen.kiwi

Nick Breen's Blog, that's all.

I re-discovered an ancient (2011) TF101 in a cupboard. It’s an NVIDIA Tegra 2 Android tablet with a physical keyboard dock.

It is long since EoL’d and its Android firmware is old enough to be unusable (at least due to ancient TLS/SSL support).

I had successfully used TWRP and flashed various other Android ROM’s some years ago. I thought it’d be a gas to revive it.

It has community support for postmarketOS though I failed to boot it, and as the guide says:

Make sure you backup your data before continuing. Note also that you won’t be able to boot Android back easily.

Indeed.

So, after failing to install postmarketOS and bricking it, restoring it to stock firmware was the name of the game. This is where a backup would have been useful: in particular the original partition table. Also, this device is old enough that almost every forum post’s or similar page’s links are long-stale and those that work have versions of wheelie and nvflash bundled with them old enough that they just don’t run anymore (think 32-bit ELF binaries built for Ubuntu 12.04).

Fortunately there are enough pages available to cobble together the tooling:

So, to business.

Deep inside the ASUS firmware ZIP inside another ZIP is a file called blob which is the entire firmware BLOB to flash to the device’s eMMC:

curl -JLO "https://dlcdnets.asus.com/pub/ASUS/EeePAD/TF101/WW_epaduser9_2_1_27UpdateLauncher.zip?model=Eee%20Pad%20Transformer%20TF101"
unzip WW_epaduser9_2_1_27UpdateLauncher.zip WW_epad-user-9.2.1.27.zip
unzip WW_epad-user-9.2.1.27.zip blob

Build blobunpack:

git clone https://github.com/AndroidRoot/BlobTools
cd BlobTools
cmake .
make
cp bin/blobunpack ~/.local/bin/
cd -

Use blobunpack to extract the individual partition BLOBs from blob:

blobunpack blob

We now have blobs that match partitions found in…

The stock flash.cfg partition table:

[device]
type=hsmmc
instance=3

[partition]
name=BCT
id=2
type=boot_config_table
allocation_policy=sequential
filesystem_type=basic
size=3145728
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0

[partition]
name=PT
id=3
type=partition_table
allocation_policy=sequential
filesystem_type=basic
size=4096
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0

[partition]
name=EBT
id=4
type=bootloader
allocation_policy=sequential
filesystem_type=basic
size=4194304
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0
filename=blob.EBT


[partition]
name=SOS
id=5
type=data
allocation_policy=sequential
filesystem_type=basic
size=12582912
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0
filename=blob.SOS

[partition]
name=LNX
id=6
type=data
allocation_policy=sequential
filesystem_type=basic
size=12582912
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0
filename=blob.LNX

[partition]
name=BAK
id=7
type=data
allocation_policy=sequential
filesystem_type=basic
size=12582912
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0

[partition]
name=GP1
id=8
type=GP1
allocation_policy=sequential
filesystem_type=basic
size=1048576
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0

[partition]
name=APP
id=9
type=data
allocation_policy=sequential
filesystem_type=basic
size=1073741824
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0
filename=blob.APP

[partition]
name=CAC
id=10
type=data
allocation_policy=sequential
filesystem_type=ext4
size=1073741824
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0

[partition]
name=MSC
id=11
type=data
allocation_policy=sequential
filesystem_type=ext4
size=5242880
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0

[partition]
name=USP
id=12
type=data
allocation_policy=sequential
filesystem_type=ext4
size=1073741824
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0


[partition]
name=PER
id=13
type=data
allocation_policy=sequential
filesystem_type=basic
size=12582912
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0

[partition]
name=YTU
id=14
type=data
allocation_policy=sequential
filesystem_type=basic
size=524288
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0

[partition]
name=UDA
id=15
type=data
allocation_policy=sequential
filesystem_type=ext4
size=18432
file_system_attribute=0
partition_attribute=0
allocation_attribute=0x808
percent_reserved=0

[partition]
name=GPT
id=16
type=GPT
allocation_policy=sequential
filesystem_type=basic
size=0xFFFFFFFFFFFFFFFF
file_system_attribute=0
partition_attribute=0
allocation_attribute=8
percent_reserved=0

That BCT has its own blob, transformer.bct found in the “bigwheelie” package referenced above is different to the one from the L4T archive (bootloader/ventana/BCT/ventana_A03_12MHz_EDB8132B1PB6DF_300Mhz_1GB_emmc_THGBM1G6D4EBAI4.bct. I used transformer.bct. They’re blobs so there’s little information to be gleamed from diff‘ing their hexdumps. NVIDIA provides a tool for generating these files, with the tantalising suggestion of a text-based format that can be compiled! But with nary a mention of the format nor an example. Apparently the source file is a Device Tree Source file: https://github.com/grate-driver/linux/blob/master/arch/arm/boot/dts/tegra20-asus-tf101.dts.

Build wheelie (or use the 0.1 version from the “bigwheelie” package.)

git clone https://github.com/AndroidRoot/wheelie
cd wheelie
cmake .
make
cp bin/wheelie ~/.local/bin/
cd -

From here we need the TF101 in APX mode plugged in via it’s proprietary USB cable. Reboot it into APX mode by holding down Volume Up and Power for a few seconds. The screen stay blank, there is no indication at all that the device is in APX mode. You can see the device with lsusb though:

Bus 003 Device 006: ID 0955:7820 NVIDIA Corp. T20 [Tegra 2] recovery mode

Interestingly in this mode it knows it is a Tegra 2 but not that it is a TF101. Compare to when it’s connected when booted to Android:

Bus 003 Device 018: ID 0b05:4e0f ASUSTek Computer, Inc. Transformer TF101

Use wheelie to do some magic with blob so that the device will accept it.

wheelie --blob blob

I’m reasonably sure that this implies the bootloader and BCT are already included in blob and wheelie 0.2 is able to extract them itself.

Or, for 0.1 bundled in “bigwheelie”:

./wheelie -2 --bl bootloader.bin --bct transformer.bct --odm `0x300d8011`

This particular TF101 is a SBK2 model, hence the -2. That ODM number is the T20/Ventana magic number; you can find them in L4T’s flash.sh.

Grab nvflash from L4T and stick it on the PATH.

Use nvflash to do some more magic to flash the individual partition BLOBs to their matching eMMC partitions.

nvflash -r --bct transformer.bct --setbct --configfile flash.cfg --create --odmdata 0x300d8011 --sync

It requires the blob.* files in the same directory, or update the filename paths in flash.cfg.

Wait for ages

Ask it to continue booting normally:

nvflash -r --go