新路程------hi3516a kernel启动

来源:互联网 发布:入门耳机 知乎 编辑:程序博客网 时间:2024/05/22 05:02

在/init/main.c里

static int __init kernel_init(void * unused){/* * Wait until kthreadd is all set-up. */wait_for_completion(&kthreadd_done);/* Now the scheduler is fully set up and can do blocking allocations */gfp_allowed_mask = __GFP_BITS_MASK;/* * init can allocate pages on any node */set_mems_allowed(node_states[N_HIGH_MEMORY]);/* * init can run on any cpu. */set_cpus_allowed_ptr(current, cpu_all_mask);cad_pid = task_pid(current);smp_prepare_cpus(setup_max_cpus);do_pre_smp_initcalls();lockup_detector_init();smp_init();sched_init_smp();do_basic_setup();/* Open the /dev/console on the rootfs, this should never fail */if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)printk(KERN_WARNING "Warning: unable to open an initial console.\n");(void) sys_dup(0);(void) sys_dup(0);/* * check if there is an early userspace init.  If yes, let it do all * the work */if (!ramdisk_execute_command)ramdisk_execute_command = "/init";if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {ramdisk_execute_command = NULL;prepare_namespace();}/* * Ok, we have completed the initial bootup, and * we're essentially up and running. Get rid of the * initmem segments and start the user-mode stuff.. */init_post();return 0;}


然后再看do_basic_setup()

static void __init do_basic_setup(void){cpuset_init_smp();usermodehelper_init();shmem_init();driver_init();init_irq_proc();do_ctors();usermodehelper_enable();do_initcalls();}

然后看do_initcalls()

static void __init do_initcalls(void){int level;for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)do_initcall_level(level);}static void __init do_initcall_level(int level){extern const struct kernel_param __start___param[], __stop___param[];initcall_t *fn;strcpy(static_command_line, saved_command_line);parse_args(initcall_level_names[level],   static_command_line, __start___param,   __stop___param - __start___param,   level, level,   repair_env_string);for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)do_one_initcall(*fn);}int __init_or_module do_one_initcall(initcall_t fn){int count = preempt_count();int ret;if (initcall_debug)ret = do_one_initcall_debug(fn);elseret = fn();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;}


然后看这里的initcall里的参数怎么来

看看

/include/linux/init.h里

#define arch_initcall(fn) __define_initcall("3",fn,3)

然后定义在

#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn

Vmlinux.lds.h (linux-3.4.y\include\vmlinux.lds.h)里

#define INIT_CALLS \
VMLINUX_SYMBOL(__initcall_start) = .;\
*(.initcallearly.init)\
INIT_CALLS_LEVEL(0)\
INIT_CALLS_LEVEL(1)\
INIT_CALLS_LEVEL(2)\
INIT_CALLS_LEVEL(3)\
INIT_CALLS_LEVEL(4)\
INIT_CALLS_LEVEL(5)\
INIT_CALLS_LEVEL(rootfs)\
INIT_CALLS_LEVEL(6)\
INIT_CALLS_LEVEL(7)\
VMLINUX_SYMBOL(__initcall_end) = .;

原理如这个文章http://blog.csdn.net/wh_19910525/article/details/16370863

然后回头看看linux-3.4.y/arch/arm/mach-hi3516a

MACHINE_START(HI3516A, "hi3516a")
.atag_offset = 0x100,
.map_io = hi3516a_map_io,
.init_early = hi3516a_init_early,
.init_irq = hi3516a_gic_init_irq,
.handle_irq = gic_handle_irq,
.timer = &hi3516a_sys_timer,
.init_machine = hi3516a_init,   //这个init_machine
.reserve = hi3516a_reserve,
.restart = hi3516a_restart,
MACHINE_END

这边可以看http://blog.csdn.net/cxw3506/article/details/8475965有详细解释


原创粉丝点击