optee os 的启动和初始化

optee的ld文件在如下路径os/core/arch/arm/kernel/kern.ld.S
ENTRY(_start)
SECTIONS
{
    . = CFG_TEE_LOAD_ADDR;

    __text_start = .;

    /*
     * Memory between CFG_TEE_LOAD_ADDR and page aligned rounded down
     * value will be mapped with unpaged "text" section attributes:
     * likely to be read-only/executable.
     */
    __flatmap_unpg_rx_start = ROUNDDOWN(__text_start, SMALL_PAGE_SIZE);

    .text : {
        KEEP(*(.text.boot.vectab1))
        KEEP(*(.text.boot.vectab2))
        KEEP(*(.text.boot))
}
从这里可以知道optee的第一行指令是_start,optee 只是arm32和arm64.这里以arm64为例
arm64的_start 定义在os/core/arch/arm/kernel/generic_entry_a64.S 中
    /*
     * Setup SP_EL0 and SPEL1, SP will be set to SP_EL0.
     * SP_EL0 is assigned stack_tmp + (cpu_id + 1) * stack_tmp_stride -
     *              stack_tmp_offset
     * SP_EL1 is assigned thread_core_local[cpu_id]
     */
    .macro set_sp
        bl    get_core_pos
        cmp    x0, #CFG_TEE_CORE_NB_CORE
        /* Unsupported CPU, park it before it breaks something */
        bge    unhandled_cpu
        add    x0, x0, #1
        adr    x2, stack_tmp_stride
        ldr    w1, [x2]
        mul    x2, x0, x1
        adrp    x1, stack_tmp
        add    x1, x1, :lo12:stack_tmp
        add    x1, x1, x2
        adr    x2, stack_tmp_offset
        ldr    w2, [x2]
        sub    x1, x1, x2
        msr    spsel, #0
        mov    sp, x1
        bl    thread_get_core_local
        msr    spsel, #1
        mov    sp, x0
        msr    spsel, #0
    .endm

.section .text.boot
入口地址从这里开始执行optee os
FUNC _start , :
    mov    x19, x0        /* Save pagable part address */
    mov    x20, x2    //x2传递过来DT address    /* Save DT address */

    adr    x0, reset_vect_table
    msr    vbar_el1, x0
    isb

    mrs    x0, sctlr_el1
    mov    x1, #(SCTLR_I | SCTLR_A | SCTLR_SA)
    orr    x0, x0, x1
    msr    sctlr_el1, x0
    isb

#ifdef CFG_WITH_PAGER
    /*
     * Move init code into correct location
     *
     * The binary is built as:
     * [Pager code, rodata and data] : In correct location
     * [Init code and rodata] : Should be copied to __init_start
     * [Hashes] : Should be saved before clearing bss
     *
     * When we copy init code and rodata into correct location we don't
     * need to worry about hashes being overwritten as size of .bss,
     * .heap, .nozi and .heap3 is much larger than the size of init
     * code and rodata and hashes.
     */
    adr    x0, __init_start    /* dst */
    adr    x1, __data_end        /* src */
    adr    x2, __init_end        /* dst limit */
copy_init:
    ldp    x3, x4, [x1], #16
    stp    x3, x4, [x0], #16
    cmp    x0, x2
    b.lt    copy_init
#endif

    /* Setup SP_EL0 and SP_EL1, SP will be set to SP_EL0 */
    set_sp

    /* Enable aborts now that we can receive exceptions */
    msr    daifclr, #DAIFBIT_ABT

    adr    x0, __text_start
#ifdef CFG_WITH_PAGER
    adrp    x1, __init_end
    add    x1, x1, :lo12:__init_end
#else
    adrp    x1, __end
    add    x1, x1, :lo12:__end
#endif
    sub    x1, x1, x0
    bl    inv_dcache_range

    /* Enable Console */
    bl    console_init //初始化串口

    bl    core_init_mmu_map //初始化mmu
    bl    core_init_mmu_regs //初始化mmu 寄存器
    bl    cpu_mmu_enable //经过前两步后可以使能mmu
    bl    cpu_mmu_enable_icache //使能icache
    bl    cpu_mmu_enable_dcache 使能Dcache

    mov    x0, x19        /* pagable part address */
    mov    x1, #-1
    mov    x2, x20        /* DT address */
    bl    generic_boot_init_primary // 执行主要初始化

    /*
     * In case we've touched memory that secondary CPUs will use before
     * they have turned on their D-cache, clean and invalidate the
     * D-cache before exiting to normal world.
     */
    mov    x19, x0
    adr    x0, __text_start
#ifdef CFG_WITH_PAGER
    adrp    x1, __init_end
    add    x1, x1, :lo12:__init_end
#else
    adrp    x1, __end
    add    x1, x1, :lo12:__end
#endif
    sub    x1, x1, x0
    bl    flush_dcache_range


    /*
     * Clear current thread id now to allow the thread to be reused on
     * next entry. Matches the thread_init_boot_thread in
     * generic_boot.c.
     */
    bl     thread_clr_boot_thread //调用thread_clr_boot_thread清理current thread id

    /* Pass the vector address returned from main_init */
    mov    x1, x19
    mov    x0, #TEESMC_OPTEED_RETURN_ENTRY_DONE
//通过smc 返回到ATF的el3中,通知atf optee已经启动完成.
    smc    #0
    b    .    /* SMC should not return */
END_FUNC _start





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux的启动初始化程序通常由两个部分组成:引导程序(bootloader)和初始化程序(init)。 引导程序是在计算机开机时最先执行的程序,主要负责加载操作系统内核和初始化系统环境。常见的Linux引导程序有GRUB和LILO。 初始化程序是Linux系统中第一个用户空间进程,它负责启动系统中的其他进程和服务,并建立用户环境。常见的Linux初始化程序有SysVinit和systemd。 下面是一个简单的初始化程序的示例: ``` #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { pid_t pid; pid = fork(); // 创建子进程 if (pid < 0) { printf("fork error\n"); return -1; } else if (pid == 0) { // 子进程执行的代码 printf("child process\n"); // 启动其他服务和进程 execl("/bin/bash", "/bin/bash", NULL); } else { // 父进程执行的代码 printf("parent process\n"); // 等待子进程结束 waitpid(pid, NULL, 0); } return 0; } ``` 这个程序使用fork()系统调用创建一个子进程,并使用execl()系统调用启动其他进程和服务。在父进程中,使用waitpid()系统调用等待子进程结束。 需要注意的是,初始化程序的编写需要考虑系统的安全性和稳定性,需要遵循一些规范和最佳实践,例如使用权限控制、错误处理、日志记录等。同时,不同的Linux发行版可能有不同的初始化程序和启动脚本,需要根据实际情况进行相应的调整和修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值