1. define [cpp] # define MACHINE_START (_ type, _ name) \ // board type, the Board name is static const struct machine_desc _ mach_desc _ # _ type \ _ used \ _ attribute _ (_ section _ (".arch.info. init ") = {\. nr = MACH_TYPE _ # _ type ,\. name = _ name, # define MACHINE_END \}; The MACHINE_START and MACHINE_END boxes indicate the machine_desc struct and initialize it according to the MACHINE_START macro parameters. nr and. name member and compile the struct mark to .arch.info. the init segment can initialize the machine_desc struct between the MACHINE_START and MACHINE_END macros. Definition of the remaining member machine_desc struct of [cpp] struct machine_desc {unsigned int nr;/* architecture number */const char * name;/* architecture name */unsigned long boot_params; /* tagged list */unsigned int nr_irqs;/* number of IRQs interrupt count */unsigned int video_start;/* start of video RAM */unsigned int video_end; /* end of video RAM */unsigned int reserve_lp0: 1;/* never has lp0 */unsigned int reserv E_lp1: 1;/* never has lp1 */unsigned int reserve_lp2: 1;/* never has lp2 */unsigned int soft_reboot: 1; /* soft reboot */void (* fixup) (struct machine_desc *, struct tag *, char **, struct meminfo *); void (* reserve) (void ); /* reserve mem blocks */void (* map_io) (void);/* IO mapping function io ing function */void (* init_irq) (void ); /* interrupt initialization function */struct sys_timer * timer;/* system tick timer */v Oid (* init_machine) (void);/* initialization function */}; example: [cpp] MACHINE_START (SMDKC110, "SMDKC110")/* Maintainer: kukjin Kim <kgene.kim@samsung.com> */. boot_params = S5P_PA_SDRAM + 0x100 ,. init_irq = s5pv210_init_irq ,. map_io = smdkc110_map_io ,. init_machine = smdkc110_machine_init ,. timer = & s3c24xx_timer, MACHINE_END here smdkc110_machine_init is the corresponding board-Level Initialization function, s5pv210_init_irq is the board-level interrupt initialization function, smdkc110_map_io is the board-level io Initialization Function... ii. Call the MACHINE_START macro to compile the machine_desc tag to .arch.info. and/arch/arm/kernel/vmlinux. [cpp] _ arch_info_begin = .; * (.arch.info. init) _ arch_info_end = .; in the linux Startup function start_kernel, setup_arch (& command_line); [cpp] void _ init setup_arch (char ** cmdline_p) {struct tag * tags = (struct tag *) is called *) & init_tags; struct machine_desc * mdesc; // declares a machine_desc struct pointer char * from = default_command_line; init_ta Gs. mem. start = PHYS_OFFSET; unwind_init (); setup_processor (); mdesc = setup_machine (machine_arch_type); // 0 obtain machine_desc machine_name = mdesc-> name based on machine_arch_type; // set the name if (mdesc-> soft_reboot) // need soft restart? Reboot_setup ("s"); if (_ atags_pointer) tags = phys_to_virt (_ atags_pointer); else if (mdesc-> boot_params) {// process the startup parameter # ifdef CONFIG_MMU if (mdesc-> boot_params <PHYS_OFFSET | mdesc-> boot_params> = PHYS_OFFSET + SZ_1M) {printk (KERN_WARNING "Default boot params at physical 0x % 08lx out of reach \ n", mdesc-> boot_params );} else # endif {tags = phys_to_virt (mdesc-> boot_params) ;}# if defined (CONFIG_DE PRECATED_PARAM_STRUCT) if (tags-> hdr. tag! = ATAG_CORE) convert_to_tag_list (tags); # endif if (tags-> hdr. tag! = ATAG_CORE) tags = (struct tag *) & init_tags; if (mdesc-> fixup) // call the mdesc-> fixup (mdesc, tags, & from, & meminfo); if (tags-> hdr. tag = ATAG_CORE) {if (meminfo. nr_banks! = 0) squash_mem_tags (tags); save_atags (tags); parse_tags (tags);} init_mm.start_code = (unsigned long) _ text; vertex = (unsigned long) _ etext; vertex = (unsigned long) _ edata; init_mm.brk = (unsigned long) _ end;/* parse_early_param needs a boot_command_line */strlcpy (boot_command_line, from, COMMAND_LINE_SIZE ); /* populate into _line too for later use, preserving boot_command_li Ne */strlcpy (cmd_line, boot_command_line, COMMAND_LINE_SIZE); * cmdline_p = cmd_line; parse_early_param (); arm_memblock_init (& meminfo, mdesc ); // The reserve method paging_init (mdesc) may be called here; //-> devicemaps_init (mdesc)-> map_io method request_standard_resources (& meminfo, mdesc ); // The video_start method # ifdef CONFIG_SMP if (is_smp () smp_init_cpus (); # endif reserve_crashkernel (); cpu_init (); tcm_init (); arch_nr_ir Qs = mdesc-> nr_irqs; // 1 sets the number of global variable interruptions init_arch_irq = mdesc-> init_irq; // 2 sets the global variable interrupt initialization function system_timer = mdesc-> timer; // 3 set the global variable sys_timer struct init_machine = mdesc-> init_machine; // 4 set the global variable board-Level Initialization function # ifdef CONFIG_VT # if defined (CONFIG_VGA_CONSOLE) conswitchp = & vga_con; # elif defined (CONFIG_DUMMY_CONSOLE) conswitchp = & dummy_con; # endif early_trap_init ();} 0. [cpp] static struct machine_desc *__ Init setup_machine (unsigned int nr) {extern struct machine_desc _ arch_info_begin [], _ arch_info_end []; struct machine_desc * p; for (p = _ arch_info_begin; p <_ arch_info_end; p ++) // The machine_desc structure between _ arch_info_begin and _ arch_info_end if (nr = p-> nr) {// find the corresponding board printk ("Machine: % s \ n", p-> name); // print the board-level information return p ;} early_print ("\ n" "Error: unrecognized/unsupported machine ID (r1 = 0x % 08x ). \ n" "Available machine support: \ n \ nID (hex) \ tNAME \ n", nr); for (p = _ arch_info_begin; p <_ arch_info_end; p ++) early_print ("% 08x \ t % s \ n", p-> nr, p-> name); early_print ("\ nPlease check your kernel config and/or bootloader. \ n "); while (true)/* can't use cpu_relax () here as it may require MMU setup */;} 1. number of interrupts start_kernel-> early_irq_init-> In the arch_probe_nr_irqs function, nr_irqs = arch_nr_irqs? Arch_nr_irqs: NR_IRQS; set global nr_irqs variable 2. interrupt initialization function start_kernel-> init_IRQ-> init_arch_irq () 3. sys_timer struct start_kernel-> time_init () call system_timer-> init () method both sys_timer-> init () 4. board-Level Initialization function [cpp] static void (* init_machine) (void) _ initdata; static int _ init customize_machine (void) {/* customizes platform devices, or adds new ones */if (init_machine) // The global function init_machine has init_machine (); // This is called when mdesc-> init_machin E () return 0;} arch_initcall (customize_machine); // use arch_initcall to modify the archmize_machine function arch_iniitcall function in/include/linux/init. define [cpp] # define arch_initcall (fn) _ define_initcall ("3", fn, 3) _ define_initcall in h [cpp] # define _ define_initcall (level, fn, id) \ static initcall_t _ initcall _ # fn # id _ used \ _ attribute _ (_ section __(". initcall "level ". init ") = fn expansion is static initcall_t _ initcall_cust Omize_machine3 _ used _ attribute _ (_ section __(". initcall3.init ") = customize_machine in vmlinux. [cpp] _ initcall_start = .; *(. initcallearly. init) _ early_initcall_end = .; *(. initcall0.init )*(. initcall0s. init )*(. initcall1.init )*(. initcall1s. init )*(. initcall2.init )*(. initcall2s. init )*(. initcall3.init )*(. initcall3s. init )*(. initcall4.init )*(. initcall4s. init )*(. initcall5.init )*(. initca Ll5s. init )*(. initcallrootfs. init )*(. initcall6.init )*(. initcall6s. init )*(. initcall7.init )*(. initcall7s. init) _ initcall_end = .; marked. the initcall3.init function is compiled into the section in the _ initcall_start and _ initcall_end boxes, and start_kernel-> rest_init ()-> kernel_thread (kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); the kernel thread kernel_init-> do_pre_smp static void _ init do_pre_smp_initcils (void) {initcall_t * fn; for (fn = _ Initcall_start; fn <_ early_initcall_end; fn ++) do_one_initcall (* fn);} This function traverses functions in _ initcall_start and _ early_initcall_end, call do_one_initcall [cpp] int _ init_or_module do_one_initcall (initcall_t fn) {int count = preempt_count (); int ret; if (initcall_debug) ret = fn ); else ret = fn (); // The fn function is executed, that is, customize_machine msgbuf [0] = 0; if (ret & ret! =-ENODEV & initcall_debug) sprintf (msgbuf, "error code % d", ret); if (preempt_count ()! = Count) {strlcat (msgbuf, "preemption imbalance", sizeof (msgbuf); preempt_count () = count;} if (irqs_disabled () {strlcat (msgbuf, "disabled interrupts", sizeof (msgbuf); local_irq_enable ();} if (msgbuf [0]) {printk ("initcall % pF returned with % s \ n", fn, msgbuf);} return ret ;}