基于opensbi-1.2 分析
1. fw_base.S
这段代码是一个 RISC-V 架构下的固件启动程序,用于在系统启动时执行初始化操作、重定位代码、设置内存保护、处理中断和异常,并最终将控制权传递给下一个启动阶段。以下是逐步解释:
1.1 初始化和准备工作
fw_boot_hart:尝试获取启动的 HART(硬件线程)的 ID,并将其存储在a6中。fw_save_info:用于保存启动阶段的信息,默认实现为空操作。fw_next_arg1:获取下一个启动阶段的参数1,如果定义了FW_PAYLOAD_FDT_ADDR,则返回该地址,否则返回a1的值。fw_next_addr:获取下一个启动阶段的地址,返回payload_bin的地址。fw_next_mode:设置下一个启动阶段的模式为 S 模式。fw_options:提供启动选项,默认返回0。
1.2 重定位代码
_relocate:如果加载地址和链接地址不一致,将代码从加载地址重定位到链接地址。_relocate_done:标记重定位完成,更新_boot_status。
1.3 初始化平台和固件
fw_platform_init:调用平台初始化函数,配置内存保护和平台资源。_bss_zero:将 BSS 区域清零,确保未初始化的全局变量为0。
1.4 设置临时环境
- 设置临时的陷阱处理程序和栈空间,以便在启动过程中处理中断和异常。
- 调用
fw_save_info保存启动信息。
1.5 处理设备树(FDT)
- 如果定义了
FW_FDT_PATH,将设备树从源地址复制到目标地址。
1.6 启动非启动 HART
_wait_relocate_copy_done:等待重定位完成。_start_warm:初始化非启动 HART 的寄存器、栈和陷阱处理程序。
1.7 中断和异常处理
_trap_handler和_trap_exit:处理中断和异常,保存和恢复寄存器状态。
1.8 内存和寄存器操作
memcpy、memset、memmove、memcmp:映射到 SBI 提供的内存操作函数。
1.9 代码逻辑
- 重定位:将代码从加载地址复制到链接地址,以确保代码在正确的地址执行。
- 平台初始化:配置内存保护和平台资源,确保系统的安全性和正确性。
- 设备树处理:将设备树从一个地址复制到另一个地址,以便内核可以使用它来配置硬件。
- 多 HART 支持:初始化非启动 HART 的寄存器、栈和陷阱处理程序,确保所有 HART 都能正确运行。
1.10 输出
- 这个启动程序确保 RISC-V 系统在启动时正确配置寄存器、内存和设备树,并为后续的启动过程准备好参数和模式。它还处理中断和异常,确保系统的稳定性和可靠性。
这个启动程序确保在 RISC-V 系统启动时正确配置寄存器、内存和设备树,并为后续的启动过程准备好参数和模式。
2. fw_dynamic.S
这段代码是一个 RISC-V 架构下的固件启动程序的一部分,它处理动态信息的验证和保存,以确保启动过程的正确性和安全性。以下是逐步解释:
2.1 代码解析
-
处理错误的动态信息:
_bad_dynamic_info: wfi j _bad_dynamic_info- 如果动态信息验证失败,进入一个无限循环,使处理器等待中断(
wfi),然后继续循环。
- 如果动态信息验证失败,进入一个无限循环,使处理器等待中断(
-
获取启动 HART ID:
fw_boot_hart: /* Sanity checks */ li a1, FW_DYNAMIC_INFO_MAGIC_VALUE REG_L a0, FW_DYNAMIC_INFO_MAGIC_OFFSET(a2) bne a0, a1, _bad_dynamic_info li a1, FW_DYNAMIC_INFO_VERSION_MAX REG_L a0, FW_DYNAMIC_INFO_VERSION_OFFSET(a2) bgt a0, a1, _bad_dynamic_info /* Read boot HART id */ li a1, FW_DYNAMIC_INFO_VERSION_2 blt a0, a1, 2f REG_L a0, FW_DYNAMIC_INFO_BOOT_HART_OFFSET(a2) ret 2: li a0, -1 ret- 验证动态信息的魔数(
FW_DYNAMIC_INFO_MAGIC_VALUE)和版本(FW_DYNAMIC_INFO_VERSION_MAX)。 - 如果动态信息的版本大于支持的最大版本,返回错误。
- 如果动态信息的版本大于等于 2,则从动态信息中读取启动 HART ID;否则返回 -1。
- 验证动态信息的魔数(
-
保存启动信息:
fw_save_info: /* Save next arg1 in 'a1' */ lla a4, _dynamic_next_arg1 REG_S a1, (a4) /* Save version == 0x1 fields */ lla a4, _dynamic_next_addr REG_L a3, FW_DYNAMIC_INFO_NEXT_ADDR_OFFSET(a2) REG_S a3, (a4) lla a4, _dynamic_next_mode REG_L a3, FW_DYNAMIC_INFO_NEXT_MODE_OFFSET(a2) REG_S a3, (a4) lla a4, _dynamic_options REG_L a3, FW_DYNAMIC_INFO_OPTIONS_OFFSET(a2) REG_S a3, (a4) /* Save version == 0x2 fields */ li a4, FW_DYNAMIC_INFO_VERSION_2 REG_L a3, FW_DYNAMIC_INFO_VERSION_OFFSET(a2) blt a3, a4, 2f lla a4, _dynamic_boot_hart REG_L a3, FW_DYNAMIC_INFO_BOOT_HART_OFFSET(a2) REG_S a3, (a4) 2: ret- 保存下一个启动阶段的参数(
next arg1)。 - 根据动态信息的版本,保存不同的字段,包括下一个启动地址、模式和选项。
- 如果动态信息的版本大于等于 2,还保存启动 HART ID。
- 保存下一个启动阶段的参数(
-
获取下一个启动参数:
fw_next_arg1: lla a0, _dynamic_next_arg1 REG_L a0, (a0) ret- 返回保存的下一个启动参数。
-
获取下一个启动地址:
fw_next_addr: lla a0, _dynamic_next_addr REG_L a0, (a0) ret- 返回保存的下一个启动地址。
-
获取下一个启动模式:
fw_next_mode: lla a0, _dynamic_next_mode REG_L a0, (a0) ret- 返回保存的下一个启动模式。
-
获取启动选项:
fw_options: lla a0, _dynamic_options REG_L a0, (a0) ret- 返回保存的启动选项。
-
动态信息变量:
_dynamic_next_arg1: RISCV_PTR 0x0 _dynamic_next_addr: RISCV_PTR 0x0 _dynamic_next_mode: RISCV_PTR PRV_S _dynamic_options: RISCV_PTR 0x0 _dynamic_boot_hart: RISCV_PTR -1- 定义动态信息相关的变量,用于存储下一个启动参数、地址、模式、选项和启动 HART ID。
2.2 代码逻辑
- 动态信息验证:在
fw_boot_hart中验证动态信息的魔数和版本,以确保动态信息的完整性和兼容性。 - 信息保存:在
fw_save_info中保存动态信息中的关键字段,包括下一个启动参数、地址、模式和选项。 - 参数获取:通过
fw_next_arg1、fw_next_addr、fw_next_mode和fw_options提供保存的启动信息,供后续启动阶段使用。
2.3 输出
该代码确保在 RISC-V 系统启动时正确验证和保存动态信息,为后续的启动过程提供必要的参数和配置。它处理了动态信息的验证、保存和传递,确保启动过程的正确性和安全性。
这个启动程序确保在 RISC-V 系统启动时正确验证和保存动态信息,为后续的启动过程提供必要的参数和配置。它处理了动态信息的验证、保存和传递,确保启动过程的正确性和安全性。
3.fw_jump.S
这段代码是一个 RISC-V 架构下的固件启动程序,用于在系统启动时执行一些关键的初始化操作,并将控制权传递给下一个启动阶段。以下是对代码的详细解释:
3.1 代码解析
-
fw_boot_hart函数:fw_boot_hart: li a0, -1 ret- 该函数在系统启动的早期阶段被调用,用于确定启动的 HART(硬件线程)ID。
- 它将寄存器
a0设置为 -1,表示没有特定的 HART ID 被选中作为启动 HART。 - 这个函数返回后,
a0的值将作为启动 HART 的 ID。
-
fw_save_info函数:fw_save_info: ret- 该函数用于保存启动阶段的信息。
- 目前实现为空操作(直接返回),表示没有具体的保存逻辑。这可能是一个占位符,供后续实现使用。
-
fw_next_arg1函数:fw_next_arg1: #ifdef FW_JUMP_FDT_ADDR li a0, FW_JUMP_FDT_ADDR #else add a0, a1, zero #endif ret- 该函数用于设置下一个启动阶段的参数1。
- 如果定义了
FW_JUMP_FDT_ADDR,则将a0设置为该地址;否则,将a1的值复制到a0。 - 这个参数通常用于传递设备树(FDT)的地址。
-
fw_next_addr函数:fw_next_addr: lla a0, _jump_addr REG_L a0, (a0) ret- 该函数用于设置下一个启动阶段的入口地址。
- 使用
lla指令将_jump_addr的地址加载到a0中,然后返回。
-
fw_next_mode函数:fw_next_mode: li a0, PRV_S ret- 该函数用于设置下一个启动阶段的模式。
- 将
a0设置为PRV_S,表示下一个阶段将在 S 模式(监督模式)下运行。
-
fw_options函数:fw_options: add a0, zero, zero ret- 该函数用于设置启动选项。
- 将
a0设置为 0,表示没有特定的启动选项。
-
_jump_addr定义:#ifndef FW_JUMP_ADDR #error "Must define FW_JUMP_ADDR" #endif _jump_addr: RISCV_PTR FW_JUMP_ADDR- 确保必须定义
FW_JUMP_ADDR,否则编译时报错。 _jump_addr是一个全局符号,表示下一个启动阶段的入口地址。它被定义为FW_JUMP_ADDR的值。
- 确保必须定义
3.2 代码逻辑
- 启动 HART 确定:
fw_boot_hart函数返回 -1,表示没有特定的 HART ID 被选中作为启动 HART。 - 参数传递:
fw_next_arg1函数根据是否定义FW_JUMP_FDT_ADDR来设置下一个启动阶段的参数1。 - 启动地址:
fw_next_addr函数从_jump_addr中加载下一个启动阶段的入口地址。 - 启动模式:
fw_next_mode函数设置下一个启动阶段的模式为 S 模式。 - 启动选项:
fw_options函数返回 0,表示没有特定的启动选项。
3.3 输出
该代码确保在 RISC-V 系统启动时正确配置寄存器,并为后续的启动过程准备好参数和模式。它处理了启动 HART 的确定、参数传递、启动地址和模式的设置,确保系统的启动过程顺利进行。
这个启动程序确保在 RISC-V 系统启动时正确配置寄存器,并为后续的启动过程准备好参数和模式。它处理了启动 HART 的确定、参数传递、启动地址和模式的设置,确保系统的启动过程顺利进行。
1869

被折叠的 条评论
为什么被折叠?



