x86系统引导(2)

来源:互联网 发布:jdk源码 视频教程 编辑:程序博客网 时间:2024/04/30 18:36

上一篇  x86系统引导(1)主要是整体上对系统的引导有个概括的理解,没有深入到具体的源码中,这一篇,我们将深入到源码中,进行分析。系统引导过程中很多都是汇编写的,我们就不分析那些了,从start_kernel函数开始。

源码如下:

/*
 * Activate the first processor.
 */
asmlinkage void __init start_kernel(void)
{
char * command_line;
extern struct kernel_param __start___param[], __stop___param[];
/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them现在中断被禁止。

 */
lock_kernel();
page_address_init();

这函数在/* defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) */这个条件满足时,才能执行,应该和高端内存有关。
printk(linux_banner);

在屏幕上显示出内核的版本信息。如下:

const char *linux_banner = 
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";


setup_arch(&command_line);

这个函数所处理的是系统结构的设置,就是这部分的主体。源码如下,其中很多我省略了:

/*
 * Determine if we were loaded by an EFI loader.  If so, then we have also been
 * passed the efi memmap, systab, etc., so we should use these data structures
 * for initialization.  Note, the efi init code path is determined by the
 * global efi_enabled. This allows the same kernel image to be used on existing
 * systems (with a traditional BIOS) as well as on EFI systems.
 */
void __init setup_arch(char **cmdline_p)
{
unsigned long max_low_pfn;


memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
pre_setup_arch_hook();空函数

void __init pre_setup_arch_hook(void)
{
}
early_cpu_init();/* 设置获取的cpu信息 */

void __init early_cpu_init(void)
{
intel_cpu_init();
cyrix_init_cpu();
nsc_init_cpu();
amd_init_cpu();
centaur_init_cpu();
transmeta_init_cpu();
rise_init_cpu();
nexgen_init_cpu();
umc_init_cpu();
early_cpu_detect();
......
}
......

  ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
  drive_info = DRIVE_INFO;
  screen_info = SCREEN_INFO;
edid_info = EDID_INFO;
apm_info.bios = APM_BIOS_INFO;
ist_info = IST_INFO;
saved_videomode = VIDEO_MODE;
if( SYS_DESC_TABLE.length != 0 ) {
MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
machine_id = SYS_DESC_TABLE.table[0];
machine_submodel_id = SYS_DESC_TABLE.table[1];
BIOS_revision = SYS_DESC_TABLE.table[2];
}
aux_device_present = AUX_DEVICE_INFO;


#ifdef CONFIG_BLK_DEV_RAM
rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
#endif

 从setup中取得BIOS自检后取得的信息,复制到内核内存空间中(原来保存在一个临时页面中) ,如果在引导命令行中另有所指,则处理命令行时再加以修改。
ARCH_SETUP
if (efi_enabled)
efi_init();
else {
printk(KERN_INFO "BIOS-provided physical RAM map:\n");
print_memory_map(machine_specific_memory_setup());
}

/**这个函数主要是有setup在引导阶段对物理内存的查询,并根据获得的信息生成一张物理内存的构成图,成为e820图,在通过参数传给内核,使内核知道系统中内存资源的配置。

主要和下面的结构有关:

#define E820_MAP    ((struct e820entry *) (PARAM+E820MAP))

struct e820map {
    int nr_map;
    struct e820entry {
unsigned long long addr;/* start of memory segment */
unsigned long long size;/* size of memory segment */
unsigned long type;/* type of memory segment */
    } map[E820MAX];
};

extern struct e820map e820;

数组中的每一项都是对一个物理内存的描述。
 * machine_specific_memory_setup - Hook for machine specific memory setup.
 *
 * Description:
 * This is included late in kernel/setup.c so that it can make
 * use of all of the static functions.
 **/
static char * __init machine_specific_memory_setup(void)
{
char *who;

who = "BIOS-e820";
/*
* Try to copy the BIOS-supplied E820-map.
*
* Otherwise fake a memory map; one section from 0k->640k,
* the next section from 1mb->appropriate_mem_k
*/
sanitize_e820_map(E820_MAP, &E820_MAP_NR);
if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
unsigned long mem_size;


/* compare results from other methods and take the greater */
if (ALT_MEM_K < EXT_MEM_K) {
mem_size = EXT_MEM_K;
who = "BIOS-88";
} else {
mem_size = ALT_MEM_K;
who = "BIOS-e801";
}


e820.nr_map = 0;
add_memory_region(0, LOWMEMSIZE(), E820_RAM);
add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
  }
return who;
}
......
下一篇从这里接着说。
if (!MOUNT_ROOT_RDONLY)
root_mountflags &= ~MS_RDONLY;
init_mm.start_code = (unsigned long) _text;
init_mm.end_code = (unsigned long) _etext;
init_mm.end_data = (unsigned long) _edata;
init_mm.brk = init_pg_tables_end + PAGE_OFFSET;


code_resource.start = virt_to_phys(_text);
code_resource.end = virt_to_phys(_etext)-1;
data_resource.start = virt_to_phys(_etext);
data_resource.end = virt_to_phys(_edata)-1;


parse_cmdline_early(cmdline_p);
max_low_pfn = setup_memory();


.......
}

x86系统引导(1)的链接

x86系统引导(3)的连接


原创粉丝点击