http://hi.baidu.com/daoguchengshu/item/f77c383fda19d46b7d034be0
刚开始,看网上内核移植,驱动添加等等,都是在xx文件添加xx结构体,不知其所以然。
没办法,看样子还是得自己一句一句分析,才能理解深刻。
内核版本是2.6.37.4,找了XC2240的zImage分析,看内核的启动流程,分析移植工作要做的和
各文件之间的调用关系。
内核从int/main.c的start_kernel函数开始启动:
这行之前还有几句,先不管,那是bootloader和解压内核的。
上面一句调试信息是在 start_kernel中的printk(KERN_NOTICE "%s", linux_banner)调用时打印出来,打印的linux_banner即是上面的字符串,到底如何从linux_banner参数得到上述字符串,我也没搞明白,这应该是每个linux都会打印的,会去读编译内核时的电脑信息等,跟移植内核没有关系。
start_kernel,第613行,调用setup_arch(&command_line)函数,setup_arch函数在arch/arm/kernel中,如下:
02 {
03 structtag*tags=(structtag*)&init_tags;
04 structmachine_desc*mdesc;
05 char*from=default_command_line;
06
07 unwind_init();
08
09 setup_processor();
10 mdesc=setup_machine(machine_arch_type);
11 machine_name=mdesc->name;
12
13 if(mdesc->soft_reboot)
14 reboot_setup("s");
15
16 if(__atags_pointer)
17 tags=phys_to_virt(__atags_pointer);
18 elseif(mdesc->boot_params)
19 tags=phys_to_virt(mdesc->boot_params);
20
21 #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
22 /*
23 * If we have the old style parameters, convert them to
24 * a tag list.
25 */
26 if(tags->hdr.tag!=ATAG_CORE)
27 convert_to_tag_list(tags);
28 #endif
29 if(tags->hdr.tag!=ATAG_CORE)
30 tags=(structtag*)&init_tags;
31
32 if(mdesc->fixup)
33 mdesc->fixup(mdesc,tags,&from,&meminfo);
34
35 if(tags->hdr.tag==ATAG_CORE) {
36 if(meminfo.nr_banks!=0)
37 squash_mem_tags(tags);
38 save_atags(tags);
39 parse_tags(tags);
40 }
41
42 init_mm.start_code=(unsignedlong) _text;
43 init_mm.end_code =(unsignedlong) _etext;
44 init_mm.end_data =(unsignedlong) _edata;
45 init_mm.brk =(unsignedlong) _end;
46
47 /* parse_early_param needs a boot_command_line */
48 strlcpy(boot_command_line,from,COMMAND_LINE_SIZE);
49
50 /* populate cmd_line too for later use, preserving boot_command_line */
51 strlcpy(cmd_line,boot_command_line,COMMAND_LINE_SIZE);
52 *cmdline_p=cmd_line;
53
54 parse_early_param();
55
56 arm_memblock_init(&meminfo,mdesc);
57
58 paging_init(mdesc);
59 request_standard_resources(&meminfo,mdesc);
60
61 #ifdef CONFIG_SMP
62 if(is_smp())
63 smp_init_cpus();
64 #endif
65 reserve_crashkernel();
66
67 cpu_init();
68 tcm_init();
69
70 /*
71 * Set up various architecture-specific pointers
72 */
73 arch_nr_irqs=mdesc->nr_irqs;
74 init_arch_irq=mdesc->init_irq;
75 system_timer=mdesc->timer;
76 init_machine=mdesc->init_machine;
77
78 #ifdef CONFIG_VT
79 #if defined(CONFIG_VGA_CONSOLE)
80 conswitchp=&vga_con;
81 #elif defined(CONFIG_DUMMY_CONSOLE)
82 conswitchp=&dummy_con;
83 #endif
84 #endif
85 early_trap_init();
86 }
第9行,调用了 setup_processor()函数,读CPU的一些信息,如下:
02 {
03 structproc_info_list*list;
04
05 /*
06 * locate processor in the list of supported processor
07 * types. The linker builds this table for us from the
08 * entries in arch/arm/mm/proc-*.S
09 */
10 list=lookup_processor_type(read_cpuid_id());
11 if(!list) {
12 printk("CPU configuration botched (ID %08x), unable "
13 "to continue.\n",read_cpuid_id());
14 while(1);
15 }
16
17 cpu_name=list->cpu_name;
18
19 #ifdef MULTI_CPU
20 processor=*list->proc;
21 #endif
22 #ifdef MULTI_TLB
23 cpu_tlb=*list->tlb;
24 #endif
25 #ifdef MULTI_USER
26 cpu_user=*list->user;
27 #endif
28 #ifdef MULTI_CACHE
29 cpu_cache=*list->cache;
30 #endif
31
32 printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
33 cpu_name,read_cpuid_id(),read_cpuid_id() &15,
34 proc_arch[cpu_architecture()],cr_alignment);
35
36 sprintf(init_utsname()->machine,"%s%c",list->arch_name,ENDIANNESS);
37 sprintf(elf_platform,"%s%c",list->elf_name,ENDIANNESS);
38 elf_hwcap=list->elf_hwcap;
39 #ifndef CONFIG_ARM_THUMB
40 elf_hwcap&=~HWCAP_THUMB;
41 #endif
42
43 feat_v6_fixup();
44
45 cacheid_init();
46 cpu_proc_init();
47 }
在这个函数中第32行,cpuname, read_cpuid()等,读变量或函数返回值,打印出CPU信息,即是开头的CPU:ARM920T [41129200] revision 0 (ARMv4T),cr=c0007177 打印信息。这也跟移植的关系不大,主要是我们移植的时候配置好CPU就行了。
再看上面的setup_processor函数,后面调用了cacheid_init()函数,这个函数具体干嘛的,现在不明白,后面分析,这个函数如下:
02 {
03 unsignedintcachetype=read_cpuid_cachetype();
04 unsignedintarch=cpu_architecture();
05
06 if(arch>=CPU_ARCH_ARMv6) {
07 if((cachetype&(7<<29)) ==4<<29) {
08 /* ARMv7 register format */
09 cacheid=CACHEID_VIPT_NONALIASING;
10 if((cachetype&(3<<14)) ==1<<14)
11 cacheid|=CACHEID_ASID_TAGGED;
12 elseif(cpu_has_aliasing_icache(CPU_ARCH_ARMv7))
13 cacheid|=CACHEID_VIPT_I_ALIASING;
14 }elseif(cachetype&(1<<23)) {
15 cacheid=CACHEID_VIPT_ALIASING;
16 }else{
17 cacheid=CACHEID_VIPT_NONALIASING;
18 if(cpu_has_aliasing_icache(CPU_ARCH_ARMv6))
19 cacheid|=CACHEID_VIPT_I_ALIASING;
20 }
21 }else{
22 cacheid=CACHEID_VIVT;
23 }
24
25 printk("CPU: %s data cache, %s instruction cache\n",
26 cache_is_vivt() ?"VIVT":
27 cache_is_vipt_aliasing() ?"VIPT aliasing":
28 cache_is_vipt_nonaliasing() ?"VIPT nonaliasing":"unknown",
29 cache_is_vivt() ?"VIVT":
30 icache_is_vivt_asid_tagged() ?"VIVT ASID tagged":
31 icache_is_vipt_aliasing() ?"VIPT aliasing":
32 cache_is_vipt_nonaliasing() ?"VIPT nonaliasing":"unknown");
33 }
第25行即是输出打印信息。到这里跟移植关系也不太大。
返回setup_arch函数,第10行调用setup_machine(machine_arch_type)函数,参数是machine_arch_type, 将返回值传递给mdesc变量。
这里虽然跟移植有关系,不过跟具体的平台关系不大,我们设置好平台机器号就好了。
achine_arch_type来自于文件:include/generated/mach-types.h [ 此文件是生成文件 ]。这个只是对应一个number,然后通过这个number去查找到相关信息。每一种板子对应于一个特定的number。然后相关的描述来于MACHINE_START宏。
取得该板子的机器码后,在setup_machine函数中会打印出机器名称。如下:
02 {
03 structmachine_desc*list;
04
05 /*
06 * locate machine in the list of supported machines.
07 */
08 list=lookup_machine_type(nr);
09 if(!list) {
10 printk("Machine configuration botched (nr %d), unable "
11 "to continue.\n",nr);
12 while(1);
13 }
14
15 printk("Machine: %s\n",list->name);
16
17 returnlist;
18 }
第15行打印出机器名,这里是WGC2440。
这个名字来自arch/arm/mach-s3c2440/mach-wgc2440.c文件中的MACHINE_START宏,这个宏后面再分析,跟机器码有关。