sbi-firmware代码解析

基于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 内存和寄存器操作

  • memcpymemsetmemmovememcmp:映射到 SBI 提供的内存操作函数。

1.9 代码逻辑

  • 重定位:将代码从加载地址复制到链接地址,以确保代码在正确的地址执行。
  • 平台初始化:配置内存保护和平台资源,确保系统的安全性和正确性。
  • 设备树处理:将设备树从一个地址复制到另一个地址,以便内核可以使用它来配置硬件。
  • 多 HART 支持:初始化非启动 HART 的寄存器、栈和陷阱处理程序,确保所有 HART 都能正确运行。

1.10 输出

  • 这个启动程序确保 RISC-V 系统在启动时正确配置寄存器、内存和设备树,并为后续的启动过程准备好参数和模式。它还处理中断和异常,确保系统的稳定性和可靠性。

这个启动程序确保在 RISC-V 系统启动时正确配置寄存器、内存和设备树,并为后续的启动过程准备好参数和模式。

2. fw_dynamic.S

这段代码是一个 RISC-V 架构下的固件启动程序的一部分,它处理动态信息的验证和保存,以确保启动过程的正确性和安全性。以下是逐步解释:

2.1 代码解析

  1. 处理错误的动态信息

    _bad_dynamic_info:
        wfi
        j     _bad_dynamic_info
    
    • 如果动态信息验证失败,进入一个无限循环,使处理器等待中断(wfi),然后继续循环。
  2. 获取启动 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。
  3. 保存启动信息

    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。
  4. 获取下一个启动参数

    fw_next_arg1:
        lla  a0, _dynamic_next_arg1
        REG_L    a0, (a0)
        ret
    
    • 返回保存的下一个启动参数。
  5. 获取下一个启动地址

    fw_next_addr:
        lla  a0, _dynamic_next_addr
        REG_L    a0, (a0)
        ret
    
    • 返回保存的下一个启动地址。
  6. 获取下一个启动模式

    fw_next_mode:
        lla  a0, _dynamic_next_mode
        REG_L    a0, (a0)
        ret
    
    • 返回保存的下一个启动模式。
  7. 获取启动选项

    fw_options:
        lla  a0, _dynamic_options
        REG_L    a0, (a0)
        ret
    
    • 返回保存的启动选项。
  8. 动态信息变量

    _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_arg1fw_next_addrfw_next_modefw_options 提供保存的启动信息,供后续启动阶段使用。

2.3 输出

该代码确保在 RISC-V 系统启动时正确验证和保存动态信息,为后续的启动过程提供必要的参数和配置。它处理了动态信息的验证、保存和传递,确保启动过程的正确性和安全性。

这个启动程序确保在 RISC-V 系统启动时正确验证和保存动态信息,为后续的启动过程提供必要的参数和配置。它处理了动态信息的验证、保存和传递,确保启动过程的正确性和安全性。

3.fw_jump.S

这段代码是一个 RISC-V 架构下的固件启动程序,用于在系统启动时执行一些关键的初始化操作,并将控制权传递给下一个启动阶段。以下是对代码的详细解释:

3.1 代码解析

  1. fw_boot_hart 函数:

    fw_boot_hart:
        li   a0, -1
        ret
    
    • 该函数在系统启动的早期阶段被调用,用于确定启动的 HART(硬件线程)ID。
    • 它将寄存器 a0 设置为 -1,表示没有特定的 HART ID 被选中作为启动 HART。
    • 这个函数返回后,a0 的值将作为启动 HART 的 ID。
  2. fw_save_info 函数:

    fw_save_info:
        ret
    
    • 该函数用于保存启动阶段的信息。
    • 目前实现为空操作(直接返回),表示没有具体的保存逻辑。这可能是一个占位符,供后续实现使用。
  3. 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)的地址。
  4. fw_next_addr 函数:

    fw_next_addr:
        lla  a0, _jump_addr
        REG_L    a0, (a0)
        ret
    
    • 该函数用于设置下一个启动阶段的入口地址。
    • 使用 lla 指令将 _jump_addr 的地址加载到 a0 中,然后返回。
  5. fw_next_mode 函数:

    fw_next_mode:
        li   a0, PRV_S
        ret
    
    • 该函数用于设置下一个启动阶段的模式。
    • a0 设置为 PRV_S,表示下一个阶段将在 S 模式(监督模式)下运行。
  6. fw_options 函数:

    fw_options:
        add  a0, zero, zero
        ret
    
    • 该函数用于设置启动选项。
    • a0 设置为 0,表示没有特定的启动选项。
  7. _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 的确定、参数传递、启动地址和模式的设置,确保系统的启动过程顺利进行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值