1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#![allow(dead_code)]

use tracing::error;

use crate::cpu;

const EXIT_FAILURE: u32 = 0; // since ((0 << 1) | 1) = 1.
const EXIT_SUCCESS: u32 = 1; // since ((1 << 1) | 1) = 3.

const IO_BASE: u16 = 0xf4;

pub enum ExitStatus {
    Success,
    Failure,
    Custom(u32),
}

pub fn exit(status: ExitStatus) -> ! {
    let code = match status {
        ExitStatus::Success => EXIT_SUCCESS,
        ExitStatus::Failure => EXIT_FAILURE,
        ExitStatus::Custom(code) => code,
    };

    unsafe {
        cpu::io_out(IO_BASE, code);
    }

    error!("Qemu did not exit, halting.");

    // If we didn't exit, just halt
    loop {
        unsafe {
            cpu::clear_interrupts();
            // this will never wake up, we disabled interrupt, (except maybe NMI?)
            cpu::halt();
        }
    }
}