Skip to main content

kernel/arch/x86_64/boot/
entry.rs

1// SPDX-License-Identifier: GPL-3.0-only
2//! x86_64 Boot Entrypoint
3//!
4//! Authors: MarioS271
5
6use crate::knotice;
7use crate::lib::panic::kernel_panic;
8use crate::lib::panic_codes::PanicCode;
9use crate::lib::types::boot_info::{BootInfo, FramebufferInfo, KernelCmdline, KernelSectionInfo};
10use crate::lib::types::fmt_buffer::FmtBuffer;
11use crate::state::simple_state::SIMPLE_STATE;
12use limine::request::{ExecutableAddressRequest, ExecutableCmdlineRequest, FramebufferRequest, HhdmRequest, MemmapRequest, RsdpRequest};
13use limine::BaseRevision;
14
15unsafe extern "C" {
16    /// Symbol which is located at the start of the kernel
17    pub static __kernel_start: u8;
18    /// Symbol which is located at the end of the kernel
19    pub static __kernel_end: u8;
20
21    /// Symbol which is located one byte after the end of the `.text` section
22    pub static __kernel_text_end: u8;
23    /// Symbol which is located one byte after the end of the `.rodata` section
24    pub static __kernel_rodata_end: u8;
25}
26
27#[used]
28pub static LIMINE_BASE_REVISION: BaseRevision = BaseRevision::with_revision(3);
29
30pub static LIMINE_KERNEL_ADDR_REQUEST: ExecutableAddressRequest = ExecutableAddressRequest::new();
31pub static LIMINE_HHDM_REQUEST: HhdmRequest = HhdmRequest::new();
32pub static LIMINE_RSDP_REQUEST: RsdpRequest = RsdpRequest::new();
33pub static LIMINE_CMDLINE_REQUEST: ExecutableCmdlineRequest = ExecutableCmdlineRequest::new();
34pub static LIMINE_FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new();
35pub static LIMINE_MEMMAP_REQUEST: MemmapRequest = MemmapRequest::new();
36
37#[unsafe(no_mangle)]
38pub extern "C" fn kernel_entry() -> ! {
39    // Stage 0
40    crate::state::kstate::KSTATE.init();
41    
42    serial_init();
43
44    knotice!(
45        "Ferrite Kernel {}, on x86_64 booted via limine",
46        env!("CARGO_PKG_VERSION"),
47    );
48
49    let kernel_phys_start = LIMINE_KERNEL_ADDR_REQUEST
50        .response()
51        .map(|r| r.physical_base)
52        .unwrap_or_else(
53            || kernel_panic(
54                PanicCode::InitFailure,
55                "Limine didn't respond to the kernel address request"
56            )
57        );
58
59    let hhdm_offset = LIMINE_HHDM_REQUEST
60        .response()
61        .map(|r| r.offset)
62        .unwrap_or_else(
63            || kernel_panic(
64                PanicCode::InitFailure,
65                "Limine didn't respond to the HHDM offset request"
66            )
67        );
68
69    let rsdp_addr = LIMINE_RSDP_REQUEST
70        .response()
71        .map(|r| r.address as u64);
72
73    let raw_cmdline = LIMINE_CMDLINE_REQUEST
74        .response()
75        .map(|r| r.cmdline())
76        .unwrap_or_else(
77            || kernel_panic(
78                PanicCode::InitFailure,
79                "Limine didn't respond to the cmdline request"
80            )
81        );
82
83    let framebuffer = LIMINE_FRAMEBUFFER_REQUEST
84        .response()
85        .and_then(|r| r.framebuffers().first())
86        .map(|fb| FramebufferInfo {
87            addr: fb.address() as *mut u32,
88            pixels_per_row: fb.pitch / 4,
89            width: fb.width,
90            height: fb.height,
91            bpp: fb.bpp
92        })
93        .unwrap_or_else(
94            || kernel_panic(
95                PanicCode::InitFailure,
96                "Limine didn't respond to the framebuffer request"
97            )
98        );
99
100    let mut cmdline = KernelCmdline::default();
101    if !raw_cmdline.is_empty() {
102        cmdline.parse_in_cmd_line(raw_cmdline);
103    }
104
105    let boot_info = BootInfo {
106        hhdm_offset,
107        rsdp_addr,
108        kernel_sections: KernelSectionInfo {
109            kernel_phys_start,
110            kernel_start: &raw const __kernel_start as u64,
111            kernel_text_end: &raw const __kernel_text_end as u64,
112            kernel_rodata_end: &raw const __kernel_rodata_end as u64,
113            kernel_end: &raw const __kernel_end as u64
114        },
115        cmdline,
116        framebuffer
117    };
118
119    crate::kernel_main(boot_info);
120}
121
122/// Initializes the kernel serial logger
123fn serial_init() {
124    use crate::drivers::tty::uart::{Uart, UartOps};
125
126    // Safety: we are in a non-SMP/non-threading context
127    unsafe {
128        SIMPLE_STATE.init_uart(
129            Uart::com1()
130        );
131    };
132
133    // Safety: uart was correctly initialized above
134    if let Err(err) = unsafe { SIMPLE_STATE.uart().lock().init() } {
135        use core::fmt::Write;
136
137        let mut fmt_buffer = FmtBuffer::<32>::new();
138        let _ = write!(&mut fmt_buffer, "Failed to initialize UART COM1 ({})", err.as_str());
139
140        // this panic will result in a silent halt, this is pretty much unavoidable here
141        kernel_panic(
142            PanicCode::InitFailure,
143            fmt_buffer.as_str()
144        );
145    };
146}