This commit is contained in:
Nicholas Orlowsky 2025-02-28 21:25:17 -05:00
parent ce2b373313
commit 9114529153
46 changed files with 126016 additions and 125522 deletions

8
.clang-format Normal file
View file

@ -0,0 +1,8 @@
---
BasedOnStyle: LLVM
AlignAfterOpenBracket: Align
AlignConsecutiveDeclarations: 'true'
AlignTrailingComments: 'true'
DisableFormat: 'false'
...

View file

@ -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
View 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));
}

View file

@ -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"); }

View file

@ -1,6 +1,6 @@
#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 {

View file

@ -1,6 +1,6 @@
#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"
@ -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)

View file

@ -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"

View file

@ -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) {

View 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
View 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
View 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
View file

@ -0,0 +1,3 @@
#pragma once
void find_rsdp();

17
kernel/drivers/blk/blk.h Normal file
View 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);

View 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);
}

View 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);

View 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++;
}
}
}

View 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);

View file

@ -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,
@ -244,14 +242,6 @@ 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;

16
kernel/drivers/ps2/ps2.h Normal file
View 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);

View file

@ -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);
}

View 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);
}

View 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
View 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
View file

@ -0,0 +1,5 @@
#pragma once
void VGA_clear_screen();
void VGA_putc(char);
void VGA_flush();

View file

@ -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);
} }
@ -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
View file

@ -0,0 +1,7 @@
#pragma once
#include <stdarg.h>
void putc(char);
void printf(char *, ...);
void printf_nolock(char *, ...);

View file

@ -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: {

View file

@ -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
View 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);

View file

@ -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) {

22
kernel/pci/pci.h Normal file
View 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();

File diff suppressed because it is too large Load diff

View file

@ -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);
}

View file

@ -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++) {

View 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 *);

View file

@ -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
View 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); }

View file

@ -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
View 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
View 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();

View file

@ -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();
}
}

View file

@ -6,5 +6,6 @@ in
nativeBuildInputs = [ nativeBuildInputs = [
pkgs.cdrkit pkgs.cdrkit
pkgs.qemu pkgs.qemu
pkgs.xxd
]; ];
} }

124887
supp/pci_supp.c Normal file

File diff suppressed because it is too large Load diff

145
supp/test_processes.c Normal file
View 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();
}
}