Arm linxu启动过程分析(一)

2024-04-16 08:32
文章标签 分析 启动 过程 arm linxu

本文主要是介绍Arm linxu启动过程分析(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文着重分析FS2410平台linux-2.6.14内核启动的详细过程,主要包括:zImage解压缩阶段、vmlinux启动汇编阶段、startkernel到创建第一个进程阶段三个部分,一般将其称为linux内核启动一、二、三阶段,本文也将采用这种表达方式。对于zImage之前的启动过程,本文不做表述,可参考作者“u-boot-1.3.1启动过程分析”一文。

-------------------------------------------------------------------------------------------------------

硬件平台:优龙FS2410开发板

CPU:S3C2410(Arm920T); NORFlash: SST39VF1601(2MB)

SDRAM:K4S561632D-TC/L75 (32M)x2)NandFlash: K9K2G08U0M-YCB0(64MB)

Netcard: CS8900A)。

软件平台:u-boot-1.3.1linux-2.6.14

-------------------------------------------------------------------------------------------------------

本文中涉及到的术语约定如下:

*        基本内核映像:即内核编译过程中最终在内核源代码根目录下生成的vmlinux映像文件,并不包含任何内核解压缩和重定位代码;

*        zImage内核映像:包含了内核及压缩和重定位代码,以及基本内核映像vmlinux的压缩挡piggy.gz的一个映像文件,通常是目标板bootloader加载的对象;

*        zImage下载地址:即bootloaderzImage下载到目标板内存的某个地址或者nandreadzImage读到内存的某个地址;

*        zImage加载地址:由Linuxbootloader完成的将zImage搬移到目标板内存的某个位置所对应的地址值,默认值0x30008000

关于内何映像的生成过程可以参考前一篇"Armlinux内核映像生成过程"

1Linux内核启动第一阶段:内核解压缩和重定位

 

该阶段是从u-boot引导进入内核执行的第一阶段,我们知道u-boot引导内核启动的最后一步是:通过一个函数指针thekernel()带三个参数跳转到内核(zImage)入口点开始执行,此时,u-boot的任务已经完成,控制权完全交给内核(zImage)。

稍作解释,在u-boot的文件lib_arm/armlinux.c(u-boot-1.3.1)或者lib_arm/bootm.c (u-boot-1.3.4)中定义了thekernel,并在do_bootm_linux的最后执行thekernel,如下:

void (*theKernel)(int zero, int arch, uint params);

theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);

//hdr->ih_ep----Entry Point Address uImage 中指定的内核入口点,这里是0x30008000。

theKernel (0, bd->bi_arch_number, bd->bi_boot_params);其中第二个参数为机器ID,第三参数为u-boot传递给内核参数存放在内存中的首地址,此处是0x30000100。

由上述zImage的生成过程我们可以知道,第一阶段运行的内核映像实际就是arch/arm/boot/compressed/vmlinux,而这一阶段所涉及的文件也只有三个: 

arch/arm/boot/compressed/vmlinux.lds

arch/arm/boot/compressed/head.S
     arch/arm/boot/compressed/misc.c


我们的分析集中在arch/arm/boot/compressed/head.S,适当参考vmlinux.lds

arch/arm/boot/compressed/vmlinux的反汇编代码可一看出,内核执行的第一个代码段位start,

*****start

vmlinux:    file format elf32-littlearm

Disassembly of section.text:

00000000<start>:

      0:e1a00000       nop               (mov r0,r0)

          ….         ….           …..

     1c:e1a00000       nop               (mov r0,r0)

       20:ea000002      b    30 <.text+0x30>

           ….         ….           …..

*****保存参数

     30:e1a07001      mov r7, r1

u-boot向内传递参数分析

//thekernel传递的三个参数分别保存在r0,r1,r2中。

//将机器ID保存在r7

     34:e3a08000       mov r8, #0     ; 0x0

//保存r0,这里似乎没有太大的意义,

这里没有保存r2,也就是u-boot传递给内核参数的首地址0x30000100,看来linux-2.6.14启动时是不需要传递该参数的而是通过structmachine_descinclude/asm-arm/mach/arch.h)来确定,但是这个文件只是该结构的定义,真正的参数赋值在哪呢?实际上,这就是在内核移植是需要做的工作了,内核移植最主要的一个文件就是arch/arm/mach-s3c2410/mach-fs2410.c,通过下面的宏来实现对machine_desc结构体的赋值,并且在该文件中对所涉及到的函数进行了具体的代码实现,这是内核移植方面的内容,与我们的主题无关,这里不再多说。

MACHINE_START(SMDK2410,"SMDK2410")

/*@TODO: request a new identifier and switch to SMDK2410 */

.phys_ram    = S3C2410_SDRAM_PA,

.phys_io = S3C2410_PA_UART,

      .io_pg_offst  = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

      .boot_params= S3C2410_SDRAM_PA + 0x100,

//指定u-boot传递给内核的参数存放的位置

      .map_io        = smdk2410_map_io,

      .init_irq = smdk2410_init_irq,

      .init_machine  = sdmk2410_init,

      .timer           = &s3c24xx_timer,

MACHINE_END

下面我们采用汇编代码来进行分析:arch/arm/boot/compressed/head.S

             .align

start:    //u-boot first jump to this execute

             .type      start,#function

             .rept 8

             mov r0,r0

             .endr

 

             b    1f

             .word     0x016f2818          @ Magic numbers to help the loader

             .word     start              @ absolute load/run zImage address

             .word     _edata                  @ zImage end address

1:           mov r7, r1                   @ save architecture ID

             mov r8,#0                   @ save r0

*****判定是否是超级用户模式

             mrs r2, cpsr          @ getcurrent mode

             tst   r2, #3          @ not user?  //判断当前是否为超级用户权限模式

             bne not_angel    //如果是超级用户权限模式,jumpto not_angel

             mov r0,#0x17             @ angel_SWIreason_EnterSVC  如果是普通用户模式,则通过软中断进入超级用户权限模式

             swi 0x123456             @ angel_SWI_ARM

*****关中断

not_angel:

             mrs r2, cpsr          @ turnoff interrupts to   //关中断

             orr  r2, r2, #0xc0         @prevent angel from running

             msr cpsr_c, r2

*****将编译时指定的一些变量加载到相应的寄存器中

/* somearchitecture specific code can be inserted by the linker here, but itshould preserve r7 and r8.    zImage的连接首地址为0x0 zImage的运行时首地址一般为0x30008000,当然可以不同 */

.text

adr  r0, LC0  //读取LC0的当前运行时地址,应当为zImage的运行时起始地址+(LC0zImage链接地址的首地址(0x0)的偏移)

ldmiar0, {r1, r2, r3, r4, r5, r6, ip, sp}//LC0中的变量值加载到r1,r2, r3, r4, r5, r6, ip, sp

subs r0,r0, r1        @ calculate thedelta offset //计算当前运行地址与链接地址的偏移

beq  not_relocated  @ if delta is zero, we are running at the addresswe were linked at.

//如果运行地址等于链接地址,则跳过重定位部分代码,否则继续执行relocate

/*                .type    LC0, #object

LC0: .word   LC0               @ r1

    .word   __bss_start        @ r2

    .word   _end              @ r3

    .word   zreladdr          @ r4

    .word   _start            @ r5

    .word   _got_start         @ r6

    .word   _got_end           @ ip

    .word   user_stack+4096    @ sp

LC1: .word   reloc_end - reloc_start

    .size   LC0, . - LC0       */

/* We're running at adifferent address.  We need to fix up various pointers:

     *  r5 - zImage base address

     *  r6 - GOT start

     *  ip - GOT end

GOTglobaloffset table

GOT是一个数组,存在ELFimage的数据段中,他们是一些指向objects的指针(通常

是数据objects).动态连接器将重新修改那些编译时还没有确定下来地址的符号的

GOT入口。所以说GOTi386动态连接中扮演着重要的角色。*/

*****将上面的变量进行重定位,转换为当前的运行时地址

        add r5, r5, r0   //zImage的链接时首地址重定位为运行时首地址

        add r6, r6, r0   //GOT的链接时首地址重定位为运行时首地址

        add ip, ip, r0

#ifndef CONFIG_ZBOOT_ROM

        /*If we're running fully PIC === CONFIG_ZBOOT_ROM = n,

         *we need to fix up pointers into the BSS region.

         *  r2 - BSS start

         *  r3 - BSS end

         *  sp - stack pointer  */

        add r2, r2, r0   //__bss_start的链接时首地址重定位为运行时首地址

        add r3, r3, r0   //_end的链接时地址重定位为运行时地址

        add sp, sp, r0 //user_stack+4096的链接时地址重定位为运行时地址

        /*Relocate all entries in the GOT table.

          重定位GOT中的所有链接地址为当前运行时地址*/

1:     ldr   r1, [r6, #0]           @ relocate entries in the GOT

        add r1, r1, r0        @ table. This fixes up the

        str  r1, [r6], #4           @ C references.

        cmpr6, ip

        blo  1b

#else

        /*Relocate entries in the GOT table.  We only relocate

         *the entries that are outside the (relocated) BSS region.

          重定位GOT中的所有链接地址为当前运行时地址但是不重定位

         BSS_STARTBSS_END部分 */

1:     ldr   r1, [r6, #0]           @ relocate entries in the GOT

        cmpr1, r2                   @ entry < bss_start ||

        cmphs    r3, r1                   @ _end < entry

        addlo      r1, r1, r0        @ table. This fixes up the

        str  r1, [r6], #4           @ C references.

        cmpr6, ip

        blo  1b

#endif

*****重定位已经完成,清零BSS

not_relocated:  movr0, #0

1:            str   r0, [r2], #4           @ clear bss

        str  r0, [r2], #4

        str  r0, [r2], #4

        str  r0, [r2], #4

        cmpr2, r3

        blo  1b

*****准备进入C程序的相关设置,开启cache,设置一些指针

/* The C runtimeenvironment should now be setup sufficiently. Turn the cache on, setup some pointers, and start decompressing. */

        cacheon是一个相当复杂的过程,这里简单描述其流程,如有兴趣可参考“Armlinux启动第一阶段cacheon分析”

bl     cache_on -------call_cache_fn-------

通过查表proc_types调用__armv4_cache_on

---------------------------__setup_mmu

__setup_mmu:  sub  r3, r4, #16384       //4k,r3=0x30004000

@Page directory size  //16384=16kB=0x4000

           bic  r3, r3, #0xff          @Align the pointer

           bic  r3, r3, #0x3f00

/*Initialise the page tables, turning on the cacheable and bufferablebits for the RAM area only.   */

           movr0, r3

           movr8, r0, lsr #18  r8=0x30004000>>18=0xc00

           movr8, r8, lsl #18        @ start ofRAM,

//r8=0xc00<<18=0x30000000

           add r9, r8, #0x10000000@ a reasonable RAM size

//r9=0x40000000

           movr1, #0x12

           orr r1, r1, #3 << 10 //r1=0xc00|0x12=0xc12

           add r2, r3, #16384  //r2=0x30004000+0x4000=0x30008000

1:        cmp r1, r8                   @ if virt > start of RAM

           orrhs     r1, r1, #0x0c         @ setcacheable, bufferable

           cmpr1, r9                   @ if virt > end of RAM

           bichs     r1, r1, #0x0c         @ clearcacheable, bufferable

           str  r1, [r0], #4           @ 1:1 mappi

 



//r0=0x300040000,r1=0xc12

//0x12表明这是一个段描述符即bit4bit11

//0xc00bit11bit1011,即AP=11,允许所有读写访问

           add r1, r1, #1048576 //1048576=0x100000

           teq r0, r2

           bne 1b

//上面代码段实现0x00000000~0x400000001GB)地址空间也表的创建,映射的目的地址也是0x00000000~0x40000000,所以没有实际意义,也许是为了打开cache以及设置访问属性。

mov  r0, #0

mcr  p15, 0, r0, c7, c10, 4    @ drain write buffer清零

mcr  p15, 0, r0, c8, c7, 0            @ flush I,D TLBs  清零

mrc  p15, 0, r0, c1, c0, 0            @ read control reg  清零

orr    r0, r0,#0x5000            @ I-cache enable, RR cache replacement

orr    r0, r0, #0x0030

bl  __common_cache_on------->

__common_cache_on:

#ifndef DEBUG

          orr  r0, r0, #0x000d            @ Write buffer, mmu

#endif

          mov r1,#-1

          mcr p15,0, r3, c2, c0, 0      @ load page tablepointer

//将页表基址写入页表基址寄存器cp15c2

          mcr p15, 0, r1, c3, c0, 0     

//设置域访问控制寄存器,写入0xffffffff,与控制位为11,也就是允许权限检查,可以访问。

          mcr p15,0, r0, c1, c0, 0      @ load controlregister

          mov pc,lr

mov  r0, #0

mcr  p15, 0, r0, c8, c7, 0     @ flush I,D TLBs

mov  pc, r12

返回, cacheon结束。

//这里的r1,r2之间的空间为解压缩内核程序所使用,也是传递给decompress_kernel的第二和第三的参数

        movr1, sp                   @ malloc space above stack  //SP的运行时地址存入r0

        add r2, sp, #0x10000    @ 64k max  //r2=sp+0x10000

 

*****解压缩内核,分三种情况,请看下篇...



这篇关于Arm linxu启动过程分析(一)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/908285

相关文章

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

springboot3打包成war包,用tomcat8启动

1、在pom中,将打包类型改为war <packaging>war</packaging> 2、pom中排除SpringBoot内置的Tomcat容器并添加Tomcat依赖,用于编译和测试,         *依赖时一定设置 scope 为 provided (相当于 tomcat 依赖只在本地运行和测试的时候有效,         打包的时候会排除这个依赖)<scope>provided

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

用命令行的方式启动.netcore webapi

用命令行的方式启动.netcore web项目 进入指定的项目文件夹,比如我发布后的代码放在下面文件夹中 在此地址栏中输入“cmd”,打开命令提示符,进入到发布代码目录 命令行启动.netcore项目的命令为:  dotnet 项目启动文件.dll --urls="http://*:对外端口" --ip="本机ip" --port=项目内部端口 例: dotnet Imagine.M

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57