当前位置: 首页 > news >正文

lx2160 LSDK21.08 firmware 笔记 - 1.bl31.bin 链接脚本 bl31.ld.S 分析

bl31.ld.S分析

通过链接脚本 bl31.ld.S,可得知整个镜像的内存布局:

  • 镜像起始运行地址- BL31_BASE
  • 镜像入口函数-bl31_entrypoint()

前言

芯片所有的软硬件资源都能够在 NXP 官网找到,本文档也是对 NXP 开源 LSDK 代码工程的学习与分析。
官网链接如下:
LSDK 软件资料
LX2160 芯片资料

1.链接脚本生成流程

通读 atf 工程 makefile 框架后得知,链接脚本通过 MAKE_BL 宏函数生成,简化后如下:

define MAKE_BL

		# 省略
		
        $(eval DEFAULT_LINKER_SCRIPT_SOURCE := $($(call uppercase,$(1))_DEFAULT_LINKER_SCRIPT_SOURCE))
        $(eval DEFAULT_LINKER_SCRIPT := $(call linker_script_path,$(DEFAULT_LINKER_SCRIPT_SOURCE)))

        # BL2 与 BL31 只使用了默认链接脚本,下面的变量为自定义变量,指向自定义连接脚本
        $(eval LINKER_SCRIPT_SOURCES := $($(call uppercase,$(1))_LINKER_SCRIPT_SOURCES))
        $(eval LINKER_SCRIPTS := $(call linker_script_path,$(LINKER_SCRIPT_SOURCES)))
        
# 省略

# Generate targets to preprocess each required linker script
# 生成链接脚本 ld 文件
$(eval $(foreach source,$(DEFAULT_LINKER_SCRIPT_SOURCE) $(LINKER_SCRIPT_SOURCES), \
        $(call MAKE_LD,$(call linker_script_path,$(source)),$(source),$(1))))

# 省略

endef

链接脚本通过下述命令生成:

$(eval $(call MAKE_LD,$(LINKERFILE),$(BL_LINKERFILE),$(1)))

其中:

  • $(1))_DEFAULT_LINKER_SCRIPT_SOURCEbl31/bl31.ld.S
  • 生成链接脚本文件为: release/bl31/bl31.ld. (bl2.ld 文件生成的代码同理)

2.bl31.ld 分析

bl31.ld 与 bl31.ld.S 的区别是使用了 gcc 编译器对一些宏进行扩展,让整个内存布局地址更明确, 通过生成的 bl31.ld, 我们可以更明确的知道地址分配,源码如下:

OUTPUT_FORMAT("elf64-littleaarch64")
OUTPUT_ARCH(aarch64)
ENTRY(bl31_entrypoint)
MEMORY {
    RAM (rwx): ORIGIN = (0x80000000 + 0x80000000 - ((64 * 1024 * 1024) + (2 * 1024 * 1024))), LENGTH = ((0x80000000 + 0x80000000 - ((64 * 1024 * 1024) + (2 * 1024 * 1024))) + (0x200000)) - (0x80000000 + 0x80000000 - ((64 * 1024 * 1024) + (2 * 1024 * 1024)))
}
SECTIONS {
    RAM_REGION_START = ORIGIN(RAM);
    RAM_REGION_LENGTH = LENGTH(RAM);
    . = (0x80000000 + 0x80000000 - ((64 * 1024 * 1024) + (2 * 1024 * 1024)));
    ASSERT(. == ALIGN(((1) << (12))),
        "BL31_BASE address is not aligned on a page boundary.")
    __BL31_START__ = .;
    .text . : {
        __TEXT_START__ = .;
        *bl31_entrypoint.o(.text*)
        *(SORT_BY_ALIGNMENT(SORT(.text*)))
        *(.vectors)
        __TEXT_END_UNALIGNED__ = .;
        . = ALIGN(((1) << (12)));
        __TEXT_END__ = .;
    } >RAM
    .rodata . : {
        __RODATA_START__ = .;
        *(SORT_BY_ALIGNMENT(.rodata*))
        . = ALIGN(8); __RT_SVC_DESCS_START__ = .; KEEP(*(.rt_svc_descs)) __RT_SVC_DESCS_END__ = .; . = ALIGN(8); __FCONF_POPULATOR_START__ = .; KEEP(*(.fconf_populator)) __FCONF_POPULATOR_END__ = .; . = ALIGN(8); __PMF_SVC_DESCS_START__ = .; KEEP(*(.pmf_svc_descs)) __PMF_SVC_DESCS_END__ = .; . = ALIGN(8); __PARSER_LIB_DESCS_START__ = .; KEEP(*(.img_parser_lib_descs)) __PARSER_LIB_DESCS_END__ = .; . = ALIGN(8); __CPU_OPS_START__ = .; KEEP(*(.cpu_ops)) __CPU_OPS_END__ = .; . = ALIGN(8); __GOT_START__ = .; *(.got) __GOT_END__ = .;
        . = ALIGN(8);
__pubsub_psci_cpu_on_finish_start = .; KEEP(*(.__pubsub_psci_cpu_on_finish)); __pubsub_psci_cpu_on_finish_end = .;
__pubsub_psci_suspend_pwrdown_start_start = .; KEEP(*(.__pubsub_psci_suspend_pwrdown_start)); __pubsub_psci_suspend_pwrdown_start_end = .;
__pubsub_psci_suspend_pwrdown_finish_start = .; KEEP(*(.__pubsub_psci_suspend_pwrdown_finish)); __pubsub_psci_suspend_pwrdown_finish_end = .;
__pubsub_cm_entering_secure_world_start = .; KEEP(*(.__pubsub_cm_entering_secure_world)); __pubsub_cm_entering_secure_world_end = .;
__pubsub_cm_exited_secure_world_start = .; KEEP(*(.__pubsub_cm_exited_secure_world)); __pubsub_cm_exited_secure_world_end = .;
__pubsub_cm_entering_normal_world_start = .; KEEP(*(.__pubsub_cm_entering_normal_world)); __pubsub_cm_entering_normal_world_end = .;
__pubsub_cm_exited_normal_world_start = .; KEEP(*(.__pubsub_cm_exited_normal_world)); __pubsub_cm_exited_normal_world_end = .;
        __RODATA_END_UNALIGNED__ = .;
        . = ALIGN(((1) << (12)));
        __RODATA_END__ = .;
    } >RAM
    ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__,
        "cpu_ops not defined for this platform.")
    __RW_START__ = . ;
    .data . : ALIGN(1) { __DATA_START__ = .; *(SORT_BY_ALIGNMENT(.data*)) __DATA_END__ = .; } >RAM
    .rela.dyn : ALIGN(8) { __RELA_START__ = .; *(.rela*) __RELA_END__ = .; } >RAM
    .stacks (NOLOAD) : { __STACKS_START__ = .; *(.tzfw_normal_stacks) __STACKS_END__ = .; } >RAM
    .bss (NOLOAD) : ALIGN(16) { __BSS_START__ = .; *(SORT_BY_ALIGNMENT(.bss*)) *(COMMON) . = ALIGN(64); __BAKERY_LOCK_START__ = .; __PERCPU_BAKERY_LOCK_START__ = .; *(.bakery_lock) . = ALIGN(64); __PERCPU_BAKERY_LOCK_END__ = .; __PERCPU_BAKERY_LOCK_SIZE__ = ABSOLUTE(__PERCPU_BAKERY_LOCK_END__ - __PERCPU_BAKERY_LOCK_START__); . = . + (__PERCPU_BAKERY_LOCK_SIZE__ * (8 * 2 - 1)); __BAKERY_LOCK_END__ = .; ASSERT((__PERCPU_BAKERY_LOCK_SIZE__ == 0) || (__PERCPU_BAKERY_LOCK_SIZE__ == (1 * 64)), "PLAT_PERCPU_BAKERY_LOCK_SIZE does not match bakery lock requirements"); . = ALIGN(64); __PMF_TIMESTAMP_START__ = .; KEEP(*(.pmf_timestamp_array)) . = ALIGN(64); __PMF_PERCPU_TIMESTAMP_END__ = .; __PERCPU_TIMESTAMP_SIZE__ = ABSOLUTE(. - __PMF_TIMESTAMP_START__); . = . + (__PERCPU_TIMESTAMP_SIZE__ * (8 * 2 - 1)); __PMF_TIMESTAMP_END__ = .; . = ALIGN(16); __BASE_XLAT_TABLE_START__ = .; *(.base_xlat_table) __BASE_XLAT_TABLE_END__ = .; __BSS_END__ = .; } >RAM
    .xlat_table (NOLOAD) : { __XLAT_TABLE_START__ = .; *(.xlat_table) __XLAT_TABLE_END__ = .; } >RAM
    __RW_END__ = .;
    __BL31_END__ = .;
    ASSERT(. <= ((0x80000000 + 0x80000000 - ((64 * 1024 * 1024) + (2 * 1024 * 1024))) + (0x200000)), "BL31 image has exceeded its limit.")
    RAM_REGION_END = .;
    /DISCARD/ : {
        *(.dynsym .dynstr .hash .gnu.hash)
    }
}

编译过程中,会生成bl31.map 文件,结合 map 文件,可以更明确的知道段分配,每一个段内的成员地址,链接脚本定义的段变量地址。
生成的链接脚本请自行阅读。

相关文章:

  • JavaWeb 课堂笔记 —— 09 MySQL 概述 + DDL
  • 基于贝叶斯方法的地震动分析及AI拓展
  • mysql安装-MySQL MGR(Group Replication)+ ProxySQL 架构
  • 前端 react+ant design ,后端 springboot +mysql+redis 全栈项目零基础小白从服务器初始化开始部署上线超详细保姆级教程
  • Ubuntu24.04 编译 Qt5 和 Qt6 源码
  • Android Cmake构建的项目,需不需要配置指定ndk及版本
  • 动态路由, RIP路由协议,RIPv1,RIPv2
  • MarkDown 输出表格的方法
  • 信息安全管理与评估2022国赛正式卷一阶段答案截图
  • [leetcode]第445场周赛
  • 亲手打造可视化故事线管理工具:开发全流程、难点突破与开发过程经验总结
  • SSH远程访问及控制
  • 数据结构——哈希详解
  • Pytorch深度学习框架60天进阶学习计划 - 第41天:生成对抗网络进阶(二)
  • Tkinter进度条与状态栏
  • c++ 里友元函数可以声明与定义放一块么,答案是可以,这是友元函数会自动成为内联函数
  • Spring 事务传播行为
  • 【Android】ContentResolver的使用
  • 【2025软考高级架构师】——软件架构设计(4)
  • 关于 LLB 的问题
  • 订婚不等于性同意!山西订婚强奸案入选最高法案例
  • 台行政机构网站删除“汉人”改为“其余人口”,国台办回应
  • 外国游客“在华扫货”热:“带空箱子到中国!”
  • 警方通报“网约车司机偷拍女乘客”:已被行政拘留
  • 竞彩湃|热刺、曼联一周双赛不易,勒沃库森能否欢送阿隆索
  • 春秋航空:如果供应链持续改善、油价回落到合理水平,公司补充运力的需求将会增长