Getting Linux on Mediatek?

According to my logbook t looks like I configured, built and installed the kernel using the following commands:

make amt6797_64_open_defconfig
# mmcblk0p27 is the system partition (fastboot flash system rootfs.img)
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 olddefconfig

make -j `nproc`

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"
fastboot boot arch/arm64/boot/aboot.img

You’ll notice above that I don’t actually flash the kernel, instead I try to boot the kernel directly. I was running with a LittleKernel that I hacked myself for easier kernel development that would automatically enter fastboot mode if the boot partition was empty (like LK for DB410C)… unfortunately I can’t find the code for that so I don’t know quite what I did.

If “fastboot boot” doesn’t work try “fastboot flash boot” instead…

Thanks a lot danielt! Now I’m able to boot debian succesfully:

Found device /dev/ttyMT0.
[\0x1b[32m OK \0x1b[0m] Reached target Sound Card. Starting Serial Getty on ttyMT0…
[\0x1b[32m OK \0x1b[0m] Started Serial Getty on ttyMT0.
[\0x1b[32m OK \0x1b[0m] Reached target Login Prompts.
[\0x1b[32m OK \0x1b[0m] Reached target Multi-User System.
[\0x1b[32m OK \0x1b[0m] Reached target Graphical terface.
Starting Update UTMP about System Runlevel Changes…
\0x1b[0m] Started Update UTMP about System Runlevel Changes.
debian_arm ttyMT0

debian_arm login:

However, I’m not able to type and get passed the initial login… Do you know what may be the issue? I’m connected to the UART0, which prompts all the booting sequence but remains impassive to my key strokes.

Best,
d.

That’s pretty weird and I really don’t have much clue. Once that getty starts we usually have everything we need to communicate with the UART.

If this were happening to me my first call would be to double check all the physical connections, especially after messing with the jumpers if you are using a 96boards-uart! Have the connections been proved to work using the Android build?

Hi danielt,

It was just a stupid mistake on my hand made UART connector extension.
Now it all works fine. Thanks a lot for your support!

Best,
d.

Dear danielt,

one last thing: were you able to set up the wireless interface? I’m not able to see it:

debian_arm:~$ sudo ifconfig -a

ifb0 Link encap:Ethernet HWaddr 9a:9e:d0:fb:45:11

ifb1 Link encap:Ethernet HWaddr ba:04:22:7c:66:23

ip6tnl0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00

lo Link encap:Local Loopback

sit0 Link encap:IPv6-in-IPv4

tunl0 Link encap:IPIP Tunnel HWaddr

In a word… no.

However neither did I try very hard. I suspect the WiFi driver is trying (and failing) to load a firmware from the root filesystem; that firmware will need to be copied from the Android images.

Thanks a lot danielt, you have helped me a lot!

No worries. It would be great to see folks interested in taking the boards to new places!

Sorry… no idea why I used past tense there. It is great to see folks interested in this.

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).