Merge pull request #38 from E-Almqvist/memory

Memory
multiboot
Elias Almqvist 3 years ago committed by GitHub
commit 8c7b94116f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      Makefile
  2. 38
      drivers/vga.c
  3. 8
      drivers/vga.h
  4. 23
      kernel/enable_paging.asm
  5. 46
      kernel/kernel.c
  6. 100
      kernel/memory.c
  7. 27
      kernel/memory.h
  8. 24
      kernel/paging.c
  9. 9
      kernel/paging.h
  10. 0
      kernel/sr_memory.asm
  11. 17
      lib/conv.c
  12. 6
      lib/conv.h
  13. 10
      lib/math.c
  14. 3
      lib/math.h
  15. 15
      lib/strf.c
  16. 1
      lib/strf.h
  17. 6
      lib/types.h
  18. 16
      lib/util.c
  19. 4
      lib/util.h

@ -22,7 +22,7 @@ eos_grub.iso : kernel.bin grub/grub.cfg
eos.iso: bootloader/bootloader.bin kernel.bin
cat $^ > eos.iso
kernel.bin: kernel/kernel_entry.o $(OBJ)
kernel.bin: kernel/kernel_entry.o kernel/sr_memory.o kernel/enable_paging.o $(OBJ)
gcc -o $@ $^ -Wl,--oformat=binary -ffreestanding -nostdlib -shared -Ttext 0x1000 -m32

@ -1,31 +1,37 @@
// VGA Graphics Library
#include "vga.h"
#include "../lib/types.h"
#include "../kernel/io.h"
#include "../kernel/memory.h"
#include "../lib/str.h"
#include "../lib/conv.h"
static unsigned int cursor_row = 0;
static unsigned int cursor_col = 0;
static uint cursor_row = 0;
static uint cursor_col = 0;
void vga_init() {
// Allocate VGA memory range
pm_alloc_range(VGA_ADDRESS, VGA_ADDRESS_MAX, true); // force alloc the VGA range
// Disable cursor
port_outb(0x3d4, 0x0a);
port_outb(0x3d5, 0x20);
// Clear screen
// clear_row(0);
// clear_screen();
clear_screen();
set_cursor_pos(0, 11);
set_cursor_pos(0, 0);
}
/*
VGA & Memory Functions
*/
char* get_memory_charpos(unsigned int col, unsigned int row) {
char* get_memory_charpos(uint col, uint row) {
return (char*)(VGA_ADDRESS + 2*((row*80) + col));
}
void writechar(char c, unsigned int col, unsigned int row, int attribute_byte) {
void writechar(char c, uint col, uint row, int attribute_byte) {
if( !attribute_byte )
attribute_byte = DEFAULT_COLOR;
@ -36,7 +42,7 @@ void writechar(char c, unsigned int col, unsigned int row, int attribute_byte) {
}
void set_cursor_pos(unsigned int col, unsigned int row) {
void set_cursor_pos(uint col, uint row) {
cursor_col = col;
cursor_row = row;
}
@ -45,7 +51,7 @@ void set_cursor_pos(unsigned int col, unsigned int row) {
/*
Graphics Functions
*/
void clear_row(unsigned int row) {
void clear_row(uint row) {
for( int c = 0; c < MAX_COLS; c++ )
writechar(0x20, c, row, 0x0);
}
@ -61,7 +67,7 @@ void clear_screen() {
*/
void print(char* str, int attribute_byte) {
for( char* c = str; *c != '\0'; c++ )
writechar(*c, (unsigned int)(c - str) + cursor_col, cursor_row, attribute_byte);
writechar(*c, (uint)(c - str) + cursor_col, cursor_row, attribute_byte);
}
void println(char* str, int attribute_byte) {
@ -69,11 +75,20 @@ void println(char* str, int attribute_byte) {
cursor_row++; // Increment to next y-pos (newline)
}
void printint(int i, int attribute_byte) {
/*
char* strbuf;
strbuf = int_to_str(i, strbuf);
println(strbuf, attribute_byte);
*/
}
void printalign(char* str, int attribute_byte, enum align alignment) {
unsigned int strlenbuf = strlen(str);
uint strlenbuf = strlen(str);
if( !alignment || alignment == LEFT ) {
print(str, attribute_byte);
set_cursor_pos(0, cursor_row);
} else if ( alignment == RIGHT ) {
set_cursor_pos(MAX_COLS - strlenbuf, cursor_row);
} else if ( alignment == MIDDLE ) {
@ -81,4 +96,5 @@ void printalign(char* str, int attribute_byte, enum align alignment) {
}
print(str, attribute_byte);
set_cursor_pos(0, cursor_row+1);
}

@ -1,7 +1,10 @@
#define VGA_ADDRESS (char*)0xb8000
#define VGA_ADDRESS_MAX (char*)0xb8fa0
#define VGA_ADDRESS 0xb8000
#define VGA_ADDRESS_MAX 0xb8fa0
#define DEFAULT_COLOR 0x07
#define URGET_COLOR 0x0c
#define SUCCESS_COLOR 0x0a
#define MAX_ROWS 25
#define MAX_COLS 80
@ -17,5 +20,6 @@ void clear_row(unsigned int row);
void set_cursor_pos();
void print();
void println();
void printint(int i, int attribute_byte);
void printalign(char* str, int attribute_byte, enum align alignment);
void vga_init();

@ -0,0 +1,23 @@
[bits 32] ; 32-bit mode
PAGING_ENABLE_FLAG equ 0x80000001
PAGE_DIRECTORY_ADDR equ 0xffffffff ; TODO: change me to something good
global enable_paging_registers ; make the SR "global" so that we can access it in the kernel etc
enable_paging_registers:
push eax
mov eax, PAGE_DIRECTORY_ADDR ; Move the address of the
; page register (page directory) into eax
; (Using eax as a middle-man register)
mov cr3, eax ; Put the address into the cr3 register (required by the MMU)
mov eax, cr0 ; eax as a middle-man register (again)
or eax, PAGING_ENABLE_FLAG ; perform the OR operation on eax (ex: 0b01 or 0b10 = 0b11)
; This is needed to enable paging (set the flag as "enabled")
mov cr0, eax ; Move it into cr0 to finally enable paging
pop eax
ret ; return to last location

@ -1,23 +1,20 @@
#include "kernel.h"
#include "memory.h"
#include "paging.h"
#include "../drivers/vga.h"
#include "../lib/str.h"
#include "../lib/strf.h"
void display_status(char* status_text, unsigned int bg_color) {
clear_row(0);
set_cursor_pos(0, 0);
print(status_text, bg_color | STATUS_TEXT_COLOR);
}
#include "../lib/conv.h"
void init() {
display_status("Kernel loaded", 0x70);
vga_init(); // Initialize the screen first
// i.e. clear the screen et cetera.
char* title = "eOS Version 0.2 2021";
println("Kernel loaded", SUCCESS_COLOR);
// enable_paging();
println("");
char* title = "eOS Version 0.3 2021";
println(title, DEFAULT_COLOR);
char* subtitle = "A x86 operating system, licenced under GPL-2.0";
@ -28,8 +25,35 @@ void init() {
println("0x1000", DEFAULT_COLOR);
*/
char* intbuf = "xxxx";
int num = 1234;
intbuf = int_to_str(num, intbuf);
print("TEST NUM: ", DEFAULT_COLOR);
println(intbuf, DEFAULT_COLOR);
/*
// Memory allocation testing
printalign("-- PMM Tests --", DEFAULT_COLOR, MIDDLE);
println("THESE ALLOC SHOULD WORK:", 0xa0);
for(int i=0; i < 4; i++) {
block_alloc(i);
}
println("(2) THIS ALLOC SHOULD FAIL:", 0xc0);
block_alloc(2); // this should fail
println("(2) Freeing 2nd block, alloc after should succeed", DEFAULT_COLOR);
block_free(2); // after this, allocation of 2nd block should work
block_alloc(2);
printalign("-- End of PMM Tests --", DEFAULT_COLOR, MIDDLE);
char* strbuf = "Concat test: ";
char* str2 = "Works!";
strbuf = strcat(strbuf, str2);
println(strbuf, DEFAULT_COLOR);
*/
}

@ -1,2 +1,102 @@
#include "memory.h"
#include "../drivers/vga.h"
// https://wiki.osdev.org/Page_Frame_Allocation
// page = block
// MAX_BLOCK_SIZE_IN_BITS/8 bytes
// i.e. : bit i of byte n define status of block 8n+i
// block = 8n+i
// in 32-bit mode, we have access to 2^32 blocks
// which is (2^32)*BLOCK_SIZE blocks
// and with a blocksize of 1024, we git around 4.3 trillion blocks
// which is more than enough
#define CHECK_BITMAP(map, idx) ((map) & (1<<(idx)))
#define BLOCK_TO_MEMP(idx) (pointer)(PM_MEM_START + (idx*BLOCK_SIZE))
#define MEMP_TO_BLOCK(memp) (uint)((memp - PM_MEM_START)/BLOCK_SIZE)
static int bitmap = 0;
static uint last_block;
void mod_bitmap(uint bit, uint bflag) {
// create a bitmask that will be applied to the bitmap
int bitmask = 1 << bit;
// apply the bitmask, resulting in the bit:n bit will set
// set to bflag
bitmap = (((bitmap & ~bitmask)) | (bflag << bit));
}
pointer block_alloc(uint blockidx) {
int block_bflag;
block_bflag = CHECK_BITMAP(bitmap, blockidx);
if( block_bflag == BM_FREE ) { // check if block is free
println("Allocating block...", DEFAULT_COLOR);
mod_bitmap(blockidx, 1);
last_block = blockidx;
return BLOCK_TO_MEMP(blockidx);
} else {
println("[ERROR] Attemped to allocate non-free block.", 0x0c);
return 0;
}
}
void block_free(uint blockidx) {
println("Dealloc block...", DEFAULT_COLOR);
mod_bitmap(blockidx, BM_FREE);
last_block = blockidx;
}
uint find_free(uint block_count) {
// TODO: find a free start block to allocate
// loop through bitmap
// check if range is free
}
bool check_block_range(uint start, uint end) {
bool allowed = true;
uint idx;
for(idx = start; idx <= end; idx++) {
if( CHECK_BITMAP(bitmap, idx) != BM_FREE )
allowed = false;
break;
}
return allowed;
}
void pm_alloc_range(ulong start, ulong end, bool force) {
uint idx_start;
uint idx_end;
ulong d_addr = end - start; // memory size
uint num_blocks = (d_addr/BLOCK_SIZE) + 1; // amount of blocks to be allocated
uint start_block = MEMP_TO_BLOCK(start); // start idx, end = start_block + num_blocks - 1
bool allowed = true && check_block_range(start_block, start_block + num_blocks - 1);
// allocate (if permitted)
if( allowed ) {
uint idx;
for(idx=start_block; idx <= start_block + num_blocks - 1; idx++)
block_alloc(idx);
return;
} else {
println("[ERROR] Tried to allocate memory range without permission!", 0x0c);
return;
}
}
pointer pm_malloc(uint block_count) {
}

@ -1,2 +1,25 @@
char* malloc(unsigned int size);
void mfree(char* p);
#include "../lib/types.h"
#define BLOCK_SIZE 1024 // 1 KiB
#define MAX_BLOCK_COUNT 32 // placeholder
#define MEMSIZE_TO_BLOCKS(n) ((n*1024)/BLOCK_SIZE)
#define BM_FREE 0
#define PM_MEM_START 0x000000 // start of memory
#define PM_MEM_END 0xb7000 // end of memory TODO: fix me/change or something
// void init_pmm(uint map_addr, uint bsize); // Initialize physical memory manager
void mod_bitmap(uint bit, uint flag);
pointer block_alloc(uint blockidx); // allocate a block
void block_free(uint blockidx); // free a block
uint find_free(uint block_count);
bool check_block_range(uint start, uint end);
void pm_alloc_range(ulong start, ulong end, bool force); // allocate a range of memory
pointer pm_malloc(uint block_count); // allocate some blocks
void pm_free(int* p); // free a var (if allocated with pm_malloc)

@ -0,0 +1,24 @@
#include "paging.h"
#include "../drivers/vga.h"
void enable_paging() {
println("Enabling paging...", DEFAULT_COLOR);
// extern int enable_paging_registers(); // Call the assembly SR
// enable_paging_registers(); // and enable paging
return;
}
// Page Entry struct
//struct page_entry {
// unsigned int index;
// unsigned int start_addr;
//} page_table[PAGE_TABLE_SIZE];
//
//int get_phys_addr(int virt_addr) {
// int index = virt_addr / PAGE_SIZE; // page index for the virtual address
// int offset = virt_addr % PAGE_SIZE; // actual physical offset for the address
//
// return page_table[index].start_addr + offset;
//}

@ -0,0 +1,9 @@
#define PAGE_SIZE 100
#define PAGE_TABLE_SIZE 128
void enable_paging();
// struct page_entry;
// char** heap_alloc(unsigned int size); // Process heap allocation
// int get_phys_addr(int virt_addr);

@ -0,0 +1,17 @@
#include "conv.h"
#include "../drivers/vga.h"
char* int_to_str(int i, char* buf) {
ulong num = (ulong)i; // convert to ulong
uint len = ulong_len(num); // number of digits
*(buf+len) = '\0'; // add a "end-of-string" at the end
int j;
for(j = 0; j < len; j++) // iterate over each digit and assign it to the buffer
// super dangerous memory write
println("char!", DEFAULT_COLOR);
*(buf+j) = (char)(ndigit(num, len-1-j) + ASCII_OFFSET); // apply the ascii offset so that i becomes a char
return buf;
}

@ -0,0 +1,6 @@
#include "types.h"
#include "util.h"
#define ASCII_OFFSET 0x30
char* int_to_str(int i, char* buf);

@ -0,0 +1,10 @@
#include "math.h"
long pow(int num, uint expon) {
long prod = 1;
while(expon > 0)
prod *= num;
expon--;
return prod;
}

@ -0,0 +1,3 @@
#include "types.h"
long pow(int, uint);

@ -1,15 +0,0 @@
#include "strf.h"
#define int_offset 48
// 0:48 - 9:57
char* int_to_str(int i, char* strbuf) {
if( i == 0 ) {
return (char*)(int_offset);
} else {
char cbuf;
cbuf = (char)((i % 10) + int_offset);
return int_to_str(i / 10, strbuf + cbuf);
}
}

@ -1 +0,0 @@
char* int_to_str(int i, char* strbuf);

@ -0,0 +1,6 @@
typedef unsigned int uint;
typedef unsigned long ulong;
typedef unsigned long* pointer;
typedef int bool;
#define true 1
#define false 0

@ -0,0 +1,16 @@
#include "util.h"
#include "math.h"
uint ulong_len(ulong n) { // get the digit length of a number
int len = 0;
while (n != 0) {
n = n / 10;
++len;
}
return len;
}
uint ndigit(ulong n, uint i) { // OBS: index order is reversed
long den = pow(10, i);
return (n/den) % 10;
}

@ -0,0 +1,4 @@
#include "types.h"
uint ulong_len(ulong n);
uint ndigit(ulong n, uint i);
Loading…
Cancel
Save