Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2122690
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2012-05-31 00:24:29

一、引导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秒,并且有时会直接卡死)

阅读(2081) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~