Problem with Bootboot and kernel
Problem with Bootboot and kernel
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
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
-
- Member
- Posts: 5562
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Problem with Bootboot and kernel
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.
Re: Problem with Bootboot and kernel
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
thank you
-
- Member
- Posts: 5562
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Problem with Bootboot and kernel
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.
Accessing it after you switch to your own page tables works the same as accessing any other memory.
Re: Problem with Bootboot and kernel
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
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
-
- Member
- Posts: 5562
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Problem with Bootboot and kernel
Paging is always enabled in 64-bit mode.miky wrote:Hi, I tried in every way but I can't access the framebuffer when the pages are enabled.
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.miky wrote:But unfortunately as soon as we call the patient initialization function, it no longer views anything.
Re: Problem with Bootboot and kernel
This i the file memory.c:
Code: Select all
#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;
}
Re: Problem with Bootboot and kernel
and the file memory.h:
Code: Select all
#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
-
- Member
- Posts: 5562
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Problem with Bootboot and kernel
Your code doesn't assign a virtual address to the framebuffer.
Re: Problem with Bootboot and kernel
You can writer an example ?
Thanks
Thanks
-
- Member
- Posts: 5562
- Joined: Mon Mar 25, 2013 7:01 pm
Re: Problem with Bootboot and kernel
Something like this?
Code: Select all
map_pages(map, fb_virtual_address, fb_virtual_address + fb_size, fb_physical_address, PTE_P|PTE_W);
Re: Problem with Bootboot and kernel
Very good thanks
Re: Problem with Bootboot and kernel
Octocontrabass, the page with examples helped me figure it out, by the way I had a similar situation, so thanks.