博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
xloader
阅读量:4344 次
发布时间:2019-06-07

本文共 4919 字,大约阅读时间需要 16 分钟。

 

[1],先看一下整个系统的结构(软件是灵魂,硬件是驱体,再强大的灵魂力若没有躯体终将是游魂野鬼,再强壮的驱体若没有灵魂终将是植物人) 

结构 作用 备注
硬件 一切软件的载体  
xloader                   引导uboot                                   
uboot 启动加载或下载linux kernel  
linux kernel OS,承载android  
android OS,承载APP  

 

 

 

 

 

  

 

[2],为什么需要xloader?

cpu上电后会自动加载一小段程序到内部ram中运行,内部的ram资源很小,一般只有几十k的空间,比如我现在用的cpu就只有32k的空间。uboot功能很强,具有初始化,交互操作,下载和引导linux的作用,因此体积上会超过cpu内部的ram大小,所以我们需要更小的xloader来为我们加载引导uboot。xloader一般只作一些最最核心的硬件初始化,比如cpu时钟,外部内存,flash和usb/SD/uart的初始化工作,然后就加载uboot,把更深入的初始就交给uboot来执行。

 

[3],xloader执行流程

[首先],看x-loader.lds文件,通过以下命令得到lds文件的路径

1 $ find -name "*.lds"

打开x-loader.lds如下:

1 ///// 2 //指定输出可执行文件是elf格式,32位ARM指令,小端 3 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") 4 //指定输出可执行文件的平台为ARM 5 OUTPUT_ARCH(arm) 6 //指定输出可执行文件的起始代码段为_start 7 ENTRY(_start) 8 SECTIONS 9 {10         //从0x0位置开始,但会在vim board/copener_pad_ref/config.mk 文件里面定义为TEXT_BASE = 0x0704100011         . = 0x00000000;12 13         //代码以4字节对齐14         . = ALIGN(4);15         //指定代码段16         .text      :17         {18           cpu/copener/start.o     (.text)        //代码的第一个代码部分19           *(.text)                             //其它代码部分20         }21 22         . = ALIGN(4);23 24         //指定只读数据段25         .rodata : { *(.rodata) }26 27         . = ALIGN(4);28 29         //指定可读写数据段30         .data : { *(.data) }31 32         . = ALIGN(4);33 34         //指定got段, got段式是uboot自定义的一个段, 非标准段35         .got : { *(.got) }36 37         . = ALIGN(4);38 39         //把__bss_start赋值为当前位置,即bss段的开始位置40         __bss_start = .;41 42         //指定bss段43         .bss : { *(.bss) }44 45         //把_end赋值为当前位置,即bss段的结束位置46         _end = .;47 }

  由上面可知程序的入口为“cpu/copener/start.S”文件,且入口函数为“_start”,开头已经有了,接下来就是怎么跟踪代码了。

 

  [然后],跟踪start.S文件:

  start.S是汇编写的文件,主要是执行了下面的操作  

1 // set the cpu to SVC32 mode2 // disable MMU3 // Enable all domains to client mode4 // Invalidate instruction cache5 // Invalidate data cache6 // Invalidate entire Unified main TLB7 8     ldr     pc, _start_armboot      /* jump to C code                   */9 _start_armboot: .word start_armboot

  start.S的最后通过“ldr pc, _start_armboot”跳入C代码中运行了。通过下面的命令把start_armboot函数所在文件lib/board.c找出。  

1 $ grep -rnws start_armboot 

  打开board.c,该函数简化后的操作如下

1 void start_armboot (void) 2 { 3     board_init();                  //pad_ref.c    空函数 4     uart_init(CFG_UART_BAUD_RATE); //uart.c       初始化串口 5     cpu_init();                    //cpu.c        设置一下cpu的频率 6     ddr_init();                    //ddr_init.c   初始化ddr 7     mem_test();                    //board.c      内存测试 8      9     for(idx = 0;idx < 892;)    {10         sram_dat = readl(SRAM_BASE_ADDR + idx);11         writel(sram_dat,DDR_DATA_BASE + idx);    12         idx = idx + 4;13     }14     15     16     if (check_romloader_fastboot()) {    //检测引导设置,若符合usb引导则fastboot USB17         TRACE(KERN_INFO, "enter fastboot USB boot\n");18         usb_boot(0x02);                  //进入USB引导操作19     }20     21 22     switch(readl(CFG_BOOT_MODE) & 0x3){  //检测其它引导模式进入相应操作23         case 0x00:24             TRACE(KERN_INFO,"SDIO\n");25             sdmmc_continue_boot(0x0);     26             27         case 0x02:28             TRACE(KERN_INFO,"USB\n");29             usb_boot(0x02);30             break;31             32         case 0x03:33             TRACE(KERN_UART,"UART\n");   34             uart_boot(0x03);35             break;36         default:37             TRACE(KERN_ERROR,"No Boot Source\n");38             break;39     }    40     TRACE(KERN_ERROR,"No U-boot found\n");41     while(1);42 }

  而后面的usb_boot(0x02)又会调用handle_fastboot(rxdata, rxsize, boot_mode),进而调用enter_entry(head.entry, boot_mode),最后调用(*(void(*)())buf)(boot_mode),然后就跳进uboot里面去运行了。

  (*(void(*)())buf)(boot_mode)是一个函数指针,类型为void(*)(),指向的是buf地址,即head.entry,涉及到的结构体如下:  

1 typedef struct {2     char         tag[4];        //NUFX3     unsigned int offset;        //4     unsigned int entry;         //where to place 5     unsigned int size;          //size of binary 6     unsigned int loader_cksum;  //chsum of binary7     unsigned int header_cksum;  //cksum of first 16 bytes of header8     }xl_header;9 extern xl_header head;

  由config.mk文件指定TEXT_BASE = 0x07041000,然后通过偏移算出Head.entry = 0x7041008。即xloader最后要跳转的地址为0x7041008。

 

[4]xloader的编译  

1 //清除上一次编译 2 $ make distclean 3  4 //配置当前编译 5 $ make copener_pad_ref_config 6  7 //编译 8 $ make 9 10 11 //生成文件时打印的信息//12 Generate x-load.img from x-load13 ELF Entry = 0x704100814 ELF Program number = 215 ELF Program Header Offset = 5216 Program[0]: offset=0x200, Size=0x74f817 Program[1]: offset=0x61656100, Size=0x412d370518 Head.tag = NUFX19 Head.offset = 0x20020 Head.entry = 0x704100821 Head.size = 0x74fc22 Head.loader_cksum = 0x5515708023 Head.header_cksum = 0xb4604cd2

  生成的文件为:  

1 oee@copener:/opt/ns115_jb/bsp/xloader$ ls -lh2 -rwxrwxr-x 1 oee oee  30K  5月 26 12:40 x-load.bin3 -rw-rw-r-- 1 oee oee  30K  5月 26 12:40 x-load.img

 

  

 

转载于:https://www.cnblogs.com/COpener/p/4530092.html

你可能感兴趣的文章
概率面试题
查看>>
linux系统虚拟机安装
查看>>
【贪心】[luoguP1650]赛马
查看>>
Codeforces Round #479 (Div. 3) D. Divide by three, multiply by two
查看>>
javascript继承
查看>>
一篇文章带你了解网络爬虫的概念及其工作原理
查看>>
Xcode如何快速定位crash的位置?
查看>>
太阳下面没有新鲜事:说说HTML5
查看>>
BZOJ2527 [Poi2011]Meteors
查看>>
CommHelper
查看>>
centos6.3安装rtorrent
查看>>
Android自定义Dialog对话框
查看>>
为什么我们做分布式使用Redis?
查看>>
C根据排序字符串
查看>>
IOS 设置子控件的frame(layoutSubviews and awakeFromNib)
查看>>
leetcode 88. Merge Sorted Array
查看>>
三分钟了解Activity工作流
查看>>
Google地图接口API之地图基础(二)
查看>>
PostgreSQL 的 语法分析调用关系
查看>>
mustache.js 数组循环的索引
查看>>