简介

​ 近段时间,msm8916-mainline项目的大佬们又为红米2完成了充电芯片的驱动,这意味着可以在主线内核中能够正常充电和检测电池容量,还有otg的供电。距离完整可用的主线Linux手机又进了一步。

​ Postmarketos项目的那帮大佬也不知道最近在整什么新的功能,导致edge版本的postmarketos要么会在构建rootfs时对包的checksum报错,要么刷进去产生一些稀奇古怪的bug,体验很差,也许基于musl libc的alpine linux可能真的不太适合手机这种设备,postmarketos的稳定版还没有完全准备好的情况下,想要让这些老爷机发挥余热也只能继续造新的轮子了。

​ 另外,针对于移动端的debian衍生版mobian也推出了搭载sdm845芯片手机的支持。终于有了与msm8916芯片相似度更高的平台出现,这也使我的移植更为轻松了,为了方便起见,我没有完成msm8916平台支持包的打包,而是在mobian一加6的刷机包上进行修改,最终形成一个个人觉得很稳定的debian刷机包,这个基本上可以算的上是一个最廉价的带屏幕的树莓派代替方案了,除了没有使用chroot方案安卓层的性能损耗和一个完整的,带systemd的文件系统,它还拥有比各种派更多的传感器和电池等一大波外设,最终完成了这么一个刷机包,(⊙v⊙)嗯~想想还有点小激动。

我最终解决了前篇文章中提到的一些致命的问题,使得不是那么令人抓狂的、可以使用的小型linux设备成为可能。

最终的系统镜像会分享给大家,Have Fun ~~

目前硬件支持的程度

支持的

  • wifi
  • 蓝牙
  • 重力传感器
  • gpu
  • 显示
    • 某些红米2的屏幕驱动暂时不能正确处理屏幕休眠,休眠唤醒之后可能会有轻微的残影或者闪屏现象
    • 已知完美的屏幕有 mdss_dsi_nt35521_720p_video 不会闪屏和残影。
    • 屏幕型号请参见lk2nd的PANEL那一栏。
  • 充电 & 电量显示
  • otg usb
  • 触摸屏
  • 放音 & 录音
  • gps
  • 旁边的音量键和电源键

不支持的

  • 前后摄像头 (调了几天,结果相机模块连电都通不了,果真还是自己太菜了~)
  • modem (通话、发短信、流量)<-- 自己用不到就没有调~~
  • 面板上的三大功能键(反正这个系统里面这几个键没什么用了)
  • 光线传感器 (懒得调,主线linux有驱动)
  • 磁场传感器(懒得调,主线linux有驱动)
  • 休眠(容易睡死,可能很长时间才会唤醒,建议关掉休眠)

填坑

解决debian的ramdisk挂载不上文件系统的问题

​ 最主要的问题是msm8916的mmc设备号在启动的时候不是固定的,有时候是mmc1,有时候是mmc0。postmarketos的解决方案是魔改initramfs,同时把system(看安装的分区来定也可能是userdata)划分为两个分区,一个叫pmos_boot,一个叫pmos_root,分别存储内核、alpine的initramfs和rootfs。在boot分区中的initramfs在启动时会按照卷标名去查找目标分区,然后引导真正的initramfs,这种解决方案巧妙之处就在于可以适用于各种空间大小的boot.img分区,不至于initramfs太大而刷不进去。

​ 一开始我就放弃了,因为如果要学postmarketos的方案的话就需要自己构建initramfs,直到无聊的我在GPT分区的archlinux执行了cat /proc/cmdline这个指令

guo@handsomelaptop cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-linux-lts root=UUID=e7c0a739-2da2-4422-b936-f3a0ccd8914b rw loglevel=3 quiet

​ 原来initramfs可以通过指定UUID的方式来确定root分区,使用userdata分区的UUID来生成新的boot.img,一切就迎刃而解了!还好老米的boot分区管够,轻松放下一个包含所有内核模块的标准Debian Initramfs。。。

mkbootimg --base 0x80000000 \--kernel_offset 0x00080000 \--ramdisk_offset 0x02000000 \--tags_offset 0x01e00000 \--pagesize 2048 \--second_offset 0x00f00000 \--ramdisk initrd \--cmdline "console=tty0 root=UUID=9086bed9-957e-46e8-8beb-32b3727cc753 rw loglevel=3 splash"\--kernel kernel-dtb -o boot.img

解决没有声音的问题

​ 事实上,我还没能完全解决声音的问题,插入耳机切换好像仍然没有工作,如果要使用耳机需要在设置里面手动设置,其他完美。在msm8916-mainline项目里面把ucm文件拷到/usr/share/alsa就可以使用了。

​ msm8916声卡ucm文件

驱动摄像头(尚未完成)

​ 整个postmarkos社区至今为止都没有人跑通过任何一款msm8916手机的摄像头,但是摄像头的驱动在主线中存在很久了,主要是供DragonBoard使用的。主要的难点主要有三个,一个是控制相机的供电,还有就是驱动和firmware。

​ 高通的相机i2c(cci)在安卓内核里面是没有办法通过i2c-tools读取的,所以我连i2c到底什么地址上接了什么都摸不太清,只能把相机的供电调好才能够知道两个摄像头的i2c地址,可是在目前的状态下i2c下,还是什么设备都没有。看原厂的内核日志,在摄像头启动的时候还加载了固件进去,而且固件还不止一个,可能跑起来有一定的难度。

​ 但是通过分析原厂内核源码和设备树,还是大体能够知道摄像头的一些信息。红米2后摄像头是ov8865,还挂了一颗eeprom,可能需要魔改驱动才能用上这颗eeprom里面的校准数据。前摄是ov5670。幸运的是我找到了后摄像头在安卓用户层的驱动(就vendor里面的动态链接库)的源码,应该需要稍微亿些些研究才能够跑通吧。

ov8865源码

eeprom源码

另外的一些尝试

​ 基于lk2nd的引导方法还是太过固定和死板了,还是安卓的那一套,采用boot.img的方法来加载内核使得内核的更新不是那么的通用(相较于其他单板电脑来说)。所以,一种新的引导方式的存在便极为重要了,也可使从sd卡引导系统和更为通用和统一的文件系统构建方法成为可能。

基于kexec的bootloader

​ 安卓的boot分区的设计初衷就是需要有一个被上一级bootloader加载的内核和ramdisk。而从2.x的linux内核开始linux就引入了kexec功能,使得一个linux内核可以引导另一个linux内核进行启动。若使用一个带kexec的内核和携带相应用户层工具的ramdisk便可以从任何分区引导任何合法的内核镜像,让多系统共存成为可能。但是单纯的从上一级原厂lk bootloader里传来的内核参数也许对于主线内核来说还是少了些东西,还是要让lk2nd把正确的参数传给这个主线内核,但是这个启动的过程就变得更加复杂了,好处就是比较好实现~

前面的一大批初始化程序 --> lk --> lk2nd --> kexec --> 目标内核

开启simple-framebuffer

​ 高通在主线的drm十分的奇怪,不能编译成内建的模块也就是选项,否则这个模块就会加载失败,还有就是不能在wifi不工作的情况下运行,wifi必须在正常加载firmware并运行的情况下drm才能正常运行,还有就是所有的panel和drm模块加载的顺序是确定的,panel与drm加载的顺序不对也是没有显示的。(来自postmarket os wiki)

​ 所以若是要在空间有限的情况下完成显示,使用drm是不太现实的,最好的情况是使用来自bootloader初始化好的framebuffer,经过多次尝试,对红米2的设备树修改如下。使用的是dragonPi项目中我移植msm8916-mainline项目的一部分特性的5.10内核。

 reserved-memory {/delete-node/ wcnss@89300000;/delete-node/ venus@89900000;// 让内核不要动framebuffer的内存+ framebuffer@83000000 {+    reg = <0x0 0x83000000 0x0 0x1400000>;+      no-map;+ };mpss_mem: gps_mem: mpss@86800000 {status = "disabled";reg = <0x0 0x86800000 0x0 0x5100000>;no-map;};wcnss_mem: wcnss@8b900000 {reg = <0x0 0x8b900000 0x0 0x600000>;no-map;};venus_mem: venus@8bf00000 {reg = <0x0 0x8bf00000 0x0 0x600000>;no-map;};};// chosen 加入以下内容   chosen {stdout-path = "serial0";#address-cells = <2>;#size-cells = <2>;ranges;framebuffer0: framebuffer@83200000 {status = "okay";compatible = "simple-framebuffer";reg = <0x0 0x83200000 0x0 (720 * 1280 * 3)>;width = <720>;height = <1280>;stride = <(720 * 3)>;format = "r8g8b8";power-domains = <&gcc MDSS_GDSC>;// 不要让系统重新初始化这些时钟clocks = <&gcc GCC_MDSS_AHB_CLK>,<&gcc GCC_MDSS_VSYNC_CLK>,<&gcc GCC_MDSS_AXI_CLK>,<&gcc GCC_MDSS_MDP_CLK>,<&gcc GCC_MDSS_BYTE0_CLK>,<&gcc GCC_MDSS_PCLK0_CLK>,<&gcc GCC_MDSS_ESC0_CLK>;};};// 弄掉高通的mipi驱动和gpu驱动 把mdss和gpu有关的节点都设为disabled

至此,我们的bootloader便可以丢掉一大波多余的内核模块了~

魔改jumpdriver

​ jumpdriver是postmarketos社区和danct12大佬弄出来的一个给pinephone刷机的小型linux系统,仅仅只带了一个busybox,用于把内置的emmc挂载成电脑u盘。buildroot对于这种简单用途来说显然是太肥了,所以我魔改了jumpdriver,让它能够在msm8916的机器上运行,带有kexec-tools和kexecboot等必要的软件,作为kexec bootloader的主体部分,执行例如扫描硬盘和开始kexec的操作。(kexec-tools暂时还用不了libz,所以还不支持以gz压缩的内核镜像)

DragonRoot

修改kexecboot

​ kexecboot是一个很老的项目,不太著名的项目maemo leste的driod4移植就是使用的kexecboot,这个应用程序能够自动挂载各种格式的分区然后在分区里面寻找包含引导项的配置文件,再通过配置文件作为kexec的参数执行kexec引导新的内核。

​ 但是在archlinux gcc版本升级到了11,引入了一些稀奇古怪的特性,比如说不能在多个c文件里声明同一个名字的公有变量,这使得kexecboot在arch里面编译不过去了。稍微修了一波,可以完美编译了,我也尝试着向kexecboot项目pull request了,但是估计是我太菜这个pull request一直就没接受~~

​ 如有需要的话可以使用我的fork

能运行,但没完全运行~

kexec-hardboot ?

​ 捣鼓出来能够boot到kexecboot阶段的bootloader以后,它能够正确挂载sd卡和emmc,正确加载里面的文件,但是没有办法引导新的内核,主要是由于kexec没有办法重置cpu核心,内核一直都在报cpus are stuck in the kernel的错误。看了下相关的代码这也许是由于缺少psci功能的trustzone firmware导致的,试着把dragonboard 410c的trustzone刷到红米2里面,结果红米2的分区太小刷不进去。只能去寻找另一个方法 kexec-hardboot。

Kexec-hardboot patch adds a real device restart to that process, so that all the drivers can be properly reinitialized. It stores new kernel to RAM, reboots the device as usual, and kernel from boot partition immediately jumps to the one which was stored to RAM before reboot.

​ 这个办法是在nexus5时代著名的MultiROM所采用的,它在整个kexec过程中加入了重启,确保整个硬件在新内核中能够正确的被初始化,看了下红米2早就有MultiRom支持了,这个要对主线内核和kexec-tools做一些修改,限于时间问题也只能作罢。

U-boot 支持

如果想实现像传统arm linux的那种引导方式又不想在整个引导环境中引入更多的环节,也可以使用u-boot来代替lk2nd的工作。一个印度老哥做了一个移植,试了一下用串口可以正常操作uboot终端,但是屏幕是不工作的,而且在archlinux上编译的u-boot启动不了。这个移植现在可以正确的为主线内核配置mac地址,但是好像不能给主线内核传电池配置和mipi panel相关的参数,有时间我在修一下这个方案,感觉比kexecboot的那个更麻烦一点。
U-boot-wt88047项目

效果展示

看B站

mesa的3d测试

python+opencv+usb摄像头测试

支持自动翻转屏幕

搜狗输入法(工作不正常而且会破坏屏幕键盘的一些功能)

关于DragonPi项目

​ 为了探索高通骁龙手机的主线内核类似树莓派的玩法,我创建了DragonPi项目。未来主要会放出一些linux发行版的构建系统源码(buildroot、armbian)和一些bootloader实现还有内核源码,目前的计划是专心做好红米2的主线方案,跑通尽可能多的外设,为大家带来便宜又好玩的硬件,觉得我这个项目对你有所帮助的话,你也可以资助我们的项目,让它变得更好!

DragonPi项目

刷机包下载

自己DIY一个pinephone——debian与主线linux在红米2(msm8916)上的移植 (二)相关推荐

  1. mobian与主线linux在红米5plus(vince)上的移植 (1) 编译lk2nd以及主线内核的调试

    1.编译lk2nd 什么是lk2nd? lk2nd是一个在高通MSM设备上面运行的bootloader, 基于 CodeAurora Little Kernel fork. 它提供了一个可定制化fas ...

  2. 轻量级linux iso,antiX 17.2 发布,基于Debian的轻量级Linux发行版

    antiX是一个基于Debian的轻量级Linux发行版. antiX项目发布了一个小更新,antiX 17.2,其中包括17.x系列的各种更新和错误修复. antiX-17.2(Helen Kell ...

  3. linux导出文件夹到u盘,把Linux系统放在U盘上直接在U盘上运行Linux

    Linux以它的高效和灵活的特性深受着某些用户的喜爱,但是又不方便平时操作的习惯,如果用户不想在电脑上安装Linux系统,又想使用Linux系统的话,这里教大家一个好方法,把Linux系统放在U盘上, ...

  4. 无需Docker, 5分钟徒手DIY 一个Linux容器

    容器技术,其优势以及应用场景想必大家都不陌生.本文旨在用DIY一个简陋的Linux容器作为例子,让感兴趣的同学大致体会容器是如何建成的. 什么是容器? 提到容器最容易想到的大概就是Docker了, 然 ...

  5. 记一个老年机的逆向工程与主线linux移植 (二)—— 主线内核和postmarketOS

    现在,这台手机已经有了一个可以调试的Bootloader.接下来可以去搜索以下其他大佬有没有什么现有的成果,免得做许多无用功. Linux Mailing List就是一个不错的地方,这里聚集着很多提 ...

  6. 荔枝派zero运行linux,荔枝派Zero: 5分钟DIY一个迷你笔记本电脑

    本文演示了使用荔枝派Zero的RGB LCD 接口快速DIY一个掌上笔记本电脑的例子,展示了Zero实现掌上人机交互设备的便利性. 除此之外,荔枝派Zero还具有MIPI摄像头接口,可用于机器视觉识别 ...

  7. 如何 DIY 一个自己的 NAS

    我一直有个想法:等毕业后租房子后,淘一些二手服务器.交换机.机架,自己在家里搞一个私有云,私有云需要准备一些文件存储服务器,用于支持 KVM 热迁移或者是自己的一些数据备份. NAS 是啥 NAS ( ...

  8. CentOS、Ubuntu、Debian三个linux比较异同

    Linux有非常多的发行版本,从性质上划分,大体分为由商业公司维护的商业版本与由开源社区维护的免费发行版本. 商业版本以Redhat为代表,开源社区版本则以debian为代表.这些版本各有不同的特点, ...

  9. DIY一个基于树莓派和Python的无人机视觉跟踪系统

    DIY一个基于树莓派和Python的无人机视觉跟踪系统 无人机通过图传将航拍到的图像存储并实时传送回地面站几乎已经是标配.如果想来点高级的--在无人机上直接处理拍摄的图像并实现自动控制要怎么实现呢?其 ...

  10. Alpine 操作系统是一个面向安全的轻型 Linux 发行版

    Alpine 操作系统是一个面向安全的轻型 Linux 发行版.它不同于通常 Linux 发行版,Alpine 采用了 musl libc 和 busybox 以减小系统的体积和运行时资源消耗,但功能 ...

最新文章

  1. 量子计算机不会“秒杀”经典计算机
  2. Android本地视频播放器开发--视频解码
  3. 多个独立的forEach循环, 内部处理条件是一样,代码优化方案
  4. python中的垃圾回收机制_python里面的垃圾回收机制
  5. OSPF——多区域概念及配置、ABR简介、ASBR简介、路由重分发
  6. GPU 加速数据科学乘风破浪
  7. Unicode 子集 数量统计
  8. 必备电子技术经典资料汇总:基础入门篇1.6G
  9. HYPERLEDGER FABRIC网络搭建之network e2ecli_default not found
  10. 基于Xlinx的时序分析与约束(1)----什么是时序分析?什么是时序约束?什么又是时序收敛?
  11. java 输入一个时间,获取当前周的周一以及周五时间【自然周】
  12. 36周岁这年,我终于知道该怎么活了!
  13. 安装ie9提示未能完成安装_win7系统安装Ie提示“Internet explorer未能完成安装”的解决方法...
  14. Ubuntu与开发板上的NFS安装与使用
  15. Linux学习(五):挂载新的硬盘
  16. 《赠卫八处士》 作者:杜甫
  17. 数字后端基本概念介绍Tie cell
  18. 怎样修复计算机系统软件,电脑驱动程序损坏怎么快速修复
  19. 地震见真情【汶川地震后巴基斯坦全国帐篷都给了中国】
  20. 【转】推荐五款支持外链的免费网盘

热门文章

  1. 计算机注册表命令,注册表命令,小编教你电脑怎么打开注册表编辑器
  2. RocketMQ消息存储学习
  3. 人工智能对《权力的游戏》大结局预测 | 广东省智能创新协会
  4. java题目练习笔记,java 20道、数量关系8道、判断推理8道、智力题8道
  5. Python爬虫系列之某了么h5签名sign算法
  6. linux识别硬盘时显示gpt,Ubuntu不识别GPT硬盘已有系统的解决方案
  7. r语言数据变量分段_R语言之数据汇总
  8. 集成融云RongCloud视频通话功能PC端
  9. ubuntu无法清空回收站解决办法
  10. 设置Android应用全屏显示(隐藏手机状态栏)