OSDev.org

The Place to Start for Operating System Developers
It is currently Mon Mar 18, 2024 9:07 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 13 posts ] 
Author Message
 Post subject: Problem with Bootboot and kernel
PostPosted: Thu Jan 05, 2023 4:40 am 
Offline

Joined: Wed Feb 11, 2009 3:39 am
Posts: 8
Hello, I have a problem with BootBoot bootloader and modified kernel for 64 bit intel, from udemy.com course.
Bootboot is known to pass a physical address of the display framebuffer to the kernel.
When paging and virtual memory management is enabled I can no longer locate the display framebuffer address.
Normal because with active paging it is necessary to translate from physical address to virtual address.
In an .H file there are these macros:

#define PTE_P 1
#define PTE_W 2
#define PTE_U 4
#define PTE_ENTRY 0x80
#define KERNEL_BASE 0xffff800000000000
#define PAGE_SIZE (2*1024*1024)

#define PA_UP(v) ((((uint64_t)v + PAGE_SIZE-1) >> 21) << 21)
#define PA_DOWN(v) (((uint64_t)v >> 21) << 21)
#define P2V(p) ((uint64_t)(p) + KERNEL_BASE)
#define V2P(v) ((uint64_t)(v) - KERNEL_BASE)
#define PDE_ADDR(p) (((uint64_t)p >> 12) << 12)
#define PTE_ADDR(p) (((uint64_t)p >> 21) << 21)


how can i locate the frame buffer pointer when paging is set ?

Thanks


Top
 Profile  
 
 Post subject: Re: Problem with Bootboot and kernel
PostPosted: Thu Jan 05, 2023 11:47 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5069
According to the documentation, the framebuffer will be mapped either at the virtual address you specified for the "fb" symbol or at virtual address 0xFFFFFFFFFC000000. You're free to map it elsewhere once you set up your own page tables.


Top
 Profile  
 
 Post subject: Re: Problem with Bootboot and kernel
PostPosted: Thu Jan 05, 2023 12:05 pm 
Offline

Joined: Wed Feb 11, 2009 3:39 am
Posts: 8
thanks for the reply, based on the macros i posted how could i then do this xhe hwi recommended ? could you write an example?


thank you


Top
 Profile  
 
 Post subject: Re: Problem with Bootboot and kernel
PostPosted: Thu Jan 05, 2023 12:28 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5069
If you're looking for examples of how to access the framebuffer before switching to your own page tables, you can find them here.

Accessing it after you switch to your own page tables works the same as accessing any other memory.


Top
 Profile  
 
 Post subject: Re: Problem with Bootboot and kernel
PostPosted: Fri Jan 06, 2023 3:27 pm 
Offline

Joined: Wed Feb 11, 2009 3:39 am
Posts: 8
Hi, I tried in every way but I can't access the framebuffer when the pages are enabled.

Among other things, there is a parameter of the bootboot structure (FB_PTR) to be used to replace FB.
But unfortunately as soon as we call the patient initialization function, it no longer views anything.

thank you


Top
 Profile  
 
 Post subject: Re: Problem with Bootboot and kernel
PostPosted: Fri Jan 06, 2023 3:34 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5069
miky wrote:
Hi, I tried in every way but I can't access the framebuffer when the pages are enabled.

Paging is always enabled in 64-bit mode.

miky wrote:
But unfortunately as soon as we call the patient initialization function, it no longer views anything.

What does your paging initialization function do? If it doesn't assign a virtual address for the framebuffer, you won't be able to access the framebuffer.


Top
 Profile  
 
 Post subject: Re: Problem with Bootboot and kernel
PostPosted: Sat Jan 07, 2023 3:43 pm 
Offline

Joined: Wed Feb 11, 2009 3:39 am
Posts: 8
This i the file memory.c:



Code:
#include "memory.h"
#include "print.h"
#include "debug.h"
#include "lib.h"
#include "stddef.h"
#include "stdbool.h"

static void free_region(uint64_t v, uint64_t e);

static struct FreeMemRegion free_mem_region[50];
static struct Page free_memory;
static uint64_t memory_end;
static uint64_t total_mem;
extern char end;

void init_memory(void)
{
    int32_t count = *(int32_t*)0x20000;
    struct E820 *mem_map = (struct E820*)0x20008;   
    int free_region_count = 0;

    ASSERT(count <= 50);

   for(int32_t i = 0; i < count; i++) {       
        if(mem_map[i].type == 1) {         
            free_mem_region[free_region_count].address = mem_map[i].address;
            free_mem_region[free_region_count].length = mem_map[i].length;
            total_mem += mem_map[i].length;
            free_region_count++;
        }
        //printk("%x  %uKB  %u\n",mem_map[i].address,mem_map[i].length/1024,(uint64_t)mem_map[i].type);
   }

    for (int i = 0; i < free_region_count; i++) {                 
        uint64_t vstart = P2V(free_mem_region[i].address);
        uint64_t vend = vstart + free_mem_region[i].length;

        if (vstart > (uint64_t)&end) {
            free_region(vstart, vend);
        }
        else if (vend > (uint64_t)&end) {
            free_region((uint64_t)&end, vend);
        }       
    }
   
    memory_end = (uint64_t)free_memory.next + PAGE_SIZE;   
}

uint64_t get_total_memory(void)
{
    return total_mem/1024/1024;
}

static void free_region(uint64_t v, uint64_t e)
{
    for (uint64_t start = PA_UP(v); start+PAGE_SIZE <= e; start += PAGE_SIZE) {       
        if (start+PAGE_SIZE <= 0xffff800030000000) {           
           kfree(start);
        }
    }
}

void kfree(uint64_t v)
{
    ASSERT(v % PAGE_SIZE == 0);
    ASSERT(v >= (uint64_t) & end);
    ASSERT(v+PAGE_SIZE <= 0xffff800030000000);

    struct Page *page_address = (struct Page*)v;
    page_address->next = free_memory.next;
    free_memory.next = page_address;
}

void* kalloc(void)
{
    struct Page *page_address = free_memory.next;

    if (page_address != NULL) {
        ASSERT((uint64_t)page_address % PAGE_SIZE == 0);
        ASSERT((uint64_t)page_address >= (uint64_t)&end);
        ASSERT((uint64_t)page_address+PAGE_SIZE <= 0xffff800030000000);

        free_memory.next = page_address->next;           
    }

    return page_address;
}

static PDPTR find_pml4t_entry(uint64_t map, uint64_t v, int alloc, uint32_t attribute)
{
    PDPTR *map_entry = (PDPTR*)map;
    PDPTR pdptr = NULL;
    unsigned int index = (v >> 39) & 0x1FF;

    if ((uint64_t)map_entry[index] & PTE_P) {
        pdptr = (PDPTR)P2V(PDE_ADDR(map_entry[index]));       
    }
    else if (alloc == 1) {
        pdptr = (PDPTR)kalloc();         
        if (pdptr != NULL) {     
            memset(pdptr, 0, PAGE_SIZE);     
            map_entry[index] = (PDPTR)(V2P(pdptr) | attribute);           
        }
    }

    return pdptr;   
}

static PD find_pdpt_entry(uint64_t map, uint64_t v, int alloc, uint32_t attribute)
{
    PDPTR pdptr = NULL;
    PD pd = NULL;
    unsigned int index = (v >> 30) & 0x1FF;

    pdptr = find_pml4t_entry(map, v, alloc, attribute);
    if (pdptr == NULL)
        return NULL;
       
    if ((uint64_t)pdptr[index] & PTE_P) {     
        pd = (PD)P2V(PDE_ADDR(pdptr[index]));     
    }
    else if (alloc == 1) {
        pd = (PD)kalloc(); 
        if (pd != NULL) {   
            memset(pd, 0, PAGE_SIZE);       
            pdptr[index] = (PD)(V2P(pd) | attribute);
        }
    }

    return pd;
}

bool map_pages(uint64_t map, uint64_t v, uint64_t e, uint64_t pa, uint32_t attribute)
{
    uint64_t vstart = PA_DOWN(v);
    uint64_t vend = PA_UP(e);
    PD pd = NULL;
    unsigned int index;

    ASSERT(v < e);
    ASSERT(pa % PAGE_SIZE == 0);
    ASSERT(pa+vend-vstart <= 1024*1024*1024);

    do {
        pd = find_pdpt_entry(map, vstart, 1, attribute);   
        if (pd == NULL) {
            return false;
        }

        index = (vstart >> 21) & 0x1FF;
        ASSERT(((uint64_t)pd[index] & PTE_P) == 0);

        pd[index] = (PDE)(pa | attribute | PTE_ENTRY);

        vstart += PAGE_SIZE;
        pa += PAGE_SIZE;
    } while (vstart + PAGE_SIZE <= vend);
 
    return true;
}

void switch_vm(uint64_t map)
{
    load_cr3(V2P(map));   
}

uint64_t setup_kvm(void)
{
    uint64_t page_map = (uint64_t)kalloc();

    if (page_map != 0) {
        memset((void*)page_map, 0, PAGE_SIZE);       
        if (!map_pages(page_map, KERNEL_BASE, P2V(0x40000000), V2P(KERNEL_BASE), PTE_P|PTE_W)) {
            free_vm(page_map);
            page_map = 0;
        }
    }
    return page_map;
}

void init_kvm(void)
{
    uint64_t page_map = setup_kvm();
    ASSERT(page_map != 0);
    switch_vm(page_map);
    //printk("memory manager is working now");
}

bool setup_uvm(uint64_t map, uint64_t start, int size)
{
    bool status = false;
    void *page = kalloc();

    if (page != NULL) {
        memset(page, 0, PAGE_SIZE);
        status = map_pages(map, 0x400000, 0x400000+PAGE_SIZE, V2P(page), PTE_P|PTE_W|PTE_U);
        if (status == true) {
            memcpy(page, (void*)start, size);
        }
        else {
            kfree((uint64_t)page);
            free_vm(map);
        }
    }
   
    return status;
}

void free_pages(uint64_t map, uint64_t vstart, uint64_t vend)
{
    unsigned int index;

    ASSERT(vstart % PAGE_SIZE == 0);
    ASSERT(vend % PAGE_SIZE == 0);

    do {
        PD pd = find_pdpt_entry(map, vstart, 0, 0);

        if (pd != NULL) {
            index = (vstart >> 21) & 0x1FF;
            if (pd[index] & PTE_P) {       
                kfree(P2V(PTE_ADDR(pd[index])));
                pd[index] = 0;
            }
        }

        vstart += PAGE_SIZE;
    } while (vstart+PAGE_SIZE <= vend);
}

static void free_pdt(uint64_t map)
{
    PDPTR *map_entry = (PDPTR*)map;

    for (int i = 0; i < 512; i++) {
        if ((uint64_t)map_entry[i] & PTE_P) {           
            PD *pdptr = (PD*)P2V(PDE_ADDR(map_entry[i]));
           
            for (int j = 0; j < 512; j++) {
                if ((uint64_t)pdptr[j] & PTE_P) {
                    kfree(P2V(PDE_ADDR(pdptr[j])));
                    pdptr[j] = 0;
                }
            }
        }
    }
}

static void free_pdpt(uint64_t map)
{
    PDPTR *map_entry = (PDPTR*)map;

    for (int i = 0; i < 512; i++) {
        if ((uint64_t)map_entry[i] & PTE_P) {         
            kfree(P2V(PDE_ADDR(map_entry[i])));
            map_entry[i] = 0;
        }
    }
}

static void free_pml4t(uint64_t map)
{
    kfree(map);
}

void free_vm(uint64_t map)
{   
    free_pages(map, 0x400000, 0x400000+PAGE_SIZE);
    free_pdt(map);
    free_pdpt(map);
    free_pml4t(map);
}

bool copy_uvm(uint64_t dst_map, uint64_t src_map, int size)
{
    bool status = false;
    unsigned int index;
    PD pd = NULL;
    uint64_t start;

    void *page = kalloc();
    if (page != NULL) {
        memset(page, 0, PAGE_SIZE);
        status = map_pages(dst_map, 0x400000, 0x400000+PAGE_SIZE, V2P(page), PTE_P|PTE_W|PTE_U);

        if (status == true) {
            pd = find_pdpt_entry(src_map, 0x400000, 0, 0);
            if (pd == NULL) {
                free_vm(dst_map);
                return false;
            }

            index = (0x400000U >> 21) & 0x1FF;
            ASSERT(((uint64_t)pd[index] & PTE_P) == 1);
            start = P2V(PTE_ADDR(pd[index]));
            memcpy(page, (void*)start, size);
        }
        else {
            kfree((uint64_t)page);
            free_vm(dst_map);
        }
    }

    return status;
}


Top
 Profile  
 
 Post subject: Re: Problem with Bootboot and kernel
PostPosted: Sat Jan 07, 2023 3:46 pm 
Offline

Joined: Wed Feb 11, 2009 3:39 am
Posts: 8
and the file memory.h:

Code:
#ifndef _MEMORY_H_
#define _MEMORY_H_

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

struct E820 {
    uint64_t address;
    uint64_t length;
    uint32_t type;
} __attribute__((packed));

struct FreeMemRegion {
    uint64_t address;
    uint64_t length;
};

struct Page {
    struct Page* next;
};

typedef uint64_t PDE;
typedef PDE* PD;
typedef PD* PDPTR;

#define PTE_P 1
#define PTE_W 2
#define PTE_U 4
#define PTE_ENTRY 0x80
//#define KERNEL_BASE 0xffff800000000000
#define KERNEL_BASE 0xffffffffffe00000
#define PAGE_SIZE (2*1024*1024)

#define PA_UP(v) ((((uint64_t)v + PAGE_SIZE-1) >> 21) << 21)
#define PA_DOWN(v) (((uint64_t)v >> 21) << 21)
#define P2V(p) ((uint64_t)(p) + KERNEL_BASE)
#define V2P(v) ((uint64_t)(v) - KERNEL_BASE)
#define PDE_ADDR(p) (((uint64_t)p >> 12) << 12)
#define PTE_ADDR(p) (((uint64_t)p >> 21) << 21)

void* kalloc(void);
void kfree(uint64_t v);
void init_memory(void);
void init_kvm(void);
bool map_pages(uint64_t map, uint64_t v, uint64_t e, uint64_t pa, uint32_t attribute);
void switch_vm(uint64_t map);
void load_cr3(uint64_t map);
void free_vm(uint64_t map);
void free_page(uint64_t map, uint64_t v, uint64_t e);
bool setup_uvm(uint64_t map, uint64_t start, int size);
uint64_t setup_kvm(void);
uint64_t get_total_memory(void);
bool copy_uvm(uint64_t dst_map, uint64_t src_map, int size);


#endif


Top
 Profile  
 
 Post subject: Re: Problem with Bootboot and kernel
PostPosted: Sat Jan 07, 2023 6:07 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5069
Your code doesn't assign a virtual address to the framebuffer.


Top
 Profile  
 
 Post subject: Re: Problem with Bootboot and kernel
PostPosted: Sun Jan 08, 2023 12:53 am 
Offline

Joined: Wed Feb 11, 2009 3:39 am
Posts: 8
You can writer an example ?

Thanks


Top
 Profile  
 
 Post subject: Re: Problem with Bootboot and kernel
PostPosted: Sun Jan 08, 2023 1:06 am 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5069
Something like this?

Code:
map_pages(map, fb_virtual_address, fb_virtual_address + fb_size, fb_physical_address, PTE_P|PTE_W);


Top
 Profile  
 
 Post subject: Re: Problem with Bootboot and kernel
PostPosted: Sun Jan 08, 2023 1:15 am 
Offline

Joined: Wed Feb 11, 2009 3:39 am
Posts: 8
Very good thanks


Top
 Profile  
 
 Post subject: Re: Problem with Bootboot and kernel
PostPosted: Wed Jan 18, 2023 4:04 am 
Offline

Joined: Wed Jan 18, 2023 3:39 am
Posts: 1
Octocontrabass, the page with examples helped me figure it out, by the way I had a similar situation, so thanks.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Gigasoft, Google [Bot] and 15 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group