Linux内核增加HDF驱动子系统

linux驱动HDF 2024-03-01

前言

HDF驱动子系统是OpenHarmony重要的特色功能之一,其主要的功能是实现驱动程序在多内核多平台的物联网环境,实现一次驱动开发,多端部署。之前移植OHOS3.0使用了传统的linux驱动,比较遗憾,今天尝试将HDF驱动子系统加入编译框架。开始前先了解几个名词。

HCS(HDF Configuration Source)是 HDF 驱动框架的配置描述源码,JSON存储。

HC-GEN(HDF Configuration Generator)是 HCS 配置转换工具,可以将 HDF 配置文件HCS转换为二进制HCB。

HCB(HDF Configuration Binary)二进制文件,驱动可使用 HDF 框架提供的配置解析接口获取配置。

内核打补丁

如何在内核加入HDF驱动,linux内核下主要实现是下面两个目录:

drivers\adapter\khdf\linux 和 drivers\framework

这两个目录是通过链接的方式加入到内核编译的,流程如下:

kernel\linux\build\kernel.mk:75

  1. $(hide) cd $(KERNEL_SRC_TMP_PATH) && patch -p1 < $(HDF_PATCH_FILE) && patch -p1 < $(DEVICE_PATCH_FILE)

可以参考3516的HDF补丁:kernel\linux\patches\linux-5.10\hi3516dv300_patch\hdf.patch

  1. patching file drivers/Kconfig
  2. patching file drivers/Makefile
  3. patching file drivers/hdf/Makefile
  4. patching symbolic link drivers/hdf/framework
  5. patching symbolic link drivers/hdf/khdf
  6. patching symbolic link include/hdf
  7. # 添加到linux内核的补丁
  8. drivers/hdf/framework -> /drivers/framework/ # 驱动子系统驱动框架、配置管理、配置解析、驱动通用框架模型、硬件通用平台能力接口等
  9. drivers/hdf/khdf -> /drivers/adapter/khdf/linux/ # 在linux内核中部署OpenHarmony驱动框架
  10. drivers/hdf/Makefile # 由hdf.patch提供
  11. include/hdf -> /drivers/framework/include/ # 驱动框架对外提供能力的头文件

内核配置

只是打上补丁还不行,还得在内核的编译配置文件中加入HDF选项。最开始的做法就是参考3516的配置选择,但是发现有些配置会导致编译失败。测试发现下面的配置是可以编译成功的。

  1. [*] Enable HDF manager
  2. (2) Set HDF support platform
  3. [*] Enable HDF platform driver
  4. [*] Enable HDF platform mipi dsi driver
  5. [*] Enable HDF platform gpio driver
  6. [*] Enable HDF platform i2c driver
  7. [*] Enable HDF platform watchdog driver
  8. [*] hi35xx pwm driver
  9. [*] Enable HDF platform pwm driver
  10. [*] Enable HDF platform uart driver
  11. [ ] Enable HDF platform sdio driver
  12. [ ] Enable HDF platform emmc driver
  13. [*] Enable HDF platform mmc driver
  14. [*] Enable HDF platform spi driver
  15. [*] Enable HDF platform rtc driver
  16. [*] Enable HDF linux test
  17. [*] Enable HDF Display driver
  18. [ ] Enable HDF Lcdkit driver
  19. [*] Enable HDF Icn9700 driver
  20. [ ] Enable HDF St7789 driver
  21. [*] Enable HDF input driver
  22. [*] Enable HDF tp 5P5 GT911 driver
  23. [*] Enable HDF tp 2P35 FT6236 driver
  24. [ ] Enable HDF wifi
  25. [ ] Enable HDF Bluetooth
  26. [*] Enable HDF sensor driver
  27. [ ] Enable HDF accel sensor driver
  28. [ ] Enable HDF gyro sensor driver
  29. [ ] Enable HDF barometer sensor driver
  30. [ ] Enable HDF hall sensor driver
  31. [*] Enable HDF storage driver
  32. [ ] Enable HDF USB PNP Notify driver
  33. [ ] Enable F_GENERIC driver
  34. [ ] Enable HDF Audio driver
  35. [*] Enable HDF vibrator driver
  36. [*] Enable HDF linear vibrator driver
  37. [ ] Enable HDF dsoftbus driver
  38. CONFIG_DRIVERS_HDF=y
  39. CONFIG_HDF_SUPPORT_LEVEL=2
  40. CONFIG_DRIVERS_HDF_PLATFORM=y
  41. CONFIG_DRIVERS_HDF_PLATFORM_MIPI_DSI=y
  42. CONFIG_DRIVERS_HDF_PLATFORM_GPIO=y
  43. CONFIG_DRIVERS_HDF_PLATFORM_I2C=y
  44. CONFIG_DRIVERS_HDF_PLATFORM_WATCHDOG=y
  45. CONFIG_PWM_HI35XX=y
  46. CONFIG_DRIVERS_HDF_PLATFORM_PWM=y
  47. CONFIG_DRIVERS_HDF_PLATFORM_UART=y
  48. # CONFIG_DRIVERS_HDF_PLATFORM_SDIO is not set
  49. # CONFIG_DRIVERS_HDF_PLATFORM_EMMC is not set
  50. CONFIG_DRIVERS_HDF_PLATFORM_MMC=y
  51. CONFIG_DRIVERS_HDF_PLATFORM_SPI=y
  52. CONFIG_DRIVERS_HDF_PLATFORM_RTC=y
  53. CONFIG_DRIVERS_HDF_TEST=y
  54. CONFIG_DRIVERS_HDF_DISP=y
  55. # CONFIG_DRIVERS_HDF_LCDKIT is not set
  56. CONFIG_DRIVERS_HDF_LCD_ICN9700=y
  57. # CONFIG_DRIVERS_HDF_LCD_ST7789 is not set
  58. CONFIG_DRIVERS_HDF_INPUT=y
  59. CONFIG_DRIVERS_HDF_TP_5P5_GT911=y
  60. CONFIG_DRIVERS_HDF_TP_2P35_FT6236=y
  61. # CONFIG_DRIVERS_HDF_WIFI is not set
  62. # CONFIG_DRIVERS_HDF_BT is not set
  63. CONFIG_DRIVERS_HDF_SENSOR=y
  64. # CONFIG_DRIVERS_HDF_SENSOR_ACCEL is not set
  65. # CONFIG_DRIVERS_HDF_SENSOR_GYRO is not set
  66. # CONFIG_DRIVERS_HDF_SENSOR_BAROMETER is not set
  67. # CONFIG_DRIVERS_HDF_SENSOR_HALL is not set
  68. CONFIG_DRIVERS_HDF_STORAGE=y
  69. # CONFIG_DRIVERS_HDF_USB_PNP_NOTIFY is not set
  70. # CONFIG_DRIVERS_HDF_USB_F_GENERIC is not set
  71. # CONFIG_DRIVERS_HDF_AUDIO is not set
  72. CONFIG_DRIVERS_HDF_VIBRATOR=y
  73. CONFIG_DRIVERS_HDF_VIBRATOR_LINEAR=y
  74. # CONFIG_DRIVERS_HDF_DSOFTBUS is not set
  75. # end of Device Drivers

[*] Enable HDF linux test 是需要设置的,如果没有设置CONFIG_DRIVERS_HDF_TEST,目录结构就出问题了,会报这样的错误。

  1. drivers/hdf/khdf/Makefile:22: PRODUCT_PATH=vendor/raspberrypi/RPI4B
  2. scripts/Makefile.build:44: drivers/hdf/khdf/../../../../vendor/raspberrypi/RPI4B/hdf_config/Makefile: No such file or directory
  3. make[5]: *** No rule to make target 'drivers/hdf/khdf/../../../../vendor/raspberrypi/RPI4B/hdf_config/Makefile'. Stop.
  4. CC [M] drivers/net/wireless/mac80211_hwsim.o
  5. make[4]: *** [scripts/Makefile.build:497: drivers/hdf/khdf/../../../../vendor/raspberrypi/RPI4B/hdf_config] Error 2
  6. make[3]: *** [scripts/Makefile.build:497: drivers/hdf/khdf] Error 2
  7. make[2]: *** [scripts/Makefile.build:497: drivers/hdf] Error 2
  8. make[2]: *** Waiting for unfinished jobs....

下面3个选项要关闭,不然会报下面的错误。

[ ] Enable HDF platform sdio driver

[ ] Enable HDF platform emmc driver

[ ] Enable HDF wifi

  1. drivers/../../../../../../drivers/adapter/khdf/linux/platform/sdio/sdio_adapter.o: In function `Hi35xxLinuxSdioRescan':
  2. sdio_adapter.c:(.text+0x20): undefined reference to `hisi_sdio_rescan'
  3. sdio_adapter.c:(.text+0x34): undefined reference to `himci_get_mmc_host'
  4. drivers/../../../../../../drivers/adapter/khdf/linux/platform/sdio/sdio_adapter.o: In function `Hi35xxLinuxSdioFindFunc':
  5. sdio_adapter.c:(.text+0xc84): undefined reference to `himci_get_mmc_host'
  6. sdio_adapter.c:(.text+0xc9c): undefined reference to `himci_get_mmc_host'
  7. sdio_adapter.c:(.text+0xcb4): undefined reference to `himci_get_mmc_host'
  8. drivers/../../../../../../drivers/adapter/khdf/linux/platform/emmc/emmc_adapter.o: In function `Hi35xxLinuxEmmcBind':
  9. emmc_adapter.c:(.text+0x214): undefined reference to `himci_get_mmc_host'
  10. drivers/../../../../../../device/hisilicon/drivers/wifi/driver/hi3881/oal/oal_sdio_host.o: In function `sdio_card_detect_change':
  11. oal_sdio_host.c:(.text+0x2ce8): undefined reference to `hisi_sdio_rescan'
  12. make[1]: *** [Makefile:1179: vmlinux] Error 1
  13. make[1]: Leaving directory '/home/liangzili/ohos/out/KERNEL_OBJ/kernel/src_tmp/linux-5.10'
  14. make: *** [kernel.mk:80: /home/liangzili/ohos/out/KERNEL_OBJ/kernel/src_tmp/linux-5.10/arch/arm/boot/zImage] Error 2
  15. ninja: build stopped: subcommand failed.

编译过程

为了方便测试可以单独进行内核编译,比如我的编译命令是这样的。

  1. ./build.sh --product-name RPI4B --ccache --build-target raspberrypi_products

可以分析下HDF这部分的编译过程。

linux-5.10\drivers\hdf\Makefile,hdf.patch会添加这个Makefile,将khdf文件夹加入编译。

  1. obj-$(CONFIG_DRIVERS_HDF) += khdf/

linux-5.10\drivers\hdf\khdf\Makefile

  1. export HDF_ROOT := drivers/hdf
  2. obj-$(CONFIG_DRIVERS_HDF) += osal/
  3. obj-$(CONFIG_DRIVERS_HDF) += network/
  4. obj-$(CONFIG_DRIVERS_HDF) += config/
  5. SUPPORT_LEVEL_STD_H := $(shell [ "$(CONFIG_HDF_SUPPORT_LEVEL)" -ge 2 ] && echo true)
  6. $(warning PRODUCT_PATH=$(PRODUCT_PATH)) # 会检查PRODUCT_PATH变量
  7. ifeq ($(PRODUCT_PATH),)
  8. $(error PRODUCT_PATH not)
  9. endif
  10. # 这里有条注释指明了*.hcs配置文件的存放路径
  11. # for L2+, hcs config should in vendor/product_company/product_name/config/khdf
  12. ifeq ($(SUPPORT_LEVEL_STD_H), true)
  13. SUB_DIR:=khdf/
  14. endif
  15. # HDF test的配置会使hcs目录结构不一样,我当时没有设置CONFIG_DRIVERS_HDF_TEST就掉这个坑里了。
  16. ifeq ($(CONFIG_DRIVERS_HDF), y)
  17. ifeq ($(CONFIG_DRIVERS_HDF_TEST), y)
  18. obj-$(CONFIG_DRIVERS_HDF) += ../../../../$(PRODUCT_PATH)/hdf_config/$(SUB_DIR)/hdf_test/
  19. obj-$(CONFIG_DRIVERS_HDF) += test/
  20. else
  21. obj-$(CONFIG_DRIVERS_HDF) += ../../../../$(PRODUCT_PATH)/hdf_config/$(SUB_DIR)
  22. endif
  23. endif
  24. # ... 后面按照配置添加一些编译目录 ...

drivers\adapter\khdf\linux\Makefile:会调用 obj-(CONFIG_DRIVERS_HDF) += ../../../../(CONFIGDRIVERSHDF)+=../../../../(PRODUCT_PATH)/hdf_config/$(SUB_DIR)/hdf_test/ 这是OHOS3.0默认的HCS文件存放路径。官方的注释也说明了,所以将设备对应的*.hcs存放到 vendor\raspberrypi\RPI4B\hdf_config\khdf 文件夹,参考 3516 的 vendor\hisilicon\Hi3516DV300\hdf_config\khdf\hdf.hcs 就可了。

  1. #include "device_info/device_info.hcs"
  2. #include "platform/i2c_config.hcs"
  3. #include "platform/hi35xx_watchdog_config.hcs"
  4. #include "platform/hi35xx_pwm_config.hcs"
  5. #include "platform/hi35xx_uart_config.hcs"
  6. #include "platform/sdio_config.hcs"
  7. #include "platform/emmc_config.hcs"
  8. #include "platform/hi35xx_spi_config.hcs"
  9. #include "input/input_config.hcs"
  10. #include "wifi/wlan_platform.hcs"
  11. #include "wifi/wlan_chip_hi3881.hcs"
  12. #include "sensor/sensor_config.hcs"
  13. #include "audio/audio_config.hcs"
  14. #include "audio/codec_config.hcs"
  15. #include "audio/dai_config.hcs"
  16. #include "audio/dma_config.hcs"
  17. #include "audio/dsp_config.hcs"
  18. #include "vibrator/vibrator_config.hcs"
  19. #include "vibrator/linear_vibrator_config.hcs"
  20. #include "lcd/lcd_config.hcs"
  21. root {
  22. module = "hisilicon,hi35xx_chip";
  23. }

参考 3516 的 vendor\hisilicon\Hi3516DV300\hdf_config\khdf\Makefile

其中:PRODUCT_PATH环境变量的来源:kernel/linux/build/kernel_module_build.sh:42:export PRODUCT_PATH=$4

  1. ifeq ($(LOCAL_HCS_ROOT),)
  2. LOCAL_HCS_ROOT := $(PRODUCT_PATH)
  3. endif
  4. SOURCE_ROOT:=$(abspath ../../../../../)
  5. HC_GEN_DIR := $(abspath $(SOURCE_ROOT)/drivers/framework/tools/hc-gen)
  6. HC_GEN := $(HC_GEN_DIR)/build/hc-gen
  7. LOCAL_HCS_ROOT := $(abspath $(dir $(realpath $(lastword $(MAKEFILE_LIST)))))
  8. HCS_DIR := $(LOCAL_HCS_ROOT)
  9. ifneq ($(TARGET_BOARD_PLATFORM),)
  10. HCS_DIR := $(LOCAL_HCS_ROOT)/$(TARGET_BOARD_PLATFORM)
  11. else
  12. ifneq ($(CONFIG_ARCH_HI3516DV300),)
  13. HCS_DIR := $(LOCAL_HCS_ROOT)
  14. endif
  15. ifneq ($(CONFIG_ARCH_HI3518EV300),)
  16. HCS_DIR := $(LOCAL_HCS_ROOT)
  17. endif
  18. endif
  19. $(info HCS_DIR = $(HCS_DIR))
  20. HCB_FLAGS := -b -i -a
  21. HCS_OBJ := hdf_hcs_hex.o
  22. HCS_OBJ_SRC := $(subst .o,.c,$(notdir $(HCS_OBJ)))
  23. CONFIG_GEN_HEX_SRC := $(addprefix $(LOCAL_HCS_ROOT)/, $(HCS_OBJ_SRC))
  24. CONFIG_HCS_SRC := $(subst _hcs_hex.o,.hcs,$(addprefix $(HCS_DIR)/, $(HCS_OBJ)))
  25. $(obj)/$(HCS_OBJ): $(CONFIG_GEN_HEX_SRC)
  26. $(Q)$(CC) $(c_flags) -c -o $@ $<
  27. $(Q)rm -f $<
  28. $(CONFIG_GEN_HEX_SRC): $(LOCAL_HCS_ROOT)/%_hcs_hex.c: $(HCS_DIR)/%.hcs | $(HC_GEN)
  29. $(Q)echo gen hdf built-in config
  30. $(Q)if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi
  31. $(Q)$(HC_GEN) $(HCB_FLAGS) -o $(subst _hex.c,,$(@)) $<
  32. $(CONFIG_GEN_SRCS): $(CONFIG_OUT_DIR)%.c: $(HCS_DIR)/%.hcs | $(HC_GEN)
  33. $(Q)echo gen hdf driver config
  34. $(Q)if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi
  35. $(Q)$(HC_GEN) -t -o $@ $<
  36. $(HC_GEN):
  37. $(HIDE)make -C $(HC_GEN_DIR)
  38. obj-$(CONFIG_DRIVERS_HDF) += $(HCS_OBJ)

查看结果

编译完成后,可以上传内核镜像到开发板,来查看HDF驱动框架是否启动成功。

加入HDF前:

  1. # ls dev/
  2. __parameters__ hwrng tty1 tty28 tty46 tty7
  3. __trigger__ input tty10 tty29 tty47 tty8
  4. autofs kmsg tty11 tty3 tty48 tty9
  5. binder linux,cma tty12 tty30 tty49 ttyAMA0
  6. block loop-control tty13 tty31 tty5 ttyS0
  7. bus mem tty14 tty32 tty50 ttyprintk
  8. cachefiles memcg tty15 tty33 tty51 unix
  9. char null tty16 tty34 tty52 urandom
  10. console port tty17 tty35 tty53 vchiq
  11. cpuctl ptmx tty18 tty36 tty54 vcs
  12. cpuset pts tty19 tty37 tty55 vcs1
  13. dri random tty2 tty38 tty56 vcsa
  14. fd rawctl tty20 tty39 tty57 vcsa1
  15. freezer snd tty21 tty4 tty58 vcsu
  16. fscklogs stderr tty22 tty40 tty59 vcsu1
  17. full stdin tty23 tty41 tty6 vga_arbiter
  18. gpiochip0 stdout tty24 tty42 tty60 vndbinder
  19. gpiochip1 system tty25 tty43 tty61 watchdog
  20. graphics tty tty26 tty44 tty62 watchdog0
  21. hwbinder tty0 tty27 tty45 tty63 zero

加入HDF后:

  1. # ls dev/
  2. HDF_PLATFORM_I2C_MANAGER loop-control tty24 tty54
  3. HDF_PLATFORM_UART_1 mem tty25 tty55
  4. HDF_TEST memcg tty26 tty56
  5. I2C_TEST null tty27 tty57
  6. __parameters__ port tty28 tty58
  7. __trigger__ ptmx tty29 tty59
  8. autofs pts tty3 tty6
  9. binder random tty30 tty60
  10. block rawctl tty31 tty61
  11. bus sample_service tty32 tty62
  12. cachefiles snd tty33 tty63
  13. char stderr tty34 tty7
  14. console stdin tty35 tty8
  15. cpuctl stdout tty36 tty9
  16. cpuset system tty37 ttyAMA0
  17. dev_mgr tty tty38 ttyS0
  18. dri tty0 tty39 ttyprintk
  19. fd tty1 tty4 unix
  20. freezer tty10 tty40 urandom
  21. fscklogs tty11 tty41 vchiq
  22. full tty12 tty42 vcs
  23. gpiochip0 tty13 tty43 vcs1
  24. gpiochip1 tty14 tty44 vcsa
  25. graphics tty15 tty45 vcsa1
  26. hdf_bl tty16 tty46 vcsu
  27. hdf_input_host tty17 tty47 vcsu1
  28. hdf_misc_vibrator tty18 tty48 vga_arbiter
  29. hdf_sensor_manager_ap tty19 tty49 vndbinder
  30. hwbinder tty2 tty5 watchdog
  31. hwrng tty20 tty50 watchdog0
  32. input tty21 tty51 zero
  33. kmsg tty22 tty52
  34. linux,cma tty23 tty53

基本算是启动成功了,接下来考虑打算用HDF的方式添加一下设备。来验证HDF驱动框架是否运转正常。

了解虚拟化的灾难恢复实践和实用性

虚拟拟化灾难恢复的元素在物理世界中是不可用的,可以使IT生活更轻松。是不是该让组织实现虚拟化了吗?虚拟化灾难恢复已经采取了一些复杂的灾难恢复措施,但是许多管理员误解或曲解了虚拟世界中这种模式转变的好处。关键的是,虚拟灾难恢复必须仍然保持真实的灾难恢复的最终结果...
虚拟主机虚拟化灾难恢复

攻击者利用 Confluence 漏洞,入侵Jenkins项目服务器

Jenkins 服务器背后开发团队披露了一个安全漏洞,该漏洞是一个OGNL(对象导航图语言)注入问题。经过身份验证的攻击者可以利用该漏洞,在Confluence 服务器和数据中心执行任意代码,攻击者在一台服务器上部署了加密挖矿工具。Jenkins 服务器披露一...
服务器漏洞服务器安全JenkinsConfluence

使用 Grafana+collectd+InfluxDB 打造现代监控系统

想打造 New Relic 那样漂亮的实时监控系统我们只需要 InfluxDB/collectd/Grafana 这三个工具,这三个工具的关系是这样的:采集数据(collectd)-> 存储数据(InfluxDB) -> 显示数据(Grafana)...
服务器运维

从2020到2028年,对DDoS防护软件的市场需求将不断增长

分布式拒绝服务(DDoS)攻击是一种恶意攻击,它借助于客户/服务器技术,将多个计算机联合起来作为攻击平台,对一个或多个目标发动DDoS攻击,从而成倍地提高拒绝服务攻击的为例。DDoS攻击通过大量合法的请求占用大量网络资源从而破坏常规网络流量,使得网络瘫痪。近年...
服务器安全DDOS防护DDosweb安全