解读linux内核代码之boot(1)
2011-06-10 21:27
253 查看
最近开始研究linux内核,之前本来是在看《Understanding The Linux Kernel》,看了几章之后,发现虽然这本书讲的很通俗易懂,但是我看的是第二版,书中对应的内核版本是2.4的,而现在最新的内核版本确实2.6.39的,大体上算法是差不多的,但是很多代码实现完全不同了,所以就放弃了这本书,开始从源代码入手开始看。
由于内核代码很多,刚开始也不知道从哪里开始看起,纠结了很久才决定从内核boot的代码开始看起。
boot的代码在/arch/x86/boot/这个目录下,下面很明显的有个main.c文件,自然地打开一看,里面有个main函数,如下
void main(void)
{
/* First, copy the boot header into the "zeropage" */
copy_boot_params();
/* Initialize the early-boot console */
console_init();
if (cmdline_find_option_bool("debug"))
puts("early console in setup code/n");
/* End of heap check */
init_heap();
/* Make sure we have all the proper CPU support */
if (validate_cpu()) {
puts("Unable to boot - please use a kernel appropriate "
"for your CPU./n");
die();
}
/* Tell the BIOS what CPU mode we intend to run in. */
set_bios_mode();
/* Detect memory layout */
detect_memory();
/* Set keyboard repeat rate (why?) */
keyboard_set_repeat();
/* Query MCA information */
query_mca();
/* Query Intel SpeedStep (IST) information */
query_ist();
/* Query APM information */
#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
query_apm_bios();
#endif
/* Query EDD information */
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
query_edd();
#endif
/* Set the video mode */
set_video();
/* Do the last things and invoke protected mode */
go_to_protected_mode();
}
函数的第一句调用函数copy_boot_params(), 这个函数依然在本文件中,作用是拷贝boot参数到第一个内存page,提醒一句,这个时候cpu还是运行在实模式下。copy_boot_params()的实现如下
static void copy_boot_params(void)
{
struct old_cmdline {
u16 cl_magic;
u16 cl_offset;
};
const struct old_cmdline * const oldcmd =
(const struct old_cmdline *)OLD_CL_ADDRESS;
BUILD_BUG_ON(sizeof boot_params != 4096);
memcpy(&boot_params.hdr, &hdr, sizeof hdr);
if (!boot_params.hdr.cmd_line_ptr &&
oldcmd->cl_magic == OLD_CL_MAGIC) {
/* Old-style command line protocol. */
u16 cmdline_seg;
/* Figure out if the command line falls in the region
of memory that an old kernel would have copied up
to 0x90000... */
if (oldcmd->cl_offset < boot_params.hdr.setup_move_size)
cmdline_seg = ds();
else
cmdline_seg = 0x9000;
boot_params.hdr.cmd_line_ptr =
(cmdline_seg << 4) + oldcmd->cl_offset;
}
}
这个函数逻辑是简单的,我并不想说这个,注意这一句memcpy(&boot_params.hdr, &hdr, sizeof hdr);中hdr这个变量,这个结构体变量在main.c里面并没有定义,然后我惊讶地发现这个hdr居然在linux内核代码中所有的h文件和c文件中都没有定义,出了在boot.h中声明了一下extern struct setup_header hdr;
最后把目光发在head.s这个汇编文件上,打开一看,果然hdr这个变量是在这个汇编文件中定义的。
在header.s中,实现了内核启动执行main函数(如上文说的)之前做的动作,包括定义hdr变量并赋值,分配stack,然后调用main函数,以及内核不能正确启动的打印信息等等。
由于内核代码很多,刚开始也不知道从哪里开始看起,纠结了很久才决定从内核boot的代码开始看起。
boot的代码在/arch/x86/boot/这个目录下,下面很明显的有个main.c文件,自然地打开一看,里面有个main函数,如下
void main(void)
{
/* First, copy the boot header into the "zeropage" */
copy_boot_params();
/* Initialize the early-boot console */
console_init();
if (cmdline_find_option_bool("debug"))
puts("early console in setup code/n");
/* End of heap check */
init_heap();
/* Make sure we have all the proper CPU support */
if (validate_cpu()) {
puts("Unable to boot - please use a kernel appropriate "
"for your CPU./n");
die();
}
/* Tell the BIOS what CPU mode we intend to run in. */
set_bios_mode();
/* Detect memory layout */
detect_memory();
/* Set keyboard repeat rate (why?) */
keyboard_set_repeat();
/* Query MCA information */
query_mca();
/* Query Intel SpeedStep (IST) information */
query_ist();
/* Query APM information */
#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
query_apm_bios();
#endif
/* Query EDD information */
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
query_edd();
#endif
/* Set the video mode */
set_video();
/* Do the last things and invoke protected mode */
go_to_protected_mode();
}
函数的第一句调用函数copy_boot_params(), 这个函数依然在本文件中,作用是拷贝boot参数到第一个内存page,提醒一句,这个时候cpu还是运行在实模式下。copy_boot_params()的实现如下
static void copy_boot_params(void)
{
struct old_cmdline {
u16 cl_magic;
u16 cl_offset;
};
const struct old_cmdline * const oldcmd =
(const struct old_cmdline *)OLD_CL_ADDRESS;
BUILD_BUG_ON(sizeof boot_params != 4096);
memcpy(&boot_params.hdr, &hdr, sizeof hdr);
if (!boot_params.hdr.cmd_line_ptr &&
oldcmd->cl_magic == OLD_CL_MAGIC) {
/* Old-style command line protocol. */
u16 cmdline_seg;
/* Figure out if the command line falls in the region
of memory that an old kernel would have copied up
to 0x90000... */
if (oldcmd->cl_offset < boot_params.hdr.setup_move_size)
cmdline_seg = ds();
else
cmdline_seg = 0x9000;
boot_params.hdr.cmd_line_ptr =
(cmdline_seg << 4) + oldcmd->cl_offset;
}
}
这个函数逻辑是简单的,我并不想说这个,注意这一句memcpy(&boot_params.hdr, &hdr, sizeof hdr);中hdr这个变量,这个结构体变量在main.c里面并没有定义,然后我惊讶地发现这个hdr居然在linux内核代码中所有的h文件和c文件中都没有定义,出了在boot.h中声明了一下extern struct setup_header hdr;
最后把目光发在head.s这个汇编文件上,打开一看,果然hdr这个变量是在这个汇编文件中定义的。
在header.s中,实现了内核启动执行main函数(如上文说的)之前做的动作,包括定义hdr变量并赋值,分配stack,然后调用main函数,以及内核不能正确启动的打印信息等等。
相关文章推荐
- Linux0.11内核--启动引导代码分析bootsect.s
- Linux 0.1 版本内核 bootsect.s 代码解析
- Linux0.11内核--启动引导代码分析bootsect.s
- Linux0.11内核--启动引导代码分析bootsect.s
- linux0.11内核代码之bootsect.s
- Linux驱动开发中s3c2410关于gpio的内核导出函数的解读
- 嵌入式Linux内核移植相关代码分析
- 使用linux 内核中代码之--list
- 嵌入式Linux内核移植相关代码分析
- Linux之Mount内核代码分析
- 关于UBOOT,LINUX内核编译,根文件系统的15个弱智问题(转)
- U-Boot与Linux内核的交互
- 专家解读Linux操作系统内核中的GCC特性
- linux 解决Ubuntu编译内核uImage出现问题“mkimage” command not found - U-Boot images will not be built问题
- 《linux 内核完全剖析》 sys.c 代码分析
- linux-内核-BootLoader/Uboot/Flash/文件系统
- 为AM335x移植Linux内核主线代码
- linux 0.11 version 启动代码分析(bootsect.s)
- U-boot中启动内核的代码阅读
- Linux内核移植 part1:uboot 框架及移植