几百块钱的Windows寨板一般都是这样的配置:CPU是Intel的Baytrail z3735f,或者Cherrytrail z8300/z8350,都是不到2GHz的四核凌动x86,而后者的核显性能数倍于前者(虽然性能都不高,但还是属于吊打树莓派的那种)。内存一般是2GB,而z83xx可以上4GB,只是性能会有所降低。闪存一般是32GB的emmc flash,聊胜于无。外设方面就是触屏WiFi蓝牙SD卡USB云云。它们一般跑着win10或者win+Android双系统。

对于树莓派一类玩家而言这些寨板吸引人的地方在于,价格便宜!x86的性能强!主频高内存大!WiFi!屏幕!然而虽然是x86的机器,它们并不能直接安装Ubuntu一类系统,原因在于:

  • 32位UEFI,因为32位的Windows占用空间小一些
  • 驱动非常不齐全

以没经过处理的Ubuntu-1404为例,64位镜像因为机子UEFI是32位的而无法启动,32位镜像没有EFI启动文件也启动不了。强行给32位镜像补上EFI文件则可以顺利安装,然而电池、SD卡、触屏、WiFi、声卡、屏幕调光、按键、陀螺仪、摄像头之类的驱动统统没有,只有USB能用。。。

要解决这两个问题势必要经过一些折腾。

启动镜像

少数安卓双系统的机子用的是64位UEFI,因此可以直接启动64位镜像。然而大多数机子并不能直接启动Ubuntu镜像。虽然32位UEFI只可以运行32位的.efi,但是multiarch版的镜像的efi可以接着启动64位的程序,从而启动到grub并继续启动下去。

multi-arch

新版的Debian 9可以直接下载multi-arch版本的镜像,它的关键是有efi/boot/bootia32.efi这个文件,从而可以用32位UEFI启动64位镜像。但是Debian装后只有基本系统,后续定制起来有点麻烦。

有个野生的名叫XJUbuntu的发行版定制了很多东西,其中有个玩家在他的台电X98 plus平板上定制Ubuntu 16.04,跑通了很多东西,制作了所谓XJUbuntuTAB。但是这个镜像很大,定制的xfce桌面我也并不特别习惯,并且很多关键驱动如电池、触屏在我平板上都不行。

如果要用原生Ubuntu,可以将bootia32.efi加到其中从而使其可以启动;

  • 如果用Debian multiarch的efi,还需要多改一些东西。这篇问答详细解释了如何操作。
  • 如果用这个efi,直接丢到镜像中就好了。

linuxium的工具

Linuxium是个机顶盒、电视棒的Linux玩家,他的博客有很多非常有意思的东西。为了在x86的电视棒上跑Ubuntu,他开发了isorespin.sh这个脚本,功能非常多,包括:

  • 添加32位UEFI启动文件
  • 添加Apollo lake的必要文件(对于N3450系列的赛扬芯平板)
  • 更改Linux内核,从而添加驱动补丁
  • 新增软件包等,从而添加固件和驱动
  • 运行脚本

其实这些都是Ubuntu-LiveCD定制的工作,只是Ubuntu的wiki上对于UEFI的定制说明太少了。

利用isorespin.sh,可以为64位Ubuntu 18.04添加32位启动项:

$ isorespin.sh -i ubuntu-18.04-desktop-amd64.iso

因为它需要mount镜像,所以它需要root权限。需要留意的是虽然它可以用--atom来添加特别的驱动,比方说rtl8723bs的WiFi和蓝牙。但是这都要梯子才能下载,命令行中sudo之后的代理有点问题,所以这些东西还是启动之后再安装吧。大概半个小时之后它会生成一个名叫linuxium-ubuntu-18.04-desktop-amd64.iso的镜像(大部分时间用在squashfs的解压和重新生成上)。

选择哪个桌面

Ubuntu 17.10开始的官方发行版桌面为GNOME;但现在的GNOME 3问题在于太过耗资源了,刚启动就占了1个多GB,开两个gnome-terminal就快要炸了。轻量级的桌面有LXDE、XFCE等等,个人感觉XFCE稍微好看点。。。

screen
screen

Linux驱动

越新版的内核,一些外设的驱动越有可能得到支持。比方说最新的Ubuntu 18.04,在我的昂达V101W上就能用SD卡、电池、背光调节、陀螺仪、开关机按钮了。其他的能折腾出来的驱动罗列如下。

WiFi

一般网卡是rtl8723bs,它的驱动已经合并到linux 4.12的staging目录下面了,所以Ubuntu 18.04有它的驱动。但是网卡还需要一个固件,可以从hadess的github上下载。

dmesg看到缺少这个固件:

$ dmesg | grep rtl8723
...
[  170.823731] rtl8723bs: acquire FW from file:rtlwifi/rtl8723bs_nic.bin
[  170.823790] rtl8723bs mmc0:0001:1: Direct firmware load for rtlwifi/rtl8723bs_nic.bin failed with error -2
...

就把固件复制到/lib/firmware/rtlwifi/目录下面,重新加载驱动即可。

$ sudo cp rtl8723bs_nic.bin /lib/firmware/rtlwifi/
$ sudo modprobe -r r8723bs
$ sudo modprobe r8723bs
$ dmesg | grep rtl8723
...
[  228.095947] rtl8723bs: acquire FW from file:rtlwifi/rtl8723bs_nic.bin
...
$ ifconfig wlan0
wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.225  netmask 255.255.255.0  broadcast 192.168.2.255
        inet6 fe80::74b5:1920:54c6:e8d  prefixlen 64  scopeid 0x20<link>
        ether 8c:18:d9:1f:3e:fd  txqueuelen 1000  (以太网)
        RX packets 579  bytes 705015 (705.0 KB)
        RX errors 0  dropped 582  overruns 0  frame 0
        TX packets 605  bytes 70957 (70.9 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

对于博通系列的SDIO网卡也一样是补上固件就能用了。博通的驱动比较通用,几乎支持所有的AP6xxx模块;它除了需要固件以为还需要配置文件,这些都可以在github上找到,比方说华硕T100的固件

值得一提的是,Lubuntu 18.04的rtl8723bs则直接可用。

蓝牙

蓝牙一般都是通过串口,以HCI协议进行交互。老版内核会认出一个MMIO的串口(通常是ttyS4),由一个systemd守护进程(而不是内核驱动)通过这个串口下载蓝牙固件、初始化、与之交互,详见这个仓库start_bt.sh

但是新版的内核引入了所谓serdev的概念,驱动事宜都由内核解决。这时串口就不仅仅是一个“字符设备”,而是一个“总线”了。这时它就不会将串口/dev/ttySx暴露给用户空间了。然而rtl8723bs的蓝牙驱动现在内核里面又没有,所以就需要一些内核补丁。

  • 可以用这个补丁,它简单地加了一个判断,不要将OBDA8723设备注册为serdev,从而可以用之前的systemd守护进程。
  • 或者用这些补丁就详细实现了HCI5协议以及rtl8723bs的驱动,进而不需要用户空间的systemd了。其实这些补丁来自于Linux-sunxi,虽然说是全志的专用内核,但是也包含了很多新奇趣怪的驱动,比方说jwrdegoede这位兄弟貌似在搞GPD win掌机的驱动。。

linux 4.17内核打了sunxi的补丁,加上蓝牙的固件和配置文件(lwfinger的仓库里面有),蓝牙就可以愉快地跑了。

[    8.027854] Bluetooth: hci0: rtl: examining hci_ver=06 hci_rev=000b lmp_ver=06 lmp_subver=8723
[    8.032153] Bluetooth: hci0: rom_version status=0 version=1
[    8.032183] Bluetooth: hci0: rtl: loading rtl_bt/rtl8723bs_fw.bin
[    8.033786] Bluetooth: hci0: rtl: loading rtl_bt/rtl8723bs_config-OBDA8723.bin
[    8.064135] Bluetooth: hci0: cfg_sz 55, total size 24263
bluetooth
bluetooth

触屏

很多win或安卓平板用的触屏芯片都是gslx680,一个I2C接口的电容屏芯片。它也需要固件,根据电容屏的行列布线不同而需要不同的固件。好事情是驱动和固件都能找到。

  • gslx680-acpi适用于ACPI平台,可以加入内核中。
  • gsl-firmware适用于不同的平板,如果没有支持的平板的话可用里面的工具自己生成。

对于我的昂达V101W-V5平板来说,可以从昂达旧官网上下载Windows驱动。找到TP/SileadTouch.fw这个固件,然后利用gsl-firmware的工具来生成适用的固件:

$ tools/unscramble SileadTouch.fw silead_ts.fw
$ sudo cp silead_ts.fw /lib/firmware

生成的固件直接丢在/lib/firmware/目录下面就行了。这时启动之后就可以用触屏了。

[    6.736112] gslx680 i2c-MSSL1680:00: gsl_ts_probe: got a device named MSSL1680:00 at address 0x40, IRQ 23, flags 0x0
[    6.768964] byt_gpio INT33FC:02: [Firmware Bug]: pin 21 forcibly re-configured as GPIO
[    6.770426] input: Silead GSLx680 Touchscreen as /devices/platform/80860F41:03/i2c-3/i2c-MSSL1680:00/input/input4
touchscreen
touchscreen

启动之后可以使用xinput_calibrator进行更细致的微调。

另外要想加一些手势操作比方说长按右键、两根手指、三根手指、滑动等等,可以用touchegg来配置。

声卡

Windows平板用的声卡一般都是alc5640,对于新版内核来说也是这样,有驱动没固件没配置文件。

  • 固件可以直接用华硕T100的固件,添加到/lib/firmware/intel/目录下面。
  • 配置文件用这份UCM,需要复制到/usr/share/alsa/ucm/bytcr-rt5640/目录下面。
  • 另外还需要用alsa的工具来配置默认输出。

linuxium用这些方法弄好了Intel计算棒的HDMI音频输出,同样道理也可以弄好普通声卡输出。

首先查看有哪些音频设备:

$ aplay -l
**** PLAYBACK 硬體裝置清單 ****
card 0: Audio [Intel HDMI/DP LPE Audio], device 0: HdmiLpeAudio [Intel HDMI/DP LPE Audio]
子设备: 1/1
子设备 #0: subdevice #0
card 0: Audio [Intel HDMI/DP LPE Audio], device 1: HdmiLpeAudio [Intel HDMI/DP LPE Audio]
子设备: 1/1
子设备 #0: subdevice #0
card 1: bytcrrt5640 [bytcr-rt5640], device 0: 1 []
子设备: 1/1
子设备 #0: subdevice #0
card 1: bytcrrt5640 [bytcr-rt5640], device 1: Deep-Buffer Audio (*) []
子设备: 1/1
子设备 #0: subdevice #0

可见card 1那里有两个bytcr-rt5640设备。试着用card1,device0来播放测试音频:

$ aplay -D plughw:1,0 /usr/share/sounds/alsa/Front_Left.wav
正在播放 WAVE '/usr/share/sounds/alsa/Front_Left.wav' : Signed 16 bit Little Endian, 频率48000Hz, Mono

不出意外可以听到扬声器说出“front left”这句话来。

然后我们就要修改/etc/pulse/default.pa来设置默认音频设备了。找到加载module-alsa-sink这一行,取消注释,并加上device=hw:1,0

load-module module-alsa-sink device=hw:1,0

然后把下面一段的“Automatically load driver modules”的那几行都注释掉。

重启,就可以有声音了。然而只是扬声器有效,耳机并不行,想必是ucm文件没有这份配置。

一些踩坑记录:

  • 如果没有固件,则声卡不能成功初始化
  • 如果没有ucm文件,则dmesg中会不断刷屏说“byt-rt5640 byt-rt5640: ASoC: CPU DAI baytrail-pcm-audio not registered”
  • 如果没有修改/etc/pulse/default.pa,那么在登录之前就有声音,进桌面就没声音。

电池

平板用的电源管理芯片一般是AXP288,它能输出多路直流电源并管理锂电池,通过I2C接口来配置和读取信息。在老板内核里面没有axp288驱动,于是Icenowy大神就写了一个systemd来生成一个测试电源,并利用i2cget来读取AXP288的寄存器,从而得到电量、是否充电之类的信息。

新版内核就有AXP288驱动了,在不少平板上都可以愉快使用,但是在我之前收的一块拆机主板上电量读取总是为0。翻手册发现,电量输出有两个可能的寄存器,一个是0xB9,一个是0xE4,前者通过电流积分来算容量,后者则根据电压来估计容量,一般情况下读前者就行了。Linux驱动中读电量的fuel_gauge_get_property()函数读取的是前面的那个寄存器寄存器,而这块板子读出来就是0,只能读后面的寄存器。于是修改如下:

@@ -498,7 +498,7 @@
             val->intval = 0;
         break;
     case POWER_SUPPLY_PROP_CAPACITY:
-        ret = fuel_gauge_reg_readb(info, AXP20X_FG_RES);
+        ret = fuel_gauge_reg_readb(info, AXP288_FG_OCV_CAP_REG);
         if (ret < 0)
             goto fuel_gauge_read_err;

这些情况在拆机主板上可能比较常见,因为长时间没电池可能导致AXP288的计数器出了问题。

battery
battery