2009年6月21日日曜日

init_heap

今回はmain関数の中で「copy_boot_params」の次に呼び出している「init_heap」を見てみます。

====
static void init_heap(void)
{
char *stack_end;

  /* ヒープを使うかどうか */
if (boot_params.hdr.loadflags & CAN_USE_HEAP) {
asm("leal %P1(%%esp),%0"
   : "=r" (stack_end) : "i" (-STACK_SIZE));

/* ヒープのオフセットリミットをheap_end_ptr に格納する */
heap_end = (char *)
((size_t)boot_params.hdr.heap_end_ptr + 0x200);
if (heap_end > stack_end)
heap_end = stack_end;
} else {
/* ブートプロトコル2.0以前のものはヒープを用意できない */
puts("WARNING: Ancient bootloader, some functionality "
    "may be limited!¥n");
}
}
====

boot_params.hdr.loadflagsの値を見てヒープを使うかどうかを判定しています。
ブートプロトコルが2.02以降ならば基本的にif文の内側に入ってきます。
if文の内側ではヒープのオフセットリミットをheap_end_ptrメンバに格納しています。
boot_params.hdrは前回見たcopy_boot_paramsにてコピーして来たものです。
bott_params.hdrは「setup_header」という構造体でbootparam.hで定義しています。

arch/x86/include/asm/bootparam.h
====
struct setup_header {
__u8 setup_sects;
__u16 root_flags;
__u32 syssize;
__u16 ram_size;
#define RAMDISK_IMAGE_START_MASK 0x07FF
#define RAMDISK_PROMPT_FLAG 0x8000
#define RAMDISK_LOAD_FLAG 0x4000
__u16 vid_mode;
__u16 root_dev;
__u16 boot_flag;
__u16 jump;
__u32 header;
__u16 version;
__u32 realmode_swtch;
__u16 start_sys;
__u16 kernel_version;
__u8 type_of_loader;
__u8 loadflags;
#define LOADED_HIGH (1<<0)
#define QUIET_FLAG (1<<5)
#define KEEP_SEGMENTS (1<<6)
#define CAN_USE_HEAP (1<<7)
__u16 setup_move_size;
__u32 code32_start;
__u32 ramdisk_image;
__u32 ramdisk_size;
__u32 bootsect_kludge;
__u16 heap_end_ptr;
__u16 _pad1;
__u32 cmd_line_ptr;
__u32 initrd_addr_max;
__u32 kernel_alignment;
__u8 relocatable_kernel;
__u8 _pad2[3];
__u32 cmdline_size;
__u32 hardware_subarch;
__u64 hardware_subarch_data;
__u32 payload_offset;
__u32 payload_length;
__u64 setup_data;
} __attribute__((packed));
=====

でかい。
前回も見たheader.Sの中での「hdr」のアドレス部分からの抜粋を下記に。

=====
hdr:
setup_sects: .byte SETUPSECTS
root_flags: .word ROOT_RDONLY
syssize: .long SYSSIZE
ram_size: .word RAMDISK
vid_mode: .word SVGA_MODE
root_dev: .word ROOT_DEV
boot_flag: .word 0xAA55
=====

先述の構造体の「boot_flag」までがここまでと対応しています。
さらにheader.Sを見て行きましょう。

====
.globl _start
_start:

...(省略)...

start_sys_seg: .word SYSSEG
.word kernel_version-512 # pointing to kernel version string
# above section of header is compatible
# with loadlin-1.5 (header v1.5). Don't
# change it.

type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin,
#      Bootlin, SYSLX, bootsect...)
# See Documentation/i386/boot.txt for
# assigned ids

# flags, unused bits must be zero (RFU) bit within loadflags
loadflags:
LOADED_HIGH = 1 # If set, the kernel is loaded high
CAN_USE_HEAP = 0x80 # If set, the loader also has set
# heap_end_ptr to tell how much
# space behind setup.S can be used for
# heap purposes.
# Only the loader knows what is free

...(省略)...

payload_offset: .long input_data
payload_length: .long input_data_end-input_data

setup_data: .quad 0 # 64-bit physical pointer to
# single linked list of
# struct setup_data

====

長いので一部省略していますが、構造体定義と照らし合わせてみれば最後まで値が入ってくることが分かります。

0 件のコメント:

コメントを投稿