# 系统小型化裁剪

## 概述

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

## 系统裁剪简介

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

- 减小存储占用：通过裁剪不必要的功能和模块，减少文件系统、内核、启动程序等占用的存储空间，适应资源受限的硬件环境。
- 提高启动速度：精简后的系统在启动时能够加载更少的模块，启动过程更加高效。
- 提升系统性能：去除不必要的功能和驱动，减少内存占用，提升系统响应速度和稳定性。
- 定制化系统：根据实际需求定制系统组件，实现精细化控制，增强系统的可维护性和可扩展性。

当前系统主要镜像有 uboot、 kernel、 rootfs 等，它们的大小根据 [ 系统分区表 ](../board_bring_up.html#span-id-bsp-part-conf) 可以获取到：

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

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

## 系统裁剪方式

### uboot 裁剪

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

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

```bash
./bd.sh uboot menuconfig
```

该命令会自动使用板级配置文件中设置的 uboot 配置文件，在配置完成后，自动完成 `savedefconfig` 和保存工作。该命令详细说明可以参考 [ 配置 Uboot 选项参数 ](../driver_develop_guide/0-Configure_Kernel_And_Uboot.html#span-id-config-uboot-uboot) 章节。

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

![uboot_config](./_static/_images/system_cropping/uboot_config.png)

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

- 禁用不需要的命令

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

    ![memtest_cmd](./_static/_images/system_cropping/memtest_cmd.png)

- 禁用文件系统支持

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

    ![FAT_FS](./_static/_images/system_cropping/FAT_FS.png)

- 禁用不需要的硬件驱动

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

    ![I2C_CONFIG](./_static/_images/system_cropping/I2C_CONFIG.png)

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

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

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

### Linux 内核裁剪

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

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

- 删除不使用的功能。如符号表、打印、调试等功能。
- 删除不使用的驱动。
- 修改内核源代码。

#### 禁用内核功能、驱动

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

```shell
./bd.sh boot menuconfig
```

该命令详细说明可以参考 [ 配置 Kernel 选项参数 ](../driver_develop_guide/0-Configure_Kernel_And_Uboot.html#span-id-config-kernel-kernel) 章节。命令执行成功后会打开 Kernel 图形化配置界面，可以在这个交互界面下完成选项的配置，删除不需要的功能模块：

![kernel_config](./_static/_images/system_cropping/kernel_config.png)

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

#### 修改内核源代码

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

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

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

命令解释：

- `nm --size vmlinux`：列出 `vmlinux` 文件中的符号信息，并显示每个符号的大小（以字节为单位）。
- `sort -k 2 -n -r`：
  - `-k 2`：按照第二列（即符号的大小列）进行排序。
  - `-n`：以数值大小排序，而不是按字典顺序。
  - `-r`：按降序排序，即从大到小。

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

```log
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` 等）：符号的名称。

例如：

```shell
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`)**：这部分的符号表示已初始化的全局变量，需要确认是否所有的全局变量都被需要，没有使用的全局变量可以裁剪。
- **只读数据段 (`r` 或 `R`)**：表示只读的全局变量，通常是库函数中的常量数据。这些数据中对于没有被使用的部分是可以被优化的。
- **文本段 (`T` 或 `t`)**：这部分的符号表示函数代码。如果某些函数不被使用或只有在特定条件下才被调用，可以是裁剪的候选。特别是局部函数（`t`）可以分析后确认是否被优化或者从内核配置中禁用。
- **弱符号 (`W`)**：这类符号是弱符号，通常是可选的或不太重要的。可以考虑裁剪。

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

#### 其他裁剪方向

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

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

### 根文件系统裁剪

本平台的根文件系统是通过 buildroot 来制作的，详细过程可以参考 [ 使用  Buildroot 制作根文件系统 ](Root_filesystem.html#span-id-buildroot-use-buildroot) 章节。

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

- **删**：删除不需要的内容。如帮助文档、没用到的库、调试程序等。
- **换**：使用小尺寸的实现替换大尺寸的实现。如使用 musl libc 库替换 glibc 库等。
- **压**：使用合适的压缩算法。

**应用程序及冗余文件裁剪：**

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

- 调试工具：比如 tcpdump、 mpstat、 strace 等等。
- 性能测试工具：比如 lmbench、 sysstat、 tiobench 等等。
- 冗余文件：帮助文档、辅助程序、配置文件和数据模块等，又比如很多应用有相同的功能，只留其一。
- 采用具有通用功能的替代软件包。 Linux 上有许多具有相似功能的软件包，可以选择其中占存储空间较小的软件包并移植到嵌入式设备上。
- 资源文件：一些音视频以及 UI 资源往往占用很大空间，如果没有用到，也需要删除。

**关于库的裁剪：**

- 使用较小的 C 库，如 musl libc， uclibc 等来替换 glibc。
- 删除没有用到的库。

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

```shell
./build.sh menuconfig x5_system_defconfig
```

进入 menuconfig 界面进行配置：

![buildroot_packages](./_static/_images/system_cropping/buildroot_packages.png)

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

![buildroot_ffmpeg](./_static/_images/system_cropping/buildroot_ffmpeg.png)

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

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

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

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

![buildroot_strip](./_static/_images/system_cropping/buildroot_strip.png)

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

## 系统裁剪的基本原则

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

- **按需求裁剪**
  - **明确目标**：裁剪应根据实际应用需求来进行。不要盲目裁剪，首先需要清楚系  需要支持哪些功能、模块和硬件。裁剪的目的是为了适应特定的硬件平台和应用场景，  不是单纯地减小系统体积。
  - **最小化功能集**：根据使用场景只保留必要的功能和服务，避免裁剪过多，导致系统无法提供预期功能。

- **逐步裁剪**
  - **分阶段进行**：裁剪过程应分阶段进行，从最不重要的模块开始，逐步移除不必要的功能。在每一阶段，进行测试和验证，确保系统的稳定性和功能完整性。
  - **保留核心功能**：始终确保系统的基本功能不受影响。例如，内核裁剪时，要特别注意保留对硬件的基本支持，特别是设备驱动和文件系统支持。

- **安全性和稳定性优先**
  - **避免破坏性裁剪**：裁剪时不要移除或禁用系统的核心功能，如内核调度、内存管理、硬件抽象层 (HAL) 等。过度裁剪可能会导致系统不稳定，甚至无法启动。
  - **充分测试**：每次裁剪后，都应对系统进行全面的功能验证，尤其是对硬件和网络等关键模块的测试。确保不会引入安全漏洞或导致系统崩溃。

- **最小化依赖**
  - **去除冗余依赖**：裁剪时应尽量减少对不必要的库和工具的依赖，特别是在 Buildroot 和根文件系统的裁剪中。移除不需要的依赖项，避免增加不必要的库文件和二进制文件。
  - **使用轻量级替代品**：例如，用 BusyBox 替代多个常规工具集，选择更小的、资源占用更低的库和工具，以减小根文件系统的体积。

- **合理管理内核配置**
  - **精简内核配置**：在内核裁剪过程中，应根据目标硬件精简内核配置。删除不必要的驱动程序、文件系统支持和调试功能，避免加载不需要的模块。
  - **模块化管理**：内核模块应该只在需要时加载，减少不必要的内核模块或驱动，这不仅有助于减少内核的体积，还可以优化系统性能。

- **高效管理存储和内存**
  - **优化存储占用**：裁剪时应重点关注存储的优化，特别是嵌入式设备存储有限的情况下，尽量减少文件系统  内核镜像和 Uboot 文件的大小。
  - **内存占用优化**：减少不必要的内存占用，尤其是在 RAM 限制较大的设备上。通过移除不必要的服务、程序和驱动，可以有效提高内存利用率。

- **模块化与可扩展性**
  - **保持模块化设计**：尽量保留系统的模块化特性，即使进行裁剪，也应确保系统可以在需要时灵活地加载模块，而不是直接将所有功能集成到系统中。
  - **可扩展性**：在裁剪过程中，不要限制未来的扩展能力。确保裁剪的部分能够轻松地被重新加入到系统中，以便后续的功能扩展。

- **遵循工具链和标准**
  - **使用标准工具链**：裁剪过程中应使用一致的工具链和配置工具（如 Uboot 的 `make menuconfig`、  Kernel 的 `make menuconfig` 或 Buildroot 的配置工具）进行操作。这些工具链已经经过优化和广泛使用，能够帮助确保裁剪的系统在目标平台上正常工作。
  - **文档化裁剪过程**：对于每一次裁剪的决策和步骤，应进行详细记录。这样可以帮助后续人员理解裁剪的目的、方法和实现，便于管理和后期修改。

- **性能与功耗平衡**
  - **优化性能**：裁剪不仅是为了减小体积，还应兼顾性能优化。可以通过移除不必要的功能和配置来提高系统性能。
  - **考虑功耗**：在嵌入式系统中，功耗往往是设计中的重要考虑因素。裁剪时，可以优先选择低功耗的硬件支持和软件功能，优化系统的功耗表现。

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

## 系统裁剪实例

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

### system 最小配置

如下是 system 的最小配置：

```shell
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 的最小配置：

```shell
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）编译根文件系统：**

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

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

有关 buildroot 编译根文件系统的详细说明请参考  [ 使用  Buildroot 制作根文件系统 ](Root_filesystem.html#span-id-buildroot-use-buildroot) 章节。

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

```shell
$ 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” （或者修改为编译根文件系统时候命令中加入的具体版本参数），如下：

```shell
# 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 ：

```shell
$ ./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
```

#### 测试新镜像

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

```shell
$ 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 大小：

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

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

查看内核模块的大小：

```shell
$ 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 模式启动。关于拨码开关的详细配置，可以参考[拨码开关](../../quick_start/x5_evb_1_b_user_guide.html#span-id-dip-switch)（以 EVB 1_b 为例）的相关章节。  

关于镜像烧录详细方式，可以参考[系统镜像烧写](../../quick_start/update_system_firmware.html#span-id-system-update) 章节。

待镜像烧录完毕，查看启动日志：

```shell
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 了。

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

```shell
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` 中的配置是一致的：

```shell
{
	"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` 设定值，以合理分配各个分区容量。

## 常见问题

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

### 功能丧失或不可用

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

**解决方案**：

- **需求驱动裁剪**：在裁剪之前，首先明确系统必须支持的功能，并确保这些功能在裁剪过程中不被移除。
- **分阶段裁剪**：逐步裁剪，避免一次性删除过多功能，每个阶段后进行系统验证，确保所需功能仍可正常使用。

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

### 系统不稳定或崩溃

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

**解决方案**：

- **核心功能保护**：裁剪时要确保核心功能如内存管理、硬件抽象层（ HAL）和中断管理模块不被移除。
- **充分测试**：每次裁剪后进行全面测试，尤其是在硬件和网络模块方面，确保系统在各种条件下稳定运行。

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

### 依赖问题

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

**解决方案**：

- **最小化依赖**：裁剪时，首先识别哪些库和工具是必须的，尽量去除不必要的依赖项。使用静态链接而非动态链接有时可以减少依赖问题。
- **使用轻量级替代品**：例如，使用 BusyBox 替代多个常规工具集，减少不必要的库和工具的依赖。

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

### 性能下降

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

**解决方案**：

- **功能裁剪与性能优化平衡**：裁剪时不仅要考虑功能的移除，还要关注性能优化。例如，保留对硬件加速支持的驱动，使用高效算法和数据结构。
- **精简内核配置**：精简内核时，应根据目标硬件去除不必要的驱动和模块，确保内核占用更少的资源。

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

### 兼容性问题

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

**解决方案**：

- **保持向后兼容性**：裁剪时要确保不影响系统的基本硬件支持和接口，特别是在内核和引导程序方面。
- **文档化裁剪过程**：记录每一步的裁剪决策和变更，以便日后回滚或调整，保证系统与硬件的兼容性。

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

## 参考文献

[The U-Boot Documentation](https://docs.u-boot.org/en/latest/)  
[Kernel Size Tuning Guide](https://elinux.org/Kernel_Size_Tuning_Guide)  
[Buildroot User Manua](https://buildroot.org/docs.html)
