Added emulator options, Added header for VBE driver, Added CPUID function, Added demodisk.img as drive

BasicGraphics
Nigel Barink 2021-07-22 22:14:58 +01:00
parent f2c8b8ac5c
commit 643f2d708b
14 changed files with 236 additions and 145 deletions

1
.gitattributes vendored
View File

@ -1,3 +1,4 @@
*.pdf filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.svg filter=lfs diff=lfs merge=lfs -text
demodisk.img filter=lfs diff=lfs merge=lfs -text

4
.gitignore vendored
View File

@ -1 +1,3 @@
build
build
CON
.vscode

View File

@ -1,16 +0,0 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}

View File

@ -24,7 +24,7 @@ all: clean build
build: build_kernel run
run:
$(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial stdio -vga std
$(EMULATOR) -kernel $(BUILD_DIR)/myos.bin -serial file:CON -vga std -monitor stdio -display gtk -m 2G -cpu core2duo -drive file=demodisk.img
build_kernel: $(OBJ_LINK_LIST)

View File

@ -10,18 +10,17 @@ ________________________
The first scrolling boot screen. 😲
<img src="screenshots/WIP_interruptHandling.png"></img>
![Interrupt handeling](screenshots/WIP_interruptHandling.png) \
W.I.P - Working on interrupt handling
![Multiboot integration](screenshots/multiboot.png) \
Multiboot information can be read by the kernel.
________________________
### The goal
Writing a hobby operating system to better understand the basic building blocks of any operating system.
________________________
### Operating System Technical specs/details
The operating system can print strings to the

View File

BIN
screenshots/multiboot.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -23,6 +23,9 @@ void irs_handler (registers regs) {
printf(" Error code: %d \n", regs.err_code);
}
}

View File

@ -46,6 +46,48 @@ void kterm_putat (char c, uint8_t color, size_t x, size_t y ) {
}
void enable_cursor (uint8_t start_cursor , uint8_t end_cursor ){
outb(0x3D4, 0x0A);
outb(0x3D5, (inb(0x3D5) & 0xC0) | start_cursor);
outb(0x3D4, 0x0B);
outb(0x3D5, (inb(0x3D5) & 0xE0) | end_cursor);
}
void disable_cursor()
{
outb(0x3D4, 0x0A);
outb(0x3D5, 0x20);
}
void update_cursor(int x, int y){
uint16_t pos = y * VGA_WIDTH + x;
outb(0x3D4, 0x0F);
outb(0x3D5, (uint8_t) (pos & 0xFF));
outb(0x3D4, 0x0E);
outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF));
}
uint16_t get_cursor_position(){
uint16_t pos = 0;
outb(0x3D4, 0x0F);
pos |= inb(0x3D5);
outb(0x3D4, 0x0E);
pos |= ((uint16_t) inb(0x3D5)) << 8;
return pos;
}
int get_cursor_x (uint16_t cursor_pos) {
return cursor_pos % VGA_WIDTH;
}
int get_cursor_y (uint16_t cursor_pos ) {
return cursor_pos / VGA_WIDTH;
}
/**
* With the help from:
@ -63,6 +105,7 @@ void kterm_scrollup(){
void kterm_put (char c) {
if(++kterm_column == VGA_WIDTH || c == '\n' ) {
update_cursor(kterm_column , kterm_row);
kterm_column = 0;
if(kterm_row == VGA_HEIGHT-1 ) {
kterm_scrollup();

View File

@ -5,12 +5,14 @@
#include <stdbool.h>
#include "../vga/colors.h"
#include "../../../io.h"
void kterm_init();
/* Kernel terminal - Colour functions*/
void kterm_resetcolor();
void kterm_setcolor(uint8_t);
/* Kernel terminal - Printing function */
void kterm_putat(char, uint8_t, size_t, size_t);
void kterm_put(char);
void kterm_write(const char*, size_t);
@ -18,6 +20,15 @@ void kterm_writestring(const char*);
void kterm_scrollup();
/* Kernel terminal - Cursor functions */
void enable_cursor (uint8_t start_cursor , uint8_t end_cursor );
void disable_cursor();
void update_cursor(int x, int y);
uint16_t get_cursor_position();
int get_cursor_x (uint16_t cursor_pos);
int get_cursor_y (uint16_t cursor_pos);
void printf ( const char *format, ...);
static void itoa (char *buf, int base, int d);

View File

@ -0,0 +1,41 @@
#define VBE_DISPI_IOPORT_INDEX 0x01CE
#define VBE_DISPI_IOPORT_DATA 0x01CF
/* VBE index values*/
#define VBE_DISPI_INDEX_ID 0x0
#define VBE_DISPI_INDEX_XRES 0x1
#define VBE_DISPI_INDEX_YRES 0x2
#define VBE_DISPI_INDEX_BPP 0x3
#define VBE_DISPI_INDEX_ENABLE 0x4
#define VBE_DISPI_INDEX_BANK 0x5
#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
#define VBE_DISPI_INDEX_X_OFFSET 0x8
#define VBE_DISPI_INDEX_Y_OFFSET 0x9
/* BGA Version */
#define VBE_DISPI_ID5 0xB0C5
#define VBE_DISPI_ID4 0xB0C3
#define VBE_DISPI_ID3 0xB0C2
#define VBE_DISPI_ID2 0xB0C1
#define VBE_DISPI_ID1 0xB0C0
/* BGA BIT DEPTH */
#define VBE_DISPI_BPP_4 0x04
#define VBE_DISPI_BPP_8 0x08
#define VBE_DISPI_BPP_15 0x0F
#define VBE_DISPI_BPP_16 0x10
#define VBE_DISPI_BPP_24 0x18
#define VBE_DISPI_BPP_32 0x20
/*unsigned short BGAReadRegister(unsigned short IndexValue){
// outpw(VBE_DISPI_IOPORT_INDEX, IndexValue);
// return inpw (VBE_DISPI_IOPORT_DATA);
}
int BGAIsAvailable (){
return (BGAReadRegister(VBE_DISPI_INDEX_ID) == VBE_DISPI_ID5);
}*/

16
src/kernel/cpu.h Normal file
View File

@ -0,0 +1,16 @@
#include <cpuid.h> // NOTE: Only available in GCC
static int get_model(){
int ebx, unused;
__cpuid(0, unused, ebx, unused, unused);
return ebx;
}
enum {
CPUID_FEAT_EDX_APIC = 1 << 9
};
static int check_apic (){
unsigned int eax, unused, edx;
__get_cpuid(1, &eax, &unused, &unused, &edx);
return edx & CPUID_FEAT_EDX_APIC;
}

View File

@ -1,108 +1,14 @@
#include "kernel.h"
/**
* simple delay function
**/
void delay(int t){
volatile int i,j;
for(i=0;i<t;i++)
for(j=0;j<25000;j++)
asm("NOP");
}
class Test {
public:
Test();
void printMe();
~Test();
};
Test::Test(){
kterm_writestring("Create a test object\n");
};
void Test::printMe(){
kterm_writestring("testObject.printMe()\n");
}
Test::~Test(){
kterm_writestring("Destroy testObject! Bye bye\n");
}
#define PORT 0x3f8
static int init_serial() {
outb(PORT + 1, 0x00); // Disable all interrupts
outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
outb(PORT + 1, 0x00); // (hi byte)
outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip
outb(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
// Check if serial is faulty (i.e: not same byte as sent)
if(inb(PORT + 0) != 0xAE) {
return 1;
}
// If serial is not faulty set it in normal operation mode
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
outb(PORT + 4, 0x0F);
return 0;
}
int is_transmit_empty() {
return inb(PORT + 5) & 0x20;
}
void write_serial(char a) {
while (is_transmit_empty() == 0);
outb(PORT,a);
}
int serial_received() {
return inb(PORT + 5) & 1;
}
char read_serial() {
while (serial_received() == 0);
return inb(PORT);
}
void print_serial(const char* string ){
for(size_t i = 0; i < strlen(string); i ++){
write_serial(string[i]);
}
}
void test_serial(){
/** Serial test **/
kterm_writestring("Writing to COM1 serial port:");
init_serial();
write_serial('A');
write_serial('B');
write_serial('C');
write_serial('D');
write_serial('E');
char Character_received = read_serial();
kterm_writestring("\n");
kterm_writestring("received from COM 1: \n");
kterm_put(Character_received);
kterm_writestring("\n");
}
extern "C" {
multiboot_info_t *mbi;
void early_main(unsigned long magic, unsigned long addr){
/** initialize terminal interface */
kterm_init();
multiboot_info_t *mbi;
if (magic != MULTIBOOT_BOOTLOADER_MAGIC){
printf("Invalid magic number: 0x%x\n", (unsigned) magic);
@ -199,31 +105,20 @@ extern "C" {
if (CHECK_FLAG (mbi->flags, 12)){
printf("Can draw!");
}
int cpu_model = get_model();
int local_apic = check_apic();
printf( "CPU Model: %x, Local APIC: %D\n", cpu_model, local_apic);
}
void kernel_main (void) {
init_serial();
/** Setup the MMU **/
//kterm_writestring("Starting MMU...\n");
//auto mmu = MMU();
//mmu.enable();
//kterm_writestring("MMU enabled!\n");
/** test interrupt handlers **/
//asm volatile ("int $0x03");
//asm volatile ("int $0x04");
while (true){
//Read time indefinetely
@ -232,14 +127,8 @@ extern "C" {
delay(1000);
}
/** Lets start using the serial port for debugging .. **/
// Hopefully once we go into realmode or do something that
// cause the screen to go black.. this serial comms part will give
// some situational awareness
//Serial serialbus = Serial::init();
}
}

View File

@ -9,6 +9,105 @@ extern "C" {
#include "MMU.h"
#include "io.h"
#include "time.h"
#include "cpu.h"
#include "arch/i386/vga/VBE.h"
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
/* This needs to be moved! */
/**
* simple delay function
**/
void delay(int t){
volatile int i,j;
for(i=0;i<t;i++)
for(j=0;j<25000;j++)
asm("NOP");
}
class Test {
public:
Test();
void printMe();
~Test();
};
Test::Test(){
kterm_writestring("Create a test object\n");
};
void Test::printMe(){
kterm_writestring("testObject.printMe()\n");
}
Test::~Test(){
kterm_writestring("Destroy testObject! Bye bye\n");
}
#define PORT 0x3f8
static int init_serial() {
outb(PORT + 1, 0x00); // Disable all interrupts
outb(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
outb(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
outb(PORT + 1, 0x00); // (hi byte)
outb(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
outb(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
outb(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
outb(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip
outb(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
// Check if serial is faulty (i.e: not same byte as sent)
if(inb(PORT + 0) != 0xAE) {
return 1;
}
// If serial is not faulty set it in normal operation mode
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
outb(PORT + 4, 0x0F);
return 0;
}
int is_transmit_empty() {
return inb(PORT + 5) & 0x20;
}
void write_serial(char a) {
while (is_transmit_empty() == 0);
outb(PORT,a);
}
int serial_received() {
return inb(PORT + 5) & 1;
}
char read_serial() {
while (serial_received() == 0);
return inb(PORT);
}
void print_serial(const char* string ){
for(size_t i = 0; i < strlen(string); i ++){
write_serial(string[i]);
}
}
void test_serial(){
/** Serial test **/
kterm_writestring("Writing to COM1 serial port:");
init_serial();
write_serial('A');
write_serial('B');
write_serial('C');
write_serial('D');
write_serial('E');
char Character_received = read_serial();
kterm_writestring("\n");
kterm_writestring("received from COM 1: \n");
kterm_put(Character_received);
kterm_writestring("\n");
}