这里有个标题会比较厉害
pine64出品了一个基于全志a64的soc全开源手机,搜了下某宝竟然要接近2000大洋,即使几年前的高通的处理器的性能都可以完爆全志了,搞一个可以运行“正常”linux的高通手机应该还是蛮有意思的。
目前以主线linux为主的比较大规模的linux移动发行版就只有postmarketos,做的真的还可以,用python写的部署工具(pmbootstrap)能够做到一个工具构建文件系统和烧录,但是postmarketos基于的发行版Alpine Linux的软件包都是用musl的c库编译的,musl虽然可以显著降低程序的体积,但是相较于glibc缺很多东西,例如locale的支持、基于electron的程序也跑不了,so要弄一个能用着爽的手机还是要自己动手。。。
目前高通主线支持最好的是msm8916,而这个soc对应小米产品的是红米2,也是咸鱼上比较容易弄到的手机之一,在postmarket os上这个手机也有支持。基本上除了摄像头和充电、otg都驱动了。
和msm8916用的芯片比较相似的开发板是dragonboard 410c,linaro至今都还在更新它的系统,gpu、解码器都有比较新的firmware。又根据postmarketos wiki中得知msm8916的有些机型没有开启secure boot,开启secure boot之后就意味着soc将拒绝加载没有签名的firmware,很幸运红米2没有开启secure boot,这代表着我们可以使用dragonboard的新firmware,拥有更高的可玩性。
但是困难也是有的,一是小米原来的lk并不支持主线带设备树内核的启动,postermarketos给出的方案是用原来的lk去引导另一个魔改过支持主线linux的lk,二是lk初始化好的framebuffer并不能给linux内核,所以在高通的drm起来之前有一段时间手机是没有显示的,需要焊接出串口才能进行调试。没有u-boot之类的东西,对比较菜的我也还是个挑战。
不过最后还是完成了大部分的移植。但是modem没有起来,所以声音是没有的。不知什么原因,mmc0的设备号会变成mmc1,所以rootfs会随机挂载不起来。rootfs用的是基于debian bulleye的mobian,玩apt贼香😎。
硬改调试串口
高通的安卓内核关掉了串口输出,lk也不支持用串口输入指令,所以唯一能够测试硬改是否有效的办法就是刷个postmarketos,pmbootstrap在pip和aur里都有,安装一个并不是很费劲。还有就是准备一个lk2nd,通过原厂的fastboot安装到boot分区。在开机第一次震动后再按一下下音量键就可以进到lk2nd了。
# 安装lk2nd
fastboot flash boot lk2nd.img
# 安装postmarket os
pmbootstrap init
pmbootstrap install
# 插入在lk2nd状态下的手机
pmbootstrap flasher flash_kernel
pmbootstrap flasher flash_rootfs --partition userdata
然后就可以进到postmarketos
点位图找到tx 和 rx
在某些手机维修论坛里可以找到手机的维修点位图,找到uart测试点。
红米2的uart 就在后摄像头的旁边
焊接。。。注意这个改造可能会使emmc的稳定性下降,在没有插usb-ttl的情况下会导致内核崩溃,或者initramfs挂不上文件系统。在调试完毕后应该改回来。。
默认的波特率为115200~
软件部分
调试内核
在postmarketos的git上把机型的内核配置文件拉下来,然后使用修改后的halium检测内核选项的脚本处理一下,把systemd启动需要的东西开了。修改后的脚本就放这里了。
check-kernel-config <你的配置文件> -w
#!/bin/bash
FILE=$1
[ -f "$FILE" ] || {
echo "Provide a config file as argument"
exit
}
write=false
if [ "$2" = "-w" ]; then
write=true
fi
CONFIGS_ON="
CONFIG_IKCONFIG
CONFIG_CPUSETS
CONFIG_AUTOFS4_FS
CONFIG_TMPFS_XATTR
CONFIG_TMPFS_POSIX_ACL
CONFIG_CGROUP_DEVICE
CONFIG_CGROUP_MEM_RES_CTLR
CONFIG_CGROUP_MEM_RES_CTLR_SWAP
CONFIG_CGROUP_MEM_RES_CTLR_KMEM
CONFIG_RTC_DRV_CMOS
CONFIG_BLK_CGROUP
CONFIG_CGROUP_PERF
CONFIG_IKCONFIG_PROC
CONFIG_SYSVIPC
CONFIG_CGROUPS
CONFIG_CGROUP_FREEZER
CONFIG_NAMESPACES
CONFIG_UTS_NS
CONFIG_IPC_NS
CONFIG_USER_NS
CONFIG_PID_NS
CONFIG_NET_NS
CONFIG_AUDIT
CONFIG_AUDITSYSCALL
CONFIG_AUDIT_TREE
CONFIG_AUDIT_WATCH
CONFIG_CC_STACKPROTECTOR
CONFIG_DEBUG_RODATA
CONFIG_DEVTMPFS
CONFIG_DEVTMPFS_MOUNT
CONFIG_DEVPTS_MULTIPLE_INSTANCES
CONFIG_ECRYPT_FS
CONFIG_ECRYPT_FS_MESSAGING
CONFIG_ENCRYPTED_KEYS
CONFIG_EXT4_FS_POSIX_ACL
CONFIG_EXT4_FS_SECURITY
CONFIG_FSNOTIFY
CONFIG_DNOTIFY
CONFIG_INOTIFY_USER
CONFIG_FANOTIFY
CONFIG_FANOTIFY_ACCESS_PERMISSIONS
CONFIG_KEYS
CONFIG_SWAP
CONFIG_VT
CONFIG_VT_CONSOLE
CONFIG_SECCOMP
CONFIG_STRICT_DEVMEM
CONFIG_SYN_COOKIES
CONFIG_BT
CONFIG_BT_RFCOMM
CONFIG_BT_RFCOMM_TTY
CONFIG_BT_BNEP
CONFIG_BT_BNEP_MC_FILTER
CONFIG_BT_BNEP_PROTO_FILTER
CONFIG_BT_HIDP
CONFIG_XFRM_USER
CONFIG_NET_KEY
CONFIG_INET
CONFIG_IP_ADVANCED_ROUTER
CONFIG_IP_MULTIPLE_TABLES
CONFIG_INET_AH
CONFIG_INET_ESP
CONFIG_INET_IPCOMP
CONFIG_INET_XFRM_MODE_TRANSPORT
CONFIG_INET_XFRM_MODE_TUNNEL
CONFIG_INET_XFRM_MODE_BEET
CONFIG_IPV6
CONFIG_INET6_AH
CONFIG_INET6_ESP
CONFIG_INET6_IPCOMP
CONFIG_INET6_XFRM_MODE_TRANSPORT
CONFIG_INET6_XFRM_MODE_TUNNEL
CONFIG_INET6_XFRM_MODE_BEET
CONFIG_IPV6_MULTIPLE_TABLES
CONFIG_NETFILTER
CONFIG_NETFILTER_ADVANCED
CONFIG_NETFILTER_NETLINK
CONFIG_NETFILTER_NETLINK_ACCT
CONFIG_NETFILTER_NETLINK_LOG
CONFIG_NETFILTER_NETLINK_QUEUE
CONFIG_NETFILTER_TPROXY
CONFIG_NETFILTER_XTABLES
CONFIG_NETFILTER_XT_CONNMARK
CONFIG_NETFILTER_XT_MARK
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE
CONFIG_NETFILTER_XT_MATCH_CLUSTER
CONFIG_NETFILTER_XT_MATCH_COMMENT
CONFIG_NETFILTER_XT_MATCH_CONNBYTES
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT
CONFIG_NETFILTER_XT_MATCH_CONNMARK
CONFIG_NETFILTER_XT_MATCH_CONNTRACK
CONFIG_NETFILTER_XT_MATCH_CPU
CONFIG_NETFILTER_XT_MATCH_DCCP
CONFIG_NETFILTER_XT_MATCH_DEVGROUP
CONFIG_NETFILTER_XT_MATCH_DSCP
CONFIG_NETFILTER_XT_MATCH_ECN
CONFIG_NETFILTER_XT_MATCH_ESP
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT
CONFIG_NETFILTER_XT_MATCH_HELPER
CONFIG_NETFILTER_XT_MATCH_HL
CONFIG_NETFILTER_XT_MATCH_IPRANGE
CONFIG_NETFILTER_XT_MATCH_LENGTH
CONFIG_NETFILTER_XT_MATCH_LIMIT
CONFIG_NETFILTER_XT_MATCH_MAC
CONFIG_NETFILTER_XT_MATCH_MARK
CONFIG_NETFILTER_XT_MATCH_MULTIPORT
CONFIG_NETFILTER_XT_MATCH_NFACCT
CONFIG_NETFILTER_XT_MATCH_OSF
CONFIG_NETFILTER_XT_MATCH_OWNER
CONFIG_NETFILTER_XT_MATCH_PKTTYPE
CONFIG_NETFILTER_XT_MATCH_POLICY
CONFIG_NETFILTER_XT_MATCH_QUOTA
CONFIG_NETFILTER_XT_MATCH_QUOTA2
CONFIG_NETFILTER_XT_MATCH_RATEEST
CONFIG_NETFILTER_XT_MATCH_REALM
CONFIG_NETFILTER_XT_MATCH_RECENT
CONFIG_NETFILTER_XT_MATCH_SCTP
CONFIG_NETFILTER_XT_MATCH_SOCKET
CONFIG_NETFILTER_XT_MATCH_STATE
CONFIG_NETFILTER_XT_MATCH_STATISTIC
CONFIG_NETFILTER_XT_MATCH_STRING
CONFIG_NETFILTER_XT_MATCH_TCPMSS
CONFIG_NETFILTER_XT_MATCH_TIME
CONFIG_NETFILTER_XT_MATCH_U32
CONFIG_NETFILTER_XT_TARGET_AUDIT
CONFIG_NETFILTER_XT_TARGET_CHECKSUM
CONFIG_NETFILTER_XT_TARGET_CLASSIFY
CONFIG_NETFILTER_XT_TARGET_CONNMARK
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK
CONFIG_NETFILTER_XT_TARGET_CT
CONFIG_NETFILTER_XT_TARGET_DSCP
CONFIG_NETFILTER_XT_TARGET_HL
CONFIG_NETFILTER_XT_TARGET_IDLETIMER
CONFIG_NETFILTER_XT_TARGET_LED
CONFIG_NETFILTER_XT_TARGET_LOG
CONFIG_NETFILTER_XT_TARGET_MARK
CONFIG_NETFILTER_XT_TARGET_NFLOG
CONFIG_NETFILTER_XT_TARGET_NFQUEUE
CONFIG_NETFILTER_XT_TARGET_NOTRACK
CONFIG_NETFILTER_XT_TARGET_RATEEST
CONFIG_NETFILTER_XT_TARGET_SECMARK
CONFIG_NETFILTER_XT_TARGET_TCPMSS
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP
CONFIG_NETFILTER_XT_TARGET_TEE
CONFIG_NETFILTER_XT_TARGET_TPROXY
CONFIG_NETFILTER_XT_TARGET_TRACE
CONFIG_NF_CONNTRACK_ZONES
CONFIG_IP6_NF_FILTER
CONFIG_IP6_NF_IPTABLES
CONFIG_IP6_NF_MANGLE
CONFIG_IP6_NF_MATCH_AH
CONFIG_IP6_NF_MATCH_EUI64
CONFIG_IP6_NF_MATCH_FRAG
CONFIG_IP6_NF_MATCH_HL
CONFIG_IP6_NF_MATCH_IPV6HEADER
CONFIG_IP6_NF_MATCH_MH
CONFIG_IP6_NF_MATCH_OPTS
CONFIG_IP6_NF_MATCH_RPFILTER
CONFIG_IP6_NF_MATCH_RT
CONFIG_IP6_NF_QUEUE
CONFIG_IP6_NF_RAW
CONFIG_IP6_NF_SECURITY
CONFIG_IP6_NF_TARGET_HL
CONFIG_IP6_NF_TARGET_REJECT
CONFIG_IP6_NF_TARGET_REJECT_SKERR
CONFIG_DNS_RESOLVER
CONFIG_IOSCHED_DEADLINE
CONFIG_SUSPEND_TIME
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS
CONFIG_CONSOLE_TRANSLATIONS
CONFIG_EVM
CONFIG_INTEGRITY_SIGNATURE
CONFIG_FHANDLE
CONFIG_EPOLL
CONFIG_SIGNALFD
CONFIG_TIMERFD
CONFIG_TMPFS_POSIX_ACL
"
CONFIGS_OFF="
"
CONFIGS_EQ="
"
ered() {
echo -e "\033[31m" $@
}
egreen() {
echo -e "\033[32m" $@
}
ewhite() {
echo -e "\033[37m" $@
}
echo -e "\n\nChecking config file for Halium specific config options.\n\n"
errors=0
fixes=0
for c in $CONFIGS_ON $CONFIGS_OFF;do
cnt=`grep -w -c $c $FILE`
if [ $cnt -gt 1 ];then
ered "$c appears more than once in the config file, fix this"
errors=$((errors+1))
fi
if [ $cnt -eq 0 ];then
if $write ; then
ewhite "Creating $c"
echo "# $c is not set" >> "$FILE"
fixes=$((fixes+1))
else
ered "$c is neither enabled nor disabled in the config file"
errors=$((errors+1))
fi
fi
done
for c in $CONFIGS_ON;do
if grep "$c=y\|$c=m" "$FILE" >/dev/null;then
egreen "$c is already set"
else
if $write ; then
ewhite "Setting $c"
sed -i "s,# $c is not set,$c=y," "$FILE"
fixes=$((fixes+1))
else
ered "$c is not set, set it"
errors=$((errors+1))
fi
fi
done
for c in $CONFIGS_EQ;do
lhs=$(awk -F= '{ print $1 }' <(echo $c))
rhs=$(awk -F= '{ print $2 }' <(echo $c))
if grep "^$c" "$FILE" >/dev/null;then
egreen "$c is already set correctly."
continue
elif grep "^$lhs" "$FILE" >/dev/null;then
cur=$(awk -F= '{ print $2 }' <(grep "$lhs" "$FILE"))
ered "$lhs is set, but to $cur not $rhs."
if $write ; then
egreen "Setting $c correctly"
sed -i 's,^'"$lhs"'.*,# '"$lhs"' was '"$cur"'\n'"$c"',' "$FILE"
fixes=$((fixes+1))
fi
else
if $write ; then
ewhite "Setting $c"
echo "$c" >> "$FILE"
fixes=$((fixes+1))
else
ered "$c is not set"
errors=$((errors+1))
fi
fi
done
for c in $CONFIGS_OFF;do
if grep "$c=y\|$c=m" "$FILE" >/dev/null;then
if $write ; then
ewhite "Unsetting $c"
sed -i "s,$c=.*,# $c is not set," $FILE
fixes=$((fixes+1))
else
ered "$c is set, unset it"
errors=$((errors+1))
fi
else
egreen "$c is already unset"
fi
done
if [ $errors -eq 0 ];then
egreen "\n\nConfig file checked, found no errors.\n\n"
else
ered "\n\nConfig file checked, found $errors errors that I did not fix.\n\n"
fi
if [ $fixes -gt 0 ];then
egreen "Made $fixes fixes.\n\n"
fi
ewhite " "
拉取并编译内核构建deb安装包(需要用deb安装包生成initramfs)
把修改后的config文件放进来
git clone https://github.com/msm8916-mainline/linux.git --depth=1
cd linux
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
make menuconfig
make -j16
fakeroot make-kpkg --initrd --cross-compile aarch64-linux-gnu- --arch arm64 kernel_image kernel_headers
注意postmarketos的内核模块启用了压缩,生成的ko.gz不能直接被debian加载,要弄掉。
[*] Enable loadable module support --->
[ ] Compress modules on installation
生成的deb软件包会在上层目录出现
配置文件系统
system.img 用的格式是sparse ext4 image,即更小的ext4有多少文件算多少容量,而不是像dd出来的raw一样是整个分区的大小,要生成这样一个img需要img2simg这个工具。
先dd一个raw ext4
dd if=/dev/zero of=rootfs.ext4 bs=1M count=4096
mkfs.ext4 rootfs.ext4
去弄一个pinephone的rootfs,这里我使用的是mobian,应该ubuntu touch也是可以的。
挂载并且释放rootfs里的内容到镜像。然后chroot进去删掉所有的和全志有关的内核和u-boot包
例如linux-image*、linux-headers*、u-boot*一类的
之后安装先前编译好的内核,把/boot文件夹中的initrd.img拿出来备用。
安装dragonboard的wifi和modem的firmware
按照postmarketos里apkbuild的方法
把下载的bsp的mba.mbn modem.* wcnss.* 放到/lib/firmware下
把proprietary-linux/wlan/prima/WCNSS_* 放到/lib/firmware/wlan/prima下
安装这个包来获得gpu和解码器的firmware
之后退出chroot并解除挂载,生成simg。
img2simg rootfs.ext4 system.img
生成boot.img
准备image.gz(在内核源码编译后的arch/arm64/boot文件夹里)、红米2的设备树文件(msm8916-wingtech-wt88047-modem.dtb)、initrd.img放在同一个文件夹下,安装mkbootimg工具。
把设备树文件附在kernel的结尾
cat Image.gz msm8916-wingtech-wt88047-modem.dtb > kernel-dtb
生成boot.img
mkbootimg \
--base 0x80000000 \
--kernel_offset 0x00080000 \
--ramdisk_offset 0x02000000 \
--tags_offset 0x01e00000 \
--pagesize 2048 \
--second_offset 0x00f00000 \
--ramdisk initrd.img \
--cmdline "earlycon console=tty0 console=ttyMSM0,115200 root=/dev/mmcblk0p30 rw "\
--kernel kernel-dtb -o mainline-boot.img
比较坑的一点就是内核没有给rw参数的话文件系统会被挂载为只读
mobian的phosh和networkmanager就会起不来。。。
烧写
就很常规~~
在lk2nd的fastboot下
fastboot flash boot mainline-boot.img
#mobian有点大 使用data分区作为rootfs分区
fastboot flash userdata system.img
启动时会花屏,这是正常现象。。。
有图有真相~