bootloader---17.引导内核

原创 2016年08月29日 13:57:30
一、引导zImage
二、代码
 稍微整理一下代码,将头文件都放在include目录下。每一个模块一个头文件,这样结构比较清晰。
root@ubuntu:~/myboot_loader# tree
.
├── boot_zImage.c
├── include
│   ├── nand.h
│   ├── string.h
│   ├── uart.h
│   └── vsprintf.h
├── main.c
├── Makefile
├── nand.c
├── sdram.c
├── start.S
├── uart.c
├── u-boot.lds
└── vsprintf.c

1 directory, 13 files
2.1 main.c

点击(此处)折叠或打开

  1. #include "uart.h"
  2. #include "nand.h"

  3. extern int boot_zImage(unsigned long from, unsigned long size);
  4. void main(void)
  5. {
  6.     uart_init();        //初始化串口
  7.     nand_init();    
  8.     uart_printf("now boot the kernel\n");

  9.     boot_zImage(0x200000, 0x200000);
  10. }
程序跳到内存中的main函数之后,初始化串口和nand flash,然后引导内核。
2.2 boot_zImage.c 取自tq2440的u-boot

点击(此处)折叠或打开

  1. #include "uart.h"
  2. #include "nand.h"
  3. #include "string.h"

  4. #define LINUX_KERNEL_OFFSET         0x8000
  5. #define LINUX_PARAM_OFFSET          0x100
  6. #define LINUX_PAGE_SIZE             0x00001000
  7. #define LINUX_PAGE_SHIFT            12
  8. #define LINUX_ZIMAGE_MAGIC          0x016f2818
  9. #define DRAM_SIZE                   0x04000000
  10. #define CONFIG_BOOTARGS             "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0 mem=128M"
  11. #define COMMAND_LINE_SIZE           256
  12. #define MACH_TYPE_S3C2440           168
  13. struct param_struct {
  14.     union {
  15.     struct {
  16.      unsigned long page_size;        /* 0 */
  17.      unsigned long nr_pages;        /* 4 */
  18.      unsigned long ramdisk_size;        /* 8 */
  19.      unsigned long flags;        /* 12 */
  20. #define FLAG_READONLY    1
  21. #define FLAG_RDLOAD    4
  22. #define FLAG_RDPROMPT    8
  23.      unsigned long rootdev;        /* 16 */
  24.      unsigned long video_num_cols;    /* 20 */
  25.      unsigned long video_num_rows;    /* 24 */
  26.      unsigned long video_x;        /* 28 */
  27.      unsigned long video_y;        /* 32 */
  28.      unsigned long memc_control_reg;    /* 36 */
  29.      unsigned char sounddefault;        /* 40 */
  30.      unsigned char adfsdrives;        /* 41 */
  31.      unsigned char bytes_per_char_h;    /* 42 */
  32.      unsigned char bytes_per_char_v;    /* 43 */
  33.      unsigned long pages_in_bank[4];    /* 44 */
  34.      unsigned long pages_in_vram;    /* 60 */
  35.      unsigned long initrd_start;        /* 64 */
  36.      unsigned long initrd_size;        /* 68 */
  37.      unsigned long rd_start;        /* 72 */
  38.      unsigned long system_rev;        /* 76 */
  39.      unsigned long system_serial_low;    /* 80 */
  40.      unsigned long system_serial_high;    /* 84 */
  41.      unsigned long mem_fclk_21285; /* 88 */
  42.     } s;
  43.     char unused[256];
  44.     } u1;
  45.     union {
  46.     char paths[8][128];
  47.     struct {
  48.      unsigned long magic;
  49.      char n[1024 - sizeof(unsigned long)];
  50.     } s;
  51.     } u2;
  52.     char commandline[COMMAND_LINE_SIZE];
  53. };

  54. /*
  55.  * Disable IRQs
  56.  */
  57. #define local_irq_disable()                    \
  58.     ({                            \
  59.         unsigned long temp;                \
  60.     __asm__ __volatile__(                    \
  61.     "mrs    %0, cpsr        @ local_irq_disable\n"    \
  62. "    orr    %0, %0, #128\n"                    \
  63. "    msr    cpsr_c, %0"                    \
  64.     : "=r" (temp)                        \
  65.     :                            \
  66.     : "memory", "cc");                    \
  67.     })

  68. static inline void cpu_arm920_cache_clean_invalidate_all(void)
  69. {
  70. __asm__(
  71.     "    mov    r1, #0\n"
  72.     "    mov    r1, #7 << 5\n"         /* 8 segments */
  73.     "1:    orr    r3, r1, #63 << 26\n"     /* 64 entries */
  74.     "2:    mcr    p15, 0, r3, c7, c14, 2\n" /* clean & invalidate D index */
  75.     "    subs    r3, r3, #1 << 26\n"
  76.     "    bcs    2b\n"             /* entries 64 to 0 */
  77.     "    subs    r1, r1, #1 << 5\n"
  78.     "    bcs    1b\n"             /* segments 7 to 0 */
  79.     "    mcr    p15, 0, r1, c7, c5, 0\n" /* invalidate I cache */
  80.     "    mcr    p15, 0, r1, c7, c10, 4\n" /* drain WB */
  81.     );
  82. }

  83. void cache_clean_invalidate(void)
  84. {
  85.     cpu_arm920_cache_clean_invalidate_all();
  86. }

  87. static inline void cpu_arm920_tlb_invalidate_all(void)
  88. {
  89.     __asm__(
  90.         "mov    r0, #0\n"
  91.         "mcr    p15, 0, r0, c7, c10, 4\n"    /* drain WB */
  92.         "mcr    p15, 0, r0, c8, c7, 0\n"    /* invalidate I & D TLBs */
  93.         );
  94. }

  95. void tlb_invalidate(void)
  96. {
  97.     cpu_arm920_tlb_invalidate_all();
  98. }


  99. void call_linux(long a0, long a1, long a2)
  100. {
  101.      local_irq_disable();
  102.     cache_clean_invalidate();
  103.     tlb_invalidate();

  104. __asm__(
  105.     "mov    r0, %0\n"
  106.     "mov    r1, %1\n"
  107.     "mov    r2, %2\n"
  108.     "mov    ip, #0\n"
  109.     "mcr    p15, 0, ip, c13, c0, 0\n"    /* zero PID */
  110.     "mcr    p15, 0, ip, c7, c7, 0\n"    /* invalidate I,D caches */
  111.     "mcr    p15, 0, ip, c7, c10, 4\n"    /* drain write buffer */
  112.     "mcr    p15, 0, ip, c8, c7, 0\n"    /* invalidate I,D TLBs */
  113.     "mrc    p15, 0, ip, c1, c0, 0\n"    /* get control register */
  114.     "bic    ip, ip, #0x0001\n"        /* disable MMU */
  115.     "mcr    p15, 0, ip, c1, c0, 0\n"    /* write control register */
  116.     "mov    pc, r2\n"
  117.     "nop\n"
  118.     "nop\n"
  119.     : /* no outpus */
  120.     : "r" (a0), "r" (a1), "r" (a2)
  121.     : "r0","r1","r2","ip"
  122.     );
  123. }

  124. /*
  125.  * pram_base: base address of linux paramter
  126.  */
  127. static void setup_linux_param(unsigned long param_base)
  128. {
  129.     struct param_struct *params = (struct param_struct *)param_base; 
  130.     char *linux_cmd = CONFIG_BOOTARGS    ;

  131.     memset((unsigned char*)params, 0, sizeof(struct param_struct));

  132.     params->u1.s.page_size = LINUX_PAGE_SIZE;
  133.     params->u1.s.nr_pages = (DRAM_SIZE >> LINUX_PAGE_SHIFT);

  134.     /* set linux command line */
  135.     memcpy(params->commandline, linux_cmd, strlen(linux_cmd) + 1);
  136. }

  137. int boot_zImage(unsigned long from, unsigned long size)
  138. {
  139.     int ret;
  140.     unsigned long boot_mem_base;    /* base address of bootable memory */
  141.     unsigned long to;
  142.     unsigned long mach_type;

  143.     boot_mem_base = 0x30000000;

  144.     /* copy kerne image */
  145.     to = boot_mem_base + LINUX_KERNEL_OFFSET;
  146.     uart_printf("Copy kernel from 0x%08lx to 0x%08lx, size = 0x%08lx ...\n ", from, to, size);

  147.     nand_read_page((unsigned char *)to, (unsigned long)from, (int)size);

  148.     uart_printf("read over! next check \n");

  149.     //uart_printf("read ok!\n");

  150.     if (*(unsigned long *)(to + 9*4) != LINUX_ZIMAGE_MAGIC) {
  151.         uart_printf("Warning: this binary is not compressed linux kernel image\n");
  152.         uart_printf("zImage magic = 0x%08lx\n", *(unsigned long *)(to + 9*4));
  153.         return -1;
  154.     }

  155.     /* Setup linux parameters and linux command line */
  156.     setup_linux_param(boot_mem_base + LINUX_PARAM_OFFSET);

  157.     /* Get machine type */
  158.     mach_type = MACH_TYPE_S3C2440;
  159.     //    printk("MACH_TYPE = %d\n", mach_type);

  160.     /* Go Go Go */
  161.     uart_printf("NOW, Booting Linux......\n");    
  162.     call_linux(0, mach_type, to);

  163.     return 0;    
  164. }
boot_zImage函数,
   a. 首先将内核从nand flash的0x00200000复制到0x30008000,复制大小为0x00200000
   b. 检查文件头是否正确
   c. 在u-boot与内核约定的参数起始地址0x30000100处,设置linux的启动参数
   d. 最后启动内核 
不过这个程序还存在问题:启动时会卡在nand_read_page处大约20秒左右,下一步看问题出在什么地方?
三、
   3.1 这样一个最最最最基本的bootloader就完成了,
  root@ubuntu:~/myboot_loader# ll  u-boot.bin 
  -rwxr-xr-x 1 root root 6796 2012-05-31 00:44 u-boot.bin*
   大小是6796,大约是6.7K.
   3.2 这个bootloader可以进一步精简,把vsprintf去掉之后
root@ubuntu:~/myboot_loader_noprint# ll u-boot.bin 
-rwxr-xr-x 1 root root 2868 2012-05-31 00:48 u-boot.bin*
   大小只有2868个字节。当然如果是小于4K,程序就可以直接在sram中进行,那么先把bootloader复制到内存这一步也可以省略,相信代码可以更小。

 myboot_loader.rar  (将后缀名改为tar.gz, 卡在nand_read_page中大约20秒)
  myboot_loader_noprint.rar   (将后缀名改为tar.gz,卡在nand_read_page中大约20秒,并且有时会直接卡死)
版权声明:本文为博主原创文章,转载请注明出处。

U-boot引导内核流程分析

当U-boot完成重定位和初始化外设后,它将正式进入工作状态,可以加载内核镜像到DDR的链接地址中了...
  • qq_28992301
  • qq_28992301
  • 2016年07月10日 20:32
  • 2202

U-boot如何引导Linux内核启动

U-BOOT全线移植分析系列之四――U-boot如何引导Linux 内核启动?Sailor_forever  sailing_9806@163.com转载请注明http://blog.csdn.ne...
  • feng5219
  • feng5219
  • 2010年12月28日 21:22
  • 3158

Linux内核学习篇一:引导启动

对于Linux内核启动问题总是一知半解,今天正好趁着学习课本的机会,写一下自己的体会,尽量通俗易懂,方便日后翻看。好了进入正题~~~~~ 首先需要明确一下几点: 1.引导程序也...
  • Carl_Qi
  • Carl_Qi
  • 2016年03月20日 22:56
  • 576

Exynos4412 Uboot 移植(四)—— Uboot引导内核过程分析

bootloader 要想启动内核,可以直接跳到内核的第一个指令处,即内核的起始地址,这样便可以完成内核的启动工作了。但是要想启动内核还需要满足一些条件,如下所示: 1、cpu 寄存器设置     *...
  • zqixiao_09
  • zqixiao_09
  • 2016年03月07日 12:32
  • 3176

为S3C2440移植内核

1.修改晶振频率        S3C2440支持两种频率:12MHZ 和16MHZ.目前市面上出售的开发板大多使用的是12MHZ的晶振,而内核源代码采用的是16MHZ频率,从而产生了错误的PCLK...
  • yx_l128125
  • yx_l128125
  • 2012年04月24日 22:23
  • 1476

学习笔记:u-boot引导内核启动

u-boot主要目的: 1. 从flash上读出内核写到SDRAM中 2. 启动内核(用do_bootm函数) 即 nand read.jffs2 0x30007FC0 kernel ...
  • sinat_24088685
  • sinat_24088685
  • 2016年04月11日 22:32
  • 742

操作系统内核的引导

最近在学习操作系统原理,也想尝试下如何编写一个操作系统,就查阅了相关资料,进行一番总结。...
  • sun_xiaofan
  • sun_xiaofan
  • 2015年04月12日 22:46
  • 1478

Grub 引导内核---神寄的命令

原来的primary master硬盘上装了win2000, gentoo,可以用grub双启动. 现在新加一块硬盘做primary master,原来的设成slave. 在新硬盘上装gentoo后,...
  • nhczp
  • nhczp
  • 2007年08月27日 18:16
  • 883

uboot引导非压缩的内核镜像vmlinux.bin

一般都是使用uboot引导uImage,uImage是在压缩的内核(如zImage)加了一些信息生成的。这些信息主要内容包括此内核是那种类型,linux还是其他的;内核的入口地址等信息。长度是0x40...
  • xyfabcde
  • xyfabcde
  • 2016年12月29日 14:19
  • 926

转:uboot无法启动linux内核

转自:http://topic.csdn.net/u/20100415/14/1569e49e-921f-4b67-92be-409bd4885679.html 1、u-boot中的命令行参数中co...
  • xautfengzi
  • xautfengzi
  • 2011年04月18日 09:30
  • 2202
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:bootloader---17.引导内核
举报原因:
原因补充:

(最多只允许输入30个字)