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_HASHPKG_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.mk302行开始 , 也注明了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 ~

posted @ 2022-07-14 20:03  虐心i  阅读(1509)  评论(0编辑  收藏  举报