一、引导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
-
#include "uart.h"
-
#include "nand.h"
-
-
extern int boot_zImage(unsigned long from, unsigned long size);
-
void main(void)
-
{
-
uart_init(); //初始化串口
-
nand_init();
-
uart_printf("now boot the kernel\n");
-
-
boot_zImage(0x200000, 0x200000);
-
}
程序跳到内存中的main函数之后,初始化串口和nand flash,然后引导内核。
2.2 boot_zImage.c 取自tq2440的u-boot
-
#include "uart.h"
-
#include "nand.h"
-
#include "string.h"
-
-
#define LINUX_KERNEL_OFFSET 0x8000
-
#define LINUX_PARAM_OFFSET 0x100
-
#define LINUX_PAGE_SIZE 0x00001000
-
#define LINUX_PAGE_SHIFT 12
-
#define LINUX_ZIMAGE_MAGIC 0x016f2818
-
#define DRAM_SIZE 0x04000000
-
#define CONFIG_BOOTARGS "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0 mem=128M"
-
#define COMMAND_LINE_SIZE 256
-
#define MACH_TYPE_S3C2440 168
-
struct param_struct {
-
union {
-
struct {
-
unsigned long page_size; /* 0 */
-
unsigned long nr_pages; /* 4 */
-
unsigned long ramdisk_size; /* 8 */
-
unsigned long flags; /* 12 */
-
#define FLAG_READONLY 1
-
#define FLAG_RDLOAD 4
-
#define FLAG_RDPROMPT 8
-
unsigned long rootdev; /* 16 */
-
unsigned long video_num_cols; /* 20 */
-
unsigned long video_num_rows; /* 24 */
-
unsigned long video_x; /* 28 */
-
unsigned long video_y; /* 32 */
-
unsigned long memc_control_reg; /* 36 */
-
unsigned char sounddefault; /* 40 */
-
unsigned char adfsdrives; /* 41 */
-
unsigned char bytes_per_char_h; /* 42 */
-
unsigned char bytes_per_char_v; /* 43 */
-
unsigned long pages_in_bank[4]; /* 44 */
-
unsigned long pages_in_vram; /* 60 */
-
unsigned long initrd_start; /* 64 */
-
unsigned long initrd_size; /* 68 */
-
unsigned long rd_start; /* 72 */
-
unsigned long system_rev; /* 76 */
-
unsigned long system_serial_low; /* 80 */
-
unsigned long system_serial_high; /* 84 */
-
unsigned long mem_fclk_21285; /* 88 */
-
} s;
-
char unused[256];
-
} u1;
-
union {
-
char paths[8][128];
-
struct {
-
unsigned long magic;
-
char n[1024 - sizeof(unsigned long)];
-
} s;
-
} u2;
-
char commandline[COMMAND_LINE_SIZE];
-
};
-
-
/*
-
* Disable IRQs
-
*/
-
#define local_irq_disable() \
-
({ \
-
unsigned long temp; \
-
__asm__ __volatile__( \
-
"mrs %0, cpsr @ local_irq_disable\n" \
-
" orr %0, %0, #128\n" \
-
" msr cpsr_c, %0" \
-
: "=r" (temp) \
-
: \
-
: "memory", "cc"); \
-
})
-
-
static inline void cpu_arm920_cache_clean_invalidate_all(void)
-
{
-
__asm__(
-
" mov r1, #0\n"
-
" mov r1, #7 << 5\n" /* 8 segments */
-
"1: orr r3, r1, #63 << 26\n" /* 64 entries */
-
"2: mcr p15, 0, r3, c7, c14, 2\n" /* clean & invalidate D index */
-
" subs r3, r3, #1 << 26\n"
-
" bcs 2b\n" /* entries 64 to 0 */
-
" subs r1, r1, #1 << 5\n"
-
" bcs 1b\n" /* segments 7 to 0 */
-
" mcr p15, 0, r1, c7, c5, 0\n" /* invalidate I cache */
-
" mcr p15, 0, r1, c7, c10, 4\n" /* drain WB */
-
);
-
}
-
-
void cache_clean_invalidate(void)
-
{
-
cpu_arm920_cache_clean_invalidate_all();
-
}
-
-
static inline void cpu_arm920_tlb_invalidate_all(void)
-
{
-
__asm__(
-
"mov r0, #0\n"
-
"mcr p15, 0, r0, c7, c10, 4\n" /* drain WB */
-
"mcr p15, 0, r0, c8, c7, 0\n" /* invalidate I & D TLBs */
-
);
-
}
-
-
void tlb_invalidate(void)
-
{
-
cpu_arm920_tlb_invalidate_all();
-
}
-
-
-
void call_linux(long a0, long a1, long a2)
-
{
-
local_irq_disable();
-
cache_clean_invalidate();
-
tlb_invalidate();
-
-
__asm__(
-
"mov r0, %0\n"
-
"mov r1, %1\n"
-
"mov r2, %2\n"
-
"mov ip, #0\n"
-
"mcr p15, 0, ip, c13, c0, 0\n" /* zero PID */
-
"mcr p15, 0, ip, c7, c7, 0\n" /* invalidate I,D caches */
-
"mcr p15, 0, ip, c7, c10, 4\n" /* drain write buffer */
-
"mcr p15, 0, ip, c8, c7, 0\n" /* invalidate I,D TLBs */
-
"mrc p15, 0, ip, c1, c0, 0\n" /* get control register */
-
"bic ip, ip, #0x0001\n" /* disable MMU */
-
"mcr p15, 0, ip, c1, c0, 0\n" /* write control register */
-
"mov pc, r2\n"
-
"nop\n"
-
"nop\n"
-
: /* no outpus */
-
: "r" (a0), "r" (a1), "r" (a2)
-
: "r0","r1","r2","ip"
-
);
-
}
-
-
/*
-
* pram_base: base address of linux paramter
-
*/
-
static void setup_linux_param(unsigned long param_base)
-
{
-
struct param_struct *params = (struct param_struct *)param_base;
-
char *linux_cmd = CONFIG_BOOTARGS ;
-
-
memset((unsigned char*)params, 0, sizeof(struct param_struct));
-
-
params->u1.s.page_size = LINUX_PAGE_SIZE;
-
params->u1.s.nr_pages = (DRAM_SIZE >> LINUX_PAGE_SHIFT);
-
-
/* set linux command line */
-
memcpy(params->commandline, linux_cmd, strlen(linux_cmd) + 1);
-
}
-
-
int boot_zImage(unsigned long from, unsigned long size)
-
{
-
int ret;
-
unsigned long boot_mem_base; /* base address of bootable memory */
-
unsigned long to;
-
unsigned long mach_type;
-
-
boot_mem_base = 0x30000000;
-
-
/* copy kerne image */
-
to = boot_mem_base + LINUX_KERNEL_OFFSET;
-
uart_printf("Copy kernel from 0x%08lx to 0x%08lx, size = 0x%08lx ...\n ", from, to, size);
-
-
nand_read_page((unsigned char *)to, (unsigned long)from, (int)size);
-
-
uart_printf("read over! next check \n");
-
-
//uart_printf("read ok!\n");
-
-
if (*(unsigned long *)(to + 9*4) != LINUX_ZIMAGE_MAGIC) {
-
uart_printf("Warning: this binary is not compressed linux kernel image\n");
-
uart_printf("zImage magic = 0x%08lx\n", *(unsigned long *)(to + 9*4));
-
return -1;
-
}
-
-
/* Setup linux parameters and linux command line */
-
setup_linux_param(boot_mem_base + LINUX_PARAM_OFFSET);
-
-
/* Get machine type */
-
mach_type = MACH_TYPE_S3C2440;
-
// printk("MACH_TYPE = %d\n", mach_type);
-
-
/* Go Go Go */
-
uart_printf("NOW, Booting Linux......\n");
-
call_linux(0, mach_type, to);
-
-
return 0;
-
}
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复制到内存这一步也可以省略,相信代码可以更小。
阅读(2109) | 评论(0) | 转发(1) |