CeDOS - Commit 12544d38

Merge pull request #2 from celinakalus/develop Adding rudimentary cstdlib for user programs
Celina Sophie Kalus
Fri, 24 Nov 2023 17:15:03 +0100
54 files changed, 1107 insertions(+), 353 deletions(-)

jump to
M .gitignore.gitignore

@@ -5,5 +5,6 @@ *.img

*.o *.bin img-contents/* +*.png .vscode
A binimg.py

@@ -0,0 +1,38 @@

+import png +import sys +import getopt + +def main(args): + width = 128 + infile = "" + outfile = "" + + opts, args = getopt.getopt(args, "i:w:o:") + for opt, arg in opts: + if opt == '-i': + infile = arg + elif opt == '-o': + outfile = arg + elif opt == '-w': + width = int(arg) + else: + print("ERROR: wrong argument format") + return + + print(width) + print(infile) + print(outfile) + + with open(infile, mode="rb") as f: + bin_data = f.read() + + rows = [] + + while len(bin_data) > 0: + rows = rows + [ bin_data[0:width-1] ] + bin_data = bin_data[width:] + + png.from_array(rows, 'L').save(outfile) + +if __name__ == "__main__": + main(sys.argv[1:])
M include/assert.hinclude/assert.h

@@ -1,6 +1,8 @@

#ifndef ASSERT_H #define ASSERT_H +#include "cedos/core.h" + #include <stdint.h> #define assert(cond) if (!(cond)) { kpanic("Assertion failed: " #cond); }
M include/cedos/core.hinclude/cedos/core.h

@@ -7,10 +7,12 @@

#include <stdarg.h> #include "cedos/drivers/console.h" +#include "cedos/interrupts.h" int core_init(void); void printk(const char* string, ...); void kpanic(const char* string); +void kfault(const char* string, INTERRUPT_FRAME *frame, uint16_t err_code); void memdump(void* start, uint32_t size); void crit_enter(void); void crit_exit(void);
A include/cedos/drivers/tty.h

@@ -0,0 +1,15 @@

+#ifndef TTY_H +#define TTY_H + +#include "cedos/file.h" +#include "cedos/drivers/keyboard.h" +#include "cedos/drivers/console.h" + +int tty_open(const char *pathname, int flags); +int tty_openat(int fd, const char *fname, int flags); +int tty_read(int fd, char *buffer, uint32_t size); +int tty_write(int fd, char *buffer, uint32_t size); + +extern file_operations_t tty_fops; + +#endif
M include/cedos/fat.hinclude/cedos/fat.h

@@ -3,11 +3,16 @@ #define FAT_H

#include <stdint.h> -void *FAT_init(); -void *FAT_read_sector_offset(uint32_t lba, uint32_t *offset); -void *FAT_read_cluster(uint16_t cluster, void *buffer); -uint16_t FAT_next_cluster(uint16_t cluster); -int FAT_root_dir_next(int index, char *fname_buffer, uint16_t *first_cluster, uint32_t *file_size); -uint32_t FAT_read_file(const char *fname, void *buffer); +#include "cedos/file.h" + +void FAT_init(); +int FAT_dir_next(file_t *file, int index, char *fname_buffer); +int FAT_openat(file_t *root, file_t *handle, const char *fname, int flags); +uint32_t FAT_read(file_t *file, uint8_t *buffer, uint32_t count); +off_t FAT_lseek(file_t *file, off_t offset, int whence); +off_t FAT_tell(file_t *file); + +extern file_operations_t FAT_fops; + #endif
M include/cedos/file.hinclude/cedos/file.h

@@ -5,9 +5,44 @@ #include <stdint.h>

#include "cedos/mm/paging.h" +typedef uint32_t fpos_t; +typedef int32_t off_t; + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +struct file; +struct file_operations; + +typedef struct file file_t; +typedef struct file_operations file_operations_t; + +struct file { + file_operations_t *fops; + uint32_t stdio_id; + uint32_t fat_cluster; + fpos_t pos; + size_t size; +}; + +struct file_operations { + int (*open)(const char *pathname, int flags); + int (*openat)(file_t *root, file_t *handle, const char *fname, int flags); + int (*read)(file_t *file, char *buffer, uint32_t size); + int (*write)(file_t *file, char *buffer, uint32_t size); + int (*dir_next)(file_t *file, int index, char *fname_buffer); + off_t (*lseek)(file_t *file, off_t offset, int whence); + off_t (*tell)(file_t *file); +}; + +int file_init(); 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); +off_t file_lseek(int fd, off_t offset, int whence); +off_t file_tell(int fd); int file_write(int fd, char *buffer, uint32_t size); +int file_dir_next(int fd, int index, char *fname_buffer); #endif
M include/cedos/interrupts.hinclude/cedos/interrupts.h

@@ -28,9 +28,9 @@ uint16_t offset_16;

}__attribute__((packed)) IDT_ENTRY; typedef struct { - uint32_t eflags; - uint32_t cs; uint32_t eip; + uint32_t cs; + uint32_t eflags; }__attribute__((packed)) INTERRUPT_FRAME; typedef uint32_t uword_t;
M include/cedos/mm/memory.hinclude/cedos/mm/memory.h

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

typedef uint32_t size_t; +#define NULL (void*)(0) + +int malloc_init(); + /*! * Allocates a block of \p size bytes of memory. (KERNEL MODE) * \param size Size in bytes of the requested block of memory.
A include/cedos/pipe.h

@@ -0,0 +1,11 @@

+#ifndef PIPE_H +#define PIPE_H + +#include "cedos/file.h" + +int pipe_read(int fd, char *buffer, uint32_t size); +int pipe_write(int fd, char *buffer, uint32_t size); + +extern file_operations_t pipe_fops; + +#endif
M include/cedos/sched/process.hinclude/cedos/sched/process.h

@@ -67,6 +67,12 @@

//! String of arguments for the process char *args; + //! process stdin + int stdin; + + //! process stdout + int stdout; + /* * String buffers for name and args * TODO: eventually move to a malloc solution
M include/cedos/sched/sched.hinclude/cedos/sched/sched.h

@@ -32,7 +32,7 @@

/*! * Spawns a new process, loads it from the given ELF file, and returns its process ID. */ -PROCESS_ID sched_spawn(const char *name, char *args); +PROCESS_ID sched_spawn(const char *name, char *args, int flags); /*! * Return the ID of the current process.
D link.txt

@@ -1,58 +0,0 @@

-OUTPUT_ARCH(i386) -OUTPUT_FORMAT(elf32-i386) - -PAGE_SIZE = 1 << 12; - -MEMORY -{ - BOOT_VMA : ORIGIN = 0x00007C00, LENGTH = 0x00001000 - KERNEL_VMA : ORIGIN = 0xC0000000, LENGTH = 0x30000000 - APPLICATION_VMA : ORIGIN = 0x10000000, LENGTH = 0xB0000000 -} - -SECTIONS -{ - BOOT : AT(0x0000) - { - */boot.o(.*) - } >BOOT_VMA - - KERNEL : AT(0x5E00) - { - */kernel.o(.*) - */kernel.o(.bss) - } >KERNEL_VMA - - APPLICATION : AT(LOADADDR(KERNEL) + SIZEOF(KERNEL)) - { - */apps.o(.*) - } >APPLICATION_VMA - - ELF : AT(0xB600) - { - */apps_raw.o(.*) - } >APPLICATION_VMA - - .bss : AT(LOADADDR(ELF) + SIZEOF(ELF)) - { - - } >KERNEL_VMA -} - -__BOOT_LMA = LOADADDR(BOOT); -__BOOT_VMA = ADDR(BOOT); -__BOOT_SIZE = SIZEOF(BOOT); - -__KERNEL_LMA = LOADADDR(KERNEL); -__KERNEL_VMA = ADDR(KERNEL); -__KERNEL_SIZE = SIZEOF(KERNEL); - -__ELF_LMA = LOADADDR(ELF); -__ELF_VMA = ADDR(ELF); -__ELF_SIZE = SIZEOF(ELF); - -__KERNEL_STACK_ADDR = 0xC0400000; - -ASSERT(__BOOT_SIZE <= 0x1000, "bootloader too big!"); -ASSERT(__KERNEL_SIZE <= 0x5000, "bootloader too big!"); -ASSERT(__ELF_SIZE <= 0x3000, "bootloader too big!");
M makefilemakefile

@@ -27,7 +27,9 @@

# common flags CCFLAGS := $(CCFLAGS) -Wno-write-strings CCFLAGS := $(CCFLAGS) -Qn +CCFLAGS := $(CCFLAGS) -pedantic -Wold-style-definition CCFLAGS := $(CCFLAGS) -Wall -Wextra -fno-exceptions +CCFLAGS := $(CCFLAGS) -Werror-implicit-function-declaration CCFLAGS := $(CCFLAGS) -nostdlib -nostartfiles -ffreestanding CCFLAGS := $(CCFLAGS) -mgeneral-regs-only -mno-red-zone CCFLAGS := $(CCFLAGS) --prefix=$(CROSS_COMP)

@@ -72,6 +74,7 @@ > sudo mount $@ ./mnt

> sudo cp $(LOCAL_BUILD)/kernel.bin ./mnt > sudo cp $(LOCAL_BUILD)/bin/* ./mnt > sudo cp ./img-contents/* ./mnt +> du -csh ./mnt/* > sudo umount ./mnt $(GLOBAL_BUILD)/cedos.img: $(GLOBAL_BUILD)/fat.img | $(MODULES)

@@ -82,6 +85,7 @@ > parted $@ set 1 boot on

> dd if=$< of=$@ seek=8 conv=notrunc > dd bs=1 if=$(LOCAL_BUILD)/boot.bin of=$@ count=446 conv=notrunc > dd if=$(LOCAL_BUILD)/boot.bin of=$@ skip=1 seek=1 count=7 conv=notrunc +> python3 binimg.py -w 256 -i $(GLOBAL_BUILD)/cedos.img -o $(GLOBAL_BUILD)/cedos.png > parted $@ print list all # > $(LD) $(OBJECTS) -T link.txt -Map=$(LOG_DIR)/bin_mapfile.txt --oformat binary --nostdlib -o $@

@@ -110,7 +114,7 @@ > $(RM) -r $(CURRENT_DIR)/build/* 2> /dev/null; true

.PHONY: run run: -> ./run.sh +> ./run.sh $(GLOBAL_BUILD)/cedos.img .PHONY: docs docs:
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 -vga std -vnc :0 2> log/run_err.log +qemu-system-i386 -drive index=0,if=floppy,format=raw,file=${1} -m 64 -monitor stdio -no-reboot -d int,cpu_reset,exec,in_asm -vga std -vnc :0 2> log/run_err.log
M src/boot/a20.ssrc/boot/a20.s

@@ -146,4 +146,4 @@ .byte 0

a20_enable_fasta20_msg: .ascii " fast A20 method: " - .byte 0+ .byte 0
M src/boot/drives.ssrc/boot/drives.s

@@ -101,6 +101,9 @@ push %cx

movw $reset_msg, %si call print + lea bootdriv_id, %si + movb (%si), %dl + movb $0x00, %ah int $0x13 pop %cx

@@ -142,19 +145,26 @@ # call print_hex_int16

movw %bx, %di + # divide LBA by number of sectors lea num_sectors, %si + xor %dx, %dx movw (%si), %bx - # inc %ax - divb %bl - movb %ah, %cl + divw %bx + + andw $0x003F, %dx + movb %dl, %cl incb %cl - xor %ah, %ah + xor %dx, %dx lea num_heads, %si movw (%si), %bx - divb %bl - movb %ah, %dh + divw %bx movb %al, %ch + movb %ah, %al + xorb %ah, %ah + shl $6, %al + orb %al, %cl + movb %dl, %dh lea bootdriv_id, %si movb (%si), %dl

@@ -316,6 +326,7 @@ .byte 13

.byte 10 .byte 0 + .section .bss .global bootdriv_id bootdriv_id:

@@ -331,4 +342,4 @@ num_cylinders:

.word 0 num_heads: - .word 0+ .word 0
M src/boot/entry.ssrc/boot/entry.s

@@ -161,15 +161,29 @@ # perform long jump to set code segment

ljmp $0x18, $protected +myhexdump: + movb (%si), %al + call print_hex_char + inc %si + push %si + movw $space_msg, %si + call print + pop %si + loop myhexdump + movw $newline_msg, %si + call print + ret + + .code32 protected: # setup registers with appropriate GDT values mov $0x20, %eax + mov %eax, %ss mov %eax, %ds mov %eax, %es mov %eax, %fs mov %eax, %gs - mov %eax, %ss call load_kernel

@@ -194,6 +208,15 @@ jmp loop

.section .data +space_msg: + .ascii " " + .byte 0 + +newline_msg: + .byte 13 + .byte 10 + .byte 0 + gdt_msg: .ascii "Setting GDT..." .byte 0

@@ -227,9 +250,9 @@ .byte 10

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

@@ -52,11 +52,7 @@ uint32_t FAT2_lba;

uint32_t root_lba; uint32_t data_lba; -void *FAT_init() { - const int sector_size = 512; - const int sector_num = 128; - const int part_size = sector_size * sector_num; - +void FAT_init() { // open image file FAT_addr = (void*)(0x10000);

@@ -109,7 +105,7 @@ return -1;

} // deleted file - if (dir_entry->name[0] == 0xE5) { + if (dir_entry->name[0] == (char)(0xE5)) { index++; continue; }

@@ -169,7 +165,7 @@ }

uint16_t FAT_next_cluster(uint16_t cluster) { // assuming FAT12 - int offset = (cluster >> 1) * 3; + uint32_t offset = (cluster >> 1) * 3; uint8_t *sect = FAT_read_sector_offset(FAT1_lba, &offset); sect += offset;
M src/boot/fat.hsrc/boot/fat.h

@@ -3,7 +3,7 @@ #define FAT_H

#include <stdint.h> -void *FAT_init(); +void FAT_init(); void *FAT_read_sector_offset(uint32_t lba, uint32_t *offset); void *FAT_read_cluster(uint16_t cluster, void *buffer); uint16_t FAT_next_cluster(uint16_t cluster);
M src/boot/link.txtsrc/boot/link.txt

@@ -8,6 +8,7 @@

MEMORY { BOOT_VMA : ORIGIN = 0x00007C00, LENGTH = 0x00001000 + BOOT_DATA : ORIGIN = 0x00009000, LENGTH = 0x00001000 KERNEL_VMA : ORIGIN = 0xC0000000, LENGTH = 0x30000000 }

@@ -20,7 +21,16 @@ . = 510;

BYTE(0x55) BYTE(0xAA) */*.o(.text) - */*.o(.data) + } >BOOT_VMA + + .data : + { */*.o(.rodata*) + */*.o(.data) } >BOOT_VMA + + .bss : + { + */*.o(.bss) + } >BOOT_DATA }
M src/boot/main.csrc/boot/main.c

@@ -16,6 +16,22 @@ }

} int load_kernel() { + // debug output + uint8_t *dbuf = (uint8_t *)(0x10000); + for (int i = 0; i < 16; i++) { + uint8_t value = dbuf[i]; + char lut[] = "0123456789ABCDEF"; + + uint8_t low = value & 0x0F; + uint8_t high = value >> 4; + + printc(lut[high]); + printc(lut[low]); + printc(' '); + } + + //while (1); + FAT_init(); int i = 0;

@@ -38,10 +54,8 @@ }

// copy all clusters uint16_t cluster = first_cluster; - void *buffer = (void *)(0x100000); + uint8_t *buffer = (uint8_t *)(0x100000); while (1) { - uint8_t *str = (uint8_t*)(0xB8000); - buffer = FAT_read_cluster(cluster, buffer); cluster = FAT_next_cluster(cluster);
M src/boot/mbr.ssrc/boot/mbr.s

@@ -86,4 +86,4 @@

newline: .byte 13 .byte 10 - .byte 0+ .byte 0
M src/boot/string.csrc/boot/string.c

@@ -29,7 +29,9 @@ void *memcpy(void *_dest, const void *_src, uint32_t n) {

uint8_t *src = (uint8_t*)(_src); uint8_t *dest = (uint8_t*)(_dest); - for (int i = 0; i < n; i++) { + for (uint32_t i = 0; i < n; i++) { dest[i] = src[i]; } + + return _dest; }
M src/kernel/core.csrc/kernel/core.c

@@ -64,7 +64,7 @@

for (int j = 0; j < 0x10; j++) { uint8_t* p = (uint8_t*)(i | j); - if (p >= start && p < (start + size)) { + if (p >= (uint8_t*)(start) && p < (uint8_t*)(start + size)) { printk_hex_char(*p); core_con->write_c(' '); } else {

@@ -114,7 +114,6 @@ void printk(const char* fmt, ...) {

crit_enter(); va_list args; va_start(args, fmt); - uint32_t index = 0; enum { STATE_DEFAULT,

@@ -169,6 +168,18 @@ stackdump();

while (1) {} } +void kfault(const char* string, INTERRUPT_FRAME *frame, uint16_t err_code) { + cli(); + printk("%s\n", string); + printk("EIP: %p\n", frame->eip); + printk("CS: %p\n", frame->cs); + printk("EFLAGS: %p\n", frame->eflags); + // register dump / stack dump + regdump(); + stackdump(); + while (1) {} +} + uint32_t crit_sect_counter = 0; uint32_t if_state = 0;

@@ -190,8 +201,8 @@ uint32_t crit_stash(void) {

uint32_t __csc = crit_sect_counter; crit_sect_counter = 0; if (__csc > 0) { - uint32_t eflags = get_eflags() | if_state; - set_eflags(eflags); + if_state = get_eflags() & (1 << 9); + sti(); } return __csc; }

@@ -199,8 +210,8 @@

void crit_restore(uint32_t state) { crit_sect_counter = state; if (crit_sect_counter > 0) { - if_state = get_eflags() & (1 << 9); - cli(); + uint32_t eflags = get_eflags() | if_state; + set_eflags(eflags); } }
M src/kernel/drivers/graphics.csrc/kernel/drivers/graphics.c

@@ -14,8 +14,10 @@ uint32_t size = REALMD_SIZE;

VIRT_ADDR dest = (VIRT_ADDR)(REALMD_VMA); memcpy(dest, src, size); + return 0; } int graphics_set_mode(int mode) { realmode_int10h((uint32_t)(mode), 0, 0); + return 0; }
M src/kernel/drivers/graphics.ssrc/kernel/drivers/graphics.s

@@ -10,6 +10,9 @@ cli

pusha + # preserve protected mode IDT + sidtl (pmode_IDT) + mov %esp, %eax mov %eax, %esi

@@ -58,7 +61,6 @@ movw %ax, %es

movw %ax, %fs # load real mode interrupt descriptor table - sidt (pmode_IDT) lidt (realmode_IDT) # switch to real mode

@@ -86,7 +88,7 @@ int $0x10

cli - lidt (pmode_IDT) + lidtl (pmode_IDT) mov %cr0, %eax or $0x00000001, %eax
M src/kernel/drivers/ps2_keyboard.csrc/kernel/drivers/ps2_keyboard.c

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

#include "cedos/pic.h" #include "cedos/core.h" #include "cedos/sched/sched.h" +#include "cedos/mm/memory.h" #include "assembly.h" #define PS2_DATA 0x60

@@ -47,8 +48,8 @@ ps2_kb_init,

ps2_kb_read }; -uint8_t buffer[BUFFER_LENGTH]; -uint32_t buffer_head, buffer_tail; +uint8_t *buffer; +volatile uint32_t buffer_head, buffer_tail; __attribute__((always_inline)) inline void buffer_enqueue(uint8_t value) { buffer[buffer_head] = value;

@@ -79,6 +80,11 @@ pic1_eoi();

} int ps2_kb_init(void) { + buffer_head = 0; + buffer_tail = 0; + + buffer = os_kernel_malloc(BUFFER_LENGTH); + // clear incoming data inb(PS2_DATA);

@@ -104,7 +110,7 @@ }

uint8_t ps2_kb_read(void) { while (buffer_empty()) { - PRINT_DBG("yield.\n"); + //PRINT_DBG("yield.\n"); sched_yield(); }
A src/kernel/drivers/tty.c

@@ -0,0 +1,45 @@

+#include "cedos/file.h" +#include "cedos/drivers/tty.h" + +#include "cedos/drivers/console.h" +#include "cedos/drivers/keyboard.h" + +file_operations_t tty_fops = { + tty_open, /* open */ + tty_openat, /* openat */ + tty_read, /* read */ + tty_write, /* write */ + NULL, /* dir_next */ + NULL /* lseek */ +}; + +int tty_open(const char *pathname, int flags) { + +} + +int tty_openat(int fd, const char *fname, int flags) { + +} + +int tty_read(int fd, char *buffer, uint32_t size) { + uint32_t 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 <= 60 ? table[scancode] : 0; + if (c == 0) { continue; } + buffer[i++] = c; + } + return size; +} + +int tty_write(int fd, char *buffer, uint32_t size) { + for (uint32_t i = 0; i < size; i++) { + std_con->write_c(buffer[i]); + } + return size; +}
M src/kernel/elf.csrc/kernel/elf.c

@@ -5,6 +5,8 @@

#include "cedos/file.h" #include "cedos/sched/process.h" +#include "cedos/mm/memory.h" + #include "assert.h" #ifdef DEBUG

@@ -112,9 +114,8 @@ assert(sizeof(SECT_HEADER) == section_size);

for (int i = 0; i < num_sections; i++) { SECT_HEADER sh = sect_headers[i]; - char *name = (char*)(sect_names_addr + sh.name); - - PRINT_DBG("Section: %s\n", name); + + PRINT_DBG("Section: %s\n", (char*)(sect_names_addr + sh.name)); PRINT_DBG("- type: %i\n", sh.type); PRINT_DBG("- offset: %i\n", sh.offset); PRINT_DBG("- size: %i\n", sh.size);

@@ -125,52 +126,70 @@ }

} PROCESS_ID elf_exec(const char *fname, char *args) { + crit_enter(); 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 = file_open(fname, 0); - assert(fd != -1); - int size = file_read(fd, elf_addr, 0); - assert(size != 0); + PRINT_DBG("File handle: %i\n", fd); + + if (fd == -1) { + printk("Executable file not found: %s\n", fname); + return -1; + } + //int size = file_read(fd, elf_addr, 0xFFFF); + //assert(size != 0); - ELF_HEADER *header = (ELF_HEADER*)(elf_addr); + ELF_HEADER header; + file_lseek(fd, 0, SEEK_SET); + int header_size = file_read(fd, (void*)(&header), sizeof(ELF_HEADER)); // magic number correct - assert(((uint32_t*)(elf_addr))[0] == 0x464C457F); + assert(*(uint32_t*)(header.e_ident) == 0x464C457F); // header size correct assert(sizeof(ELF_HEADER) == 52); + assert(header_size == sizeof(ELF_HEADER)); // get section table - int sh_offset = header->secthead_offset; - SECT_HEADER *sect_headers = (SECT_HEADER*)(elf_addr + sh_offset); + int sh_offset = header.secthead_offset; + + SECT_HEADER sect_headers[16]; + file_lseek(fd, sh_offset, SEEK_SET); + int sect_headers_size = file_read(fd, (void*)(&sect_headers), sizeof(sect_headers)); + + assert(sect_headers_size != 0); - int num_sections = header->sh_num; - int section_size = header->sh_entry_size; + int num_sections = header.sh_num; + int section_size = header.sh_entry_size; - SECT_HEADER sect_names_sh = sect_headers[header->sh_strndx]; - VIRT_ADDR sect_names_addr = elf_addr + sect_names_sh.offset; + SECT_HEADER *sect_names_sh = &sect_headers[header.sh_strndx]; + + char *sect_names = os_kernel_malloc(sect_names_sh->size); + file_lseek(fd, sect_names_sh->offset, SEEK_SET); + file_read(fd, sect_names, sect_names_sh->size); assert(sizeof(SECT_HEADER) == section_size); // go through all sections and copy/allocate memory as necessary PRINT_DBG("Enumerating %i sections:\n", num_sections); for (int i = 0; i < num_sections; i++) { - SECT_HEADER sh = sect_headers[i]; - char *name = (char*)(sect_names_addr + sh.name); + SECT_HEADER *sh = &sect_headers[i]; + char *name = (char*)(sect_names + sh->name); - if ((sh.flags & SHF_ALLOC) && (sh.flags & SHF_EXECINSTR)) { - VIRT_ADDR lma = elf_addr + sh.offset; - VIRT_ADDR vma = sh.addr; - uint32_t size = sh.size; - PRINT_DBG("%p\n", sh.flags); + if ((sh->flags & SHF_ALLOC) && (sh->flags & SHF_EXECINSTR)) { + uint32_t lma = sh->offset; + uint32_t vma = sh->addr; + uint32_t sect_size = sh->size; + PRINT_DBG("%p\n", sh->flags); PRINT_DBG("Copying code section %s to its destination ", name); PRINT_DBG("(LMA: %p, VMA: %p)\n", lma, vma); - memcpy(vma, lma, size); - } else if (sh.flags & SHF_ALLOC) { - VIRT_ADDR lma = elf_addr + sh.offset; - VIRT_ADDR vma = sh.addr; + file_lseek(fd, sh->offset, SEEK_SET); + int read_size = file_read(fd, vma, sect_size); + assert(sect_size == read_size); + } else if (sh->flags & SHF_ALLOC) { + uint32_t lma = sh->offset; + uint32_t vma = sh->addr; PRINT_DBG("Allocating space for section %s ", name); PRINT_DBG("(LMA: %p, VMA: %p)\n", lma, vma);

@@ -182,10 +201,11 @@ }

PRINT_DBG("\n"); - PRINT_DBG("Entry point: %p\n", header->entry); + PRINT_DBG("Entry point: %p\n", header.entry); + crit_exit(); // enter the process - PROCESS_MAIN *entry = header->entry; + PROCESS_MAIN *entry = (PROCESS_MAIN*)(header.entry); entry(args); return 0;
M src/kernel/fat.csrc/kernel/fat.c

@@ -1,6 +1,21 @@

+#include "cedos/file.h" #include "cedos/fat.h" #include "string.h" +#include "assert.h" + +#include "cedos/mm/memory.h" + #include <stdint.h> + +file_operations_t FAT_fops = { + NULL, /* open */ + FAT_openat, /* openat */ + FAT_read, /* read */ + NULL, /* write */ + FAT_dir_next, /* dir_next */ + FAT_lseek, /* lseek */ + FAT_tell /* tell */ +}; typedef struct { char jmp[3];

@@ -52,10 +67,9 @@ uint32_t FAT2_lba;

uint32_t root_lba; uint32_t data_lba; -void *FAT_init() { +void FAT_init() { const int sector_size = 512; const int sector_num = 128; - const int part_size = sector_size * sector_num; // open image file FAT_addr = (void*)(0x10000);

@@ -91,7 +105,7 @@ return (void*)((uint8_t*)(buffer) + cluster_size);

} int FAT_root_dir_next(int index, char *fname_buffer, uint16_t *first_cluster, uint32_t *file_size) { - memset(fname_buffer, 0, sizeof(fname_buffer)); + //memset(fname_buffer, 0, sizeof(fname_buffer)); while (1) { // index overflow

@@ -109,7 +123,7 @@ return -1;

} // deleted file - if (dir_entry->name[0] == 0xE5) { + if (dir_entry->name[0] == (char)(0xE5)) { index++; continue; }

@@ -138,7 +152,9 @@ continue;

} if (index == 0 && (dir_entry->file_attr & 0x08) && dir_entry->file_size == 0) { - // volume label + // volume label + index++; + continue; } else if ((dir_entry->file_attr & 0x10) && dir_entry->file_size == 0) { // subdirectory

@@ -167,11 +183,19 @@ return index + 1;

} } +int FAT_dir_next(file_t *file, int index, char *fname_buffer) { + uint16_t first_cluster; + uint32_t file_size; + + // TODO: subdirectories + return FAT_root_dir_next(index, fname_buffer, &first_cluster, &file_size); +} + uint16_t FAT_next_cluster(uint16_t cluster) { // assuming FAT12 - int offset = (cluster >> 1) * 3; + uint32_t *offset = (cluster >> 1) * 3; uint8_t *sect = FAT_read_sector_offset(FAT1_lba, &offset); - sect += offset; + sect += (uint32_t)(offset); if (cluster & 0x01) { uint16_t high = (uint16_t)(sect[2]);

@@ -184,16 +208,10 @@ return low | high;

} } -int FAT_openat(int fd, const char *fname, int flags) { +int FAT_openat(file_t *root, file_t *handle, 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) { char buffer[832];

@@ -204,24 +222,73 @@ if (i <= 0) { return -1; }

if (strcmp(buffer, fname) == 0) { // file found - return first_cluster | 0x1000; + handle->pos = 0; + handle->size = file_size; + handle->fops = &FAT_fops; + handle->fat_cluster = first_cluster; + return 0; } } } -uint32_t FAT_read(int fd, void *buffer, int count) { - if (!(fd & 0x1000)) { return -1; } - - uint16_t cluster = fd & 0xFFF; +uint32_t FAT_read(file_t *file, uint8_t *buffer, uint32_t count) { + uint16_t cluster = file->fat_cluster; + fpos_t offset = file->pos; + size_t file_size = file->size; uint32_t size = 0; - while (1) { - buffer = FAT_read_cluster(cluster, buffer); + uint32_t cluster_size = boot_sect->bytes_per_sect * boot_sect->sect_per_cluster; + uint8_t *cluster_buffer = os_kernel_malloc(cluster_size); + + if (offset + count > file_size) { + count = file_size - offset; + } + + while (offset >= cluster_size) { cluster = FAT_next_cluster(cluster); - size += boot_sect->bytes_per_sect * boot_sect->sect_per_cluster; - + if (cluster == 0xFFF || cluster == 0x000) { return -1; } + offset -= cluster_size; + } + + while (count > 0) { if (cluster == 0xFFF || cluster == 0x000) { break; } + + FAT_read_cluster(cluster, cluster_buffer); + cluster = FAT_next_cluster(cluster); + + uint32_t memcpy_size; + + if (offset + count > cluster_size) { + memcpy_size = (cluster_size - offset); + } else { + memcpy_size = count; + } + + memcpy(buffer, (cluster_buffer + offset), memcpy_size); + + offset = 0; + count -= memcpy_size; + buffer += memcpy_size; + size += memcpy_size; } + file->pos += size; + return size; +} + +off_t FAT_lseek(file_t *file, off_t offset, int whence) { + if (whence == SEEK_SET) { + file->pos = offset; + } else if (whence == SEEK_CUR) { + file->pos += offset; + } else if (whence == SEEK_END) { + // to be implemented + } else { + kpanic("Wrong whence!"); + } +} + +off_t FAT_tell(file_t *file) { + return file->pos; }
M src/kernel/file.csrc/kernel/file.c

@@ -1,47 +1,127 @@

#include "cedos/file.h" +#include "cedos/fat.h" +#include "cedos/pipe.h" -#include "cedos/drivers/console.h" -#include "cedos/drivers/keyboard.h" +#include "cedos/drivers/tty.h" +#include "cedos/core.h" + +#include "cedos/mm/memory.h" + +#include "cedos/sched/sched.h" +#include "cedos/sched/process.h" -const int root_fd = 0x1000; +#ifdef DEBUG +#define PRINT_DBG(...) printk("[" __FILE__ "] " __VA_ARGS__) +#else +#define PRINT_DBG(...) {} +#endif + +//const int root_fd = 0x1000; + +file_t *file_table; +int next_free = 0; + +int stdin, stdout, fat_root, pipe; + +int file_init() { + file_table = os_kernel_malloc(sizeof(file_t) * 512); + + file_table[next_free].fops = &tty_fops; + file_table[next_free].stdio_id = 0; + file_table[next_free].fat_cluster = 0; + stdin = next_free++; + + file_table[next_free].fops = &tty_fops; + file_table[next_free].stdio_id = 1; + file_table[next_free].fat_cluster = 0; + stdout = next_free++; + + // FAT root + file_table[next_free].fops = &FAT_fops; + file_table[next_free].stdio_id = 0; + file_table[next_free].fat_cluster = 0; + fat_root = next_free++; + + // pipe + file_table[next_free].fops = &pipe_fops; + pipe = next_free++; + + return 0; +} int file_open(const char *pathname, int flags) { while (*pathname == '/') { pathname++; } - return file_openat(0x1000, pathname, flags); + return file_openat(fat_root, pathname, flags); +} + +file_t *get_process_local_file(int fd) { + if (fd > 1) { return &file_table[fd]; } + + PROCESS_ID pid = get_current_process(); + PRINT_DBG("pid: %i\n", pid); + PROCESS *p = get_process(pid); + + if (fd == 0) { return &file_table[p->stdin]; } + if (fd == 1) { return &file_table[p->stdout]; } + + return NULL; } int file_openat(int fd, const char *fname, int flags) { - if (fd & 0x1000) { - return FAT_openat(fd, fname, flags); - } else { - // open other files - } + int new_fd = next_free++; + + PRINT_DBG("Given fd: %i\n", fd); + PRINT_DBG("New fd: %i\n", new_fd); + + file_t *root = get_process_local_file(fd); + file_t *handle = &file_table[new_fd]; + + if (root->fops->openat == NULL) { return -1; } + + if (root->fops->openat(root, handle, fname, flags)) { return -1; } + + return new_fd; } int file_read(int fd, char *buffer, uint32_t size) { - 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; - } - } + file_t *file = get_process_local_file(fd); + + if (file->fops->read == NULL) { return -1; } + + return file->fops->read(file, buffer, size); } int file_write(int fd, char *buffer, uint32_t size) { - for (int i = 0; i < size; i++) { - std_con->write_c(buffer[i]); - } + file_t *file = get_process_local_file(fd); + + if (file->fops->write == NULL) { return -1; } + + file->fops->write(file, buffer, size); +} + +int file_dir_next(int fd, int index, char *fname_buffer) { + file_t *file = get_process_local_file(fd); + + if (file->fops->dir_next == NULL) { return -1; } + + file->fops->dir_next(file, index, fname_buffer); +} + +off_t file_lseek(int fd, off_t offset, int whence) { + file_t *file = get_process_local_file(fd); + + if (file->fops->lseek == NULL) { return -1; } + + return file->fops->lseek(file, offset, whence); +} + +off_t file_tell(int fd) { + file_t *file = get_process_local_file(fd); + + if (file->fops->tell == NULL) { return -1; } + + return file->fops->tell(file); }
M src/kernel/interrupts.csrc/kernel/interrupts.c

@@ -31,7 +31,7 @@ kpanic("CRITICAL: DOUBLE FAULT");

} EXCEPTION(gpf_isr, frame, error_code) { - kpanic("CRITICAL: GENERAL PROTECTION FAULT"); + kfault("CRITICAL: GENERAL PROTECTION FAULT", frame, error_code); } INTERRUPT(pic1_handler, frame) {
M src/kernel/link.txtsrc/kernel/link.txt

@@ -16,7 +16,7 @@ {

*/*(.text) */*(.data) */*(.rodata*) - + */*(.bss) } >KERNEL_VMA REALMD : AT(LOADADDR(KERNEL) + SIZEOF(KERNEL))
M src/kernel/main.csrc/kernel/main.c

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

#include "cedos/sched/process.h" #include "cedos/mm/paging.h" +#include "cedos/mm/memory.h" #include "cedos/interrupts.h" #include "cedos/syscall.h"

@@ -16,6 +17,7 @@ #include "cedos/core.h"

#include "cedos/elf.h" +#include "cedos/file.h" #include "cedos/fat.h" #include "linker.h"

@@ -53,6 +55,10 @@ printk("Activating interrupts...");

sti(); printk("done.\n"); + printk("Initiallizing malloc..."); + malloc_init(); + printk("done.\n"); + printk("Installing syscalls..."); syscall_init(); printk("done.\n");

@@ -65,13 +71,17 @@ printk("Initializing keyboard...");

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

@@ -116,41 +126,6 @@ crit_exit();

} } -int sysinit(void) { - uint8_t scancode = 0; - - memdump((VIRT_ADDR)0x10000000, 0x3000); - - //syscall(0, 0xCAFEBABE, 0xDEADBEEF, 0x42069420); - - printk("PRESS ENTER:"); - - do { - scancode = ps2_kb.read(); - printk("%c", scancode); - } while (scancode != 0x1C); - - printk("THANKS, NOW PRESS ESC TO EXIT:"); - - do { - scancode = ps2_kb.read(); - printk("%c", scancode); - } while (scancode != 0x01); - - syscall(1, 0, 0, 0); - - //while (1) { - // printk("x"); - // hlt(); - //} - - //sched_exec(create_empty_page_dir(), fibonacci, "fibonacci"); - //sched_exec(create_empty_page_dir(), node, "node"); - //while (get_process_count() < 5) { sched_yield(); } - //tasktree(1); - printk("Terminating.\n"); -} - int os_main(void) { infodump();

@@ -158,7 +133,7 @@ // create test tasks

printk("Creating tasks.\n"); - int pid = sched_spawn("shelf", "Hello World!"); + int pid = sched_spawn("shelf", "Hello World!", 0); assert(pid != -1); //sched_spawn("fibonacci.o", "Hello World!"); //sched_spawn("fibonacci.o", "Hello World!");
M src/kernel/mm/memory.csrc/kernel/mm/memory.c

@@ -1,12 +1,60 @@

#include "cedos/mm/memory.h" +#include "assert.h" + +struct memblock { + struct memblock *next; + int size; +}; + +volatile struct memblock volatile *malloc_first, *malloc_last, *malloc_next_free; + +int malloc_init() { + uint32_t mem_start = 0xC0400000u; + uint32_t mem_end = 0xC0800000u; + + malloc_first = (volatile struct memblock*)(mem_start); + malloc_last = (volatile struct memblock*)(mem_end - sizeof(struct memblock)); + malloc_next_free = malloc_first; + + malloc_first->size = 0; + malloc_first->next = malloc_last; + + malloc_last->size = 0; + malloc_last->next = NULL; +} + /*! * Allocates a block of \p size bytes of memory. (KERNEL MODE) * \param size Size in bytes of the requested block of memory. * \return Memory address to the new memory block */ void* os_kernel_malloc(size_t size) { - return (void*)0; + // size == 0 means the block is free + assert(malloc_next_free->size == 0); + + // TODO: test if memory block is large enough + + + uint32_t addr = (uint32_t)(malloc_next_free); + addr += sizeof(struct memblock); + addr += size; + + // TODO: in some cases, one might rather link to the + // next block after that instead of creating a new block + + struct memblock *new_block = (volatile struct memblock*)(addr); + + new_block->next = malloc_next_free->next; + new_block->size = 0; + + malloc_next_free->next = new_block; + malloc_next_free->size = size; + + void *pointer = (void*)(&malloc_next_free[1]); + malloc_next_free = new_block; + + return pointer; } /*!
M src/kernel/mm/paging.csrc/kernel/mm/paging.c

@@ -66,8 +66,6 @@ */

int force_map_page_to(PHYS_ADDR page_addr, uint32_t dir_index, uint32_t table_index, uint32_t flags) { PAGE_DIR_ENTRY* page_dir = PAGE_DIR_ALT_MAPPED_ADDR; PAGE_TABLE_ENTRY* page_table = PAGE_TABLE_ALT_MAPPED_ADDR(dir_index); - - int tmp = 0; if (!is_present(page_dir[dir_index])) { // acquire new page table

@@ -83,7 +81,7 @@ }

int map_page_to(PHYS_ADDR page_addr, uint32_t dir_index, uint32_t table_index, uint32_t flags) { if (is_addr_available(dir_index, table_index)) { - force_map_page_to(page_addr, dir_index, table_index, flags); + return force_map_page_to(page_addr, dir_index, table_index, flags); } else { return 0; }

@@ -107,14 +105,14 @@ }

int map_page_to_this(PHYS_ADDR page_addr, uint32_t dir_index, uint32_t table_index, uint32_t flags) { if (is_addr_available(dir_index, table_index)) { - force_map_page_to_this(page_addr, dir_index, table_index, flags); + return force_map_page_to_this(page_addr, dir_index, table_index, flags); } else { return 0; } } size_t copy_to_pdir(VIRT_ADDR src, size_t length, PHYS_ADDR pdir, VIRT_ADDR dest) { - VIRT_ADDR mount_dest = 0xe0000000; + VIRT_ADDR mount_dest = (VIRT_ADDR)(0xe0000000); mount_page_dir(pdir); PHYS_ADDR page;

@@ -136,6 +134,8 @@ dest += part_length;

src += part_length; length -= part_length; } + + return dest; } int map_range_to(PHYS_ADDR page_dir, VIRT_ADDR dest, PHYS_ADDR src, uint32_t page_count, uint32_t flags) {

@@ -194,20 +194,26 @@ page_dir[0] = PAGE_DIR_MAPPED_ADDR[0];

// map kernel page_dir[PAGE_DIR_INDEX(0xc0000000)] = PAGE_DIR_MAPPED_ADDR[PAGE_DIR_INDEX(0xc0000000)]; + page_dir[PAGE_DIR_INDEX(0xc0400000)] = PAGE_DIR_MAPPED_ADDR[PAGE_DIR_INDEX(0xc0400000)]; return page_dir_phys; } + +#define PAGE_FAULT_FLAGS_PRESENT (1 << 0) EXCEPTION(page_fault_isr, frame, error_code) { volatile VIRT_ADDR faulty_addr; __asm__ volatile ("mov %%cr2, %0" : "=a" (faulty_addr)); - //if (PAGE_DIR_INDEX(faulty_addr) >= PAGE_ENTRY_COUNT - 2) { return; } - PRINT_DBG("PAGE FAULT: %X\n", faulty_addr); - PHYS_ADDR new_page = get_free_page(); - force_map_page_to_this(new_page, PAGE_DIR_INDEX(faulty_addr), PAGE_TABLE_INDEX(faulty_addr), PAGE_TABLE_FLAGS); - // dump registers to stdout + + if (error_code & PAGE_FAULT_FLAGS_PRESENT) { + kpanic("Page-protection violation!"); + } else { + PHYS_ADDR new_page = get_free_page(); + force_map_page_to_this(new_page, PAGE_DIR_INDEX(faulty_addr), PAGE_TABLE_INDEX(faulty_addr), PAGE_TABLE_FLAGS); + } } int paging_init(void) { install_interrupt(0x0e, page_fault_isr, 0x18, TRAP_GATE); + return 0; }
A src/kernel/pipe.c

@@ -0,0 +1,50 @@

+#include "cedos/file.h" +#include "cedos/pipe.h" +#include "cedos/sched/sched.h" + +file_operations_t pipe_fops = { + NULL, /* open */ + NULL, /* openat */ + pipe_read, /* read */ + pipe_write, /* write */ + NULL, /* dir_next */ + NULL /* lseek */ +}; + +#define PIPE_BUFFER_SIZE 512 + +uint8_t pipe_buffer[PIPE_BUFFER_SIZE]; +int read_head = 0; +int write_head = 0; + +uint8_t pipe_readc() { + while (write_head == read_head) { + sched_yield(); + } + + int rh_next = (read_head + 1) % PIPE_BUFFER_SIZE; + uint8_t res = pipe_buffer[read_head]; + read_head = rh_next; + return res; +} + +void pipe_writec(uint8_t c) { + int wh_next = (write_head + 1) % PIPE_BUFFER_SIZE; + while (wh_next == read_head) { + sched_yield(); + } + pipe_buffer[write_head] = c; + write_head = wh_next; +} + +int pipe_read(int fd, char *buffer, uint32_t size) { + for (int i = 0; i < size; i++) { + buffer[i] = pipe_readc(); + } +} + +int pipe_write(int fd, char *buffer, uint32_t size) { + for (int i = 0; i < size; i++) { + pipe_writec(buffer[i]); + } +}
M src/kernel/sched/sched.csrc/kernel/sched/sched.c

@@ -3,6 +3,7 @@ #include "cedos/sched/process.h"

#include "cedos/sched/sched_strats.h" #include "cedos/mm/paging.h" +#include "cedos/mm/memory.h" #include "cedos/drivers/console.h" #include "cedos/drivers/speaker.h"

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

#include "cedos/pit.h" #include "cedos/pic.h" #include "cedos/elf.h" +#include "cedos/file.h" #include "assembly.h" #include "assert.h"

@@ -19,7 +21,7 @@

#define KERNEL_PRIVATE_STACK (void*)(0xC0600000) #define USER_STACK (void*)(0xC0000000) -#define PROCESS_STD_EFLAGS (0x00000286) +#define PROCESS_STD_EFLAGS (0x00000200) #ifdef DEBUG #define PRINT_DBG(...) printk("[" __FILE__ "] " __VA_ARGS__)

@@ -28,9 +30,8 @@ #define PRINT_DBG(...) {}

#endif PROCESS* get_slot(void) { - static PROCESS free_slots[8]; - static uint32_t index = 0; - return &(free_slots[index++]); + PROCESS *new_process = (PROCESS*)os_kernel_malloc(sizeof(PROCESS)); + return new_process; } PROCESS_ID current_pid;

@@ -44,15 +45,19 @@

void entry_idle(char *args) { while (1) { - + hlt(); } } /*! * Spawn a new process and returns its process ID. */ -PROCESS_ID sched_spawn(const char *name, char *args) { +PROCESS_ID sched_spawn(const char *name, char *args, int flags) { crit_enter(); + + PRINT_DBG("process name: %s\n", name); + PRINT_DBG("process args: %s\n", args); + PRINT_DBG("process flags: %i\n", flags); if (name != NULL) { int fd = file_open(name, 0);

@@ -64,18 +69,31 @@

// set process context PROCESS *p = get_slot(); p->page_dir = page_dir; - p->eip = sched_dispatcher; p->ebp = USER_STACK; p->esp = USER_STACK - sizeof(SCHED_FRAME); p->eflags = PROCESS_STD_EFLAGS; - p->entry = 0xDEADBEEF; + p->entry = (PROCESS_MAIN*)(0xDEADBEEF); + + if (name == NULL) { + p->eip = entry_idle; + } else { + p->eip = sched_dispatcher; + } + + if (flags != 0) { + p->stdin = (int)(flags & 0xFF); + p->stdout = (int)(flags >> 8); + } else { + p->stdin = 0; + p->stdout = 1; + } // TODO: implement with malloc strcpy(p->name_buf, name); strcpy(p->args_buf, args); - p->name = &(p->name_buf); - p->args = &(p->args_buf); + p->name = (const char*)&(p->name_buf); + p->args = (const char*)&(p->args_buf); PROCESS_ID pid = add_process(p, current_pid); p->id = pid;

@@ -84,16 +102,11 @@ // setup stack

static SCHED_FRAME frame; frame.eax = frame.ebx = frame.ecx = frame.edx = 0; frame.esi = frame.edi = 0; - frame.ebp = p->ebp; - frame.esp = p->esp; + frame.ebp = (uint32_t)(p->ebp); + frame.esp = (uint32_t)(p->esp); frame.eflags = p->eflags; frame.cs = 0x18; - - if (name == NULL) { - frame.eip = entry_idle; - } else { - frame.eip = sched_dispatcher; - } + frame.eip = (uint32_t)(p->eip); // load stack copy_to_pdir(&frame, sizeof(frame), p->page_dir, p->esp);

@@ -117,9 +130,9 @@ //kpanic("SCHEDULER STACK INFO");

PROCESS* current = get_process(current_pid); if (current_pid != 0) { - current->esp = (uint32_t)frame; - current->ebp = ebp; - current->eip = frame->eip; + current->esp = (VIRT_ADDR)(frame); + current->ebp = (VIRT_ADDR)(ebp); + current->eip = (VIRT_ADDR)frame->eip; current->eflags = frame->eflags;

@@ -149,29 +162,39 @@ // prepare to return to process

PROCESS* next = get_process(current_pid); switch_page_dir(next->page_dir); + PRINT_DBG("esp: %p\n", next->esp); + PRINT_DBG("ebp: %p\n", next->ebp); + PRINT_DBG("eip: %p\n", next->eip); + PRINT_DBG("eflags: %p\n", next->eflags); + STACK_CHECKSUM checksum; stack_compute_checksum(&(checksum), next->esp, next->ebp); // check stack if (stack_compare_checksum(&(next->checksum), &(checksum))) { printk("STACK DAMAGED: PROCESS %i (%s), ESP %X, EBP %X\n", current_pid, get_process(current_pid)->name, next->esp, next->ebp); - memdump((void*)(next->esp), (void*)(next->ebp - next->esp)); + memdump((void*)(next->esp), (void*)((uint32_t)(next->ebp) - (uint32_t)(next->esp))); kpanic("CRITICAL STACK DAMAGE"); } // prepare stack frame = (volatile SCHED_FRAME*)(next->esp); ebp = next->ebp; - //frame->cs = 0x08; - //frame->eip = next->eip; - frame->eflags = next->eflags; - frame->esp = next->esp; - frame->ebp = next->ebp; + + if (current_pid == 0) { + frame->cs = 0x18; + frame->eip = next->eip; + frame->eflags = (uint32_t)(next->eflags); + frame->esp = (uint32_t)(next->esp); + frame->ebp = (uint32_t)(next->ebp); + } + + PRINT_DBG("esp: %p, ebp: %p, eip: %p, eflags: %p\n", frame->esp, frame->ebp, frame->eip, frame->eflags); // reset the timer pit_setup_channel(PIT_CHANNEL_0, PIT_MODE_0, SCHED_INTERVAL); - + pic1_eoi(); }

@@ -184,7 +207,7 @@

current_pid = 0; // create idle process - PROCESS_ID idle = sched_spawn(NULL, NULL); + PROCESS_ID idle = sched_spawn(NULL, NULL, 0); assert(idle != -1); return 1;

@@ -237,8 +260,6 @@

void sched_wait(PROCESS_ID pid) { assert(pid != current_pid); - if (pid < 0) { return; } - while (1) { PROCESS *p = get_process(pid); if (p == NULL || p->state == PSTATE_TERMINATED) { break; }

@@ -253,6 +274,8 @@

// perform the first timer interrupt manually pic_unmask_interrupt(0); INT(0x20); + + return 0; } int sched_stop(void) {

@@ -262,6 +285,8 @@ // kill all processes

// disable interrupts pic_mask_interrupt(0); + + return 0; } int sched_dispatcher(void) {

@@ -279,4 +304,6 @@ sched_kill(current_pid);

// just for absolute safety kpanic("Executing a terminated process!!\n"); + + return 0; }
M src/kernel/sched/sched.ssrc/kernel/sched/sched.s

@@ -15,6 +15,7 @@

// pass process stack as arguments push %ebx push %eax + xor %eax, %eax call sched_interrupt_c pop %eax pop %ebx
M src/kernel/sched/stack_check.csrc/kernel/sched/stack_check.c

@@ -3,7 +3,7 @@

void stack_compute_checksum(STACK_CHECKSUM* checksum, const void *esp, const void *ebp) { *checksum = 0; - for (uint32_t *p = esp; p < ebp; p = &p[1]) { + for (uint32_t *p = (uint32_t)(esp); p < (uint32_t)(ebp); p = &p[1]) { *checksum ^= *p; } }
M src/kernel/string.csrc/kernel/string.c

@@ -20,6 +20,7 @@ while (source[i]) {

destination[i] = source[i]; i++; } + destination[i] = 0; return destination; }
M src/kernel/syscall.csrc/kernel/syscall.c

@@ -8,10 +8,6 @@ void test(uint32_t ebx, uint32_t ecx, uint32_t edx) {

printk("SYSCALL 0x01: EBX=%i ECX=%X EDX=%X\n", ebx, ecx, edx); } -int __sysprint(const char *fmt, int arg1, int arg2) { - printk(fmt, arg1, arg2); -} - void* SYSCALL_TABLE[] = { file_read, file_write,

@@ -20,7 +16,11 @@ get_current_process,

sched_spawn, sched_wait, file_open, - graphics_set_mode + graphics_set_mode, + hard_reset, + file_dir_next, + file_lseek, + file_tell }; extern void syscall_interrupt(void);
M src/kernel/syscall.ssrc/kernel/syscall.s

@@ -17,4 +17,4 @@ mov %eax, (%esi)

// restore stack add $12, %esp - iret+ iret
M src/libcedos/cedos.csrc/libcedos/cedos.c

@@ -20,21 +20,27 @@ interrupt(0x30, res, 3, 0, 0, 0);

return res; } -int file_openat(int fd, const char *fname, int flags) { +int sc_file_read(int fd, char *buffer, uint32_t size) { volatile uint32_t res = 0; - interrupt(0x30, res, 6, fd, fname, flags); + interrupt(0x30, res, 0, fd, buffer, size); + return res; +} + +int sc_file_write(int fd, char *buffer, uint32_t size) { + volatile uint32_t res = 0; + interrupt(0x30, res, 1, fd, buffer, size); return res; } -int sc_file_read(int fd, char *buffer, uint32_t size) { +int sc_file_lseek(int fd, uint32_t offset, int whence) { volatile uint32_t res = 0; - interrupt(0x30, res, 0, fd, buffer, size); + interrupt(0x30, res, 10, fd, offset, whence); return res; } -int sc_file_write(int fd, char *buffer, uint32_t size) { +int sc_file_tell(int fd) { volatile uint32_t res = 0; - interrupt(0x30, res, 1, fd, buffer, size); + interrupt(0x30, res, 11, fd, 0, 0); return res; }

@@ -44,12 +50,18 @@ interrupt(0x30, res, 4, fname, args, 0);

return res; } +int process_spawn_pipe(const char *fname, const char *args, int stdin, int stdout) { + volatile uint32_t res = 0; + interrupt(0x30, res, 4, fname, args, stdin | (stdout << 8)); + return res; +} + 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) { +int sc_file_open(char *pathname, uint32_t flags) { volatile uint32_t res = 0; interrupt(0x30, res, 6, pathname, flags, 0); return res;

@@ -58,4 +70,16 @@

void graphics_set_mode(int mode) { volatile uint32_t res = 0; interrupt(0x30, res, 7, mode, 0, 0); +} + +void hard_reset() { + volatile uint32_t res = 0; + interrupt(0x30, res, 8, 0, 0, 0); +} + +int dir_next(int fd, int index, char *fname_buffer) { + void *pointer = (void*)(0); + volatile uint32_t res = 0; + interrupt(0x30, res, 9, fd, index, fname_buffer); + return res; }
M src/libcedos/include/cedos.hsrc/libcedos/include/cedos.h

@@ -9,13 +9,20 @@ int sysprint(const char *fmt, int arg1, int arg2);

int yield(); int get_pid(); int process_spawn(const char *fname, const char *args); +int process_spawn_pipe(const char *fname, const char *args, int stdin, int stdout); 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); +int sc_file_open(char *buffer, uint32_t flags); +int sc_file_lseek(int fd, uint32_t offset, int whence); +int sc_file_tell(int fd); + +void hard_reset(); + +int dir_next(int fd, int index, char *fname_buffer); #endif
M src/libcedos/include/stdio.hsrc/libcedos/include/stdio.h

@@ -1,6 +1,43 @@

#ifndef STDIO_H #define STDIO_H +#include <stdarg.h> +#include <stddef.h> + +typedef struct { int unused; } FILE; + +#define stdin (FILE*)(0) +#define stdout (FILE*)(1) +#define stderr (FILE*)(1) + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +#define EOF (-1) + +FILE* fopen(const char*, const char*); + +int fputc ( int character, FILE * stream ); +int fputs ( const char * str, FILE * stream ); +int fgetc ( FILE * stream ); +char * fgets ( char * str, int num, FILE * stream ); + +int getchar ( void ); +int putchar ( int character ); + +size_t fread(void*, size_t, size_t, FILE*); +size_t fwrite(const void*, size_t, size_t, FILE*); + +int vsprintf ( char * str, const char * format, va_list args); +int vfprintf(FILE*, const char*, va_list args); +int vprintf(const char *fmt, va_list args); + +int sprintf ( char * str, const char * format, ... ); +int fprintf(FILE*, const char*, ...); int printf(const char *fmt, ...); + +int fseek(FILE*, long, int); +long ftell(FILE*); #endif
M src/libcedos/stdio.csrc/libcedos/stdio.c

@@ -7,13 +7,89 @@

char user_numeric[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; char user_hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; +FILE* fopen(const char* filename, const char* mode) { + return (FILE*)(sc_file_open(filename, NULL)); +} + +size_t fread(void* buffer, size_t size, size_t count, FILE* file) { + return sc_file_read((int)(file), buffer, size * count); +} + +size_t fwrite(const void* buffer, size_t size, size_t count, FILE* file) { + return sc_file_write((int)(file), buffer, size * count); +} + +int fputc ( int character, FILE * stream ) { + int retval; + char c = character; + retval = fwrite(&c, 1, 1, stream); + + if (retval == 1) { + return (int)(c); + } else { + return EOF; + } +} + +int fgetc ( FILE * stream ) { + int retval; + char c = 0; + retval = fread(&c, 1, 1, stream); + + if (retval == 1) { + return (int)(c); + } else { + return EOF; + } +} + +int fputs ( const char * str, FILE * stream ) { + int i = 0; + + while (str[i] != 0 && str[i] != '\n') { i++; } + + fwrite(str, 1, i, stream); + + return i; +} + +char * fgets ( char * str, int num, FILE * stream ) { + int i = 0; + + while (i < num) { + str[i] = fgetc(stream); + if (str[i] == '\n' || str[i] == EOF) { break; } + i++; + } + + return i + 1; +} + +int getchar ( void ) { + return fgetc(stdin); +} +int putchar ( int character ) { + return fputc(character, stdout); +} + +int sprintf( char * str, const char * format, ... ); +int fprintf(FILE*, const char*, ...); +int printf(const char *fmt, ...); + +int fseek(FILE*, long, int); +long ftell(FILE*); + int print(char *buffer, int num) { - return sc_file_write(0, buffer, num); + return fwrite(buffer, sizeof(char), num, stdout); } int read_char(char *buffer, int num) { return sc_file_read(1, buffer, num); +} + +void print_char(char c) { + print(&c, 1); } /*void print_hex_char(uint8_t c) {

@@ -66,6 +142,17 @@ return rek_sprint_uint((unsigned int)value, buffer);

} } +int sprint_string(char *str, char *buffer) { + int length = 0; + while (str[length]) { buffer[length] = str[length]; length++; } + return length; +} + +int sprint_char(char c, char *buffer) { + buffer[0] = c; + return 1; +} + /*void rek_print_uint(unsigned int value) { if (value > 0) { rek_print_uint(value / 10);

@@ -103,43 +190,92 @@ int size = sprint_hex_char(c, buffer);

print(buffer, size); } -void print_char(char c) { - print(&c, 1); -} +int vsprintf(char *str, const char *fmt, va_list args) { + uint32_t index = 0; -int printf(const char *fmt, ...) { - va_list args; - va_start(args, fmt); - uint32_t index = 0; + int offset = 0; while (*fmt) { int i = 0; - while (fmt[i] != '\0' && fmt[i] != '%') { i++; } - if (i > 0) { print(fmt, i); } + while (fmt[i] != '\0' && fmt[i] != '%') { + offset += sprint_char(fmt[i++], str + offset); + } if (fmt[i] == '\0') { break; } fmt = fmt + i + 1; if (*fmt == 'X') { - print_uint32(va_arg(args, uint32_t)); + offset += sprint_uint32(va_arg(args, uint32_t), str + offset); } else if (*fmt == 'i') { - print_int(va_arg(args, int)); + offset += sprint_int(va_arg(args, int), str + offset); } else if (*fmt == 'x') { - print_int(va_arg(args, char)); + offset += sprint_hex_char(va_arg(args, int), str + offset); } else if (*fmt == 'u') { - print_uint(va_arg(args, unsigned int)); + offset += sprint_uint(va_arg(args, unsigned int), str + offset); } else if (*fmt == 'p') { - print_uint32(va_arg(args, uint32_t)); + offset += sprint_uint32(va_arg(args, uint32_t), str + offset); } else if (*fmt == 's') { const char* string = va_arg(args, const char*); - print_string(string); + offset += sprint_string(string, str + offset); } else if (*fmt == 'c') { - print_char(va_arg(args, int)); + offset += sprint_char(va_arg(args, int), str + offset); } else if (*fmt == '%') { - print_char('%'); + offset += sprint_char('%', str + offset); } else { - print_char(*fmt); + offset += sprint_char(*fmt, str + offset); } fmt++; } -}+ + str[offset] = 0; + return offset; +} + +int vfprintf(FILE *file, const char *fmt, va_list args) { + uint8_t buffer[512]; + int res = vsprintf(buffer, fmt, args); + res = fwrite(buffer, sizeof(uint8_t), res, file); + return res; +} + +int sprintf(char *str, const char *fmt, ...) { + va_list args; + + va_start(args, fmt); + int res = vsprintf(str, fmt, args); + va_end(args); + + return res; +} + +int fprintf(FILE *file, const char *fmt, ...) { + va_list args; + + va_start(args, fmt); + int res = vfprintf(file, fmt, args); + va_end(args); + + return res; +} + +int vprintf(const char *fmt, va_list args) { + return vfprintf(stdout, fmt, args); +} + +int printf(const char *fmt, ...) { + va_list args; + + va_start(args, fmt); + int res = vfprintf(stdout, fmt, args); + va_end(args); + + return res; +} + +int fseek(FILE* file, long offset, int whence) { + return sc_file_lseek(file, offset, whence); +} + +long ftell(FILE* file) { + return sc_file_tell(file); +}
M src/shell/cat.csrc/shell/cat.c

@@ -3,23 +3,21 @@ #include "stdio.h"

#include <stdint.h> +#define BUFFER_SIZE 1024 + void main(char *args) { - int fd = sc_file_open(args, 0); + FILE* file = fopen(args, "r"); - if (fd < 0) { + if (file == NULL) { printf("Could not find file: %s\n", args); return; } - char *buffer = (void*)(0x2000000); - - int size = sc_file_read(fd, buffer, -1); + char buffer[BUFFER_SIZE]; - while (size > 0) { - int chunk = 256; - if (size < chunk) { chunk = size; } - sc_file_write(0, buffer, chunk); - size -= chunk; - buffer += chunk; + while (1) { + int size = fread(buffer, 1, 1024, file); + if (size == 0) { break; } + fwrite(buffer, 1, size, stdout); } }
M src/shell/hexdump.csrc/shell/hexdump.c

@@ -3,40 +3,41 @@ #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); + FILE* file = fopen(args, "r"); - if (fd < 0) { + if (file == NULL) { printf("Could not find file: %s\n", args); return; } - char *buffer = (void*)(0x2000000); + uint8_t in_buffer[16]; + uint8_t out_buffer[64]; + + while (1) { + int in_offset = ftell(file); - int size = sc_file_read(fd, buffer, -1); + int size = fread(in_buffer, 1, 16, file); + if (size == 0) { break; } - hexdump(buffer, size); + int out_offset = 0; + out_offset += sprintf(out_buffer + out_offset, "%x%x%x%x ", in_offset >> 24, in_offset >> 16, in_offset >> 8, in_offset); + for (int i = 0; i < 16; i++) { + if (i < size) { + out_offset += sprintf(out_buffer + out_offset, "%x ", in_buffer[i]); + } else { + out_offset += sprintf(out_buffer + out_offset, " "); + } + } + out_offset += sprintf(out_buffer + out_offset, " |"); + for (int i = 0; i < 16; i++) { + if (i >= size) { break; } + uint8_t c = in_buffer[i]; + if (c < 0x20 || c > 0x7F) { c = '.'; } + out_offset += sprintf(out_buffer + out_offset, "%c", c); + } + out_offset += sprintf(out_buffer + out_offset, "|\n"); + fwrite(out_buffer, 1, out_offset, stdout); + } }
M src/shell/imgview.csrc/shell/imgview.c

@@ -7,33 +7,93 @@ #define GMODE_TEXT 0x02

#define GMODE_VIDEO 0x13 #define MAX(x, y) (x > y ? x : y) +#define MIN(x, y) (x < y ? x : y) + +typedef struct __attribute__((packed)) { + uint16_t signature; + uint32_t file_size; + uint16_t reserved_1; + uint16_t reserved_2; + uint32_t offset_pixelarray; +} BMP_FILE_HEADER; + +typedef struct { + uint32_t DIB_header_size; + uint32_t image_width; + uint32_t image_height; + /* ... */ +} DIB_HEADER; + +uint32_t convert_endian(uint32_t value) { + uint32_t res = 0; + + return value; + + for (int i = 0; i < 2; i++) { + uint8_t c = value & 0x0000FFFF; + value = value >> 16; + res = res << 16; + res |= c; + } + + return res; +} void main(char *args) { // open image file - int fd = sc_file_open(args, 0); + int fd = fopen(args, "r"); 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); + BMP_FILE_HEADER bmp_header; + DIB_HEADER dib_header; + + int size = 0; + + size = fread(&bmp_header, sizeof(bmp_header), 1, fd); + if (size != sizeof(bmp_header)) { printf("Error while reading BMP header\n"); return; } + + size = fread(&dib_header, sizeof(dib_header), 1, fd); + if (size != sizeof(dib_header)) { printf("Error while reading DIB header\n"); return; } + + int offset = bmp_header.offset_pixelarray; + int width = dib_header.image_width; + int height = dib_header.image_height; + + uint8_t rowbuf[512]; + + int off_x = 0; + int off_y = 0; + + fseek(fd, offset, SEEK_SET); // switch video mode and display image graphics_set_mode(GMODE_VIDEO); - for (int i = 0; i < MAX(size, limit); i++) { - gbuff[i] = fbuff[i]; + uint8_t *gbuff = (uint8_t*)(0xA0000); + + for (int y = 0; y < MIN(height, 240); y++) { + size = fread(rowbuf, sizeof(uint8_t), width, fd); + + if (size != width) { + graphics_set_mode(GMODE_TEXT); + printf("Error while reading row %i.", y); + } + + for (int x = 0; x < MIN(width, 320); x++) { + int g_i = (239 - y) * 320 + x; + + gbuff[g_i] = rowbuf[x]; + } } while (1) { - char c; - sc_file_read(0, &c, 1); + char c = getchar(); if (c == 0x1B) { break; } }
A src/shell/ls.c

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

+#include "cedos.h" +#include "stdio.h" + +#include <stdint.h> + +void main(char *args) { + char buffer[256]; + + int index = 0; + + while (1) { + int next = dir_next(2, index, buffer); + + if (next == -1) { return; } + + printf("%s\n", buffer); + index = next; + } +}
A src/shell/quit.c

@@ -0,0 +1,10 @@

+#include "cedos.h" +#include "stdio.h" + +#include <stdint.h> + +void main(char *args) { + printf("Thank you for using CeDOS!\n"); + + hard_reset(); +}
M src/shell/shelf.csrc/shell/shelf.c

@@ -8,7 +8,7 @@ int i = 0;

char c; buffer[0] = 0; while (1) { - sc_file_read(1, &c, 1); + c = getchar(); if (c == '\n') { break; } if (c == 0) { continue; }

@@ -16,15 +16,15 @@ if (c == 0x08 && i <= 0) { continue; }

if (c == 0x08) { buffer[--i] = 0; - sc_file_write(0, &c, 1); + putchar(c); } else { buffer[i++] = c; - sc_file_write(0, &c, 1); + putchar(c); } } buffer[i] = 0; - sc_file_write(0, &c, 1); + putchar(c); return i; }