现在的位置: 首页 > 综合 > 正文

复制初始化头变量

2013年07月06日 ⁄ 综合 ⁄ 共 4963字 ⁄ 字号 评论关闭

3.3.1 复制初始化头变量

131行是第一个函数,copy_boot_params(),顾名思义用来拷贝启动参数到内存的0号页面中:

 

  29static void copy_boot_params(void)

  30{

  31        struct old_cmdline {

  32                u16 cl_magic;

  33                u16 cl_offset;

  34        };

  35        const struct old_cmdline * const oldcmd =

  36                (const struct old_cmdline *)OLD_CL_ADDRESS;

  37

  38        BUILD_BUG_ON(sizeof boot_params != 4096);

  39        memcpy(&boot_params.hdr, &hdr, sizeof hdr);

  40

  41        if (!boot_params.hdr.cmd_line_ptr &&

  42            oldcmd->cl_magic == OLD_CL_MAGIC) {

  43                /* Old-style command line protocol. */

  44                u16 cmdline_seg;

  45

  46                /* Figure out if the command line falls in the region

  47                   of memory that an old kernel would have copied up

  48                   to 0x90000... */

  49                if (oldcmd->cl_offset < boot_params.hdr.setup_move_size)

  50                        cmdline_seg = ds();

  51                else

  52                        cmdline_seg = 0x9000;

  53

  54                boot_params.hdr.cmd_line_ptr =

  55                        (cmdline_seg << 4) + oldcmd->cl_offset;

  56        }

  57}

 

35行,const struct old_cmdline * const oldcmd,这里用到const的的概念了。首先,oldcmd是个指针,指向old_cmdline结构。前面加上const,说明是个指针常量。其*前面的const,有说明这个oldcmd指向的内容也是一个常量。好了,这里就是两个常量。

 

接下来,39行,将hdr的内容拷贝到全局变量boot_paramshdr字段中。注意哈,这两个hdr不是同一个东西一个是header.S文件中定义的数据段中的内容,一个是boot_params数据结构中的一个字段,只是名字叫hdr。在这里第一次见到boot_params,它是在arch/x86/include/asm/Bootparam.h文件中定义。这里第一次出现,接下来的大部分工作都是填充这个boot_params。这个boot_params来头可不小,它刚好是一个页面的大小。在arch/x86/boot/Main.c的第18行:

18 struct boot_params boot_params __attribute__((aligned(16)));

 

注意,这个变量boot_paramsMain.c的全局变量,且未被初始化,所以位于BSS段。grubvmlinuz加载进内存后,boot_params就位于_bss_start的开始位置。而后面当启动保护模式的分页功能后,第一个页面就是从它开始的(注意,不是从0x0开始的喔)。所以内核注释它为“zeropage”,即所谓的0号页面,足见这个boot_params的重要性:

 

  84/* The so-called "zeropage" */

  85struct boot_params {

  86        struct screen_info screen_info;                 /* 0x000 */

  87        struct apm_bios_info apm_bios_info;             /* 0x040 */

  88        __u8  _pad2[4];                                 /* 0x054 */

  89        __u64  tboot_addr;                              /* 0x058 */

  90        struct ist_info ist_info;                       /* 0x060 */

  91        __u8  _pad3[16];                                /* 0x070 */

  92        __u8  hd0_info[16];     /* obsolete! */         /* 0x080 */

  93        __u8  hd1_info[16];     /* obsolete! */         /* 0x090 */

  94        struct sys_desc_table sys_desc_table;           /* 0x0a0 */

  95        __u8  _pad4[144];                               /* 0x0b0 */

  96        struct edid_info edid_info;                     /* 0x140 */

  97        struct efi_info efi_info;                       /* 0x1c0 */

  98        __u32 alt_mem_k;                                /* 0x1e0 */

  99        __u32 scratch;          /* Scratch field! */    /* 0x1e4 */

 100        __u8  e820_entries;                             /* 0x1e8 */

 101        __u8  eddbuf_entries;                           /* 0x1e9 */

 102        __u8  edd_mbr_sig_buf_entries;                  /* 0x1ea */

 103        __u8  _pad6[6];                                 /* 0x1eb */

 104        struct setup_header hdr;    /* setup header */  /* 0x1f1 */

 105        __u8  _pad7[0x290-0x1f1-sizeof(struct setup_header)];

 106        __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];      /* 0x290 */

 107        struct e820entry e820_map[E820MAX];             /* 0x2d0 */

 108        __u8  _pad8[48];                                /* 0xcd0 */

 109        struct edd_info eddbuf[EDDMAXNR];               /* 0xd00 */

 110        __u8  _pad9[276];                               /* 0xeec */

 111} __attribute__((packed));

 

就这个东西,把前面的初始化变量hdr拷贝到boot_paramshdr字段中。它的hdr字段是个setup_header结构,定义在同一个头文件中:

 

  24struct setup_header {

  25        __u8    setup_sects;

  26        __u16   root_flags;

  27        __u32   syssize;

  28        __u16   ram_size;

  29#define RAMDISK_IMAGE_START_MASK        0x07FF

  30#define RAMDISK_PROMPT_FLAG             0x8000

  31#define RAMDISK_LOAD_FLAG               0x4000

  32        __u16   vid_mode;

  33        __u16   root_dev;

  34        __u16   boot_flag;

  35        __u16   jump;

  36        __u32   header;

  37        __u16   version;

  38        __u32   realmode_swtch;

  39        __u16   start_sys;

  40        __u16   kernel_version;

  41        __u8    type_of_loader;

  42        __u8    loadflags;

  43#define LOADED_HIGH     (1<<0)

  44#define QUIET_FLAG      (1<<5)

  45#define KEEP_SEGMENTS   (1<<6)

  46#define CAN_USE_HEAP    (1<<7)

  47        __u16   setup_move_size;

  48        __u32   code32_start;

  49        __u32   ramdisk_image;

  50        __u32   ramdisk_size;

  51        __u32   bootsect_kludge;

  52        __u16   heap_end_ptr;

  53        __u8    ext_loader_ver;

  54        __u8    ext_loader_type;

  55        __u32   cmd_line_ptr;

  56        __u32   initrd_addr_max;

  57        __u32   kernel_alignment;

  58        __u8    relocatable_kernel;

  59        __u8    _pad2[3];

  60        __u32   cmdline_size;

  61        __u32   hardware_subarch;

  62        __u64   hardware_subarch_data;

  63        __u32   payload_offset;

  64        __u32   payload_length;

  65        __u64   setup_data;

  66} __attribute__((packed));

 

 

细心的朋友可能已经发现了,这些字段跟我们前面在header.S中看到的初始化头变量hdr中的字段是一一对应的,所以在c代码里面才能通过memcpy的方式拷贝过来。

 

随后的if语句针对老内核,对boot_params.hdrcmd_line_ptr字段做些调整,我们就不管他了。

抱歉!评论已关闭.