jump to
@@ -0,0 +1,89 @@
+#include <stdint.h> +#include <stddef.h> + +#include "string.h" +#include "fat12.h" + +void printc(char c) { + static uint8_t *display = (uint8_t*)(0xB8000); + *(display++) = c; + *(display++) = 0x0F; +} + +void print_string(char *str) { + while (*str != 0) { + printc(*(str++)); + } +} + +void assert_failed(const char * message) { + print_string(message); + + while (1) {} +} + +FAT12_descriptor_t fat_desc; + +void *FAT12_read(uint32_t lba, uint32_t *offset, size_t size, void *buffer) { + void *FAT_addr = (void*)(0x10000); + + if (offset != NULL) { + lba += (*offset) / fat_desc.bytes_per_sect; + *offset = (*offset) % fat_desc.bytes_per_sect; + + void *ptr = (void*)((long)(FAT_addr) + (long)(lba * fat_desc.bytes_per_sect)); + return memcpy(buffer, ptr + *offset, size); + } else { + void *ptr = (void*)((long)(FAT_addr) + (long)(lba * fat_desc.bytes_per_sect)); + return memcpy(buffer, ptr, size); + } +} + +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); + FAT12_init(&fat_desc); + + int i = 0; + + // first cluster of kernel.bin file + uint16_t first_cluster; + + while (1) { + char buffer[832]; + uint32_t file_size; + + i = FAT12_root_dir_next(&fat_desc, i, buffer, &first_cluster, &file_size); + + print_string(buffer); + print_string(" "); + if (i <= 0) { return -1; } + + if (!(strcmp(buffer, "kernel.bin"))) { break; } + } + + // copy all clusters + uint16_t cluster = first_cluster; + uint8_t *buffer = (uint8_t *)(0x100000); + while (1) { + buffer = FAT12_read_cluster(&fat_desc, cluster, buffer); + cluster = FAT12_next_cluster(&fat_desc, cluster); + + if (cluster == 0xFFF || cluster == 0x000) { break; } + } + + return 0; +}
@@ -0,0 +1,10 @@
+#ifndef ASSERT_H +#define ASSERT_H + +#include <stdint.h> + +extern void assert_failed(const char * message); + +#define assert(cond) if (!(cond)) { assert_failed("Assertion failed: " #cond); } + +#endif
@@ -0,0 +1,180 @@
+#include "fat12.h" + +#include <stdint.h> +#include <stddef.h> + +#include "string.h" + +typedef struct { + char jmp[3]; + char oemname[8]; + + uint16_t bytes_per_sect; + uint8_t sect_per_cluster; + uint16_t num_reserved_sectors; + uint8_t num_FAT; + uint16_t max_root_dir_entries; + uint16_t total_log_sectors; + uint8_t media_desc; + uint16_t log_sect_per_fat; +} __attribute__((packed)) BOOT_SECT; + +typedef struct { + char name[8]; + char ext[3]; + uint8_t file_attr; + uint8_t user_attr; + uint8_t del_char; + uint16_t create_time; + uint16_t create_date; + uint16_t last_access_date; + uint16_t access_rights; + uint16_t last_modified_time; + uint16_t last_modified_date; + uint16_t start_of_clusters; + uint32_t file_size; +} __attribute__((packed)) DIR_ENTRY; + +typedef struct { + uint8_t seq_num; + uint16_t part_1[5]; + uint8_t file_attr; + uint8_t user_attr; + uint8_t del_char; + uint16_t part_2[6]; + uint16_t start_of_clusters; + uint16_t part_3[2]; +} __attribute__((packed)) VFAT_LFN_ENTRY; + + +/** + * @brief +*/ +void FAT12_init(FAT12_descriptor_t *fat) { + BOOT_SECT boot_sect; + FAT12_read(0, NULL, sizeof(boot_sect), &boot_sect); + + // copy FAT parameters from boot sector into fat descriptor + fat->bytes_per_sect = boot_sect.bytes_per_sect; + fat->log_sect_per_fat = boot_sect.log_sect_per_fat; + fat->max_root_dir_entries = boot_sect.max_root_dir_entries; + fat->media_desc = boot_sect.media_desc; + fat->num_FAT = boot_sect.num_FAT; + fat->num_reserved_sectors = boot_sect.num_reserved_sectors; + fat->sect_per_cluster = boot_sect.sect_per_cluster; + fat->total_log_sectors = boot_sect.total_log_sectors; + + // calculate starting addresses of FAT regions + fat->FAT1_lba = fat->num_reserved_sectors; + fat->FAT2_lba = fat->FAT1_lba + fat->log_sect_per_fat; + fat->root_lba = fat->FAT1_lba + (fat->log_sect_per_fat * fat->num_FAT); + + long root_dir_size = fat->max_root_dir_entries * sizeof(DIR_ENTRY); + fat->data_lba = fat->root_lba + (root_dir_size / fat->bytes_per_sect); + + // calculate cluster size + fat->cluster_size = fat->bytes_per_sect * fat->sect_per_cluster; +} + +void *FAT12_read_cluster(FAT12_descriptor_t *fat, uint16_t cluster, void *buffer) { + FAT12_read(fat->data_lba + ((cluster - 2) * fat->sect_per_cluster), NULL, fat->cluster_size, buffer); + + return buffer += fat->cluster_size; +} + +int FAT12_root_dir_next(FAT12_descriptor_t *fat, int index, char *fname_buffer, uint16_t *first_cluster, uint32_t *file_size) { + memset(fname_buffer, 0, sizeof(fname_buffer)); + + while (1) { + //printk("%i\n", index); + // index overflow + if (index >= fat->max_root_dir_entries) { + return -1; + } + + uint32_t offset = index * sizeof(DIR_ENTRY); + DIR_ENTRY dir_entry; + FAT12_read(fat->root_lba, &offset, sizeof(DIR_ENTRY), &dir_entry); + + // if first character of name is 0, then no subsequent entry is in use + if (dir_entry.name[0] == 0x00) { + return -1; + } + + // deleted file + if (dir_entry.name[0] == (char)(0xE5)) { + index++; + continue; + } + + // VFAT LFN entry + if (dir_entry.file_attr == 0x0F && dir_entry.start_of_clusters == 0 && dir_entry.file_size != 0) { + VFAT_LFN_ENTRY *lfn_entry = (VFAT_LFN_ENTRY*)(&dir_entry); + + int offset = 13 * ((lfn_entry->seq_num & 0x3F) - 1); + + // read long file name + for (int i = 0; i < 5; i++) { + fname_buffer[offset++] = lfn_entry->part_1[i]; + } + + for (int i = 0; i < 6; i++) { + fname_buffer[offset++] = lfn_entry->part_2[i]; + } + + for (int i = 0; i < 2; i++) { + fname_buffer[offset++] = lfn_entry->part_3[i]; + } + + index++; + continue; + } + + if (index == 0 && (dir_entry.file_attr & 0x08) && dir_entry.file_size == 0) { + // volume label + index++; + continue; + + } else if ((dir_entry.file_attr & 0x10) && dir_entry.file_size == 0) { + // subdirectory + + } else { + // regular file + + } + + *file_size = dir_entry.file_size; + *first_cluster = dir_entry.start_of_clusters; + + // if no VFAT LFN exists, use DOS name + if (fname_buffer[0] == 0) { + for (int i = 0; i < 8; i++) { + fname_buffer[i] = dir_entry.name[i]; + } + fname_buffer[8] = '.'; + for (int i = 0; i < 3; i++) { + fname_buffer[i + 9] = dir_entry.ext[i]; + } + fname_buffer[12] = 0; + } + + return index + 1; + } +} + +uint16_t FAT12_next_cluster(FAT12_descriptor_t *fat, uint16_t cluster) { + // assuming FAT12 + uint32_t offset = (cluster >> 1) * 3; + uint8_t sect[3]; + FAT12_read(fat->FAT1_lba, &offset, sizeof(sect), sect); + + if (cluster & 0x01) { + uint16_t high = (uint16_t)(sect[2]); + uint16_t low = (uint16_t)(sect[1] & 0xF0) >> 4; + return (high << 4) | low; + } else { + uint16_t low = (uint16_t)(sect[0]); + uint16_t high = (uint16_t)(sect[1] & 0x0F) << 8; + return low | high; + } +}
@@ -0,0 +1,82 @@
+#ifndef FAT12_H +#define FAT12_H + +#include <stdint.h> +#include <stddef.h> + +typedef struct { + // logical block addresses of FAT regions + uint32_t FAT1_lba; + uint32_t FAT2_lba; + uint32_t root_lba; + uint32_t data_lba; + + // FAT parameters, read out from boot sector + uint32_t bytes_per_sect; + uint32_t sect_per_cluster; + uint32_t num_reserved_sectors; + uint32_t num_FAT; + uint32_t max_root_dir_entries; + uint32_t total_log_sectors; + uint32_t media_desc; + uint32_t log_sect_per_fat; + + // calculated cluster size in bytes + uint32_t cluster_size; +} FAT12_descriptor_t; + + +/** + * @brief Read out a portion from the raw FAT12 image. + * This function has to be defined by whichever code is including this driver. + */ +extern void *FAT12_read(uint32_t lba, uint32_t *offset, size_t size, void *buffer); + + +/** + * @brief Initialize FAT12 descriptor structure + * + * The FAT12 descriptor contains read-out and pre-computed + * information about a given FAT12 image or disk. + * FAT12_init initializes the descriptor \p fat based on the FAT + * device that is accessible through the FAT12_read function. + * + * @param fat FAT descriptor to be initialized. +*/ +void FAT12_init(FAT12_descriptor_t *fat); + +/** + * @brief Read a single cluster from the FAT image. + * + * @param fat FAT descriptor of the FAT device. The driver user has to + * ensure that the descriptor corresponds to the FAT device accessible + * through the FAT12_read function. + * @param cluster Index of the cluster to read. + * @param buffer Pointer to a cluster-sized buffer. +*/ +void *FAT12_read_cluster(FAT12_descriptor_t *fat, uint16_t cluster, void *buffer); + +/** + * @brief Iterate through entries in the root directory and return the next file name, the first cluster index, and file size. + * + * @param fat FAT descriptor of the FAT device. + * @param index Index within the root directory table at which to start. + * @param fname_buffer Pointer to a buffer for the file name. + * @param first_cluster Pointer to a uint16_t to be filled with the index of the first cluster of the file. + * @param file_size Pointer to a uint32_t to be filled with the file size. + * + * @return -1 if the search has reached an end; Index within the directory table otherwise. +*/ +int FAT12_root_dir_next(FAT12_descriptor_t *fat, int index, char *fname_buffer, uint16_t *first_cluster, uint32_t *file_size); + +/** + * @brief Given a cluster index, return the value of the FAT table. + * + * @param fat FAT descriptor of the FAT device. + * @param cluster Cluster index. + * + * @return Value of the FAT at the given cluster index. +*/ +uint16_t FAT12_next_cluster(FAT12_descriptor_t *fat, uint16_t cluster); + +#endif
@@ -0,0 +1,107 @@
+#include "memory.h" +#include "string.h" + +#include "assert.h" + +struct memblock { + struct memblock *next; + size_t size; +}; + +volatile struct memblock volatile *malloc_first, *malloc_last, *malloc_next_free; + +int malloc_init(void *start, void *end) { + uint32_t mem_start = (uint32_t)(start); + uint32_t mem_end = (uint32_t)(end); + + 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; + + return 0; +} + +static struct memblock* get_memblock_from_ptr(void* ptr) { + /* Just search through all blocks */ + struct memblock* next = malloc_first; + uint32_t target = (uint32_t)(ptr); + + while (next) { + uint32_t start = (uint32_t)(&next[1]); + uint32_t end = (uint32_t)(next->next); + + if (target >= start && target < end) { + return next; + } + + next = next->next; + } + + return 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* malloc(size_t size) { + // 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; +} + +void* realloc(void* ptr, size_t new_size) { + void* new_ptr = malloc(new_size); + struct memblock* block = get_memblock_from_ptr(ptr); + + if (block == NULL) { + /* corresponding block not found */ + return NULL; + } + if (block->size == 0) { + /* corresponding block was already freed */ + return NULL; + } + + memcpy(new_ptr, ptr, block->size); + free(ptr); + + return new_ptr; +} + +/*! + * Frees a previously allocated block of memory. (KERNEL MODE) + * \param ptr Pointer to the memory block to be freed. + */ +void free(void* ptr) { + +}
@@ -0,0 +1,43 @@
+/*! \file + * Provides functions for memory allocation. + */ +#ifndef MEMORY_H +#define MEMORY_H + +#include <stdint.h> + +typedef uint32_t size_t; + +#define NULL (void*)(0) + +/*! + * Initialize memory allocator with predefined memory region. + * \param start Start of malloc memory region. + * \param end End of malloc memory region. + * \return Currently always 0. + */ +int malloc_init(void *start, void *end); + +/*! + * Allocates a block of \p size bytes of memory. + * \param size Size in bytes of the requested block of memory. + * \return Memory address to the new memory block, or NULL if failed + */ +void* malloc(size_t size); + +/*! + * Reallocates an already allocated block with new size. + * Contents are preserved. Pointer might change. + * Will fail if memory block at \p ptr has already been freed. + * \param ptr Pointer to already allocated memory block + * \param new_size Size of the new block + * \return Memory address to the new memory block, or NULL if failed*/ +void* realloc(void* ptr, size_t new_size); + +/*! + * Frees a previously allocated block of memory. + * \param ptr Pointer to the memory block to be freed. + */ +void free(void* ptr); + +#endif
@@ -1,10 +0,0 @@
-#ifndef ASSERT_H -#define ASSERT_H - -#include "cedos/core.h" - -#include <stdint.h> - -#define assert(cond) if (!(cond)) { kpanic("Assertion failed: " #cond); } - -#endif
@@ -6,8 +6,8 @@ #define KERNEL_H
#include <stdarg.h> -#include "cedos/drivers/console.h" -#include "cedos/interrupts.h" +#include "drivers/console.h" +#include "interrupts.h" int core_init(void); void printk(const char* string, ...);
@@ -25,7 +25,7 @@ /*!
* Reads a single character from the keyboard * \return A single char corresponding to a key press. */ - uint8_t (*read)(void); + int (*read)(void); } KB_DRIVER; //! PS/2 keyboard driver (default driver)
@@ -1,9 +1,9 @@
#ifndef TTY_H #define TTY_H -#include "cedos/file.h" -#include "cedos/drivers/keyboard.h" -#include "cedos/drivers/console.h" +#include "file.h" +#include "drivers/keyboard.h" +#include "drivers/console.h" int tty_open(const char *pathname, int flags); int tty_openat(int fd, const char *fname, int flags);
@@ -1,8 +1,8 @@
#ifndef ELF_H #define ELF_H -#include "cedos/sched/sched.h" -#include "cedos/sched/process.h" +#include "sched/sched.h" +#include "sched/process.h" /*! * Executes an elf file from memory
@@ -3,7 +3,7 @@ #define FAT_H
#include <stdint.h> -#include "cedos/file.h" +#include "file.h" void FAT_init(); int FAT_dir_next(file_t *file, int index, char *fname_buffer);
@@ -3,7 +3,7 @@ #define FILE_H
#include <stdint.h> -#include "cedos/mm/paging.h" +#include "mm/paging.h" typedef uint32_t fpos_t; typedef int32_t off_t;
@@ -1,41 +0,0 @@
-/*! \file - * Provides functions for memory allocation. - */ -#ifndef MEMORY_H -#define MEMORY_H - -#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. - * \return Memory address to the new memory block - */ -void* os_kernel_malloc(size_t size); - -/*! - * Frees a previously allocated block of memory. (KERNEL MODE) - * \param ptr Pointer to the memory block to be freed. - */ -void os_kernel_free(void* ptr); - -/*! - * Allocates a block of \p size bytes of memory. (USER MODE) - * \param size Size in bytes of the requested block of memory. - * \return Memory address to the new memory block - */ -void* os_user_malloc(size_t size); - -/*! - * Frees a previously allocated block of memory. (USER MODE) - * \param ptr Pointer to the memory block to be freed. - */ -void os_user_free(void* ptr); - -#endif
@@ -4,6 +4,8 @@ */
#ifndef PAGE_ALLOCATOR_H #define PAGE_ALLOCATOR_H +#include <stdint.h> + /*! * Returns a free page and marks it as used. * \return Address of the first byte on the page or NULL if no page was allocated.@@ -15,5 +17,7 @@ * Adds a previously allocated page as free.
* \param page_addr Pointer to any byte within the page to be freed. */ void mark_as_free(void* page_addr); + +uint32_t mem_usage(void); #endif
@@ -1,7 +1,7 @@
#ifndef PIPE_H #define PIPE_H -#include "cedos/file.h" +#include "file.h" int pipe_read(int fd, char *buffer, uint32_t size); int pipe_write(int fd, char *buffer, uint32_t size);
@@ -4,8 +4,8 @@ */
#ifndef PROCESS_H #define PROCESS_H -#include "cedos/mm/paging.h" -#include "cedos/sched/stack_check.h" +#include "mm/paging.h" +#include "sched/stack_check.h" /*! * Defines all possible states for processes.@@ -85,6 +85,9 @@ PROCESS_STATE state;
//! Process priority. PROCESS_PRIO priority; + + //! Process starvation counter + int starvation; //! Stack checksum STACK_CHECKSUM checksum;
@@ -6,11 +6,12 @@ #define SCHEDULER_H
#include <stdint.h> -#include "cedos/sched/process.h" +#include "sched/process.h" -#include "cedos/mm/paging.h" +#include "mm/paging.h" -#define SCHED_INTERVAL (0xFFFF) +// 11928 ~ 10ms per interval +#define SCHED_INTERVAL (1193) /*! * Structure of the process stack when the scheduler is executed.@@ -62,6 +63,20 @@ * Returns processing time to the scheduler prematurely and blocks the
* process for one unit of time. */ void sched_yield(void); + +/** + * @brief Blocks the current process for the given number of ticks. + * + * @param ticks Number of ticks. + */ +void sched_sleep(int ticks); + +/** + * @brief Unblocks the process given by \p pid immediately. + * + * @param pid ID of the process to be unblocked. + */ +void sched_unblock(int pid); /*! * Kills the process with the specified ID.
@@ -35,5 +35,6 @@
unsigned int strlen (const char *str); char *strcpy(char *destination, const char *source); int strcmp(const char *str1, const char *str2); +const char * strchr ( const char * str, int character ); #endif
@@ -0,0 +1,65 @@
+#include "memory.h" +#include "alarm.h" +#include "core.h" +#include "sched/sched.h" + +struct alarm *first = NULL; +int alarm_id_next = 1000; + +int alarm_add(int ticks, PROCESS_ID pid, alarm_mode m) { + struct alarm *next = malloc(sizeof(struct alarm)); + + next->alarm_id = alarm_id_next++; + next->ticks_remaining = ticks; + next->pid = pid; + next->m = m; + + // add to list + next->next = first; + first = next; + + return next->alarm_id; +} + +void alarm_tick(void) { + struct alarm **next = &first; + + while (*next) { + if ((*next)->ticks_remaining-- <= 0) { + // send signal to process + switch((*next)->m) { + case ALARM_WAKEUP: + sched_unblock((*next)->pid); + break; + case ALARM_KILL: + sched_kill((*next)->pid); + break; + default: + printk("Unknown alarm mode: %i\n", (int)((*next)->m)); + break; + } + + // remove alarm + *next = (*next)->next; + } else { + next = &((*next)->next); + } + } +} + +int alarm_cancel(int alarm_id) { + struct alarm **next = &first; + + while (*next) { + if ((*next)->alarm_id == alarm_id) { + // remove alarm + *next = (*next)->next; + return 0; + } else { + next = &((*next)->next); + } + } + + // alarm was not found + return -1; +}
@@ -0,0 +1,48 @@
+#ifndef ALARM_H +#define ALARM_H + +#include "sched/process.h" + +typedef enum { + ALARM_UNDEF = 0, + ALARM_WAKEUP = 1, + ALARM_KILL = 2 +} alarm_mode; + +struct alarm { + int alarm_id; + int ticks_remaining; + PROCESS_ID pid; + alarm_mode m; + + struct alarm *next; +}; + +/** + * @brief Decrease all alarm counters and act on finished alarms. + * + * This function is called by sched_interrupt_c. + */ +void alarm_tick(void); + +/** + * @brief Add a new alarm. + * + * @param ticks Number of ticks to count down. + * @param pid Process ID of the process targeted by the alarm. + * @param m Alarm mode. Defines which action to take once the timer has run out. + * + * @return ID of the created alarm. + */ +int alarm_add(int ticks, PROCESS_ID pid, alarm_mode m); + +/** + * @brief Cancel an existing alarm. + * + * @param alarm_id ID of the alarm to be cancelled. + * + * @return 0 on success, -1 if the alarm was not found. + */ +int alarm_cancel(int alarm_id); + +#endif
@@ -0,0 +1,3 @@
+#include "drivers/console.h" + +CON_DRIVER *std_con = &vga_con;
@@ -0,0 +1,3 @@
+#include "drivers/keyboard.h" + +KB_DRIVER *std_kb = &ps2_kb;
@@ -0,0 +1,61 @@
+#include "file.h" +#include "drivers/tty.h" + +#include "drivers/console.h" +#include "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; + static int state = 0; + static char next[2]; + while (i < size) { + if (state > 0) { + buffer[i++] = next[--state]; + continue; + } + 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, ' ', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'A' }; + int scancode = std_kb->read(); + if (scancode < 0) { + break; + } else if (scancode <= 60) { + char c = scancode <= 60 ? table[scancode] : 0; + if (c == 0) { continue; } + buffer[i++] = c; + } else if (scancode == 0xE0) { + scancode = std_kb->read(); + if (scancode > 0x48 || table[scancode] == 0) { continue; } + buffer[i++] = '^'; + next[1] = '['; + next[0] = table[scancode]; + state = 2; + } + } + return i; +} + +int tty_write(int fd, char *buffer, uint32_t size) { + std_con->write_n(buffer, size); + return size; +}
@@ -0,0 +1,266 @@
+#include "drivers/console.h" +#include "linker.h" +#include "assembly.h" +#include "string.h" + +#define VGA_TEXTMODE_COLUMNS 80 +#define VGA_TEXTMODE_LINES 25 +#define VGA_TEXTMODE_BPC 2 +#define VGA_TEXTMODE_LINE_WIDTH (VGA_TEXTMODE_COLUMNS * VGA_TEXTMODE_BPC) +#define VGA_TEXTMODE_CELLS (VGA_TEXTMODE_COLUMNS * VGA_TEXTMODE_LINES) +#define VGA_MEM_POS(line, column) ((line) * VGA_TEXTMODE_COLUMNS * VGA_TEXTMODE_BPC + (column) * VGA_TEXTMODE_BPC) +#define VGA_MEM_CELL(line, column) ((line) * VGA_TEXTMODE_COLUMNS + (column)) + +#define VGA_TEXTMODE_MEM ((uint8_t*)0xB8000) +#define VGA_MEM_VALUE(line, column) (VGA_TEXTMODE_MEM[VGA_MEM_POS((line), (column))]) +#define VGA_MEM_COLOR(line, column) (VGA_TEXTMODE_MEM[VGA_MEM_POS((line), (column)) + 1]) +#define VGA_MEM_ADDR(line, column) (&(VGA_MEM_VALUE((line), (column)))) + +#define VGA_INDEX_REG ((uint16_t)0x3D4) +#define VGA_DATA_REG ((uint16_t)0x3D5) + +uint32_t line = 0; +uint32_t column = 0; +uint8_t color = 0x0F; + +int vga_con_init(void); +void vga_con_write_c(const char c); +void vga_con_write_n(const char *string, uint32_t num); +void vga_con_write_s(const char *string); +void vga_con_clear(int mode); +void vga_con_clear_line(int mode); +void vga_con_newline(void); +void vga_con_backspace(void); + +CON_DRIVER vga_con = { + "VGA console", + vga_con_init, + vga_con_write_c, + vga_con_write_n, + vga_con_write_s, + vga_con_clear, + vga_con_newline, + vga_con_backspace +}; + +__attribute((always_inline)) inline void set_char(char value) { + VGA_MEM_VALUE(line, column) = value; + VGA_MEM_COLOR(line, column) = color; +} + +__attribute((always_inline)) inline void lfcr() { + line++; + column = 0; + + if (line >= VGA_TEXTMODE_LINES) { + memcpy( + VGA_MEM_ADDR(0, 0), + VGA_MEM_ADDR(1, 0), + VGA_TEXTMODE_LINE_WIDTH * (VGA_TEXTMODE_LINES - 1) + ); + memset( + VGA_MEM_ADDR(VGA_TEXTMODE_LINES - 1, 0), + 0, + VGA_TEXTMODE_LINE_WIDTH + ); + line = VGA_TEXTMODE_LINES - 1; + } +} + +__attribute((always_inline)) inline void write_char(char value) { + if (column >= VGA_TEXTMODE_COLUMNS || value == '\n') { + lfcr(); + } + + switch (value) { + case '\n': + break; + case '\0': + break; + default: + set_char(value); + column++; + break; + } +} + +__attribute((always_inline)) inline void set_cursor(uint16_t line, uint16_t column) { + uint16_t pos = line * VGA_TEXTMODE_COLUMNS + column; + outb(0x0F, VGA_INDEX_REG); + outb((uint8_t)(pos & 0xFF), VGA_DATA_REG); + outb(0x0E, VGA_INDEX_REG); + outb((uint8_t)(pos >> 8), VGA_DATA_REG); +} + +void enable_cursor(void) { + outb(0x0A, VGA_INDEX_REG); + outb((inb(VGA_DATA_REG) & 0x0C) | 0x00, VGA_DATA_REG); + outb(0x0B, VGA_INDEX_REG); + outb((inb(VGA_DATA_REG) & 0xE0) | 0x0F, VGA_DATA_REG); +} + +int vga_con_init(void) { + vga_con_clear(2); + + enable_cursor(); + set_cursor(line, column); + + for (uint32_t i = 0; i < 320 * 200; i++) { + uint8_t* disp = (uint8_t*)0xA0000; + disp[i] = (uint8_t)i; + } + + return 1; +} + +void vga_con_write_c(const char c) { + static enum { + NORMAL = 0, + ESCAPE_START = 1, + ESCAPE_N = 2, + ESCAPE_M = 3, + ESCAPE_C = 4 + } state; + static int n, m; + + if (state == NORMAL && c == '\e') { + // beginning of escape sequence + state = ESCAPE_START; + n = 0; + m = 0; + } else if (state == ESCAPE_START && c == '[') { + state = ESCAPE_N; + } else if (state == ESCAPE_N && c >= '0' && c <= '9') { + n = n * 10 + (c - '0'); + } else if (state == ESCAPE_M && c >= '0' && c <= '9') { + m = m * 10 + (c - '0'); + } else if (state == ESCAPE_N && c == ';') { + state = ESCAPE_M; + } else if (state == ESCAPE_N && c == 'G') { + column = n; + //set_cursor(line, column); + state = NORMAL; + } else if (state == ESCAPE_M && c == 'H') { + line = n; + column = m; + //set_cursor(line, column); + state = NORMAL; + } else if (state == ESCAPE_N && c == 'J') { + vga_con_clear(n); + state = NORMAL; + } else if (state == ESCAPE_N && c == 'K') { + vga_con_clear_line(n); + state = NORMAL; + } else if (state == ESCAPE_N && c == 'm') { + uint8_t color_compat[8] = { 0x00, 0x04, 0x02, 0x06, 0x01, 0x05, 0x03, 0x07 }; + if (n == 0) { + color = 0x0F; + } else if (n >= 30 && n <= 37) { + color = (color & 0xF0) | color_compat[n - 30]; + } else if (n >= 40 && n <= 47) { + color = (color & 0x0F) | (color_compat[n - 40] << 4); + } else if (n >= 90 && n <= 97) { + color = (color & 0xF0) | (color_compat[n - 90] + 8); + } else if (n >= 100 && n <= 107) { + color = (color & 0x0F) | ((color_compat[n - 100] + 8) << 4); + } else if (n < 106) { + color = n - 90 + 8; + } + state = NORMAL; + } else if (state != NORMAL) { + state = NORMAL; + } else if (c == 0x08) { + vga_con_backspace(); + //set_cursor(line, column); + } else { + write_char(c); + //set_cursor(line, column); + } +} + +void vga_con_write_n(const char *string, uint32_t num) { + for (uint32_t i = 0; i < num; i++) { + vga_con_write_c(string[i]); + } + set_cursor(line, column); +} + +void vga_con_write_s(const char *string) { + while (*string) { + write_char(*(string++)); + } + set_cursor(line, column); +} + +void vga_con_clear_line(int mode) { + // clear from cursor to end of screen + // clear from beginning of screen to cursor + // clear whole display + int start, end; + + switch(mode) { + case 0: + start = column; + end = VGA_TEXTMODE_COLUMNS; + break; + case 1: + start = 0; + end = column; + break; + default: + case 2: + start = 0; + end = VGA_TEXTMODE_COLUMNS; + break; + } + + for (int i = start; i < end; i++) { + VGA_MEM_VALUE(line, i) = 0; + VGA_MEM_COLOR(line, i) = color; + } +} + +void vga_con_clear(int mode) { + int cursor_pos = VGA_MEM_CELL(line, column); + int start, end; + + switch(mode) { + case 0: + start = cursor_pos; + end = VGA_TEXTMODE_CELLS; + break; + case 1: + start = 0; + end = cursor_pos; + break; + default: + case 2: + start = 0; + end = VGA_TEXTMODE_CELLS; + break; + } + + for (int i = 0; i < VGA_TEXTMODE_CELLS; i++) { + VGA_TEXTMODE_MEM[2 * i] = 0; + VGA_TEXTMODE_MEM[2 * i + 1] = color; + } + + line = 0; + column = 0; +} + +void vga_con_newline(void) { + lfcr(); +} + +void vga_con_backspace(void) { + if (column == 0 && line > 0) { + line--; + column = VGA_TEXTMODE_COLUMNS - 1; + } else if (column > 0) { + column--; + } + + set_char(0); + set_cursor(line, column); +}
@@ -0,0 +1,139 @@
+#include "file.h" +#include "fat.h" +#include "string.h" +#include "assert.h" +#include "core.h" + +#include "memory.h" +#include "fat12.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 */ +}; + +uint8_t *cluster_buffer; + +FAT12_descriptor_t *fat_desc; + +void *FAT12_read(uint32_t lba, uint32_t *offset, size_t size, void *buffer) { + void *FAT_addr = (void*)(0x10000); + + if (offset != NULL) { + lba += (*offset) / fat_desc->bytes_per_sect; + *offset = (*offset) % fat_desc->bytes_per_sect; + + void *ptr = (void*)((long)(FAT_addr) + (long)(lba * fat_desc->bytes_per_sect)); + return memcpy(buffer, ptr + *offset, size); + } else { + void *ptr = (void*)((long)(FAT_addr) + (long)(lba * fat_desc->bytes_per_sect)); + return memcpy(buffer, ptr, size); + } +} + + +void FAT_init() { + fat_desc = malloc(sizeof(FAT12_descriptor_t)); + + FAT12_init(fat_desc); + + cluster_buffer = malloc(fat_desc->cluster_size); +} + + +int FAT_dir_next(file_t *file, int index, char *fname_buffer) { + uint16_t first_cluster; + uint32_t file_size; + + // TODO: subdirectories + return FAT12_root_dir_next(fat_desc, index, fname_buffer, &first_cluster, &file_size); +} + +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) + uint16_t first_cluster; + while (1) { + char buffer[832]; + uint32_t file_size; + + i = FAT12_root_dir_next(fat_desc, i, buffer, &first_cluster, &file_size); + if (i <= 0) { return -1; } + + if (strcmp(buffer, fname) == 0) { + // file found + handle->pos = 0; + handle->size = file_size; + handle->fops = &FAT_fops; + handle->fat_cluster = first_cluster; + return 0; + } + } +} + +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; + + if (offset + count > file_size) { + count = file_size - offset; + } + + while (offset >= fat_desc->cluster_size) { + cluster = FAT12_next_cluster(fat_desc, cluster); + if (cluster == 0xFFF || cluster == 0x000) { return -1; } + offset -= fat_desc->cluster_size; + } + + while (count > 0) { + if (cluster == 0xFFF || cluster == 0x000) { break; } + + FAT12_read_cluster(fat_desc, cluster, cluster_buffer); + cluster = FAT12_next_cluster(fat_desc, cluster); + + uint32_t memcpy_size; + + if (offset + count > fat_desc->cluster_size) { + memcpy_size = (fat_desc->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; +}
@@ -0,0 +1,19 @@
+#include "mm/page_allocator.h" +#include "mm/paging.h" +#include "core.h" + +uint8_t* first_free = (uint8_t*)0x00500000; + +void* get_free_page() { + void* res = first_free; + first_free += PAGE_SIZE; + return res; +} + +uint32_t mem_usage(void) { + return (uint32_t)(first_free); +} + +void mark_as_free(void* page_addr) { + +}
@@ -0,0 +1,58 @@
+#include "file.h" +#include "pipe.h" +#include "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; + +int pipe_readc() { + if (write_head == read_head) { + return -1; + } + + int rh_next = (read_head + 1) % PIPE_BUFFER_SIZE; + uint8_t res = pipe_buffer[read_head]; + read_head = rh_next; + return res; +} + +int pipe_writec(uint8_t c) { + int wh_next = (write_head + 1) % PIPE_BUFFER_SIZE; + if ((wh_next + 1) % PIPE_BUFFER_SIZE == read_head) { + return -1; + } + pipe_buffer[write_head] = c; + write_head = wh_next; + return c; +} + +int pipe_read(int fd, char *buffer, uint32_t size) { + int i = 0; + while (i < size) { + int res = pipe_readc(); + if (res == -1) { break; } + buffer[i++] = (char)(res); + } + return i; +} + +int pipe_write(int fd, char *buffer, uint32_t size) { + int i = 0; + while (i < size) { + int res = pipe_writec(buffer[i++]); + if (res == -1) { break; } + } + return i; +}
@@ -0,0 +1,33 @@
+#include "sched/process.h" + +#define NULL ((void*)0) + +PROCESS_ID next_schedule(PROCESS_ID current) { + PROCESS* next = get_first_process(); + + PROCESS* choice = NULL; + + while (next) { + // skip idle process + if (next->id == 0) { + next = next->next; + continue; + } + + next->starvation++; + + // choose ready process with highest starvation value + if (next->state == PSTATE_READY && next->starvation > choice->starvation) { + choice = next; + } + + next = next->next; + } + + if (choice) { + choice->starvation = 0; + return choice->id; + } else { + return 0; + } +}
@@ -0,0 +1,11 @@
+#include "time.h" + +int ticks = 0; + +void time_tick(void) { + ticks++; +} + +int time_get_ticks(void) { + return ticks; +}
@@ -0,0 +1,8 @@
+#ifndef __TIME_H +#define __TIME_H + +void time_tick(void); + +int time_get_ticks(void); + +#endif
@@ -0,0 +1,11 @@
+#include "cedos.h" +#include "stdio.h" + +void assert_failed(const char * message) { + printf(message); + + int pid = get_pid(); + + /* TODO: Kill this process */ + while (1) {} +}
@@ -0,0 +1,23 @@
+#include "stdlib.h" + +int atoi (const char * str) { + int res = 0; + int sign = 1; + int i = 0; + + if (str[0] == '+') { + sign = 1; + i = 1; + } else if (str[0] == '-') { + sign == -1; + i = 1; + } else if (str[0] < '0' || str[0] > '9') { + return 0; + } + + while (str[i] >= '0' && str[i] <= '9') { + res = 10 * res + (str[i++] - '0'); + } + + return res; +}
@@ -0,0 +1,46 @@
+/*! \file + * Provides functions for memory allocation. + */ +#ifndef MEMORY_H +#define MEMORY_H + +#include <stdint.h> + +typedef uint32_t size_t; + +#define NULL (void*)(0) + +/*! + * Initialize memory allocator with predefined memory region. + * \param start Start of malloc memory region. + * \param end End of malloc memory region. + * \return Currently always 0. + */ +int malloc_init(void *start, void *end); + +/*! + * Allocates a block of \p size bytes of memory. + * \param size Size in bytes of the requested block of memory. + * \return Memory address to the new memory block + */ +void* malloc(size_t size); + +/*! + * Reallocates an already allocated block with new size. + * Contents are preserved. Pointer might change. + * Will fail if memory block at \p ptr has already been freed. + * \param ptr Pointer to already allocated memory block + * \param new_size Size of the new block + * \return Memory address to the new memory block, or NULL if failed*/ +void* realloc(void* ptr, size_t new_size); + +/*! + * Frees a previously allocated block of memory. + * \param ptr Pointer to the memory block to be freed. + */ +void free(void* ptr); + + +int atoi (const char * str); + +#endif
@@ -5,7 +5,7 @@ export CURRENT_DIR := $(shell pwd)
export ROOT_DIR := $(CURRENT_DIR) export SOURCE_DIR := $(CURRENT_DIR)/src export INCLUDE_DIR := $(CURRENT_DIR)/include -export LOG_DIR := $(CURRENT_DIR)/log +export BUILD_LOGS := $(CURRENT_DIR)/log # path to cross compiler export CROSS_COMP := $(HOME)/opt/cross/bin/i686-elf-@@ -34,6 +34,9 @@ CCFLAGS := $(CCFLAGS) -nostdlib -nostartfiles -ffreestanding
CCFLAGS := $(CCFLAGS) -mgeneral-regs-only -mno-red-zone CCFLAGS := $(CCFLAGS) --prefix=$(CROSS_COMP) +GIT_VERSION := "$(shell git describe --abbrev=4 --dirty --always --tags)" +CCFLAGS := $(CCFLAGS) -DVERSION=\"$(GIT_VERSION)\" + # debug target .PHONY: debug@@ -49,64 +52,183 @@ CCFLAGS := $(CCFLAGS) -O1
GLOBAL_BUILD := $(GLOBAL_BUILD)/release endif -LOCAL_BUILD := $(GLOBAL_BUILD)/components +ifndef VERBOSE +.SILENT: +> echo "Silent mode active." +endif + +BUILD_OBJECTS := $(GLOBAL_BUILD)/obj +BUILD_ARTIFACTS := $(GLOBAL_BUILD)/artifacts +BUILD_LOGS := $(GLOBAL_BUILD)/logs +BUILD_MOUNT := $(GLOBAL_BUILD)/mnt export CCFLAGS export GLOBAL_BUILD -MODULES := boot kernel libcedos shell -OBJECTS := $(patsubst %,$(LOCAL_BUILD)/%.o,$(MODULES)) $(LOCAL_BUILD)/apps_raw.o -DIRS := $(LOCAL_BUILD) $(LOG_DIR) +SRC_ALL := $(shell find common/ boot/ kernel/ libcedos/ shell/ -name '*.c') +ASM_ALL := $(shell find common/ boot/ kernel/ libcedos/ shell/ -name '*.s') + +OBJECTS := $(patsubst %,$(BUILD_OBJECTS)/%.o,$(SRC_ALL) $(ASM_ALL)) + + +DIRS := $(dir $(OBJECTS)) $(BUILD_ARTIFACTS) $(BUILD_LOGS) +DIRS := $(sort $(DIRS)) -$(MODULES): | $(DIRS) $(DIRS): > $(MKDIR) $@ +ifndef VERBOSE +> echo "MKDIR $@" +endif .PHONY: build -build: $(GLOBAL_BUILD)/cedos.img +build: $(BUILD_ARTIFACTS)/cedos.img +$(OBJECTS): $(DIRS) + +$(BUILD_OBJECTS)/%.s.o: %.s +> $(AS) -o $@ $< +ifndef VERBOSE +> echo "AS $@" +endif + +# common +OBJ_COMMON := $(filter $(BUILD_OBJECTS)/common/%,$(OBJECTS)) +$(BUILD_OBJECTS)/common/%.c.o: common/%.c +> $(CC) -c -Icommon $(CCFLAGS) -o $@ $< + -$(GLOBAL_BUILD)/fat.img: $(MODULES) -# > $(LD) $(OBJECTS) -r -T link.txt -Map=$(LOG_DIR)/elf_mapfile.txt --oformat elf32-i386 -o $@ -> dd if=/dev/zero of=$@ count=896 -> 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)/bin/* ./mnt -> sudo cp ./img-contents/* ./mnt || echo "No img-contents folder; Skipping." -> du -csh ./mnt/* -> sudo umount ./mnt +# boot +OBJ_BOOT := $(filter $(BUILD_OBJECTS)/boot/%,$(OBJECTS)) +OUT_BOOT := $(BUILD_ARTIFACTS)/boot.elf $(BUILD_ARTIFACTS)/boot.bin + +$(BUILD_OBJECTS)/boot/%.c.o: boot/%.c +> $(CC) -c -Iboot -Icommon $(CCFLAGS) -o $@ $< +ifndef VERBOSE +> echo "CC $@" +endif -$(GLOBAL_BUILD)/cedos.img: $(GLOBAL_BUILD)/fat.img | $(MODULES) -> dd if=/dev/zero of=$@ count=904 -> parted $@ mklabel msdos -> parted $@ mkpart primary FAT32 8s 896s -s -> 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 $@ +$(BUILD_ARTIFACTS)/boot.elf: $(OBJ_BOOT) $(OBJ_COMMON) +> $(LD) $^ -T boot/link.txt -Map=$(BUILD_LOGS)/boot_mapfile.txt --oformat elf32-i386 -o $@ +ifndef VERBOSE +> echo "LD $@" +endif -.PHONY: logs -logs: $(LOG_DIR)/base.sym $(LOG_DIR)/objdump.txt +$(BUILD_ARTIFACTS)/boot.bin: $(OBJ_BOOT) $(OBJ_COMMON) +> $(LD) $^ -T boot/link.txt -Map=$(BUILD_LOGS)/boot_mapfile.txt --oformat binary -o $@ +ifndef VERBOSE +> echo "LD $@" +endif .PHONY: boot -boot: -> $(MAKE) GLOBAL_BUILD=$(LOCAL_BUILD) -C src/boot $(LOCAL_BUILD)/boot.bin +boot: $(OUT_BOOT) + + +# kernel +OBJ_KERNEL := $(filter $(BUILD_OBJECTS)/kernel/%,$(OBJECTS)) +OUT_KERNEL := $(BUILD_ARTIFACTS)/kernel.elf $(BUILD_ARTIFACTS)/kernel.bin + +$(BUILD_OBJECTS)/kernel/%.c.o: kernel/%.c +> $(CC) -c -Ikernel -Icommon $(CCFLAGS) -o $@ $< +ifndef VERBOSE +> echo "CC $@" +endif + +$(BUILD_ARTIFACTS)/kernel.elf: $(OBJ_KERNEL) $(OBJ_COMMON) +> $(LD) $^ -T kernel/link.txt -Map=$(BUILD_LOGS)/kernel_mapfile.txt --oformat elf32-i386 -o $@ +ifndef VERBOSE +> echo "LD $@" +endif + +$(BUILD_ARTIFACTS)/kernel.bin: $(OBJ_KERNEL) $(OBJ_COMMON) +> $(LD) $^ -T kernel/link.txt -Map=$(BUILD_LOGS)/kernel_mapfile.txt --oformat binary -o $@ +ifndef VERBOSE +> echo "LD $@" +endif .PHONY: kernel -kernel: -> $(MAKE) GLOBAL_BUILD=$(LOCAL_BUILD) -C src/kernel $(LOCAL_BUILD)/kernel.bin +kernel: $(OUT_KERNEL) + + +# libcedos +OBJ_LIBCEDOS := $(filter $(BUILD_OBJECTS)/libcedos/%,$(OBJECTS)) +OUT_LIBCEDOS := $(BUILD_ARTIFACTS)/libcedos.a + +$(BUILD_OBJECTS)/libcedos/%.c.o: libcedos/%.c +> $(CC) -c -Ilibcedos -Icommon $(CCFLAGS) -o $@ $< +ifndef VERBOSE +> echo "CC $@" +endif + +$(BUILD_ARTIFACTS)/libcedos.a: $(OBJ_LIBCEDOS) $(OBJ_COMMON) +> $(AR) rcs $@ $^ +ifndef VERBOSE +> echo "AR $@" +endif .PHONY: libcedos -libcedos: -> $(MAKE) GLOBAL_BUILD=$(LOCAL_BUILD) -C src/libcedos build +libcedos: $(OUT_LIBCEDOS) + + +# shell +OBJ_SHELL := $(filter $(BUILD_OBJECTS)/shell/%,$(OBJECTS)) +OUT_SHELL := $(patsubst $(BUILD_OBJECTS)/shell/%.c.o,$(BUILD_ARTIFACTS)/%,$(OBJ_SHELL)) + +SHELL_CCFLAGS += -I../libcedos/include +SHELL_LDFLAGS += -L$(BUILD_ARTIFACTS) +SHELL_LDFLAGS += -lcedos + +SHELL_LDFLAGS += -T shell/link.txt +SHELL_LDFLAGS += -Map=$(BUILD_LOGS)/$(notdir $@)_mapfile.txt +SHELL_LDFLAGS += -N + +$(BUILD_OBJECTS)/shell/%.c.o: shell/%.c +> $(CC) -c -Ishell -Ilibcedos -Icommon $(CCFLAGS) $(SHELL_CCFLAGS) -o $@ $< +ifndef VERBOSE +> echo "CC $@" +endif + +$(BUILD_ARTIFACTS)/%: $(BUILD_OBJECTS)/shell/%.c.o | $(BUILD_ARTIFACTS)/libcedos.a +> $(LD) $^ $(LDFLAGS) $(SHELL_LDFLAGS) -o $@ +ifndef VERBOSE +> echo "LD $@" +endif .PHONY: shell -shell: -> $(MAKE) GLOBAL_BUILD=$(LOCAL_BUILD) -C src/shell build +shell: $(OUT_SHELL) + + +# disk image +$(BUILD_ARTIFACTS)/fat.img: $(filter %.bin,$(OUT_KERNEL)) $(OUT_SHELL) | $(BUILD_ARTIFACTS)/boot.bin +# > $(LD) $(OBJECTS) -r -T link.txt -Map=$(BUILD_LOGS)/elf_mapfile.txt --oformat elf32-i386 -o $@ +> dd if=/dev/zero of=$@ count=896 +> mkfs.fat -n "cedos" -S 512 -s 8 -r 64 $@ +> mkdir -p $(BUILD_MOUNT) +> sudo mount $@ $(BUILD_MOUNT) +> sudo cp $^ $(BUILD_MOUNT) +> sudo cp ./img-contents/* $(BUILD_MOUNT) || echo "No img-contents folder; Skipping." +> du -csh $(BUILD_MOUNT)/* +> sudo umount $(BUILD_MOUNT) +> rm -r $(BUILD_MOUNT) +ifndef VERBOSE +> echo "MKFS $@" +endif + +$(BUILD_ARTIFACTS)/cedos.img: $(BUILD_ARTIFACTS)/fat.img | $(MODULES) +> dd if=/dev/zero of=$@ count=904 +> parted $@ mklabel msdos +> parted $@ mkpart primary FAT32 8s 896s -s +> parted $@ set 1 boot on +> dd if=$< of=$@ seek=8 conv=notrunc +> dd bs=1 if=$(BUILD_ARTIFACTS)/boot.bin of=$@ count=446 conv=notrunc +> dd if=$(BUILD_ARTIFACTS)/boot.bin of=$@ skip=1 seek=1 count=7 conv=notrunc +> python3 binimg.py -w 256 -i $(BUILD_ARTIFACTS)/cedos.img -o $(BUILD_ARTIFACTS)/cedos.png +> parted $@ print list all +# > $(LD) $(OBJECTS) -T link.txt -Map=$(BUILD_LOGS)/bin_mapfile.txt --oformat binary --nostdlib -o $@ +ifndef VERBOSE +> echo "MKPART $@" +endif + +.PHONY: logs +logs: $(BUILD_LOGS)/base.sym $(BUILD_LOGS)/objdump.txt .PHONY: clean clean:@@ -114,7 +236,7 @@ > $(RM) -r $(CURRENT_DIR)/build/* 2> /dev/null; true
.PHONY: run run: -> ./run.sh $(GLOBAL_BUILD)/cedos.img +> ./run.sh $(BUILD_ARTIFACTS)/cedos.img .PHONY: docs docs:
@@ -1,5 +1,5 @@
if [ -z "$QEMU_VNC" ]; then - 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 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 2> build/release/logs/run_err.log else - 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 + 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> build/release/logs/run_err.log fi
@@ -0,0 +1,13 @@
+#include "cedos.h" + +#include <stdint.h> +#include "stdlib.h" +#include "string.h" + +#include "cedos.h" + +void main(char *args) { + int pid = atoi(args); + + process_kill(pid); +}
@@ -0,0 +1,93 @@
+#include "cedos.h" +#include "stdio.h" +#include "string.h" + +const uint32_t K[64] = { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 }; + +const uint32_t s[64] = { + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 }; + +#define MD5_CHUNK_SIZE 512 + +#define lrotate32(x, i) ((x << i) | (x >> (32 - i))) + +void main(char *args) { + FILE* file = fopen(args, "r"); + + if (file == NULL) { + printf("Could not find file: %s\n", args); + return; + } + + char buffer[MD5_CHUNK_SIZE]; + uint32_t hash[4] = { 0x01234567, 0x89abcdef, 0xfedcba98, 0x76543210 }; + + int run = 1; + while (run) { + memset(buffer, 0, MD5_CHUNK_SIZE); + int size = fread(buffer, 1, MD5_CHUNK_SIZE, file); + if (size < MD5_CHUNK_SIZE) { + buffer[size] = 0x80; + run = 0; + } + + uint32_t *M = buffer; + uint32_t chunk_hash[4] = { hash[0], hash[1], hash[2], hash[3] }; + uint32_t F, g; + + for (int i = 0; i < 64; i++) { + if (i < 16) { + F = (chunk_hash[1] & chunk_hash[2]) + | ((~chunk_hash[1]) & chunk_hash[3]); + g = i; + } else if (i < 32) { + F = (chunk_hash[3] & chunk_hash[1]) + | ((~chunk_hash[3]) & chunk_hash[2]); + g = (5 * i + 1) % 16; + } else if (i < 48) { + F = chunk_hash[1] ^ chunk_hash[2] ^ chunk_hash[3]; + g = (3 * i + 5) % 16; + } else { + F = chunk_hash[2] ^ (chunk_hash[2] | (~chunk_hash[3])); + g = (7 * i) % 16; + } + + F = F + chunk_hash[0] + K[i] + M[g]; + chunk_hash[0] = chunk_hash[3]; + chunk_hash[3] = chunk_hash[2]; + chunk_hash[2] = chunk_hash[1]; + chunk_hash[1] = chunk_hash[1] + lrotate32(F, s[i]); + } + + hash[0] += chunk_hash[0]; + hash[1] += chunk_hash[1]; + hash[2] += chunk_hash[2]; + hash[3] += chunk_hash[3]; + } + + uint8_t *digest = (uint8_t *)(hash); + + for (int i = 0; i < 16; i++) { + printf("%x", digest[i]); + } + printf("\n"); +}
@@ -0,0 +1,9 @@
+#include "cedos.h" +#include "stdio.h" + +#include <stdint.h> + +void main(char *args) { + uint32_t memusage = sc_mem_usage(); + printf("%i KB\n", memusage / 1000); +}
@@ -0,0 +1,29 @@
+#include "stdio.h" +#include "stdlib.h" +#include "string.h" + +int main(char *args) { + printf("Malloc test\n"); + + void* a = malloc(1024); + printf("addr a: %p\n", a); + + void* b = malloc(1024); + printf("addr a: %p\n", b); + + printf("Copying test strings.\n"); + + strcpy(a, "This is test string a."); + strcpy(b, "Test string b is this."); + + printf("String in a: %s\n", a); + printf("String in b: %s\n", b); + + printf("Testing realloc.\n"); + + a = realloc(a, 512); + b = realloc(b, 2048); + + printf("Value of a at addr %p: %s\n", a, a); + printf("Value of b at addr %p: %s\n", b, b); +}
@@ -0,0 +1,125 @@
+#include "cedos.h" +#include "stdio.h" +#include "string.h" +#include "stdlib.h" + +#include <stdint.h> + +struct hist_item { + char* buffer; + struct hist_item* next; +}; + +struct hist_item* hist_first = NULL; + +char* read_line() { + int i = 0; + char c; + + char* buffer = malloc(512); + buffer[0] = 0; + + struct hist_item* history = hist_first; + + while (1) { + c = getchar(); + + if (c == '\n') { + break; + } else if (c == 0) { + continue; + } else if (c == 0x08 && i <= 0) { + continue; + } else if (c == '^' && getchar() == '[' && getchar() == 'A') { + if (history == NULL) { continue; } + strcpy(buffer, history->buffer); + while (i) { putchar(0x08); i--; } + i = strlen(buffer); + puts(buffer); + history = history->next; + continue; + } else if (c == 0x08) { + buffer[--i] = 0; + putchar(c); + } else { + buffer[i++] = c; + putchar(c); + } + } + + buffer[i] = 0; + putchar(c); + + if (i > 0) { + // append command history + struct hist_item* next = malloc(sizeof(struct hist_item)); + next->buffer = buffer; + next->next = hist_first; + hist_first = next; + } + + char *ret_buf = malloc(512); + strcpy(ret_buf, buffer); + + return ret_buf; +} + +int async[32]; +int async_index; + +void main(char *args) { + uint32_t a = 0, b = 1, i = 0; + printf("\n"); + printf("\e[94mShELF shell interface for CeDOS\e[97m\n"); + printf("Version: " VERSION "\n"); + + while (1) { + printf("/> "); + + char* buffer = read_line(buffer, hist_first); + + if (strlen(buffer) == 0) { continue; } + + char *file = buffer; + char *args = strchr(file, ' '); + char *amp = strchr(file, '.'); + + if (args != NULL) { + args[0] = 0; + args++; + } + + if (strcmp(file, "exit") == 0) { + printf("Thank you for using ShELF!\n"); + break; + } else if (strcmp(file, "history") == 0) { + struct hist_item* item = hist_first; + + while (item) { + printf("%s\n", item->buffer); + item = item->next; + } + + continue; + } else if (strcmp(file, "clear") == 0) { + printf("\e[2J"); + continue; + } + + int pid = process_spawn(file, args); + + //printf("Child process %i spawned, waiting for termination...\n", pid); + + if (pid == -1) { + printf("File not found: %s\n", buffer); + } else if (amp != NULL) { + printf("[%i] %i\n", async_index, pid); + + async[async_index++] = pid; + } else { + process_wait(pid); + } + + //printf("Child process %i terminated.\n", pid); + } +}
@@ -0,0 +1,38 @@
+#include "cedos.h" +#include "stdio.h" + +#include <stdint.h> +#include "stdlib.h" +#include "string.h" + +#include "cedos.h" + +void main(char *args) { + if (args == NULL || strlen(args) == 0) { + int ticks = sc_time_get_ticks(); + printf("%i\n", ticks); + } else { + int interval = atoi(args); + + if (interval <= 0) { + printf("Invalid interval value.\n"); + return; + } + + int pid = get_pid(); + int color = 40 + (pid % 8); + + int superticks = 0; + + while (1) { + int ticks = sc_time_get_ticks(); + + if (ticks / interval != superticks) { + printf("\e[%im\e[0K[%i] %i ticks\e[0m\n", color, pid, ticks); + superticks = ticks / interval; + } + + sleep(interval); + } + } +}
@@ -186,6 +186,9 @@ mov %eax, %fs
mov %eax, %gs call load_kernel + + test %eax, %eax + jnz loop # create a page directory for the kernel that maps it to 0xC0000000 # and identity maps the first 1M of memory
@@ -1,182 +0,0 @@
-#include "fat.h" -#include "string.h" -#include <stdint.h> - -typedef struct { - char jmp[3]; - char oemname[8]; - - uint16_t bytes_per_sect; - uint8_t sect_per_cluster; - uint16_t num_reserved_sectors; - uint8_t num_FAT; - uint16_t max_root_dir_entries; - uint16_t total_log_sectors; - uint8_t media_desc; - uint16_t log_sect_per_fat; -} __attribute__((packed)) BOOT_SECT; - -typedef struct { - char name[8]; - char ext[3]; - uint8_t file_attr; - uint8_t user_attr; - uint8_t del_char; - uint16_t create_time; - uint16_t create_date; - uint16_t last_access_date; - uint16_t access_rights; - uint16_t last_modified_time; - uint16_t last_modified_date; - uint16_t start_of_clusters; - uint32_t file_size; -} __attribute__((packed)) DIR_ENTRY; - -typedef struct { - uint8_t seq_num; - uint16_t part_1[5]; - uint8_t file_attr; - uint8_t user_attr; - uint8_t del_char; - uint16_t part_2[6]; - uint16_t start_of_clusters; - uint16_t part_3[2]; -} __attribute__((packed)) VFAT_LFN_ENTRY; - - -void *FAT_addr; -BOOT_SECT *boot_sect; - -uint32_t FAT1_lba; -uint32_t FAT2_lba; -uint32_t root_lba; -uint32_t data_lba; - -void FAT_init() { - // open image file - FAT_addr = (void*)(0x10000); - - boot_sect = (BOOT_SECT*)(FAT_addr); - - FAT1_lba = boot_sect->num_reserved_sectors; - FAT2_lba = FAT1_lba + boot_sect->log_sect_per_fat; - root_lba = FAT1_lba + (boot_sect->log_sect_per_fat * boot_sect->num_FAT); - - long root_dir_size = boot_sect->max_root_dir_entries * sizeof(DIR_ENTRY); - data_lba = root_lba + (root_dir_size / boot_sect->bytes_per_sect); -} - -void *FAT_read_sector_offset(uint32_t lba, uint32_t *offset) { - if (offset != NULL) { - lba += (*offset) / boot_sect->bytes_per_sect; - *offset = (*offset) % boot_sect->bytes_per_sect; - } - - return (void*)((long)(FAT_addr) + (long)(lba * boot_sect->bytes_per_sect)); -} - -void *FAT_read_cluster(uint16_t cluster, void *buffer) { - // TODO: perform memcpy - void *addr = FAT_read_sector_offset(data_lba + ((cluster - 2) * boot_sect->sect_per_cluster), NULL); - - uint32_t cluster_size = boot_sect->bytes_per_sect * boot_sect->sect_per_cluster; - - memcpy(buffer, addr, cluster_size); - - 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)); - - while (1) { - // index overflow - if (index >= boot_sect->max_root_dir_entries) { - return -1; - } - - uint32_t offset = index * sizeof(DIR_ENTRY); - void *sect = FAT_read_sector_offset(root_lba, &offset); - DIR_ENTRY *dir_entry = (DIR_ENTRY *)((uint32_t)(sect) + offset); - - // if first character of name is 0, then no subsequent entry is in use - if (dir_entry->name[0] == 0x00) { - return -1; - } - - // deleted file - if (dir_entry->name[0] == (char)(0xE5)) { - index++; - continue; - } - - // VFAT LFN entry - if (dir_entry->file_attr == 0x0F && dir_entry->start_of_clusters == 0 && dir_entry->file_size != 0) { - VFAT_LFN_ENTRY *lfn_entry = (VFAT_LFN_ENTRY*)(dir_entry); - - int offset = 13 * ((lfn_entry->seq_num & 0x3F) - 1); - - // read long file name - for (int i = 0; i < 5; i++) { - fname_buffer[offset++] = lfn_entry->part_1[i]; - } - - for (int i = 0; i < 6; i++) { - fname_buffer[offset++] = lfn_entry->part_2[i]; - } - - for (int i = 0; i < 2; i++) { - fname_buffer[offset++] = lfn_entry->part_3[i]; - } - - index++; - continue; - } - - if (index == 0 && (dir_entry->file_attr & 0x08) && dir_entry->file_size == 0) { - // volume label - - } else if ((dir_entry->file_attr & 0x10) && dir_entry->file_size == 0) { - // subdirectory - - } else { - // regular file - - } - - *file_size = dir_entry->file_size; - *first_cluster = dir_entry->start_of_clusters; - - // if no VFAT LFN exists, use DOS name - if (fname_buffer[0] == 0) { - for (int i = 0; i < 8; i++) { - fname_buffer[i] = dir_entry->name[i]; - } - fname_buffer[8] = '.'; - for (int i = 0; i < 3; i++) { - fname_buffer[i + 9] = dir_entry->ext[i]; - } - fname_buffer[12] = 0; - } - - return index + 1; - } -} - -uint16_t FAT_next_cluster(uint16_t cluster) { - // assuming FAT12 - uint32_t offset = (cluster >> 1) * 3; - uint8_t *sect = FAT_read_sector_offset(FAT1_lba, &offset); - sect += offset; - - if (cluster & 0x01) { - uint16_t high = (uint16_t)(sect[2]); - uint16_t low = (uint16_t)(sect[1] & 0xF0) >> 4; - return (high << 4) | low; - } else { - uint16_t low = (uint16_t)(sect[0]); - uint16_t high = (uint16_t)(sect[1] & 0x0F) << 8; - return low | high; - } -} -
@@ -1,13 +0,0 @@
-#ifndef FAT_H -#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); -void *FAT_find_file(const char *fname); - -#endif
@@ -1,66 +0,0 @@
-#include <stdint.h> - -#include "string.h" -#include "fat.h" - -void printc(char c) { - static uint8_t *display = (uint8_t*)(0xB8000); - *(display++) = c; - *(display++) = 0x0F; -} - -void print_string(char *str) { - while (*str != 0) { - printc(*(str++)); - } -} - -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; - - // first cluster of kernel.bin file - uint16_t first_cluster; - - while (1) { - char buffer[832]; - uint32_t file_size; - - i = FAT_root_dir_next(i, buffer, &first_cluster, &file_size); - - print_string(buffer); - print_string(" "); - if (i <= 0) { return -1; } - - if (!(strcmp(buffer, "kernel.bin"))) { break; } - } - - // copy all clusters - uint16_t cluster = first_cluster; - uint8_t *buffer = (uint8_t *)(0x100000); - while (1) { - buffer = FAT_read_cluster(cluster, buffer); - cluster = FAT_next_cluster(cluster); - - if (cluster == 0xFFF || cluster == 0x000) { break; } - } - - return 0; -}
@@ -1,30 +0,0 @@
-.RECIPEPREFIX = > - -LOCAL_BUILD := $(GLOBAL_BUILD)/boot - -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) - -DIRS := $(sort $(dir $(OBJECTS))) - -$(OBJECTS): | $(DIRS) -$(DIRS): -> $(MKDIR) $(DIRS) - -.PHONY: build -build: $(GLOBAL_BUILD)/boot.bin -$(GLOBAL_BUILD)/boot.bin: $(OBJECTS) -> $(LD) $^ -T link.txt -Map=$(LOG_DIR)/boot_mapfile.txt -o $@ -> $(LD) $^ -T link.txt -Map=$(LOG_DIR)/boot_mapfile.txt --oformat elf32-i386 -o boot.o - -$(LOCAL_BUILD)/%.s.o: %.s -> $(AS) -o $@ $< - -$(LOCAL_BUILD)/%.c.o: %.c $(wildcard *.h) -> $(CC) -c $(CCFLAGS) -o $@ $<
@@ -1,7 +1,6 @@
#include "paging.h" #include "linker.h" #include "string.h" -#include "fat.h" void *create_kernel_environment() {
@@ -1,37 +0,0 @@
-#include "string.h" - -#include <stdint.h> - -void *memset(void *ptr, uint8_t value, uint32_t num) { - for (uint32_t i = 0; i < num; i++) { - ((uint8_t*)ptr)[i] = value; - } - return ptr; -} - -int strcmp(const char *str1, const char *str2) { - int i = 0; - - while (1) { - if (str1[i] != str2[i]) { - return str1[i] - str2[i]; - } - - if (str1[i] == 0) { - return 0; - } - - i++; - } -} - -void *memcpy(void *_dest, const void *_src, uint32_t n) { - uint8_t *src = (uint8_t*)(_src); - uint8_t *dest = (uint8_t*)(_dest); - - for (uint32_t i = 0; i < n; i++) { - dest[i] = src[i]; - } - - return _dest; -}
@@ -1,5 +1,5 @@
-#include "cedos/core.h" -#include "cedos/drivers/console.h" +#include "core.h" +#include "drivers/console.h" #include "assembly.h" CON_DRIVER *core_con;@@ -228,4 +228,8 @@
int core_init(void) { core_con = std_con; return core_con->init(); -}+} + +void assert_failed(const char * message) { + kpanic(message); +}
@@ -1,5 +1,5 @@
-#include "cedos/drivers/speaker.h" -#include "cedos/pit.h" +#include "drivers/speaker.h" +#include "pit.h" #include "assembly.h" #include <stdint.h>
@@ -1,3 +0,0 @@
-#include "cedos/drivers/console.h" - -CON_DRIVER *std_con = &vga_con;
@@ -1,5 +1,5 @@
-#include "cedos/drivers/graphics.h" -#include "cedos/mm/paging.h" +#include "drivers/graphics.h" +#include "mm/paging.h" #include "string.h" #include "linker.h"
@@ -1,3 +0,0 @@
-#include "cedos/drivers/keyboard.h" - -KB_DRIVER *std_kb = &ps2_kb;
@@ -1,9 +1,9 @@
-#include "cedos/drivers/keyboard.h" -#include "cedos/interrupts.h" -#include "cedos/pic.h" -#include "cedos/core.h" -#include "cedos/sched/sched.h" -#include "cedos/mm/memory.h" +#include "drivers/keyboard.h" +#include "interrupts.h" +#include "pic.h" +#include "core.h" +#include "sched/sched.h" +#include "memory.h" #include "assembly.h" #define PS2_DATA 0x60@@ -39,13 +39,13 @@ /*!
* Reads a single character from the PS/2 keyboard * \return A single char corresponding to a key press. */ -uint8_t ps2_kb_read(void); +int ps2_kb_readc(void); //! PS/2 keyboard driver (default driver) KB_DRIVER ps2_kb = { "PS/2 keyboard driver", ps2_kb_init, - ps2_kb_read + ps2_kb_readc }; uint8_t *buffer;@@ -83,7 +83,7 @@ int ps2_kb_init(void) {
buffer_head = 0; buffer_tail = 0; - buffer = os_kernel_malloc(BUFFER_LENGTH); + buffer = malloc(BUFFER_LENGTH); // clear incoming data inb(PS2_DATA);@@ -108,11 +108,21 @@
return 1; } -uint8_t ps2_kb_read(void) { - while (buffer_empty()) { - //PRINT_DBG("yield.\n"); - sched_yield(); +int ps2_kb_readc(void) { + if (buffer_empty()) { + return -1; + } else { + return (int)(buffer_dequeue()); } +} - return buffer_dequeue(); +int ps2_kb_read(int fd, char *buffer, uint32_t size) { + int res = 0; + for (int i = 0; i < size; i++) { + if (buffer_empty()) { break; } + + buffer[i] = buffer_dequeue(); + res++; + } + return res; }
@@ -1,45 +0,0 @@
-#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; -}
@@ -1,162 +0,0 @@
-#include "cedos/drivers/console.h" -#include "linker.h" -#include "assembly.h" -#include "string.h" - -#define VGA_TEXTMODE_COLUMNS 80 -#define VGA_TEXTMODE_LINES 25 -#define VGA_TEXTMODE_BPC 2 -#define VGA_TEXTMODE_LINE_WIDTH (VGA_TEXTMODE_COLUMNS * VGA_TEXTMODE_BPC) -#define VGA_TEXTMODE_CELLS (VGA_TEXTMODE_COLUMNS * VGA_TEXTMODE_LINES) -#define VGA_MEM_POS(line, column) ((line) * VGA_TEXTMODE_COLUMNS * VGA_TEXTMODE_BPC + (column) * VGA_TEXTMODE_BPC) - -#define VGA_TEXTMODE_MEM ((uint8_t*)0xB8000) -#define VGA_MEM_VALUE(line, column) (VGA_TEXTMODE_MEM[VGA_MEM_POS((line), (column))]) -#define VGA_MEM_COLOR(line, column) (VGA_TEXTMODE_MEM[VGA_MEM_POS((line), (column)) + 1]) -#define VGA_MEM_ADDR(line, column) (&(VGA_MEM_VALUE((line), (column)))) - -#define VGA_INDEX_REG ((uint16_t)0x3D4) -#define VGA_DATA_REG ((uint16_t)0x3D5) - -uint32_t line = 0; -uint32_t column = 0; -uint8_t color = 0x0F; - -int vga_con_init(void); -void vga_con_write_c(const char c); -void vga_con_write_n(const char *string, uint32_t num); -void vga_con_write_s(const char *string); -void vga_con_clear(void); -void vga_con_newline(void); -void vga_con_backspace(void); - -CON_DRIVER vga_con = { - "VGA console", - vga_con_init, - vga_con_write_c, - vga_con_write_n, - vga_con_write_s, - vga_con_clear, - vga_con_newline, - vga_con_backspace -}; - -__attribute((always_inline)) inline void set_char(char value) { - VGA_MEM_VALUE(line, column) = value; - VGA_MEM_COLOR(line, column) = color; -} - -__attribute((always_inline)) inline void lfcr() { - line++; - column = 0; - - if (line >= VGA_TEXTMODE_LINES) { - memcpy( - VGA_MEM_ADDR(0, 0), - VGA_MEM_ADDR(1, 0), - VGA_TEXTMODE_LINE_WIDTH * (VGA_TEXTMODE_LINES - 1) - ); - memset( - VGA_MEM_ADDR(VGA_TEXTMODE_LINES - 1, 0), - 0, - VGA_TEXTMODE_LINE_WIDTH - ); - line = VGA_TEXTMODE_LINES - 1; - } -} - -__attribute((always_inline)) inline void write_char(char value) { - if (column >= VGA_TEXTMODE_COLUMNS || value == '\n') { - lfcr(); - } - - switch (value) { - case '\n': - break; - case '\0': - break; - default: - set_char(value); - column++; - break; - } -} - -__attribute((always_inline)) inline void set_cursor(uint16_t line, uint16_t column) { - uint16_t pos = line * VGA_TEXTMODE_COLUMNS + column; - outb(0x0F, VGA_INDEX_REG); - outb((uint8_t)(pos & 0xFF), VGA_DATA_REG); - outb(0x0E, VGA_INDEX_REG); - outb((uint8_t)(pos >> 8), VGA_DATA_REG); -} - -void enable_cursor(void) { - outb(0x0A, VGA_INDEX_REG); - outb((inb(VGA_DATA_REG) & 0x0C) | 0x00, VGA_DATA_REG); - outb(0x0B, VGA_INDEX_REG); - outb((inb(VGA_DATA_REG) & 0xE0) | 0x0F, VGA_DATA_REG); -} - -int vga_con_init(void) { - vga_con_clear(); - - enable_cursor(); - set_cursor(line, column); - - for (uint32_t i = 0; i < 320 * 200; i++) { - uint8_t* disp = (uint8_t*)0xA0000; - disp[i] = (uint8_t)i; - } - - return 1; -} - -void vga_con_write_c(const char c) { - if (c == 0x08) { - vga_con_backspace(); - set_cursor(line, column); - } else { - write_char(c); - set_cursor(line, column); - } -} - -void vga_con_write_n(const char *string, uint32_t num) { - for (uint32_t i = 0; i < num; i++) { - write_char(string[0]); - } - set_cursor(line, column); -} - -void vga_con_write_s(const char *string) { - while (*string) { - write_char(*(string++)); - } - set_cursor(line, column); -} - -void vga_con_clear(void) { - for (int i = 0; i < VGA_TEXTMODE_CELLS; i++) { - VGA_TEXTMODE_MEM[2 * i] = 0; - VGA_TEXTMODE_MEM[2 * i + 1] = 0; - } - - line = 0; - column = 0; -} - -void vga_con_newline(void) { - lfcr(); -} - -void vga_con_backspace(void) { - if (column == 0 && line > 0) { - line--; - column = VGA_TEXTMODE_COLUMNS - 1; - } else if (column > 0) { - column--; - } - - set_char(0); - set_cursor(line, column); -}
@@ -1,11 +1,11 @@
#include <stdint.h> -#include "cedos/elf.h" -#include "cedos/core.h" +#include "elf.h" +#include "core.h" -#include "cedos/file.h" -#include "cedos/sched/process.h" +#include "file.h" +#include "sched/process.h" -#include "cedos/mm/memory.h" +#include "memory.h" #include "assert.h"@@ -143,6 +143,11 @@ ELF_HEADER header;
file_lseek(fd, 0, SEEK_SET); int header_size = file_read(fd, (void*)(&header), sizeof(ELF_HEADER)); + if (header_size != sizeof(ELF_HEADER)) { + printk("Error while reading executable.\n"); + return -1; + } + // magic number correct assert(*(uint32_t*)(header.e_ident) == 0x464C457F);@@ -152,21 +157,38 @@ assert(header_size == sizeof(ELF_HEADER));
// get section table int sh_offset = header.secthead_offset; + int sh_num = header.sh_num; + + assert(header.sh_entry_size == sizeof(SECT_HEADER)); SECT_HEADER sect_headers[16]; file_lseek(fd, sh_offset, SEEK_SET); - int sect_headers_size = file_read(fd, (void*)(§_headers), sizeof(sect_headers)); + int sect_headers_size = file_read(fd, (void*)(§_headers), sizeof(SECT_HEADER) * sh_num); + + if (sect_headers_size != sizeof(SECT_HEADER) * sh_num) { + printk("Error while reading executable.\n"); + return -1; + } - assert(sect_headers_size != 0); - int num_sections = header.sh_num; int section_size = header.sh_entry_size; SECT_HEADER *sect_names_sh = §_headers[header.sh_strndx]; - char *sect_names = os_kernel_malloc(sect_names_sh->size); + char *sect_names = malloc(sect_names_sh->size); + + if (sect_names == NULL) { + printk("Error while starting executable: Memory allocation failed.\n"); + return -1; + } + file_lseek(fd, sect_names_sh->offset, SEEK_SET); - file_read(fd, sect_names, sect_names_sh->size); + int sect_names_size = file_read(fd, sect_names, sect_names_sh->size); + + if (sect_names_size != sect_names_sh->size) { + printk("Error while reading executable.\n"); + return -1; + } assert(sizeof(SECT_HEADER) == section_size);@@ -186,7 +208,11 @@ PRINT_DBG("(LMA: %p, VMA: %p)\n", lma, vma);
file_lseek(fd, sh->offset, SEEK_SET); int read_size = file_read(fd, vma, sect_size); - assert(sect_size == read_size); + + if (read_size != sect_size) { + printk("Error while reading executable.\n"); + return -1; + } } else if (sh->flags & SHF_ALLOC) { uint32_t lma = sh->offset; uint32_t vma = sh->addr;
@@ -1,6 +1,6 @@
.section .text -.global __KERNEL_START -__KERNEL_START: +.global start +start: # move stack to kernel space mov $__KERNEL_STACK_ADDR, %eax mov %eax, %esp
@@ -1,294 +0,0 @@
-#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]; - char oemname[8]; - - uint16_t bytes_per_sect; - uint8_t sect_per_cluster; - uint16_t num_reserved_sectors; - uint8_t num_FAT; - uint16_t max_root_dir_entries; - uint16_t total_log_sectors; - uint8_t media_desc; - uint16_t log_sect_per_fat; -} __attribute__((packed)) BOOT_SECT; - -typedef struct { - char name[8]; - char ext[3]; - uint8_t file_attr; - uint8_t user_attr; - uint8_t del_char; - uint16_t create_time; - uint16_t create_date; - uint16_t last_access_date; - uint16_t access_rights; - uint16_t last_modified_time; - uint16_t last_modified_date; - uint16_t start_of_clusters; - uint32_t file_size; -} __attribute__((packed)) DIR_ENTRY; - -typedef struct { - uint8_t seq_num; - uint16_t part_1[5]; - uint8_t file_attr; - uint8_t user_attr; - uint8_t del_char; - uint16_t part_2[6]; - uint16_t start_of_clusters; - uint16_t part_3[2]; -} __attribute__((packed)) VFAT_LFN_ENTRY; - - -void *FAT_addr; -BOOT_SECT *boot_sect; - -uint32_t FAT1_lba; -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; - - // open image file - FAT_addr = (void*)(0x10000); - - boot_sect = (BOOT_SECT*)(FAT_addr); - - FAT1_lba = boot_sect->num_reserved_sectors; - FAT2_lba = FAT1_lba + boot_sect->log_sect_per_fat; - root_lba = FAT1_lba + (boot_sect->log_sect_per_fat * boot_sect->num_FAT); - - long root_dir_size = boot_sect->max_root_dir_entries * sizeof(DIR_ENTRY); - data_lba = root_lba + (root_dir_size / boot_sect->bytes_per_sect); -} - -void *FAT_read_sector_offset(uint32_t lba, uint32_t *offset) { - if (offset != NULL) { - lba += (*offset) / boot_sect->bytes_per_sect; - *offset = (*offset) % boot_sect->bytes_per_sect; - } - - return (void*)((long)(FAT_addr) + (long)(lba * boot_sect->bytes_per_sect)); -} - -void *FAT_read_cluster(uint16_t cluster, void *buffer) { - // TODO: perform memcpy - void *addr = FAT_read_sector_offset(data_lba + ((cluster - 2) * boot_sect->sect_per_cluster), NULL); - - uint32_t cluster_size = boot_sect->bytes_per_sect * boot_sect->sect_per_cluster; - - memcpy(buffer, addr, cluster_size); - - 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)); - - while (1) { - // index overflow - if (index >= boot_sect->max_root_dir_entries) { - return -1; - } - - uint32_t offset = index * sizeof(DIR_ENTRY); - void *sect = FAT_read_sector_offset(root_lba, &offset); - DIR_ENTRY *dir_entry = (DIR_ENTRY *)((uint32_t)(sect) + offset); - - // if first character of name is 0, then no subsequent entry is in use - if (dir_entry->name[0] == 0x00) { - return -1; - } - - // deleted file - if (dir_entry->name[0] == (char)(0xE5)) { - index++; - continue; - } - - // VFAT LFN entry - if (dir_entry->file_attr == 0x0F && dir_entry->start_of_clusters == 0 && dir_entry->file_size != 0) { - VFAT_LFN_ENTRY *lfn_entry = (VFAT_LFN_ENTRY*)(dir_entry); - - int offset = 13 * ((lfn_entry->seq_num & 0x3F) - 1); - - // read long file name - for (int i = 0; i < 5; i++) { - fname_buffer[offset++] = lfn_entry->part_1[i]; - } - - for (int i = 0; i < 6; i++) { - fname_buffer[offset++] = lfn_entry->part_2[i]; - } - - for (int i = 0; i < 2; i++) { - fname_buffer[offset++] = lfn_entry->part_3[i]; - } - - index++; - continue; - } - - if (index == 0 && (dir_entry->file_attr & 0x08) && dir_entry->file_size == 0) { - // volume label - index++; - continue; - - } else if ((dir_entry->file_attr & 0x10) && dir_entry->file_size == 0) { - // subdirectory - - } else { - // regular file - - } - - *file_size = dir_entry->file_size; - *first_cluster = dir_entry->start_of_clusters; - - // if no VFAT LFN exists, use DOS name - if (fname_buffer[0] == 0) { - for (int i = 0; i < 8; i++) { - fname_buffer[i] = dir_entry->name[i]; - } - fname_buffer[8] = '.'; - for (int i = 0; i < 3; i++) { - fname_buffer[i + 9] = dir_entry->ext[i]; - } - fname_buffer[12] = 0; - } - - 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 - uint32_t *offset = (cluster >> 1) * 3; - uint8_t *sect = FAT_read_sector_offset(FAT1_lba, &offset); - sect += (uint32_t)(offset); - - if (cluster & 0x01) { - uint16_t high = (uint16_t)(sect[2]); - uint16_t low = (uint16_t)(sect[1] & 0xF0) >> 4; - return (high << 4) | low; - } else { - uint16_t low = (uint16_t)(sect[0]); - uint16_t high = (uint16_t)(sect[1] & 0x0F) << 8; - return low | high; - } -} - -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) - uint16_t first_cluster; - while (1) { - char buffer[832]; - uint32_t file_size; - - i = FAT_root_dir_next(i, buffer, &first_cluster, &file_size); - if (i <= 0) { return -1; } - - if (strcmp(buffer, fname) == 0) { - // file found - handle->pos = 0; - handle->size = file_size; - handle->fops = &FAT_fops; - handle->fat_cluster = first_cluster; - return 0; - } - } -} - -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; - - 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); - 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; -}
@@ -1,14 +1,14 @@
-#include "cedos/file.h" -#include "cedos/fat.h" -#include "cedos/pipe.h" +#include "file.h" +#include "fat.h" +#include "pipe.h" -#include "cedos/drivers/tty.h" -#include "cedos/core.h" +#include "drivers/tty.h" +#include "core.h" -#include "cedos/mm/memory.h" +#include "memory.h" -#include "cedos/sched/sched.h" -#include "cedos/sched/process.h" +#include "sched/sched.h" +#include "sched/process.h" #ifdef DEBUG #define PRINT_DBG(...) printk("[" __FILE__ "] " __VA_ARGS__)@@ -24,7 +24,7 @@
int stdin, stdout, fat_root, pipe; int file_init() { - file_table = os_kernel_malloc(sizeof(file_t) * 512); + file_table = malloc(sizeof(file_t) * 512); file_table[next_free].fops = &tty_fops; file_table[next_free].stdio_id = 0;@@ -79,6 +79,8 @@
file_t *root = get_process_local_file(fd); file_t *handle = &file_table[new_fd]; + if (fd < 0) { return -1; } + if (root->fops->openat == NULL) { return -1; } if (root->fops->openat(root, handle, fname, flags)) { return -1; }@@ -87,6 +89,8 @@ return new_fd;
} int file_read(int fd, char *buffer, uint32_t size) { + if (fd < 0) { return 0; } + file_t *file = get_process_local_file(fd); if (file->fops->read == NULL) { return -1; }@@ -95,6 +99,8 @@ return file->fops->read(file, buffer, size);
} int file_write(int fd, char *buffer, uint32_t size) { + if (fd < 0) { return 0; } + file_t *file = get_process_local_file(fd); if (file->fops->write == NULL) { return -1; }@@ -103,6 +109,8 @@ file->fops->write(file, buffer, size);
} int file_dir_next(int fd, int index, char *fname_buffer) { + if (fd < 0) { return -1; } + file_t *file = get_process_local_file(fd); if (file->fops->dir_next == NULL) { return -1; }@@ -111,6 +119,8 @@ file->fops->dir_next(file, index, fname_buffer);
} off_t file_lseek(int fd, off_t offset, int whence) { + if (fd < 0) { return -1; } + file_t *file = get_process_local_file(fd); if (file->fops->lseek == NULL) { return -1; }@@ -119,6 +129,8 @@ return file->fops->lseek(file, offset, whence);
} off_t file_tell(int fd) { + if (fd < 0) { return -1; } + file_t *file = get_process_local_file(fd); if (file->fops->tell == NULL) { return -1; }
@@ -1,11 +1,11 @@
-#include "cedos/drivers/console.h" +#include "drivers/console.h" -#include "cedos/sched/sched.h" +#include "sched/sched.h" -#include "cedos/interrupts.h" -#include "cedos/pic.h" -#include "cedos/core.h" -#include "cedos/pit.h" +#include "interrupts.h" +#include "pic.h" +#include "core.h" +#include "pit.h" #define array_sizeof(array) (sizeof(array)/sizeof(array[0])) #define NULL ((void*)0)
@@ -13,6 +13,7 @@ SECTIONS
{ KERNEL : AT(0x0000) { + */entry.s.o(.text) */*(.text) */*(.data) */*(.rodata*)
@@ -1,24 +1,24 @@
-#include "cedos/drivers/console.h" -#include "cedos/drivers/keyboard.h" -#include "cedos/drivers/graphics.h" +#include "drivers/console.h" +#include "drivers/keyboard.h" +#include "drivers/graphics.h" -#include "cedos/sched/sched.h" -#include "cedos/sched/process.h" +#include "sched/sched.h" +#include "sched/process.h" -#include "cedos/mm/paging.h" -#include "cedos/mm/memory.h" +#include "mm/paging.h" +#include "memory.h" -#include "cedos/interrupts.h" -#include "cedos/syscall.h" -#include "cedos/pic.h" -#include "cedos/pit.h" -#include "cedos/core.h" +#include "interrupts.h" +#include "syscall.h" +#include "pic.h" +#include "pit.h" +#include "core.h" -#include "cedos/elf.h" +#include "elf.h" -#include "cedos/file.h" -#include "cedos/fat.h" +#include "file.h" +#include "fat.h" #include "linker.h" #include "assert.h"@@ -56,7 +56,7 @@ sti();
printk("done.\n"); printk("Initiallizing malloc..."); - malloc_init(); + malloc_init(0xC0400000u, 0xC0800000u); printk("done.\n"); printk("Installing syscalls...");
@@ -1,33 +0,0 @@
-.RECIPEPREFIX = > - -LOCAL_BUILD := $(GLOBAL_BUILD)/kernel - -SRC_DIR := $(shell pwd) - -C_SOURCES := $(wildcard *.c) $(wildcard **/*.c) -S_SOURCES := $(wildcard *.s) $(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) - -DIRS := $(sort $(dir $(OBJECTS))) - -$(OBJECTS): | $(DIRS) -$(DIRS): -> $(MKDIR) $(DIRS) - -.PHONY: build -build: folder -$(GLOBAL_BUILD)/kernel.bin: $(OBJECTS) | folder -> $(LD) $^ -o $@ -T link.txt -Map=$(LOG_DIR)/kernel_mapfile.txt - -.PHONY: folder -folder: -> $(MKDIR) $(LOCAL_BUILD) - -$(LOCAL_BUILD)/%.s.o: %.s -> $(AS) -o $@ $< - -$(LOCAL_BUILD)/%.c.o: %.c $(wildcard *.h) -> $(CC) -c -I$(INCLUDE_DIR) $(CCFLAGS) -o $@ $<
@@ -1,83 +0,0 @@
-#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) { - // 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; -} - -/*! - * Frees a previously allocated block of memory. (KERNEL MODE) - * \param ptr Pointer to the memory block to be freed. - */ -void os_kernel_free(void* ptr) { - -} - -/*! - * Allocates a block of \p size bytes of memory. (USER MODE) - * \param size Size in bytes of the requested block of memory. - * \return Memory address to the new memory block - */ -void* os_user_malloc(size_t size) { - return (void*)0; -} - -/*! - * Frees a previously allocated block of memory. (USER MODE) - * \param ptr Pointer to the memory block to be freed. - */ -void os_user_free(void* ptr) { - -}
@@ -1,14 +0,0 @@
-#include "cedos/mm/page_allocator.h" -#include "cedos/mm/paging.h" - -uint8_t* first_free = (uint8_t*)0x00200000; - -void* get_free_page() { - void* res = first_free; - first_free += PAGE_SIZE; - return res; -} - -void mark_as_free(void* page_addr) { - -}
@@ -1,9 +1,9 @@
-#include "cedos/mm/paging.h" -#include "cedos/mm/page_allocator.h" +#include "mm/paging.h" +#include "mm/page_allocator.h" #include "linker.h" #include "string.h" -#include "cedos/interrupts.h" -#include "cedos/core.h" +#include "interrupts.h" +#include "core.h" #define MAKE_PAGE_ENTRY(addr, flags) (uint32_t)(((uint32_t)(addr) & 0xFFFFF000) | (flags))
@@ -1,4 +1,4 @@
-#include "cedos/pic.h" +#include "pic.h" #include "assembly.h" /*!
@@ -1,50 +0,0 @@
-#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]); - } -}
@@ -1,6 +1,6 @@
-#include "cedos/pit.h" +#include "pit.h" #include "assembly.h" -#include "cedos/pic.h" +#include "pic.h" #define PIT_ACCESS_MODE_LO_HI (0b11 << 4) #define PIT_COMMAND_PORT ((uint16_t)0x43)
@@ -1,4 +1,4 @@
-#include "cedos/sched/process.h" +#include "sched/process.h" #define NULL ((void*)0)
@@ -1,19 +1,20 @@
-#include "cedos/sched/sched.h" -#include "cedos/sched/process.h" -#include "cedos/sched/sched_strats.h" +#include "sched/sched.h" +#include "sched/process.h" +#include "sched/sched_strats.h" -#include "cedos/mm/paging.h" -#include "cedos/mm/memory.h" +#include "mm/paging.h" +#include "memory.h" -#include "cedos/drivers/console.h" -#include "cedos/drivers/speaker.h" +#include "drivers/console.h" +#include "drivers/speaker.h" -#include "cedos/core.h" -#include "cedos/interrupts.h" -#include "cedos/pit.h" -#include "cedos/pic.h" -#include "cedos/elf.h" -#include "cedos/file.h" +#include "core.h" +#include "interrupts.h" +#include "pit.h" +#include "pic.h" +#include "elf.h" +#include "file.h" +#include "alarm.h" #include "assembly.h" #include "assert.h"@@ -30,7 +31,7 @@ #define PRINT_DBG(...) {}
#endif PROCESS* get_slot(void) { - PROCESS *new_process = (PROCESS*)os_kernel_malloc(sizeof(PROCESS)); + PROCESS *new_process = (PROCESS*)malloc(sizeof(PROCESS)); return new_process; }@@ -90,7 +91,12 @@ }
// TODO: implement with malloc strcpy(p->name_buf, name); - strcpy(p->args_buf, args); + + if (args == 0) { + p->args_buf[0] = 0; + } else { + strcpy(p->args_buf, args); + } p->name = (const char*)&(p->name_buf); p->args = (const char*)&(p->args_buf);@@ -118,6 +124,7 @@ /* TODO: check if code exists at entry point */
// start the process p->state = PSTATE_READY; + p->starvation = 0; crit_exit();@@ -126,8 +133,9 @@ }
void sched_interrupt_c(SCHED_FRAME * volatile frame, uint32_t volatile ebp) { - //kpanic("SCHEDULER STACK INFO"); PROCESS* current = get_process(current_pid); + + alarm_tick(); if (current_pid != 0) { current->esp = (VIRT_ADDR)(frame);@@ -135,8 +143,6 @@ current->ebp = (VIRT_ADDR)(ebp);
current->eip = (VIRT_ADDR)frame->eip; current->eflags = frame->eflags; - - // save stack checksum stack_compute_checksum(&(current->checksum), current->esp, current->ebp); }@@ -150,13 +156,6 @@ // select next process
PRINT_DBG("exiting %i, ", current_pid); current_pid = next_schedule(current_pid); PRINT_DBG("entering %i\n", current_pid); - - // unblock all blocked processes - for (PROCESS *p = get_first_process(); p != NULL; p = p->next) { - if (p->state == PSTATE_BLOCKED) { - p->state = PSTATE_READY; - } - } // prepare to return to process PROCESS* next = get_process(current_pid);@@ -208,19 +207,14 @@ current_pid = 0;
// create idle process PROCESS_ID idle = sched_spawn(NULL, NULL, 0); - assert(idle != -1); + assert(idle == 0); return 1; } void sched_yield(void) { crit_enter(); - //PRINT_DBG("yield.\n"); PROCESS *current = get_process(current_pid); - if (current != NULL && current->state != PSTATE_TERMINATED) { - current->state = PSTATE_READY; - //current->state = PSTATE_RUNNING; - } uint32_t csc = crit_stash(); sti();@@ -228,6 +222,29 @@ INT(0x20);
crit_restore(csc); crit_exit(); +} + +void sched_sleep(int ticks) { + // block the process. unblocking is done by the alarm. + PROCESS *process = get_process(current_pid); + process->state = PSTATE_BLOCKED; + + // create a wakeup-alarm to unblock the process. + alarm_add(ticks, current_pid, ALARM_WAKEUP); + + sched_yield(); + + // if this happens, it means the scheduler chose + // a blocked process as next process, which should + // never happen. + if (process->state == PSTATE_BLOCKED) { + kpanic("ERROR!"); + } +} + +void sched_unblock(int pid) { + PROCESS *process = get_process(pid); + process->state = PSTATE_READY; } int sched_kill(PROCESS_ID pid) {
@@ -16,6 +16,7 @@ // pass process stack as arguments
push %ebx push %eax xor %eax, %eax + call time_tick call sched_interrupt_c pop %eax pop %ebx
@@ -1,14 +0,0 @@
-#include "cedos/sched/process.h" - -#define NULL ((void*)0) - -PROCESS_ID next_schedule(PROCESS_ID current) { - PROCESS* process = get_process(current); - - if (process != NULL && process->next != NULL && process->next->state != PSTATE_TERMINATED) { - return process->next->id; - } else { - PROCESS *first = get_first_process(); - return first->id; - } -}
@@ -1,4 +1,4 @@
-#include "cedos/sched/stack_check.h" +#include "sched/stack_check.h" void stack_compute_checksum(STACK_CHECKSUM* checksum, const void *esp, const void *ebp) { *checksum = 0;
@@ -51,4 +51,20 @@ }
i++; } +} + +const char * strchr ( const char * str, int character ) { + int i = 0; + + while (1) { + if (str[i] == 0) { + return NULL; + } + + if (str[i] == character) { + return &(str[i]); + } + + i++; + } }
@@ -1,8 +1,10 @@
-#include "cedos/interrupts.h" -#include "cedos/core.h" -#include "cedos/sched/sched.h" -#include "cedos/file.h" -#include "cedos/drivers/graphics.h" +#include "interrupts.h" +#include "core.h" +#include "sched/sched.h" +#include "file.h" +#include "drivers/graphics.h" +#include "time.h" +#include "mm/page_allocator.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);@@ -20,7 +22,11 @@ graphics_set_mode,
hard_reset, file_dir_next, file_lseek, - file_tell + file_tell, + time_get_ticks, + mem_usage, + sched_kill, + sched_sleep }; extern void syscall_interrupt(void);
@@ -82,4 +82,26 @@ void *pointer = (void*)(0);
volatile uint32_t res = 0; interrupt(0x30, res, 9, fd, index, fname_buffer); return res; -}+} + +int sc_time_get_ticks(void) { + volatile int res = 0; + interrupt(0x30, res, 12, 0, 0, 0); + return res; +} + +uint32_t sc_mem_usage(void) { + volatile int res = 0; + interrupt(0x30, res, 13, 0, 0, 0); + return res; +} + +void process_kill(int pid) { + volatile uint32_t res = 0; + interrupt(0x30, res, 14, pid, 0, 0); +} + +void sleep(int ticks) { + volatile uint32_t res = 0; + interrupt(0x30, res, 15, ticks, 0, 0); +}
@@ -7,10 +7,12 @@ #include <stdint.h>
int sysprint(const char *fmt, int arg1, int arg2); int yield(); +void sleep(int ticks); 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 process_kill(int pid); void graphics_set_mode(int mode);@@ -23,6 +25,9 @@
void hard_reset(); int dir_next(int fd, int index, char *fname_buffer); + +int sc_time_get_ticks(void); +uint32_t sc_mem_usage(void); #endif
@@ -20,8 +20,14 @@
int fputc ( int character, FILE * stream ); int fputs ( const char * str, FILE * stream ); +int putc ( int character ); +int puts ( const char * str ); + int fgetc ( FILE * stream ); char * fgets ( char * str, int num, FILE * stream ); + +int getc ( void ); +char * gets ( char * str, int num ); int getchar ( void ); int putchar ( int character );
@@ -1,31 +0,0 @@
-.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 $@ $<
@@ -2,8 +2,12 @@ #include "assembly.h"
#include <stdint.h> +#include "memory.h" + extern void main(char *args); int _start(char *args) { + malloc_init(0x20000000, 0x30000000); + main(args); }
@@ -31,16 +31,24 @@ return EOF;
} } +int putc ( int character ) { + return fputc(character, stdout); +} + int fgetc ( FILE * stream ) { int retval; char c = 0; retval = fread(&c, 1, 1, stream); + while (retval == 0) { + yield(); + retval = fread(&c, 1, 1, stream); + } - if (retval == 1) { - return (int)(c); - } else { - return EOF; - } + return (int)(c); +} + +int getc ( void ) { + return fgetc(stdin); } int fputs ( const char * str, FILE * stream ) {@@ -53,6 +61,10 @@
return i; } +int puts ( const char * str ) { + return fputs(str, stdout); +} + char * fgets ( char * str, int num, FILE * stream ) { int i = 0;@@ -63,6 +75,10 @@ i++;
} return i + 1; +} + +char * gets ( char * str, int num ) { + return fgets(str, num, stdin); } int getchar ( void ) {@@ -105,10 +121,12 @@ }
int sprint_uint32(uint32_t value, char *buffer) { uint8_t* mem = (uint8_t*)(&value); + int res = 0; for (int i = 0; i < 4; i++) { - sprint_hex_char(mem[3-i], buffer); + res += sprint_hex_char(mem[3-i], buffer); buffer += 2; } + return res; } int rek_sprint_uint(unsigned int value, char *buffer) {
@@ -8,7 +8,7 @@
void main(char *args) { FILE* file = fopen(args, "r"); - if (file == NULL) { + if (file == -1) { printf("Could not find file: %s\n", args); return; }
@@ -1,36 +0,0 @@
-.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 $@ $<
@@ -1,74 +0,0 @@
-#include "cedos.h" -#include "stdio.h" - -#include <stdint.h> - -int read_line(char *buffer) { - int i = 0; - char c; - buffer[0] = 0; - while (1) { - c = getchar(); - - if (c == '\n') { break; } - if (c == 0) { continue; } - if (c == 0x08 && i <= 0) { continue; } - - if (c == 0x08) { - buffer[--i] = 0; - putchar(c); - } else { - buffer[i++] = c; - putchar(c); - } - } - - buffer[i] = 0; - putchar(c); - - return i; -} - -void main(char *args) { - uint32_t a = 0, b = 1, i = 0; - printf("\n"); - printf("ShELF shell interface for CeDOS\n"); - printf("Version: " VERSION "\n"); - - while (1) { - printf("/> "); - - char buffer[256]; - 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(file, args); - - //printf("Child process %i spawned, waiting for termination...\n", pid); - - if (pid == -1) { - printf("File not found: %s\n", buffer); - } else { - process_wait(pid); - } - - //printf("Child process %i terminated.\n", pid); - } -}