OpenWrt之Kernel version hash 的那些事
OpenWrt之Kernel version hash luci的那些事
Kernel Version
在OpenWrt中 , 有指定的kernel version , 也就是内核版本 , 具体配置在include/kernel-version.mk
中 ,
kernel version由版本号
和Hash
校验构成 , 形式如下:
LINUX_VERSION-5.4 = .203
LINUX_KERNEL_HASH-5.4.203 = fc933f5b13066cfa54aacb5e86747a167bad1d8d23972e4a03ab5ee36c29798a
在mster分支中 , kernel-version.mk
有做变动 , 添加了以下改动
KERNEL_DETAILS_FILE=$(INCLUDE_DIR)/kernel-$(KERNEL_PATCHVER)
内核版本会遍历在include
目录下以kernel-5.4
的形式文件 , kernel-5.4
内容如下:
LINUX_VERSION-5.4 = .203
LINUX_KERNEL_HASH-5.4.203 = fc933f5b13066cfa54aacb5e86747a167bad1d8d23972e4a03ab5ee36c29798a
内核版本被独立出来 , 如果有新的内核版本添加,只需要添加多一个文件即可 , 比如新增5.18.11
的内核
, 只需要在include
目录下创建一个kernel-5.18
即可
LINUX_VERSION-5.18 = .11
LINUX_KERNEL_HASH-5.18.11 = e20d8e54a782f7079b22762e8ee8adec0d08351b1083553adb2d6885ad1815af
Kernel Hash校验
kernel 下载链接: https://www.kernel.org/
Hash校验方法
OpenWrt采用的Kernel Hash校验方式是检测SHA256
, 其实不仅仅是kernel , 一些插件的PKG_HASH
和PKG_MIRROR_HASH
, 乃至OpenWrt的大多数Hash校验都是SHA256
, 当然也是有MD5
的
- windows10及以上系统 , 打开windows powershell (计算MD5则把
SHA256
替换成MD5
)
方式一:
certutil -hashfile linux-5.18.11.tar.xz SHA256
方式二(效率最快):
(Get-FileHash linux-5.18.11.tar.xz -Algorithm SHA256).Hash.ToLower()
生成的Hash直接复制到剪辑版, 还可以改良成这样
Set-Clipboard((Get-FileHash linux-5.18.11.tar.xz -Algorithm SHA256).Hash.ToLower())
- Linux系统 (计算MD5则把
sha256sum
替换成md5sum
)
sha256sum linux-5.18.11.tar.xz
注意: OpenWrt 对比的Hash是小写 , 所以生成的Hash是大写时需要转换成小写
Download Hash校验逻辑
在include/download.mk
中 , 能看到有不少的情况都是用的SHA256
校验
# MKHASH详见 scripts/mkhash.c
gen_sha256sum = $(shell $(MKHASH) sha256 $(DL_DIR)/$(1))
# Used in Build/CoreTargets and HostBuild/Core as an integrity check for
# downloaded files. It will add a FORCE rule if the sha256 hash does not
# match, so that the download can be more thoroughly handled by download.pl.
define check_download_integrity
expected_hash:=$(strip $(if $(filter-out x,$(HASH)),$(HASH),$(MIRROR_HASH)))
$$(if $$(and $(FILE),$$(wildcard $(DL_DIR)/$(FILE)), \
$$(filter undefined,$$(flavor DownloadChecked/$(FILE)))), \
$$(eval DownloadChecked/$(FILE):=1) \
$$(if $$(filter-out $$(call gen_sha256sum,$(FILE)),$$(expected_hash)), \
$(DL_DIR)/$(FILE): FORCE) \
)
endef
ifdef CHECK
check_escape=$(subst ','\'',$(1))
#')
# $(1): suffix of the F_, C_ variables, e.g. hash_deprecated, hash_mismatch, etc.
# $(2): filename
# $(3): expected hash value
# $(4): var name of the the form: {PKG_,Download/<name>:}{,MIRROR_}{HASH,MIRROR_HASH}
check_warn_nofix = $(info $(shell printf "$(_R)WARNING: %s$(_N)" '$(call check_escape,$(call C_$(1),$(2),$(3),$(4)))'))
ifndef FIXUP
check_warn = $(check_warn_nofix)
else
check_warn = $(if $(filter-out undefined,$(origin F_$(1))),$(filter ,$(shell $(call F_$(1),$(2),$(3),$(4)) >&2)),$(check_warn_nofix))
endif
ifdef FIXUP
F_hash_deprecated = $(SCRIPT_DIR)/fixup-makefile.pl $(CURDIR)/Makefile fix-hash $(3) $(call gen_sha256sum,$(1)) $(2)
F_hash_mismatch = $(F_hash_deprecated)
F_hash_missing = $(SCRIPT_DIR)/fixup-makefile.pl $(CURDIR)/Makefile add-hash $(3) $(call gen_sha256sum,$(1))
endif
# $(1): filename
# $(2): expected hash value
# $(3): var name of the the form: {PKG_,Download/<name>:}{,MIRROR_}{HASH,MIRROR_HASH}
C_download_missing = $(1) is missing, please run make download before re-running this check
C_hash_mismatch = $(3) does not match $(1) hash $(call gen_sha256sum,$(1))
C_hash_deprecated = $(3) uses deprecated hash, set to $(call gen_sha256sum,$(1))
C_hash_missing = $(3) is missing, set to $(call gen_sha256sum,$(1))
但是也有MD5
校验的
hash_var = $(if $(filter-out x,$(1)),MD5SUM,HASH)
endif
define DownloadMethod/unknown
echo "ERROR: No download method available"; false
endef
define DownloadMethod/default
$(SCRIPT_DIR)/download.pl "$(DL_DIR)" "$(FILE)" "$(HASH)" "$(URL_FILE)" $(foreach url,$(URL),"$(url)") \
$(if $(filter check,$(1)), \
$(call check_hash,$(FILE),$(HASH),$(2)$(call hash_var,$(MD5SUM))) \
$(call check_md5,$(MD5SUM),$(2)MD5SUM,$(2)HASH) \
)
endef
# $(1): "check"
# $(2): "PKG_" if <name> as in Download/<name> is "default", otherwise "Download/<name>:"
# $(3): shell command sequence to do the download
define wrap_mirror
$(if $(if $(MIRROR),$(filter-out x,$(MIRROR_HASH))),$(SCRIPT_DIR)/download.pl "$(DL_DIR)" "$(FILE)" "$(MIRROR_HASH)" "" || ( $(3) ),$(3)) \
$(if $(filter check,$(1)), \
$(call check_hash,$(FILE),$(MIRROR_HASH),$(2)MIRROR_$(call hash_var,$(MIRROR_MD5SUM))) \
$(call check_md5,$(MIRROR_MD5SUM),$(2)MIRROR_MD5SUM,$(2)MIRROR_HASH) \
)
endef
在include/download.mk
的302
行开始 , 也注明了PKG_HASH
等的定义
define Download/default
FILE:=$(PKG_SOURCE)
URL:=$(PKG_SOURCE_URL)
URL_FILE:=$(PKG_SOURCE_URL_FILE)
SUBDIR:=$(PKG_SOURCE_SUBDIR)
PROTO:=$(PKG_SOURCE_PROTO)
$(if $(PKG_SOURCE_MIRROR),MIRROR:=$(filter 1,$(PKG_MIRROR)))
$(if $(PKG_MIRROR_MD5SUM),MIRROR_MD5SUM:=$(PKG_MIRROR_MD5SUM))
$(if $(PKG_MIRROR_HASH),MIRROR_HASH:=$(PKG_MIRROR_HASH))
VERSION:=$(PKG_SOURCE_VERSION)
$(if $(PKG_MD5SUM),MD5SUM:=$(PKG_MD5SUM))
$(if $(PKG_HASH),HASH:=$(PKG_HASH))
endef
.config生成逻辑
OpenWrt的kernel的config配置大致可以分为3层 , 通过以下文件来了解
include/kernel-build.mk
oldconfig menuconfig nconfig xconfig: $(STAMP_PREPARED) $(STAMP_CHECKED) FORCE
rm -f $(LINUX_DIR)/.config.prev
rm -f $(STAMP_CONFIGURED)
$(LINUX_RECONF_CMD) > $(LINUX_DIR)/.config
$(_SINGLE)$(KERNEL_MAKE) \
include/target.mk
# select the config file to be changed by kernel_menuconfig/kernel_oldconfig
ifeq ($(CFG_TARGET),target)
LINUX_RECONFIG_LIST = $(wildcard $(GENERIC_LINUX_CONFIG) $(LINUX_TARGET_CONFIG))
LINUX_RECONFIG_TARGET = $(LINUX_TARGET_CONFIG)
else ifeq ($(CFG_TARGET),subtarget)
LINUX_RECONFIG_LIST = $(wildcard $(GENERIC_LINUX_CONFIG) $(LINUX_TARGET_CONFIG) $(LINUX_SUBTARGET_CONFIG))
LINUX_RECONFIG_TARGET = $(LINUX_SUBTARGET_CONFIG)
else ifeq ($(CFG_TARGET),subtarget_target)
LINUX_RECONFIG_LIST = $(wildcard $(GENERIC_LINUX_CONFIG) $(LINUX_SUBTARGET_CONFIG) $(LINUX_TARGET_CONFIG))
LINUX_RECONFIG_TARGET = $(LINUX_TARGET_CONFIG)
else ifeq ($(CFG_TARGET),env)
LINUX_RECONFIG_LIST = $(LINUX_KCONFIG_LIST)
LINUX_RECONFIG_TARGET = $(TOPDIR)/env/kernel-config
else ifneq ($(strip $(CFG_TARGET)),)
$(error CONFIG_TARGET=$(CFG_TARGET) is invalid. Valid: target|subtarget|subtarget_target|env)
endif
__linux_confcmd = $(2) $(patsubst %,+,$(wordlist 2,9999,$(1))) $(1)
LINUX_CONF_CMD = $(SCRIPT_DIR)/kconfig.pl $(call __linux_confcmd,$(LINUX_KCONFIG_LIST))
LINUX_RECONF_CMD = $(SCRIPT_DIR)/kconfig.pl $(call __linux_confcmd,$(LINUX_RECONFIG_LIST))
LINUX_RECONF_DIFF = $(SCRIPT_DIR)/kconfig.pl - '>' $(call __linux_confcmd,$(filter-out $(LINUX_RECONFIG_TARGET),$(LINUX_RECONFIG_LIST))) $(1) $(GENERIC_PLATFORM_DIR)/config-filter
当我们使用make kernel_menuconfig
时 , 会通过kconfig.pl
脚本 将
底层: target/linux/generic/config-5.18
中层: target/linux/[CPU_TYPE]/[CPU_CFLAGS]/config-5.18
这两个层进行合并 , 保存退出后通过kconfig.pl脚本重新将配置文件保存到generic/config-5.18
文件
当我们使用make menuconfig
时, 会通过kconfig.pl
脚本 将
底层: target/linux/generic/config-5.18
中层: target/linux/[CPU_TYPE]/[CPU_CFLAGS]/config-5.18
外层: .config
这三个层合并得到最终的配置文件
分析到此结束 , Enjoy it ~