S905X processor (secured boot) software security overview

This article will discuss software protection on the S905X processor. The ultimate goal is to launch unauthorized software.

S905X


The S905X processor is an ARM Cortex-A53 with a clock frequency of up to 1.5 GHz, stuffed with all kinds of decoders for video and audio streams, such as H.265 4K, VP9, ​​supporting 4KUHD, etc. In general, not a bad choice. Unlike its predecessor, AMLogic integrated the so-called “Advanced TrustZone security system” into this processor, which controls all critical system operations, such as accessing protected areas of ROM memory, checking the signature and decrypting software, etc. Detailed documentation on this topic can be found on the manufacturer's website . SecureOS acts as ATOS-V1.5-g3e467d9 (I will not assert, I did not check).

Training


Having disassembled the prefix, I easily found the RxD, TxD and GND pins for UART. On the reverse side there was a connector for the reset button (not verified) and a place for the connector. Judging by the location, the connector looked like a board-to-board for an alternative eMMS card (pinout is naturally absent).



Free-access documentation for the S905 such critical topics as, for example, the boot sequence didn’t touch on much or less and was practically useless from the point of view of RE. Putting the documentation aside, I connected UART and ... was pleasantly surprised by the processor loading speed. But that’s probably all. U-Boot didn’t react at all to the keyboard and, after some hardware settings, smartly loaded and launched the Android kernel.

U-Boot'a boot log
 GXL:BL1:9ac50e:bb16dc;FEAT:BDFC31BC:0;POC:3;RCY:0;EMMC:0;READ:0;0.0;0.0;CHK:0;
TE: 351954

BL2 Built : 16:42:36, Nov  3 2016. 
gxl g3eddb43 - xiaobo.gu@droid05

set vcck to 1120 mv
set vddee to 1000 mv
Board ID = 4
CPU clk: 1200MHz
DQS-corr enabled
DDR scramble enabled
DDR3 chl: Rank0+1 @ 768MHz - FAIL
DDR3 chl: Rank0 @ 768MHz - PASS
Rank0: 1024MB(auto)-2T-11
DataBus test pass!
AddrBus test pass!
-s
Load fip header from eMMC, src: 0x0000c200, des: 0x01400000, size: 0x00004000
aml log : R2048 check pass!
New fip structure!
Load bl30 from eMMC, src: 0x00010200, des: 0x01700000, size: 0x0000d600
aml log : R2048 check pass!
Load bl31 from eMMC, src: 0x00020200, des: 0x01700000, size: 0x00015400
aml log : R2048 check pass!
Load bl32 from eMMC, src: 0x00038200, des: 0x01700000, size: 0x00035a00
aml log : R2048 check pass!
Load bl33 from eMMC, src: 0x00070200, des: 0x01700000, size: 0x000aa200
aml log : R2048 check pass!
NOTICE:  BL3-1: v1.0(debug):fb68908
NOTICE:  BL3-1: Built : 18:30:11, Nov  1 2016
aml log : bl31 detect secure boot !
[Image: gxl_v1.1.3154-065f772 2016-09-29 14:08:54 yan.wang@droid05]

OPS=0x84

bc fc af 5f a2 b4 4d 4b 1c 91 59 9f [1.280536 Inits done]

secure task start!
high task start!
low task start!
INFO:    BL3-1: Initializing runtime services
INFO:    BL3-1: Initializing BL3-2
INFO:    BL3-2: ATOS-V1.5-g3e467d9 #1 Mon Aug 22 17:11:43 CST 2016 arm
INFO:    BL3-2: chip version = RevC (21:C - 0:0)
INFO:    BL3-2: crypto engine DMA
INFO:    BL3-2: secure time TEE
INFO:    BL3-1: Preparing for EL3 exit to normal world
INFO:    BL3-1: Next image address = 0x1000000
INFO:    BL3-1: Next image spsr = 0x3c9


U-Boot 2015.01 (Nov 23 2018 - 15:50:35)

DRAM:  1 GiB
Relocation Offset is: 36ec8000
register usb cfg[0][1] = 0000000037f5e258
[CANVAS]canvas init
vpu: error: vpu: check dts: FDT_ERR_BADMAGIC, load default parameters
vpu: clk_level = 7
vpu: set clk: 666667000Hz, readback: 666660000Hz(0x300)
vpp: vpp_init
boot_device_flag : 1
Nand PHY Ver:1.01.001.0006 (c) 2013 Amlogic Inc.
init bus_cycle=6, bus_timing=7, system=5.0ns
reset failed
get_chip_type and ret:fffffffe
get_chip_type and ret:fffffffe
chip detect failed and ret:fffffffe
nandphy_init failed and ret=0xfffffff1
MMC:   aml_priv->desc_buf = 0x0000000033ec86b0
aml_priv->desc_buf = 0x0000000033eca9d0
SDIO Port B: 0, SDIO Port C: 1
emmc/sd response timeout, cmd8, status=0x1ff2800
emmc/sd response timeout, cmd55, status=0x1ff2800
[mmc_startup] mmc refix success
[mmc_init] mmc init success
mmc read lba=0x14000, blocks=0x400
      Amlogic multi-dtb tool
      Multi dtb detected
      Multi dtb tool version: v2 .
      Support 2 dtbs.
        aml_dt soc: gxl platform: sx6b6x variant: 1g
        dtb 0 soc: gxl   plat: sx6b6x   vari: 1g
        dtb 1 soc: gxl   plat: sx6b6x   vari: 2g
      Find match dtb: 0
start dts,buffer=0000000033ecd270,dt_addr=0000000033ecda70
parts: 11
00:      logo	0000000002000000 1
01:  recovery	0000000002000000 1
02:       rsv	0000000000800000 1
03:       tee	0000000000800000 1
04:     crypt	0000000002000000 1
05:      misc	0000000002000000 1
06: instaboot	0000000020000000 1
07:      boot	0000000002000000 1
08:    system	0000000050000000 1
09:     cache	0000000040000000 2
10:      data	ffffffffffffffff 4
get_dtb_struct: Get emmc dtb OK!
overide_emmc_partition_table: overide cache 
[mmc_get_partition_table] skip partition cache.
Partition table get from SPL is : 
        name                        offset              size              flag
===================================================================================
   0: bootloader                         0            400000                  0
   1: reserved                     2400000           4000000                  0
   2: cache                        6c00000          40000000                  2
   3: env                         47400000            800000                  0
   4: logo                        48400000           2000000                  1
   5: recovery                    4ac00000           2000000                  1
   6: rsv                         4d400000            800000                  1
   7: tee                         4e400000            800000                  1
   8: crypt                       4f400000           2000000                  1
   9: misc                        51c00000           2000000                  1
  10: instaboot                   54400000          20000000                  1
  11: boot                        74c00000           2000000                  1
  12: system                      77400000          50000000                  1
  13: data                        c7c00000         10a400000                  4
mmc read lba=0x12000, blocks=0x2
mmc read lba=0x12002, blocks=0x2
mmc_read_partition_tbl: mmc read partition OK!
eMMC/TSD partition table have been checked OK!
mmc env offset: 0x47400000 
WARNING: 'recovery_from_sdcard' neither in running nor in imported env!
WARNING: 'recovery_from_udisk' neither in running nor in imported env!
In:    serial
Out:   serial
Err:   serial
hpd_state=0
cvbs performance type = 6, table = 0
[store]To run cmd[emmc dtb_read 0x1000000 0x40000]
read emmc dtb
      Amlogic multi-dtb tool
      Multi dtb detected
      Multi dtb tool version: v2 .
      Support 2 dtbs.
        aml_dt soc: gxl platform: sx6b6x variant: 1g
        dtb 0 soc: gxl   plat: sx6b6x   vari: 1g
        dtb 1 soc: gxl   plat: sx6b6x   vari: 2g
      Find match dtb: 0
Net:   dwmac.c9410000
wipe_data=successful
wipe_cache=successful
upgrade_step=2
[OSD]load fb addr from dts
[OSD]failed to get fb addr for logo
[OSD]use default fb_addr parameters
[OSD]fb_addr for logo: 0x3d800000
[OSD]load fb addr from dts
[OSD]failed to get fb addr for logo
[OSD]use default fb_addr parameters
[OSD]fb_addr for logo: 0x3d800000
[CANVAS]addr=0x3d800000 width=3840, height=2160
amlkey_init() enter!
[EFUSE_MSG]keynum is 4
[BL31]: tee size: 0
[KM]Error:f[key_manage_query_size]L507:key[deviceid] not programed yet
gpio: pin GPIOAO_2 (gpio 102) value is 1
get_cpu_id flag_12bit=1
SARADC channel(0) is 0x3e1.
SARADC closed.
Hit Enter or space or Ctrl+C key to stop autoboot -- :  0 
[imgread]szTimeStamp[2019121002280214]
[imgread]secureKernelImgSz=0x977000
aml log : R2048 check pass!
aml log : R2048 check pass!
aml log : R2048 check pass!
ee_gate_off ...
## Booting Android Image at 0x01080000 ...
reloc_addr =33f4d440
copy done
      Amlogic multi-dtb tool
      Single dtb detected
load dtb from 0x1000000 ......
   Uncompressing Kernel Image ... OK
   kernel loaded at 0x01080000, end = 0x02258fd0
   Loading Ramdisk to 33d12000, end 33eb6000 ... OK
   Loading Device Tree to 000000001fff3000, end 000000001ffff8f4 ... OK
signature: 
fdt_instaboot: no instaboot image

Starting kernel ...


It is worth noting that U-Boot (bl33) itself was already running in the “normal world” environment (BL3-1 switched the mode immediately before transferring control to it). Those. even if we somehow take control of the U-Boot, we will only have limited access to the system. In principle, this is not so important. After all, even if you remove the ROM dump, pull out the AES keys and open RSA from the fuse, then there will be no big sense from this, because there is still no RSA private key.

U-Boot itself did not read any keys. He loaded the kernel into memory and called on Security Monitor to decrypt and verify the code. Security Monitor did everything necessary and told U-Boot to load the kernel or not. In general, a serious approach to software protection with its own TrustedOS and some kind of functionality like BIOS.

My further plan was to access eMMC memory.

eMMC


To connect to eMMC, it was necessary to find at least the DAT_0, CLK, CMD and GND pins. And also find out at what voltage the eMMC controller worked (1V8 or 3V3). It was impossible to do this visually and for trace tracks I pulled out eMMC myself. Since the chip was in my hands, after tracing I connected it to the adapter and dumped a full dump. Unfortunately, I did not have professional equipment and I used improvised materials for this. The result is such a “Dead Bug”.


Well, actually the pinout of the connector:



After the pinout was done, I looked at how the processor behaves without eMMC. Judging by the log, ROM after an unsuccessful attempt to boot from eMMC tried to load the code from the mSD card. This was encouraging. I quickly uploaded the dump to the mSD card and turned on the console. A small surprise awaited me here. ROM downloaded the BL2 code from the card and transferred control to it (that means the “boot” section on eMMC was not involved and there was no need for root access). Well, when the turn came to U-Boot, he complained a couple of times about the lack of eMMC (dev 1) and for a long time without thinking he stopped in the terminal.

cmd store failed 
Err imgread(L132):Fail to read 0x100000B from part[recovery] at offset 0
gxl_sx6b6x_768_v2#version


U-Boot 2015.01 (Nov 23 2018 - 15:50:35)
aarch64-none-elf-gcc (crosstool-NG linaro-1.13.1-4.8-2013.11 - Linaro GCC 2013.10) 4.8.3 20131111 (prerelease)
GNU ld (crosstool-NG linaro-1.13.1-4.8-2013.11 - Linaro GCC 2013.10) 2.23.2.20130610 Linaro 2013.10-4
gxl_sx6b6x_768_v2#

For a start, it was not bad at all. After some experiments with the terminal, I added the bootdelay = 5 parameter to the “env” section, calculated the new checksum and soldered the eMMC back. With the new option, I was hoping the U-Boot could be stopped. But in practice, everything was different. It seems that U-Boot was not interested in this parameter and the boot process was no different from the regular one. It’s sad, because a terminal with an eMMC connected was necessary for me for further actions. With a little thought, I closed DAT_0 to ground and inserted my mSD card. ROM now could not load code from eMMC and switched to mSD. Having loaded U-Boot in this way, I opened the contacts and asked:

gxl_sx6b6x_768_v2#mmc dev 1

emmc/sd response timeout, cmd8, status=0x1ff2800
emmc/sd response timeout, cmd55, status=0x1ff2800
[mmc_startup] mmc refix success
[mmc_init] mmc init success
mmc read lba=0x14000, blocks=0x400
      Amlogic multi-dtb tool
      Multi dtb detected
      Multi dtb tool version: v2 .
      Support 2 dtbs.
        aml_dt soc: gxl platform: sx6b6x variant: 1g
        dtb 0 soc: gxl   plat: sx6b6x   vari: 1g
        dtb 1 soc: gxl   plat: sx6b6x   vari: 2g
      Find match dtb: 0
start dts,buffer=0000000033ee4050,dt_addr=0000000033ee4850
parts: 11
00:      logo	0000000002000000 1
01:  recovery	0000000002000000 1
02:       rsv	0000000000800000 1
03:       tee	0000000000800000 1
04:     crypt	0000000002000000 1
05:      misc	0000000002000000 1
06: instaboot	0000000020000000 1
07:      boot	0000000002000000 1
08:    system	0000000050000000 1
09:     cache	0000000040000000 2
10:      data	ffffffffffffffff 4
get_dtb_struct: Get emmc dtb OK!
overide_emmc_partition_table: overide cache 
[mmc_get_partition_table] skip partition cache.
Partition table get from SPL is : 
        name                        offset              size              flag
===================================================================================
   0: bootloader                         0            400000                  0
   1: reserved                     2400000           4000000                  0
   2: cache                        6c00000          40000000                  2
   3: env                         47400000            800000                  0
   4: logo                        48400000           2000000                  1
   5: recovery                    4ac00000           2000000                  1
   6: rsv                         4d400000            800000                  1
   7: tee                         4e400000            800000                  1
   8: crypt                       4f400000           2000000                  1
   9: misc                        51c00000           2000000                  1
  10: instaboot                   54400000          20000000                  1
  11: boot                        74c00000           2000000                  1
  12: system                      77400000          50000000                  1
  13: data                        c7c00000         10a400000                  4
mmc read lba=0x12000, blocks=0x2
mmc read lba=0x12002, blocks=0x2
mmc_read_partition_tbl: mmc read partition OK!
eMMC/TSD partition table have been checked OK!
switch to partitions #0, OK
mmc1(part 0) is current device
gxl_sx6b6x_768_v2#

U-Boot did not resist and happily switched to eMMC. I looked, of course, what was in the bootdelay parameter. And instead of my five, I saw 0. there again. It looks like U-Boot at some point wrote down 0 there, in case someone suddenly changes something there. But it didn’t interest me anymore and the topic with eMMC was closed.

Note: having a pinout of the connector, you can connect to eMMC without soldering the chip. To do this, you need a special adapter with a voltage converter, because eMMC controller runs on 1V8 and if you connect an ordinary SD adapter to 3V3, there is a risk of burning components lying on the 1V8 bus.

It will also be necessary to remove this resistor, otherwise the processor will interfere with the adapter.


Missing components


Having full access to the U-Boot terminal, I had to do two things: get to the DeviceTree set-top box and convince U-Boot to abandon the Security Monitor services related to kernel testing. For the first launch, it would be nice to have the original kernel, so as not to waste time debugging a new one.

It was extremely easy to get DeviceTree. I asked:

gxl_sx6b6x_768_v2#emmc dtb_read 0x1000000 0x40000

read emmc dtb
gxl_sx6b6x_768_v2#

and he was in my pocket.

U-Boot required a detailed analysis. From the log it followed that U-Boot itself was loaded and decrypted initially at 0x1000000, and subsequently transferred itself to 0x36ES8000 (offset). I dumped U-Boot and analyzed it in IDA.

Of course, I was interested in the place where the Security Monitor was accessed from the bootm command. Here it is


where
X0 - AML_D_P_IMG_DECRYPT
X1 - nLoadAddr
X2 - GXB_IMG_SIZE
X3 - GXB_IMG_DEC_ALL

To remove the original kernel dump, it was necessary to load it into memory via the imgread function and modify bootm so that immediately after calling aml_sec_boot_check memory was issued starting from the address 0x1080000 to the terminal (this is certainly not the only way). To do this, I wrote a piece of code and downloaded it to the right place. Here's what happened (of course, I can’t give a full log):

gxl_sx6b6x_768_v2#imgread kernel boot

[imgread]szTimeStamp[2019121002280214]
[imgread]secureKernelImgSz=0x977000
gxl_sx6b6x_768_v2#bootm

aml log : R2048 check pass!
aml log : R2048 check pass!
aml log : R2048 check pass!

Ready for dumping kernel

41 4e 44 52 4f 49 44 21 20 d8 7b 20 20 20 08 01  | ANDROID!

In addition to the kernel, I also got ramdisk (it can come in handy in case there are any important drivers or firmware, for example, for WiFi).

I'm not Android anymore


For the first launch of my software, I made uImage from the original kernel, built my rootfs on the basis of Busybox and used my own dtb. I loaded all three parts directly from the USB drive and ran the “bootm” command, disabling decryption and image verification before.

gxl_sx6b6x_768_v2#usb start
(Re)start USB...
USB0:   USB3.0 XHCI init start
Register 2000140 NbrPorts 2
Starting the controller
USB XHCI 1.00
scanning bus 0 for devices... 2 USB Device(s) found
       scanning usb for storage devices... 1 Storage Device(s) found
gxl_sx6b6x_768_v2#mw.l 0x37ed240c 0xd2800000
gxl_sx6b6x_768_v2#fatload usb 0:1 0x1000000 dtb.img
reading dtb.img
40960 bytes read in 43 ms (929.7 KiB/s)
gxl_sx6b6x_768_v2#fatload usb 0:1 0x2000000 uImage
reading uImage
8116288 bytes read in 4197 ms (1.8 MiB/s)
gxl_sx6b6x_768_v2#fatload usb 0:1 0x3000000 rootfs.img.uboot
reading rootfs.img.uboot
1041462 bytes read in 563 ms (1.8 MiB/s)
gxl_sx6b6x_768_v2#bootm 0x2000000 0x3000000 0x1000000

ee_gate_off ...
## Booting kernel from Legacy Image at 02000000 ...
   Image Name:   S905X Original
   Image Type:   AArch64 Linux Kernel Image (gzip compressed)
   Data Size:    8116224 Bytes = 7.7 MiB
   Load Address: 01080000
   Entry Point:  01080000
   Verifying Checksum ... OK
## Loading init Ramdisk from Legacy Image at 03000000 ...
   Image Name:   Root Filesystem
   Image Type:   AArch64 Linux RAMDisk Image (gzip compressed)
   Data Size:    1041398 Bytes = 1017 KiB
   Load Address: 033d1200
   Entry Point:  033d1200
   Verifying Checksum ... OK
      Amlogic multi-dtb tool
      Single dtb detected
load dtb from 0x1000000 ......
## Flattened Device Tree blob at 01000000
   Booting using the fdt blob at 0x1000000
   Uncompressing Kernel Image ... OK
   kernel loaded at 0x01080000, end = 0x02258fd0
   Loading Ramdisk to 33db8000, end 33eb63f6 ... OK
   Loading Device Tree to 000000001fff3000, end 000000001ffff8f4 ... OK
fdt_instaboot: no instaboot image

Starting kernel ...

uboot time: 136710682 us
[    0.000000@0] Initializing cgroup subsys cpu
[    0.000000@0] Initializing cgroup subsys cpuacct
[    0.000000@0] Linux version 3.14.29 (build@build2) (gcc version 4.9.2 20140904 (prerelease) (crosstool-NG linaro-1.13.1-4.9-2014.09 - Linaro GCC 4.9-2014.09) ) #1 SMP PREEMPT Thu Sep 12 21:24:53 MSK 2019
[    0.000000@0] CPU: AArch64 Processor [410fd034] revision 4

[    6.302659@2] meson_uart c81004c0.serial: ttyS0 use xtal(8M) 24000000 change 115200 to 115200
# cat /proc/cpuinfo
Processor	: AArch64 Processor rev 4 (aarch64)
processor	: 0
processor	: 1
processor	: 2
processor	: 3
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 wp half thumb fastmult vfp edsp neon vfpv3 tlsi vfpv4 idiva idivt 
CPU implementer	: 0x41
CPU architecture: 8
CPU variant	: 0x0
CPU part	: 0xd03
CPU revision	: 4

Hardware	: Amlogic
Serial		: 210c84009f59911c4b4db4a25faffcbc
#

Jailbreak


Due to the fact that U-Boot was immunized against changing env parameters (this concerned not only “bootdelay”), it was impossible to influence the boot process through env, and in order to load its software, the prefix had to be connected to the computer. This option did not suit me at all. Having analyzed the entire loading chain, this command caught my attention:

init_display=osd open;osd clear;imgread pic logo bootup $loadaddr;bmp display $bootup_offset;bmp scale

in particular:

imgread pic logo bootup $loadaddr

where U-Boot was loading a certain “bootup” resource at the address loadaddr = 0x1080000. The resource itself was described by such a structure:

struct resource_header{
	unsigned int 	magic;		/* Image Header Magic Number	*/
	unsigned int 	hcrc;		/* Image Header CRC Checksum	*/
	unsigned int	size;		/* Image Data Size		*/
	unsigned int	start;		/* item data offset in the image*/
	unsigned int	end;		/* Entry Point Address		*/
	unsigned int	next;		/* Next item head offset in the image*/
	unsigned int	dcrc;		/* Image Data CRC Checksum	*/
	unsigned char	index;		/* Operating System		*/
	unsigned char	nums;		/* CPU architecture		*/
	unsigned char   type;		/* Image Type			*/
	unsigned char 	comp;		/* Compression Type		*/
	char 	name[32];		/* Image Name			*/
}

Of course, the “size” and “start” parameters were interesting. Proceeding from them and also the “loadaddr” parameter, U-Boot resolved three new parameters for direct reading from eMMC. Ideally, of course, he downloaded the picture from the “logo” section at 0x000B00C0 into memory at 0x1130000 ... I think the course of my thoughts is now clear. I solved new parameters “size” and “start” and wrote my code, which was saved on eMMC. After such manipulations, U-Boot was no longer reading a picture, but an exploit, which immediately gained control. The exploit consisted of several lines in assembler.

LDR X21, printf
ADR X0, .message
BLR X21

LDR X21, run_command
ADR X0, .command
MOV X1,#0x0
BLR X21

.align 4
printf: .quad 0x37EE50A0
.align 4
run_command: .quad 0x37EE9BA0

.align 4
.message: .string "\nJailbreaking BL3-3...\n"
.align 4
.command: .string "fatload mmc 0:1 0x1000000 uboot.bin; go 0x1000000"


He read uboot.bin from the first section of the mSD card and transferred control to it (uboot.bin was a freshly collected unencrypted U-Boot. Of course, it was possible to use a native modified one). It turns out that the boot process returned to the place where BL3-1 decrypted the original U-Boot and transferred control to it. Only this time, the unsigned code was already running. And now the download from eMMS looked like this (the last fragment):

Hit Enter or space or Ctrl+C key to stop autoboot -- :  0

Jailbreaking BL3-3...
card in
[mmc_init] mmc init success
reading uboot.bin
408579 bytes read in 28 ms (13.9 MiB/s)
## Starting application at 0x01000000 ...


U-Boot 2017.11-02414-g9b5924abf2-dirty (Mar 01 2020 - 22:17:58 +0100) p212

DRAM:  1 GiB
MMC:   mmc@72000: 0, mmc@74000: 1
reading uboot.env
In:    serial@4c0
Out:   serial@4c0
Err:   serial@4c0
[BL31]: tee size: 0
[BL31]: tee size: 0
Net:   
Warning: ethernet@c9410000 (eth0) using random MAC address - 22:10:89:5b:74:85
eth0: ethernet@c9410000
Hit any key to stop autoboot:  2 0
=> version
U-Boot 2017.11-02414-g9b5924abf2-dirty (Mar 01 2020 - 22:17:58 +0100) p212

aarch64-elf-gcc (Linaro GCC 7.2-2017.11) 7.2.1 20171011
GNU ld (Linaro_Binutils-2017.11) 2.28.2.20170706
=> 

Conclusion


So that the prefix does not lie idle on the shelf, I decided to put LibreElec on it. Freshly assembled image almost immediately launched without any problems. The kernel was finalized with a small file, drivers for WiFi and remote control were installed, and the poweroff function was redone. And everything worked fine, but then I remembered that the console also supports Bluetooth, which naturally did not work in LibreElec. Although I did not need it, I still decided to set it up to complement the picture.
On board was Ampak's AP6255 chip, responsible for both WiFi and Bluetooth. UART Bluetooth was connected to ttyS1, but the chip did not respond to any HCI commands and pretended to be dead. Moreover, on the native core, the chip, as expected, responded to the team.
The documentation for this chip is very poor and all that could be extracted from there is a pinout. First of all, I checked the chip power and BT_WAKE pin. Everything was normal. Having experimented with the driver itself and the ttyS1 port, I did not get any result - the chip was silent as a partisan and I connected an oscilloscope to it. On it I checked and compared all the electronic UART signals (RTS, TXD, RXD, CTS). Everything was normal. Next, I checked the reset sequence, which is controlled via rfkill (these were the BT_WAKE and BT_REGON pins). But here everything was all right. Then I checked the LPO pin, where according to the documentation a signal with a frequency of 32.768KHz should enter, but even here I saw a signal on the oscilloscope. In general, everything was in order, but the chip did not work with my core. After spending a couple more days disassembling the original UART driver, I returned to the LPO signal and measured its frequency.The result showed 26KHz. Oh how.
The wifi_dt driver was responsible for this signal, which in my core did not correctly generate the frequency. I disassembled the original driver and took over the initialization of the pwm signal from there and ... the chip came to life (later I found a version of this driver with the correct signal). And so, the chip was ready for further tuning, but I had no idea how to put it on alert, because I did not find any drivers / firmware / documentation for it. In the original Android, there was nothing in the kernel log except rfkill when working with Bluetooth. This is understandable, because there was no kernel driver, and the launch took place at the user level. It was necessary to somehow get to the log of Android itself, and for this, root access to the device was needed. To do this, in my naivety, I added the necessary settings to the system section and turned on adb.But with this scenario, Android noticed something was wrong and refused to start at all, referring to some manipulations there ... Well, no, no. I restored the system partition and redid rootfs by simply including sh there. After the subsequent launch, I had root access in the terminal.
This is how the chip was initialized.

5759  5781 I bt_hci_h4: hal_open
5759  5781 I bt_userial_vendor: userial vendor open: opening /dev/ttyS1
5759  5781 E bt_userial_vendor: userial vendor open success!!
5759  5781 I bt_userial_vendor: device fd = 52 open
5759  5781 I bt_hwcfg: bt vendor lib: set UART baud 2000000
5759  5781 I bt_hwcfg: FW prepatch file: /etc/bluetooth/4335/bcm4335_prepatch.hcd
5759  5781 I bt_hwcfg: bt vendor lib: loading prepatch /etc/bluetooth/4335/bcm4335_prepatch.hcd
5759  5781 D bt_hwcfg: Chipset BCM4335A0
5759  5781 D bt_hwcfg: Target name = [BCM4335A0]
5759  5781 I bt_hwcfg: FW patchfile: /etc/bluetooth/4335/bcm4335.hcd
5759  5781 I bt_hwcfg: bt vendor lib: set UART baud 115200
5759  5781 D bt_hwcfg: Settlement delay -- 200 ms
5759  5781 I bt_hwcfg: Setting fw settlement delay to 200 
5759  5781 I bt_hwcfg: bt vendor lib: set UART baud 2000000
5759  5781 I bt_hwcfg: Setting local bd addr to 22:22:99:F7:B6:BD
5759  5781 I bt_hwcfg: vendor lib fwcfg completed


This information was enough to write a program that did the same. The last step was to launch hciattach and LibreElec recognized Bluetooth properly. Now the device has been fully configured. If anyone is interested, here is the finished image.

All Articles