这里将告诉您解压内核镜像,教程操作步骤:

步骤 0

uboot 将 zImage 复制到内存之后,跳转到 zImage 处开始执行,首先执行的代码是 arch/arm/boot/compressed/head.S 文件,首先是一些涉及不同体系结构调试相关的汇编宏定义

#ifdefDEBUG#ifdefined(CONFIG_DEBUG_ICEDCC)#ifdefined(CONFIG_CPU_V6)||defined(CONFIG_CPU_V6K)||defined(CONFIG_CPU_V7).macroloadsp,rb,tmp.endm.macrowriteb,ch,rbmcrp14,0,ch,c0,c5,0.endm...省略...#endif#endif#endif

步骤 1

首先是保存 bootloader 传递过来的机器 ID 和 atags 起始地址

@设置段名.section".start",#alloc,#execinstr.align.arm@设置指令为arm模式start:.typestart,#function@声明为函数标签.rept7movr0,r0.endrARM(movr0,r0)ARM(b1f)@向下跳转THUMB(adrr12,BSYM(1f))THUMB(bxr12).word0x016f2818@Magicnumberstohelptheloader.wordstart@程序其实地址,即zImage的地址.word_edata@zImage结束地址THUMB(.thumb)1:movr7,r1@保存bootloader传递过来的机器IDmovr8,r2@保存bootloader传递过来的atags起始地址

步骤 2

关闭中断、进入 SVC 模式

#ifndef__ARM_ARCH_2__mrsr2,cpsr@getcurrentmodetstr2,#3@notuser?bnenot_angelmovr0,#0x17@进入SVC模式ARM(swi0x123456)@angel_SWI_ARMTHUMB(svc0xab)@angel_SWI_THUMBnot_angel:mrsr2,cpsrorrr2,r2,#0xc0@关闭FIQ和IRQmsrcpsr_c,r2#elseteqppc,#0x0c000003@turnoffinterrupts

步骤 3

为了加速解压过程,打开缓存

#ifdefCONFIG_AUTO_ZRELADDR@如果配置了运行时自动计算重定位地址@则根据当前pc位置和TEXT_OFFSET计算出解压位置@TEXT_OFFSET在arch/arm/Makefile中指定,表示的是相对于内存起始地址的偏移@定义为textofs-y:=0x00008000TEXT_OFFSET:=$(textofs-y)movr4,pcandr4,r4,#0xf8000000@这里假设zImage是被放在内存的前128MB内的addr4,r4,#TEXT_OFFSET@得到zImage解压的物理地址#else@这里是直接在arch/arm/mach-s5p4418/Makefile.boot中定义的@定义为zreladdr-y:=0x40008000ldrr4,=zreladdr@r4存放解压后内核存放的起始地址#endif@打开缓存和MMUblcache_on

步骤 4

检查解压后的内核镜像是否与当前镜像发生覆盖

restart:adrr0,LC0ldmiar0,{r1,r2,r3,r6,r10,r11,r12}@将LC0数据放入寄存器中ldrsp,[r0,#28]@更新栈指针位置subr0,r0,r1@计算当前程序位置和链接地址间的偏移量addr6,r6,r0@得到zImage运行地址的结束位置addr10,r10,r0@存放未压缩内核大小的运行地址/**内核编译系统会将未压缩的内核大小追加到压缩后的内核数据之后*并以小端格式存储*/@取出未压缩内核大小放入r9ldrbr9,[r10,#0]ldrblr,[r10,#1]orrr9,r9,lr,lsl#8ldrblr,[r10,#2]ldrbr10,[r10,#3]orrr9,r9,lr,lsl#16orrr9,r9,r10,lsl#24#ifndefCONFIG_ZBOOT_ROM/*在栈指针之上分配内存空间放到r10中(64kmax)*/addsp,sp,r0addr10,sp,#0x10000#elsemovr10,r6#endifmovr5,#0@initdtbsizeto0/**检查解压后的内核是否会覆盖当前代码*r4=最终解压后的内核起始地址*r9=解压后的内核镜像大小*r10=当前镜像结束地址,其中包括所分配的内存区域*Webasicallywant:*r4-16k页表>=r10->OK*r4+imagelength<=addressofwont_overwrite->OK*/addr10,r10,#16384@内核镜像前的16KB页表cmpr4,r10bhswont_overwrite@解压后的内核起始地址大于等于r10addr10,r4,r9adrr9,wont_overwritecmpr10,r9@或者解压后的内核结束地址在wont_overwrite地址之前blswont_overwrite/**r6=_edata*r10=endofthedecompressedkernel*/@当前代码段向后移动到的目的地址,不足256字节的补足256字节,向上取整addr10,r10,#((reloc_code_end-restart+256)&~255)bicr10,r10,#255@当前代码段起始地址,以32字节为单位,向下取整adrr5,restartbicr5,r5,#31subr9,r6,r5@需要移动镜像的大小addr9,r9,#31@以32字节为单位向上取整bicr9,r9,#31addr6,r9,r5@循环结束地址addr9,r9,r10@目的地址结束位置@循环移动当前镜像1:ldmdbr6!,{r0-r3,r10-r12,lr}cmpr6,r5stmdbr9!,{r0-r3,r10-r12,lr}bhi1bsubr6,r9,r6@代码重定位的偏移地址#ifndefCONFIG_ZBOOT_ROMaddsp,sp,r6@对栈指针也进行重定位#endifblcache_clean_flush@跳转到重定位后的镜像restart处重新执行,检查是否存在覆盖adrr0,BSYM(restart)addr0,r0,r6movpc,r0

步骤 5

清理 bss 段、解压内核、关闭缓存,最后启动内核

/*至此,当前镜像和解压后的内核不会发生覆盖问题*/wont_overwrite:/**Ifdeltaiszero,wearerunningattheaddresswewerelinkedat.*r0=delta*r2=BSSstart*r3=BSSend*r4=kernelexecutionaddress*r5=appendeddtbsize(0ifnotpresent)*r7=architectureID*r8=atagspointer*r11=GOTstart*r12=GOTend*sp=stackpointer*/orrsr1,r0,r5beqnot_relocatedaddr11,r11,r0addr12,r12,r0not_relocated:movr0,#01:strr0,[r2],#4@清理bss段strr0,[r2],#4strr0,[r2],#4strr0,[r2],#4cmpr2,r3blo1b/**至此,C语言运行环境已经初始化完成*r4=解压后的内核起始地址*r7=机器ID*r8=atags指针*/movr0,r4movr1,sp@在栈指针之上分配内存空间addr2,sp,#0x10000@64kmaxmovr3,r7bldecompress_kernel@解压内核blcache_clean_flushblcache_off@关闭缓存movr0,#0@mustbezeromovr1,r7@restorearchitecturenumbermovr2,r8@restoreatagspointerARM(movpc,r4)@启动内核THUMB(bxr4)@entrypointisalwaysARM.align2.typeLC0,#objectLC0:.wordLC0@r1:LC0的链接地址.word__bss_start@r2:bss段的起始地址.word_end@r3:bss段的结束地址.word_edata@r6:zImage的结束地址.wordinput_data_end-4@r10:存放未压缩的内核大小的链接地址.word_got_start@r11:全局偏移表起始位置.word_got_end@ip:全局偏移表结束位置.word.L_user_stack_end@sp:栈指针.sizeLC0,.-LC0@该LC0数据的大小解压内核镜像就为您介绍到这里,感谢您关注懒咪学编程c.lanmit.com.

本文地址:https://c.lanmit.com/czxt/Linux/119424.html

linux 解压安卓内核,解压内核镜像相关推荐

  1. 【Linux 内核】编译 Linux 内核 ② ( 解压内核源码 | 查询当前 Linux 内核版本号 | 进入并查看 linux 内核源码目录 )

    文章目录 一.解压内核源码 二.查询当前 Linux 内核版本号 三.进入并查看 linux 内核源码目录 一.解压内核源码 将 下载的 Linux 内核源码 linux-5.6.14.tar.gz ...

  2. Linux开机启动过程(5):内核解压

    内核引导过程. Part 5. 内核解压 这是内核引导过程系列文章的第五部分.在前一部分我们看到了切换到64位模式的过程,在这一部分我们会从这里继续.我们会看到跳进内核代码的最后步骤:内核解压前的准备 ...

  3. linux内核如何读写ddr,linux内核解压详解.doc

    linux内核解压详解 Description: /*?OldLinux论坛 -- 有关早期Linux内核代码发展的论坛. 9!%83gY* ?linux/arch/arm/boot/compress ...

  4. Linux学习之zImage内核镜像解压过程详解

      zImage内核镜像解压过程详解 收藏 zImage内核镜像解压过程详解 作者: 刘洪涛,华清远见嵌入式培训中心 讲师. 本文以linux-2.6.14内核在S3C2410平台上运行为例,讲解内核 ...

  5. 2. 内核解压-关中断进入svc模式

    内核解压的代码在arch/arm/boot/compressed/head.S start:.type start,#function.rept 7__nop.endr #ifndef CONFIG_ ...

  6. 内核解压失败或【system halted】问题汇总

    文章目录 1.内核解压失败 2.system halted 内核死机 1.内核解压失败 出现这种情况,一般主要体现在以下几个方面: uboot 环境变量 bootcmd 参数配置不正确.举例: 1.1 ...

  7. 3. 内核解压-确定解压信息

    源码位置arch/arm/boot/compressed/head.S #ifdef CONFIG_AUTO_ZRELADDR/* * Find the start of physical memor ...

  8. linux tar.xz 解压命令,Linux下.tar.xz文件的解压教程详解

    前言 对于xz这个压缩相信很多人陌生,但xz是绝大数linux默认就带的一个压缩工具,xz格式比7z还要小. 最近在下载某个源码包的时候遇到的这种压缩格式,乘此机会分享一下xz的压缩与解压方法. 安装 ...

  9. uboot linux内核传递参数,Uboot与Linux之间的参数传递详解

    原标题:Uboot与Linux之间的参数传递详解 U-boot会给Linux Kernel传递很多参数,如:串口,RAM,videofb等.而Linux kernel也会读取和处理这些参数.两者之间通 ...

最新文章

  1. postmessage 游戏窗口内无效_前端的微前端在交通项目内的应用实践
  2. [Kaggle] Sentiment Analysis on Movie Reviews(BERT)
  3. 日志级别_SpringBoot实战(十三):Admin动态修改日志级别
  4. 高计算密度+低功耗!浪潮新一代高密度服务器SA5248M4横空出世
  5. qt connect函数_Qt Inside信号和槽之connect
  6. App后台开发运维和架构实践学习总结(3)——RestFul架构下API接口设计注意点
  7. 淘宝爬取某人的所有购物订单
  8. Winform中使用进度条的一个例子
  9. 【转载】【凯子哥带你学Framework】Activity界面显示全解析(下)
  10. Java锁Synchronized,对象锁和类锁举例
  11. java 使用websocket_Java使用WebSocket
  12. 终极算法:机器学习和人工智能如何重塑世界
  13. 非线性系统【三】LaSalle不变原理
  14. 英文邮件开场白(Dear / Hi / TO)
  15. 上年龄的笔记本升级固态硬盘和内存经验谈
  16. mysql左链表右链表区别_MySql链表语句--博客园老牛大讲堂
  17. JAVA高级(一)——lambda
  18. USB Type-C接口(1)——硬件/Lenovo
  19. 2013年中国android智能手机用户调查研究报告,ZDC:2013年7月中国智能手机市场分析报告...
  20. 基于永磁同步电机的容积卡尔曼滤波ckf转速位置估计,估计效果很好

热门文章

  1. 【ES】ES检索的时候特殊字符该怎么处理
  2. IDEA:IDEA采取debug的时候卡死-不报错
  3. 【kafka】记一次线上kafka一直rebalance故障 消费慢 数据积压
  4. 使用Thread类和Runnable方法来创建一个线程的区别
  5. Cookie、Session、Token、JWT分别是什么(四)
  6. 从0开始配置Win环境下VScode (VScode For C/C++)
  7. RabbitMQ实现多系统间的分布式事务,保证数据一致性
  8. 分布式缓存 Redis 集群搭建,这里一次性帮你搞定!
  9. Flask实现发送邮件功能
  10. 安川机器人编程加电弧_安川焊接机器人编程