Linux i386 Boot Code HOWTO
Prev |  | Next

# C. GRUB and LILO

Both GNU GRUB and LILO understand the real-mode kernel header format and will load the bootsect (one sector), setup code (setup_sects sectors) and compressed kernel image (syssize*16 bytes) into memory. They fill out the loader identifier (type_of_loader) and try to pass appropriate parameters and options to the kernel. After they finish their jobs, control is passed to setup code.

## C.1. GNU GRUB

The following GNU GRUB program outline is based on grub-0.93.

    stage2/stage2.c:cmain()
    `-- run_menu()
        `-- run_script();
            |-- builtin = find_command(heap);
            |-- kernel_func();              // builtin->func() for command "kernel"
            |   `-- load_image();           // search BOOTSEC_SIGNATURE in boot.c
            |   /* memory from 0x100000 is populated by and in the order of
            |    *   (bvmlinux, bbootsect, bsetup) or (vmlinux, bootsect, setup) */
            |-- initrd_func();              // for command "initrd"
            |   `-- load_initrd();
            `-- boot_func();                // for implicit command "boot"
                `-- linux_boot();           // defined in stage2/asm.S
                    or big_linux_boot();    //   not in grub/asmstub.c!

    // In stage2/asm.S
    linux_boot:
            /* copy kernel */
            move system code from 0x100000 to 0x10000 (linux_text_len bytes);
    big_linux_boot:
            /* copy the real mode part */
            EBX = linux_data_real_addr;
            move setup code from linux_data_tmp_addr (0x100000+text_len)
                to linux_data_real_addr (0x9100 bytes);
            /* change %ebx to the segment address */
            linux_setup_seg = (EBX >> 4) + 0x20;
            /* XXX new stack pointer in safe area for calling functions */
            ESP = 0x4000;
            stop_floppy();
            /* final setup for linux boot */
            prot_to_real();
            cli;
            SS:ESP = BX:9000;
            DS = ES = FS = GS = BX;
            /* jump to start, i.e. ljmp linux_setup_seg:0
             * Note that linux_setup_seg is just changed to BX. */
            .byte   0xea
            .word   0
    linux_setup_seg:
            .word   0

Refer to "info grub" for GRUB manual.

One reported GNU GRUB bug should be noted if you are porting grub-0.93 and making changes to bsetup.

## C.2. LILO

Unlike GRUB, LILO does not check the configuration file when booting system. Tricks happen when lilo is invoked from terminal.

The following LILO program outline is based on lilo-22.5.8.

    lilo.c:main()
    |-- cfg_open(config_file);
    |-- cfg_parse(cf_options);
    |-- bsect_open(boot_dev, map_file, install, delay, timeout);
    |   |-- open_bsect(boot_dev);
    |   `-- map_create(map_file);
    |-- cfg_parse(cf_top)
    |   `-- cfg_do_set();
    |       `-- do_image();             // walk->action for "image=" section
    |           |-- cfg_parse(cf_image) -> cfg_do_set();
    |           |-- bsect_common(&descr, 1);
    |           |   |-- map_begin_section();
    |           |   |-- map_add_sector(fallback_buf);
    |           |   `-- map_add_sector(options);
    |           |-- boot_image(name, &descr) or boot_device(name, range, &descr);
    |           |   |-- int fd = geo_open(&descr, name, O_RDONLY);
    |           |   |   read(fd, &buff, SECTOR_SIZE);
    |           |   |   map_add(&geo, 0, image_sectors);
    |           |   |   map_end_section(&descr->start, setup_sects+2+1);
    |           |   |       /* two sectors created in bsect_common(),
    |           |   |        *   another one sector for bootsect */
    |           |   |   geo_close(&geo);
    |           |   `-- fd = geo_open(&descr, initrd, O_RDONLY);
    |           |       map_begin_section();
    |           |       map_add(&geo, 0, initrd_sectors);
    |           |       map_end_section(&descr->initrd,0);
    |           |       geo_close(&geo);
    |           `-- bsect_done(name, &descr);
    `-- bsect_update(backup_file, force_backup, 0); // update boot sector
        |-- make_backup();
        |-- map_begin_section();
        |   map_add_sector(table);
        |   map_write(&param2, keytab, 0, 0);
        |   map_close(&param2, here2);
        |-- // ... perform the relocation of the boot sector
        |-- // ... setup bsect_wr to correct place
        |-- write(fd, bsect_wr, SECTOR_SIZE);
        `-- close(fd);

map_add(), map_add_sector() and map_add_zero() may call map_register() to complete their jobs, while map_register() will keep a list for all (CX, DX, AL) triplets (data structure SECTOR_ADDR) used to identify all registered sectors.

LILO runs `first.S` and `second.S` to boot a system. It calls second.S:doboot() to load map file, bootsect and setup code. Then it calls lfile() to load the system code, calls launch2() -> launch() -> cl_wait() -> start_setup() -> start_setup2() and finnaly executes "jmpi 0,SETUPSEG" instruction to run setup code.

Refer to "man lilo" and "man lilo.conf" for LILO details.

## C.3. Reference

- GNU GRUB

- GRUB Tutorial

- LILO (freshmeat.net)

- LDP HOWTO-INDEX: Boot Loaders and Booting the OS

Prev | Home | Next
Internal Linker Script |  | FAQ