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

这里有个标题会比较厉害

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挂不上文件系统。在调试完毕后应该改回来。。
ttl
默认的波特率为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

启动时会花屏,这是正常现象。。。

有图有真相~

debian启动了
debian+phosh

phosh
apt
看b站~
vscode

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值