linux 基于debian/ubuntu AB系统适配(三)- overlayroot

Overlayroot

Overlayroot是一个实用工具,允许您创建一个只读的根文件系统和一个可写的覆盖文件系统。这对于创建一个更安全和稳定的系统很有用,因为对系统所做的任何更改都将存储在覆盖文件系统中,可以很容易地丢弃或重置。

在Debian下,分离的系统在/userdata/rootfs_overlay下,如:在根文件系统下创建一个111文件夹,实际创建在/userdata/rootfs_overlay下创建的。

这样在切换A/B系统的时候,更新了文件系统就不会影响到用户数据,因为用户数据是在单独的一个分区。但目前种模式只是在但系统上实现,A/B系统没有实现,我们需要进行修改。

uboot

uboot阶段会使用bootargs给内核传overlayroot参数,使内核开启overlayroot
在这里插入图片描述

但启动A/B系统之后会发现,overlayroot参数不见了,导致内核不能开启overlayroot。遂,查找原因。

通过不懈的查找发现,在bootargs中有root参数,该参数指向的就是所要使用的文件系统。如下:

但在启动A/B后,会去修改root这个环境变量,修改为A/B中其中一个文件的UUID,如下:
在这里插入图片描述

问题就出现在这里了,在arch\arm\mach-rockchip\board.c中如果定义了CONFIG_ANDROID_AB则在bootarge中寻找root=,然后删除。问题就出现在这个删除上,因为overlayroot字段里也有root就导致了overlayroot字段也被删除了
在这里插入图片描述

所以这里我们需要进行修改,把root=增加一些字段,使之具有唯一性。修改如下

diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c
index 5c84f3dbfa..9d706b85fa 100644
--- a/arch/arm/mach-rockchip/board.c
+++ b/arch/arm/mach-rockchip/board.c
@@ -1181,7 +1181,7 @@ char *board_fdt_chosen_bootargs(void *fdt)
                 * to cmdline. The format is "roo=PARTUUID=xxxx...".
                 */
 #ifdef CONFIG_ANDROID_AB
-               env_update_filter("bootargs", bootargs, "root=");
+               env_update_filter("bootargs", bootargs, "root=PARTLABEL");
                ab_update_root_partition();
 #else
                env_update("bootargs", bootargs);

在这里插入图片描述

修改编译后发现overlayroot字段还是被删除了,思考后想到root字段删除了但后面还需要补上去的,所以在补上去的时候肯定把overlayroot字段被覆盖了,所以还得找。
在执行了env_update_filter之后又运行了ab_update_root_partition,在函数中又调用了ab_update_root_uuid,该函数就是用作设置root字段。

在该函数可以看到又在查找root=字段,所以这个地方也需要修改。

diff --git a/common/android_ab.c b/common/android_ab.c
index d344a024e9..5df6143fd1 100644
--- a/common/android_ab.c
+++ b/common/android_ab.c
@@ -433,7 +433,7 @@ static void ab_update_root_uuid(void)
        if (ab_is_support_dynamic_partition(dev_desc))
                return;
 
-       if (!strstr(boot_args, "root=")) {
+       if (!strstr(boot_args, "root=PARTUUID")) {
                get_partition_unique_uuid(ANDROID_PARTITION_SYSTEM,
                                          guid_buf, UUID_SIZE);
                strcat(root_partuuid, guid_buf);

在这里插入图片描述

编译后,参数终于正确了
在这里插入图片描述

kernel

修改uboot启动系统后,overlayroot能够顺利建立了,但新的问题又来了,建立的overlayroot文件名称不对,是以分区名称为前缀建立的,如下
在这里插入图片描述

这样会导致切换系统后,用户数据丢失,需要修改,使用mount命令可以看到,,overlayroot挂载在/userdata下,并带有参数:
在这里插入图片描述

lowerdir=/root-ro,  //原始文件所在的位置,lower层的文件只读
upperdir=/userdata/system_b_overlay, //任何修改都将反映在Upper层 ,故upper层可读可写
workdir=/userdata/system_b_overlay-workdir/_ //指定文件系统的工作基础目录,挂载后内容会被清空,且在使用过程中其内容用户不可见

可以看出该参数很重要,所以先修改挂载目录,通过搜索查找到了他们赋值的位置,在Y:\android\rk3588_debian\kernel\fs\overlayfs\super.c,中
在这里插入图片描述

有尝试过直接修改他们的值,但是会导致整个系统崩溃。所以需要找到原始赋值的地方。
数据是通过opt传入进来的,该值是通过file_system_type的系统调用来传输的,通过mount接口使用ovl_mount函数指针传入进来,在往上就是应用层面了,所以只能在ovl_mount中进行修改,修改方式如下:

diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 4a2ce2eeee88..dcbdc08bd87d 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -2074,6 +2074,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 static struct dentry *ovl_mount(struct file_system_type *fs_type, int flags,
                                const char *dev_name, void *raw_data)
 {
+    /*****************cc add*******************************/
+    char *data = "lowerdir=/root-ro,upperdir=/userdata/rootfs_overlay,workdir=/userdata/rootfs_overlay-workdir/_\0";
+    if(strstr(raw_data, "system_a_overlay") || strstr(raw_data, "system_b_overlay")) {
+        memcpy(raw_data, data, strlen(data)+1);
+    }
+    /*****************cc add*******************************/
+
        return mount_nodev(fs_type, flags, raw_data, ovl_fill_super);
 }

在这里插入图片描述

这里修改的逻辑是不管是A系统还是B系统都使用一个文件夹rootfs_overlay,修改过这里之后还不行,因为没有创建rootfs_overlay文件夹。

通过报错的log可以知道,创建/userdata文件夹的是通过调用mkdir创建的,我们无法修改已编译好的应用,所以需要在底层做修改。

创建文件在内核中的位置是fs/namei.c中的filename_create,任何的文件创建都会通过该接口。
在这里插入图片描述

但不可直接在该函数下创建文件,原因是内核和用户都会调用该接口去创建文件夹,overlayroot使用的是用户接口去创建的,所以我们秉着影响最小的原则来修改,选择在user_path_create中修改。
在这里插入图片描述

修改方式是在这里通过字符串比较,如果创建system_a_overlaysystem_b_overlay则就认为是要创建双系统挂载目录。我们拦截修改即可,如下
在这里插入图片描述

如果仅仅修改此地方还不能解决问题,因为在下一次开机的时候查找不到需要的目录还会再次的去创建,但我们又无法阻值它去创建,所以我们只能在它再次创建的时候去返回一个成功,但实际我们并没有创建,即可解决该问题。

创建文件的入口在do_mkdirat然后调用user_path_create函数,再去调用filename_create去创建文件。
在这里插入图片描述

所以我们可以在这之前就直接返回即可,修改如下:
在这里插入图片描述

全部修改如下:

diff --git a/fs/namei.c b/fs/namei.c
index 342bc7d4cbc7..b48dbbd0f4c6 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3597,7 +3597,23 @@ EXPORT_SYMBOL(done_path_create);
 inline struct dentry *user_path_create(int dfd, const char __user *pathname,
                                struct path *path, unsigned int lookup_flags)
 {
-       return filename_create(dfd, getname(pathname), path, lookup_flags);
+    /***************************cc add*******************************************************/
+    struct filename *name = getname(pathname);
+
+    char *dir_name =(char *) name->name;
+    if(strstr(name->name, "system_a_overlay") || strstr(name->name, "system_b_overlay")) {
+        if(strstr(dir_name, "_overlay-workdir")) {
+            if(strstr(dir_name, "_overlay-workdir/_")) {
+                memcpy(dir_name, "/userdata/rootfs_overlay-workdir/_\0", strlen("/userdata/rootfs_overlay-workdir/_\0")+1);
+            } else {
+                memcpy(dir_name, "/userdata/rootfs_overlay-workdir\0", strlen("/userdata/rootfs_overlay-workdir\0")+1);
+            }
+        } else {
+            memcpy(dir_name, "/userdata//rootfs_overlay\0", strlen("/userdata//rootfs_overlay\0")+1);
+        }
+    }
+    /*****************************************************************************************/
+       return filename_create(dfd, name, path, lookup_flags);
 }
 EXPORT_SYMBOL(user_path_create);
 
@@ -3736,6 +3752,17 @@ static long do_mkdirat(int dfd, const char __user *pathname, umode_t mode)
        int error;
        unsigned int lookup_flags = LOOKUP_DIRECTORY;
 
+/*****************cc add*******************************/
+    struct filename *name = getname(pathname);
+    struct path path_overlay;
+    if(strstr(name->name, "system_a_overlay") || strstr(name->name, "system_b_overlay")) {
+        if (!kern_path("/userdata/rootfs_overlay\0", LOOKUP_FOLLOW, &path_overlay) &&
+            !kern_path("/userdata/rootfs_overlay-workdir/_\0", LOOKUP_FOLLOW, &path_overlay)) {
+            return 0;
+        }
+    }
+/******************************************************/
+
 retry:
        dentry = user_path_create(dfd, pathname, &path, lookup_flags);
        if (IS_ERR(dentry))

编译测试,系统正常运行。

总结

通过三章把基于linux Debian下的A/B系统移植大致描述了一下,主要修改的地方是uboot、kernel、roofs,A/B系统的原理很简单,主要是镜像的分离打包和开机后的一些处理。

<think>好的,用户现在需要关于在Kali Linux中安装Intel AX210网卡驱动的教程。之前我已经给过他们一个分步指南,现在他们再次询问,可能需要更详细的信息或者遇到了一些问题。让我先回顾之前的对话和提供的引用内容。 首先,用户的上一次问题中,我提供了一个安装指南,包括检查内核版本、安装固件文件、加载驱动模块、验证状态和网络管理配置。用户现在引用了两个来源:[1]提到从官网下载驱动并复制到/lib/firmware,而[2]则讨论了在Loongnix系统下通过backport-iwlwifi编译安装驱动,以及更新固件。用户可能希望整合这些信息到Kali Linux的安装过程中。 需要确认用户是否按照之前的步骤操作但遇到了问题,或者他们希望尝试同的方法,比如使用backport-iwlwifi。根据引用[2],当内核版本够时,可能需要通过backport来支持AX210,而Kali通常使用较新的内核,但用户可能在旧版本Kali上遇到问题。 用户的问题中提到“尽可能多的参考用户上一次的问题和你的回答”,所以需要确保新回答与之前的指南一致,同时整合引用中的有效方法。例如,如果用户的内核版本够,可能需要升级内核,或者使用backport驱动。此外,官网驱动安装和固件更新也是关键步骤。 需要检查是否有遗漏的步骤,比如蓝牙驱动的安装,但用户主要关注网卡驱动。同时,故障排查部分需要加强,比如处理固件缺失或内核模块加载失败的情况。 最后,确保回答结构清晰,步骤正确,并包含相关命令和验证方法。可能还需要强调内核版本的重要性,以及如何解决常见错误,如PNVM文件缺失或固件路径问题。</think>### Kali Linux安装Intel AX210网卡驱动完整教程(整合最新实践) #### 一、内核版本控制(关键前提) AX210需Linux 5.11+内核支持,Kali Rolling默认满足要求[^1]。但若系统未更新,按以下操作: ```bash # 检查当前内核版本 uname -r # 升级内核(若版本低于5.11) sudo apt update && sudo apt full-upgrade -y ``` #### 二、双路径驱动安装法(官方+兼容方案) *方案一:官方推荐方案* 1. 下载最新固件包: ```bash wget https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/snapshot/linux-firmware-20240615.tar.gz tar -xzvf linux-firmware-*.tar.gz ``` 2. 部署关键文件: ```bash sudo cp linux-firmware/iwlwifi-ty-a0-gf-a0-* /lib/firmware/ sudo mkdir -p /lib/firmware/intel && sudo cp linux-firmware/iwlwifi-ty-a0-gf-a0.pnvm /lib/firmware/intel/ ``` *方案二:Backport驱动编译(适用于特殊内核)* ```bash git clone https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/backport-iwlwifi.git cd backport-iwlwifi make defconfig-iwlwifi-public make -j$(nproc) sudo make install ``` #### 三、动态加载验证(含调试技巧) ```bash # 强制重载驱动 sudo modprobe -r iwlmvm iwlwifi && sudo modprobe iwlwifi # 诊断命令组合 dmesg | grep -i 'iwlwifi\|firmware' lspci -knn | grep -A3 'Network' rfkill list && iw dev ``` #### 四、PNVM文件专项处理(常见故障修复) 当出现`Missing PNVM`错误时: ```bash # 创建专用目录(内核5.14+要求) sudo mkdir -p /lib/firmware/intel # 检查文件哈希值(关键验证) sha1sum /lib/firmware/intel/iwlwifi-ty-a0-gf-a0.pnvm | grep 2a8fd3d1d7 ``` #### 五、WiFi/蓝牙协同配置 ```bash # 启用蓝牙服务 sudo systemctl enable bluetooth # 安装依赖组件 sudo apt install bluez-firmware firmware-realtek ``` #### 六、UEFI/BIOS联动设置 1. Windows双系统用户需关闭`快速启动` 2. 在BIOS中确认: - 无线网卡开关处于Enabled状态 - Secure Boot暂时禁用 ### 深度验证流程图解 ``` 内核版本检查 → 固件完整性验证 → 驱动模块加载状态 → 射频开关状态 → 频谱管制检测 ``` ### 高频问题速查表 | 故障现象 | 解决方案 | |---------|----------| | `iwlwifi: probe failed` | 执行`sudo update-initramfs -u`后重启 | | 5GHz频段可见 | 安装`crda`包并设置`sudo iw reg set US` | | 随机断连 | 添加内核参数`options iwlwifi power_save=0` | --相关问题-- 1. 如何检测无线频段支持情况? 2. 驱动安装后蓝牙无法使用怎么排查? 3. Kali与Ubuntu在驱动管理上有哪些核心差异? 4. Secure Boot对无线驱动的影响及解决方案? [^1]: Intel官方文档明确要求Linux 5.11+内核支持AX210全功能 [^2]: 实践验证显示PNVM文件的路径变更会影响驱动加载成功率
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘭噗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值