Linux/LoongArch 启动指南:BootLoader 传参协议与 EFI 内核镜像头结构解析

发布时间:2026/9/14 2:18:32

Linux/LoongArch 启动指南:BootLoader 传参协议与 EFI 内核镜像头结构解析 Linux/LoongArch 启动指南BootLoader 传参协议与 EFI 内核镜像头结构解析【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux本文基于 Linux 内核源码树中的 Documentation/arch/loongarch/booting.rst 官方文档系统讲解 LoongArch 架构下 BootLoader 与内核之间的启动握手协议从kernel_entry传入的 3 个寄存器参数到 Linux/LoongArch 内核镜像作为 EFI/PE 文件所携带的 64 字节镜像头布局并逐一映射到 arch/loongarch 下的真实源码实现。读完本文你将掌握 LoongArch 平台启动链路的完整图景能够理解boot.cfg、UEFI/PMON 等引导环境如何与内核约定内存布局与入口也能在阅读 head.S、efi-header.S 等汇编时做到心中有数。BootLoader 传递给内核的信息LoongArch 架构同时支持 ACPI 与 FDT扁平设备树两种固件表描述方式。无论走哪条路径BootLoader 需要传递给内核的信息都包括内存布局memmap、initrd、内核命令行command line以及可选的 ACPI/FDT 表。这些信息不是通过某个结构体一次性打包而是通过kernel_entry入口处的 3 个通用寄存器约定传递寄存器名称含义a0efi_boot标志位表示当前引导环境是否完全符合 UEFI 规范a1cmdline指向内核命令行字符串的指针a2systemtable指向 EFI System Table 的指针文档特别强调此阶段涉及的所有指针均为物理地址All pointers involved at this stage are in physical addresses此时内核尚未开启 MMU 页表映射BootLoader 必须保证传入的是可直接访问的物理地址。源码中的参数落盘fw_arg0 / fw_arg1 / fw_arg2内核在入口汇编 arch/loongarch/kernel/head.S 中第一时间将这 3 个寄存器保存到三个全局变量中la.pcrel t0, fw_arg0 PTR_S a0, t0, 0 # firmware arguments la.pcrel t0, fw_arg1 PTR_S a1, t0, 0 la.pcrel t0, fw_arg2 PTR_S a2, t0, 0三个变量在 arch/loongarch/kernel/setup.c 中定义并在 include/asm/bootinfo.h 中导出unsigned long fw_arg0, fw_arg1, fw_arg2;后续 C 代码对它们的消费集中在 arch/loongarch/kernel/env.c 的init_environ()void __init init_environ(void) { int efi_boot fw_arg0; char *cmdline early_memremap_ro(fw_arg1, COMMAND_LINE_SIZE); if (efi_boot) set_bit(EFI_BOOT, efi.flags); else clear_bit(EFI_BOOT, efi.flags); strscpy(boot_command_line, cmdline, COMMAND_LINE_SIZE); strscpy(init_command_line, cmdline, COMMAND_LINE_SIZE); early_memunmap(cmdline, COMMAND_LINE_SIZE); efi_system_table fw_arg2; }可以看到三个参数的消费路径与文档描述完全一致fw_arg0efi_boot非零时置位EFI_BOOT标志否则清除。该标志决定后续内核是否按完整 UEFI 环境处理例如是否使用 EFI 运行时服务、efifb 等。fw_arg1cmdline通过early_memremap_ro做早期只读临时映射这正是此时还是物理地址的体现拷贝进boot_command_line/init_command_line后立即early_memunmap释放。而在支持可重定位CONFIG_RELOCATABLE的启动路径中relocate.c 同样用early_memremap_ro(fw_arg1, COMMAND_LINE_SIZE)读取命令行用于 KASLR 决策。fw_arg2systemtable保存到全局efi_system_table类型为u64env.c作为后续 EFI 驱动与运行时服务访问的根。此外kexec 路径也复用了这套约定machine_kexec.c 将fw_arg0/fw_arg2保存进kimage-arch保证二次启动内核时能继承 UEFI 环境信息。Linux/LoongArch 内核镜像的头部Linux/LoongArch 内核镜像本身是EFI 镜像。作为 PE 文件它在文件开头携带一个64 字节的定制头其布局如下来自原文档字段注释已保留u32 MZ_MAGIC /* MZ, MS-DOS header */ u32 res0 0 /* Reserved */ u64 kernel_entry /* Kernel entry point */ u64 _end - _text /* Kernel image effective size */ u64 load_offset /* Kernel image load offset from start of RAM */ u64 res1 0 /* Reserved */ u64 res2 0 /* Reserved */ u64 res3 0 /* Reserved */ u32 LINUX_PE_MAGIC /* Magic number */ u32 pe_header - _head /* Offset to the PE header */逐字段说明MZ_MAGICMZ两字节 DOS 头魔数是 PE 文件的基本签名。内核通过它识别一个合法的 LoongArch 镜像。kernel_entry内核入口点的物理地址BootLoader 最终跳转的目标。_end - _text内核镜像的有效大小effective size即从_text到_end的字节数。load_offset内核镜像相对内存起始处的加载偏移load offset from start of RAMBootLoader 据此决定把镜像放到内存的哪个位置。LINUX_PE_MAGICLinux PE 魔数用于在MZ之外进一步确认这是 Linux 格式的 PE 镜像。pe_header - _head从镜像头起点到完整 PE 头COFF/可选头的偏移量指向紧随其后的标准 PE 头部结构。镜像头在汇编中的真实定义这一 64 字节头在 arch/loongarch/kernel/head.SCONFIG_EFI_STUB使能时中逐字节落地_head: .word IMAGE_DOS_SIGNATURE /* MZ, MS-DOS header */ .org 0x8 .dword _kernel_entry /* Kernel entry point (physical address) */ .dword _kernel_asize /* Kernel image effective size */ .quad PHYS_LINK_KADDR /* Kernel image load offset from start of RAM */ .org 0x38 /* 0x20 ~ 0x37 reserved */ .long LINUX_PE_MAGIC .long pe_header - _head /* Offset to the PE header */ pe_header: __EFI_PE_HEADER与文档字段一一对应_kernel_entry、_kernel_asize、PHYS_LINK_KADDR、LINUX_PE_MAGIC、pe_header - _head中间0x20 ~ 0x37共 24 字节为保留区对应三个u64 res。头部符号在链接脚本中的定义这些头字段引用的符号在 arch/loongarch/kernel/vmlinux.lds.S 中定义_kernel_entry ABSOLUTE(kernel_entry PHYSADDR_MASK); _kernel_asize ABSOLUTE(_end - _text); _kernel_fsize ABSOLUTE(_edata - _text); _kernel_vsize ABSOLUTE(_end - __initdata_begin); _kernel_rsize ABSOLUTE(_edata - __initdata_begin);_kernel_entry将汇编入口kernel_entry用PHYSADDR_MASK掩码为物理地址印证了文档入口点是物理地址的说法_kernel_asize _end - _text与文档公式完全一致同组还导出了_kernel_fsize文件大小、_kernel_vsize虚拟大小、_kernel_rsize供后续 EFI stub 与 PE 头使用。C 侧的对等结构体定义在 arch/loongarch/include/asm/image.hstruct loongarch_image_header { uint8_t dos_sig[2]; uint16_t padding_1[3]; uint64_t kernel_entry; uint64_t kernel_asize; uint64_t text_offset; uint32_t padding_2[7]; uint32_t pe_header; };并配套提供loongarch_header_check_dos_sig()辅助函数用于校验M Z签名image.h。该结构体被 kexec 的 EFI 加载路径直接复用kexec_efi.c 中读取kernel_asize作为内存段大小、text_offset作为buf_min并以kernel_segment-mem h-kernel_entry - text_offset计算二次内核的入口最后设置image-startkexec_efi.c保证跳转目标与头部声明的入口一致。load_offset 与内存加载地址load_offset在汇编中取值为PHYS_LINK_KADDR其定义为PHYSADDR(VMLINUX_LOAD_ADDRESS)include/asm/addrspace.h。而VMLINUX_LOAD_ADDRESS由 arch/loongarch/Makefile 按位宽决定ifdef CONFIG_32BIT load-y 0xa0200000 else load-y 0x9000000000200000 endif即32 位内核默认加载地址为0xa020000064 位内核为0x90000000002000000x9000_0000_0000_0000之上的地址属于 LoongArch 的窗口映射段。这一地址同时通过KBUILD_CPPFLAGS以-DVMLINUX_LOAD_ADDRESS...注入编译Makefile。可重定位内核CONFIG_RELOCATABLE在此基础上叠加 KASLR 随机偏移最终运行时地址可通过kaslr_offset()include/asm/setup.h换算。紧随其后的完整 PE/COFF 头64 字节定制头只是前菜其后pe_header处才是标准 PE/COFF 头由宏__EFI_PE_HEADER在 arch/loongarch/kernel/efi-header.S 中生成要点如下COFF 文件头IMAGE_NT_SIGNATURE后Machine字段在CONFIG_32BIT下为IMAGE_FILE_MACHINE_LOONGARCH32否则为IMAGE_FILE_MACHINE_LOONGARCH64efi-header.SCharacteristics标记为可执行镜像、去调试信息。可选头PE32使用IMAGE_NT_OPTIONAL_HDR64_MAGIC即 64 位 PE32 格式AddressOfEntryPoint指向__efistub_efi_pe_entry - _headefi-header.S即真正的 EFI stub 入口ImageBase为 0、Subsystem为IMAGE_SUBSYSTEM_EFI_APPLICATIONEFI 应用。节表定义了.text代码、可读可执行与.data已初始化数据、可读可写两个节efi-header.S对齐常量取PECOFF_SEGMENT_ALIGN0x10000。因此一个完整的 Linux/LoongArch 内核镜像在磁盘上的结构是64 字节定制头含 MZ 签名→ 标准 PE 头 → .text/.data 节。UEFI 固件可将其作为标准 EFI 应用直接加载执行进入__efistub_efi_pe_entry而传统 BootLoader如 PMON则读取定制头字段自行搬运镜像并跳转到kernel_entry。内核入口 kernel_entry 的启动汇编流程无论从哪条路径进入最终都会汇聚到kernel_entryhead.S。其启动顺序可归纳为基础环境设置SETUP_TWINS/SETUP_MODES/JUMP_VIRT_ADDR/SETUP_DMWINS完成窗口映射DMW与虚拟地址切换。清零 .bss从__bss_start循环清到__bss_stophead.S。保存固件参数将a0/a1/a2写入fw_arg0/fw_arg1/fw_arg2即上文所述协议落盘。初始化 percpu 与栈将CSR_IMPCTL1中 percpu 相关位清零、KSave3/u0置 0并设置init_task、init_stack与sphead.S。可重定位与 KASLRCONFIG_RELOCATABLE时调用relocate_kernel若再开启CONFIG_RANDOMIZE_BASE则按随机偏移跳入新内核new_pc current_pc random_offsethead.S。KASAN 早期初始化CONFIG_KASAN时调用kasan_early_init。进入 C 世界bl start_kernel其后是永不返回的ASM_BUG()兜底。此外SMP 从核slave CPU不经过 BootLoader 传参协议而是由主核通过cpuboot_data传递任务、栈和偏移后进入smpboot_entryhead.S。小结围绕官方文档 booting.rst本文串起了 LoongArch 启动链路的完整闭环协议层a0 efi_boot、a1 cmdline、a2 systemtable三个物理地址参数经 head.S 落盘为fw_arg0/1/2再被 env.c 的init_environ()消费驱动 EFI 标志、命令行与系统表初始化镜像层内核镜像是带 64 字节定制头的 EFI/PE 文件字段由 head.S 生成、由 vmlinux.lds.S 定义符号、由 image.h 描述 C 结构并被 kexec 的 kexec_efi.c 作为加载依据入口层kernel_entry完成建栈、清 BSS、保存固件参数、可重定位与跳转start_kernel的全过程。对 BootLoader、固件开发者或内核移植工程师而言理解这套寄存器传参 头部自描述的约定是在 LoongArch 平台上正确引导 Linux 的关键第一步。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/14 2:13:31

货物贸易进出口:条码如何打通跨境链路

货物贸易进出口,到底在统计什么 实物商品的进口与出口活动,构成了国际贸易中最基础的一环。货物进出口总额,指的是在一定时期内,一国或地区全部实际进出口商品的总金额,它直接反映出一国对外贸易的规模与发展水平。 中…

2026/9/14 2:13:31

嵌入式入门避坑指南:从裸机点亮到ARM Linux真实开发路径

1. 这不是退学,是及时止损:一个嵌入式初学者的真实踩坑时间线“花两个月学了嵌入式,已退学,不想有人再上当”——这句话在技术社区里像一块烧红的铁,烫得人不敢直视。它背后没有情绪宣泄,只有一份被压缩到极…

2026/9/14 2:13:31

Android Compose热重载技术解析与实践指南

1. Compose热重载技术解析最近在Android开发社区掀起一阵热潮的Compose HotSwan技术,本质上是一种实时代码更新机制。作为一名长期奋战在Android开发一线的工程师,我亲测这项技术确实能实现"改完代码1秒生效"的效果,彻底告别了传统…

2026/9/14 2:58:33

PHP原生学生管理系统部署与CRUD实战指南

简介:这是一套基于PHP开发的轻量级学生信息管理系统源码,面向Web开发初学者与课程设计实践者,适用于高校计算机专业PHP入门实训、数据库应用开发练习及小型教务管理原型搭建。资源包含完整的前后端实现:后端以22个PHP文件构成MVC结…

2026/9/14 2:58:33

YOLOv8坐姿矫正实战:从目标检测模型训练到PySide6界面部署

简介:一套基于YOLOv8的智能书桌坐姿矫正提醒项目,主要面向计算机相关专业学生完成毕业设计、课程设计或大作业,也适合目标检测方向的初学者进阶实践。项目针对久坐姿态不规范的问题,利用深度学习目标检测实现实时提醒,…

2026/9/14 2:58:33

kohya_ss LoRA微调完整指南:4步从安装到启动训练

kohya_ss LoRA微调完整指南:4步从安装到启动训练 【免费下载链接】kohya_ss 项目地址: https://gitcode.com/GitHub_Trending/ko/kohya_ss 你想用自己的角色、画风或物体训练一个 Stable Diffusion LoRA,却被命令行参数劝退?kohya_ss…

2026/9/14 2:58:33

嵌入式自学痛点破解:知识断层、路径模糊与实操脱节

1. 这套“200集嵌入式自学教程”到底在解决什么真实问题? 我带过三十多个嵌入式方向的应届生和转行学员,也给十多家中小硬件公司做过技术顾问。每次聊到“自学嵌入式”,几乎所有人都会先叹一口气——不是不想学,是真不知道从哪下手…

2026/9/14 2:17:50

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/14 0:03:22

KCF目标跟踪算法与OTB工程实现:毕业设计实战解析

简介:这是一份基于KCF核相关滤波算法、融合尺度池与抗遮挡处理的目标检测跟踪MATLAB完整源码,主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要项目实战练习的初学者。源码在OTB数据集上完成验证,能够…

2026/9/14 0:03:22

语音情感识别实战:Keras实现LSTM、CNN、SVM与MLP多模型对比

简介:面向语音情感识别入门与进阶开发者,这份基于Keras的项目源码完整实现了LSTM、CNN、SVM、MLP四种模型,兼容Python3.8与Keras/TensorFlow2环境。压缩包内含49个文件,大小约70.31MB,主体包括Python脚本、yaml/json配…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/13 11:18:28

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码