How to use kernel functions on early stage?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
cyberfined
Posts: 6
Joined: Sat Dec 03, 2022 7:54 am

How to use kernel functions on early stage?

Post by cyberfined »

Hello everyone. I have written higher half kernel for x86_64 UEFI platform with GRUB as a bootloader. It works, but I have one problem. I can't use printk function from the kernel on the early stage that creates new page tables to move kernel to the higher half, because it is counting on it runs on the higher half. My question: is there a good way to use printk from the kernel or copy its content and relink with address on which the early stage executes? Or should i just copy all the code to another .c file, rename printk in it to something like early_printk and use early_printk on the early stage?
nullplan
Member
Member
Posts: 1867
Joined: Wed Aug 30, 2017 8:24 am

Re: How to use kernel functions on early stage?

Post by nullplan »

I have separated the pre-paging part of the kernel into its own executable, partially because of issues like this. Now the debug code can be linked into both of them as needed. It is not a drain on resources as the pre-paging part can just be freed once the main kernel is running.
Carpe diem!
cyberfined
Posts: 6
Joined: Sat Dec 03, 2022 7:54 am

Re: How to use kernel functions on early stage?

Post by cyberfined »

Yes, I though about that, I just hope there is a simpler way to do it. Because it means to write my own ELF loader, it's not hard, but still takes time. It seems I have to do it. Thank you!
nullplan
Member
Member
Posts: 1867
Joined: Wed Aug 30, 2017 8:24 am

Re: How to use kernel functions on early stage?

Post by nullplan »

Not necessarily. The pre-paging executable can just contain exactly the code you have now, and then the main kernel as a data item (in .rodata). Or, since you say you are booting with GRUB, GRUB supports loading modules, so you can get GRUB to load the pre-paging stuff as main kernel and the main kernel as module. That is actually how I implement legacy booting with GRUB.
Carpe diem!
cyberfined
Posts: 6
Joined: Sat Dec 03, 2022 7:54 am

Re: How to use kernel functions on early stage?

Post by cyberfined »

A solution with main kernel as a module sounds interesting, I try to implement it
thewrongchristian
Member
Member
Posts: 442
Joined: Tue Apr 03, 2018 2:44 am

Re: How to use kernel functions on early stage?

Post by thewrongchristian »

cyberfined wrote: Sun Apr 06, 2025 5:09 am A solution with main kernel as a module sounds interesting, I try to implement it
I find it easier to just have a single kernel image, but with different sections linked to different base addresses.

I have a .bootstrap_code, .bootstrap_data, .bootstrap_stack and .bootstrap_pgtbl (he latter two are page sized/aligned), and the bootstrap environment that sets up the kernel runtime page table for higher half operation is linked and run in the lower half of memory accessible to the bootloader.

Then I just have regular .text, .data etc sections for my kernel, which are linked into the higher half at the kernel runtime address. Once the bootstrap code has setup the initial runtime page table, I jump to the kernel proper.

As an added benefit, because the bootstrap code and data are page sized and aligned, I can just reuse their pages in the pool of free pages, they're no longer used after bootstrap.

Linker script fragment:

Code: Select all

	/* Begin putting sections at 1 MiB, a conventional place for kernels to be
	   loaded at by the bootloader. */
	. = 1M;
	_bootstrap_start = .; 

	/* First put the multiboot header, as it is required to be put very early
	   early in the image or the bootloader won't recognize the file format. */
	.bootstrap :
	{
		*(.bootstrap_data)
		*(.bootstrap_code)
	}
	.bootstrap_aligned ALIGN(4K) :
	{
		*(.bootstrap_stack)
		*(.bootstrap_pgtbl)
	}

	/* Rest of the kernel lives in high memory */
	_kernel_offset_bootstrap = .;
	. += kernel_offset;
	_kernel_offset = .;

	/* Next we'll put the .text section. */
	.text ALIGN(4K) : AT(ADDR(.text) - kernel_offset)
	{
		code_start = .;
		*(.text)
		code_end = .;
	}
Post Reply