CONFIG_USB_STORAGE=m
CONFIG_USB_STORAGE_REALTEK=m
CONFIG_REALTEK_AUTOPM=y
dmesg | grep -E "SCSI|Bulk"
内核虚拟地址打印方式:强制转换成uintptr_t类型,然后使用%lx打印即可。或者直接使用%px打印内核虚拟地址。
Tool: Binary Viewer, 010editor
1 Android 8.0 build kernel module
1.1 Makefile
# [RFC] kbuild: add CLANG_TRIPLE to prevent clang from compiling with wrong --target
# ARCH=arm64 or x86_64
# apt install linux-headers-$(uname -r)
# PC KDIR = /lib/modules/$(uname -r)/build
PREFIX=/path/to/android
KDIR=$(PREFIX)/out/target/product/$(TARGET_PRODUCT)/obj/kernel
# should not add prefix ./, otherwise fail to build
MOD_SRC=drivers/usb/storage
KO=usb-storage.ko
# obj-m = usb-storage.ko
all:
make -C $(KDIR) \
ARCH=x86_64 \
LLVM=1 \
M=$(MOD_SRC) \
KBUILD_EXTRA_SYMBOLS=\
$(KDIR)/Module.symvers \
V=1 \
CONFIG_USB_STORAGE=m \
modules
$(call sign_module)
clean:
make -C $(KDIR) \
M=$(MOD_SRC) \
clean
aarch64-poky-linux-strip -S xxx.ko
$STRIP -S xxx.ko
After this change, it's easy to use ZMODEM file transfer.
1.2 sign module
qcom AndroidKernelModule.mk sign module.
PEM: Privacy Enhanced Mail
modinfo /path/to/usb-storage.ko
zcat /proc/config.gz |grep SIG_
define sign_module
cp $(KDIR)/drivers/usb/storage/$(KO) .
$(KDIR)/scripts/sign-file sha512 \
$(KDIR)/certs/signing_key.pem \
$(KDIR)/certs/signing_key.x509 \
$(KO)
hexdump -C $(KO) | tail
endef
1.3 How to get ko keyring files?
./scripts/extract-sys-certs.pl /PATH/TO/vmlinux /tmp/signing_key.x509
openssl x509 -pubkey -noout -inform der -in /tmp/signing_key.x509 -out /tmp/signing_key.pem
2 ko modversion
2.1 Module.symvers
modprobe --dump-modversions xxx.ko | grep module_layout
cat Module.symvers | grep module_layout
.tmp_versions: rename all .mod to .xxx under .tmp_versions
vmlinux: rename vmlinux to vmlinux-bak
after the above two change, make -C will use Module.symvers to generate ko modversion.
2.2 SA8155 extract-symvers
modprobe --dump-modversions xxx.ko > nm.symvers
python extract-symvers.py nm.symvers Module.symvers
import sys,os
def my_replace(src_file, line_in):
arr_in = line_in.split()
f = open(src_file, 'r')
for line in f:
arr = line.split()
if (arr[1] == arr_in[1]):
f.close()
arr_in[0] = arr[0]
mstr = '\t'
mstr = mstr.join(str(i) for i in arr_in)
return (mstr + '\t' + '\n')
f.close()
return line_in
def run_replace(src_file, dst_file):
tmp_f = open('tmp.txt', 'w')
f = open(dst_file, 'r')
for line in f:
tmp_f.writelines(my_replace(
src_file, line))
tmp_f.close()
f.close()
os.rename(dst_file, "Module_orig.symvers")
os.rename('tmp.txt', "Module.symvers")
def main():
arg0_proc_name = sys.argv[0]
if sys.argv[0].rfind(
os.path.sep) > 0 :
index = sys.argv[0].rfind(
os.path.sep)
arg0_proc_name = \
sys.argv[0][index + 1:]
if len(sys.argv) < 3:
print('\nUsage: python ' +
arg0_proc_name +
'
'
sys.exit(0)
run_replace(sys.argv[1],
sys.argv[2])
if __name__ == '__main__':
main()
3 kernel module debug
3.1 module log
# p: enable pr_debug
insmod
echo "module
/sys/kernel/debug/dynamic_debug/control
get module_name from lsmod
3.2 ko objdump
init_module+0x7c/0xeb0
func+offset/last_addr
aarch64-poky-linux-objdump -l -C -S xxx.ko > deasm.log
vi deasm.log
输入#00 Frame前面显示的pc指向的地址(需要去掉前面的多个0)
ARM64汇编中,x0 - x7用来传递函数第一到第八个参数,超出的参数通过堆栈来传递。
3.3 ARM64汇编
sub sp, sp, #0x80 // 分配stack局部空间,大小是0x80字节,准备存放函数局部变量
ldr x0, [x1]; // 从x1指向的地址里面取出一个64位大小的数存入x0
ldp x1, x2, [x10, #0x10]; // 从x10 + 0x10指向的地址里面取出2个64位的数,分别存入x1,x2
str x5, [sp, #24]; // 把x5的值(64位数值)存到sp + 24指向的内存地址上
stp x29, x30, [sp, #-16]!; // 把x29,x30的值存到sp - 16的地址上,并且把sp -= 16
ldp x29, x30, [sp], #16; // 从sp地址取出2个64位数,分别存入x29,x30,然后sp += 16
4 Android-T
4.1 GKI
Open .config to find clang version from CONFIG_CC_VERSION_TEXT, then export clang and pahole (poke a hole) binaries to PATH.
define sign_module
$(KDIR)/scripts/sign-file sha1 \
$(KDIR)/certs/signing_key.pem \
$(KDIR)/certs/signing_key.x509 \
xxx.ko
endef
make -C $(KDIR) \
M=$(PWD) \
LLVM=1 \
ARCH=arm64 \
modules
llvm-strip -S xxx.ko
$(call sign_module)
4.2 vendorbootimage
boot.img: GKI kernel
vendor_boot.img: dtb.img, bootconfig and vendor_ramdisk.img
make vendorbootimage
lpdump super.img
lpunpack super.img output_dir
4.3 ninja build
all Android.mk -> out/build-$TARGET_PRODUCT.ninja
all Android.bp -> out/soong/build.ninja
Then build-$TARGET_PRODUCT.ninja and build.ninja are merged to
out/combined-$TARGET_PRODUCT.ninja
ln -sf out/combined-$TARGET_PRODUCT.ninja build.ninja
cp prebuilts/build-tools/linux-x86/bin/ninja \
out/host/linux-x86/bin
cp prebuilts/build-tools/linux-x86/lib64/libc++.so \
out/host/linux-x86/lib64
cp prebuilts/build-tools/linux-x86/lib64/libjemalloc5.so \
out/host/linux-x86/lib64
ninja
4.4 sparse and checkpatch
# make C=2
# C=2 will calls sparse binary to check sparse.
# checkpatch_all.sh
#!/bin/bash
LOG_NAME=./sparse.log
read_dir()
{
for file in $(ls $1)
do
if [ -d $1"/"$file ]; then
if [[ $file != '.' && \
$file != '..' ]]; then
read_dir $1"/"$file
fi
else
my_f=$1"/"$file
./scripts/checkpatch.pl \
--no-tree -f $my_f >> \
$LOG_NAME
fi
done
}
if [ -f $LOG_NAME ]; then
rm $LOG_NAME
fi
if [ $# -lt 1 ]; then
echo "$0
exit
fi
read_dir $1
echo "log file: $LOG_NAME"
5 Abbreviations
GKI: Generic Kernel Image, from android11-5.4
KMI: Kernel Module Interface
QSSI: Android-T Qualcomm Single System Image