summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/boot/limine
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/boot/limine')
-rw-r--r--arch/x86_64/boot/limine/framebuffer.c49
1 files changed, 20 insertions, 29 deletions
diff --git a/arch/x86_64/boot/limine/framebuffer.c b/arch/x86_64/boot/limine/framebuffer.c
index 85c3f43..637a7fc 100644
--- a/arch/x86_64/boot/limine/framebuffer.c
+++ b/arch/x86_64/boot/limine/framebuffer.c
@@ -14,47 +14,38 @@
#define FRAMEBUFFER_MAX_HUGEPAGES ((FRAMEBUFFER_MAX_PAGES + 511) / 512)
#define FRAMEBUFFER_MAX_GIANTPAGES ((FRAMEBUFFER_MAX_HUGEPAGES + 511) / 512)
-PAGEALIGN static page_t fb_pml2[FRAMEBUFFER_MAX_GIANTPAGES][512];
-PAGEALIGN static page_t fb_pml1[FRAMEBUFFER_MAX_HUGEPAGES][512];
+PAGEALIGN static page_t fb_pages[FRAMEBUFFER_MAX_GIANTPAGES + FRAMEBUFFER_MAX_HUGEPAGES][512];
-extern page_t _kernel_pml3[512];
+extern page_t _kernel_pml4[512];
void*
fb_remap(uintptr_t fb_address,
size_t fb_bytes)
{
- memset(fb_pml2, 0, 0x1000 * FRAMEBUFFER_MAX_GIANTPAGES);
- memset(fb_pml1, 0, 0x1000 * FRAMEBUFFER_MAX_HUGEPAGES);
-
fb_address &= ~IDENT_VIRT_BASE;
- size_t fb_pages = (fb_bytes + 4095) >> 12;
- size_t fb_hugepages = (fb_pages + 511) >> 9;
- size_t fb_giantpages = (fb_hugepages + 511) >> 9;
+ size_t fb_numpages = (fb_bytes + 4095) >> 12;
- if(fb_pages > FRAMEBUFFER_MAX_PAGES) {
+ if(fb_numpages > FRAMEBUFFER_MAX_PAGES) {
kprintf("Framebuffer is too big! Please recompile the kernel with a bigger framebuffer allowance!");
return NULL;
}
- for(size_t pml2 = 0; pml2 < fb_giantpages; pml2++) {
- uintptr_t fb_pml2_pptr = KPTR_TOPHYS(&fb_pml2[pml2]);
- _kernel_pml3[pml2].value = fb_pml2_pptr | PAGE_PRESENT | PAGE_GLOBAL | PAGE_WRITEABLE;
- }
-
- for(size_t pml1 = 0; pml1 < fb_hugepages; pml1++) {
- size_t pml2 = pml1 >> 9;
- size_t pml1_mod = pml1 % 512;
- uintptr_t pml1_pptr = KPTR_TOPHYS(&fb_pml1[pml1]);
- fb_pml2[pml2][pml1_mod].value = pml1_pptr | PAGE_PRESENT | PAGE_GLOBAL | PAGE_WRITEABLE;
- }
-
- for(size_t pml0 = 0; pml0 < fb_pages; pml0++) {
- size_t pml1 = pml0 >> 9;
- size_t pml0_mod = pml0 % 512;
- uintptr_t pml0_pptr = fb_address + (pml0 << 12);
- fb_pml1[pml1][pml0_mod].value = pml0_pptr | PAGE_PRESENT | PAGE_GLOBAL | PAGE_WRITEABLE | PAGE_WRITETHROUGH | PAGE_XD;
+ uintptr_t vptr = IDENT_VIRT_BASE | (511ULL << PMLI_SHL(3));
+ size_t last_table = 0;
+ for(size_t page = 0; page < fb_numpages; page++) {
+ uintptr_t frame = fb_address + (page << 12);
+ uintptr_t frame_virt = vptr + (page << 12);
+
+ int tblres = 0;
+ do {
+ uintptr_t tbl_frame = KPTR_TOPHYS(&fb_pages[last_table++]);
+ tblres = pagedir_map_table(_kernel_pml4, tbl_frame, frame_virt);
+ if(tblres == EHASMAP) last_table--;
+ } while(tblres == 0);
+
+ pagedir_map_frame(_kernel_pml4, frame, frame_virt,
+ PAGE_GLOBAL | PAGE_WRITEABLE | PAGE_XD);
}
- uintptr_t fb_virt = IDENT_VIRT_BASE | (511ULL << PMLI_SHL(3));
- return (void*)fb_virt;
+ return (void*)vptr;
}