Limine Bare Bones: Difference between revisions

no edit summary
[unchecked revision][unchecked revision]
No edit summary
No edit summary
Line 9:
The Limine boot protocol is firmware and architecture agnostic. The Limine bootloader supports x86-64, IA-32, aarch64, and riscv64.
 
This article will demonstrate how to write a small Limine-compliant x86-64 higher half Limine-compliant kernel in (GNU) [[C]], and boot it using the [[Limine]] bootloader.
 
It is also very recommended to check out [https://github.com/limine-bootloader/limine-c-template this template project] as it provides example buildable code to go along with this guide.
Line 16:
 
For this example, we will create these 2 files to create the basic directory tree of our project:
* src/kernelmain.c
* linker.ld
 
Line 25:
Obviously, this is just a bare bones example, and one should always refer to the [https://github.com/limine-bootloader/limine/blob/trunk/PROTOCOL.md Limine protocol specification] for more details and information.
 
===src/kernelmain.c===
 
This is the kernel "main".
Line 35:
#include <limine.h>
 
// Set the base revision to 12, this is recommended as this is the latest
// base revision described by the Limine boot protocol specification.
// See specification for further info.
 
__attribute__((used, section(".requests")))
static volatile LIMINE_BASE_REVISION(12);
 
// The Limine requests can be placed anywhere, but it is important that
// the compiler does not optimise them away, so, usually, they should
// be made volatile or equivalent, _and_ they should be accessed at least
// once or marked as used with the "used" attribute as done here.
// once.
 
__attribute__((used, section(".requests")))
static volatile struct limine_framebuffer_request framebuffer_request = {
.id = LIMINE_FRAMEBUFFER_REQUEST,
.revision = 0
};
 
// Finally, define the start and end markers for the Limine requests.
// These can also be moved anywhere, to any .c file, as seen fit.
 
__attribute__((used, section(".requests_start_marker")))
static volatile LIMINE_REQUESTS_START_MARKER;
 
__attribute__((used, section(".requests_end_marker")))
static volatile LIMINE_REQUESTS_END_MARKER;
 
// GCC and Clang reserve the right to generate calls to the following
Line 136 ⟶ 147:
// Note: we assume the framebuffer model is RGB with 32-bit pixels.
for (size_t i = 0; i < 100; i++) {
volatile uint32_t *fb_ptr = framebuffer->address;
fb_ptr[i * (framebuffer->pitch / 4) + i] = 0xffffff;
}
Line 162 ⟶ 173:
PHDRS
{
text requests PT_LOAD FLAGS((1 << 01) | (1 << 2)) ; /* ExecuteWrite + Read */
rodatatext PT_LOAD FLAGS((1 << 2)0) ; | (1 << 2)) ; /* ReadExecute only+ Read */
data rodata PT_LOAD FLAGS((1 << 12)) |; (1 << 2)) ; /* WriteRead + Readonly */
dynamicdata PT_LOAD PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDRWrite for+ relocationsRead */
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDR for relocations */
}
 
Line 175 ⟶ 187:
/* that is the beginning of the region. */
. = 0xffffffff80000000;
 
/* Define a section to contain the Limine requests and assign it to its own PHDR */
.requests : {
*(.requests_start_marker)
*(.requests)
*(.requests_end_marker)
} :requests
 
/* Move to the next memory page for .text */
. += CONSTANT(MAXPAGESIZE);
 
.text : {
Anonymous user