uboot relocation
uboot relocation
platform: ARM64
arch/arm/lib/crt0_64.S
uboot分为relocation前和relocation后两个stage,这两个stage stack所在的位置不同
对于relocation前,在_main()里设置sp的初始值为CONFIG_SYS_INIT_SP_ADDR,将这个初始值减去sizeof(struct global_data)以划出global_data struct的空间,这个相减的结果再保存到sp,此时的sp是这个stage的stack top
66 ENTRY(_main) 78 #else 79 ldr x0, =(CONFIG_SYS_INIT_SP_ADDR) 80 #endif 81 bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */ 82 mov x0, sp 83 bl board_init_f_alloc_reserve 84 mov sp, x0 85 /* set up gd here, outside any C code */ 86 mov x18, x0 87 bl board_init_f_init_reserve 88 89 mov x0, #0 90 bl board_init_f 92 #if !defined(CONFIG_SPL_BUILD) 93 /* 94 * Set up intermediate environment (new sp and gd) and call 95 * relocate_code(addr_moni). Trick here is that we'll return 96 * 'here' but relocated. 97 */ 98 ldr x0, [x18, #GD_START_ADDR_SP] /* x0 <- gd->start_addr_sp */ 99 bic sp, x0, #0xf /* 16-byte alignment for ABI compliance */ 100 ldr x18, [x18, #GD_NEW_GD] /* x18 <- gd->new_gd */ 101 102 adr lr, relocation_return 110 /* Add in link-vs-relocation offset */ 111 ldr x9, [x18, #GD_RELOC_OFF] /* x9 <- gd->reloc_off */ 112 add lr, lr, x9 /* new return address after relocation */ 113 ldr x0, [x18, #GD_RELOCADDR] /* x0 <- gd->relocaddr */ /*GD_RELOCADDR是relocaddr成员在global_data struct里的offset,x18即是gd指针*/
114 b relocate_code
然后调用board_init_f,这个函数会执行init_sequece_f数组里的函数,这些函数会设置uboot relocation相关的gd成员,这些成员有:
gd->relocaddr:setup_dest_addr()先给gd->relocaddr设置一个初值,设置为CONFIG_SYS_INIT_SP_ADDR,这个macro一般是define在include/configs/下的相应header里。后面在一些其它函数里还会去+-gd->relocaddr,最后在setup_reloc()里计算relocation offset,即设置gd->reloc_off;
gd->reloc_off:gd->relocaddr和uboot初始加载地址CONFIG_SYS_TEXT_BASE的差值;
gd->start_addr_sp: relocation的新stack pointer;
gd->new_gd: reloation的新的struct global_data的地址
static int setup_dest_addr(void) gd->relocaddr = CONFIG_SYS_INIT_SP_ADDR;
727 static int setup_reloc(void) 728 { 729 if (gd->flags & GD_FLG_SKIP_RELOC) { 730 debug("Skipping relocation due to flag\n"); 731 return 0; 732 } 733 734 #ifdef CONFIG_SYS_TEXT_BASE 735 #ifdef ARM 736 gd->reloc_off = gd->relocaddr - (unsigned long)__image_copy_start; 737 #elif defined(CONFIG_M68K) 738 /* 739 * On all ColdFire arch cpu, monitor code starts always 740 * just after the default vector table location, so at 0x400 741 */ 742 gd->reloc_off = gd->relocaddr - (CONFIG_SYS_TEXT_BASE + 0x400); 743 #elif !defined(CONFIG_SANDBOX) 744 gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE; 745 #endif 746 #endif 747 memcpy(gd->new_gd, (char *)gd, sizeof(gd_t)); 748 749 debug("Relocation Offset is: %08lx\n", gd->reloc_off); 750 debug("Relocating to %08lx, new gd at %08lx, sp at %08lx\n", 751 gd->relocaddr, (ulong)map_to_sysmem(gd->new_gd), 752 gd->start_addr_sp); 753 754 return 0; 755 }
然后_main()将board_init_f里设置好的gd->start_addr_sp设置到sp,此时的sp是relocation后运行所使用的stack的stack top,并将gd->new_gd的值读取出来保存到x18,此时x18指向了relocation后的global_data struct的地址
然后调用relocate_code去执行uboot relocation,它只有一个参数,保存在x0里,它的值就是上面确定的gd->relocaddr
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
2020-06-09 对IIC总线时序的一点理解以及ACK和NACK(NAK)
2020-06-09 usb Defined Class Codes