在Linux移植之內核啟動過程start_kernel函數簡析中已經指出了start_kernel函數的調用層次,這篇主要是對具體的tag參數列表進行解析。
1、內存參數ATAG_MEM參數解析
2、命令行參數ATAG_CMDLINE解析,以傳入的命令參數bootargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0為列:
1)、noinitrd參數解析過程,當你沒有使用ramdisk啟動系統的時候,你需要使用noinitrd這個參數,但是如果使用了的話,就需要指定initrd=r_addr,size, r_addr表示initrd在內存中的位置,size表示initrd的大小。
2)、root=/dev/mtdblock3參數解析過程
3)、init=/linuxrc參數解析過程
4)、 console=ttySAC0參數解析過程
start_kernel
setup_arch //解析UBOOT傳入的啟動參數
setup_command_line //解析UBOOT傳入的啟動參數
do_early_param //解析early參數,uboot中沒傳這個參數
unknown_bootoption//解析到了命令行參數,saved_root_name在這塊初始化
console_init();//控制臺初始化
rest_init
kernel_thread
kernel_init
prepare_namespace //解析命令行參數解析成功掛接在哪個分區
mount_root//掛接根文件系統
init_post
//執行應用程序
1、內存參數ATAG_MEM參數解析
看到archarmkernelSetup.c文件,在setup_arch函數里看到如下幾行,首先根據內核啟動時第一階段得到的machine_arch_type,取得mdesc結構體,這個結構體在Linux移植之內核啟動過程引導階段分析已經介紹過,這里主要關心的是boot_params參數,里面存放的是tag參數列表的存放地址,然后將取得的物理地址轉換為虛擬地址供后面使用tag。
776 console_init();//控制臺初始化
777 archarmkernelSetup.c
778
779 setup_processor();//設置處理器相關的一些設置
780 mdesc = setup_machine(machine_arch_type);//獲得開發板的machine_desc結構
781 machine_name = mdesc->name;//取得開發板的名稱
782
783 if (mdesc->soft_reboot)
784 reboot_setup('s');
785
786 if (mdesc->boot_params)//確定uboot傳入的啟動參數的地址
787 tags = phys_to_virt(mdesc->boot_params);//將啟動參數的物理地址轉換為虛擬地址
setup_arch函數繼續往下看
109 static struct meminfo meminfo __initdata = { 0, };
798 if (tags->hdr.tag == ATAG_CORE) {//ATAG_CORE為tag標記列表的開始
799 if (meminfo.nr_banks != 0)//如果已經在內核中定義了meminfo結構
780 squash_mem_tags(tags);//則忽略內存tag
781 parse_tags(tags);//解釋每個tag
782 }
其中meminfo就是處理完ATAG_MEN參數后,將里面的內容放去meninfo中,它的結構定義在includeasm-armSetup.h 中
207 struct meminfo {
208 int nr_banks;
209 struct membank bank[NR_BANKS];
210 };
接著繼續看parse_tags函數,它也位于archarmkernelSetup.c中
733 static void __init parse_tags(const struct tag *t)
734 {
735 for (; t->hdr.size; t = tag_next(t))//循環取出tag列表,然后處理
736 if (!parse_tag(t)) //處理取出的tag列表
737 printk(KERN_WARNING
738 'Ignoring unrecognised tag 0x%08xn',
739 t->hdr.tag);
740 }
接著分析parse_tag函數,它同樣位于archarmkernelSetup.c中
715 static int __init parse_tag(const struct tag *tag)
716 {
717 extern struct tagtable __tagtable_begin, __tagtable_end;
718 struct tagtable *t;
719
720 for (t = &__tagtable_begin; t < &__tagtable_end; t++)//從.taglist.init段找出符合的處理tag列表的結構
721 if (tag->hdr.tag == t->tag) {//找到符合的tag
722 t->parse(tag);//調用相應的處理tag的函數處理
723 break;
724 }
725
726 return t < &__tagtable_end;//t<&__tagtable_end說明找到了tag
727 }
parse_tag會從.taglist.init段找出符合的tag,然后調用相應的處理函數處理。tagtable 的結構如下,它位于includeasm-armSetup.h 中
171 struct tagtable {
172 __u32 tag;//處理的tag值
173 int (*parse)(const struct tag *);//處理函數
174 };
我們需要的是處理ATAG_MEN參數的函數,搜搜ATAG_MEN,在archarmkernelSetup.c中找到了parse_tag_mem32處理ATAG_MEN參數的函數。它的功能就是取出內存的開始地址與大小信息后存放在meminfo結構中
614 static int __init parse_tag_mem32(const struct tag *tag)
615 {
616 if (meminfo.nr_banks >= NR_BANKS) {
617 printk(KERN_WARNING
618 'Ignoring memory bank 0x%08x size %dKBn',
619 tag->u.mem.start, tag->u.mem.size / 1024);
620 return -EINVAL;
621 }
622 arm_add_memory(tag->u.mem.start, tag->u.mem.size);//取出內存的開始地址與大小信息后存放在meminfo結構中
623 return 0;
624 }
625
626 __tagtable(ATAG_MEM, parse_tag_mem32);//解析ATAG_MEM列表,函數為parse_tag_mem32
再看到__tagtable,同樣位于includeasm-armSetup.h中。主要就是將tagtable 這個結構體放在.taglist.init段
188 #define __tag __used __attribute__((__section__('.taglist.init')))
189 #define __tagtable(tag, fn)
190 static struct tagtable __tagtable_##fn __tag = { tag, fn }
到這里就分析完了tag列表中ATAG_MEM參數的處理,接下去分析ATAG_CMDLINE參數的處理。
2、命令行參數ATAG_CMDLINE解析
找到與ATAG_CMDLINE參數的過程與前面ATAG_MEM參數一樣的流程就不分析了,直接找到處理ATAG_CMDLINE參數的函數,它位于archarmkernelSetup.c中。它只是簡單的將tag->u.cmdline.cmdline的內容復制到default_command_line中。
702 static int __init parse_tag_cmdline(const struct tag *tag)
703 {
704 strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);//簡單的將tag的內容復制到字符串default_command_line中
705 return 0;
706 }
707
708 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
接著看到default_command_line,它定義在archarmkernelSetup.c中,它的大小為1024字節
114 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
它初始化為CONFIG_CMDLINE,位于includelinuxAutoconf.h中
374 #define CONFIG_CMDLINE 'root=/dev/hda1 ro init=/bin/bash console=ttySAC0'
所以拷貝之后
default_command_line[] = 'noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0'
繼續往下看default_command_line,在archarmkernelSetup.c下的setup_arch函數中:其中parse_cmdline是對位于.early_param.init段的內容進行前期的初始化。相應的命令有:cachepolicy=、nocache、nowb、ecc=、initrd=、mem=等等,我們的參數沒有涉及到這類命令,所以不去細細的分析這個函數了。
809 memcpy(boot_command_line, from, COMMAND_LINE_SIZE);//form指向default_command_line,將default_command_line中的內容拷貝到boot_command_line中
810 boot_command_line[COMMAND_LINE_SIZE-1] = ' 主站蜘蛛池模板: 德格县| 喀喇| 板桥市| 岳池县| 香河县| 和田市| 崇明县| 海南省| 望江县| 许昌县| 潼南县| 蒲城县| 河间市| 莱阳市| 周口市| 潮安县| 雅安市| 武汉市| 利川市| 翁源县| 成都市| 关岭| 行唐县| 家居| 山西省| 恭城| 和硕县| 那曲县| 遵义市| 大足县| 颍上县| 绥芬河市| 伽师县| 鹤山市| 建平县| 云林县| 屏山县| 景德镇市| 通河县| 隆德县| 通海县|