use core::alloc::{GlobalAlloc, Layout};
use core::ptr::{self, NonNull};
use crate::prelude::*;
use crate::table::boot::{BootServices, MemoryType};
static mut BOOT_SERVICES: Option<NonNull<BootServices>> = None;
pub unsafe fn init(boot_services: &BootServices) {
BOOT_SERVICES = NonNull::new(boot_services as *const _ as *mut _);
}
fn boot_services() -> NonNull<BootServices> {
unsafe { BOOT_SERVICES.expect("Boot services are unavailable or have been exited") }
}
pub fn exit_boot_services() {
unsafe {
BOOT_SERVICES = None;
}
}
pub struct Allocator;
#[allow(clippy::cast_ptr_alignment)]
unsafe impl GlobalAlloc for Allocator {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let mem_ty = MemoryType::LOADER_DATA;
let size = layout.size();
let align = layout.align();
if align > 8 {
let ptr = if let Ok(ptr) = boot_services()
.as_ref()
.allocate_pool(mem_ty, size + align)
.warning_as_error()
{
ptr
} else {
return ptr::null_mut();
};
let mut offset = ptr.align_offset(align);
if offset == 0 {
offset = align;
}
let return_ptr = ptr.add(offset);
(return_ptr as *mut *mut u8).sub(1).write(ptr);
return_ptr
} else {
boot_services()
.as_ref()
.allocate_pool(mem_ty, size)
.warning_as_error()
.unwrap_or(ptr::null_mut())
}
}
unsafe fn dealloc(&self, mut ptr: *mut u8, layout: Layout) {
if layout.align() > 8 {
ptr = (ptr as *const *mut u8).sub(1).read();
}
boot_services()
.as_ref()
.free_pool(ptr)
.warning_as_error()
.unwrap();
}
}
#[global_allocator]
static ALLOCATOR: Allocator = Allocator;