~cypheon/xos

666e83dc8928b3ec9831d91515bdb4d183e7d25f — Johann Rudloff 7 years ago 54853d7
Add memory map detection in bootloader.
3 files changed, 116 insertions(+), 29 deletions(-)

M boot1.asm
M kernel.c
M kmem.c
M boot1.asm => boot1.asm +81 -27
@@ 4,10 4,17 @@ global pread_sector

extern boot2_main

%define BIOS_MEMDETECT_MAGIC 0x534d4150
%define MMAP_BASE 0x1000

start:
  mov si, hallo
  call print

  push dword MMAP_BASE
  call near detect_memory
  add esp, 4

  ; hide cursor
  mov ah, 0x01
  mov cx, 0x2607


@@ 15,9 22,80 @@ start:

  jmp enter_protected

idle:
  hlt
  jmp idle
hallo: db 'xos boot loader stage 1 ...', 0xa, 0xd, 0

print:
  mov ah, 0x0e
.repeat:
  lodsb
  cmp al, 0
  je .done
  int 0x10
  jmp .repeat
.done:
  ret

enter_protected:
  cli
  lgdt [gdt_desc]

  mov eax, cr0
  or al, 1
  mov cr0, eax

  jmp 0x08:protected_main

detect_memory:
  mov di, [esp + 2] ; mmap base
  add di, 4 ; first dword reserved for count
  xor ebp, ebp ; valid entries counter

  xor ebx, ebx

  call .e820
  jc .failed

  ; first call checks:
  cmp eax, BIOS_MEMDETECT_MAGIC
  jne .failed
  test ebx, ebx
  je .failed

.item:
  jcxz .next
  cmp cl, 0x18 ; extended record?
  jb .normal
.extended:
  test [di + 20], byte 1 ; ignored
  je .next
.normal:
  mov ecx, [di + 8]
  or ecx, [di + 12] ; zero length?
  jz .next
  inc bp
  add di, 20

.next:
  test ebx, ebx
  je .finish
  call .e820
  jc .finish
  jmp .item

.failed:
  mov ebp, 0
.finish:
  mov di, [esp+2]
  mov [di], ebp
  ret

.e820
  mov eax, 0xe820
  mov edx, BIOS_MEMDETECT_MAGIC
  mov [di + 20], dword 1
  mov ecx, 24
  int 0x15
  ret

bits 32



@@ 105,30 183,6 @@ pread_sector:

bits 16

hallo: db 'xos boot loader stage 1 ...', 0xa, 0xd, 0

print:
  mov ah, 0x0e
.repeat:
  lodsb
  cmp al, 0
  je .done
  int 0x10
  jmp .repeat
.done:
  ret

enter_protected:
  cli
  lgdt [gdt_desc]

  mov eax, cr0
  or al, 1
  mov cr0, eax

  jmp 0x08:protected_main


gdt_desc:
  dw 0x1f
  dd gdt

M kernel.c => kernel.c +2 -2
@@ 47,13 47,13 @@ static struct proc *launch(const char *binary, uint32_t mem);

void kernel_main() {
  kprint("kernel main entered\n");
  console_init(&global_console);
  setup_gdt();

  kmem_init();
  paging_init();

  setup_gdt();

  console_init(&global_console);
  console_clear(&global_console);
  console_print(&global_console, "xos kernel loaded\n");


M kmem.c => kmem.c +33 -0
@@ 1,10 1,23 @@
#include <sys/console.h>
#include <sys/kernel.h>
#include <sys/memory.h>
#include <sys/paging.h>

#define DEBUG
#include <debug.h>

#define KMEM_ARENA_START 0x200000
#define KMEM_ARENA_END 0x400000

struct detect_mmap_info {
  uint32_t base_low;
  uint32_t base_high;
  uint32_t length_low;
  uint32_t length_high;
  uint16_t type;
  uint16_t pad;
} __attribute__ ((__packed__));

struct kmem {
  void *free; // first free page
};


@@ 15,7 28,11 @@ struct free_info {

static struct kmem kmem_state;

void kmem_detect(void);

void kmem_init(void) {
  kmem_detect();

  // begin with the last page
  void *page = (void *)(KMEM_ARENA_END - PAGE_SIZE);



@@ 32,6 49,22 @@ void kmem_init(void) {
  kmem_state.free = previous;
}

void
kmem_detect(void) {
  uint32_t mmap_count = *(uint32_t *)0x1000;
  struct detect_mmap_info *mmap = (struct detect_mmap_info *)(0x1000 + 4);
  khexprint("mmap count", mmap_count);
  khexprint("mmap size", sizeof(struct detect_mmap_info));
  for (int i=0; i<mmap_count; ++i) {
    khexprint("=========== mmap entry", i);
    khexprint("base_low", mmap[i].base_low);
    khexprint("base_high", mmap[i].base_high);
    khexprint("length_low", mmap[i].length_low);
    khexprint("length_high", mmap[i].length_high);
    khexprint("type", mmap[i].type);
  }
}

void *kmem_alloc_pages(size_t pages) {
  if (pages != 1) {
    panic("can only alloc one page at a time");