Search code examples
assemblyx86kernelgnu-assemblergrub

How to pass parameters to Kernel using GRUB 0.97 menu.lst?


I'm working on an OS and I have to create a debug mode. In order to do this, I want to add an entry in menu.lst, pointing to the same kernel, but with an added argument.

In the GRUB manual, it's written that everything after kernel's address in the kernel command is passed verbatim to the kernel command line: https://ftp.gnu.org/old-gnu/Manuals/grub/html_node/kernel.html

So I did something like this in menu.lst:

title   os-debug
    root (fd0)
    kernel /kernel 001
    module /initrd.img

In the stack created by GRUB, the command-line is available at offset 16, as stated here: https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Specification

So in my file boot.S I did like this to find my parameter in the stack:

movl 16(%ebx), %ecx

And... It doesn't work (I created a gdbserver in order to debug this specific boot file), but I'm sure I can access the stack correctly , because I'm accessing initrd like this:

movl 24(%ebx), %eax

I have also correctly defined my flags:

#define MBOOT_FLAGS (MBOOT_PAGE_ALIGN | MBOOT_MEMORY_INFO | 
MBOOT_INFO_CMDLINE)'

Any idea how can i get a parameter to be passed from menu.lst to boot.S? Here's all the beginning of my boot.S file:

/* Multiboot flags. */
 #define MBOOT_FLAGS (MBOOT_PAGE_ALIGN | MBOOT_MEMORY_INFO | 
 MBOOT_INFO_CMDLINE)

 /* Exported symbols. */
 .globl start
 .globl idle_pgdir

 .section .bootstrap

/*
* Grub multiboot header.
*/
.align 4
mboot_header:
    .long  MBOOT_MAGIC                  /* Magic number.              */
    .long  MBOOT_FLAGS                  /* Flags.                     */
    .long  -(MBOOT_MAGIC + MBOOT_FLAGS) /* Checksum.                  */
    .long  mboot_header                 /* Pointer to this structure. */


/*
* Kernel entry point.
*/
start:  
    cmpl $1, 20(%ebx)
    jne halt

    /* Retrieve initrd location. */
    movl 24(%ebx), %eax
    movl (%eax), %eax

    movl 16(%ebx), %ecx
    pushl %ecx

after, the init RAM is built so I have to process with my stack before, but I'm not able to have my argument at this point considering my tests

My menu.lst:

timeout 10

title   OS
    root (fd0)
    kernel /kernel
    module /initrd.img

title   OS-debug
    root (fd0)
    kernel /kernel 001
    module /initrd.img

Solution

  • I'd like to answer my own question to explain why my model was not working. The model of Michael Petch works correctly, but in my implementation I had a different problem

    The GRUB 0.97 documentation contains an error: https://ftp.gnu.org/old-gnu/Manuals/grub/html_node/kernel.html

    The rest of the line is passed verbatim as the kernel command-line.

    It's not "the rest of the line" but instead "the whole line", in my case: kernel /kernel 001

    So, I wasn't checking enough memory, and so I always had "rek" as an output, which was corresponding to the first 3 char. I resolved my issue with this assembly code:

    /* Retrieve command-line passed by GRUB. */
    movl $cmdline, %edi
    movl 16(%ebx), %ecx
    addl $MBOOT_KPARAM_OFFSET, %ecx
    jmp bottom
    top:
        addl $4, %ecx 
        stosl
    bottom:
        movl (%ecx), %eax
        cmpl $0,%eax
        jne top 
    

    Where #define MBOOT_KPARAM_OFFSET 0x00000008, which is corresponding to the offset needed to shift "kernel /kernel ". The rest of the code is then used to put a parameter in the memory, no matter of its size (using %edi and stosl)