我的4g网卡运行着GNU/Linux -- 某4g无线网卡的逆向工程与主线Linux移植 (二)_lk2nd-程序员宅基地

技术标签: kernel  linux  内核  移植  

修改lk2nd

观察lk2nd现有的设备树,和一部分实现,发现lk2nd的设备树其实也并不是只用于原装bootloader识别,大佬们也实现了设备树中的按键定义在系统中的注册。
查看littlekernel中进入fastboot的逻辑,不难发现除了音量下键可以作为进入fastboot的事件,home和返回键也可以作为进入fastboot的条件之一。

在app/aboot/aboot.c中

	if (!boot_into_fastboot)
 {
    
 	if (keys_get_state(KEY_VOLUMEUP))
 		boot_into_recovery = 1;
 	if (!boot_into_recovery &&
 		(keys_get_state(KEY_HOME) || keys_get_state(KEY_BACK) || keys_get_state(KEY_VOLUMEDOWN)))
 		boot_into_fastboot = true;
 }

整个按键的初始化在lk2nd中加入了通过设备树初始化的部分,通过读取lk2nd,keys属性来完成。
在lk2nd/lk2nd-device.c中

static struct lk2nd_keymap* lk2nd_parse_keys(const void *fdt, int offset)
{
    
	int len;
	const uint32_t *val;
	struct lk2nd_keymap *map = NULL;

#define KEY_SIZE (3 * sizeof(uint32_t))
	int i = 0;
	val = fdt_getprop(fdt, offset, "lk2nd,keys", &len);
	if (len > 0 && len % KEY_SIZE == 0) {
    
		len /= KEY_SIZE;
		/* last element indicates end of the array with key=0 */
		map = calloc(len + 1, sizeof(struct lk2nd_keymap));
		for (int i = 0; i < len; i++) {
    
			map[i].key    = fdt32_to_cpu(val[i*3]);
			map[i].gpio   = fdt32_to_cpu(val[i*3 + 1]) & 0xFFFF;
			map[i].type   = fdt32_to_cpu(val[i*3 + 1]) >> 16;
			map[i].pull   = fdt32_to_cpu(val[i*3 + 2]) & 0xFF;
			map[i].active = fdt32_to_cpu(val[i*3 + 2]) >> 8;
		}
	}

	dprintf(INFO, "Device keymap:\n");
	while (map && map[i].key) {
    
		dprintf(INFO, "key=0x%X, gpio=%x, type=%d, pull=%d, active=%d\n",
			map[i].key, map[i].gpio, map[i].type, map[i].pull, map[i].active);
		i++;
	}

	return map;
}

其实实现edl按键进入fastboot的思路就已经很清晰了,就是在设备树中加一条定义就行,把gpio37注册成为home按键。
最终的设备树代码如下所示

// SPDX-License-Identifier: GPL-2.0-only
// Copyright (C) 2021 HandsomeYingyan <[email protected]>

/dts-v1/;

#include <skeleton.dtsi>
#include <lk2nd.h>

/ {
    
	model = "Handsome Stick";
	compatible = "handsome,stick", "qcom,msm8916", "lk2nd,device";
	qcom,msm-id = <0xce 0x00 0xf8 0x00 0xf9 0x00 0xfa 0x00>;
	qcom,board-id = <0x08 0x100>;
	lk2nd,keys = <KEY_HOME 37 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
};

刷入boot分区测试,完美触发!在测试的时候发现fastboot烧写boot.img采用的不是先擦除再烧写,而是覆盖的方式。如果lk2nd有问题,安卓内核就会一直重启,进不到原来的bootloader的fastboot模式。
解决的方法也很简单,使用edl工具在edl模式下擦除boot分区就行。

$ edl e boot

第一次执行可能会卡住,直接中断马上再执行相同指令,就完成了boot分区的擦除。
但是,一个好用的bootloader还需要能够知道设备的启动状态,由于安卓的默认灯也是红色。我定义bootloader一开始亮起的灯为蓝灯,最终对代码的修改如下。
加入对wifi三个led灯和edl按键 gpio号的宏定义
target/msm8916/init.c

#define TLMM_EDL_BTN_GPIO    37
#define TLMM_USR_BLUE_LED_GPIO  20
#define TLMM_USR_GREEN_LED_GPIO  21
#define TLMM_USR_RED_LED_GPIO  22 /* UNUSED */

在target_init()中加入gpio初始化语句

 gpio_tlmm_config(TLMM_USR_BLUE_LED_GPIO, 0, 
 GPIO_OUTPUT,GPIO_PULL_UP, GPIO_2MA, GPIO_ENABLE);

这样lk2nd基本上就起来了,能够启动原来的安卓内核和按edl按键进入fastboot模式,让免拆刷机成为可能,唯一不好的地方就是按edl键的时间必须要准,太早就直接进edl模式了,太慢就直接进内核了。

lk1st yes!

lk2nd 的存在使得在整个引导过程中多了一层来传递主线内核需要的参数,拖慢了启动的速度。所以在最终的版本中lk2nd只用于提取原来的modem和wifi的校准数据,而设备引导由这套代码生成的lk1st完成。
lk作为aboot,许多设备树相关的东西就用不了了。也就是说前面那个设备树定义的按键在lk1st下是没有用的,必须通过自己注册按键的方式来实现。
由于这个板子上是有fb(fastboot)触点的,不想破坏原来的fastboot键功能,这里仍然将按键注册为home键。为了方便调试我还加了一个行为,进入fastboot后绿灯亮起。

target/msm8916/init.c

/* HACK : treat edl btn as home btn */
int target_home()
{
    
        static uint8_t first_time = 0;
	    uint8_t status = 0;
        if (!first_time) {
    
            	    gpio_tlmm_config(TLMM_EDL_BTN_GPIO, 0, GPIO_INPUT, GPIO_PULL_DOWN, GPIO_2MA, GPIO_ENABLE);
	    /* Wait for the gpio config to take effect - debounce time */
	    udelay(10000);
            first_time = 1;
        }
	/* Get status of GPIO */
	status = gpio_status(TLMM_VOL_UP_BTN_GPIO);
	/* light up green led when edl btn is pressed*/
	if(status == 1) {
    
	   gpio_tlmm_config(TLMM_USR_GREEN_LED_GPIO, 0, GPIO_OUTPUT,GPIO_PULL_UP, GPIO_2MA, GPIO_ENABLE);
	}
	/* Active high signal. */
	return status;
}

向系统注册按键

 #if WITH_LK2ND
 uint32_t target_volume_down_old()
 #else
@@ -217,6 +255,10 @@ static void target_keystatus()
 
 	if(target_volume_up())
 		keys_post_event(KEY_VOLUMEUP, 1);
+
+	if(target_home())
+		keys_post_event(KEY_HOME, 1);
+
 }
 #endif

代码就修改完成了,接下来就是编译之后烧写到设备里,但是不能直接将产物进行烧写,还需对其进行签名。这里我使用的是qtestsign工具,它的简介以及十分详细,这里就不再赘述了。

烧写之后,lk完美运行,接下来就是主线linux的移植了!
在这里插入图片描述
fastboot模式
在这里插入图片描述

移植主线Linux

为了验证主线linux内核是否能够在这个设备上启动先使用我之前在红米2上弄的一个用于kexec的dragonroot 来试试。
果不其然,运行不了。在预料之外的是内核压根跳转不了,littlekernel报了一个关于scm的错然后直接重启。换成原厂的bootloader错误依旧。
error

稍微查了一下发现是trustzone固件的问题,貌似这个板子自带的trustzone固件用不了64位的内核,这也就是为什么lk2nd用的了而linux内核却不行的原因。lk2nd默认是以arm32的形式编译的。
尝试使用dragonboard的trustzone固件,但是分区太小刷不进去。
反正也到这里了,只能重新分区了。备份modem和wifi数据后刷入dragonboard的分区表,再把dragonboard的那一套固件刷进去,再次尝试刷入dragonroot,主线内核轻松跑起来了!
it boots!
接下来的工作相对来说就比较简单了,东拼西凑弄了个可以使用的设备树,大体上内核部分也就完美了。重新组装下postmarketos的boot.img,直接使用红米2的rootfs,大体上就完美了。

postmarketos

PostmarketOS 使用体验

运行了一天,稳定性还是不错的,发热量也不是很大(空载状态下运行手摸接近室温)
内存很充裕,但是emmc太小了(好像只有2个多G可用)
neofetch

得益于postmarketos基于的alpine linux轻量级的特点,资源占用也不是很高。
htop

当然,wifi、蓝牙、modem也是工作的。但是modem没有卡试,也没激活商家提供的卡,只知道可以认出运营商,即使有问题,问题也不是很大。gps、gpu和硬件解码器能识别出,应该问题也不大。

wifi
蓝牙

modem
在刷入hyp虚拟化firmware之后,kvm也可以使用了。

kvm
硬件上的所有功能应该是压榨干净了,但是还没完全干净。

WHY?

作为一个高级路由器,一个host模式usb不应该是基本要求吗?
根据常识不难设计出转换的板子,两个usb母口电源线并联,用一个mircousb供电,数据线分别相连就行。
在这里插入图片描述

在这里插入图片描述
图

但是这个usb默认工作在slave模式下,厂家也没设计io口作为usb
的id引脚,只能通过手动的方式切换usb模式。
查找一番后发现可以通过sysfs切换,这就很nice了。

   $ sudo -s
   $ echo host > /sys/kernel/debug/usb/ci_hdrc.0/role

芜湖!成功认出了我插入的USB鼠标。
在这里插入图片描述
u盘也是没有问题的。
在这里插入图片描述

这下离线下载、打印服务器之类的玩法实现也比较轻松了。至此,一个非常廉价、性能还可以的arm64单板电脑就诞生了。

这个板子唯一的遗憾就是emmc太小了,要是有sd卡槽,基本上就无敌了。
缺一个好用的系统,就完美了。

Openwrt ?

这个比较复杂。其一是没有任何openwrt设备的soc是自带modem的,usb modem很久以前就支持了,但是不确定modem能不能驱动。其二是msm8916没有被官方支持,而且内核是安卓格式的,必须对生成镜像的过程进行修改,加一些构建工具。还要backport msm8916-mainline主线内核里的一些修改到稳定版内核。

另外openwrt还没有管理usb slave(gadget)模式的工具。我的目标不仅仅是让usb实现网卡的功能,还要实现串口、adb、磁盘挂载等一些其他的功能。这可能要自己造轮子了。

其实研究红米2的时候就在我的openwrt fork – HandsomeMod 里我已经做了一些尝试了,能够进入shell,但是硬件还没有完全跑起来。

但是这是迟早的事情,谁叫你配置这么高又卖的这么便宜呢,哈哈~~

源代码及帮助

目前lk linux 和一部分二进制的包已经开源到github上。
WIKI里也记录了许许多多的玩法。
感兴趣的老哥自取
OpenStick主页
OpenStick WIKI

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/github_38345754/article/details/121481021

智能推荐

python 转盘 圆形,用python实现一个转盘-程序员宅基地

文章浏览阅读579次。用python实现一个转盘发布时间:2019-09-22 08:09:12编辑:auto阅读(624)#抽奖 面向对象版本import tkinterimport timeimport threadingclass choujiang:#初始化魔术方法def __init__(self):#准备好界面self.root = tkinter.Tk()self.root.title('lowB版转盘..._越转越快的圆形python代码

Kali系统上安装配置GVM(OpenVAS)V21.4_找不到命令 “gvm-setpu”,您的意思是: “gvm-setup” 命令来自 debian 软-程序员宅基地

文章浏览阅读2k次。一、kali-linux系统准备工作: 1、kali 系统下载地址【https://www.kali.org/get-kali/】,我直接选择VMware虚拟机。2、kali系统更新: a、更改下更新源为阿里、清华等源地址:vim /etc/apt/source.list 文本内容如下:#aliyun 阿里云deb http://mirrors.aliyun.com/kali kali-rolling main non-f..._找不到命令 “gvm-setpu”,您的意思是: “gvm-setup” 命令来自 debian 软件包 gv

【花雕动手做】ASRPRO-Plus语音识别(03)---板载硬件模块和12项综合应用功能_asrpro语音模块-程序员宅基地

文章浏览阅读2k次,点赞2次,收藏4次。2、离线语音识别模块:搭载ASRPRO核心板,内置脑神经网络处理器,支持DNN、TDNN、RNN等神经网络及卷积运算硬件运算,非软件运算,支持语音识别、声纹识别、语音增强、语音检测等功能。4、更新和维护:随着技术的不断发展和用户需求的变化,可能需要更新屏幕固件或更换更先进的屏幕,开发者应定期检查更新并采取必要的维护措施,以确保设备的正常运行和使用效果。1、语音增强:ASRPRO-Plus采用一系列先进的数字信号处理技术,对输入的语音信号进行降噪、回声消除、增益控制等处理,以提高语音信号的清晰度和可懂度。_asrpro语音模块

QT radioButton_qt ui界面buttongroup-程序员宅基地

文章浏览阅读332次。【代码】QT radioButton。_qt ui界面buttongroup

wsl2 kali 安装报错 WslRegisterDistribution failed with error: 0x80004005-程序员宅基地

文章浏览阅读5.5k次,点赞13次,收藏13次。修改注册表解决 wsl2 kali 安装报错 0x80004005_wslregisterdistribution failed with error: 0x80004005

HTML元素随滚动条滚动-程序员宅基地

文章浏览阅读1.4k次。比较常见的是一个Div层随滚动条滚动,使Div层位置相对于可视区域不变,其实质就是当滚动条位置改变后,重新定位层的位置。网上有不少的例子,总的思路可以分为两类:1.CSS样式定位。不同的浏览器及其版本,实现稍有不同。这种方式是利用CSS的expression特性,通过执行绑定的一个计算坐标位置的js表达式,把结果设置为层的坐标值,最终实现Div层位置的滚动。2.Javascript定位。使..._html页面内容随着滚轮

随便推点

探索GitHub CSV工具:高效数据处理的新选择-程序员宅基地

文章浏览阅读901次,点赞12次,收藏17次。探索GitHub CSV工具:高效数据处理的新选择项目地址:https://gitcode.com/gavinr/github-csv-tools项目简介在大数据时代,CSV文件作为通用的数据交换格式,始终扮演着重要角色。GitHub CSV Tools 是一个专为开发者和数据分析师打造的轻量级命令行工具集,它旨在简化CSV文件的读取、解析、过滤、转换及合并等任务。该项目完全开源,并提供易...

Unity开发移动端相机的优缺点分析_unity 相机多了会有坏处吗-程序员宅基地

文章浏览阅读7.2k次。它对相机硬件不是太“了解” 用它的API,3000块钱的手机和500块钱的手机的拍照效果相差不大。造成这种差异的原因是,unity的相机方面的API,他没有获取相机参数的方式,对于相机的硬件设备,它只是单方面的要求,没有互动,它的模式是,我需要什么样的图片,那么我就要求相机返回什么样的图片给我,而不关心它是否真的能有能力返回给我。通俗的讲就是,在它看来,哈士奇和泰迪都是狗,它们没有任何区别。_unity 相机多了会有坏处吗

快速集成iOS基于RTMP的视频推流-程序员宅基地

文章浏览阅读56次。来源:Monkey_ALin链接:http://www.jianshu.com/p/8ea016b2720e效果图iTools有点卡, 但是推到服务器倒是很快的.推流前言这篇blog是iOS视频直播初窥:的一个补充. 因为之前传到github上的项目中没有集成视频的推流.有很多朋友简信和微博上问我..._ios rtmp 推流demo

Flutter组件--Slivers的基本使用_sliverfixedextentlist-程序员宅基地

文章浏览阅读839次。我们考虑一个这样的布局:一个滑动的视图中包括一个标题视图(HeaderView),一个列表视图(ListView),一个网格视图(GridView)。我们怎么可以让它们做到统一的滑动效果呢?使用前面的滚动是很难做到的。Flutter中有一个可以完成这样滚动效果的Widget:CustomScrollView,可以统一管理多个滚动视图。在CustomScrollView中,每一个独立的,可滚动的Widget被称之为Sliver。_sliverfixedextentlist

View 事件传递,分发与拦截_view 事件包含阻止传递-程序员宅基地

文章浏览阅读336次。目录[-]1、基础知识2、传递流程1、基础知识(1) 所有 Touch 事件都被封装成了 MotionEvent 对象,包括 Touch 的位置、时间、历史记录以及第几个手指(多指触摸)等。(2) 事件类型分为 ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POI_view 事件包含阻止传递

[爬虫]爬取搜狗的词库-程序员宅基地

文章浏览阅读277次。同学要做用户搜索词意图分析,要用到分词,让我给写一个爬虫爬取搜狗词库的脚本。以前爬取网页都使用正则匹配,想要用美丽的汤很久了,正好借此机会体验一下它的强大威力。脚本对搜狗词库主页进行一级爬取结果,然后对每一个分类进行二级页面爬取,然后获取该分类下的词库文件,保存到执行脚本同目录的1文件夹下。python还是新手一个,要是对有帮助的同学尽管拿去。#coding=utf-8'''Created..._c# 爬取搜狗词库

推荐文章

热门文章

相关标签