嵌入式linux学习记录十五,uboot熟悉2

嵌入式linux学习记录十五,uboot熟悉2


  1. 配置LDSCRIPT,确定 U-Boot 链接脚本(Linker Script)的绝对路径
    1. BOARDDIR:在根目录下config.mk中定义。

    2. CONFIG_SYS_LDSCRIPT是老的uboot遗留下来的,这段现在不是对LDSCRIPT设置



  2. 配置LDSCRIPT,确定 U-Boot 链接脚本(Linker Script)的绝对路径
    1. $(wildcard ...):这是 GNU make 的内置函数。它会检查参数中匹配的文件是否存在,并返回存在的文件的路径。如果文件不存在,则返回空字符串。

  3. 根目录下的config.mk文件被称为“全局编译规则编译器”“变量大本营”。


  4. U-Boot 编译出来的固件体积与运行速度之间的关键权衡


  5. 都是一些编译参数设置
    1. -fno-stack-protector:剥离堆栈保护器
    2. -fno-delete-null-pointer-checks:拦截空指针优化陷阱
    3. -g:向编译器和汇编器统一注入-g参数。这意味着编译出来的 ELF 固件里会包含完整的调试符号表(保留了原始的 C 语言行号、变量名映射)
    4. -Wno-format-nonliteral:过滤无意义的报警


  6. 一个针对特定古董硬件架构(Motorola 68000,简称 m68k)以及特定老版本 GCC 编译器(GCC 3.4)的“陈年陈条”和 Bug 修复兜底机制

    1. include scripts/Makefile.extrawarn:编译命令后面加上W=1,这个脚本就会彻底觉醒,用最严苛的洁癖视角审视所有的驱动 C 代码,帮你抓出隐藏的隐患。
    2. make KCFLAGS="-O3 -DDEBUG_MY_DRIVER":通过加算$(KCFLAGS),向开发者递出了全系统的最高指挥棒。

    1. UBOOTINCLUDE:该变量使用 GCC 的-I参数,按优先级从上到下显式指定了头文件的搜寻目录:

    2. NOSTDINC_FLAGS:切断宿主机依赖,目的在于使编译环境与 PC 操作系统脱钩

    3. cpp_flags:组合了预处理器所需的全部资源(全局预处理标志、平台预处理标志、刚才计算出的 U-Boot 头文件路径、以及屏蔽系统头文件的-nostdinc标志)。

    4. c_flags:将 C 编译器的专属参数(如之前计算出的-O2优化级别、-g调试符号等)与预处理器标志cpp_flags进行叠加。



  7. 构建 U-Boot 编译阶段的核心目标库列表(libs-y变量)。它决定了接下来的 Kbuild 编译系统需要深入到源码树的哪些子目录中去编译驱动、文件系统、网络协议栈等模块,并最终将它们打包成.a静态库文件以供链接。
    1. scripts/Makefile.build:在 U-Boot 中,顶层 Makefile 本身不负责直接编译具体的.c文件。当顶层 Makefile 决定要编译某个子目录(例如你刚才看到的drivers/gpio/)时,它会通过make -f scripts/Makefile.build obj=drivers/gpio命令,把实际的编译重任委派给scripts/Makefile.build

      1. u-boot-dirs:清洗目录尾部斜杠并追加工具目录 tools。这个变量主要用于控制接下来make递归进入子目录编译的循环序列。去掉了斜杠,Make 引擎才能结合scripts/Makefile.build精准定位到物理文件夹。
      2. u-boot-alldirs:收集全量目录用于清理。这个变量包含了 U-Boot 工程下几乎所有的子目录。它最核心的用途是提供给make cleanmake mrpropper命令。当执行清理工程时,系统直接遍历u-boot-alldirs,就能把所有目录(不管有没有被编译)底下的垃圾文件一次性全部扫除干净。
      3. u-boot-init:来自于$(head-y)。在arch/arm/Makefile中,它被赋值为arch/arm/cpu/armv7/start.o。这是 U-Boot 的第一行汇编代码所在的位置。由于它被拎出来作为u-boot-init,链接脚本u-boot.lds会在最后组装时,强行把它放在二进制镜像的最前端(0x0偏移处)。只有这样,i.MX6ULL 芯片上电时,Boot ROM 才能第一眼看到它并正确执行。
      4. u-boot-main:就是刚才拼装完毕的、包含了各个驱动目录下built-in.olibs-y列表。


    2. 为 U-Boot 链接阶段引入底层数学与位运算支持库(libgcc.a。动态链接交叉编译器自带的官方库(正点原子默认)


    3. 构建链接脚本预处理器标志(LDPPFLAGS变量)

      1. BOARD_SIZE_CHECK:定义一个用于检测编译输出固件体积是否超标的 Shell 脚本变量。在嵌入式开发中,特定硬件平台分配给 U-Boot 的存储空间(如片内高速度 SRAM、内部 Flash 或特定的分区表边界)是存在物理上限的。如果编译出的固件超出了这个限制,强行烧录会导致覆盖其他数据区或硬件无法启动。


    4. 定义一个对编译出的二进制固件进行“静态链接重定位修复”的 Shell 脚本宏变量(DO_STATIC_RELA)。

      在现代 64 位 CPU 架构(如 ARM64)中,U-Boot 为了支持位置无关代码(PIC/PIE),即允许 U-Boot 镜像在运行期间动态地把自己从一个内存地址拷贝到另一个内存地址(重定位),会在 ELF 文件中生成一个动态重定位段(.rel.dyn.rela.dyn)。

      但是,在 U-Boot 刚刚上电、DDR 内存还没初始化、重定位代码还没运行的极早期裸机阶段,这些位置无关的绝对地址指针是无效的。为了让 U-Boot 在最早期能正常读取全局变量,必须在编译阶段通过外部工具,把这些动态重定位关联的物理地址硬编码写入二进制文件中。这就是“静态重定位修复”。



    5. 构建 U-Boot 编译结束时最终需要生成的“终极目标文件列表”(ALL-y变量)。在 Makefile 中,一个庞大的工程最终会输出很多种格式的文件(如纯二进制、符号表、配置文件等)。Kbuild 通过ALL-y变量把这些需要输出的目标全部打包收集起来,作为默认编译规则(all:伪目标)的依赖项。
      1. ALL-y:无条件收集的核心基础目标
      2. CONFIG_ONENAND_U_BOOT:如果板子采用的是三星的 OneNAND 闪存芯片作为启动介质
      3. CONFIG_SPL_FSL_PBL:FSL(飞思卡尔/NXP)处理器引导加载构造分支

      1. spl/u-boot-spl.bin:如果开启了二级启动(CONFIG_SPL=y),则追加生成 SPL 的二进制镜像。

      2. u-boot.img:如果使用了标准 SPL 架构外壳(CONFIG_SPL_FRAMEWORK=y),SPL 需要识别特定格式的 U-Boot 镜像。u-boot.img是在纯二进制的u-boot.bin前面加上了64 字节的 MKIMAGE 头部信息(包含镜像类型、加载地址、校验和等),专供 SPL 识别并引导。

      3. tpl/u-boot-tpl.bin:三级引导目标。在某些片内 SRAM 空间极度严苛的芯片上,先跑 SPL,再跑 TPL,最后才进 U-Boot。对于 i.MX6ULL,此项未定义。

      4. u-boot.dtb:如果开启了设备树分离模式(CONFIG_OF_SEPARATE=y,这是正点原子 i.MX6ULL 的默认配置),系统会将设备树源码(.dts)编译为独立的二进制设备树文件(.dtb),并将u-boot.dtb加入生成目标列表。

      5. u-boot-dtb.img:当同时满足“使用 SPL 框架”且“设备树分离”时追加。该目标在后续规则中,会把u-boot.bin和编译好的u-boot.dtb物理上拼接到一起,然后再用mkimage工具加上 64 字节头部,生成一个复合镜像,供 SPL 一次性加载。

      6. CONFIG_OF_HOSTFILE:这是 U-Boot 在 Sandbox(沙盒模拟)模式下,直接读取宿主机 Linux 里的设备树文件时使用的配置。

      7. 有些 SoC 原厂(例如三星、TI 或部分 NXP 芯片)的底层 Boot ROM 不认标准的u-boot-spl.bin,需要特定格式(如u-boot-spl.imxMLO)。原厂会在 Kconfig 中将这个特定的文件名写入CONFIG_SPL_TARGET字符串。

      8. u-boot.elf:重新生成带完整符号表的 ELF 格式可执行文件。

      9. u-boot-app.efi/u-boot-payload.efi:当把 U-Boot 配置为作为 UEFI 应用程序运行,或者作为 UEFI 的 Stub(存根)载荷时,追加生成符合 UEFI 规范的可执行文件。

      10. 追加生成u-boot.rom。这是专门针对 X86 物理主板 BIOS 闪存颗粒的大小经过精密填充和对齐后生成的完整镜像,可以直接用烧录器刷入主板的 Flash 芯片中。对于你的 ARM 架构平台,此判断不成立。

    6. continues