4.4.4. 系统小型化裁剪

4.4.4.1. 概述

在嵌入式系统开发过程中,系统裁剪旨在去除不必要的功能和文件,以减少对系统资源(如存储、内存和 CPU)的占用,并提升整体性能。通过对系统各个组成部分进行优化和调整,裁剪过程去除了冗余组件,保留了必需的功能,从而确保系统能够更好地适应特定硬件平台和应用需求。

4.4.4.2. 系统裁剪简介

系统裁剪的主要目的是优化存储占用、降低功耗、提升性能,并减少内存占用。这不仅能有效节省存储空间,以适应资源有限的嵌入式设备,还能提高系统启动速度和响应效率,减少资源浪费。

  • 减小存储占用:通过裁剪不必要的功能和模块,减少文件系统、内核、启动程序等占用的存储空间,适应资源受限的硬件环境。

  • 提高启动速度:精简后的系统在启动时能够加载更少的模块,启动过程更加高效。

  • 提升系统性能:去除不必要的功能和驱动,减少内存占用,提升系统响应速度和稳定性。

  • 定制化系统:根据实际需求定制系统组件,实现精细化控制,增强系统的可维护性和可扩展性。

当前系统主要镜像有 uboot、 kernel、 rootfs 等,它们的大小根据 系统分区表 可以获取到:

镜像 大小
uboot 2M
kernel 12M
rootfs 250M

可以看出,在系统镜像中, uboot、 kernel 和 rootfs 的体积呈现出递增的趋势。相较于小尺寸的组件,大尺寸组件的裁剪能够带来更显著的体积缩减效果。例如,对 rootfs 进行 1MB 的裁剪可能相对容易,但要实现相同幅度的裁剪在 uboot 上则要困难得多。 因此,系统裁剪的工作重点应当放在 kernel 和 rootfs 上,这两个部分的优化将对整体系统的大小产生决定性的影响。

4.4.4.3. 系统裁剪方式

uboot 裁剪

uboot 是嵌入式设备中的引导加载程序,其主要功能是启动设备、加载内核和初始化硬件。在进行 uboot 裁剪时,主要目标是精简 uboot 的代码,删除与硬件平台无关的模块和功能。

本平台中 uboot 配置文件是 uboot/configs/hobot_x5_soc_defconfig,可以使用如下命令进行 uboot 的选项配置:

./bd.sh uboot menuconfig

该命令会自动使用板级配置文件中设置的 uboot 配置文件,在配置完成后,自动完成 savedefconfig 和保存工作。该命令详细说明可以参考 配置 Uboot 选项参数 章节。

命令执行成功后会打开 uboot 图形化配置界面,此时可以在这个交互界面下完成选项的配置:

uboot_config

在这个界面,即可根据需求禁用不需要的功能或者命令,以减小 uboot 镜像的大小。

  • 禁用不需要的命令

    例如,如果不需要 memtest 命令,可以禁用该命令,在 menuconfig 界面取消选中即可:

    memtest_cmd

  • 禁用文件系统支持

    如果不需要支持某些文件系统(如 FAT、 ext4 等),可以通过取消相关定义来禁用。例如,禁用 FAT 文件系统支持:

    FAT_FS

  • 禁用不需要的硬件驱动

    如果不需要 I2C 设备支持,可以禁用 I2C 驱动,在 menuconfig 界面取消选中 I2C support 即可:

    I2C_CONFIG

在 menuconfig 的配置界面上完成配置后,选择 Exit 退出,根据提示选择 Yes 保存修改到 .config 文件 (本平台会保存到 uboot/configs/hobot_x5_auto_defconfig 文件)中。

修改完配置项后,需要清理旧的构建文件,并重新编译 uboot 镜像:

# 清理旧的编译文件
./bd.sh uboot clean
# 重新编译
./bd.sh uboot

Linux 内核裁剪

Linux 内核是嵌入式系统的核心,裁剪的目标是根据需求,移除不必要的驱动程序、功能以及文件系统支持,以降低内核的体积和资源消耗,从而得到一个精简高效的 Linux 系统。

通常关于 Linux 内核裁剪主要有如下方法:

  • 删除不使用的功能。如符号表、打印、调试等功能。

  • 删除不使用的驱动。

  • 修改内核源代码。

禁用内核功能、驱动

与 uboot 配置过程类似,本平台提供了相关命令进行 Kernel 的选项配置:

./bd.sh boot menuconfig

该命令详细说明可以参考 配置 Kernel 选项参数 章节。命令执行成功后会打开 Kernel 图形化配置界面,可以在这个交互界面下完成选项的配置,删除不需要的功能模块:

kernel_config

在 Linux 内核 menuconfig 界面中删除不需要的功能或者驱动的操作过程与 uboot 配置相同。内核裁剪的关键在于准确识别哪些部分可以删除,以避免影响系统的正常功能。在 menuconfig 配置界面完成设置后,选择 Exit 退出,并根据提示选择 Yes 保存修改到 .config 文件中(本平台一般使用的是 kernel/arch/arm64/configs/hobot_x5_soc_defconfig)。

修改内核源代码

内核源码庞大,直接修改往往难度很大,可借助相关工具来评估模块以及符号的大小,然后进行针对性的裁剪。

可以使用如下命令显示 vmlinux 文件中的符号信息,vmlinux 文件位于 out/build/kernel 下:

nm --size vmlinux | sort -k 2 -n -r

命令解释:

  • nm --size vmlinux:列出 vmlinux 文件中的符号信息,并显示每个符号的大小(以字节为单位)。

  • sort -k 2 -n -r

    • -k 2:按照第二列(即符号的大小列)进行排序。

    • -n:以数值大小排序,而不是按字典顺序。

    • -r:按降序排序,即从大到小。

截取得到的部分日志如下:

out/build/kernel$ nm --size vmlinux | sort -k 2 -n -r
0000000000200000 b _buf_log_main
0000000000058000 d _printk_rb_static_infos
0000000000040000 b _buf_log_system
0000000000040000 b _buf_log_radio
0000000000040000 b _buf_log_events
0000000000020000 b __log_buf
0000000000018000 d _printk_rb_static_descs
00000000000082f8 b ipc_shm_data
0000000000006000 b memblock_memory_init_regions
0000000000004020 B hstates
0000000000003e14 T hidinput_connect
0000000000003b88 r edid_cea_modes_1
00000000000039c0 R v4l2_dv_timings_presets
0000000000003740 r alg_test_descs
00000000000035c0 r orientation_data
0000000000003480 r wm8962_dapm_widgets
00000000000033b4 T ZSTD_compressBlock_doubleFast_dictMatchState
0000000000002fa8 t allowlist

日志解读:

每一行包含了以下信息:

  • 地址(如 0000000000200000):该符号在 vmlinux 中的地址。

  • 大小(如 b, d, t, T, r 等符号类型后面的数值):表示符号所占的字节数。

  • 符号类型(如 T, b, d 等):表示符号的类型。

  • 符号名(如 _buf_log_main, _printk_rb_static_infos 等):符号的名称。

例如:

0000000000200000 b _buf_log_main
0000000000058000 d _printk_rb_static_infos

在这个输出中:

  • _buf_log_main 的大小为 0x200000(即 2MB),并且它是一个 BSS 段的符号(b 表示 BSS)。

  • _printk_rb_static_infos 的大小为 0x58000(即 348KB),并且它是一个数据段的符号(d 表示数据)。

符号类型介绍:

  • T:表示符号是一个函数并且位于文本(代码)段中。

  • t:表示符号是一个局部函数,位于文本段中。

  • D:表示符号是一个数据段变量。

  • d:表示符号是一个局部数据变量。

  • b:表示符号是一个 BSS 段变量(未初始化数据)。

  • r:表示符号是只读数据。

  • R:表示符号是只读数据,且其地址是由链接器在加载时填充的。

  • W:表示符号是一个弱符号。

根据符号类型可以初步判断哪些内容是可以删除的:

  • BSS 段 (b):这部分的符号表示未初始化的静态变量,这些符号可能占用空间,但它们通常是可以裁剪的。如果这些符号对应的变量没有被使用,就可以考虑删除或优化。

  • 数据段 (d):这部分的符号表示已初始化的全局变量,需要确认是否所有的全局变量都被需要,没有使用的全局变量可以裁剪。

  • 只读数据段 (rR):表示只读的全局变量,通常是库函数中的常量数据。这些数据中对于没有被使用的部分是可以被优化的。

  • 文本段 (Tt):这部分的符号表示函数代码。如果某些函数不被使用或只有在特定条件下才被调用,可以是裁剪的候选。特别是局部函数(t)可以分析后确认是否被优化或者从内核配置中禁用。

  • 弱符号 (W):这类符号是弱符号,通常是可选的或不太重要的。可以考虑裁剪。

可以优先聚焦在那些非常大的符号上,尤其是那些占用数十 KB 或更多内存的符号。确认它是否真的需要,如果不需要,就将其裁剪掉,这样可以节省较多的空间。

其他裁剪方向

  • 去除调试信息 如果目标是生产环境,可以通过禁用调试符号和信息来减少内核镜像的大小。 可以在 menuconfig 中禁用以下选项:

    CONFIG_DEBUG_INFO=n  # 禁用调试信息
    CONFIG_DEBUG_KERNEL=n  # 禁用内核调试
    

根文件系统裁剪

本平台的根文件系统是通过 buildroot 来制作的,详细过程可以参考 使用 Buildroot 制作根文件系统 章节。

文件系统裁剪的主要思路是删、换、压:

  • :删除不需要的内容。如帮助文档、没用到的库、调试程序等。

  • :使用小尺寸的实现替换大尺寸的实现。如使用 musl libc 库替换 glibc 库等。

  • :使用合适的压缩算法。

应用程序及冗余文件裁剪:

在不影响整体功能的情况下,一些应用程序或冗余文件往往可以删除:

  • 调试工具:比如 tcpdump、 mpstat、 strace 等等。

  • 性能测试工具:比如 lmbench、 sysstat、 tiobench 等等。

  • 冗余文件:帮助文档、辅助程序、配置文件和数据模块等,又比如很多应用有相同的功能,只留其一。

  • 采用具有通用功能的替代软件包。 Linux 上有许多具有相似功能的软件包,可以选择其中占存储空间较小的软件包并移植到嵌入式设备上。

  • 资源文件:一些音视频以及 UI 资源往往占用很大空间,如果没有用到,也需要删除。

关于库的裁剪:

  • 使用较小的 C 库,如 musl libc, uclibc 等来替换 glibc。

  • 删除没有用到的库。

可以在 system/buildroot/source 目录下执行执行下面命令删除不需要的应用以及库:

./build.sh menuconfig x5_system_defconfig

进入 menuconfig 界面进行配置:

buildroot_packages

根文件系统中所有的应用包都在 target packages 目录下,可以根据需求进行修改。比如,禁用 ffmpeg 应用包,就可以在该目录下取消选中 ffmpeg 配置项:

buildroot_ffmpeg

menuconfig 配置界面完成设置后,选择 Exit 退出,并根据提示选择 Yes 保存修改到 .config 文件(本平台是 system/buildroot/source/configs/x5_system_defconfig)中。

接着,先清理先前的内容,并重新执行编译命令:

cd system/buildroot/source
./build.sh clean x5_system_defconfig
./build.sh build x5_system_defconfig 0.0.1

另外,strip 会去掉应用程序与库的符号信息和调试信息,大大减少空间占用。本平台默认开启了 buildroot 的 strip 配置项:

buildroot_strip

该配置项将使用 strip 命令删除目标文件系统中的二进制文件和库,这主要是通过删除调试符号来节省空间,本机调试需要目标上的调试符号,但使用远程调试时则不需要。

4.4.4.4. 系统裁剪的基本原则

在进行系统裁剪的过程中,为了确保裁剪后系统能够正常工作并满足性能和资源要求,需要遵循以下原则:

  • 按需求裁剪

    • 明确目标:裁剪应根据实际应用需求来进行。不要盲目裁剪,首先需要清楚系 需要支持哪些功能、模块和硬件。裁剪的目的是为了适应特定的硬件平台和应用场景, 不是单纯地减小系统体积。

    • 最小化功能集:根据使用场景只保留必要的功能和服务,避免裁剪过多,导致系统无法提供预期功能。

  • 逐步裁剪

    • 分阶段进行:裁剪过程应分阶段进行,从最不重要的模块开始,逐步移除不必要的功能。在每一阶段,进行测试和验证,确保系统的稳定性和功能完整性。

    • 保留核心功能:始终确保系统的基本功能不受影响。例如,内核裁剪时,要特别注意保留对硬件的基本支持,特别是设备驱动和文件系统支持。

  • 安全性和稳定性优先

    • 避免破坏性裁剪:裁剪时不要移除或禁用系统的核心功能,如内核调度、内存管理、硬件抽象层 (HAL) 等。过度裁剪可能会导致系统不稳定,甚至无法启动。

    • 充分测试:每次裁剪后,都应对系统进行全面的功能验证,尤其是对硬件和网络等关键模块的测试。确保不会引入安全漏洞或导致系统崩溃。

  • 最小化依赖

    • 去除冗余依赖:裁剪时应尽量减少对不必要的库和工具的依赖,特别是在 Buildroot 和根文件系统的裁剪中。移除不需要的依赖项,避免增加不必要的库文件和二进制文件。

    • 使用轻量级替代品:例如,用 BusyBox 替代多个常规工具集,选择更小的、资源占用更低的库和工具,以减小根文件系统的体积。

  • 合理管理内核配置

    • 精简内核配置:在内核裁剪过程中,应根据目标硬件精简内核配置。删除不必要的驱动程序、文件系统支持和调试功能,避免加载不需要的模块。

    • 模块化管理:内核模块应该只在需要时加载,减少不必要的内核模块或驱动,这不仅有助于减少内核的体积,还可以优化系统性能。

  • 高效管理存储和内存

    • 优化存储占用:裁剪时应重点关注存储的优化,特别是嵌入式设备存储有限的情况下,尽量减少文件系统 内核镜像和 Uboot 文件的大小。

    • 内存占用优化:减少不必要的内存占用,尤其是在 RAM 限制较大的设备上。通过移除不必要的服务、程序和驱动,可以有效提高内存利用率。

  • 模块化与可扩展性

    • 保持模块化设计:尽量保留系统的模块化特性,即使进行裁剪,也应确保系统可以在需要时灵活地加载模块,而不是直接将所有功能集成到系统中。

    • 可扩展性:在裁剪过程中,不要限制未来的扩展能力。确保裁剪的部分能够轻松地被重新加入到系统中,以便后续的功能扩展。

  • 遵循工具链和标准

    • 使用标准工具链:裁剪过程中应使用一致的工具链和配置工具(如 Uboot 的 make menuconfig、 Kernel 的 make menuconfig 或 Buildroot 的配置工具)进行操作。这些工具链已经经过优化和广泛使用,能够帮助确保裁剪的系统在目标平台上正常工作。

    • 文档化裁剪过程:对于每一次裁剪的决策和步骤,应进行详细记录。这样可以帮助后续人员理解裁剪的目的、方法和实现,便于管理和后期修改。

  • 性能与功耗平衡

    • 优化性能:裁剪不仅是为了减小体积,还应兼顾性能优化。可以通过移除不必要的功能和配置来提高系统性能。

    • 考虑功耗:在嵌入式系统中,功耗往往是设计中的重要考虑因素。裁剪时,可以优先选择低功耗的硬件支持和软件功能,优化系统的功耗表现。

  • 保持向后兼容性

    • 避免破坏兼容性:特别是在内核裁剪和 Uboot 裁剪时,要确保与原先系统兼容。移除某些模块时,注意不要影响现有的硬件支持和系统接口,以便后续的更新和维护不至于引入不必要的问题。

4.4.4.5. 系统裁剪实例

由于 NAND 容量有限,在实际使用中可以根据场景对 NAND 的 Kernel、 system、 hbre 等进行剪裁。以下提供了适用于 BSP 包的 Kernel 和 System 最小配置。只需将这些配置项替换到相应的配置文件中,完成系统裁剪,重新编译后,便可生成最小系统镜像。

system 最小配置

如下是 system 的最小配置:

BR2_aarch64=y
BR2_cortex_a55=y
BR2_TOOLCHAIN_EXTERNAL=y
BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y
BR2_TOOLCHAIN_EXTERNAL_CUSTOM_PREFIX="aarch64-none-linux-gnu"
BR2_TOOLCHAIN_EXTERNAL_GCC_11=y
BR2_TOOLCHAIN_EXTERNAL_HEADERS_4_20=y
BR2_TOOLCHAIN_EXTERNAL_CUSTOM_GLIBC=y
# BR2_TOOLCHAIN_EXTERNAL_INET_RPC is not set
BR2_TOOLCHAIN_EXTERNAL_CXX=y
BR2_CCACHE=y
# BR2_PIC_PIE is not set
BR2_SSP_NONE=y
BR2_RELRO_NONE=y
BR2_FORTIFY_SOURCE_NONE=y
BR2_INIT_SYSV=y
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
BR2_ROOTFS_MERGED_USR=y
BR2_TARGET_GENERIC_ROOT_PASSWD="root"
BR2_SYSTEM_BIN_SH_BASH=y
BR2_SYSTEM_DEFAULT_PATH="/bin:/sbin:/usr/bin:/usr/sbin"
BR2_PACKAGE_FFMPEG=y
BR2_PACKAGE_FFMPEG_ENCODERS=""
BR2_PACKAGE_FFMPEG_DECODERS=""
BR2_PACKAGE_FFMPEG_MUXERS=""
BR2_PACKAGE_FFMPEG_DEMUXERS=""
BR2_PACKAGE_FFMPEG_PARSERS=""
BR2_PACKAGE_FFMPEG_BSFS=""
BR2_PACKAGE_FFMPEG_PROTOCOLS=""
BR2_PACKAGE_FFMPEG_FILTERS=""
# BR2_PACKAGE_FFMPEG_INDEVS is not set
# BR2_PACKAGE_FFMPEG_OUTDEVS is not set
BR2_PACKAGE_FFMPEG_EXTRACONF=" --disable-everything --enable-gray --enable-safe-bitstream-reader --enable-encoder=adpcm_g726le --enable-encoder=flac  --enable-encoder=pcm_alaw --enable-encoder=pcm_mulaw --enable-encoder=adpcm_ima_wav --enable-encoder=srt --enable-encoder=subrip  --enable-encoder=text  --enable-encoder=movtext --enable-encoder=ass    --enable-decoder=adpcm_g726le   --enable-decoder=flac           --enable-decoder=pcm_alaw      --enable-decoder=pcm_mulaw       --enable-decoder=adpcm_ima_wav  --enable-decoder=h264   --enable-decoder=hevc   --enable-decoder=mjpeg  --enable-muxer=adts     --enable-muxer=mpegts   --enable-muxer=rtsp     --enable-muxer=rtp      --enable-muxer=avi      --enable-muxer=flv      --enable-muxer=hls      --enable-muxer=mp4      --enable-muxer=flac --enable-demuxer=flac --enable-demuxer=aac --enable-demuxer=mpegts  --enable-demuxer=h264 --enable-demuxer=hevc --enable-demuxer=mjpeg --enable-demuxer=image2  --enable-demuxer=mov --enable-demuxer=rtsp --enable-demuxer=hls  --enable-demuxer=rtp --enable-demuxer=flv --enable-demuxer=mpegps --enable-demuxer=mpegtsraw --enable-demuxer=mpegvideo --enable-parser=h264 --enable-parser=hevc --enable-parser=aac --enable-parser=flac --enable-parser=mjpeg --enable-parser=mpeg4video --enable-parser=mpegvideo --enable-parser=mpegaudio --enable-bsf=h264_mp4toannexb --enable-bsf=aac_adtstoasc --enable-bsf=null --enable-bsf=extract_extradata --enable-protocol=file --enable-protocol=http --enable-protocol=rtp --enable-protocol=rtmpts --enable-protocol=https --enable-protocol=hls --enable-protocol=data --disable-armv5te --disable-armv6 --disable-mmx --disable-optimizations --disable-asm "
BR2_PACKAGE_BZIP2=y
BR2_PACKAGE_MEMSTAT=y
BR2_PACKAGE_MTD=y
BR2_PACKAGE_EUDEV_RULES_GEN=y
# BR2_PACKAGE_EUDEV_ENABLE_HWDB is not set
BR2_PACKAGE_I2C_TOOLS=y
BR2_PACKAGE_TINYALSA=y
BR2_PACKAGE_MINIZIP_ZLIB=y
BR2_PACKAGE_LIBKCAPI=y
BR2_PACKAGE_LIBKCAPI_ENCAPP=y
BR2_PACKAGE_LIBKCAPI_HASHER=y
BR2_PACKAGE_LIBKCAPI_RNGAPP=y
BR2_PACKAGE_LIBOPENSSL_BIN=y
BR2_PACKAGE_LIBOPENSSL_ENGINES=y
BR2_PACKAGE_LIBGPIOD=y
BR2_PACKAGE_LIBGPIOD_TOOLS=y
BR2_PACKAGE_CJSON=y
BR2_PACKAGE_JSONCPP=y
BR2_PACKAGE_LIBEVENT=y
BR2_PACKAGE_LRZSZ=y
BR2_PACKAGE_NET_TOOLS=y
BR2_PACKAGE_OPENSSH=y
BR2_PACKAGE_OPTEE_CLIENT=y
# BR2_PACKAGE_OPTEE_CLIENT_RPMB_EMU is not set
BR2_PACKAGE_SYSKLOGD=y
BR2_PACKAGE_TAR=y
BR2_PACKAGE_UTIL_LINUX_LIBUUID=y

将上面内容替换 BSP 包的 system/buildroot/source/configs/x5_system_defconfig 文件中的内容。

Kernel 最小配置

如下是 Kernel 的最小配置:

CONFIG_WERROR=y
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
CONFIG_IRQ_TIME_ACCOUNTING=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASKSTATS=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_MEMCG=y
CONFIG_BLK_CGROUP=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_NAMESPACES=y
CONFIG_USER_NS=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
# CONFIG_RD_ZSTD is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_ARCH_HOBOT=y
CONFIG_ARCH_HOBOT_X5=y
CONFIG_ARM64_VA_BITS_48=y
CONFIG_SCHED_MC=y
CONFIG_SCHED_SMT=y
CONFIG_NR_CPUS=8
CONFIG_HZ_100=y
CONFIG_PARAVIRT=y
CONFIG_KEXEC_FILE=y
CONFIG_CRASH_DUMP=y
CONFIG_COMPAT=y
CONFIG_RANDOMIZE_BASE=y
CONFIG_HOBOT_BOOT_LZ4=y
CONFIG_PM_DEBUG=y
CONFIG_PM_ADVANCED_DEBUG=y
CONFIG_PM_TEST_SUSPEND=y
CONFIG_CPU_IDLE=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPUFREQ_DT=y
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_PARTITION_ADVANCED=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_PAGE_REPORTING=y
CONFIG_KSM=y
CONFIG_MEMORY_FAILURE=y
CONFIG_CMA=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=y
CONFIG_UNIX=y
CONFIG_UNIX_DIAG=y
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_MROUTE=y
CONFIG_NET_FOU=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
CONFIG_INET_UDP_DIAG=y
CONFIG_INET_RAW_DIAG=y
# CONFIG_IPV6 is not set
CONFIG_NETWORK_PHY_TIMESTAMPING=y
CONFIG_NETFILTER=y
CONFIG_VLAN_8021Q=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_HFSC=y
CONFIG_NET_SCH_PRIO=y
CONFIG_NET_SCH_MULTIQ=y
CONFIG_NET_SCH_TBF=y
CONFIG_NET_SCH_CBS=y
CONFIG_NET_SCH_ETF=y
CONFIG_NET_SCH_TAPRIO=y
CONFIG_NET_SCH_MQPRIO=y
CONFIG_NET_SCH_SKBPRIO=y
CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_MARK=y
CONFIG_NET_CLS_ACT=y
CONFIG_NET_ACT_POLICE=y
CONFIG_NET_ACT_GACT=y
CONFIG_NET_ACT_SKBEDIT=y
CONFIG_DCB=y
CONFIG_NETLINK_DIAG=y
CONFIG_CGROUP_NET_PRIO=y
CONFIG_CGROUP_NET_CLASSID=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_FW_LOADER_USER_HELPER=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
# CONFIG_DMIID is not set
CONFIG_EFI_CAPSULE_LOADER=y
CONFIG_EFI_DISABLE_RUNTIME=y
# CONFIG_ARM_SMCCC_SOC_ID is not set
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_CFI_STAA=y
CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_NAND_DENALI_DT=y
CONFIG_MTD_SPI_NAND=y
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_BLOCK=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=409600
CONFIG_EEPROM_AT24=y
CONFIG_HOBOT_VIO_N2D=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_ALACRITECH is not set
# CONFIG_NET_VENDOR_AMAZON is not set
# CONFIG_NET_VENDOR_AMD is not set
# CONFIG_NET_VENDOR_AQUANTIA is not set
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_VENDOR_ASIX is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CADENCE is not set
# CONFIG_NET_VENDOR_CAVIUM is not set
# CONFIG_NET_VENDOR_CORTINA is not set
# CONFIG_NET_VENDOR_DAVICOM is not set
# CONFIG_NET_VENDOR_ENGLEDER is not set
# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_FUNGIBLE is not set
# CONFIG_NET_VENDOR_GOOGLE is not set
# CONFIG_NET_VENDOR_HISILICON is not set
# CONFIG_NET_VENDOR_HUAWEI is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_ADI is not set
# CONFIG_NET_VENDOR_LITEX is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MELLANOX is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_NET_VENDOR_MICROSEMI is not set
# CONFIG_NET_VENDOR_MICROSOFT is not set
# CONFIG_NET_VENDOR_NI is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_NETRONOME is not set
# CONFIG_NET_VENDOR_PENSANDO is not set
# CONFIG_NET_VENDOR_QUALCOMM is not set
# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SOLARFLARE is not set
# CONFIG_NET_VENDOR_SMSC is not set
# CONFIG_NET_VENDOR_SOCIONEXT is not set
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_SELFTESTS=y
CONFIG_DWMAC_DWC_QOS_ETH=y
# CONFIG_NET_VENDOR_SYNOPSYS is not set
# CONFIG_NET_VENDOR_VERTEXCOM is not set
# CONFIG_NET_VENDOR_VIA is not set
# CONFIG_NET_VENDOR_WANGXUN is not set
# CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_NET_VENDOR_XILINX is not set
CONFIG_X5_ETH=y
CONFIG_JPLUS_ETH=y
CONFIG_REALTEK_PHY=y
CONFIG_USB_NET_DRIVERS=m
CONFIG_KEYBOARD_GPIO=y
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO_SERPORT is not set
CONFIG_SERIO_AMBAKMI=y
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_LEGACY_PTY_COUNT=16
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=8
CONFIG_SERIAL_8250_RUNTIME_UARTS=8
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_HW_RANDOM=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_SPI=y
CONFIG_SPI_DESIGNWARE=y
CONFIG_SPI_DW_DMA=y
CONFIG_SPI_DW_MMIO=y
CONFIG_SPI_SPIDEV=m
CONFIG_SPI_SLAVE=y
CONFIG_PPS_CLIENT_HOBOT_PPS=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_HORIZON=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_DWAPB=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_SYSCON_REBOOT_MODE=y
CONFIG_SENSORS_MR75203=y
CONFIG_THERMAL=y
CONFIG_THERMAL_WRITABLE_TRIPS=y
CONFIG_THERMAL_GOV_USER_SPACE=y
CONFIG_CPU_THERMAL=y
CONFIG_DEVFREQ_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_DW_WATCHDOG=y
CONFIG_MFD_HI6421_PMIC=y
CONFIG_MFD_HPU3501=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_DEBUG=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_HPU3501=y
CONFIG_MEDIA_SUPPORT=y
# CONFIG_DVB_NET is not set
# CONFIG_DVB_DYNAMIC_MINORS is not set
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=m
# CONFIG_RADIO_ADAPTERS is not set
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_HOBOT_VIO=m
CONFIG_HOBOT_VIO_JPLUS=y
CONFIG_HOBOT_VIO_COMMON=m
CONFIG_HOBOT_VIN_NODE=m
CONFIG_HOBOT_VCON=m
CONFIG_HOBOT_CAMSYS=m
CONFIG_HOBOT_GDC_JPLUS=m
CONFIG_HOBOT_SENSOR=m
CONFIG_HOBOT_DESERIAL=m
CONFIG_HOBOT_LPWM=m
CONFIG_HOBOT_OSD=m
CONFIG_HOBOT_VSI_CAM=m
CONFIG_HOBOT_MIPI_CSI=y
CONFIG_HOBOT_CODEC_NODE=m
CONFIG_HOBOT_MIPI_CSI_DRV=m
CONFIG_HOBOT_MIPI_HOST_MAX_NUM=6
CONFIG_HOBOT_MIPI_HOST_SNRCLK=y
CONFIG_HOBOT_MIPI_DEV_MAX_NUM=2
CONFIG_HOBOT_MIPI_PHY=m
CONFIG_HOBOT_MIPI_DEBUG=m
CONFIG_VIDEO_VS_ISP_NAT=m
CONFIG_VIDEO_VS_VSE_NAT=m
CONFIG_VIDEO_VS_SIF_NAT=m
CONFIG_VIDEO_VS_CAM_PULSE=m
CONFIG_VIDEO_VS_ISP_V4L=m
CONFIG_VIDEO_VS_VSE_V4L=m
CONFIG_VIDEO_VS_SIF_V4L=m
CONFIG_VIDEO_VS_GDC_ARM_V4L=m
CONFIG_VIDEO_HOBOTC_JPU=m
CONFIG_VIDEO_HOBOTC_VPU=m
# CONFIG_CXD2880_SPI_DRV is not set
# CONFIG_MEDIA_TUNER_E4000 is not set
# CONFIG_MEDIA_TUNER_FC0011 is not set
# CONFIG_MEDIA_TUNER_FC0012 is not set
# CONFIG_MEDIA_TUNER_FC0013 is not set
# CONFIG_MEDIA_TUNER_FC2580 is not set
# CONFIG_MEDIA_TUNER_IT913X is not set
# CONFIG_MEDIA_TUNER_M88RS6000T is not set
# CONFIG_MEDIA_TUNER_MAX2165 is not set
# CONFIG_MEDIA_TUNER_MC44S803 is not set
# CONFIG_MEDIA_TUNER_MSI001 is not set
# CONFIG_MEDIA_TUNER_MT2060 is not set
# CONFIG_MEDIA_TUNER_MT2063 is not set
# CONFIG_MEDIA_TUNER_MT20XX is not set
# CONFIG_MEDIA_TUNER_MT2131 is not set
# CONFIG_MEDIA_TUNER_MT2266 is not set
# CONFIG_MEDIA_TUNER_MXL301RF is not set
# CONFIG_MEDIA_TUNER_MXL5005S is not set
# CONFIG_MEDIA_TUNER_MXL5007T is not set
# CONFIG_MEDIA_TUNER_QM1D1B0004 is not set
# CONFIG_MEDIA_TUNER_QM1D1C0042 is not set
# CONFIG_MEDIA_TUNER_QT1010 is not set
# CONFIG_MEDIA_TUNER_R820T is not set
# CONFIG_MEDIA_TUNER_SI2157 is not set
# CONFIG_MEDIA_TUNER_SIMPLE is not set
# CONFIG_MEDIA_TUNER_TDA18212 is not set
# CONFIG_MEDIA_TUNER_TDA18218 is not set
# CONFIG_MEDIA_TUNER_TDA18250 is not set
# CONFIG_MEDIA_TUNER_TDA18271 is not set
# CONFIG_MEDIA_TUNER_TDA827X is not set
# CONFIG_MEDIA_TUNER_TDA8290 is not set
# CONFIG_MEDIA_TUNER_TDA9887 is not set
# CONFIG_MEDIA_TUNER_TEA5761 is not set
# CONFIG_MEDIA_TUNER_TEA5767 is not set
# CONFIG_MEDIA_TUNER_TUA9001 is not set
# CONFIG_MEDIA_TUNER_XC2028 is not set
# CONFIG_MEDIA_TUNER_XC4000 is not set
# CONFIG_MEDIA_TUNER_XC5000 is not set
# CONFIG_DVB_M88DS3103 is not set
# CONFIG_DVB_MXL5XX is not set
# CONFIG_DVB_STB0899 is not set
# CONFIG_DVB_STB6100 is not set
# CONFIG_DVB_STV090x is not set
# CONFIG_DVB_STV0910 is not set
# CONFIG_DVB_STV6110x is not set
# CONFIG_DVB_STV6111 is not set
# CONFIG_DVB_DRXK is not set
# CONFIG_DVB_MN88472 is not set
# CONFIG_DVB_MN88473 is not set
# CONFIG_DVB_SI2165 is not set
# CONFIG_DVB_TDA18271C2DD is not set
# CONFIG_DVB_CX24110 is not set
# CONFIG_DVB_CX24116 is not set
# CONFIG_DVB_CX24117 is not set
# CONFIG_DVB_CX24120 is not set
# CONFIG_DVB_CX24123 is not set
# CONFIG_DVB_DS3000 is not set
# CONFIG_DVB_MB86A16 is not set
# CONFIG_DVB_MT312 is not set
# CONFIG_DVB_S5H1420 is not set
# CONFIG_DVB_SI21XX is not set
# CONFIG_DVB_STB6000 is not set
# CONFIG_DVB_STV0288 is not set
# CONFIG_DVB_STV0299 is not set
# CONFIG_DVB_STV0900 is not set
# CONFIG_DVB_STV6110 is not set
# CONFIG_DVB_TDA10071 is not set
# CONFIG_DVB_TDA10086 is not set
# CONFIG_DVB_TDA8083 is not set
# CONFIG_DVB_TDA8261 is not set
# CONFIG_DVB_TDA826X is not set
# CONFIG_DVB_TS2020 is not set
# CONFIG_DVB_TUA6100 is not set
# CONFIG_DVB_TUNER_CX24113 is not set
# CONFIG_DVB_TUNER_ITD1000 is not set
# CONFIG_DVB_VES1X93 is not set
# CONFIG_DVB_ZL10036 is not set
# CONFIG_DVB_ZL10039 is not set
# CONFIG_DVB_AF9013 is not set
# CONFIG_DVB_CX22700 is not set
# CONFIG_DVB_CX22702 is not set
# CONFIG_DVB_CXD2820R is not set
# CONFIG_DVB_CXD2841ER is not set
# CONFIG_DVB_DIB3000MB is not set
# CONFIG_DVB_DIB3000MC is not set
# CONFIG_DVB_DIB7000M is not set
# CONFIG_DVB_DIB7000P is not set
# CONFIG_DVB_DIB9000 is not set
# CONFIG_DVB_DRXD is not set
# CONFIG_DVB_EC100 is not set
# CONFIG_DVB_L64781 is not set
# CONFIG_DVB_MT352 is not set
# CONFIG_DVB_NXT6000 is not set
# CONFIG_DVB_RTL2830 is not set
# CONFIG_DVB_RTL2832 is not set
# CONFIG_DVB_RTL2832_SDR is not set
# CONFIG_DVB_S5H1432 is not set
# CONFIG_DVB_SI2168 is not set
# CONFIG_DVB_SP887X is not set
# CONFIG_DVB_STV0367 is not set
# CONFIG_DVB_TDA10048 is not set
# CONFIG_DVB_TDA1004X is not set
# CONFIG_DVB_ZD1301_DEMOD is not set
# CONFIG_DVB_ZL10353 is not set
# CONFIG_DVB_CXD2880 is not set
# CONFIG_DVB_STV0297 is not set
# CONFIG_DVB_TDA10021 is not set
# CONFIG_DVB_TDA10023 is not set
# CONFIG_DVB_VES1820 is not set
# CONFIG_DVB_AU8522_DTV is not set
# CONFIG_DVB_AU8522_V4L is not set
# CONFIG_DVB_BCM3510 is not set
# CONFIG_DVB_LG2160 is not set
# CONFIG_DVB_LGDT3305 is not set
# CONFIG_DVB_LGDT3306A is not set
# CONFIG_DVB_LGDT330X is not set
# CONFIG_DVB_MXL692 is not set
# CONFIG_DVB_NXT200X is not set
# CONFIG_DVB_OR51132 is not set
# CONFIG_DVB_OR51211 is not set
# CONFIG_DVB_S5H1409 is not set
# CONFIG_DVB_S5H1411 is not set
# CONFIG_DVB_DIB8000 is not set
# CONFIG_DVB_MB86A20S is not set
# CONFIG_DVB_S921 is not set
# CONFIG_DVB_MN88443X is not set
# CONFIG_DVB_TC90522 is not set
# CONFIG_DVB_PLL is not set
# CONFIG_DVB_TUNER_DIB0070 is not set
# CONFIG_DVB_TUNER_DIB0090 is not set
# CONFIG_DVB_A8293 is not set
# CONFIG_DVB_AF9033 is not set
# CONFIG_DVB_ASCOT2E is not set
# CONFIG_DVB_ATBM8830 is not set
# CONFIG_DVB_HELENE is not set
# CONFIG_DVB_HORUS3A is not set
# CONFIG_DVB_ISL6405 is not set
# CONFIG_DVB_ISL6421 is not set
# CONFIG_DVB_ISL6423 is not set
# CONFIG_DVB_IX2505V is not set
# CONFIG_DVB_LGS8GL5 is not set
# CONFIG_DVB_LGS8GXX is not set
# CONFIG_DVB_LNBH25 is not set
# CONFIG_DVB_LNBH29 is not set
# CONFIG_DVB_LNBP21 is not set
# CONFIG_DVB_LNBP22 is not set
# CONFIG_DVB_M88RS2000 is not set
# CONFIG_DVB_TDA665x is not set
# CONFIG_DVB_DRX39XYJ is not set
# CONFIG_DVB_CXD2099 is not set
# CONFIG_DVB_SP2 is not set
CONFIG_DRM=y
CONFIG_DRM_PANEL_ATK_MD0550=y
CONFIG_DRM_SII902X=y
CONFIG_VERISILICON_X5_SYSCON_BRIDGE=m
CONFIG_DRM_VERISILICON=m
CONFIG_VERISILICON_DC8000_NANO=y
CONFIG_VERISILICON_BT1120=y
CONFIG_VERISILICON_DW_MIPI_DSI=y
CONFIG_VERISILICON_WRITEBACK_SIF=y
CONFIG_VERISILICON_GEM_ION=y
CONFIG_VERISILICON_GC_PROC_SUPPORT=y
CONFIG_FB=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BACKLIGHT_PWM=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
CONFIG_SND_DESIGNWARE_I2S=m
CONFIG_SND_DESIGNWARE_PCM=y
CONFIG_SND_ARCHBAND_PDM=y
CONFIG_SND_VIRT_CODEC=y
CONFIG_SND_SOC_WM8962=y
CONFIG_SND_DUPLEX_CARD=m
CONFIG_SND_HOBOT_SOUND_MACHINE=m
CONFIG_SND_SIMPLE_CARD=m
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_STORAGE=y
CONFIG_USB_UAS=y
CONFIG_USB_DWC3=y
CONFIG_USB_GADGET=y
CONFIG_USB_CONFIGFS=m
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_ACM=y
CONFIG_USB_CONFIGFS_OBEX=y
CONFIG_USB_CONFIGFS_NCM=y
CONFIG_USB_CONFIGFS_ECM=y
CONFIG_USB_CONFIGFS_ECM_SUBSET=y
CONFIG_USB_CONFIGFS_RNDIS=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
CONFIG_USB_CONFIGFS_F_LB_SS=y
CONFIG_USB_CONFIGFS_F_FS=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_UVC=y
CONFIG_USB_ZERO=m
CONFIG_USB_ETH=m
CONFIG_USB_FUNCTIONFS=m
CONFIG_USB_FUNCTIONFS_ETH=y
CONFIG_USB_FUNCTIONFS_RNDIS=y
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
CONFIG_USB_G_MULTI=m
CONFIG_USB_G_MULTI_CDC=y
CONFIG_USB_G_WEBCAM=m
CONFIG_USB_RAW_GADGET=m
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_OF_DWCMSHC=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DEBUG=y
CONFIG_RTC_DRV_DWAPB=y
CONFIG_DMADEVICES=y
CONFIG_DW_AXI_DMAC=y
CONFIG_UIO=y
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
CONFIG_STAGING=y
CONFIG_ANDROID_LOGGER=y
CONFIG_BOOTLOADER_LOG=y
CONFIG_ION=y
CONFIG_ION_SYSTEM_HEAP=y
CONFIG_ION_CARVEOUT_HEAP=y
CONFIG_ION_CHUNK_HEAP=y
CONFIG_ION_CMA_HEAP=y
CONFIG_ION_HOBOT=y
# CONFIG_FSL_ERRATUM_A008585 is not set
# CONFIG_HISILICON_ERRATUM_161010101 is not set
# CONFIG_ARM64_ERRATUM_858921 is not set
CONFIG_MAILBOX=y
CONFIG_DROBOT_LITE_MMU=y
CONFIG_REMOTEPROC=y
CONFIG_HOBOT_BPU=y
CONFIG_BPU=m
CONFIG_BPU_CORE=m
CONFIG_PM_DEVFREQ=y
CONFIG_DEVFREQ_GOV_PERFORMANCE=y
CONFIG_DEVFREQ_GOV_POWERSAVE=y
CONFIG_ARM_X5_DDRC_DEVFREQ=y
CONFIG_PM_DEVFREQ_EVENT=y
CONFIG_DEVFREQ_EVENT_X5_DFI=y
CONFIG_EXTCON=y
CONFIG_EXTCON_USB_GPIO=y
CONFIG_IIO=y
CONFIG_IIO_SW_TRIGGER=y
CONFIG_GUC_ADC=y
CONFIG_PWM=y
CONFIG_PWM_DROBOT=y
CONFIG_PHY_SNPS_MIPI_DPHY=y
CONFIG_ARM_DSU_PMU=y
CONFIG_NVMEM_HORIZON_EFUSE=y
CONFIG_TEE=y
CONFIG_OPTEE=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_FANOTIFY=y
CONFIG_VFAT_FS=y
CONFIG_EXFAT_FS=y
CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
CONFIG_EFIVAR_FS=y
CONFIG_UBIFS_FS=y
CONFIG_PSTORE=y
CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_PMSG=y
CONFIG_PSTORE_RAM=y
CONFIG_SCHED_LOGGER=y
CONFIG_NFS_FS=y
CONFIG_SUNRPC_DEBUG=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_CRYPTO_USER=y
CONFIG_CRYPTO_DH=y
CONFIG_CRYPTO_ECDH=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_CMAC=y
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_USER_API_SKCIPHER=y
CONFIG_CRYPTO_USER_API_RNG=y
CONFIG_CRYPTO_USER_API_AEAD=y
CONFIG_CRYPTO_DEV_TE=y
CONFIG_CRC_ITU_T=y
CONFIG_CRC7=y
CONFIG_LIBCRC32C=m
CONFIG_XZ_DEC=y
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=32
CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO_DWARF4=y
CONFIG_GDB_SCRIPTS=y
CONFIG_VMLINUX_MAP=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_FTRACE is not set
# CONFIG_STRICT_DEVMEM is not set
CONFIG_CORESIGHT=y
CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
CONFIG_CORESIGHT_CATU=y
CONFIG_CORESIGHT_SINK_TPIU=y
CONFIG_CORESIGHT_SINK_ETBV10=y
CONFIG_CORESIGHT_SOURCE_ETM4X=y
CONFIG_CORESIGHT_CTI=y
CONFIG_CORESIGHT_CTI_INTEGRATION_REGS=y
CONFIG_MEMTEST=y

将上述内容替换 BSP 包的 kernel/arch/arm64/configs/hobot_x5_soc_defconfig 文件中的内容。

编译与测试

编译新镜像

1)编译根文件系统:

按照下面命令重新编译根文件系统:

cd system/ubuntu/source
./build.sh clean
./build.sh menuconfig x5_system_defconfig
./build.sh build x5_system_defconfig 0.0.1

有关 buildroot 编译根文件系统的详细说明请参考  使用 Buildroot 制作根文件系统 章节。

生成的根文件系统镜像在 system/buildroot/source/framework/output/images 目录中:

$ cd system/buildroot/source/framework/output/images
$ ls
deb_make  dr-system_0.0.1~gcc11.3.1_all.deb  rootfs.tar  rtl_bt  rtlwifi

2)复制根文件系统镜像到预编译目录:

需要将生成的镜像复制到 system/buildroot/prebuilt 目录下,并且将 system/buildroot/prebuilt/series 文件中的根文件系统镜像的名称修改为 “ dr-system_0.0.1~gcc11.3.1_all.deb” (或者修改为编译根文件系统时候命令中加入的具体版本参数),如下:

# system/buildroot/prebuilt/series
dr-system_0.0.1~gcc11.3.1_all.deb
dr-libgtest_1.14.0~gcc11.3.rel1_arm64.deb
dr-libgdcbin_1.0.0~gcc11.3.rel1_arm64.deb
dr-perf_6.1.12~gcc11.3.rel1_arm64.deb
dr-libdnn_1.24.5~gcc11.3.rel1_arm64.deb
dr-libhpatchz_3.1.1~gcc11.3.rel1_arm64.deb

3)重新编译 BSP 包镜像:

注意 先执行 ./bd.sh distclean 命令清理掉之前的编译产物,再执行 ./bd.sh 重新编译镜像,此时选择配置项为 NAND flash,也就是选项 3 :

$ ./bd.sh distclean
$ ./bd.sh

You're building on #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025
Lunch menu... pick a combo:
      0. horizon/x5/board_x5_evb_debug_config.mk
      1. horizon/x5/board_x5_evb_jammy_debug_config.mk
      2. horizon/x5/board_x5_evb_jammy_release_config.mk
      3. horizon/x5/board_x5_evb_nand_debug_config.mk
      4. horizon/x5/board_x5_evb_nand_release_config.mk
      5. horizon/x5/board_x5_evb_release_config.mk
      6. horizon/x5/board_x5_soc_debug_config.mk
      7. horizon/x5/board_x5_soc_release_config.mk
Which would you like? [0] : 3

测试新镜像

查看裁剪后生成的根文件系统镜像大小:

$ cd system/buildroot/source/framework/output/images
$ ls -lh dr-system_0.0.1~gcc11.3.1_all.deb
-rw-r--r-- 1 sxq sxq 7.0M Jan  8 20:14 dr-system_0.0.1~gcc11.3.1_all.deb

可以看到根文件系统镜像已经变成了 7MB(裁剪之前是 25MB)。

查看裁剪后生成的 vmlinux 大小:

$ cd out/build/kernel
$ ls -lh vmlinux
-rwxr-xr-x 1 sxq sxq 252M Jan  9 11:23 vmlinux

可以看到 vmlinux 已经变成了 252MB(裁剪之前是 257MB)。

查看内核模块的大小:

$ cd out/deploy/boot/modules/lib/modules
$ du -h --max-depth=1
5.3M    ./6.1.83-DR-PL5.1_V1.0.16
5.3M    .

可以看到内核模块目录大小变成了 5.3MB(裁剪之前是 20MB)。

待编译结束,即可重新烧录镜像进行测试。
注意 烧录时需要将拨码开关配置为 “[D0:D2] 000”,将板端配置为 NAND 模式才能进行烧录,待烧录完成需要将拨码开关配置为 “[D0:D2] 101”,才能使单板配置为 NAND 模式启动。关于拨码开关的详细配置,可以参考拨码开关(以 EVB 1_b 为例)的相关章节。

关于镜像烧录详细方式,可以参考系统镜像烧写 章节。

待镜像烧录完毕,查看启动日志:

SNOTICE:  Welcome to Horizon X5 ASIC BOOTROM - V4.1
NOTICE:                 OTP config:
NOTICE:                         otp exist: true
NOTICE:                         test region size: 304
NOTICE:                         secure region size: 120
NOTICE:                         none secure region size: 56
NOTICE:   Enable MMU
NOTICE:  Booting Trusted Firmware
NOTICE:  BL1: v2.8(release):
NOTICE:  BL1: Built : 17:42:12, Oct 19 2023
NOTICE:  Enter SPI NAND-FLASH Mode......
NOTICE:   Nand PAGE_SIZE_4K
NOTICE:   Nand is_dummy = true
NOTICE:   Nand CLK_12M
NOTICE:  SPI baudrate is set to 12000000Hz
NOTICE:   Nand reset
NOTICE:  reg_status should = 0x18
NOTICE:  SPI Nand flash buffer mode set PASS
NOTICE:  Manufacturer ID 0x2c  Device ID 0x352c
NOTICE:  Enter media_source_select process(5).
NOTICE:  SPI Nand flash set quad PASS

上述 Uboot 日志中可以看到已经是 NAND flash 了。

内核中可以看到分区情况如下:

root@buildroot:~# cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00040000 00040000 "mbr"
mtd1: 00240000 00040000 "miniboot"
mtd2: 00240000 00040000 "miniboot_bak1"
mtd3: 00040000 00040000 "misc"
mtd4: 00200000 00040000 "uboot"
mtd5: 00180000 00040000 "ubootenv"
mtd6: 02000000 00040000 "boot"
mtd7: 09600000 00040000 "system"
mtd8: 06400000 00040000 "hbre"
mtd9: 0dd80000 00040000 "userdata"

日志中显示了设备的 MTD( Memory Technology Devices )分区信息,其中各个字段解释如下:

  • dev: 设备的名称标识符。

  • size: 该分区的大小,以字节为单位。

  • erasesize: 每次擦除操作的大小,以字节为单位。这个大小通常决定了闪存擦除的最小单位。

  • name: 分区的名称,通常是为特定用途或功能分配的。

各个分区的具体信息如下:

dev size erasesize name 说明
mtd0 0x00040000 (256 KB) 0x00040000 (256 KB) "mbr" 主引导记录( MBR ),通常用于启动时的分区信息。
mtd1 0x00240000 (2.25 MB) 0x00040000 (256 KB) "miniboot" 小型引导程序,用于初始化设备并加载更大程序。
mtd2 0x00240000 (2.25 MB) 0x00040000 (256 KB) "miniboot_bak1" miniboot 的备份,通常用于恢复系统。
mtd3 0x00040000 (256 KB) 0x00040000 (256 KB) "misc" 设备的其他配置或不可区分的数据区域。
mtd4 0x00200000 (2 MB) 0x00040000 (256 KB) "uboot" uBoot,常见的引导加载程序,用于启动系统。
mtd5 0x00180000 (1.5 MB) 0x00040000 (256 KB) "ubootenv" 存储 uBoot 环境变量,如启动设置等。
mtd6 0x02000000 (32 MB) 0x00040000 (256 KB) "boot" 存储启动映像的分区。
mtd7 0x09600000 (150 MB) 0x00040000 (256 KB) "system" 存储系统文件和核心文件,通常是根文件系统。
mtd8 0x06400000 (100 MB) 0x00040000 (256 KB) "hbre" 自定义分区,可能与硬件或应用程序相关。
mtd9 0x0dd80000 (223 MB) 0x00040000 (256 KB) "userdata" 存储用户数据的分区,通常用于存储应用数据或用户配置。

日志结果和 BSP 包分区表 device/horizon/x5/board_cfg/soc/x5-soc-debug-nand-gpt.json 中的配置是一致的:

{
	"mbr": {
		"size": "256k",
		"medium": "nand"
	},
	"miniboot": "sub_config/miniboot_nand.json",
	"misc": {
		"size": "256k",
		"medium": "nand"
	},
	"uboot": {
		"part_type": "GOLDEN",
		"size": "2m",
		"medium": "nand"
	},
	"ubootenv": {
		"size": "1536k",
		"medium": "nand"
	},
	"boot": {
		"part_type": "GOLDEN",
		"size": "32m",
		"medium": "nand"
	},
	"system": {
		"fs_type": "ubifs",
		"part_type": "GOLDEN",
		"size": "150m",
		"medium": "nand"
	},
	"hbre": {
		"fs_type": "ubifs",
		"part_type": "GOLDEN",
		"size": "100m",
		"medium": "nand"
	},
	"userdata": {
		"fs_type": "ubifs",
		"part_type": "GOLDEN",
		"size": "32m",
		"medium": "nand"
	}
}

可以根据最终经过裁剪后得到的镜像大小修改分区表中的 size 设定值,以合理分配各个分区容量。

4.4.4.6. 常见问题

在系统裁剪过程中,常见的几个问题包括功能丧失、系统不稳定、依赖问题、性能下降和兼容性问题等。以下是这些问题的具体说明以及相应的解决方案。

功能丧失或不可用

问题描述:裁剪过程中,如果移除了过多的功能或模块,可能会导致系统无法提供所需的基本功能。

解决方案

  • 需求驱动裁剪:在裁剪之前,首先明确系统必须支持的功能,并确保这些功能在裁剪过程中不被移除。

  • 分阶段裁剪:逐步裁剪,避免一次性删除过多功能,每个阶段后进行系统验证,确保所需功能仍可正常使用。

举例: 如果裁剪掉了某些文件系统支持模块,可能导致存储不可用。为避免此问题,应在裁剪时保留对特定文件系统(如 ext4 或 FAT)的支持。

系统不稳定或崩溃

问题描述:过度裁剪或移除核心模块(如内核调度、内存管理等)会导致系统崩溃或无法启动。

解决方案

  • 核心功能保护:裁剪时要确保核心功能如内存管理、硬件抽象层( HAL)和中断管理模块不被移除。

  • 充分测试:每次裁剪后进行全面测试,尤其是在硬件和网络模块方面,确保系统在各种条件下稳定运行。

举例: 在裁剪内核时,删除了对特定硬件的驱动支持,导致系统无法识别设备。应通过保留最基本的硬件支持和驱动程序,避免这种情况。

依赖问题

问题描述:裁剪时可能会去除一些不必要的库或工具,但如果裁剪不当,可能导致系统在运行时缺少某些库依赖,导致程序崩溃或无法启动。

解决方案

  • 最小化依赖:裁剪时,首先识别哪些库和工具是必须的,尽量去除不必要的依赖项。使用静态链接而非动态链接有时可以减少依赖问题。

  • 使用轻量级替代品:例如,使用 BusyBox 替代多个常规工具集,减少不必要的库和工具的依赖。

举例: 裁剪过程中可能去除了某些开发库,导致程序无法启动或运行异常。应通过使用静态链接或者保留必要的依赖项,确保系统稳定运行。

性能下降

问题描述:某些功能虽然看似不必要,但其存在可能对系统的性能有重要影响。

解决方案

  • 功能裁剪与性能优化平衡:裁剪时不仅要考虑功能的移除,还要关注性能优化。例如,保留对硬件加速支持的驱动,使用高效算法和数据结构。

  • 精简内核配置:精简内核时,应根据目标硬件去除不必要的驱动和模块,确保内核占用更少的资源。

举例: 裁剪时如果移除了对内存页交换( swap)的支持,可能导致内存资源紧张时系统性能下降。应确保内存管理机制完整,避免因过度裁剪引起性能下降。

兼容性问题

问题描述:裁剪可能导致系统与现有硬件或软件的不兼容,尤其是在内核或启动引导程序(如 Uboot)裁剪时。如果移除不当,可能导致系统无法启动或硬件不兼容。

解决方案

  • 保持向后兼容性:裁剪时要确保不影响系统的基本硬件支持和接口,特别是在内核和引导程序方面。

  • 文档化裁剪过程:记录每一步的裁剪决策和变更,以便日后回滚或调整,保证系统与硬件的兼容性。

举例: 如果在裁剪 Uboot 时删除了对某些启动设备的支持(如 SD 卡启动支持),可能导致系统无法启动。应确保在裁剪过程中保留必要的硬件支持和启动功能。

4.4.4.7. 参考文献

The U-Boot Documentation
Kernel Size Tuning Guide
Buildroot User Manua