bootloader 传递参数给内核 atag的用法
•bootloader 通过tags传递配置参数到linux kernel
•tags的定义:
• Tag以tagcore开始,以 null结束
• 如 unsigned * ptr=tags (tags是存放tag的物理地址)
• Ptr++=2;
• Ptr++=ATAG_CORE;
• 以上是开始
• ……………………………其他tag
• Tag是这样的一个结构体。第一个偏移是tag的大小,第二个是tag的号。接下来就是tag大小-2的tag数据。注意tag中的每一项都是4字节对齐的。
•
• Ptr++=0;
• Ptr++=0;
•以上是结束
下面是一个例子
1 void boot_linux(void *kernel, unsigned *tags,
2 const char *cmdline, unsigned machtype,
3 void *ramdisk, unsigned ramdisk_size)
4 {
5 unsigned *ptr = tags;
6 /* CORE */
7 *ptr++ = 2;
8 *ptr++ = 0x54410001; 构建tag 头 0x54410001这个数就是ATAG_CORE
9 if (ramdisk_size) {
10 *ptr++ = 4;
11 *ptr++ = 0x54420005;
12 *ptr++ = (unsigned)ramdisk;
13 *ptr++ = ramdisk_size; 构建内容 ramdisl
14 }
15 ptr = target_atag_mem(ptr); 构建内容 mem
16 }
17 }
18 /* END */
19 *ptr++ = 0;
20 *ptr++ = 0; 构建结束标志
21 dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d)\n",
22 kernel, ramdisk, ramdisk_size);
23
24 }
2 const char *cmdline, unsigned machtype,
3 void *ramdisk, unsigned ramdisk_size)
4 {
5 unsigned *ptr = tags;
6 /* CORE */
7 *ptr++ = 2;
8 *ptr++ = 0x54410001; 构建tag 头 0x54410001这个数就是ATAG_CORE
9 if (ramdisk_size) {
10 *ptr++ = 4;
11 *ptr++ = 0x54420005;
12 *ptr++ = (unsigned)ramdisk;
13 *ptr++ = ramdisk_size; 构建内容 ramdisl
14 }
15 ptr = target_atag_mem(ptr); 构建内容 mem
16 }
17 }
18 /* END */
19 *ptr++ = 0;
20 *ptr++ = 0; 构建结束标志
21 dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d)\n",
22 kernel, ramdisk, ramdisk_size);
23
24 }
上面显示了构建一个tag的方法
•构建tags 头: tag头是以ATAG_CORE 为tags标志的一段内存
构建tags的内容: 下面的代码显示构建过程
•构建tags尾: 以null结束
#define SIZE_44M 0x02C00000 // 44M
#define EBI1_ADDR_1026M 0x40200000
#define SIZE_128M 0x08000000 // 128M
#define EBI1_ADDR_1152M 0x48000000
#define SIZE_256M 0x10000000 // 256M
#define EBI1_ADDR_1280M 0x50000000
#define SIZE_768M 0x30000000 // 256M + 512M
#define EBI1_CS1_ADDR_BASE 0x00A40024
unsigned* target_atag_mem(unsigned* ptr)
{
unsigned value = 0;
/* ATAG_MEM */
*ptr++ = 4;
*ptr++ = 0x54410002;
*ptr++ = SIZE_44M;
*ptr++ = EBI1_ADDR_1026M;
*ptr++ = 4;
*ptr++ = 0x54410002;
*ptr++ = SIZE_128M;
*ptr++ = EBI1_ADDR_1152M;
value = readl(EBI1_CS1_ADDR_BASE);
value = (value >> 8) & 0xFF;
if (value == 0x50)
{
/* For 512MB RAM*/
*ptr++ = 4;
*ptr++ = 0x54410002;
*ptr++ = SIZE_256M;
*ptr++ = EBI1_ADDR_1280M;
}
else if (value == 0x60)
{
/* For 1GB RAM*/
*ptr++ = 4;
*ptr++ = 0x54410002;
*ptr++ = SIZE_768M;
*ptr++ = EBI1_ADDR_1280M;
}
return ptr;
}
#define EBI1_ADDR_1026M 0x40200000
#define SIZE_128M 0x08000000 // 128M
#define EBI1_ADDR_1152M 0x48000000
#define SIZE_256M 0x10000000 // 256M
#define EBI1_ADDR_1280M 0x50000000
#define SIZE_768M 0x30000000 // 256M + 512M
#define EBI1_CS1_ADDR_BASE 0x00A40024
unsigned* target_atag_mem(unsigned* ptr)
{
unsigned value = 0;
/* ATAG_MEM */
*ptr++ = 4;
*ptr++ = 0x54410002;
*ptr++ = SIZE_44M;
*ptr++ = EBI1_ADDR_1026M;
*ptr++ = 4;
*ptr++ = 0x54410002;
*ptr++ = SIZE_128M;
*ptr++ = EBI1_ADDR_1152M;
value = readl(EBI1_CS1_ADDR_BASE);
value = (value >> 8) & 0xFF;
if (value == 0x50)
{
/* For 512MB RAM*/
*ptr++ = 4;
*ptr++ = 0x54410002;
*ptr++ = SIZE_256M;
*ptr++ = EBI1_ADDR_1280M;
}
else if (value == 0x60)
{
/* For 1GB RAM*/
*ptr++ = 4;
*ptr++ = 0x54410002;
*ptr++ = SIZE_768M;
*ptr++ = EBI1_ADDR_1280M;
}
return ptr;
}
atag的解析
•1 定义一个tag号 如 ATAG_MSM_PARTITION 0X4D534D70
• 2 编写tag处理函数 如
• Static int __init parse_tag_msm_partition(const struct tag * tag)
• 3 注册tag
•如 __tagtable(ATAG_MSM_PARTITION, parse_tag_msm_partition)
• 到此 parse_tag_msm_partition 函数在系统启动时会调用
memtag的解析
•Setup.c
•static int __init parse_tag_mem32(const struct tag *tag)
•{
• return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
•}
•__tagtable(ATAG_MEM, parse_tag_mem32);
•arm_add_memory 会把tag中的mem块添加到meminfo 结构中,在系统安装mem时会把他们连续的映射到linux的虚拟地址空间中
做个备忘