Start work on x86_64 platform
This commit is contained in:
parent
20a954716e
commit
e51f3e4db2
101
cpu/x86_64/boot.asm
Normal file
101
cpu/x86_64/boot.asm
Normal 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
16
cpu/x86_64/linker.ld
Normal file
@ -0,0 +1,16 @@
|
||||
ENTRY(start)
|
||||
|
||||
SECTIONS {
|
||||
. = 1M;
|
||||
|
||||
.boot :
|
||||
{
|
||||
/* ensure that the multiboot header is at the beginning */
|
||||
*(.multiboot_header)
|
||||
}
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text)
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
timeout=0
|
||||
|
||||
menuentry "My OS" {
|
||||
multiboot /boot/kernel.elf
|
||||
multiboot2 /boot/kernel.elf
|
||||
module /boot/initrd initrd
|
||||
boot
|
||||
}
|
||||
|
295
kernel/kernel.c
295
kernel/kernel.c
@ -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(;;);
|
||||
}
|
||||
|
@ -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
1
psinfo/x86_64/ar.txt
Normal file
@ -0,0 +1 @@
|
||||
/Users/peterterpstra/x86_64-elf/bin/x86_64-elf-ar
|
1
psinfo/x86_64/as.txt
Normal file
1
psinfo/x86_64/as.txt
Normal file
@ -0,0 +1 @@
|
||||
/Users/peterterpstra/x86_64-elf/bin/x86_64-elf-as
|
1
psinfo/x86_64/cc.txt
Normal file
1
psinfo/x86_64/cc.txt
Normal file
@ -0,0 +1 @@
|
||||
/Users/peterterpstra/x86_64-elf/bin/x86_64-elf-gcc
|
1
psinfo/x86_64/emu.txt
Normal file
1
psinfo/x86_64/emu.txt
Normal file
@ -0,0 +1 @@
|
||||
qemu-system-x86_64
|
1
psinfo/x86_64/gdb.txt
Normal file
1
psinfo/x86_64/gdb.txt
Normal file
@ -0,0 +1 @@
|
||||
/Users/peterterpstra/x86_64-elf/bin/x86_64-elf-gdb
|
1
psinfo/x86_64/nasm.txt
Normal file
1
psinfo/x86_64/nasm.txt
Normal file
@ -0,0 +1 @@
|
||||
nasm -felf64
|
Loading…
x
Reference in New Issue
Block a user