Start work on x86_64 platform

This commit is contained in:
pjht 2019-04-22 13:18:27 -05:00
parent 20a954716e
commit e51f3e4db2
11 changed files with 273 additions and 148 deletions

101
cpu/x86_64/boot.asm Normal file
View File

@ -0,0 +1,101 @@
section .multiboot_header
header_start:
dd 0xe85250d6 ; magic number (multiboot 2)
dd 0 ; architecture 0 (protected mode i386)
dd header_end - header_start ; header length
; checksum
dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start))
; insert optional multiboot tags here
; required end tag
dw 0 ; type
dw 0 ; flags
dd 8 ; size
header_end:
global start
section .text
bits 32
start:
mov esp, stack_top
call check_multiboot
call check_cpuid
call check_long_mode
; print `OK` to screen
mov dword [0xb8000], 0x2f4b2f4f
hlt
check_multiboot:
cmp eax, 0x36d76289
jne .no_multiboot
ret
.no_multiboot:
mov al, "0"
jmp error
check_cpuid:
; Check if CPUID is supported by attempting to flip the ID bit (bit 21)
; in the FLAGS register. If we can flip it, CPUID is available.
; Copy FLAGS in to EAX via stack
pushfd
pop eax
; Copy to ECX as well for comparing later on
mov ecx, eax
; Flip the ID bit
xor eax, 1 << 21
; Copy EAX to FLAGS via the stack
push eax
popfd
; Copy FLAGS back to EAX (with the flipped bit if CPUID is supported)
pushfd
pop eax
; Restore FLAGS from the old version stored in ECX (i.e. flipping the
; ID bit back if it was ever flipped).
push ecx
popfd
; Compare EAX and ECX. If they are equal then that means the bit
; wasn't flipped, and CPUID isn't supported.
cmp eax, ecx
je .no_cpuid
ret
.no_cpuid:
mov al, "1"
jmp error
check_long_mode:
; test if extended processor info in available
mov eax, 0x80000000 ; implicit argument for cpuid
cpuid ; get highest supported argument
cmp eax, 0x80000001 ; it needs to be at least 0x80000001
jb .no_long_mode ; if it's less, the CPU is too old for long mode
; use extended info to test if long mode is available
mov eax, 0x80000001 ; argument for extended processor info
cpuid ; returns various feature bits in ecx and edx
test edx, 1 << 29 ; test if the LM-bit is set in the D-register
jz .no_long_mode ; If it's not set, there is no long mode
ret
.no_long_mode:
mov al, "2"
jmp error
error:
mov dword [0xb8000], 0x4f524f45
mov dword [0xb8004], 0x4f3a4f52
mov dword [0xb8008], 0x4f204f20
mov byte [0xb800a], al
hlt
section .bss
stack_bottom:
resb 16*4096
stack_top:

16
cpu/x86_64/linker.ld Normal file
View File

@ -0,0 +1,16 @@
ENTRY(start)
SECTIONS {
. = 1M;
.boot :
{
/* ensure that the multiboot header is at the beginning */
*(.multiboot_header)
}
.text :
{
*(.text)
}
}

View File

@ -1,7 +1,7 @@
timeout=0
menuentry "My OS" {
multiboot /boot/kernel.elf
multiboot2 /boot/kernel.elf
module /boot/initrd initrd
boot
}

View File

@ -1,150 +1,151 @@
#include "../cpu/cpu_init.h"
#include "../drivers/vga.h"
#include "../drivers/pci.h"
#include "../drivers/serial.h"
#include "../cpu/i386/ports.h"
#include "vfs.h"
#include "../fs/devfs.h"
#include "../fs/initrd.h"
#include <grub/text_fb_info.h>
#include <stdlib.h>
#include <tasking.h>
#include <string.h>
#include <memory.h>
// #include "../cpu/cpu_init.h"
// #include "../drivers/vga.h"
// #include "../drivers/pci.h"
// #include "../drivers/serial.h"
// #include "../cpu/i386/ports.h"
// #include "vfs.h"
// #include "../fs/devfs.h"
// #include "../fs/initrd.h"
// #include <grub/text_fb_info.h>
// #include <stdlib.h>
// #include <tasking.h>
// #include <string.h>
// #include <memory.h>
#include <grub/multiboot.h>
#include "klog.h"
#include "elf.h"
#include <errno.h>
#include "../drivers/ide.h"
#include "parts.h"
#include "../fs/ext2.h"
static long initrd_sz;
static char* initrd;
static multiboot_info_t* mbd;
typedef int (*func_ptr)();
static int console_dev_drv(char* filename,int c,long pos,char wr) {
if (wr) {
if (c=='\f') {
vga_clear();
} else if (c=='\b') {
vga_backspace();
}
char str[2];
str[0]=(char)c;
str[1]='\0';
vga_write_string(str);
return 0;
} else {
return 0;
// return devbuf_get(kbd_buf);
}
}
static int initrd_dev_drv(char* filename,int c,long pos,char wr) {
if (wr) {
return 0;
}
if (pos>=initrd_sz) {
return EOF;
}
return initrd[pos];
}
static void read_initrd(multiboot_info_t* mbd) {
if ((mbd->flags&MULTIBOOT_INFO_MODS)!=0) {
uint32_t mods_count=mbd->mods_count;
if (mods_count>0) {
while (mods_count>0) {
multiboot_module_t* mods_addr=(multiboot_module_t*)(mbd->mods_addr+0xC0000000);
if (strcmp((char*)(mods_addr->cmdline+0xC0000000),"initrd")==0) {
initrd=malloc(sizeof(char)*(mods_addr->mod_end-mods_addr->mod_start));
initrd_sz=(mods_addr->mod_end-mods_addr->mod_start);
memcpy(initrd,(void*)mods_addr->mod_start+0xC0000000,initrd_sz);
};
mods_count--;
}
}
} else {
klog("PANIC","Cannnot load initrd. No modules found!");
for(;;) {}
}
if (!initrd) {
klog("PANIC","Cannnot load initrd. Initrd module not found!");
for(;;) {}
}
}
static void init() {
init_vfs();
init_devfs();
devfs_add(console_dev_drv,"console");
stdout=fopen("/dev/console","w");
stdin=fopen("/dev/console","r");
stderr=fopen("/dev/console","w");
read_initrd(mbd);
devfs_add(initrd_dev_drv,"initrd");
initrd_init();
mount("/initrd/","","initrd");
// Detect PCI
port_long_out(0xCF8,(1<<31));
uint32_t word=port_long_in(0xCFC);
port_long_out(0xCF8,(1<<31)|0x4);
if (word!=port_long_in(0xCFC)) {
// pci_init();
}
// Detect and initailize serial ports
serial_init();
FILE* file=fopen("/initrd/prog.elf","r");
elf_header header;
fread(&header,sizeof(elf_header),1,file);
if (header.magic!=ELF_MAGIC) {
klog("INFO","Invalid magic number for prog.elf");
fclose(file);
} else {
fseek(file,header.prog_hdr,SEEK_SET);
elf_pheader pheader;
fread(&pheader,sizeof(elf_pheader),1,file);
alloc_memory_virt(1,(void*)pheader.vaddr);
fseek(file,pheader.offset,SEEK_SET);
fread((void*)pheader.vaddr,pheader.filesz,1,file);
klog("INFO","VADDR:%x",pheader.vaddr);
func_ptr prog=(func_ptr)header.entry;
int val=prog();
klog("INFO","RAN PROG:%d",val);
}
ide_init();
load_parts("/dev/hda");
init_ext2();
mount("/","/dev/hda1","ext2");
klog("INFO","MOUNT");
FILE* f=fopen("/file","r");
char str[256];
fgets(str,256,f);
str[strlen(str)-1]='\0';
klog("INFO","Got string %s",str);
for(;;) {
yield();
}
}
// #include "klog.h"
// #include "elf.h"
// #include <errno.h>
// #include "../drivers/ide.h"
// #include "parts.h"
// #include "../fs/ext2.h"
//
// static long initrd_sz;
// static char* initrd;
// static multiboot_info_t* mbd;
// typedef int (*func_ptr)();
//
// static int console_dev_drv(char* filename,int c,long pos,char wr) {
// if (wr) {
// if (c=='\f') {
// vga_clear();
// } else if (c=='\b') {
// vga_backspace();
// }
// char str[2];
// str[0]=(char)c;
// str[1]='\0';
// vga_write_string(str);
// return 0;
// } else {
// return 0;
// // return devbuf_get(kbd_buf);
// }
// }
//
// static int initrd_dev_drv(char* filename,int c,long pos,char wr) {
// if (wr) {
// return 0;
// }
// if (pos>=initrd_sz) {
// return EOF;
// }
// return initrd[pos];
// }
//
// static void read_initrd(multiboot_info_t* mbd) {
// if ((mbd->flags&MULTIBOOT_INFO_MODS)!=0) {
// uint32_t mods_count=mbd->mods_count;
// if (mods_count>0) {
// while (mods_count>0) {
// multiboot_module_t* mods_addr=(multiboot_module_t*)(mbd->mods_addr+0xC0000000);
// if (strcmp((char*)(mods_addr->cmdline+0xC0000000),"initrd")==0) {
// initrd=malloc(sizeof(char)*(mods_addr->mod_end-mods_addr->mod_start));
// initrd_sz=(mods_addr->mod_end-mods_addr->mod_start);
// memcpy(initrd,(void*)mods_addr->mod_start+0xC0000000,initrd_sz);
// };
// mods_count--;
// }
// }
// } else {
// klog("PANIC","Cannnot load initrd. No modules found!");
// for(;;) {}
// }
// if (!initrd) {
// klog("PANIC","Cannnot load initrd. Initrd module not found!");
// for(;;) {}
// }
// }
//
// static void init() {
// init_vfs();
// init_devfs();
// devfs_add(console_dev_drv,"console");
// stdout=fopen("/dev/console","w");
// stdin=fopen("/dev/console","r");
// stderr=fopen("/dev/console","w");
// read_initrd(mbd);
// devfs_add(initrd_dev_drv,"initrd");
// initrd_init();
// mount("/initrd/","","initrd");
// // Detect PCI
// port_long_out(0xCF8,(1<<31));
// uint32_t word=port_long_in(0xCFC);
// port_long_out(0xCF8,(1<<31)|0x4);
// if (word!=port_long_in(0xCFC)) {
// // pci_init();
// }
// // Detect and initailize serial ports
// serial_init();
// FILE* file=fopen("/initrd/prog.elf","r");
// elf_header header;
// fread(&header,sizeof(elf_header),1,file);
// if (header.magic!=ELF_MAGIC) {
// klog("INFO","Invalid magic number for prog.elf");
// fclose(file);
// } else {
// fseek(file,header.prog_hdr,SEEK_SET);
// elf_pheader pheader;
// fread(&pheader,sizeof(elf_pheader),1,file);
// alloc_memory_virt(1,(void*)pheader.vaddr);
// fseek(file,pheader.offset,SEEK_SET);
// fread((void*)pheader.vaddr,pheader.filesz,1,file);
// klog("INFO","VADDR:%x",pheader.vaddr);
// func_ptr prog=(func_ptr)header.entry;
// int val=prog();
// klog("INFO","RAN PROG:%d",val);
// }
// ide_init();
// load_parts("/dev/hda");
// init_ext2();
// mount("/","/dev/hda1","ext2");
// klog("INFO","MOUNT");
// FILE* f=fopen("/file","r");
// char str[256];
// fgets(str,256,f);
// str[strlen(str)-1]='\0';
// klog("INFO","Got string %s",str);
// for(;;) {
// yield();
// }
// }
//
void kmain(multiboot_info_t* header) {
mbd=header;
cpu_init(mbd);
text_fb_info info;
if (header->flags&MULTIBOOT_INFO_FRAMEBUFFER_INFO&&header->framebuffer_type==2) {
info.address=(char*)(((uint32_t)header->framebuffer_addr&0xFFFFFFFF)+0xC0000000);
info.width=header->framebuffer_width;
info.height=header->framebuffer_height;
} else {
info.address=(char*)0xC00B8000;
info.width=80;
info.height=25;
}
vga_init(info);
createTask(init);
for (;;) {
yield();
}
// mbd=header;
// cpu_init(mbd);
// text_fb_info info;
// if (header->flags&MULTIBOOT_INFO_FRAMEBUFFER_INFO&&header->framebuffer_type==2) {
// info.address=(char*)(((uint32_t)header->framebuffer_addr&0xFFFFFFFF)+0xC0000000);
// info.width=header->framebuffer_width;
// info.height=header->framebuffer_height;
// } else {
// info.address=(char*)0xC00B8000;
// info.width=80;
// info.height=25;
// }
// vga_init(info);
// createTask(init);
// for (;;) {
// yield();
// }
for(;;);
}

View File

@ -5,6 +5,7 @@ CC = i386-elf-gcc
prog.elf: $(OBJ)
i386-elf-ld -o $@ $^
rm -rf *.o
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@

1
psinfo/x86_64/ar.txt Normal file
View File

@ -0,0 +1 @@
/Users/peterterpstra/x86_64-elf/bin/x86_64-elf-ar

1
psinfo/x86_64/as.txt Normal file
View File

@ -0,0 +1 @@
/Users/peterterpstra/x86_64-elf/bin/x86_64-elf-as

1
psinfo/x86_64/cc.txt Normal file
View File

@ -0,0 +1 @@
/Users/peterterpstra/x86_64-elf/bin/x86_64-elf-gcc

1
psinfo/x86_64/emu.txt Normal file
View File

@ -0,0 +1 @@
qemu-system-x86_64

1
psinfo/x86_64/gdb.txt Normal file
View File

@ -0,0 +1 @@
/Users/peterterpstra/x86_64-elf/bin/x86_64-elf-gdb

1
psinfo/x86_64/nasm.txt Normal file
View File

@ -0,0 +1 @@
nasm -felf64