浅析armlinux-setup_arch()->convert_to_tag_list()函数3
文章来源:http://gliethttp.cublog.cn
建议首先参考《浅析armlinux2_4_19启动程式[head-armv.s文档]》[http://gliethttp.cublog.cn]
//1.旧格式param_struct结构体
#define COMMAND_LINE_SIZE 1024
/* This is the old deprecated way to pass parameters to the kernel */
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];
};
//2.arch/arm/kernel/Compat.c->convert_to_tag_list()
//if (tags->hdr.tag != ATAG_CORE)//假如传递参数非tag list格式,那么就是param_struct格式
//convert_to_tag_list(tags);
//使用convert_to_tag_list将param_struct格式参数转化为tag list格式参数
void __init convert_to_tag_list(struct tag *tags)
{//tags地址为物理地址0x20000100[gliethttp]
struct param_struct *params = (struct param_struct *)tags;
build_tag_list(params, ¶ms->u2);//将转换结果临时存储在¶ms->u2,之后拷贝到params
}
//3.arch/arm/kernel/Compat.c->build_tag_list()
static void __init build_tag_list(struct param_struct *params, void *taglist)
{struct tag *tag = taglist;
if (params->u1.s.page_size != PAGE_SIZE) {
printk(KERN_WARNING "Warning: bad configuration page, "
"trying to continue\n");
return;
}
printk(KERN_DEBUG "Converting old-style param struct to taglist\n");
//ATAG_CORE 将params下core相关配置,转换成tag,形成list[gliethttp]
tag->hdr.tag = ATAG_CORE;
tag->hdr.size = tag_size(tag_core);
tag->u.core.flags = params->u1.s.flags & FLAG_READONLY;
tag->u.core.pagesize = params->u1.s.page_size;
tag->u.core.rootdev = params->u1.s.rootdev;
//ATAG_RAMDISK 紧跟着ATAG_CORE继续存储
tag = tag_next(tag);
tag->hdr.tag = ATAG_RAMDISK;
tag->hdr.size = tag_size(tag_ramdisk);
tag->u.ramdisk.flags = (params->u1.s.flags & FLAG_RDLOAD ? 1 : 0) |
(params->u1.s.flags & FLAG_RDPROMPT ? 2 : 0);
tag->u.ramdisk.size = params->u1.s.ramdisk_size;
tag->u.ramdisk.start = params->u1.s.rd_start;
//ATAG_INITRD 紧跟存储
tag = tag_next(tag);
tag->hdr.tag = ATAG_INITRD;
tag->hdr.size = tag_size(tag_initrd);
tag->u.initrd.start = params->u1.s.initrd_start;
tag->u.initrd.size = params->u1.s.initrd_size;
//ATAG_SERIAL
tag = tag_next(tag);
tag->hdr.tag = ATAG_SERIAL;
tag->hdr.size = tag_size(tag_serialnr);
tag->u.serialnr.low = params->u1.s.system_serial_low;
tag->u.serialnr.high = params->u1.s.system_serial_high;
//ATAG_REVISION
tag = tag_next(tag);
tag->hdr.tag = ATAG_REVISION;
tag->hdr.size = tag_size(tag_revision);
tag->u.revision.rev = params->u1.s.system_rev;
#ifdef CONFIG_ARCH_ACORN//false
if (machine_is_riscpc()) {
int i;
//4个memory块
for (i = 0; i 4; i++)
tag = memtag(tag, PHYS_OFFSET + (i 26),
params->u1.s.pages_in_bank * PAGE_SIZE);
} else
#endif
//ok,只有一个32M[0x2000000]内存块,见后
tag = memtag(tag, PHYS_OFFSET, params->u1.s.nr_pages * PAGE_SIZE);
#ifdef CONFIG_FOOTBRIDGE//未用
if (params->u1.s.mem_fclk_21285) {
tag = tag_next(tag);
tag->hdr.tag = ATAG_MEMCLK;
tag->hdr.size = tag_size(tag_memclk);
tag->u.memclk.fmemclk = params->u1.s.mem_fclk_21285;
}
#endif
#ifdef CONFIG_ARCH_EBSA285//未用
if (machine_is_ebsa285()) {
tag = tag_next(tag);
tag->hdr.tag = ATAG_VIDEOTEXT;
tag->hdr.size = tag_size(tag_videotext);
tag->u.videotext.x = params->u1.s.video_x;
tag->u.videotext.y = params->u1.s.video_y;
tag->u.videotext.video_page = 0;
tag->u.videotext.video_mode = 0;
tag->u.videotext.video_cols = params->u1.s.video_num_cols;
tag->u.videotext.video_ega_bx = 0;
tag->u.videotext.video_lines = params->u1.s.video_num_rows;
tag->u.videotext.video_isvga = 1;
tag->u.videotext.video_points = 8;
}
#endif
#ifdef CONFIG_ARCH_ACORN//未用
tag = tag_next(tag);
tag->hdr.tag = ATAG_ACORN;
tag->hdr.size = tag_size(tag_acorn);
tag->u.acorn.memc_control_reg = params->u1.s.memc_control_reg;
tag->u.acorn.vram_pages = params->u1.s.pages_in_vram;
tag->u.acorn.sounddefault = params->u1.s.sounddefault;
tag->u.acorn.adfsdrives = params->u1.s.adfsdrives;
#endif
//ATAG_CMDLINE
tag = tag_next(tag);
tag->hdr.tag = ATAG_CMDLINE;
tag->hdr.size = (strlen(params->commandline) + 3 +
sizeof(struct tag_header)) >> 2;
strcpy(tag->u.cmdline.cmdline, params->commandline);
//ATAG_NONE 明确的结尾标识
tag = tag_next(tag);
tag->hdr.tag = ATAG_NONE;
tag->hdr.size = 0;
//间缓存到taglist中的tag list数据转储到params
memmove(params, taglist, ((int)tag) - ((int)taglist) +
sizeof(struct tag_header)/*ATAG_NONE的长度*/);
}
//4.arch/arm/kernel/Compat.c->memtag()
static struct tag * __init memtag(struct tag *tag, unsigned long start, unsigned long size)
{
//ATAG_MEM 紧跟前一个tag,start=0x20000000
tag = tag_next(tag);
tag->hdr.tag = ATAG_MEM;
tag->hdr.size = tag_size(tag_mem32);
tag->u.mem.size = size;
tag->u.mem.start = start;
return tag;
}
//5.lib/String.c->memmove
void * memmove(void * dest,const void *src,size_t count)
{char *tmp, *s;
if (dest = src) {//假如dest在src的前面,那么顺序++拷贝绝对不会出现覆盖
tmp = (char *) dest;
s = (char *) src;
while (count--)
*tmp++ = *s++;
}
else {//假如dest在src的后面,那么从+count处,倒着拷贝不会出现覆盖[gliethttp]
tmp = (char *) dest + count;
s = (char *) src + count;
while (count--)
*--tmp = *--s;
}
return dest;
}
阅读(539) | 评论(0) | 转发(0) |