Getting Linux on Mediatek?

Dear danielt,

I’ve been trying to find out why the wlan interface is dead after booting with Linux but I’m running out of ideas.

As far as I can see, the wlan drivers are linked in kernel compilation:

$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j 8

CC drivers/misc/mediatek/connectivity/wlan/gen3/mgmt/roaming_fsm.o

CC drivers/misc/mediatek/connectivity/wlan/gen3/mgmt/tkip_mic.o
CC drivers/misc/mediatek/connectivity/wlan/gen3/mgmt/hs20.o

CC drivers/misc/mediatek/connectivity/wlan/gen3/mgmt/tdls.o

The problem is that during booting the wireless device is not identified and I don’t really know the reason…|

I’ve uploaded the booting log and the result of the lshw command in my dropbox:

I could really use some help :stuck_out_tongue:

Best,
d.

I have been further digging and I might have found the root cause of the problem: we are using an empty ramdisk image, while the reference Android system is using all the initialization there. I’ve reversed ingenieered the Android ramdisk and this is what it contains:

$ ls -1
charger
data
default.prop
dev
enableswap.sh
factory_init.connectivity.rc
factory_init.project.rc
factory_init.rc
file_contexts
fstab.mt6797
init
init.common_svc.rc
init.connectivity.rc
init.environ.rc
init.modem.rc
init.mt6797.rc
init.mt6797.usb.rc
init.project.rc
init.rc
init.recovery.mt6797.rc
init.trace.rc
init.usb.rc
init.xlog.rc
init.zygote32.rc
init.zygote64_32.rc
meta_init.connectivity.rc
meta_init.modem.rc
meta_init.project.rc
meta_init.rc
oem
proc
property_contexts
sbin
seapp_contexts
selinux_version
sepolicy
service_contexts
sys
system
ueventd.mt6797.rc
ueventd.rc

This initailzation binaries make use of Android binaries such as wmt_launcher, which we don’t have in our Linux rfs. How would you suggest to proceed?

Best,
David

You don’t mention what you have tried so far… Have you already copied the firmware from the android system (where IIRC it lives in a directory in /etc) to /lib/firmware on your debian image? There’s certainly some logic in drivers/misc/mediatek/connectivity/wlan/gen3/ to load firmware (“cd …; git grep request_firmware”).

However it’s also the case that the module_init function (called initWlan) is not being called in your logs. I guess that is the most urgent question to solve.

I did copy all the firmware from Android (android_rfs/etc/firmware/* → linux_rfs/etc/firmware)

android_rfs/etc/firmware/ROMv3_patch_1_0_hdr.bin
android_rfs/etc/firmware/WIFI_RAM_CODE_6797
android_rfs/etc/firmware/mt6631
android_rfs/etc/firmware/mt6631/mt6631_fm_v2_coeff.bin
android_rfs/etc/firmware/mt6631/mt6631_fm_v1_patch.bin
android_rfs/etc/firmware/mt6631/mt6631_fm_v3_patch.bin
android_rfs/etc/firmware/mt6631/mt6631_fm_v5_coeff.bin
android_rfs/etc/firmware/mt6631/mt6631_fm_v3_coeff.bin
android_rfs/etc/firmware/mt6631/mt6631_fm_v5_patch.bin
android_rfs/etc/firmware/mt6631/mt6631_fm_v4_coeff.bin
android_rfs/etc/firmware/mt6631/mt6631_fm_v1_coeff.bin
android_rfs/etc/firmware/mt6631/mt6631_fm_v4_patch.bin
android_rfs/etc/firmware/pcm_suspend_by_mp1.bin
android_rfs/etc/firmware/ROMv3_patch_1_1_hdr.bin
android_rfs/etc/firmware/pcm_sodi_by_mp1.bin
android_rfs/etc/firmware/pcm_vcorefs_hpm.bin
android_rfs/etc/firmware/WMT_SOC.cfg
android_rfs/etc/firmware/pcm_vcorefs_ultra.bin
android_rfs/etc/firmware/pcm_sodi.bin
android_rfs/etc/firmware/pcm_deepidle.bin
android_rfs/etc/firmware/pcm_suspend.bin
android_rfs/etc/firmware/pcm_deepidle_by_mp1.bin
android_rfs/etc/firmware/pcm_vcorefs_lpm.bin

However, based on a reference Android booting log, I see that the drivers are loaded with the wmt_loader and my Linux booting does not arrive that far. My understanding is that all this happens in the Android ramdisk image (which includes initialization files such as init.rc or init.mt6797.rc ). You can see next the Android booting log just mentioned:

[ 8.672320] <6>.(3)[242:wmt_loader][WLAN-MOD-INIT][I]do_wlan_drv_init:start to do wlan module init 0x6797
[ 8.673373] <6>.(3)[242:wmt_loader][MTK-WIFI] WIFI_init: mtk_wmt_WIFI_chrdev driver(major 153) installed.
[ 8.673379] <6>.(3)[242:wmt_loader][WLAN-MOD-INIT][I]do_wlan_drv_init:WMT-WIFI char dev init, ret:0
[ 8.679672] <6>.(8)[242:wmt_loader][WLAN-MOD-INIT][I]do_wlan_drv_init:WLAN-GEN3 driver init, ret:0
[ 8.679674] <6>.(8)[242:wmt_loader][WLAN-MOD-INIT][I]do_wlan_drv_init:finish wlan module init

Is it possible that the driver loading does not happen in the kernel but in the ramdisk? If so, what can I do to replicate the initialization on a Linux booting?

I’m also attaching a snippet of the init.connectivity.rc file that I believe responsible of the wlan driver loading:

service wmt_loader /system/bin/wmt_loader
class core
user root
group root
oneshot

service wmt_launcher /system/bin/wmt_launcher -p /system/etc/firmware/
user system
group system
class core

Firstly, please note that, when running on a normal Linux system (with udev) then firmware is loaded from /lib/firmware rather than /etc/firmware, this needs to be fixed, however I think you are right that there’s more going on here so I wouldn’t expect getting the firmware into the right directory to be enough.

What is wmt_loader (a shell script or a “real” binary)?

I’ve changed the firmware to the correct directory (/lib/firmware) but, as you expected, the problem remains.
I’ve also checked the wmt_loader and unfortunately it’s a “real” binary…

Let me share my latest findings: the kernel init process runs successfully and then it continues the initialization in the root file system:

...
if (!try_to_run_init_process("/sbin/init") ||
    !try_to_run_init_process("/etc/init") ||
    !try_to_run_init_process("/bin/init") ||
    !try_to_run_init_process("/bin/sh"))
	return 0;
...

Thus, I understand that I should properly configure the init system in my root file system (Systemd in my case). I’ll keep on digging…

Continuing with my debugging, I’m now examining the Android kernel booting process. I see that the wifi driver is configured through a sys_call as shown by the following snippet resulting from a dump_stack():

[ 11.934678] <0>.(5)[243:wmt_loader][] dump_stack+0x7c/0xc0
[ 11.934687] <0>.(5)[243:wmt_loader][] do_connectivity_driver_init+0x1c/0x180
[ 11.934691] <0>.(5)[243:wmt_loader][] wmt_detect_unlocked_ioctl+0x1cc/0x2f8
[ 11.934699] <0>.(5)[243:wmt_loader][] do_vfs_ioctl+0x338/0x5b8
[ 11.934703] <0>.(5)[243:wmt_loader][] SyS_ioctl+0x88/0xa0

Do you know how could I emulate the sys_call in Linux?

Interesting.

Does the process keep running (like a service) or is it just doing the
setup?

If it keeps running you might have to experiment with running the program
in libhybris.

If it’s just setup it might be interesting to explore whether you can get
strace to run in bionic (if you capture all the syscalls with strace you
could replay the bits we don’t understand).

It is just a setup. Can you explain me a bit more how could I capture the syscalls? I thought of strace, but I don’t have access to the command line when booting Android.

If there’s not serial command line you should be able to run shell commands via adb.

To be honest I’ve never tried running strace on Android but it seems that it is possible: Debugging with strace - Android Games - Android Developer

Perhaps it may be possible to modify the init files so wmt_launcher starts up running under strace (just store the trace on the filesystem for later retrieval).

Thanks for the tip, I will then try via adb.

Btw, do you know how should I configure the kernel configuration to be able to boot Android?
This is what I do right now:

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-  amt6797_64_open_debug_defconfig
scripts/config \
--enable CMDLINE_FORCE --set-str CMDLINE \
'console=tty0 console=ttyMT0,921600n1 root=/dev/ram vmalloc=496M slub_max_order=0 slub_debug=O androidboot.hardware=mt6797 maxcpus=5 mrdump.lk=MRDUMP04 mrdump_rsvmem=0x46000000,0x400000,0x44800000,0x9c280 androidboot.verifiedbootstate=green bootopt=64S3,32N2,64N2 lcm=1-nt35695_fhd_dsi_cmd_truly_nt50358_drv fps=6000 vram=29229056 printk.disable_uart=0 ddebug_query="file *mediatek* +p ; file *gpu* =_" bootprof.pl_t=4252 bootprof.lk_t=3294 boot_reason=4 androidboot.serialno=0123456789ABCDEF androidboot.bootreason=wdt_by_pass_pwk gpt=1 initcall_debug=1 usb2jtag_mode=0'
scripts/config \
--disable TOUCHSCREEN_MTK \
--disable TOUCHSCREEN_MTK_GT1151 \
--enable TMPFS \
--enable DEVTMPFS \
--enable CGROUPS \
--enable FHANDLE \
--enable AUTOFS4_FS \
--enable FTRACE_SYSCALLS \
--enable IPV6

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-  olddefconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-  -j 8

abootimg \
--create arch/arm64/boot/aboot_android_debug.img \
-k arch/arm64/boot/Image.gz-dtb \
-r /home/novo/Work/Android/fastRecovery/test/boot.img-ramdisk \
-c "pagesize = 0x800" \
-c "kerneladdr = 0x40080000" \
-c "ramdiskaddr = 0x45000000" \
-c "secondaddr = 0x40f00000" \
-c "tagsaddr = 0x44000000" \
-c "name = " \
-c "cmdline = bootopt=64S3,32N2,64N2"

But something goes bad and keeps on rebooting.

I don’t remember exactly but you probably want to get rid of the CMDLINE
and CMDLINE_FORCE. IIRC the reason we needed to override the kernel
command line was precisely in order to prevent the system from booting
to Android.

Okay, I have received my 1.8V UART and can now try and experiment, so this is just what I have had, trying to reproduce what you have done.

@DavidNovo
Re: something goes bad and keeps on rebooting.

I think the problem will be the root=/dev/ram (I think that was for me at least), but to be sure, look for ‘panic’ in the command line output. E.g. try

stty -F /dev/ttyUSB0 speed 921600 raw
grep --text panic < /dev/ttyUSB0

I expect you would get something like

Unable to mount root fs on unknown-block

to appear in your output, as /dev/ram probably won’t contain a mountable filesystem.

If you have trouble getting to fastboot as it just keeps rebooting, try using xflash, something like:

./xflash  enter-fastboot Path-to-mediatek-x20-aosp-16.10/Images/Normal\ Image/MT6797_Android_scatter.txt

you can get xflash from http://builds.96boards.org/releases/helio-x20/mediatek/aosp/latest/

hi @DavidNovo, how you get linux installed onto x20, I’m very interested about this. Could you kindly tell me how to do this? And do you have any documents to follow?

Hi Eric, I was able to boot linux onto the x20 following danielt’s instructions. However, the big cores were not functioning correctly as their maximum frequency was limited to about 700 MHz.

Hi Eric, I was able to boot linux onto the x20 following danielt’s
instructions. However, the big cores were not functioning correctly as
their maximum frequency was limited to about 700 MHz.

Wow. That is going back a few years!

Usually the recipe I use is something like:

  • Build a kernel[1] and check basic functionality by running it using
    a buildroot rootfs via initramfs (basic functionality includes some
    kind of networking… on 96Boards platforms I often use USB
    networking).

  • Add Debian -- Details of package cdebootstrap-static in sid to the
    buildroot rootfs using an overlay

  • Find a biggish existing partition and reformat it. Then mount it and
    use cdebootstrap to create a fresh debian rootfs.

  • Remove the initramfs and point it at the newly minted debian
    partition.

This approach definitely lacks style: using FAI to pre-author a rootfs
and installing it with fastboot is arguably much better (and is what I
would do it I wanted to productise my private hacking). However having a
buildroot rootfs around for troubleshooting makes it easy to figure out
what is happening when things don’t work.

Daniel.

[1] That part is, I hope, clear from posts earlier up the thread.

hi @danielt, you mean run the kernel img? I don’t know how to do this, could you be more specific? Besides, I’m trying to install ubunut onto x20, and here is how I do it:

  1. download the ubuntu (ubuntu-base-16.04.1-base-arm64.tar.gz)
  2. sudo tar -xpf ubuntu-base-16.04.1-base-arm64.tar.gz -C temp
  3. dd if=/dev/zero of=arm64_linux_root_file_system.img bs=1M count=512
  4. mkfs ext3 -F arm64_linux_root_file_system.img
  5. sudo mount -o loop,rw,sync arm64_linux_root_file_system.img rootfs/
  6. sudo cp -rf temp/* rootfs/
  7. sudo umount rootfs/
  8. Download the Linux kernel
  9. config and compile the kernel as following:
    make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-  amt6797_64_open_debug_defconfig
    
    scripts/config \
    	--enable CMDLINE_FORCE --set-str CMDLINE \
    	'console=ttyMT0,921600n1 root=/dev/mmcblk0p27 rw vmalloc=496M maxcpus=5 mrdump.lk=MRDUMP04 mrdump_rsvmem=0x46000000,0x400000,0x44800000,0x9c280 lcm=1-nt35695_fhd_dsi_cmd_truly_nt50358_drv fps=6000 vram=29229056 boot_reason=0 gpt=1 loglevel=1'
    
    scripts/config \
    	--disable TOUCHSCREEN_MTK \
    	--disable TOUCHSCREEN_MTK_GT1151 \
    	--enable TMPFS \
    	--enable DEVTMPFS \
    	--enable CGROUPS \
    	--enable FHANDLE \
    	--enable AUTOFS4_FS \
    	--enable IPV6
    
    make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-  olddefconfig
    make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-  -j 8
    
    touch arch/arm64/boot/empty
    gzip -f arch/arm64/boot/empty
    abootimg \
    	--create arch/arm64/boot/aboot.img \
    	-k arch/arm64/boot/Image.gz-dtb \
    	-r arch/arm64/boot/empty.gz \
    	-c "pagesize = 0x800" \
    	-c "kerneladdr = 0x40080000" \
    	-c "ramdiskaddr = 0x45000000" \
    	-c "secondaddr = 0x40f00000" \
    	-c "tagsaddr = 0x44000000" \
    	-c "name = " \
    	-c "cmdline = bootopt=64S3,32N2,64N2"
    
  10. download the imgs to x20 using fastboot
    fastboot flash system arm64_linux_root_file_system.img
    fastboot flash boot arch/arm64/boot/aboot.img
    

But now the x20 board is UNbootable, I don’t know where thing goes wrong, could you give me some tips?

For early experimentation I use fastboot boot rather than fastboot flash boot but other than that you already seem to be doing everything I did.

Make sure you have hooked up to the correct UART. I can’t remember if I was using LS-UART0 or LS-UART1 but as soon as the kernel boots you should see the boot messages on one of these… and then (probably) you will see a panic because the kernel doesn’t find the rootfs.

OK, I see. But I don’t have the UART, is this necessary? Dose there exist any other way to debug this board?