Page 1 of 1

Reading flags from grub when using multiboot 1

Posted: Sat Nov 02, 2024 12:24 pm
by AnotherIdiot
I have been trying to read flags from grub when booting via multiboot one on my project PaybackOS (link is https://github.com/PaybackOS/PaybackOS ) I have tried converting mb_info into a char* then using strstr on it but it has failed, all work I have done so far is on the beta branch. Can anyone please help me with this?

Re: Reading flags from grub when using multiboot 1

Posted: Sat Nov 02, 2024 1:33 pm
by iansjack
Why read it as a char array rather than making use of the fact that it’s a well defined structure?

Re: Reading flags from grub when using multiboot 1

Posted: Sat Nov 02, 2024 2:01 pm
by MichaelPetch
Likely you have been using garbage passed as parameters to `_init`. First you need to fix the issue that the 2 parameters aren't being pushed correctly. You need to set up the stack before you can push `eax` and `ebx`. I may have introduced that problem in a commit long ago but didn't notice it because you weren't using parameters passed to `_init` at the time.

The push of `ESP` before calling `_init` does nothing but put a useless value on the stack. After fixing boot.s you should at least have proper arguments passed to `_init` to process the multiboot structure.

I made a pull request with the fix that issue here: https://github.com/PaybackOS/PaybackOS/pull/22

Re: Reading flags from grub when using multiboot 1

Posted: Sat Nov 02, 2024 2:36 pm
by nullplan
MichaelPetch wrote: Sat Nov 02, 2024 2:01 pm I made a pull request with the fix that issue here: https://github.com/PaybackOS/PaybackOS/pull/22
That version is better than what the OP has now, but strictly speaking it is still undefined behavior. The code is compiled against i686-elf, a platform that uses the SysV ABI, AFAIK. And that ABI has been defining 16 byte stack alignment for 20 years now. That is the alignment you must have before the call instruction, when calling any C function. The initial mov to ESP puts it at a 16 byte alignment, but then pushing only two registers means it is off by 8 bytes. This can be easily remedied by turning the initial mov to ESP into

Code: Select all

movl $stack_top - 8, %esp
Then after the two pushes, the stack pointer is aligned again.

BTW, the call_constructors function also uses undefined behavior. Its code is currently:

Code: Select all

typedef void (*constructor)();
extern "C" constructor start_ctors[];
extern "C" constructor end_ctors[];

// Function to iterate through all global constructors and
// call them. This must be done befor calling _init
extern "C" void call_constructors()
{
    for(constructor* ctor = start_ctors; ctor != end_ctors; ctor++)
        (*ctor)();
}
This is undefined, since ctor is initialized as pointer into one array, and then compared with a pointer to a different array. I would suggest doing something like the following instead:

Code: Select all

extern "C" void call_constructors()
{
    size_t n = ((uintptr_t)end_ctors - (uintptr_t)start_ctors)/(sizeof(constructor));
    for (constructor *ctor = start_ctors; ctor < start_ctors + n; ctor++)
        (*ctor)();
}

Re: Reading flags from grub when using multiboot 1

Posted: Sat Nov 02, 2024 2:40 pm
by MichaelPetch
The 16 byte stack alignment doesn't really apply since his make.config sets compile options that include `-mpreferred-stack-boundary=2 -mgeneral-regs-only`. I added the fix to the undefined behaviour to my pull request.

Re: Reading flags from grub when using multiboot 1

Posted: Mon Nov 04, 2024 2:43 pm
by AnotherIdiot
Thank you to all who helped me, the code fixes from Micheal were just merged, thank you all for your help!