•
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
的虚拟地址空间中
做个备忘