barebox启动分析(一)

来源:互联网 发布:人力资源部门数据分析 编辑:程序博客网 时间:2024/06/06 00:17

barebox启动分析 一

当做了uboot,kernel,little kernel 的启动分析后,其实会发现启动分析也有一定的方法

第一步链接脚本

无论是哪个项目,我们看代码的入口总是先去找main,而这些项目,我们去找链接脚本
barebox的链接脚本:arch/arm/lib/barebox.lds.S

ENTRY(start)SECTIONS{#ifdef CONFIG_RELOCATABLE        . = 0x0;#else        . = TEXT_BASE;#endif#ifndef CONFIG_PBL_IMAGE        PRE_IMAGE#endif        . = ALIGN(4);        .text      :           {                _stext = .;                _text = .;                *(.text_entry*)                __bare_init_start = .;                *(.text_bare_init*)                __bare_init_end = .;                . = ALIGN(4);                __exceptions_start = .;                KEEP(*(.text_exceptions*))                __exceptions_stop = .;                *(.text*)        }        BAREBOX_BARE_INIT_SIZE

可以发现如果定义了CONFIG_PBL_IMAGE,一段代码是执行pbl代码。因为一般的嵌入是soc都需要pbl引导。所以我们就分析有pbl的情况。当使用pbl时它使用了另一个链接脚本:arch/arm/lib/pbl.lds.S

OUTPUT_ARCH(arm)SECTIONS{        . = BASE;        PRE_IMAGE        . = ALIGN(4);        .text      :           {                _stext = .;                _text = .;                *(.text_head_entry*)                __bare_init_start = .;                *(.text_bare_init*)                __bare_init_end = .;                *(.text*)        }

可以看见放在最前面的代码段是text_head_entry
然后我们通过grep “text_head_entry” arch/arm -nr
grep_text_head_entry)
我们如愿异常的找到我们自己的main

第二步 抓住代码入口

为了找到这个入口,我查了很多代码。

ENTRY_FUNCTION(start_barebox_karo_tx28, r0, r1, r2){        barebox_arm_entry(IMX_MEMORY_BASE, SZ_128M, NULL);}

ENTRY_FUNCTION的定义:

#define ENTRY_FUNCTION(name, arg0, arg1, arg2)                          \        static void __##name(uint32_t, uint32_t, uint32_t);             \                                                                        \        void __naked __section(.text_head_entry_##name) name            \                                (uint32_t r0, uint32_t r1, uint32_t r2) \                {                                                       \                        __barebox_arm_head();                           \                        __##name(r0, r1, r2);                           \                }                                                       \                static void __naked noinline __##name                   \                        (uint32_t arg0, uint32_t arg1, uint32_t arg2)#endif  /* _BAREBOX_ARM_H_ */

这个宏回调了最后执行的是:barebox_arm_entry

void __naked __noreturn barebox_arm_entry(unsigned long membase,                                          unsigned long memsize, void *boarddata){               arm_setup_stack(arm_mem_stack(membase, membase + memsize) + STACK_SIZE - 16);        arm_early_mmu_cache_invalidate();        if (IS_ENABLED(CONFIG_PBL_MULTI_IMAGES))                barebox_multi_pbl_start(membase, memsize, boarddata);        else if (IS_ENABLED(CONFIG_PBL_SINGLE_IMAGE))                barebox_single_pbl_start(membase, memsize, boarddata);        else                barebox_non_pbl_start(membase, memsize, boarddata);}       

根据我们配置的宏它执行了:barebox_single_pbl_start

__noreturn void barebox_single_pbl_start(unsigned long membase,                unsigned long memsize, void *boarddata){        uint32_t offset;        uint32_t pg_start, pg_end, pg_len;        void __noreturn (*barebox)(unsigned long, unsigned long, void *);        uint32_t endmem = membase + memsize;        unsigned long barebox_base;.................................        pbl_barebox_uncompress((void*)barebox_base, (void *)pg_start, pg_len);        arm_early_mmu_cache_flush();        flush_icache();        if (IS_ENABLED(CONFIG_THUMB2_BAREBOX))                barebox = (void *)(barebox_base + 1);        else                barebox = (void *)barebox_base;        barebox(membase, memsize, boarddata);

可以看见它把barebox本身解压到一个内存地址然后调过去执行了。

0 0
原创粉丝点击