vivi是韩国MiZi公司专门为三星ARM芯片开发的bootloader,本文试图分析其C语言部分,在S3C2410上基于NandFlash启动的开发板,即设置其操作模式为00(NandFlash Mode)。
vivi从/arch/s3c2410/head.s开始运行,上电后,通过S3C2410的硬件机制,将NandFlash上前4K代码复制到S3C2410自带的片内RAM(地址范围:0X0000 0000--0X0000 1000,即占据Bank0的地址空间),这里运行的代码主要是将NandFlash中vivi的代码拷贝到RAM中,然后实现跳转:
@ jump to ram
ldr r1, =on_the_ram
add pc, r1, #0
nop
nop
1: b 1b @ infinite loop
on_the_ram:
由于vivi.lds中
SECTIONS {
. = 0x33f00000;
.text : { *(.text) }
.data ALIGN(4) : { *(.data) }
.bss ALIGN(4) : { *(.bss) *(COMMON) }
}
故,on_the_ram应该是相对于0x33f0 0000,直接跳转到RAM空间。准备好堆栈空间后,就跳转到main函数:
@ get read to call C functions
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
mov a2, #0 @ set argv to NULL
bl main @ call main
main函数首先调用board_init()函数设置Timer和各引脚控制寄存器;
调用mem_map_init()给宏mmu_table_base指向的一段RAM区域赋值,此段RAM存放的即为MMU_TABLE;
调用mmu_init()设置芯片MMU寄存器,使能mmu功能;
调用heap_init()函数,给静态变量gHeapBase赋值为宏HEAP_BASE,分配RAM中堆空间并初始化,大小为宏HEAP_SIZE;
调用mtd_dev_init()函数,初始化MTD设备,具体在这块板子上表现为:调用smc_init()为mtd_info类型变量mymtd、nand_chip类型变量this分配内存,设置NandFlash controller、I/O等寄存器,设置this中包含的读些函数等,并为flash其分配读些缓冲区。
调用init_priv_data(),将:
vivi_parameter_t default_vivi_parameters[] = {
{ "mach_type", MACH_TYPE, NULL },
{ "media_type", MT_S3C2410, NULL },
{ "boot_mem_base", 0x30000000, NULL },
{ "baudrate", UART_BAUD_RATE, NULL },
{ "xmodem_one_nak", 0, NULL },
{ "xmodem_initial_timeout", 300000, NULL },
{ "xmodem_timeout", 1000000, NULL },
{ "ymodem_initial_timeout", 1500000, NULL },
{ "boot_delay", 0x1000, NULL }
}
char linux_cmd[] = "noinitrd root=31:2 init=/linuxrc console=ttySAC0";
mtd_partition_t default_mtd_partitions[] = {
{
name: "vivi",
offset: 0,
size: 0x00020000,
flag: 0
}, {
name: "param",
offset: 0x00020000,
size: 0x00010000,
flag: 0
}, {
name: "kernel",
offset: 0x00030000,
size: 0x000C0000,
flag: 0
}, {
name: "root",
offset: 0x00100000,
size: 0x00140000,
flag: MF_BONFS
}
};
以及个人定义的一些变量从Flash中拷贝到RAM;
调用misc()及init_builtin_cmds()函数给static user_command_t *head_cmd:
typedef struct user_command {
const char *name;
void (*cmdfunc)(int argc, const char **);
struct user_command *next_cmd;
const char *helpstr;
} user_command_t;
赋值,形成命令链表,以供查询;
最后调用boot_or_vivi();
综上,全局数据涉及:堆栈起始地址及大小、MMU_TABLE占用的RAM区、描述flash的smc_mtd、default_mtd_parameters等等。在shell环境下,vivi的功能就是通过操作这些全局数据实现的。
阅读(1175) | 评论(0) | 转发(0) |