org
This commit is contained in:
parent
ce2b373313
commit
9114529153
8
.clang-format
Normal file
8
.clang-format
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveDeclarations: 'true'
|
||||||
|
AlignTrailingComments: 'true'
|
||||||
|
DisableFormat: 'false'
|
||||||
|
|
||||||
|
...
|
|
@ -1,4 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
set(CMAKE_C_COMPILER_WORKS 1) # todo: find the proper fix for this, rn this is
|
||||||
|
# b/c cmake expects libc to be avaliable and it's not under nixos
|
||||||
|
|
||||||
project(razzle C ASM)
|
project(razzle C ASM)
|
||||||
|
|
||||||
|
@ -20,7 +22,7 @@ set(CMAKE_ASM_FLAGS "-g")
|
||||||
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/linker.ld)
|
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/linker.ld)
|
||||||
|
|
||||||
# Common source files
|
# Common source files
|
||||||
FILE(GLOB SOURCES kernel/kernel.c)
|
FILE(GLOB_RECURSE SOURCES kernel/*.c)
|
||||||
|
|
||||||
# Architecture Specific Files
|
# Architecture Specific Files
|
||||||
if (ARCH STREQUAL "i386")
|
if (ARCH STREQUAL "i386")
|
||||||
|
@ -40,13 +42,15 @@ add_custom_command(OUTPUT os.iso
|
||||||
COMMENT "Generating OS ISO"
|
COMMENT "Generating OS ISO"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Supplemental PCI data to be loaded into memory
|
||||||
add_custom_target(pci_supp
|
add_custom_target(pci_supp
|
||||||
COMMAND xxd -i ../build_supp/pci/pci.ids > ../kernel/pci_supp.c
|
COMMAND xxd -i ../build_supp/pci/pci.ids > ../supp/pci_supp.c
|
||||||
COMMENT "Generating Supplemental PCI data"
|
COMMENT "Generating Supplemental PCI data"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Run & Debug targets
|
# Run & Debug targets
|
||||||
add_custom_target(run COMMAND qemu-system-i386 -boot d -m 512 -machine type=pc-i440fx-3.1 -serial stdio -device piix3-ide,id=ide -drive id=disk,file=/dev/null,format=raw,if=none -device ide-hd,drive=disk,bus=ide.1 -device ide-cd,drive=cdrom -drive id=cdrom,file=os.iso,media=cdrom,if=none DEPENDS os.iso)
|
add_custom_target(run
|
||||||
|
COMMAND qemu-system-i386 -boot d -m 512 -machine type=pc-i440fx-3.1 -serial mon:stdio -device piix3-ide,id=ide -drive id=disk,file=/dev/null,format=raw,if=none -device ide-hd,drive=disk,bus=ide.1 -device ide-cd,drive=cdrom -drive id=cdrom,file=os.iso,media=cdrom,if=none
|
||||||
|
DEPENDS os.iso)
|
||||||
add_custom_target(debug COMMAND ../debug.sh DEPENDS os.iso)
|
add_custom_target(debug COMMAND ../debug.sh DEPENDS os.iso)
|
||||||
|
|
||||||
|
|
9
arch/i386/asm/asm.c
Normal file
9
arch/i386/asm/asm.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include "asm.h"
|
||||||
|
|
||||||
|
void __sl_acquire(uint32_t *lock_id) {
|
||||||
|
__asm__("retry_lock: lock bts $0,(%0); pause; jc retry_lock" : "+g"(lock_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void __sl_release(uint32_t *lock_id) {
|
||||||
|
__asm__("lock btr $0, (%0)" : "+g"(lock_id));
|
||||||
|
}
|
|
@ -9,13 +9,8 @@ struct regs {
|
||||||
unsigned int eip, cs, eflags, useresp, ss;
|
unsigned int eip, cs, eflags, useresp, ss;
|
||||||
};
|
};
|
||||||
|
|
||||||
void __sl_acquire(uint32_t *lock_id) {
|
void __sl_acquire(uint32_t *);
|
||||||
__asm__("retry_lock: lock bts $0,(%0); pause; jc retry_lock" : "+g"(lock_id));
|
void __sl_release(uint32_t *);
|
||||||
}
|
|
||||||
|
|
||||||
void __sl_release(uint32_t *lock_id) {
|
|
||||||
__asm__("lock btr $0, (%0)" : "+g"(lock_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void outb(int port, int val) {
|
static inline void outb(int port, int val) {
|
||||||
__asm__ volatile("outb %b0, %w1" : : "a"(val), "Nd"(port) : "memory");
|
__asm__ volatile("outb %b0, %w1" : : "a"(val), "Nd"(port) : "memory");
|
||||||
|
@ -37,6 +32,16 @@ static inline uint32_t inl(uint32_t port) {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void outw(uint16_t port, uint16_t val) {
|
||||||
|
__asm__ volatile("outw %w0, %w1" : : "a"(val), "Nd"(port) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t inw(uint16_t port) {
|
||||||
|
uint32_t val;
|
||||||
|
__asm__ volatile("inw %w1, %w0" : "=a"(val) : "Nd"(port) : "memory");
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void interrupt_disable() { __asm__ volatile("cli"); }
|
static inline void interrupt_disable() { __asm__ volatile("cli"); }
|
||||||
|
|
||||||
static inline void interrupt_enable() { __asm__ volatile("sti"); }
|
static inline void interrupt_enable() { __asm__ volatile("sti"); }
|
|
@ -1,15 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../kernel/memory.c"
|
#include "../../kernel/memory/memory.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct gdt_row_t {
|
struct gdt_row_t {
|
||||||
uint16_t limit_low;
|
uint16_t limit_low;
|
||||||
uint16_t base_low;
|
uint16_t base_low;
|
||||||
uint8_t base_middle;
|
uint8_t base_middle;
|
||||||
uint8_t access;
|
uint8_t access;
|
||||||
uint8_t granularity_limit_high;
|
uint8_t granularity_limit_high;
|
||||||
uint8_t base_high;
|
uint8_t base_high;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct gdt_ptr_t {
|
struct gdt_ptr_t {
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../kernel/memory.c"
|
#include "../../kernel/memory/memory.h"
|
||||||
#include "./handlers.h"
|
#include "./handlers.h"
|
||||||
#include "gdt.c"
|
#include "gdt.c"
|
||||||
|
|
||||||
struct idt_row_t {
|
struct idt_row_t {
|
||||||
uint16_t base_lo;
|
uint16_t base_lo;
|
||||||
uint16_t sel;
|
uint16_t sel;
|
||||||
uint8_t unset;
|
uint8_t unset;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint16_t base_hi;
|
uint16_t base_hi;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
@ -26,7 +26,8 @@ enum idt_flag_t {
|
||||||
IDTFLAG_INTERRUPT = 0b00001110,
|
IDTFLAG_INTERRUPT = 0b00001110,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define KERNEL_INTERRUPT_FLAG (IDTFLAG_PRESENT | IDTFLAG_DPL_KERNEL | IDTFLAG_INTERRUPT)
|
#define KERNEL_INTERRUPT_FLAG \
|
||||||
|
(IDTFLAG_PRESENT | IDTFLAG_DPL_KERNEL | IDTFLAG_INTERRUPT)
|
||||||
#define USER_TRAP_FLAG (IDTFLAG_PRESENT | IDTFLAG_DPL_USER | IDTFLAG_INTERRUPT)
|
#define USER_TRAP_FLAG (IDTFLAG_PRESENT | IDTFLAG_DPL_USER | IDTFLAG_INTERRUPT)
|
||||||
|
|
||||||
#define IDT_SIZE (256)
|
#define IDT_SIZE (256)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "./gdt.c"
|
#include "./gdt.c"
|
||||||
#include "./idt.c"
|
#include "./idt.c"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../kernel/ps2.c"
|
#include "../../kernel/drivers/ps2/ps2.h"
|
||||||
#include "../../kernel/syscall.c"
|
#include "../../kernel/syscall/syscall.h"
|
||||||
#include "./asm.c"
|
#include "./asm/asm.c"
|
||||||
#include "./idt.c"
|
#include "./idt.c"
|
||||||
#include "handlers.h"
|
#include "handlers.h"
|
||||||
|
|
||||||
|
@ -79,11 +79,11 @@ void irq_handler(struct regs *r) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send EOI to follower controller
|
// Send EOI to follower controller
|
||||||
if (r->int_no >= 40 && r->int_no < 48) {
|
if (r->int_no >= 40 && r->int_no < 48) {
|
||||||
outb(0xA0, 0x20);
|
outb(0xA0, 0x20);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send EOI to leader controller
|
// Send EOI to leader controller
|
||||||
outb(0x20, 0x20);
|
outb(0x20, 0x20);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,4 @@
|
||||||
#pragma once
|
#include "scheduler.h"
|
||||||
|
|
||||||
#include "asm.c"
|
|
||||||
|
|
||||||
enum eflags_t {
|
|
||||||
EFLAG_CARRY = 0x0001,
|
|
||||||
EFLAG_RES = 0x0002,
|
|
||||||
EFLAG_PARITY = 0x0004,
|
|
||||||
EFLAG_INTERRUPT = 0x0200
|
|
||||||
};
|
|
||||||
|
|
||||||
void initialize_registers(struct regs *new_regs, char *entrypoint,
|
void initialize_registers(struct regs *new_regs, char *entrypoint,
|
||||||
uint32_t address_base, uint32_t address_space_size) {
|
uint32_t address_base, uint32_t address_space_size) {
|
15
arch/i386/scheduler/scheduler.h
Normal file
15
arch/i386/scheduler/scheduler.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../asm/asm.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum eflags_t {
|
||||||
|
EFLAG_CARRY = 0x0001,
|
||||||
|
EFLAG_RES = 0x0002,
|
||||||
|
EFLAG_PARITY = 0x0004,
|
||||||
|
EFLAG_INTERRUPT = 0x0200
|
||||||
|
};
|
||||||
|
|
||||||
|
void initialize_registers(struct regs *, char *, uint32_t, uint32_t);
|
||||||
|
void store_registers(struct regs *, struct regs *);
|
||||||
|
void switch_context(struct regs *, struct regs *);
|
2
format.sh
Executable file
2
format.sh
Executable file
|
@ -0,0 +1,2 @@
|
||||||
|
git ls-files -- '*.c' '*.h' | xargs clang-format -i -style=file
|
||||||
|
git diff --exit-code --color
|
116
kernel/acpi/rsdp.c
Normal file
116
kernel/acpi/rsdp.c
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "../io/io.h"
|
||||||
|
#include "../memory/memory.h"
|
||||||
|
#include "rsdp.h"
|
||||||
|
|
||||||
|
struct rsdp_t {
|
||||||
|
char signature[8];
|
||||||
|
uint8_t checksum;
|
||||||
|
char oem_id[6];
|
||||||
|
uint8_t revision;
|
||||||
|
uint32_t rsdt_address;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct xsdp_t {
|
||||||
|
char signature[8];
|
||||||
|
uint8_t checksum;
|
||||||
|
char oem_id[6];
|
||||||
|
uint8_t revision;
|
||||||
|
uint32_t unused;
|
||||||
|
uint32_t length;
|
||||||
|
uint32_t xsdt_addr_hi;
|
||||||
|
uint32_t xsdt_addr_lo;
|
||||||
|
uint8_t checksum_ext;
|
||||||
|
uint8_t unused_[3];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct acpi_header_t {
|
||||||
|
char signature[4];
|
||||||
|
uint32_t length;
|
||||||
|
uint8_t revision;
|
||||||
|
uint8_t checksum;
|
||||||
|
char oem_id[6];
|
||||||
|
char oem_table_id[8];
|
||||||
|
uint32_t oem_revision;
|
||||||
|
uint32_t creator_id;
|
||||||
|
uint32_t creator_division;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct rsdt_t {
|
||||||
|
struct acpi_header_t header;
|
||||||
|
uint32_t pointer[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t validate(struct rsdp_t *ptr) {
|
||||||
|
char sig[] = "RSD PTR ";
|
||||||
|
if (!memseq(ptr->signature, sig, 8))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uint8_t *rsdp_bytes = (uint8_t *)ptr;
|
||||||
|
uint8_t sum = 0;
|
||||||
|
for (uint8_t i = 0; i < 20; i++) {
|
||||||
|
sum += rsdp_bytes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sum == 0 && ptr->revision == 2) {
|
||||||
|
printf_nolock("acpi: ACPI v2+ not yet supported :(\n");
|
||||||
|
for (;;) {
|
||||||
|
}
|
||||||
|
// TODO: test with ACPI 2 System
|
||||||
|
struct xsdp_t *r2_ptr = (struct xsdp_t *)ptr;
|
||||||
|
|
||||||
|
uint8_t *xsdp_bytes = ((uint8_t *)r2_ptr) + 8;
|
||||||
|
for (uint8_t i = 0; i < 16; i++) {
|
||||||
|
sum += xsdp_bytes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *find_table(struct rsdt_t *table, char *sig) {
|
||||||
|
uint32_t entries = (table->header.length - sizeof table->header) / 4;
|
||||||
|
for (uint32_t i = 0; i < entries; i++) {
|
||||||
|
struct acpi_header_t *entry = (struct acpi_header_t *)table->pointer[i];
|
||||||
|
if (memseq(entry->signature, sig, 4)) {
|
||||||
|
printf_nolock("Found %s / %s\n", entry->oem_id, entry->signature);
|
||||||
|
printf_nolock("Signature: %s\n", entry->signature);
|
||||||
|
printf_nolock("Length : %d\n", entry->length);
|
||||||
|
printf_nolock("Oem ID : %s\n", entry->oem_id);
|
||||||
|
printf_nolock("Checksum : %d\n", entry->checksum);
|
||||||
|
return (void *)entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf_nolock("Not Found");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void find_rsdp() {
|
||||||
|
struct rsdp_t *ptr;
|
||||||
|
|
||||||
|
volatile uint8_t found = 0;
|
||||||
|
for (uint32_t addr = 0x00000000; addr <= 0x000FFFFF; addr++) {
|
||||||
|
ptr = (struct rsdp_t *)addr;
|
||||||
|
|
||||||
|
if (validate(ptr)) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
uint8_t *ebda = (uint8_t *)(*((uint16_t *)0x40e) << 4);
|
||||||
|
for (uint32_t i = 0; i <= 1024; i += 16) {
|
||||||
|
ptr = (struct rsdp_t *)ebda;
|
||||||
|
if (validate(ptr)) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf_nolock("acpi: RSDP Found [OEM: %s, SIG: %s]\n", ptr->oem_id,
|
||||||
|
ptr->signature);
|
||||||
|
}
|
3
kernel/acpi/rsdp.h
Normal file
3
kernel/acpi/rsdp.h
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
void find_rsdp();
|
17
kernel/drivers/blk/blk.h
Normal file
17
kernel/drivers/blk/blk.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct block_dev {
|
||||||
|
char name[16];
|
||||||
|
uint32_t sector_size;
|
||||||
|
uint32_t device_no;
|
||||||
|
uint32_t num_sectors;
|
||||||
|
uint32_t (*read_sector)(uint32_t, uint32_t, char *);
|
||||||
|
uint32_t (*write_sector)(uint32_t, uint32_t, char *);
|
||||||
|
};
|
||||||
|
|
||||||
|
void BLK__init();
|
||||||
|
uint32_t BLK__register_device(struct block_dev*);
|
||||||
|
uint32_t BLK__get_block_devices(struct block_dev* devices, uint32_t req_num);
|
||||||
|
uint32_t BLK__get_block_device(struct block_dev* devices, uint32_t req_num);
|
45
kernel/drivers/blk/ramblk/ramblk.c
Normal file
45
kernel/drivers/blk/ramblk/ramblk.c
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include "./ramblk.h"
|
||||||
|
#include "../../../memory/memory.h"
|
||||||
|
#include "../blk.h"
|
||||||
|
|
||||||
|
#define RAMFS_BYTES (1024 * 1024 * 5) // 5 MB
|
||||||
|
#define SECTOR_SIZE (512)
|
||||||
|
|
||||||
|
char ramfs_blocks[RAMFS_BYTES];
|
||||||
|
|
||||||
|
uint32_t RAMBLK__read_sector(uint32_t device, uint32_t sector, char *out) {
|
||||||
|
if (sector * SECTOR_SIZE >= RAMFS_BYTES) {
|
||||||
|
// Out of bounds
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t byte = sector * SECTOR_SIZE;
|
||||||
|
|
||||||
|
memcpy(ramfs_blocks + byte, out, SECTOR_SIZE);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t RAMBLK__write_sector(uint32_t device, uint32_t sector, char *in) {
|
||||||
|
if ((sector + 1) * SECTOR_SIZE >= RAMFS_BYTES) {
|
||||||
|
// Out of bounds
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t byte = sector * SECTOR_SIZE;
|
||||||
|
|
||||||
|
memcpy(in, ramfs_blocks + byte, SECTOR_SIZE);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RAMBLK__init() {
|
||||||
|
memset(ramfs_blocks, 0x00, RAMFS_BYTES);
|
||||||
|
struct block_dev bd = {
|
||||||
|
.name = "RAM_BLK",
|
||||||
|
.sector_size = SECTOR_SIZE,
|
||||||
|
.device_no = 0,
|
||||||
|
.num_sectors = RAMFS_BYTES / SECTOR_SIZE,
|
||||||
|
.read_sector = &RAMBLK__read_sector,
|
||||||
|
.write_sector = &RAMBLK__write_sector
|
||||||
|
};
|
||||||
|
BLK__register_device(&bd);
|
||||||
|
}
|
7
kernel/drivers/blk/ramblk/ramblk.h
Normal file
7
kernel/drivers/blk/ramblk/ramblk.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
void RAMBLK__init();
|
||||||
|
uint32_t RAMBLK__read_sector(uint32_t device, uint32_t sector, char *out);
|
||||||
|
uint32_t RAMBLK__write_sector(uint32_t device, uint32_t sector, char *in);
|
208
kernel/drivers/fs/nqfs/nqfs.c
Normal file
208
kernel/drivers/fs/nqfs/nqfs.c
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
// Nick's Quick(ly made) File System
|
||||||
|
#include "nqfs.h"
|
||||||
|
#include "../../../io/io.h"
|
||||||
|
#include "../../../memory/memory.h"
|
||||||
|
|
||||||
|
#define FILEPTR_SECTORS (128)
|
||||||
|
#define FILEPTR_PER_SECTOR (4)
|
||||||
|
#define FILEPTR_CNT (FILEPTR_SECTORS * FILEPTR_PER_SECTOR)
|
||||||
|
|
||||||
|
void NQFS_init() {}
|
||||||
|
|
||||||
|
uint32_t NQFS_get_next_free_block(struct block_dev *device) {
|
||||||
|
char sector[512];
|
||||||
|
struct NQFS_storage_block *sb = (struct NQFS_storage_block *)sector;
|
||||||
|
|
||||||
|
for (uint32_t i = FILEPTR_SECTORS; i < device->num_sectors; ++i) {
|
||||||
|
if (!device->read_sector(device->device_no, i, sector)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (sb->magic_number != 0xC001) {
|
||||||
|
sb->magic_number = 0xC001;
|
||||||
|
sb->next_sector = 0;
|
||||||
|
if (!device->write_sector(device->device_no, i, sector)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t NQFS_create_file(struct block_dev *device, char *filename) {
|
||||||
|
char sector[512];
|
||||||
|
for (int i = 0; i < FILEPTR_SECTORS; ++i) {
|
||||||
|
if (!device->read_sector(device->device_no, i, sector)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
struct NQFS_inode *fp = (struct NQFS_inode *)sector;
|
||||||
|
for (int j = 0; j < FILEPTR_PER_SECTOR; ++j) {
|
||||||
|
if (!fp->allocd) {
|
||||||
|
uint32_t new_sector = NQFS_get_next_free_block(device);
|
||||||
|
if (new_sector == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fp->allocd = 1;
|
||||||
|
fp->size = 0;
|
||||||
|
fp->start_sector = new_sector;
|
||||||
|
strncpy(filename, fp->filename, NQFS_MAX_FILENAME_SIZE);
|
||||||
|
fp->filename[NQFS_MAX_FILENAME_SIZE - 1] = '\0';
|
||||||
|
if (!device->write_sector(device->device_no, i, sector)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printf_nolock("Created file \"%s\" at sector %d fp %d\n", fp->filename,
|
||||||
|
new_sector, i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
fp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint32_t NQFS_read_bytes(struct block_dev *device, uint32_t inode_sector,
|
||||||
|
char *out, uint32_t size) {
|
||||||
|
char sector[512];
|
||||||
|
struct NQFS_inode *fp = (struct NQFS_inode *)sector;
|
||||||
|
if (!device->read_sector(device->device_no, inode_sector, sector)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char storage_sector[512];
|
||||||
|
struct NQFS_storage_block *sb = (struct NQFS_storage_block *)storage_sector;
|
||||||
|
|
||||||
|
if (fp->start_sector != 0) {
|
||||||
|
uint32_t read_sector = fp->start_sector;
|
||||||
|
|
||||||
|
if (size > fp->size) {
|
||||||
|
size = fp->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (size > 0) {
|
||||||
|
if (!device->read_sector(device->device_no, read_sector,
|
||||||
|
storage_sector)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t readable = NQFS_STORAGE_BYTES_SECTOR;
|
||||||
|
if (size < readable) {
|
||||||
|
readable = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy data into struct
|
||||||
|
memcpy(sb->data, out, readable);
|
||||||
|
out += readable;
|
||||||
|
size -= readable;
|
||||||
|
|
||||||
|
if (size > 0) {
|
||||||
|
read_sector = sb->next_sector;
|
||||||
|
if (read_sector == 0) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
printf_nolock("didn't find start\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t NQFS_write_bytes(struct block_dev *device, uint32_t inode_sector,
|
||||||
|
char *in, uint32_t size) {
|
||||||
|
uint32_t total_written = 0;
|
||||||
|
char sector[512];
|
||||||
|
struct NQFS_inode *fp = (struct NQFS_inode *)sector;
|
||||||
|
if (!device->read_sector(device->device_no, inode_sector, sector)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char storage_sector[512];
|
||||||
|
struct NQFS_storage_block *sb = (struct NQFS_storage_block *)storage_sector;
|
||||||
|
|
||||||
|
if (fp->start_sector != 0) {
|
||||||
|
uint32_t cur_size = fp->size;
|
||||||
|
uint32_t read_sector = fp->start_sector;
|
||||||
|
|
||||||
|
while (cur_size >= NQFS_STORAGE_BYTES_SECTOR) {
|
||||||
|
if (!device->read_sector(device->device_no, read_sector,
|
||||||
|
storage_sector)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_size -= NQFS_STORAGE_BYTES_SECTOR;
|
||||||
|
read_sector = sb->next_sector;
|
||||||
|
if (read_sector == 0) {
|
||||||
|
sb->next_sector = NQFS_get_next_free_block(device);
|
||||||
|
read_sector = sb->next_sector;
|
||||||
|
if (read_sector == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (size > 0) {
|
||||||
|
if (!device->read_sector(device->device_no, read_sector,
|
||||||
|
storage_sector)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t writeable = NQFS_STORAGE_BYTES_SECTOR - cur_size;
|
||||||
|
if (size < writeable) {
|
||||||
|
writeable = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy data into struct
|
||||||
|
memcpy(in + total_written, sb->data + cur_size, writeable);
|
||||||
|
cur_size = 0;
|
||||||
|
|
||||||
|
fp->size += writeable;
|
||||||
|
total_written += writeable;
|
||||||
|
|
||||||
|
if (!device->write_sector(device->device_no, inode_sector, sector)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write struct out to disk
|
||||||
|
if (!device->write_sector(device->device_no, read_sector,
|
||||||
|
storage_sector)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size -= writeable;
|
||||||
|
if (size > 0) {
|
||||||
|
sb->next_sector = NQFS_get_next_free_block(device);
|
||||||
|
// Write struct out to disk
|
||||||
|
if (!device->write_sector(device->device_no, read_sector,
|
||||||
|
storage_sector)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
read_sector = sb->next_sector;
|
||||||
|
if (read_sector == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf_nolock("File didn't point to a storage block\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NQFS_DEBUG_list_files(struct block_dev *device) {
|
||||||
|
char sector[512];
|
||||||
|
for (int i = 0; i < FILEPTR_SECTORS; ++i) {
|
||||||
|
if (!device->read_sector(device->device_no, i, sector)) {
|
||||||
|
printf_nolock("Error reading sector %d\n", i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct NQFS_inode *fp = (struct NQFS_inode *)sector;
|
||||||
|
for (int j = 0; j < FILEPTR_PER_SECTOR; ++j) {
|
||||||
|
if (fp->allocd) {
|
||||||
|
printf_nolock("Found file: %s\n", fp->filename);
|
||||||
|
}
|
||||||
|
fp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
kernel/drivers/fs/nqfs/nqfs.h
Normal file
32
kernel/drivers/fs/nqfs/nqfs.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../blk/blk.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define NQFS_MAX_FILENAME_SIZE (64)
|
||||||
|
#define NQFS_STORAGE_BYTES_SECTOR (504)
|
||||||
|
|
||||||
|
struct NQFS_inode {
|
||||||
|
uint8_t allocd;
|
||||||
|
char filename[NQFS_MAX_FILENAME_SIZE];
|
||||||
|
uint32_t start_sector;
|
||||||
|
uint32_t size;
|
||||||
|
char _[55];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct NQFS_storage_block {
|
||||||
|
uint32_t magic_number;
|
||||||
|
char data[NQFS_STORAGE_BYTES_SECTOR];
|
||||||
|
uint32_t next_sector;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
uint32_t NQFS_get_next_free_inode(struct block_dev *device);
|
||||||
|
uint32_t NQFS_create_file(struct block_dev *device, char *filename);
|
||||||
|
|
||||||
|
// Returns number of bytes read into char
|
||||||
|
uint32_t NQFS_read_bytes(struct block_dev *device, uint32_t inode_sector,
|
||||||
|
char *out, uint32_t max_size);
|
||||||
|
uint32_t NQFS_write_bytes(struct block_dev *device, uint32_t inode_sector,
|
||||||
|
char *in, uint32_t size);
|
||||||
|
|
||||||
|
void NQFS_DEBUG_list_files(struct block_dev *device);
|
|
@ -1,8 +1,6 @@
|
||||||
#pragma once
|
#include "./ps2.h"
|
||||||
|
|
||||||
#include "./scheduler.c"
|
struct ps2_waiter_t ps2_waiters[MAX_PROCESSES];
|
||||||
#include "./vga.c"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
enum key_code_t {
|
enum key_code_t {
|
||||||
backtick_tilde = 1,
|
backtick_tilde = 1,
|
||||||
|
@ -63,7 +61,7 @@ enum key_code_t {
|
||||||
|
|
||||||
struct key_event_t {
|
struct key_event_t {
|
||||||
enum key_code_t key;
|
enum key_code_t key;
|
||||||
uint8_t is_down;
|
uint8_t is_down;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kb_state {
|
struct kb_state {
|
||||||
|
@ -244,30 +242,22 @@ char keycode_to_char(enum key_code_t key_code) {
|
||||||
return '\0';
|
return '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct ps2_waiter_t {
|
|
||||||
uint8_t alloc;
|
|
||||||
uint32_t pid;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ps2_waiter_t ps2_waiters[MAX_PROCESSES];
|
|
||||||
|
|
||||||
void init_ps2() {
|
void init_ps2() {
|
||||||
for(uint32_t i = 0; i < MAX_PROCESSES; i++) {
|
for (uint32_t i = 0; i < MAX_PROCESSES; i++) {
|
||||||
ps2_waiters[i].alloc = 0;
|
ps2_waiters[i].alloc = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_keypress_char(char c) {
|
void handle_keypress_char(char c) {
|
||||||
if (c != '\0') {
|
if (c != '\0') {
|
||||||
for(uint32_t i = 0; i < MAX_PROCESSES; i++) {
|
for (uint32_t i = 0; i < MAX_PROCESSES; i++) {
|
||||||
if(ps2_waiters[i].alloc) {
|
if (ps2_waiters[i].alloc) {
|
||||||
process_table[ps2_waiters[i].pid].registers.eax = c;
|
process_table[ps2_waiters[i].pid].registers.eax = c;
|
||||||
ps2_waiters[i].alloc = 0;
|
ps2_waiters[i].alloc = 0;
|
||||||
process_table[ps2_waiters[i].pid].state = TASKSTATE_ready;
|
process_table[ps2_waiters[i].pid].state = TASKSTATE_ready;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_keypress(uint8_t char_code) {
|
void handle_keypress(uint8_t char_code) {
|
||||||
|
@ -296,11 +286,11 @@ void handle_keypress(uint8_t char_code) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
if (event.is_down) {
|
if (event.is_down) {
|
||||||
char c = keycode_to_char(event.key);
|
char c = keycode_to_char(event.key);
|
||||||
handle_keypress_char(c);
|
handle_keypress_char(c);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
16
kernel/drivers/ps2/ps2.h
Normal file
16
kernel/drivers/ps2/ps2.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "../../scheduler/scheduler.h"
|
||||||
|
|
||||||
|
struct ps2_waiter_t {
|
||||||
|
uint8_t alloc;
|
||||||
|
uint32_t pid;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct ps2_waiter_t ps2_waiters[MAX_PROCESSES];
|
||||||
|
|
||||||
|
void init_ps2();
|
||||||
|
void handle_keypress_char(char);
|
||||||
|
void handle_keypress(uint8_t);
|
|
@ -1,36 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include "../../arch/i386/asm.c"
|
|
||||||
|
|
||||||
#define COM1 (0x3F8)
|
|
||||||
|
|
||||||
int serial_init() {
|
|
||||||
outb(COM1 + 1, 0x01);
|
|
||||||
outb(COM1 + 3, 0x80);
|
|
||||||
outb(COM1 + 0, 0x03);
|
|
||||||
outb(COM1 + 1, 0x00);
|
|
||||||
outb(COM1 + 3, 0x03);
|
|
||||||
outb(COM1 + 2, 0xC7);
|
|
||||||
outb(COM1 + 4, 0x0B);
|
|
||||||
outb(COM1 + 4, 0x0F);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int serial_has_tx() {
|
|
||||||
return inb(COM1 + 5) & 0x20;
|
|
||||||
}
|
|
||||||
|
|
||||||
int serial_has_rx() {
|
|
||||||
return inb(COM1 + 5) & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_tx(char a) {
|
|
||||||
while (serial_has_tx() == 0);
|
|
||||||
|
|
||||||
outb(COM1,a);
|
|
||||||
}
|
|
||||||
|
|
||||||
char serial_rx() {
|
|
||||||
while (serial_has_rx() == 0);
|
|
||||||
|
|
||||||
return inb(COM1);
|
|
||||||
}
|
|
36
kernel/drivers/serial/serial.c
Normal file
36
kernel/drivers/serial/serial.c
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "serial.h"
|
||||||
|
#include "../../../arch/i386/asm/asm.h"
|
||||||
|
|
||||||
|
#define COM1 (0x3F8)
|
||||||
|
|
||||||
|
int serial_init() {
|
||||||
|
outb(COM1 + 1, 0x01);
|
||||||
|
outb(COM1 + 3, 0x80);
|
||||||
|
outb(COM1 + 0, 0x03);
|
||||||
|
outb(COM1 + 1, 0x00);
|
||||||
|
outb(COM1 + 3, 0x03);
|
||||||
|
outb(COM1 + 2, 0xC7);
|
||||||
|
outb(COM1 + 4, 0x0B);
|
||||||
|
outb(COM1 + 4, 0x0F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int serial_has_tx() { return inb(COM1 + 5) & 0x20; }
|
||||||
|
|
||||||
|
int serial_has_rx() { return inb(COM1 + 5) & 1; }
|
||||||
|
|
||||||
|
void serial_tx(char a) {
|
||||||
|
while (serial_has_tx() == 0)
|
||||||
|
;
|
||||||
|
|
||||||
|
outb(COM1, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
char serial_rx() {
|
||||||
|
while (serial_has_rx() == 0)
|
||||||
|
;
|
||||||
|
|
||||||
|
return inb(COM1);
|
||||||
|
}
|
5
kernel/drivers/serial/serial.h
Normal file
5
kernel/drivers/serial/serial.h
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
int serial_init();
|
||||||
|
void serial_tx(char);
|
||||||
|
char serial_rx();
|
109
kernel/drivers/vga/vga.c
Normal file
109
kernel/drivers/vga/vga.c
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vga.h"
|
||||||
|
#include "../../memory/memory.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define WIDTH 80
|
||||||
|
#define HEIGHT 25
|
||||||
|
|
||||||
|
static char vga_buf[HEIGHT * (WIDTH * 2)];
|
||||||
|
|
||||||
|
static uint8_t vgabuf_col = 0;
|
||||||
|
static uint8_t vgabuf_row = 0;
|
||||||
|
|
||||||
|
static uint8_t vgabuf_start_row = 0;
|
||||||
|
static uint8_t vgabuf_move_row = 0;
|
||||||
|
|
||||||
|
static uint8_t default_color_code = 10;
|
||||||
|
static char *vram = (char *)0xb8000;
|
||||||
|
|
||||||
|
static inline int VGA_idx(int row, int col) {
|
||||||
|
return (row * WIDTH * 2) + (col * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void VGA_set(int row, int col, char c, int color_code) {
|
||||||
|
vga_buf[VGA_idx(row, col)] = c;
|
||||||
|
vga_buf[VGA_idx(row, col) + 1] = color_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VGA_flush() {
|
||||||
|
int topwrite = ((HEIGHT - vgabuf_start_row) * WIDTH * 2);
|
||||||
|
|
||||||
|
// Fill the top of the display from the offsetted buffer
|
||||||
|
memcpy(vga_buf + (vgabuf_start_row * WIDTH * 2), vram, topwrite);
|
||||||
|
|
||||||
|
// Fill the bottom of the display from the offsetted buffer
|
||||||
|
memcpy(vga_buf, vram + topwrite, ((vgabuf_start_row)*WIDTH * 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void VGA_clear_screen() {
|
||||||
|
for (int r = 0; r < HEIGHT - 1; r++) {
|
||||||
|
for (int c = 0; c < WIDTH; c++) {
|
||||||
|
VGA_set(r, c, ' ', default_color_code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vgabuf_start_row = 0;
|
||||||
|
vgabuf_col = 0;
|
||||||
|
vgabuf_row = 0;
|
||||||
|
|
||||||
|
VGA_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VGA_clear_line() {
|
||||||
|
for (int i = 0; i < WIDTH; ++i) {
|
||||||
|
VGA_set(vgabuf_start_row, i, ' ', default_color_code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VGA_putc(char c) {
|
||||||
|
if (vgabuf_col == WIDTH) {
|
||||||
|
vgabuf_row = (vgabuf_row + 1) % HEIGHT;
|
||||||
|
vgabuf_col = 0;
|
||||||
|
|
||||||
|
if (vgabuf_start_row > 0 || vgabuf_row == 0) {
|
||||||
|
if (vgabuf_move_row == vgabuf_start_row) {
|
||||||
|
vgabuf_start_row = (vgabuf_start_row + 1) % HEIGHT;
|
||||||
|
vgabuf_move_row = vgabuf_start_row;
|
||||||
|
} else {
|
||||||
|
vgabuf_move_row++;
|
||||||
|
}
|
||||||
|
VGA_clear_line();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '\n') {
|
||||||
|
for (int i = vgabuf_col; i < WIDTH; i++) {
|
||||||
|
VGA_set(vgabuf_row, i, ' ', default_color_code);
|
||||||
|
}
|
||||||
|
vgabuf_row = (vgabuf_row + 1) % HEIGHT;
|
||||||
|
vgabuf_col = 0;
|
||||||
|
|
||||||
|
if (vgabuf_start_row > 0 || vgabuf_row == 0) {
|
||||||
|
if (vgabuf_move_row == vgabuf_start_row) {
|
||||||
|
vgabuf_start_row = (vgabuf_start_row + 1) % HEIGHT;
|
||||||
|
vgabuf_move_row = vgabuf_start_row;
|
||||||
|
} else {
|
||||||
|
vgabuf_move_row++;
|
||||||
|
}
|
||||||
|
VGA_clear_line();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '\b') {
|
||||||
|
if (vgabuf_col == 0) {
|
||||||
|
vgabuf_col = WIDTH - 1;
|
||||||
|
vgabuf_row--;
|
||||||
|
vgabuf_move_row--;
|
||||||
|
} else {
|
||||||
|
vgabuf_col--;
|
||||||
|
}
|
||||||
|
// VGA_set(vgabuf_row, vgabuf_col, ' ', default_color_code);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VGA_set(vgabuf_row, vgabuf_col, c, default_color_code);
|
||||||
|
vgabuf_col++;
|
||||||
|
}
|
5
kernel/drivers/vga/vga.h
Normal file
5
kernel/drivers/vga/vga.h
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
void VGA_clear_screen();
|
||||||
|
void VGA_putc(char);
|
||||||
|
void VGA_flush();
|
|
@ -1,58 +1,12 @@
|
||||||
#pragma once
|
#include "io.h"
|
||||||
|
#include "../drivers/serial/serial.h"
|
||||||
#include "./spin_lock.c"
|
#include "../drivers/vga/vga.h"
|
||||||
#include "./drivers/serial.c"
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define WIDTH 80
|
#include "../spin_lock.h"
|
||||||
#define HEIGHT 25
|
|
||||||
|
|
||||||
static uint8_t col = 0;
|
|
||||||
static uint8_t row = 0;
|
|
||||||
static uint8_t color_code = 10;
|
|
||||||
static char *vram = (char *)0xb8000;
|
|
||||||
|
|
||||||
void clear_screen() {
|
|
||||||
for (int i = 0; i < HEIGHT - 1; i++) {
|
|
||||||
for (int j = 0; j < WIDTH; j++) {
|
|
||||||
vram[(i * WIDTH * 2) + (j * 2)] = 0;
|
|
||||||
// vram[(i * WIDTH * 2) + (j*2 + 1)] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
row = 0;
|
|
||||||
col = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void putc(char c) {
|
void putc(char c) {
|
||||||
if (col == WIDTH) {
|
VGA_putc(c);
|
||||||
row = (row + 1) % HEIGHT;
|
|
||||||
col = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == '\n') {
|
|
||||||
for (int i = col; i < WIDTH; i++) {
|
|
||||||
vram[(row * WIDTH * 2) + (i * 2)] = ' ';
|
|
||||||
vram[(row * WIDTH * 2) + (i * 2 + 1)] = color_code;
|
|
||||||
}
|
|
||||||
row = (row + 1) % HEIGHT;
|
|
||||||
col = 0;
|
|
||||||
serial_tx('\n');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == '\b') {
|
|
||||||
col--;
|
|
||||||
vram[(row * WIDTH * 2) + (col * 2)] = ' ';
|
|
||||||
vram[(row * WIDTH * 2) + (col * 2 + 1)] = color_code;
|
|
||||||
serial_tx('\b');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vram[(row * WIDTH * 2) + (col * 2)] = c;
|
|
||||||
vram[(row * WIDTH * 2) + (col * 2 + 1)] = color_code;
|
|
||||||
col++;
|
|
||||||
|
|
||||||
serial_tx(c);
|
serial_tx(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,8 +47,8 @@ void print_hex(uint32_t x) {
|
||||||
do {
|
do {
|
||||||
uint32_t digit = (x & 0xF0000000) >> 28;
|
uint32_t digit = (x & 0xF0000000) >> 28;
|
||||||
if (digit != 0 || !fp || x == 0) {
|
if (digit != 0 || !fp || x == 0) {
|
||||||
putc((digit < 10) ? (digit + '0') : (digit - 10 + 'A'));
|
putc((digit < 10) ? (digit + '0') : (digit - 10 + 'A'));
|
||||||
fp = 0;
|
fp = 0;
|
||||||
}
|
}
|
||||||
x <<= 4;
|
x <<= 4;
|
||||||
} while (x != 0);
|
} while (x != 0);
|
||||||
|
@ -150,6 +104,7 @@ void printf_base(char *str, va_list list) {
|
||||||
putc(str[i]);
|
putc(str[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
VGA_flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void printf_nolock(char *str, ...) {
|
void printf_nolock(char *str, ...) {
|
7
kernel/io/io.h
Normal file
7
kernel/io/io.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
void putc(char);
|
||||||
|
void printf(char *, ...);
|
||||||
|
void printf_nolock(char *, ...);
|
|
@ -1,32 +1,48 @@
|
||||||
#include "./drivers/serial.c"
|
#pragma once
|
||||||
#include "./pci.c"
|
|
||||||
#include "./rsdp.c"
|
#include "./acpi/rsdp.h"
|
||||||
#include "./scheduler.c"
|
#include "./drivers/serial/serial.h"
|
||||||
#include "./vga.c"
|
#include "./drivers/vga/vga.h"
|
||||||
|
#include "./io/io.h"
|
||||||
|
#include "./pci/pci.h"
|
||||||
|
#include "./scheduler/scheduler.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "./test_processes.c"
|
#include "../arch/i386/scheduler/scheduler.c"
|
||||||
|
#include "../supp/test_processes.c"
|
||||||
|
#include "./drivers/blk/ramblk/ramblk.h"
|
||||||
|
#include "./drivers/fs/nqfs/nqfs.h"
|
||||||
|
#include "./drivers/ps2/ps2.h"
|
||||||
|
#include "drivers/blk/blk.h"
|
||||||
|
|
||||||
#ifdef ARCH_I386
|
#ifdef ARCH_I386
|
||||||
#include "../arch/i386/init.c"
|
#include "../arch/i386/init.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int kernel_main() {
|
int kernel_main() {
|
||||||
lock = 0;
|
|
||||||
|
|
||||||
outb(0x3D4, 0x0A);
|
outb(0x3D4, 0x0A);
|
||||||
outb(0x3D5, 0x20);
|
outb(0x3D5, 0x20);
|
||||||
serial_init();
|
serial_init();
|
||||||
|
|
||||||
find_rsdp();
|
find_rsdp();
|
||||||
pci_enumerate_devices();
|
pci_enumerate_devices();
|
||||||
clear_screen();
|
VGA_clear_screen();
|
||||||
|
|
||||||
interrupt_disable();
|
interrupt_disable();
|
||||||
|
|
||||||
arch_init();
|
arch_init();
|
||||||
|
|
||||||
init_process_table();
|
init_process_table();
|
||||||
|
init_ps2();
|
||||||
|
|
||||||
|
// Init block device list
|
||||||
|
BLK__init();
|
||||||
|
|
||||||
|
// Init block device drivers
|
||||||
|
RAMBLK__init();
|
||||||
|
|
||||||
|
struct block_dev blk_devices[128];
|
||||||
|
uint32_t blkdev_cnt = BLK__get_block_devices(blk_devices, 128);
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < blkdev_cnt; ++i) {
|
||||||
|
printf("blk: %d: %s with capacity %d Bytes\n", blk_devices[i].device_no, blk_devices[i].name, (blk_devices[i].num_sectors * blk_devices[i].sector_size));
|
||||||
|
}
|
||||||
|
|
||||||
start_process("razzle", (char *)&test_razzle);
|
start_process("razzle", (char *)&test_razzle);
|
||||||
start_process("dazzle", (char *)&test_dazzle);
|
start_process("dazzle", (char *)&test_dazzle);
|
||||||
|
@ -38,7 +54,7 @@ int kernel_main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void fault_handler(struct regs *r) {
|
void fault_handler(struct regs *r) {
|
||||||
clear_screen();
|
VGA_clear_screen();
|
||||||
printf("!!! Kernel Panic !!!\n");
|
printf("!!! Kernel Panic !!!\n");
|
||||||
switch (r->int_no) {
|
switch (r->int_no) {
|
||||||
case 0: {
|
case 0: {
|
||||||
|
|
|
@ -1,22 +1,4 @@
|
||||||
#pragma once
|
#include "memory.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
// Below doesn't work!
|
|
||||||
// uint8_t streq(char *ptr, char* ptr2) {
|
|
||||||
// while (1 == 1) {
|
|
||||||
// if (*ptr != *ptr2) {
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (*ptr == '\0') {
|
|
||||||
// return 1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ptr++;
|
|
||||||
// ptr2++;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
uint8_t memseq(char *ptr, char *ptr2, uint32_t len) {
|
uint8_t memseq(char *ptr, char *ptr2, uint32_t len) {
|
||||||
for (uint32_t i = 0; i < len; i++) {
|
for (uint32_t i = 0; i < len; i++) {
|
9
kernel/memory/memory.h
Normal file
9
kernel/memory/memory.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint8_t memseq(char *, char *, uint32_t len);
|
||||||
|
uint8_t streq(char *, char *);
|
||||||
|
void memset(char *, char, uint32_t);
|
||||||
|
void memcpy(char *, char *, uint32_t);
|
||||||
|
void strncpy(char *, char *, uint32_t);
|
|
@ -1,28 +1,14 @@
|
||||||
#pragma once
|
#include "./pci.h"
|
||||||
#include "./pci_supp.c"
|
#include "../../supp/pci_supp.c"
|
||||||
#include "vga.c"
|
#include "../io/io.h"
|
||||||
#include <stdint.h>
|
#include "../memory/memory.h"
|
||||||
|
|
||||||
#ifdef ARCH_I386
|
#ifdef ARCH_I386
|
||||||
#include "../arch/i386/asm.c"
|
#include "../../arch/i386/asm/asm.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PCI_NO_VENDOR (0xFFFF)
|
struct pci_device pci_devices_list[PCI_MAX_DEVICES];
|
||||||
#define PCI_MAX_NAMESIZE (128)
|
uint32_t pci_devices_count;
|
||||||
#define PCI_MAX_DEVICES (256)
|
|
||||||
|
|
||||||
struct pci_device {
|
|
||||||
uint16_t device_id;
|
|
||||||
uint16_t vendor_id;
|
|
||||||
char device_name[PCI_MAX_NAMESIZE];
|
|
||||||
char vendor_name[PCI_MAX_NAMESIZE];
|
|
||||||
uint32_t bar[6];
|
|
||||||
uint8_t class_code;
|
|
||||||
uint8_t subclass_code;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct pci_device pci_devices_list[PCI_MAX_DEVICES];
|
|
||||||
static uint32_t pci_devices_count;
|
|
||||||
|
|
||||||
uint16_t pci_read_config(uint8_t bus, uint8_t slot, uint8_t function,
|
uint16_t pci_read_config(uint8_t bus, uint8_t slot, uint8_t function,
|
||||||
uint8_t offset) {
|
uint8_t offset) {
|
||||||
|
@ -60,10 +46,10 @@ uint32_t ascii_byte_to_num(char c) {
|
||||||
|
|
||||||
void pci_get_vendor_dev_name(uint16_t vendor_id, uint16_t device_id,
|
void pci_get_vendor_dev_name(uint16_t vendor_id, uint16_t device_id,
|
||||||
char *vendor_name, char *device_name) {
|
char *vendor_name, char *device_name) {
|
||||||
int len = ___build_supp_pci_pci_ids_len;
|
int len = ___build_supp_pci_pci_ids_len;
|
||||||
unsigned char *buf = &___build_supp_pci_pci_ids[0];
|
unsigned char *buf = &___build_supp_pci_pci_ids[0];
|
||||||
int pps = PPS_NUM_1;
|
int pps = PPS_NUM_1;
|
||||||
int ppss = PPSS_VENDOR;
|
int ppss = PPSS_VENDOR;
|
||||||
|
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
|
22
kernel/pci/pci.h
Normal file
22
kernel/pci/pci.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define PCI_NO_VENDOR (0xFFFF)
|
||||||
|
#define PCI_MAX_NAMESIZE (128)
|
||||||
|
#define PCI_MAX_DEVICES (256)
|
||||||
|
|
||||||
|
struct pci_device {
|
||||||
|
uint16_t device_id;
|
||||||
|
uint16_t vendor_id;
|
||||||
|
char device_name[PCI_MAX_NAMESIZE];
|
||||||
|
char vendor_name[PCI_MAX_NAMESIZE];
|
||||||
|
uint32_t bar[6];
|
||||||
|
uint8_t class_code;
|
||||||
|
uint8_t subclass_code;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct pci_device pci_devices_list[PCI_MAX_DEVICES];
|
||||||
|
extern uint32_t pci_devices_count;
|
||||||
|
|
||||||
|
void pci_enumerate_devices();
|
124888
kernel/pci_supp.c
124888
kernel/pci_supp.c
File diff suppressed because it is too large
Load diff
112
kernel/rsdp.c
112
kernel/rsdp.c
|
@ -1,112 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "memory.c"
|
|
||||||
#include "vga.c"
|
|
||||||
|
|
||||||
struct rsdp_t {
|
|
||||||
char signature[8];
|
|
||||||
uint8_t checksum;
|
|
||||||
char oem_id[6];
|
|
||||||
uint8_t revision;
|
|
||||||
uint32_t rsdt_address;
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
|
|
||||||
struct xsdp_t {
|
|
||||||
char signature[8];
|
|
||||||
uint8_t checksum;
|
|
||||||
char oem_id[6];
|
|
||||||
uint8_t revision;
|
|
||||||
uint32_t unused;
|
|
||||||
uint32_t length;
|
|
||||||
uint32_t xsdt_addr_hi;
|
|
||||||
uint32_t xsdt_addr_lo;
|
|
||||||
uint8_t checksum_ext;
|
|
||||||
uint8_t unused_[3];
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
|
|
||||||
struct acpi_header_t {
|
|
||||||
char signature[4];
|
|
||||||
uint32_t length;
|
|
||||||
uint8_t revision;
|
|
||||||
uint8_t checksum;
|
|
||||||
char oem_id[6];
|
|
||||||
char oem_table_id[8];
|
|
||||||
uint32_t oem_revision;
|
|
||||||
uint32_t creator_id;
|
|
||||||
uint32_t creator_division;
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
|
|
||||||
struct rsdt_t {
|
|
||||||
struct acpi_header_t header;
|
|
||||||
uint32_t pointer[64];
|
|
||||||
};
|
|
||||||
|
|
||||||
uint8_t validate(struct rsdp_t *ptr) {
|
|
||||||
char sig[] = "RSD PTR ";
|
|
||||||
if (!memseq(ptr->signature, sig, 8)) return 0;
|
|
||||||
|
|
||||||
uint8_t *rsdp_bytes = (uint8_t *) ptr;
|
|
||||||
uint8_t sum = 0;
|
|
||||||
for(uint8_t i = 0; i < 20; i++) {
|
|
||||||
sum += rsdp_bytes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sum == 0 && ptr->revision == 2) {
|
|
||||||
printf_nolock("acpi: ACPI v2+ not yet supported :(\n");
|
|
||||||
for(;;){}
|
|
||||||
// TODO: test with ACPI 2 System
|
|
||||||
struct xsdp_t *r2_ptr = (struct xsdp_t*) ptr;
|
|
||||||
|
|
||||||
uint8_t *xsdp_bytes = ((uint8_t *) r2_ptr) + 8;
|
|
||||||
for(uint8_t i = 0; i < 16; i++) {
|
|
||||||
sum += xsdp_bytes[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sum == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* find_table(struct rsdt_t* table, char* sig) {
|
|
||||||
uint32_t entries = (table->header.length - sizeof table->header) / 4;
|
|
||||||
for (uint32_t i = 0; i < entries; i++) {
|
|
||||||
struct acpi_header_t* entry = (struct acpi_header_t*) table->pointer[i];
|
|
||||||
if (memseq(entry->signature, sig, 4)) {
|
|
||||||
printf_nolock("Found %s / %s\n", entry->oem_id, entry->signature);
|
|
||||||
printf_nolock("Signature: %s\n", entry->signature);
|
|
||||||
printf_nolock("Length : %d\n", entry->length);
|
|
||||||
printf_nolock("Oem ID : %s\n", entry->oem_id);
|
|
||||||
printf_nolock("Checksum : %d\n", entry->checksum);
|
|
||||||
return (void*)entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf_nolock("Not Found");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void find_rsdp() {
|
|
||||||
struct rsdp_t *ptr;
|
|
||||||
|
|
||||||
volatile uint8_t found = 0;
|
|
||||||
for (uint32_t addr = 0x00000000; addr <= 0x000FFFFF; addr++) {
|
|
||||||
ptr = (struct rsdp_t *) addr;
|
|
||||||
|
|
||||||
if (validate(ptr)) {
|
|
||||||
found = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
uint8_t* ebda = (uint8_t*)(*((uint16_t*)0x40e) << 4);
|
|
||||||
for (uint32_t i = 0; i <= 1024; i += 16) {
|
|
||||||
ptr = (struct rsdp_t*) ebda;
|
|
||||||
if (validate(ptr)) {
|
|
||||||
found = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf_nolock("acpi: RSDP Found [OEM: %s, SIG: %s]\n", ptr->oem_id, ptr->signature);
|
|
||||||
}
|
|
|
@ -1,29 +1,13 @@
|
||||||
#pragma once
|
#include "scheduler.h"
|
||||||
|
#include "../io/io.h"
|
||||||
|
#include "../memory/memory.h"
|
||||||
|
|
||||||
#ifdef ARCH_I386
|
#ifdef ARCH_I386
|
||||||
#include "../arch/i386/scheduler.c"
|
#include "../../arch/i386/scheduler/scheduler.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "./memory.c"
|
struct task_struct process_table[MAX_PROCESSES];
|
||||||
#include "./vga.c"
|
uint32_t current_pid;
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define ADDRESS_SPACE_SIZE 1000000
|
|
||||||
#define MAX_PROCESSES 128
|
|
||||||
|
|
||||||
enum task_state_t { TASKSTATE_unused, TASKSTATE_ready, TASKSTATE_blocked };
|
|
||||||
|
|
||||||
struct task_struct {
|
|
||||||
uint32_t pid;
|
|
||||||
enum task_state_t state;
|
|
||||||
struct regs registers;
|
|
||||||
unsigned int address_base;
|
|
||||||
char *allocd_addr;
|
|
||||||
char *process_name;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct task_struct process_table[MAX_PROCESSES];
|
|
||||||
static uint32_t current_pid;
|
|
||||||
|
|
||||||
void init_process_table() {
|
void init_process_table() {
|
||||||
for (uint32_t i = 0; i < MAX_PROCESSES; i++) {
|
for (uint32_t i = 0; i < MAX_PROCESSES; i++) {
|
29
kernel/scheduler/scheduler.h
Normal file
29
kernel/scheduler/scheduler.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef ARCH_I386
|
||||||
|
#include "../../arch/i386/scheduler/scheduler.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ADDRESS_SPACE_SIZE 1000000
|
||||||
|
#define MAX_PROCESSES 128
|
||||||
|
|
||||||
|
enum task_state_t { TASKSTATE_unused, TASKSTATE_ready, TASKSTATE_blocked };
|
||||||
|
|
||||||
|
struct task_struct {
|
||||||
|
uint32_t pid;
|
||||||
|
enum task_state_t state;
|
||||||
|
struct regs registers;
|
||||||
|
unsigned int address_base;
|
||||||
|
char *allocd_addr;
|
||||||
|
char *process_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct task_struct process_table[MAX_PROCESSES];
|
||||||
|
extern uint32_t current_pid;
|
||||||
|
|
||||||
|
void init_process_table();
|
||||||
|
void start_process(char *, char *);
|
||||||
|
void process_debug();
|
||||||
|
void schedule(struct regs *);
|
|
@ -1,9 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef ARCH_I386
|
|
||||||
#include "../arch/i386/asm.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void sl_acquire(uint32_t *lock) { __sl_acquire(lock); }
|
|
||||||
|
|
||||||
void sl_release(uint32_t *lock) { __sl_release(lock); }
|
|
9
kernel/spin_lock.h
Normal file
9
kernel/spin_lock.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef ARCH_I386
|
||||||
|
#include "../arch/i386/asm/asm.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void sl_acquire(uint32_t *lock) { __sl_acquire(lock); }
|
||||||
|
|
||||||
|
static inline void sl_release(uint32_t *lock) { __sl_release(lock); }
|
145
kernel/syscall.c
145
kernel/syscall.c
|
@ -1,145 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "scheduler.c"
|
|
||||||
#include "ps2.c"
|
|
||||||
#include "pci.c"
|
|
||||||
#include "vga.c"
|
|
||||||
|
|
||||||
#ifdef ARCH_I386
|
|
||||||
#include "../arch/i386/syscall.c"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum syscall_type_d { SYSCALL_yield, SYSCALL_getc, SYSCALL_exit, SYSCALL_lspci, SYSCALL_lsproc };
|
|
||||||
|
|
||||||
void yield() { INVOKE_SYSCALL(SYSCALL_yield); }
|
|
||||||
char getc() {
|
|
||||||
INVOKE_SYSCALL(SYSCALL_getc);
|
|
||||||
|
|
||||||
char result;
|
|
||||||
__asm__ volatile (
|
|
||||||
"movb %%al, %0"
|
|
||||||
: "=r"(result)
|
|
||||||
);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
uint32_t lspci(struct pci_device* devlist, uint32_t len) {
|
|
||||||
int result = 0;
|
|
||||||
__asm__ volatile (
|
|
||||||
"movl %0, %%ebx"
|
|
||||||
: : "r"((uint32_t) devlist) : "%ebx"
|
|
||||||
);
|
|
||||||
|
|
||||||
__asm__ volatile (
|
|
||||||
"movl %0, %%ecx"
|
|
||||||
: : "r"(len) : "%ecx"
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
INVOKE_SYSCALL(SYSCALL_lspci);
|
|
||||||
|
|
||||||
__asm__ volatile (
|
|
||||||
"movl %%eax, %k0"
|
|
||||||
: "=r"(result)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t lsproc(struct task_struct* proclist, uint32_t len) {
|
|
||||||
int result = 0;
|
|
||||||
__asm__ volatile (
|
|
||||||
"movl %0, %%ebx"
|
|
||||||
: : "r"((uint32_t) proclist) : "%ebx"
|
|
||||||
);
|
|
||||||
|
|
||||||
__asm__ volatile (
|
|
||||||
"movl %0, %%ecx"
|
|
||||||
: : "r"(len) : "%ecx"
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
INVOKE_SYSCALL(SYSCALL_lsproc);
|
|
||||||
|
|
||||||
__asm__ volatile (
|
|
||||||
"movl %%eax, %k0"
|
|
||||||
: "=r"(result)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __syscall_yield(struct regs *r) {
|
|
||||||
// for now, just reschedule
|
|
||||||
// TODO: reset PIT timer so
|
|
||||||
// next process doesn't get an
|
|
||||||
// unreasonably small quantum
|
|
||||||
|
|
||||||
schedule(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
void syscall(struct regs *r) {
|
|
||||||
int syscall_no = r->eax;
|
|
||||||
|
|
||||||
switch (syscall_no) {
|
|
||||||
|
|
||||||
case SYSCALL_yield: {
|
|
||||||
__syscall_yield(r);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
case SYSCALL_getc: {
|
|
||||||
process_table[current_pid].state = TASKSTATE_blocked;
|
|
||||||
|
|
||||||
for(uint32_t i = 0; i < MAX_PROCESSES; i++) {
|
|
||||||
if(!ps2_waiters[i].alloc) {
|
|
||||||
ps2_waiters[i].alloc = 1;
|
|
||||||
ps2_waiters[i].pid = current_pid;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__syscall_yield(r);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
case SYSCALL_lspci: {
|
|
||||||
uint32_t len = r->ecx;
|
|
||||||
len = len < pci_devices_count ? len : pci_devices_count;
|
|
||||||
struct pci_device* devlist = (struct pci_device*) r->ebx;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < len; ++i) {
|
|
||||||
devlist[i] = pci_devices_list[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
r->eax = len;
|
|
||||||
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
case SYSCALL_lsproc: {
|
|
||||||
uint32_t len = r->ecx;
|
|
||||||
struct task_struct*proclist = (struct task_struct*) r->ebx;
|
|
||||||
|
|
||||||
uint32_t i = 0, j = 0;
|
|
||||||
for (; i < len; ++i, ++j) {
|
|
||||||
for(; j < MAX_PROCESSES && process_table[j].state == TASKSTATE_unused; ++j) {}
|
|
||||||
if (j == MAX_PROCESSES) break;
|
|
||||||
|
|
||||||
proclist[i] = process_table[j];
|
|
||||||
}
|
|
||||||
|
|
||||||
r->eax = i;
|
|
||||||
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
case SYSCALL_exit: {
|
|
||||||
process_table[current_pid].state = TASKSTATE_unused;
|
|
||||||
__syscall_yield(r);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
149
kernel/syscall/syscall.c
Normal file
149
kernel/syscall/syscall.c
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
#include "./syscall.h"
|
||||||
|
#include "../drivers/ps2/ps2.h"
|
||||||
|
#include "../io/io.h"
|
||||||
|
#include "../pci/pci.h"
|
||||||
|
#include "../scheduler/scheduler.h"
|
||||||
|
|
||||||
|
#ifdef ARCH_I386
|
||||||
|
#include "../../arch/i386/syscall.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum syscall_type_d {
|
||||||
|
SYSCALL_yield,
|
||||||
|
SYSCALL_getc,
|
||||||
|
SYSCALL_exit,
|
||||||
|
SYSCALL_lspci,
|
||||||
|
SYSCALL_lsproc,
|
||||||
|
SYSCALL_powerctl
|
||||||
|
};
|
||||||
|
|
||||||
|
void powerctl(uint32_t power_mode) {
|
||||||
|
// TODO: Add reboot mode when ACPI is done
|
||||||
|
INVOKE_SYSCALL(SYSCALL_powerctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void yield() { INVOKE_SYSCALL(SYSCALL_yield); }
|
||||||
|
char getc() {
|
||||||
|
INVOKE_SYSCALL(SYSCALL_getc);
|
||||||
|
|
||||||
|
char result;
|
||||||
|
__asm__ volatile("movb %%al, %0" : "=r"(result));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint32_t lspci(struct pci_device *devlist, uint32_t len) {
|
||||||
|
int result = 0;
|
||||||
|
__asm__ volatile("movl %0, %%ebx" : : "r"((uint32_t)devlist) : "%ebx");
|
||||||
|
|
||||||
|
__asm__ volatile("movl %0, %%ecx" : : "r"(len) : "%ecx");
|
||||||
|
|
||||||
|
INVOKE_SYSCALL(SYSCALL_lspci);
|
||||||
|
|
||||||
|
__asm__ volatile("movl %%eax, %k0" : "=r"(result));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t lsproc(struct task_struct *proclist, uint32_t len) {
|
||||||
|
int result = 0;
|
||||||
|
__asm__ volatile("movl %0, %%ebx" : : "r"((uint32_t)proclist) : "%ebx");
|
||||||
|
|
||||||
|
__asm__ volatile("movl %0, %%ecx" : : "r"(len) : "%ecx");
|
||||||
|
|
||||||
|
INVOKE_SYSCALL(SYSCALL_lsproc);
|
||||||
|
|
||||||
|
__asm__ volatile("movl %%eax, %k0" : "=r"(result));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __syscall_powerctl() {
|
||||||
|
// TODO: Implement properly
|
||||||
|
printf_nolock("Attempting shutdown using hypervisor-specific methods.");
|
||||||
|
printf_nolock("ACPI is not yet supported.");
|
||||||
|
outw(0x604, 0x2000);
|
||||||
|
outw(0x4004, 0x3400);
|
||||||
|
outw(0x600, 0x34);
|
||||||
|
outw(0xB004, 0x2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __syscall_yield(struct regs *r) {
|
||||||
|
// for now, just reschedule
|
||||||
|
// TODO: reset PIT timer so
|
||||||
|
// next process doesn't get an
|
||||||
|
// unreasonably small quantum
|
||||||
|
|
||||||
|
schedule(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void syscall(struct regs *r) {
|
||||||
|
int syscall_no = r->eax;
|
||||||
|
|
||||||
|
switch (syscall_no) {
|
||||||
|
|
||||||
|
case SYSCALL_powerctl: {
|
||||||
|
__syscall_powerctl();
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
case SYSCALL_yield: {
|
||||||
|
__syscall_yield(r);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
case SYSCALL_getc: {
|
||||||
|
process_table[current_pid].state = TASKSTATE_blocked;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < MAX_PROCESSES; i++) {
|
||||||
|
if (!ps2_waiters[i].alloc) {
|
||||||
|
ps2_waiters[i].alloc = 1;
|
||||||
|
ps2_waiters[i].pid = current_pid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__syscall_yield(r);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
case SYSCALL_lspci: {
|
||||||
|
uint32_t len = r->ecx;
|
||||||
|
len = len < pci_devices_count ? len : pci_devices_count;
|
||||||
|
struct pci_device *devlist = (struct pci_device *)r->ebx;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < len; ++i) {
|
||||||
|
devlist[i] = pci_devices_list[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
r->eax = len;
|
||||||
|
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
case SYSCALL_lsproc: {
|
||||||
|
uint32_t len = r->ecx;
|
||||||
|
struct task_struct *proclist = (struct task_struct *)r->ebx;
|
||||||
|
|
||||||
|
uint32_t i = 0, j = 0;
|
||||||
|
for (; i < len; ++i, ++j) {
|
||||||
|
for (; j < MAX_PROCESSES && process_table[j].state == TASKSTATE_unused;
|
||||||
|
++j) {
|
||||||
|
}
|
||||||
|
if (j == MAX_PROCESSES)
|
||||||
|
break;
|
||||||
|
|
||||||
|
proclist[i] = process_table[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
r->eax = i;
|
||||||
|
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
case SYSCALL_exit: {
|
||||||
|
process_table[current_pid].state = TASKSTATE_unused;
|
||||||
|
__syscall_yield(r);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
12
kernel/syscall/syscall.h
Normal file
12
kernel/syscall/syscall.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define POWERCTL_shutdown (0)
|
||||||
|
#define POWERCTL_reboot (1)
|
||||||
|
|
||||||
|
void powerctl(uint32_t);
|
||||||
|
char getc();
|
||||||
|
uint32_t lspci();
|
||||||
|
uint32_t lsproc();
|
||||||
|
void yield();
|
|
@ -1,133 +0,0 @@
|
||||||
/*
|
|
||||||
* Since RAZZLE doesn't have disk support yet, all code for test processes are
|
|
||||||
* included in this file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "./scheduler.c"
|
|
||||||
#include "./spin_lock.c"
|
|
||||||
#include "./syscall.c"
|
|
||||||
#include "./scheduler.c"
|
|
||||||
|
|
||||||
uint32_t lock2 = 0;
|
|
||||||
|
|
||||||
uint32_t counter;
|
|
||||||
|
|
||||||
void test_razzle() {
|
|
||||||
sl_acquire(&lock2);
|
|
||||||
counter = 0;
|
|
||||||
sl_release(&lock2);
|
|
||||||
for (;;) {
|
|
||||||
sl_acquire(&lock2);
|
|
||||||
counter++;
|
|
||||||
//row = 1;
|
|
||||||
//col = 0;
|
|
||||||
//printf("%s (pid %d): %u \n", process_table[current_pid].process_name,
|
|
||||||
// current_pid, i);
|
|
||||||
sl_release(&lock2);
|
|
||||||
yield();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sh_cpuid() {
|
|
||||||
char model[13];
|
|
||||||
uint32_t res[3];
|
|
||||||
__asm__ volatile ("mov $0, %%eax; cpuid; mov %%ebx, %0; mov %%edx, %1; mov %%ecx, %2;" : "=r" (res[0]), "=r" (res[1]), "=r" (res[2]) ::"ebx", "ecx", "edx");
|
|
||||||
for(uint32_t i = 0; i < 3; i++) {
|
|
||||||
model[(i*4) + 0] = (res[i] >> 0) & 0xFF;
|
|
||||||
model[(i*4) + 1] = (res[i] >> 8) & 0xFF;
|
|
||||||
model[(i*4) + 2] = (res[i] >> 16) & 0xFF;
|
|
||||||
model[(i*4) + 3] = (res[i] >> 24) & 0xFF;
|
|
||||||
}
|
|
||||||
model[12] = '\0';
|
|
||||||
printf("%s\n", model);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sh_lspci() {
|
|
||||||
struct pci_device devlist[7];
|
|
||||||
int devices = lspci(&devlist[0], 7);
|
|
||||||
for(int j = 0; j < devices; ++j) {
|
|
||||||
printf("%s %s (%d %d)\n", devlist[j].vendor_name, devlist[j].device_name, devlist[j].class_code, devlist[j].subclass_code);
|
|
||||||
printf("Device ID: %x\n", devlist[j].device_id);
|
|
||||||
printf("Vendor ID: %x\n", devlist[j].vendor_id);
|
|
||||||
printf("Bar 5 : %x %u\n\n", devlist[j].bar[5], devlist[j].bar[5]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sh_lsproc() {
|
|
||||||
struct task_struct proclist[7];
|
|
||||||
int procs = lsproc(&proclist[0], 7);
|
|
||||||
for(int j = 0; j < procs; ++j) {
|
|
||||||
switch (proclist[j].state) {
|
|
||||||
case TASKSTATE_ready:
|
|
||||||
printf("R");
|
|
||||||
break;
|
|
||||||
case TASKSTATE_blocked:
|
|
||||||
printf("B");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("?");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf(" %d: %s", proclist[j].pid, proclist[j].process_name);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_dazzle() {
|
|
||||||
char prompt[] = "you@razzle ~$ ";
|
|
||||||
char command[2048];
|
|
||||||
|
|
||||||
printf("%s", prompt);
|
|
||||||
uint32_t i = 0;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
char c = getc();
|
|
||||||
sl_acquire(&lock2);
|
|
||||||
|
|
||||||
switch(c) {
|
|
||||||
case '\b':
|
|
||||||
command[i--] = '\0';
|
|
||||||
printf("\b \b");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '\n':
|
|
||||||
command[i] = '\0';
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
if (streq(command, "lspci")) {
|
|
||||||
sh_lspci();
|
|
||||||
} else if (streq(command, "cpuid")) {
|
|
||||||
sh_cpuid();
|
|
||||||
} else if (streq(command, "help")) {
|
|
||||||
printf("dazzle, the shell for RAZZLE\n");
|
|
||||||
printf("--------------------------------------------------------\n");
|
|
||||||
printf("help : print this menu\n");
|
|
||||||
printf("cpuid : print CPU vendor id string\n");
|
|
||||||
printf("lspci : print list of PCI devices\n");
|
|
||||||
printf("lsproc : print list of running processes\n");
|
|
||||||
printf("counter : print counter maintained by background process\n");
|
|
||||||
} else if (streq(command, "counter")) {
|
|
||||||
printf("%d\n", counter);
|
|
||||||
} else if (streq(command, "lsproc")) {
|
|
||||||
sh_lsproc();
|
|
||||||
} else {
|
|
||||||
printf("Unknown command\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s", prompt);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
printf("%c", c);
|
|
||||||
command[i++] = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sl_release(&lock2);
|
|
||||||
yield();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,5 +6,6 @@ in
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
pkgs.cdrkit
|
pkgs.cdrkit
|
||||||
pkgs.qemu
|
pkgs.qemu
|
||||||
|
pkgs.xxd
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
124887
supp/pci_supp.c
Normal file
124887
supp/pci_supp.c
Normal file
File diff suppressed because it is too large
Load diff
145
supp/test_processes.c
Normal file
145
supp/test_processes.c
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
/*
|
||||||
|
* Since RAZZLE doesn't have disk support yet, all code for test processes are
|
||||||
|
* included in this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../kernel/io/io.h"
|
||||||
|
#include "../kernel/memory/memory.h"
|
||||||
|
#include "../kernel/pci/pci.h"
|
||||||
|
#include "../kernel/scheduler/scheduler.h"
|
||||||
|
#include "../kernel/spin_lock.h"
|
||||||
|
#include "../kernel/syscall/syscall.h"
|
||||||
|
|
||||||
|
uint32_t lock2 = 0;
|
||||||
|
|
||||||
|
uint32_t counter;
|
||||||
|
|
||||||
|
void test_razzle() {
|
||||||
|
sl_acquire(&lock2);
|
||||||
|
counter = 0;
|
||||||
|
sl_release(&lock2);
|
||||||
|
for (;;) {
|
||||||
|
sl_acquire(&lock2);
|
||||||
|
counter++;
|
||||||
|
// row = 1;
|
||||||
|
// col = 0;
|
||||||
|
// printf("%s (pid %d): %u \n", process_table[current_pid].process_name,
|
||||||
|
// current_pid, i);
|
||||||
|
sl_release(&lock2);
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sh_cpuid() {
|
||||||
|
char model[13];
|
||||||
|
uint32_t res[3];
|
||||||
|
__asm__ volatile(
|
||||||
|
"mov $0, %%eax; cpuid; mov %%ebx, %0; mov %%edx, %1; mov %%ecx, %2;"
|
||||||
|
: "=r"(res[0]), "=r"(res[1]), "=r"(res[2])::"ebx", "ecx", "edx");
|
||||||
|
for (uint32_t i = 0; i < 3; i++) {
|
||||||
|
model[(i * 4) + 0] = (res[i] >> 0) & 0xFF;
|
||||||
|
model[(i * 4) + 1] = (res[i] >> 8) & 0xFF;
|
||||||
|
model[(i * 4) + 2] = (res[i] >> 16) & 0xFF;
|
||||||
|
model[(i * 4) + 3] = (res[i] >> 24) & 0xFF;
|
||||||
|
}
|
||||||
|
model[12] = '\0';
|
||||||
|
printf("%s\n", model);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sh_lspci() {
|
||||||
|
struct pci_device devlist[7];
|
||||||
|
int devices = lspci(&devlist[0], 7);
|
||||||
|
for (int j = 0; j < devices; ++j) {
|
||||||
|
printf("%s %s (%d %d)\n", devlist[j].vendor_name, devlist[j].device_name,
|
||||||
|
devlist[j].class_code, devlist[j].subclass_code);
|
||||||
|
printf("Device ID: %x\n", devlist[j].device_id);
|
||||||
|
printf("Vendor ID: %x\n", devlist[j].vendor_id);
|
||||||
|
printf("Bar 5 : %x %u\n\n", devlist[j].bar[5], devlist[j].bar[5]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sh_lsproc() {
|
||||||
|
struct task_struct proclist[7];
|
||||||
|
int procs = lsproc(&proclist[0], 7);
|
||||||
|
for (int j = 0; j < procs; ++j) {
|
||||||
|
switch (proclist[j].state) {
|
||||||
|
case TASKSTATE_ready:
|
||||||
|
printf("R");
|
||||||
|
break;
|
||||||
|
case TASKSTATE_blocked:
|
||||||
|
printf("B");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("?");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf(" %d: %s", proclist[j].pid, proclist[j].process_name);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_dazzle() {
|
||||||
|
char prompt[] = "you@razzle ~$ ";
|
||||||
|
char command[2048];
|
||||||
|
|
||||||
|
printf("%s", prompt);
|
||||||
|
uint32_t i = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
char c = getc();
|
||||||
|
sl_acquire(&lock2);
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case '\b':
|
||||||
|
if (i == 0)
|
||||||
|
break;
|
||||||
|
command[i--] = '\0';
|
||||||
|
printf("\b \b");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\n':
|
||||||
|
command[i] = '\0';
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
if (streq(command, "lspci")) {
|
||||||
|
sh_lspci();
|
||||||
|
} else if (streq(command, "cpuid")) {
|
||||||
|
sh_cpuid();
|
||||||
|
} else if (streq(command, "help")) {
|
||||||
|
printf("dazzle, the shell for RAZZLE\n");
|
||||||
|
printf("--------------------------------------------------------\n");
|
||||||
|
printf("help : print this menu\n");
|
||||||
|
printf("cpuid : print CPU vendor id string\n");
|
||||||
|
printf("lspci : print list of PCI devices\n");
|
||||||
|
printf("lsproc : print list of running processes\n");
|
||||||
|
printf("counter : print counter maintained by background process\n");
|
||||||
|
printf("shutdown: shuts down the VM using VM-specific methods\n");
|
||||||
|
} else if (streq(command, "counter")) {
|
||||||
|
printf("%d\n", counter);
|
||||||
|
} else if (streq(command, "lsproc")) {
|
||||||
|
sh_lsproc();
|
||||||
|
} else if (streq(command, "shutdown")) {
|
||||||
|
powerctl(POWERCTL_shutdown);
|
||||||
|
printf("If the computer is still on, you must manually power it off. "
|
||||||
|
"ACPI is not yet implemented.\n");
|
||||||
|
} else {
|
||||||
|
printf("Unknown command\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s", prompt);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("%c", c);
|
||||||
|
command[i++] = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sl_release(&lock2);
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue