背景
Linux内核版本可以在/proc/version
中查看。
但是设备树默认没有版本信息(有些平台可以通过demsg
查到编译时间)。
在工作中,希望:
- 内核版本中添加产品型号、硬件版本、内核定制版本等信息。
- 设备树与内核的版本绑定,通过
/proc/dtb
查看。
内核版本
Contents
● product_version:产品型号
● hardware_version:硬件版本
● soft_version:内核定制版本
● build_type:分debug和release
Kernel
修改source/kernel_src/kernel/kernel-4.9/init/version.c
:
const char linux_banner[] =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") " UTS_VERSION " custom_version:" " [product:" PRODUCT_NAME ", hardware:" HARDWARE_VERSION ", soft:" SOFT_VERSION ", type:" BUILD_TYPE "] " "\n";
const char linux_proc_banner[] =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") " UTS_VERSION " custom_version:" " [product:" PRODUCT_NAME ", hardware:" HARDWARE_VERSION ", soft:" SOFT_VERSION ",type:" BUILD_TYPE "] " "\n";
Makefile
修改source/kernel_src/kernel/kernel-4.9/Makefile
:
uts_len := 64
define filechk_utsrelease.h
if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \
echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \
exit 1; \
fi; \
#--------------------------------------------
# 内核版本号
#--------------------------------------------
(echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \
#--------------------------------------------
# 以下PRODUCTNAME/HDVERSION/SOFTVERSION/BUILDTYPE
# 为编译前设置的临时环境变量
#--------------------------------------------
echo \#define PRODUCT_NAME \"$(PRODUCTNAME)\"; \
echo \#define HARDWARE_VERSION \"$(HDVERSION)\"; \
echo \#define SOFT_VERSION \"$(SOFTVERSION)\"; \
echo \#define BUILD_TYPE \"$(BUILDTYPE)\";)
endef
编译完成后,会生成include/generated/utsrelease.h,包含上述宏定义。
Show
设备树版本
DTS
添加custom-version.dtsi:
/ {
// 具体版本号在编译前填充
custom,dtbbuildversion = "";
};
dts中添加包含关系:
#include <custom-version.dtsi>
Kernel
添加custom_dts_info.c
:
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/string.h>
static const char *dtb_ver = NULL;
static int __init display_custom_dtb_info(void)
{
unsigned long dt_root;
dt_root = of_get_flat_dt_root();
dtb_ver = of_get_flat_dt_prop(dt_root, "custom,dtbbuildversion", NULL);
if (dtb_ver)
pr_info("DTB Build version: %s\n", dtb_ver);
else
pr_info("DTB Build version: <unknown>\n");
return 0;
}
early_initcall(display_custom_dtb_info);
static int dtb_proc_show(struct seq_file *m, void *v)
{
char *dtb_ver_show = kzalloc(100, GFP_KERNEL);
strcat(dtb_ver_show, "DTB Build version: ");
if (dtb_ver)
strcat(dtb_ver_show, dtb_ver);
else
strcat(dtb_ver_show, "<unknown>");
strcat(dtb_ver_show, "\n");
seq_printf(m, dtb_ver_show);
kfree(dtb_ver_show);
return 0;
}
static int dtb_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, dtb_proc_show, NULL);
}
static const struct file_operations dtb_proc_fops = {
.open = dtb_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int __init proc_dtb_init(void)
{
proc_create("dtb", 0, NULL, &dtb_proc_fops);
return 0;
}
fs_initcall(proc_dtb_init);
Version
编译前填充版本号:
DTB_VERSION="${PRO_NAME}_${HW_NAME}_${custom_BUILD_VERSION}_${custom_BUILD_TYPE}"
DTS_VERSION_FILE=`find $DTS_DIR -name custom-version.dtsi` # DTS_DIR是设备树路径
sed -i "s/custom,dtbbuildversion.*$/custom,dtbbuildversion = \"$DTB_VERSION\"\;/g" $DTS_VERSION_FILE
Show
P.S.
在系统中反编译设备树的命令:
dtc -I fs -O dts /sys/firmware/devicetree/base > <devicetree>.dts