Android交叉编译驱动模块

在为android 编译ko 包并使用insmod加载过程中遇到两个问题,记录如下:

android 编译ko包实际与linux编译ko没有区别,首先编写.c .h文件等,之后编写makefile文件,

makefile中 KERNEL_DIR 为kernel编译后产生的临时文件夹的目录,有些系统工程会重定向生成的内核临时文件目录,

所以不能简单的吧KERNEL_DIR  定义为kernel源文件目录。而是应该确定生成的临时文件的目录后使用临时文件目录

例如本次使用的工程,编译后的临时文件目录为

out/target/product/xxxxxx/obj/KERNEL_OBJ/  
所以设置 KERNEL_DIR := xxx/out/target/product/xxxxxx/obj/KERNEL_OBJ/  

在编写编译选项时本次的工程并没有在顶层makefile里指定使用的系统平台等,所以编译指令里需要添加上对系统平台

的指定,以及交叉编译器的使用。

make -C  $(KERNEL_DIR) ARCH=arm CROSS_COMPILE=arm-eabi- M=$(PWD) modules

使用imx6dq的Makefile文件参考如下:

KERNELDIR := /media/imx/old_imx/out/target/product/sabresd_6dq/obj/KERNEL_OBJ/
CURRENT_PATH := $(shell pwd)
#arm32 bit system
    ARCH = arm
    CROSS_COMPILE=/media/imx/old_imx/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-

#arm64 bit system
#    ARCH = arm64
#    CROSS_COMPILE=<android源码顶层目录>/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-


obj-m := module.o


build: kernel_modules

kernel_modules:
$(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules

#签名参考
        #@$(内核路径)/scripts/sign-file sha512 $(PWD)/signing_key.pem $(PWD)/signing_key.x509 $(PWD)/hello.ko
clean:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

注意一点:imx无模块签名sign-file,高通的有,要根据实际情况

编译生成module.ko 后,push 到android设备的system/bin目录,

若编译的系统平台(qcom)与目前使用系统平台不符(rk),会有如下提示
在insmod module.ko 时提示:

insmod module.ko
insmod: init_module ‘module.ko’ failed (Exec format error)

usb 线之前是连到rk的板子上,切换到qcom的开发板后继续insmod

切换正确平台
提示

insmod module.ko
insmod: init_module ‘module.ko’ failed (Required key not available)

根据提示应该是key的问题,查阅资料发现Linux 从3.n(具体版本不清楚)开启了对加载的module进行签名认证的功能

在这个功能使能之后,内核只允许安装特定的key签名的模块。

内核配置项 

CONFIG_MODULE_SIG=y

表示开启了签名机制,但是这时候模块签名或不签名都可以使用

CONFIG_MODULE_SIG_FORCE=y
如果上述配置项使能,则模块必须有正确的签名才能正常使用。

CONFIG_MODULE_SIG_ALL=y

内核在编译的时候,并不会主动去给模块签名,除非你把上述配置项打开。 
查看内核配置文件,发现上面3个配置项确实都打开了,因此肯定是ko签名的问题。

查看当前编译的签名信息:
使用命令hexdump -C spidev.ko | tail

查找到  signing_key.priv signing_key.x509 文件,拷贝到module源码目录,

单独手动签名使用命令:

perl ../../xxxx/kernel/scripts/sign-file sha512 signing_key.priv signing_key.x509  module.ko

建议在makefile文件里配置对module.ko进行签名

此时签名正确,将module push 进设备insmode 悲催的是又提示

insmod module.ko
insmod: init_module ‘module.ko’ failed (Required key not available)

奇怪的问题,后来突然想起,最近重新编译了一次kernel 镜像,此次module 是在这次基础上编译的,是否与重新编译有关,

然后对设备fastboot flash boot boot.img 重新烧录 kernel 镜像,在进行push   而后insmod 此次模块加载成功。

总结 签名失败问题:

解决方案:

1、关闭内核的模块签名校验问题

2、使用当前内核的签名对模块进行签名 (每次编译后签名秘钥对会更新,所以在对上个版本或者更早之前的版本或者其他机器编译的内核镜像

加载模块时,需要重新烧写模块编译时的当前内核镜像,这样才不会出现签名仍然不一致问题。)

发表评论

滚动至顶部