CeDOS - Commit 0187a3fb

Merge pull request #1 from celinakalus/develop Improvements to the file system interface, addition of graphics modes, improvements of the shell interface. - Applications can now open files for reading - cat/hexdump commands prints the contents of a file on the terminal - Bitmap images are now "viewable" through the imgview command (it does not understand the bitmap format itself, so it prints the header as well, and images need to be 320px wide)
Celina Sophie Kalus
Fri, 07 Apr 2023 12:25:15 +0200
40 files changed, 562 insertions(+), 171 deletions(-)
M .gitignore.gitignore

@@ -4,5 +4,6 @@ docs/*

*.img *.o *.bin +img-contents/* .vscode
A include/cedos/drivers/graphics.h

@@ -0,0 +1,7 @@

+#ifndef GRAPHICS_H +#define GRAPHICS_H + +int graphics_set_mode(int mode); +int graphics_init(void); + +#endif
M include/cedos/file.hinclude/cedos/file.h

@@ -5,6 +5,8 @@ #include <stdint.h>

#include "cedos/mm/paging.h" +int file_open(const char *pathname, int flags); +int file_openat(int fd, const char *fname, int flags); int file_read(int fd, char *buffer, uint32_t size); int file_write(int fd, char *buffer, uint32_t size);
M include/linker.hinclude/linker.h

@@ -6,36 +6,20 @@ #define LINKER_H

#include <stdint.h> -extern uint8_t __SS_VMA; -extern uint8_t __SS_LMA; -extern uint8_t __SS_SIZE; - extern uint8_t __KERNEL_VMA; extern uint8_t __KERNEL_LMA; extern uint8_t __KERNEL_SIZE; -extern uint8_t __APP_VMA; -extern uint8_t __APP_LMA; -extern uint8_t __APP_SIZE; - -extern uint8_t __ELF_VMA; -extern uint8_t __ELF_LMA; -extern uint8_t __ELF_SIZE; - -#define SS_VMA (&__SS_VMA) -#define SS_LMA (&__SS_LMA) -#define SS_SIZE (uint32_t)(&__SS_SIZE) - -#define KERNEL_VMA (&__KERNEL_VMA) -#define KERNEL_LMA (&__KERNEL_LMA) +#define KERNEL_VMA (void*)(&__KERNEL_VMA) +#define KERNEL_LMA (void*)(&__KERNEL_LMA) #define KERNEL_SIZE (uint32_t)(&__KERNEL_SIZE) -#define APP_VMA (&__APP_VMA) -#define APP_LMA (&__APP_LMA) -#define APP_SIZE (uint32_t)(&__APP_SIZE) +extern uint8_t __REALMD_VMA; +extern uint8_t __REALMD_LMA; +extern uint8_t __REALMD_SIZE; -#define ELF_VMA (&__ELF_VMA) -#define ELF_LMA (&__ELF_LMA) -#define ELF_SIZE (uint32_t)(&__ELF_SIZE) +#define REALMD_VMA (void*)(&__REALMD_VMA) +#define REALMD_LMA (void*)(&__REALMD_LMA) +#define REALMD_SIZE (uint32_t)(&__REALMD_SIZE) #endif
M makefilemakefile

@@ -13,6 +13,7 @@

export CC := $(CROSS_COMP)gcc export LD := $(CROSS_COMP)ld export AS := $(CROSS_COMP)as +export AR := $(CROSS_COMP)ar export OBJCOPY := $(CROSS_COMP)objcopy export OBJDUMP := $(CROSS_COMP)objdump

@@ -51,7 +52,7 @@

export CCFLAGS export GLOBAL_BUILD -MODULES := boot kernel apps +MODULES := boot kernel libcedos shell OBJECTS := $(patsubst %,$(LOCAL_BUILD)/%.o,$(MODULES)) $(LOCAL_BUILD)/apps_raw.o DIRS := $(LOCAL_BUILD)

@@ -69,7 +70,8 @@ > mkfs.fat -n "cedos" -S 512 -s 8 -r 32 $@

> mkdir -p ./mnt > sudo mount $@ ./mnt > sudo cp $(LOCAL_BUILD)/kernel.bin ./mnt -> sudo cp $(LOCAL_BUILD)/*.o ./mnt +> sudo cp $(LOCAL_BUILD)/bin/* ./mnt +> sudo cp ./img-contents/* ./mnt > sudo umount ./mnt $(GLOBAL_BUILD)/cedos.img: $(GLOBAL_BUILD)/fat.img | $(MODULES)

@@ -94,9 +96,13 @@ .PHONY: kernel

kernel: > $(MAKE) GLOBAL_BUILD=$(LOCAL_BUILD) -C src/kernel $(LOCAL_BUILD)/kernel.bin -.PHONY: apps -apps: -> $(MAKE) GLOBAL_BUILD=$(LOCAL_BUILD) -C src/apps build +.PHONY: libcedos +libcedos: +> $(MAKE) GLOBAL_BUILD=$(LOCAL_BUILD) -C src/libcedos build + +.PHONY: shell +shell: +> $(MAKE) GLOBAL_BUILD=$(LOCAL_BUILD) -C src/shell build .PHONY: clean clean:
M run.shrun.sh

@@ -1,1 +1,1 @@

-qemu-system-i386 -drive index=0,if=floppy,format=raw,file=./build/release/cedos.img -m 64 -monitor stdio -no-reboot -d int,cpu_reset,exec,in_asm 2> log/run_err.log+qemu-system-i386 -drive index=0,if=floppy,format=raw,file=./build/release/cedos.img -m 64 -monitor stdio -no-reboot -d int,cpu_reset,exec,in_asm -vga std -vnc :0 2> log/run_err.log
M src/apps/common/cedos.csrc/libcedos/cedos.c

@@ -20,6 +20,12 @@ interrupt(0x30, res, 3, 0, 0, 0);

return res; } +int file_openat(int fd, const char *fname, int flags) { + volatile uint32_t res = 0; + interrupt(0x30, res, 6, fd, fname, flags); + return res; +} + int sc_file_read(int fd, char *buffer, uint32_t size) { volatile uint32_t res = 0; interrupt(0x30, res, 0, fd, buffer, size);

@@ -41,4 +47,15 @@

void process_wait(int pid) { volatile uint32_t res = 0; interrupt(0x30, res, 5, pid, 0, 0); +} + +int sc_file_open(char *pathname, int flags) { + volatile uint32_t res = 0; + interrupt(0x30, res, 6, pathname, flags, 0); + return res; +} + +void graphics_set_mode(int mode) { + volatile uint32_t res = 0; + interrupt(0x30, res, 7, mode, 0, 0); }
M src/apps/common/cedos.hsrc/libcedos/include/cedos.h

@@ -11,7 +11,11 @@ int get_pid();

int process_spawn(const char *fname, const char *args); void process_wait(int pid); +void graphics_set_mode(int mode); + int sc_file_read(int fd, char *buffer, uint32_t size); int sc_file_write(int fd, char *buffer, uint32_t size); +int sc_file_openat(int fd, char *buffer, uint32_t size); + #endif
M src/apps/common/stdio.csrc/libcedos/stdio.c

@@ -97,6 +97,12 @@ while (str[length]) { length++; }

print(str, length); } +int print_hex_char(uint8_t c) { + char buffer[2]; + int size = sprint_hex_char(c, buffer); + print(buffer, size); +} + void print_char(char c) { print(&c, 1); }

@@ -117,6 +123,8 @@ if (*fmt == 'X') {

print_uint32(va_arg(args, uint32_t)); } else if (*fmt == 'i') { print_int(va_arg(args, int)); + } else if (*fmt == 'x') { + print_int(va_arg(args, char)); } else if (*fmt == 'u') { print_uint(va_arg(args, unsigned int)); } else if (*fmt == 'p') {
D src/apps/echo.c

@@ -1,8 +0,0 @@

-#include "common/cedos.h" -#include "common/stdio.h" - -#include <stdint.h> - -void main(char *args) { - printf(args); -}
D src/apps/fibonacci.c

@@ -1,19 +0,0 @@

-#include "common/cedos.h" -#include "common/stdio.h" - -#include <stdint.h> - -void main(char *args) { - uint32_t a = 0, b = 1, i = 0; - while (1) { - uint32_t tmp = a + b; - a = b; - b = tmp; - printf("fib (%i) = %i\n", i, a); - i++; - char c = 0; - sc_file_read(0, &c, 1); - if (c == 0x1B) { break; } - //printf("[%c]\n", (int)(uint32_t)c);//yield(); - } -}
D src/apps/makefile

@@ -1,37 +0,0 @@

-.RECIPEPREFIX = > - -LOCAL_BUILD = $(GLOBAL_BUILD)/apps - -SRC_DIR := $(shell pwd) - -C_SOURCES := $(wildcard common/*.c) -S_SOURCES := $(wildcard common/*.s) - -C_OBJECTS := $(patsubst common/%.c,$(LOCAL_BUILD)/common/%.c.o,$(C_SOURCES)) -S_OBJECTS := $(patsubst common/%.s,$(LOCAL_BUILD)/common/%.s.o,$(S_SOURCES)) -OBJECTS = $(S_OBJECTS) $(C_OBJECTS) - -APP_SOURCES := $(wildcard *.c) -APP_OBJECTS := $(patsubst %.c,$(GLOBAL_BUILD)/%.o,$(APP_SOURCES)) - -DIRS := $(sort $(dir $(OBJECTS) $(APP_OBJECTS))) - -$(OBJECTS): | $(DIRS) -$(DIRS): -> $(MKDIR) $(DIRS) - -.PHONY: build -build: $(APP_OBJECTS) -$(GLOBAL_BUILD)/%.o: $(LOCAL_BUILD)/%.o $(OBJECTS) -> $(LD) -T link.txt -Map=$(LOG_DIR)/apps_mapfile.txt -N $^ -o $@ -# > $(OBJCOPY) -I binary -O elf32-i386 $(GLOBAL_BUILD)/apps.o $(GLOBAL_BUILD)/apps_raw.o -# > $(LD) -T link.txt -r $^ -o $(GLOBAL_BUILD)/apps.o --oformat elf32-i386 - -$(LOCAL_BUILD)/%.s.o: %.s -> $(AS) -o $@ $< - -$(LOCAL_BUILD)/%.o: %.c $(wildcard *.h) -> $(CC) -c -I$(INCLUDE_DIR) -I./common $(CCFLAGS) -o $@ $< - -$(LOCAL_BUILD)/%.c.o: %.c $(wildcard *.h) -> $(CC) -c -I$(INCLUDE_DIR) -I./common $(CCFLAGS) -o $@ $<
M src/apps/shell.csrc/shell/shelf.c

@@ -1,9 +1,9 @@

-#include "common/cedos.h" -#include "common/stdio.h" +#include "cedos.h" +#include "stdio.h" #include <stdint.h> -void read_line(char *buffer) { +int read_line(char *buffer) { int i = 0; char c; buffer[0] = 0;

@@ -25,22 +25,41 @@ }

buffer[i] = 0; sc_file_write(0, &c, 1); + + return i; } void main(char *args) { uint32_t a = 0, b = 1, i = 0; printf("\n"); - printf("CeDOS shell\n"); + printf("ShELF shell interface for CeDOS\n"); + printf("Version: " VERSION "\n"); while (1) { printf("/> "); char buffer[256]; - read_line(buffer); + int length = read_line(buffer); + + if (length == 0) { continue; } + + char *file = buffer; + char *args = (char *)(0); + + int i = 0; + while (1) { + if (buffer[i] == ' ') { + buffer[i] = 0; + args = &(buffer[i+1]); + break; + } + + i++; + } //printf("Executing %s...\n", buffer); - int pid = process_spawn(buffer, "Hello, world!\n"); + int pid = process_spawn(file, args); //printf("Child process %i spawned, waiting for termination...\n", pid);
M src/boot/entry.ssrc/boot/entry.s

@@ -158,13 +158,13 @@ or $0x00000001, %eax

mov %eax, %cr0 # perform long jump to set code segment - ljmp $0x8, $protected + ljmp $0x18, $protected .code32 protected: # setup registers with appropriate GDT values - mov $0x10, %eax + mov $0x20, %eax mov %eax, %ds mov %eax, %es mov %eax, %fs

@@ -186,7 +186,7 @@ or $0x80000010, %eax

movl %eax, %cr0 # jump to kernel code - ljmp $8, $0xC0000000 + ljmp $0x18, $0xC0000000 # loop until the heat death of the universe loop:

@@ -227,7 +227,7 @@ .byte 10

.byte 0 GDT_DESCRIPTOR: - .word 0x23 + .word 0x39 .int GDT IDT_DESCRIPTOR:
M src/boot/gdt.csrc/boot/gdt.c

@@ -11,9 +11,15 @@ (uint8_t)(((limit >> 16) & 0x0F) | ((flags << 4) & 0xF0)), \

(uint8_t)(base >> 24) \ } -GDT_ENTRY GDT[5] = { +GDT_ENTRY GDT[7] = { // null descriptor GDT_MAKE_ENTRY(0x00000000, 0x00000000, 0x00, 0x0), + + // 16 bit code descriptor + GDT_MAKE_ENTRY(0x00000000, 0x0000FFFF, 0x9A, 0x8), + + // 16 bit data descriptor + GDT_MAKE_ENTRY(0x00000000, 0x0000FFFF, 0x92, 0x8), // identity mapping (code, ring 0) GDT_MAKE_ENTRY(0x00000000, 0x000FFFFF, 0x9A, 0xC),
M src/boot/gdt.hsrc/boot/gdt.h

@@ -38,6 +38,6 @@

/*! * The GDT. */ -GDT_ENTRY GDT[5]; +GDT_ENTRY GDT[7]; #endif
M src/boot/paging.csrc/boot/paging.c

@@ -5,9 +5,9 @@ #include "fat.h"

void *create_kernel_environment() { - PAGE_DIR_ENTRY (*pdir)[PAGE_ENTRY_COUNT] = (void*)(0 * PAGE_SIZE); - PAGE_TABLE_ENTRY (*kernel)[PAGE_ENTRY_COUNT] = (void*)(1 * PAGE_SIZE); - PAGE_TABLE_ENTRY (*lowmem)[PAGE_ENTRY_COUNT] = (void*)(2 * PAGE_SIZE); + PAGE_DIR_ENTRY (*pdir)[PAGE_ENTRY_COUNT] = (void*)(1 * PAGE_SIZE); + PAGE_TABLE_ENTRY (*kernel)[PAGE_ENTRY_COUNT] = (void*)(2 * PAGE_SIZE); + PAGE_TABLE_ENTRY (*lowmem)[PAGE_ENTRY_COUNT] = (void*)(3 * PAGE_SIZE); // set everything to zero memset(pdir, 0, 3 * PAGE_SIZE);
A src/kernel/drivers/graphics.c

@@ -0,0 +1,21 @@

+#include "cedos/drivers/graphics.h" +#include "cedos/mm/paging.h" + +#include "string.h" +#include "linker.h" + +#include <stdint.h> + +extern void realmode_int10h(uint32_t eax, uint32_t ebx, uint32_t ecx); + +int graphics_init(void) { + VIRT_ADDR src = (VIRT_ADDR)((uint32_t)(KERNEL_VMA) + (uint32_t)(REALMD_LMA)); + uint32_t size = REALMD_SIZE; + VIRT_ADDR dest = (VIRT_ADDR)(REALMD_VMA); + + memcpy(dest, src, size); +} + +int graphics_set_mode(int mode) { + realmode_int10h((uint32_t)(mode), 0, 0); +}
A src/kernel/drivers/graphics.s

@@ -0,0 +1,138 @@

+.section .text.realmode +.global realmode_int10h +.code32 +realmode_int10h: + push %ebp + mov %esp, %ebp + + pushf + cli + + pusha + + mov %esp, %eax + mov %eax, %esi + + mov %ebp, %eax + mov %eax, %edi + + # setup real mode stack + mov $0xF000, %eax + mov %eax, %esp + mov %eax, %ebp + + push %esi + push %edi + + mov +16(%edi), %eax + push %eax + mov +12(%edi), %eax + push %eax + mov +8(%edi), %eax + push %eax + + push %ebp + mov %esp, %ebp + + # disable paging + mov %cr3, %eax + push %eax + + mov %cr0, %eax + and $0x3FFFFFFD, %eax + mov %eax, %cr0 + + xor %eax, %eax + mov %eax, %cr3 + + # switch to 16 bit protected mode + ljmp $0x8, $pmode16 + +.code16 +pmode16: + # setup segments + movw $0x10, %ax + movw %ax, %ss + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + + # load real mode interrupt descriptor table + sidt (pmode_IDT) + lidt (realmode_IDT) + + # switch to real mode + mov %cr0, %eax + and $0xFFFFFFFE, %eax + mov %eax, %cr0 + + ljmp $0, $realmode +realmode: + # setup segments + movw $0x0000, %ax + movw %ax, %ss + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + + sti + + # load arguments + movw +4(%bp), %ax + movw +8(%bp), %bx + movw +12(%bp), %cx + + int $0x10 + + cli + + lidt (pmode_IDT) + + mov %cr0, %eax + or $0x00000001, %eax + mov %eax, %cr0 + + ljmp $0x18, $pmode32 + +.code32 +pmode32: + # set data segments + movw $0x20, %ax + movw %ax, %ss + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + + # restore paging + pop %eax + mov %eax, %cr3 + + mov %cr0, %eax + or $0x80000010, %eax + mov %eax, %cr0 + + # clean up argument buffer + pop %ebp + add $12, %esp + + # restore original stack + pop %ebp + pop %eax + mov %eax, %esp + + popa + popf + + # return + pop %ebp + ret + + +realmode_IDT: + .word 0x3FF + .int 0 + +pmode_IDT: + .word 0 + .int 0 +
M src/kernel/drivers/ps2_keyboard.csrc/kernel/drivers/ps2_keyboard.c

@@ -95,7 +95,7 @@ outb(PS2_WRTE_CONF, PS2_COMMAND);

nop(); nop(); nop(); nop(); outb(conf, PS2_DATA); - install_interrupt(PIC1_IRQ(0x01), keyboard_int_handler, 0x08, INT_GATE); + install_interrupt(PIC1_IRQ(0x01), keyboard_int_handler, 0x18, INT_GATE); pic_unmask_interrupt(0x01);
M src/kernel/elf.csrc/kernel/elf.c

@@ -2,7 +2,7 @@ #include <stdint.h>

#include "cedos/elf.h" #include "cedos/core.h" -#include "cedos/fat.h" +#include "cedos/file.h" #include "cedos/sched/process.h" #include "assert.h"

@@ -128,9 +128,9 @@ PROCESS_ID elf_exec(const char *fname, char *args) {

PRINT_DBG("Loading ELF executable \"%s\".\n", fname); VIRT_ADDR elf_addr = (VIRT_ADDR*)(0xA0000000); // TODO: needs to change when we have other file systems - int fd = FAT_openat(0, fname, 0); + int fd = file_open(fname, 0); assert(fd != -1); - int size = FAT_read(fd, elf_addr, 0); + int size = file_read(fd, elf_addr, 0); assert(size != 0); ELF_HEADER *header = (ELF_HEADER*)(elf_addr);
M src/kernel/fat.csrc/kernel/fat.c

@@ -188,6 +188,11 @@ int FAT_openat(int fd, const char *fname, int flags) {

int i = 0; // TODO: take fd into consideration (open file in that subdirectory) + + + if (!(fd & 0x1000)) { return -1; } + + fd &= 0x0FFF; uint16_t first_cluster; while (1) {

@@ -199,13 +204,15 @@ if (i <= 0) { return -1; }

if (strcmp(buffer, fname) == 0) { // file found - return first_cluster; + return first_cluster | 0x1000; } } } uint32_t FAT_read(int fd, void *buffer, int count) { - uint16_t cluster = fd; + if (!(fd & 0x1000)) { return -1; } + + uint16_t cluster = fd & 0xFFF; uint32_t size = 0; while (1) {
M src/kernel/file.csrc/kernel/file.c

@@ -3,18 +3,40 @@

#include "cedos/drivers/console.h" #include "cedos/drivers/keyboard.h" +const int root_fd = 0x1000; + +int file_open(const char *pathname, int flags) { + while (*pathname == '/') { + pathname++; + } + + return file_openat(0x1000, pathname, flags); +} + +int file_openat(int fd, const char *fname, int flags) { + if (fd & 0x1000) { + return FAT_openat(fd, fname, flags); + } else { + // open other files + } +} + int file_read(int fd, char *buffer, uint32_t size) { - int i = 0; - while (i < size) { - char table[] = { - '^', 0x1B, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\\', '´', 0x08, - '\t', 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 'ü', '+', '\n', - 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ö', 'ä', '#', - 0, '<', 'y', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '-'}; - uint32_t scancode = std_kb->read(); - char c = scancode >= 0 && scancode <= 60 ? table[scancode] : 0; - if (c == 0) { continue; } - buffer[i++] = c; + if (fd & 0x1000) { + return FAT_read(fd, buffer, size); + } else { + int i = 0; + while (i < size) { + char table[] = { + '^', 0x1B, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\\', '´', 0x08, + '\t', 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 'ü', '+', '\n', + 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ö', 'ä', '#', + 0, '<', 'y', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '-', 0, 0, 0, ' ' }; + uint32_t scancode = std_kb->read(); + char c = scancode >= 0 && scancode <= 60 ? table[scancode] : 0; + if (c == 0) { continue; } + buffer[i++] = c; + } } }
M src/kernel/interrupts.csrc/kernel/interrupts.c

@@ -65,17 +65,17 @@

int interrupts_init(void) { for (uint32_t i = 0; i < INTERRUPT_COUNT; i++) { if (i == 0x03) { - install_interrupt(i, breakpoint_isr, 0x08, INT_GATE); + install_interrupt(i, breakpoint_isr, 0x18, INT_GATE); } else if (i == 0x08) { - install_interrupt(i, double_fault_isr, 0x08, INT_GATE); + install_interrupt(i, double_fault_isr, 0x18, INT_GATE); } else if (i == 0x0d) { - install_interrupt(i, gpf_isr, 0x08, INT_GATE); + install_interrupt(i, gpf_isr, 0x18, INT_GATE); } else if (i >= 0x21 || i < 0x28) { - install_interrupt(i, pic1_handler, 0x08, INT_GATE); + install_interrupt(i, pic1_handler, 0x18, INT_GATE); } else if (i >= 0x28 || i < 0x30) { - install_interrupt(i, pic2_handler, 0x08, INT_GATE); + install_interrupt(i, pic2_handler, 0x18, INT_GATE); } else { - install_interrupt(i, default_isr, 0x08, INT_GATE); + install_interrupt(i, default_isr, 0x18, INT_GATE); } }
M src/kernel/link.txtsrc/kernel/link.txt

@@ -5,22 +5,33 @@ PAGE_SIZE = 1 << 12;

MEMORY { + REALMD_VMA : ORIGIN = 0x00009000, LENGTH = 0x30000000 KERNEL_VMA : ORIGIN = 0xC0000000, LENGTH = 0x30000000 } SECTIONS { - KERNEL : AT(0x4E00) + KERNEL : AT(0x0000) { */*(.text) */*(.data) */*(.rodata*) } >KERNEL_VMA + + REALMD : AT(LOADADDR(KERNEL) + SIZEOF(KERNEL)) + { + */*(.text.realmode) + + } >REALMD_VMA } __KERNEL_LMA = LOADADDR(KERNEL); __KERNEL_VMA = ADDR(KERNEL); __KERNEL_SIZE = SIZEOF(KERNEL); + +__REALMD_LMA = LOADADDR(REALMD); +__REALMD_VMA = ADDR(REALMD); +__REALMD_SIZE = SIZEOF(REALMD); __KERNEL_STACK_ADDR = 0xC0400000;
M src/kernel/main.csrc/kernel/main.c

@@ -1,5 +1,7 @@

#include "cedos/drivers/console.h" #include "cedos/drivers/keyboard.h" +#include "cedos/drivers/graphics.h" + #include "cedos/sched/sched.h" #include "cedos/sched/process.h"

@@ -25,6 +27,7 @@ #define PRINT_DBG(...) printk("[" __FILE__ "] " __VA_ARGS__)

#else #define PRINT_DBG(...) {} #endif + int os_init(void) { core_init();

@@ -61,6 +64,14 @@

printk("Initializing keyboard..."); ps2_kb.init(); printk("done.\n"); + + printk("Initializing root file system..."); + FAT_init(); + printk("done."); + + printk("Initializing graphics..."); + graphics_init(); + printk("done."); printk("Initialization finished.\n--------------\n");

@@ -143,41 +154,11 @@

int os_main(void) { infodump(); - FAT_init(); - - int i = 0; - - while (1) { - char buffer[832]; - uint16_t first_cluster; - uint32_t file_size; - - i = FAT_root_dir_next(i, buffer, &first_cluster, &file_size); - if (i <= 0) { break; } - - PRINT_DBG("%s (start: %i, size: %i)\n", buffer, first_cluster, file_size); - - uint16_t cluster = first_cluster; - - if (cluster == 0xFFF || cluster == 0x000) { continue; } - - PRINT_DBG(" clusters: \n"); - while (1) { - PRINT_DBG(" %x\n", cluster); - - //char *sect = FAT_read_cluster(cluster); - //hexdump(sect, 512 * 8); - - cluster = FAT_next_cluster(cluster); - if (cluster == 0xFFF || cluster == 0x000) { break; } - } - } - // create test tasks printk("Creating tasks.\n"); - int pid = sched_spawn("shell.o", "Hello World!"); + int pid = sched_spawn("shelf", "Hello World!"); assert(pid != -1); //sched_spawn("fibonacci.o", "Hello World!"); //sched_spawn("fibonacci.o", "Hello World!");
M src/kernel/mm/paging.csrc/kernel/mm/paging.c

@@ -209,5 +209,5 @@ // dump registers to stdout

} int paging_init(void) { - install_interrupt(0x0e, page_fault_isr, 0x08, TRAP_GATE); + install_interrupt(0x0e, page_fault_isr, 0x18, TRAP_GATE); }
M src/kernel/sched/sched.csrc/kernel/sched/sched.c

@@ -55,7 +55,7 @@ PROCESS_ID sched_spawn(const char *name, char *args) {

crit_enter(); if (name != NULL) { - int fd = FAT_openat(0, name, 0); + int fd = file_open(name, 0); if (fd == -1) { return -1; } }

@@ -87,7 +87,7 @@ frame.esi = frame.edi = 0;

frame.ebp = p->ebp; frame.esp = p->esp; frame.eflags = p->eflags; - frame.cs = 0x8; + frame.cs = 0x18; if (name == NULL) { frame.eip = entry_idle;

@@ -179,7 +179,7 @@ extern void* sched_interrupt;

int sched_init(void) { // install scheduler interrupt - install_interrupt(PIC1_IRQ(0x00), &sched_interrupt, 0x08, INT_GATE); + install_interrupt(PIC1_IRQ(0x00), &sched_interrupt, 0x18, INT_GATE); current_pid = 0;

@@ -241,7 +241,7 @@ if (pid < 0) { return; }

while (1) { PROCESS *p = get_process(pid); - if (p->state == PSTATE_TERMINATED) { break; } + if (p == NULL || p->state == PSTATE_TERMINATED) { break; } sched_yield(); }
M src/kernel/syscall.csrc/kernel/syscall.c

@@ -2,6 +2,7 @@ #include "cedos/interrupts.h"

#include "cedos/core.h" #include "cedos/sched/sched.h" #include "cedos/file.h" +#include "cedos/drivers/graphics.h" void test(uint32_t ebx, uint32_t ecx, uint32_t edx) { printk("SYSCALL 0x01: EBX=%i ECX=%X EDX=%X\n", ebx, ecx, edx);

@@ -17,7 +18,9 @@ file_write,

sched_yield, get_current_process, sched_spawn, - sched_wait + sched_wait, + file_open, + graphics_set_mode }; extern void syscall_interrupt(void);

@@ -26,6 +29,6 @@ /*!

* Installs the syscall interrupt to INT 0x30 */ int syscall_init(void) { - install_interrupt(0x30, &syscall_interrupt, 0x08, INT_GATE); + install_interrupt(0x30, &syscall_interrupt, 0x18, INT_GATE); return 1; }
A src/libcedos/makefile

@@ -0,0 +1,31 @@

+.RECIPEPREFIX = > + +LOCAL_BUILD = $(GLOBAL_BUILD)/libcedos + +SRC_DIR := $(shell pwd) + +C_SOURCES := $(wildcard *.c) +S_SOURCES := $(wildcard *.s) + +C_OBJECTS := $(patsubst %.c,$(LOCAL_BUILD)/%.c.o,$(C_SOURCES)) +S_OBJECTS := $(patsubst %.s,$(LOCAL_BUILD)/%.s.o,$(S_SOURCES)) +OBJECTS = $(S_OBJECTS) $(C_OBJECTS) + +LIBCEDOS := $(GLOBAL_BUILD)/lib/libcedos.a + +DIRS := $(sort $(dir $(OBJECTS) $(LIBCEDOS))) + +$(OBJECTS) $(LIBCEDOS): | $(DIRS) +$(DIRS): +> $(MKDIR) $(DIRS) + +.PHONY: build +build: $(LIBCEDOS) +$(LIBCEDOS): $(OBJECTS) +> $(AR) rcs $@ $^ + +$(LOCAL_BUILD)/%.s.o: %.s +> $(AS) -o $@ $< + +$(LOCAL_BUILD)/%.c.o: %.c $(wildcard *.h) +> $(CC) -c -fPIC -I$(INCLUDE_DIR) -I./include $(CCFLAGS) -o $@ $<
A src/shell/cat.c

@@ -0,0 +1,25 @@

+#include "cedos.h" +#include "stdio.h" + +#include <stdint.h> + +void main(char *args) { + int fd = sc_file_open(args, 0); + + if (fd < 0) { + printf("Could not find file: %s\n", args); + return; + } + + char *buffer = (void*)(0x2000000); + + int size = sc_file_read(fd, buffer, -1); + + while (size > 0) { + int chunk = 256; + if (size < chunk) { chunk = size; } + sc_file_write(0, buffer, chunk); + size -= chunk; + buffer += chunk; + } +}
A src/shell/echo.c

@@ -0,0 +1,8 @@

+#include "cedos.h" +#include "stdio.h" + +#include <stdint.h> + +void main(char *args) { + printf("%s\n", args); +}
A src/shell/gmode.c

@@ -0,0 +1,35 @@

+#include "cedos.h" +#include "stdio.h" + +#include <stdint.h> + +void main(char *args) { + int mode = 0; + int i = 0; + + while (args[i] != 0) { + uint8_t c = (uint8_t)(args[i]); + if (c >= 'a' && c <= 'f') { + c -= 'a'; + } else if (c >= 'A' && c <= 'F') { + c -= 'A'; + } else if (c >= '0' && c <= '9') { + c -= '0'; + } else { + printf("Character not recognized: %c\n", c); + } + + mode <<= 4; + mode += (int)(c); + i++; + } + + printf("Setting graphics mode %i...\n", mode); + + graphics_set_mode(mode); + + for (int i = 0; i < 320 * 240; i++) { + uint8_t *vmem = (uint8_t*)(0xA0000); + vmem[i] = (uint8_t)(i); + } +}
A src/shell/hexdump.c

@@ -0,0 +1,42 @@

+#include "cedos.h" +#include "stdio.h" + +#include <stdint.h> + +int hexdump(char *address, int length) { + unsigned char *first_line = (char *)((long)address & (long)0xFFFFFFF0); + unsigned char *last_line = (char *)((long)(address + length) & (long)0xFFFFFFF0); + + while (1) { + if (first_line >= last_line) { break; } + printf("%p ", first_line); + for (int i = 0; i < 16; i++) { + printf("%X ", (unsigned int)(first_line[i])); + } + printf(" |"); + for (int i = 0; i < 16; i++) { + uint8_t c = *(uint8_t*)(&first_line[i]); + if (c < 0x20 || c > 0x7F) { c = '.'; } + printf("%c", c); + } + printf("\n"); + + + first_line += 0x10; + } +} + +void main(char *args) { + int fd = sc_file_open(args, 0); + + if (fd < 0) { + printf("Could not find file: %s\n", args); + return; + } + + char *buffer = (void*)(0x2000000); + + int size = sc_file_read(fd, buffer, -1); + + hexdump(buffer, size); +}
A src/shell/imgview.c

@@ -0,0 +1,41 @@

+#include "cedos.h" +#include "stdio.h" + +#include <stdint.h> + +#define GMODE_TEXT 0x02 +#define GMODE_VIDEO 0x13 + +#define MAX(x, y) (x > y ? x : y) + +void main(char *args) { + // open image file + int fd = sc_file_open(args, 0); + + if (fd < 0) { + printf("Could not find file: %s\n", args); + return; + } + + uint8_t *fbuff = (uint8_t*)(0x2000000); + + int size = sc_file_read(fd, fbuff, -1); + int limit = 320 * 240; + + uint8_t *gbuff = (uint8_t*)(0xA0000); + + // switch video mode and display image + graphics_set_mode(GMODE_VIDEO); + + for (int i = 0; i < MAX(size, limit); i++) { + gbuff[i] = fbuff[i]; + } + + while (1) { + char c; + sc_file_read(0, &c, 1); + if (c == 0x1B) { break; } + } + + graphics_set_mode(GMODE_TEXT); +}
A src/shell/makefile

@@ -0,0 +1,36 @@

+.RECIPEPREFIX = > + +GIT_VERSION := "$(shell git describe --abbrev=4 --dirty --always --tags)" +CCFLAGS += -DVERSION=\"$(GIT_VERSION)\" + +LOCAL_BUILD = $(GLOBAL_BUILD)/shell/build + +SRC_DIR := $(shell pwd) + +CCFLAGS += -I../libcedos/include +LDFLAGS += -L$(GLOBAL_BUILD)/lib +LDFLAGS += -lcedos + +LDFLAGS += -T link.txt +LDFLAGS += -Map=$(LOG_DIR)/$(notdir $@)_mapfile.txt +LDFLAGS += -N + +APP_SOURCES := $(wildcard *.c) +APP_OBJECTS := $(patsubst %.c,$(GLOBAL_BUILD)/bin/%,$(APP_SOURCES)) $(patsubst %.c,$(LOCAL_BUILD)/%.c.o,$(APP_SOURCES)) + +DIRS := $(sort $(dir $(APP_OBJECTS))) + +$(APP_OBJECTS): | $(DIRS) +$(DIRS): +> $(MKDIR) $(DIRS) + +.PHONY: build +build: $(APP_OBJECTS) +$(GLOBAL_BUILD)/bin/%: $(LOCAL_BUILD)/%.c.o | $(LIBCEDOS) +> $(LD) $^ $(LDFLAGS) -o $@ + +$(LOCAL_BUILD)/%.c.o: %.s +> $(AS) -o $@ $< + +$(LOCAL_BUILD)/%.c.o: %.c $(wildcard *.h) +> $(CC) -c -fPIC -I$(INCLUDE_DIR) -I./common $(CCFLAGS) -o $@ $<