OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 9:44 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: grub can't find multiboot header in a higher-half kernel
PostPosted: Sun May 16, 2021 8:40 am 
Offline
Member
Member
User avatar

Joined: Sun Mar 21, 2021 1:09 pm
Posts: 38
Location: current location
Hello, I have tried to implement a higher-half kernel. For that i used the tutorial in the Wiki. I am not so sure about the cause, but in the hexeditor, it shows that the multiboot header is at address 0x451c and i am assuming that grub cannot find it, because it is not at the front. ( the header is intact ).
Now how do I modify the linker script to put it earlier into my program? Problem is, I even tested the code for the tutorial without my own. even there grub
could not find my header - with one exception: if I delete the tty.c part of the kernel.c file. The disassembly doesn't help either - objdump shows the multiboot header at the front where it should be, at one megabyte. The linker throws no errors. I have "fixed" it one time by putting the header and bootstrap code into the .text section
[code][.text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000)
{
*(.multiboot.data) /* the header*/
*(.multiboot.text)
*(.text)

}/code]
but that just page faulted, which is probably for the better. objdump shows the multiboot header in this case in the linker-specified location, the higher half, but it still worked, because like a miracle, it is now at 0x1000. how do i specify the location of the multiboot header in the linker script?
sorry for my bad english, i'm not a native speaker.

_________________
iustitiae iniustos iudicat


Top
 Profile  
 
 Post subject: Re: grub can't find multiboot header in a higher-half kernel
PostPosted: Sun May 16, 2021 9:00 am 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
acccidiccc wrote:
it shows that the multiboot header is at address 0x451c
Well, I personally don't like Grub, so I'm no expert on it, but shouldn't be the Multiboot header located in the first 8 kilobytes and aligned at 16 bytes? This address 0x451c is above 0x2000 and it ain't paragraph aligned, so no wonder Grub can't find it.

acccidiccc wrote:
Now how do I modify the linker script to put it earlier into my program? Problem is, I even tested the code for the tutorial without my own. even there grub
could not find my header - with one exception: if I delete the tty.c part of the kernel.c file. The disassembly doesn't help either - objdump shows the multiboot header at the front where it should be, at one megabyte.
Link address doesn't matter, only the file offset. Try to use "KEEP()" in the linker script to tell the linker not to rearrange the multiboot section within the file.
Code:
.text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000)
{
KEEP(*(.multiboot.data)) /* the header*/
*(.multiboot.text)
*(.text)

}
Otherwise make sure of it, that the object file which contains the header is the first in the linker's argument list.

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: grub can't find multiboot header in a higher-half kernel
PostPosted: Sun May 16, 2021 10:57 am 
Offline
Member
Member
User avatar

Joined: Sun Mar 21, 2021 1:09 pm
Posts: 38
Location: current location
Hello, Thanks for your Reply. Sadly this did not solve my problem. I just realized that the cause for my problem was that the .text section was placed first in the binary. It is larger than 8K though, which caused the header to be placed at the odd address. the reason that the "solution", that is putting the header in the .text section, worked, is that the multiboot header was the first thing. However the .text section is the section that is called after the jump to the higher half. The full script read
Code:
ENTRY (_start)

SECTIONS
{
        . = 0x00100000;
   /* The kernel will live at 3GB + 1MB in the virtual address space, */
   /* which will be mapped to 1MB in the physical address space. */
   /* Note that we page-align the sections. */

   _kernel_start = .;
        .multiboot.data : {
            *(.multiboot.data)
        }

       .multiboot.text : {
           *(.multiboot.text)
       }

   . += 0xC0000000;
   /* Add a symbol that indicates the start address of the kernel. */
   .text ALIGN (4K) : AT (ADDR (.text) - 0xC0000000)
   {
      *(.text)
   }
   .rodata ALIGN (4K) : AT (ADDR (.rodata) - 0xC0000000)
   {
      *(.rodata)
   }
   .data ALIGN (4K) : AT (ADDR (.data) - 0xC0000000)
   {
      *(.data)
   }
   .bss ALIGN (4K) : AT (ADDR (.bss) - 0xC0000000)
   {
      *(COMMON)
      *(.bss)
      *(.bootstrap_stack)
   }
   /* Add a symbol that indicates the end address of the kernel. */
   _kernel_end = .;
}

putting the header and bootstrap trampoline code into the higher half is obviously a bad idea. The memory probably gets accessed from the loader and page and yadayada. I probably have to swap .text sections. Is there any way to make the .multiboot.data section to be first in terms of offset?

_________________
iustitiae iniustos iudicat


Top
 Profile  
 
 Post subject: Re: grub can't find multiboot header in a higher-half kernel
PostPosted: Sun May 16, 2021 1:12 pm 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
acccidiccc wrote:
I just realized that the cause for my problem was that the .text section was placed first in the binary.
With a linker script, you're in full control of which section comes after another.
acccidiccc wrote:
However the .text section is the section that is called after the jump to the higher half.
Bad idea. Use the entry point, that's what it is for.
acccidiccc wrote:
/* Add a symbol that indicates the start address of the kernel. */
I see no symbol here. (Maybe not needed, just make sure you have an Assembly function called "_start"). Whereever it goes in the text segment, its VMA will be saved in the elf_hdr->e_entry field, use that when you pass control over.
acccidiccc wrote:
putting the header and bootstrap trampoline code into the higher half is obviously a bad idea.
As I've said, it doesn't matter. For the header only the file offset counts, not the link address, VMA is totally indifferent. (There's no such thing, higher half file offset.) When you use "readelf -l", you'll see both, for example:
Code:
LOAD           0x0000000000000e10 0x0000000000600e10 0x0000000000600e10
                      ^file offset       ^Virtual Memory Address
As you can see here 0xe10 != 0x600e10. Furthermore, Multiboot header can be outside of loadable segments, and not loaded into memory in run-time at all.
acccidiccc wrote:
Is there any way to make the .multiboot.data section to be first in terms of offset?
Yes, as I've already said, use the KEEP() pseudo function in the linker script. Also make sure you put it in the first segment (that's probably the text segment and not the data segment), and read about section placement, you'll find useful information there.

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: grub can't find multiboot header in a higher-half kernel
PostPosted: Tue May 18, 2021 11:27 am 
Offline
Member
Member
User avatar

Joined: Sun Mar 21, 2021 1:09 pm
Posts: 38
Location: current location
Thanks again for the response. I've given up trying to combine multiboot and a higher half kernel. Instead I'm now using limine.

_________________
iustitiae iniustos iudicat


Top
 Profile  
 
 Post subject: Re: grub can't find multiboot header in a higher-half kernel
PostPosted: Wed May 19, 2021 11:48 am 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
acccidiccc wrote:
Thanks again for the response. I've given up trying to combine multiboot and a higher half kernel. Instead I'm now using limine.
Your loss. It would worth learning these things you'll probably need linker script features in the future too.

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: grub can't find multiboot header in a higher-half kernel
PostPosted: Thu May 20, 2021 6:59 am 
Offline
Member
Member
User avatar

Joined: Sun Mar 21, 2021 1:09 pm
Posts: 38
Location: current location
I think I actually know more about linker scripts now. I just used the KEEP wrong.
Code:
.text : {
    KEEP(*(.multiboot)
    *(.multiboot)
}

if i am not mistaken, this is the correct form of using it:
Code:
.text : {
     KEEP(*(.multiboot))
}


It's also not like I didn't try. I know why it didn't work; The Grub Multiboot header was easy to fix, the problem later was the entry point.
putting the contents of the multiboot header in the start of .text also worked. The issue was mixing the trampoline code and the later higher half code.
Adding 0xc0000000 to .
Code:
. += 0xc0000000;
didn't work. putting .text into the higher-half would make .multiboot.text the entry point, and
grub didn't like that (entry point isn't a segment)
Code:
.set _start, (_trampoline + 0xc0000000)
also didn't work. So I used the limine bootloader, which didn't really change much for me, except make my life easier, by setting up graphics and stuff. Now I actually understand the things in a linker script.

_________________
iustitiae iniustos iudicat


Top
 Profile  
 
 Post subject: Re: grub can't find multiboot header in a higher-half kernel
PostPosted: Thu May 20, 2021 11:45 am 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
I'd start with ignoring the so-called "higher-half" hack and get your kernel loading first. Once you get it working, you can decide if you want to continue with this hack or not.

I personally don't understand why this forum/wiki encourages people to use such a hack. It's very messy and hard to get right, especially for newbies.

It is far easier to just have a bootloader that will setup virtual memory and load the kernel where you want it directly.

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: grub can't find multiboot header in a higher-half kernel
PostPosted: Thu May 20, 2021 12:19 pm 
Offline
Member
Member

Joined: Wed Aug 30, 2017 8:24 am
Posts: 1593
kzinti wrote:
I personally don't understand why this forum/wiki encourages people to use such a hack. It's very messy and hard to get right, especially for newbies.
Yep. I started to dislike that hack from the very first time I saw it. Mixing physical and virtual addresses like that can only lead to confusion. Thankfully, for AMD64 in legacy boot mode I need a separate loader anyway, and that gave me the idea to separate the part that sets up the initial memory mappings from the rest of the kernel, which I did, and now I'm much happier. This also gives me a buffer between the bootloader and the kernel proper, which I can use to adopt new bootloaders. And, all that code for the initial page table setup, that is entirely useless once it has run (doubly so in the AMD64 case, since that code is for the wrong architecture then), can now be freed completely afterwards, for it is contained in a separate binary.

_________________
Carpe diem!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: DotBot [Bot], Majestic-12 [Bot] and 59 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group