KERNEL_DIR、系統平臺、交叉編譯器的指定,以及核心模組驅動檔案的簽名
【問題一:KERNEL_DIR、系統平臺、交叉編譯器的指定】
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裡指定使用的系統平臺等,所以編譯指令裡需要新增上對系統平臺的指定,以及交叉編譯器的使用。最終使用的Makefile檔案如下:
#********高通平臺裝置驅動Makefile********
CROSS_ARCH:=ARCH=arm CROSS_COMPILE="$(ARM_EABI_TOOLCHAIN)/arm-eabi-"
KERNEL_DIR:=$(ANDROID_PRODUCT_OUT)/obj/KERNEL_OBJ/
PWD:=$(shell pwd)
#這裡模組名為scull
obj-m += scull.o
scull-objs:= main.o pipe.o access.o
.PHONY: modules package clean
all:package
modules:
@if [ "$(ANDROID_BUILD_TOP)_yes" = "_yes" ]; then echo "You have to run \". build/envsetup.sh\" to init enviroment first. \nAnd then you have to run \"choosecombo\" to setup the project."&&exit 1; fi
@if [ ! -d $(KERNEL_DIR) ]; then echo "Build kernle first."&&cd $(ANDROID_BUILD_TOP)&&make bootimage&&cd -; fi
$(MAKE) $(CROSS_ARCH) -C $(KERNEL_DIR) M=$(PWD) modules
package:modules
@mkdir -p ./package
@cp $(obj-m:.o=.ko) ./package
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers package
#********聯芯平臺的裝置驅動Makefile********
EXTRA_CFLAGS += $(DEBFLAGS)
EXTRA_CFLAGS += -I$(LDDINC)
ifneq ($(KERNELRELEASE),)
# call from kernel build system
scull-objs := main.o pipe.o access.o
obj-$(CONFIG_SCULL) := scull.o
else
# KERNELDIR ?= /lib/modules/$(shell uname -r)/build
KERNELDIR ?= /home/zhouxiang/work/mpe168/android-4.4.4_r2/kernel/linux-3.10
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) LDDINC=$(PWD)/../include modules
endif
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
depend .depend dep:
$(CC) $(CFLAGS) -M *.c > .depend
ifeq (.depend,$(wildcard .depend))
include .depend
endif
【問題二:模組驅動檔案的簽名】
編譯生成module.ko後,push到android裝置的system/bin目錄,在insmod module.ko時提示:
insmod module.ko
insmod: init_module 'module.ko' failed (Required key not available)
根據提示應該是key的問題,查閱資料發現Linux從3.n(具體版本不清楚)開啟了對載入的module進行簽名認證的功能在這個功能使能之後,核心只允許安裝特定的key簽名的模組。
核心配置項(所在檔案:kernel/kernel/Makefile)中:
CONFIG_MODULE_SIG=y
表示開啟了簽名機制,但是這時候模組簽名或不簽名都可以使用。
CONFIG_MODULE_SIG_FORCE=y
如果上述配置項使能,則模組必須有正確的簽名才能正常使用。
CONFIG_MODULE_SIG_ALL=y
核心在編譯的時候,並不會主動去給模組簽名,除非你把上述配置項開啟。檢視核心配置檔案,發現上面3個配置項確實都打開了,因此肯定是ko簽名的問題。
對於核心簽名的理解參考文章:http://blog.csdn.net/hui872370036/article/details/69950869
如何為ko包簽名呢?
首先,找到signing_key.priv signing_key.x509檔案(在out/target/product/xxxxxx/obj/KERNEL_OBJ/目錄下),拷貝到module原始碼目錄。
然後,對module.ko進行簽名,使用命令:
perl ../../xxxx/kernel/scripts/sign-file sha512 signing_key.priv signing_key.x509 module.ko
簽名後檢視簽名信息,執行命令:hexdump -C module.ko | tail
00043680 9b 6f d3 d2 f6 71 27 15 73 38 d6 7b c1 c5 04 fb |.o...q'.s8.{....|
00043690 a7 16 4c 19 01 76 b8 a5 de 90 b4 0a 10 db aa 2f |..L..v........./|
000436a0 23 f4 97 5c a0 ce 70 c5 eb 87 95 92 5c e3 17 fd |#..\..p.....\...|
000436b0 ef 88 9b 3e 0b db 78 38 ac ee 9c b7 ef 82 ba 97 |...>..x8........|
000436c0 24 a9 6a 7a e4 5e 75 a6 d3 9a 98 5f 50 1d 77 28 |$.jz.^u...._P.w(|
000436d0 9e 11 26 48 bb cd 79 51 82 26 05 fb 61 01 06 01 |..&H..yQ.&..a...|
000436e0 1e 14 00 00 00 00 00 02 02 7e 4d 6f 64 75 6c 65 |.........~Module|
000436f0 20 73 69 67 6e 61 74 75 72 65 20 61 70 70 65 6e | signature appen|
00043700 64 65 64 7e 0a |ded~.|
00043705
此時簽名正確
最後,安裝裝置驅動檔案。若又提示
insmod module.ko
insmod: init_module 'module.ko' failed (Required key not available)
重新編譯了一次kernel映象,並對裝置fastboot flash boot boot.img重新燒錄kernel映象,再進行push, 而後insmod此次模組載入成功。
總結簽名失敗問題:
解決方案:
1、關閉核心的模組簽名校驗問題
2、使用當前核心的簽名對模組進行簽名 (每次編譯後簽名祕鑰對會更新,所以在對上個版本或者更早之前的版本或者其他機器編譯的核心映象載入模組時,需要重新燒寫模組編譯時的當前核心映象,這樣才不會出現簽名仍然不一致問題。)