Getting Linux on Mediatek?

Dear kovirobi and danielt,

I’m also interested in getting Linux on the X20. Shall we team up to document the process so that the whole community can benefit from our effort?

Best,
David

Okay, that sounds good to me, hopefully I can be of some help :slight_smile: At the moment I have not done much at all, just trying to fight the tools provided by android, because they don’t seem to be able to work much at all (I’m using adb shell to connect to my device)

Great, I don’t have experience with Android either. At least we can share the pain :wink:
Tomorrow I will be able to spend some time trying to port Linux to the X20 board. I’ll post my progress here.

I’ll be happy to help if I can but TBH I drifted away from this work
because my (rather unusual) needs were met by the mainline kernel
efforts for this board:

Dear danielt,

I gave it a try but I am now stuck, hopefully you can help me to find a way out. Let me explain what I did so far:

  1. Use multistrap to create a debian root file system (arch=arm64, suite=jessie). I am able to chroot into it and succesfully run ‘dpkg --configure -a’

  2. Create an empty image file:

    dd if=/dev/zero of=arm64_linux_root_file_system.img bs=1M count=2560

  3. Format the newly created file:

    mkfs ext3 -F arm64_linux_root_file_system.img

  4. Mount the image file and copy the root file system into it:

    sudo mount -o loop,rw,sync arm64_linux_root_file_system.img /tmp/mount_tmp
    sudo cp -rf dev-arm64/* /tmp/mount_tmp/

  5. Download your version of the Linux kernel (commit: ece0e740c5492b51790c86dd2e9dabf04e829110)

  6. Crosscompile the kernel:

    make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- amt6797_64_open_defconfig
    make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j8 Imag

So far, so good, but now is when it gets fuzzy. I am able to read the following partition table of my mediatek X20 through the UART0:

[1940] Part Info.(1blk=512B):

[1940] [0x0000000000008000-0x0000000001007fff] ( 32768 blocks): “recovery”

[1940] [0x0000000001008000-0x0000000001087fff] ( 1024 blocks): “para”

[1940] [0x0000000001088000-0x0000000001a87fff] ( 20480 blocks): “expdb”

[1940] [0x0000000001a88000-0x0000000001b87fff] ( 2048 blocks): “frp”

[1940] [0x0000000001b88000-0x0000000002387fff] ( 16384 blocks): “nvcfg”

[1940] [0x0000000002388000-0x0000000004387fff] ( 65536 blocks): “nvdata”

[1940] [0x0000000004388000-0x0000000006387fff] ( 65536 blocks): “metadata”

[1940] [0x0000000006388000-0x0000000006b87fff] ( 16384 blocks): “protect1”

[1940] [0x0000000006b88000-0x00000000077fffff] ( 25536 blocks): “protect2”

[1940] [0x0000000007800000-0x0000000007ffffff] ( 16384 blocks): “seccfg”

[1940] [0x0000000008000000-0x00000000081fffff] ( 4096 blocks): “oemkeystore”

[1940] [0x0000000008200000-0x00000000084fffff] ( 6144 blocks): “proinfo”

[1960] [0x0000000008500000-0x0000000009cfffff] ( 49152 blocks): “md1img”

[1960] [0x0000000009d00000-0x000000000a0fffff] ( 8192 blocks): “md1dsp”

[1960] [0x000000000a100000-0x000000000a3fffff] ( 6144 blocks): “md1arm7”

[1960] [0x000000000a400000-0x000000000a8fffff] ( 10240 blocks): “md3img”

[1960] [0x000000000a900000-0x000000000a9fffff] ( 2048 blocks): “scp1”

[1960] [0x000000000aa00000-0x000000000aafffff] ( 2048 blocks): “scp2”

[1960] [0x000000000ab00000-0x000000000affffff] ( 10240 blocks): “nvram”

[1960] [0x000000000b000000-0x000000000b07ffff] ( 1024 blocks): “lk”

[1960] [0x000000000b080000-0x000000000b0fffff] ( 1024 blocks): “lk2”

[1960] [0x000000000b100000-0x000000000c0fffff] ( 32768 blocks): “boot”

[1960] [0x000000000c100000-0x000000000c8fffff] ( 16384 blocks): “logo”

[1960] [0x000000000c900000-0x000000000cdfffff] ( 10240 blocks): “tee1”

[1960] [0x000000000ce00000-0x000000000d2fffff] ( 10240 blocks): “tee2”

[1980] [0x000000000d300000-0x000000000dffffff] ( 26624 blocks): “keystore”

[1980] [0x000000000e000000-0x00000000adffffff] ( 5242880 blocks): “system”

[1980] [0x00000000ae000000-0x00000000c8ffffff] ( 884736 blocks): “cache”

[1980] [0x00000000c9000000-0x00000001d0ffbdff] ( 8650719 blocks): “userdata”

[1980] [0x00000001d0ffbe00-0x00000001d1ffbdff] ( 32768 blocks): “flashinfo”

Based on one of your previous posts, I replaced the “system” (2560M) partition with my root file system image (arm64_linux_root_file_system.img). However, I don’t know how to go about the patched Linux kernel. I assume that I should replace the partition “boot” with a new “boot.img” including the new kernel? If so, shall I use a tool such as “mkbooting” to build it? Shall I first unpack the original “boot.img” to get some parts/info? As you can see, I can use some help here and thus, I would very much appreciate if you could walk me through this part of the porting procedure :slight_smile:

Best,
David

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…