diff --git a/Makefile b/Makefile index ba05820..f83231b 100644 --- a/Makefile +++ b/Makefile @@ -41,13 +41,11 @@ INTERNAL_OBJS := $(CRTI_OBJ) $(OBJS) $(CRTN_OBJ) build: all iso run # === Build all targets and clean === -buildc: test all iso run clean +buildc: all iso run clean # === Default target === all: $(TARGET) -test: - printf $(CRTI_OBJ) # === Linking === $(TARGET): ./arch/x86/boot/boot.o $(filter-out boot.o, $(OBJ_LINK_LIST)) diff --git a/README.md b/README.md new file mode 100644 index 0000000..9a25b69 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +<--- Espresso. ---> + +Espresso is a simple operating system built with C and i686(IA32) assembler. + +== BUILDING == + +First, you need a cross-compiler and toolchain built, see https://wiki.osdev.org/GCC_Cross-Compiler for instructions. + +then, `cd` into the directory with the code (you should see the `kernel`, `include`, and `lib` directories if you're in the right place.) and type `make build`. +this will also run the OS. type `make clean` after every change to rebuild everything. diff --git a/arch/x86/boot/boot.s b/arch/x86/boot/boot.s index 9dd6705..5ae98bf 100644 --- a/arch/x86/boot/boot.s +++ b/arch/x86/boot/boot.s @@ -45,29 +45,8 @@ doesn't make sense to return from this function as the bootloader is gone. .global _start .global _kernel_early -/*.global loadPageDirectory -.global enablePaging*/ .type _start, @function - -/*load_page_directory: - push %ebp - mov %esp, %ebp - mov 8(%esp), %eax - mov %eax, %cr3 - mov %ebp, %esp - pop %ebp - ret - -enable_paging: - push %ebp - mov %esp, %ebp - mov %cr0, %eax - or $0x80000000, %eax - mov %eax, %cr0 - mov %ebp, %esp - pop %ebp - ret*/ enable_sse_asm: push %eax @@ -138,7 +117,7 @@ enable_sse_asm: .no_sse: .no_cpuid: lea sse_initialized, %edi - mov $0, (%edi) + movl $0, (%edi) .done: pop %edi @@ -203,9 +182,8 @@ _start: /* - Call _kernel_early, early low-level initialization will happen there; - please note that while _kernel_early is written in assembler, - kernel_early is written in C. (kernel_early is called by _kernel_early, don't be confused. ;) ) + Call _kernel_early, early low-level initialization will happen there. + NOTE: I don't use 'jmp' because it doesn't work. Nice try. */ call _kernel_early diff --git a/arch/x86/new_intrin.c b/arch/x86/new_intrin.c new file mode 100644 index 0000000..b0ea4ad --- /dev/null +++ b/arch/x86/new_intrin.c @@ -0,0 +1,16 @@ +#include + +#ifdef __NEW_INTRINSICS_ + +bool cpu_supports_sse2(void) +{ + int k = __buildin_cpu_supports("sse2"); + return k > 0 ? true : false +} + +bool cpu_supports_sse(void) +{ + return __buildin_cpu_supports("sse") > 0 ? true : false; +} + +#endif diff --git a/drivers/fs/sfs.c b/drivers/fs/sfs.c index c58dd12..8d104f1 100644 --- a/drivers/fs/sfs.c +++ b/drivers/fs/sfs.c @@ -5,7 +5,12 @@ #include -#define SFS_BEGINNING_LBA 8 +#define SFS_HEADER_START_LBA 8 +#define SFS_HEADER_REGION_SECTORS 1024 +#define SFS_HEADERS_PER_SECTOR 8 +#define TOTAL_SECTORS 32768 +#define SFS_DATA_START_LBA (TOTAL_SECTORS / 4) + #pragma pack(push, 1) typedef struct sfs_file_header { @@ -24,38 +29,39 @@ typedef struct sfs_file_header { } sfs_file_header_t; #pragma pack(pop) -static sfs_file_header_t* base; + +uint8_t buffer[512] = { 0 }; + +/* Global allocator pointer to the next free sector in the data region */ +uint64_t sfs_next_free_data_sector = SFS_DATA_START_LBA; - -int32_t sfs_init(bool format) +int32_t sfs_init(void) { - uint8_t buffer[512] = { 0 }; + uint8_t sector_buf[512]; - int32_t kl = read_sector(SFS_BEGINNING_LBA, buffer); - - if (kl != 0) + for (uint64_t lba = SFS_HEADER_START_LBA; lba < SFS_HEADER_START_LBA + SFS_HEADER_REGION_SECTORS; ++lba) { - return -1; - } - - volatile sfs_file_header_t null_file; - memcpy(&null_file, buffer, sizeof(sfs_file_header_t)); - - if ((&null_file)->magic != 0xBEEF) - { - if (!format) + if (read_sector(lba, sector_buf) != 0) { - return -2; + return -1; } - - //sfs_format(); - return -2; + + sfs_file_header_t* hdr = (sfs_file_header_t*)sector_buf; + + if (hdr->magic == 0xBEEF) + { + uint64_t end = hdr->data_beginning + hdr->num_sectors; + if (end > sfs_next_free_data_sector) + { + sfs_next_free_data_sector = end; + } + } + + /* TODO: support multiple headers per sector, loop through all 512/64 = 8 headers here */ } - - memcpy(base, &null_file, sizeof(sfs_file_header_t)); - + return 0; } @@ -75,20 +81,210 @@ bool sfs_get_formatted_name(const char* raw_name, char output[37]) return true; } +int32_t sfs_create_file(const char* _name, int32_t size_bytes) +{ + if (size_bytes < 0) + { + return -1; + } -/* + char name[37]; + if (!sfs_get_formatted_name(_name, name)) + { + return -2; + } + + uint32_t sectors_needed = (size_bytes + 511) / 512; + uint8_t sector_buf[512]; + + for (uint64_t lba = SFS_HEADER_START_LBA; lba < SFS_HEADER_START_LBA + SFS_HEADER_REGION_SECTORS; ++lba) + { + if (read_sector(lba, sector_buf) != 0) + { + return -3; + } + + for (int i = 0; i < SFS_HEADERS_PER_SECTOR; ++i) + { + sfs_file_header_t* hdr = ((sfs_file_header_t*)sector_buf) + i; + + if (hdr->magic != 0xBEEF) + { + hdr->magic = 0xBEEF; + memcpy(hdr->filename, name, 37); + hdr->data_beginning = sfs_next_free_data_sector; + hdr->num_sectors = sectors_needed; + + sfs_next_free_data_sector += sectors_needed; + + if (write_sector(lba, sector_buf) != 0) + { + return -4; + } + + return 0; + } + } + } + + return -5; +} + + +/* + num is number of bytes Note: if a negative value is passed for num, then read the whole file */ -int32_t sfs_read_file(char* _name, void* buffer, uint32_t num) +int32_t sfs_read_file(char* _name, void* buffer, int32_t num) { char name[37] = { '\0' }; - if (sfs_get_formatted_name(_name, name)) + if (!sfs_get_formatted_name(_name, name)) { - return -128; + return -1; } - printf("%s", name); + memclr(buffer, sizeof(buffer)); /* Zero out buffer */ + + uint64_t j = SFS_HEADER_START_LBA; + + if (read_sector(j, buffer) != 0) + { + return -2; + } + + sfs_file_header_t file; + + memcpy(&file, buffer, sizeof(file)); + + if (file.magic != 0xBEEF) + { + return -3; + } + + while (strncmp(file.filename, name, 37) != 0) + { + memclr(buffer, sizeof(buffer)); + + if (read_sector(++j, buffer) != 0) + { + return -4; + } + + memcpy(&file, buffer, sizeof(file)); + + if (file.magic != 0xBEEF) + { + return -5; + } + } + + /* File found, now to read data */ + + uint32_t sectors_to_read = file.num_sectors; + if (num >= 0) + { + uint32_t max_sectors = (num + 511) / 512; + + if (max_sectors < sectors_to_read) + { + sectors_to_read = max_sectors; + } + } + + for (uint32_t i = 0; i < sectors_to_read; ++i) + { + if (read_sector((uint64_t)(file.data_beginning) + i, (uint8_t*)buffer + i * 512) != 0) + { + return -6; /* read error */ + } + } + + return sectors_to_read * 512; + + memclr(buffer, sizeof(buffer)); return 0; } + +/* + Writes num bytes to an existing file. + If the file exists, it will be resized (grown/shrunk) to fit num bytes. + Returns number of bytes written (rounded up to sectors), or a negative error code. +*/ +int32_t sfs_write_file(char* _name, const void* buffer, int32_t num) +{ + if (num < 0) + { + return -1; + } + + char name[37] = { '\0' }; + if (!sfs_get_formatted_name(_name, name)) + { + return -2; + } + + uint8_t sector_buf[512]; + uint64_t header_lba = SFS_HEADER_START_LBA; + sfs_file_header_t file; + + while (1) { + if (read_sector(header_lba, sector_buf) != 0) + { + return -3; + } + + memcpy(&file, sector_buf, sizeof(file)); + + if (file.magic != 0xBEEF) + { + return -4; + } + + if (strncmp(file.filename, name, 37) == 0) + { + break; + } + + ++header_lba; + } + + uint32_t sectors_needed = (num + 511) / 512; + + if (sectors_needed != file.num_sectors) + { + file.num_sectors = sectors_needed; + file.data_beginning = sfs_next_free_data_sector; + sfs_next_free_data_sector += sectors_needed; + } + + file.magic = 0xBEEF; + memcpy(sector_buf, &file, sizeof(file)); + + if (write_sector(header_lba, sector_buf) != 0) + { + return -5; + } + + for (uint32_t i = 0; i < sectors_needed; ++i) + { + uint8_t temp[512] = {0}; + + if (i == sectors_needed - 1 && (num % 512 != 0)) + { + memcpy(temp, (const uint8_t*)buffer + i * 512, num % 512); + } + else + { + memcpy(temp, (const uint8_t*)buffer + i * 512, 512); + } + + if (write_sector(file.data_beginning + i, temp) != 0) + { + return -6; + } + } + + return sectors_needed * 512; +} diff --git a/include/fs/sfs.h b/include/fs/sfs.h index 53c1f85..be8a842 100644 --- a/include/fs/sfs.h +++ b/include/fs/sfs.h @@ -3,10 +3,13 @@ #include -int32_t sfs_init(bool format); +int32_t sfs_init(void); bool sfs_get_formatted_name(const char* raw_name, char output[37]); -int32_t sfs_read_file(char* name, void* buffer, uint32_t num); +int32_t sfs_create_file(const char* _name, int32_t size_bytes); + +int32_t sfs_read_file(char* name, void* buffer, int32_t num); +int32_t sfs_write_file(char* _name, const void* buffer, int32_t num); #endif diff --git a/include/kernel/kconfig.h b/include/kernel/kconfig.h index 435af3c..7b4673b 100644 --- a/include/kernel/kconfig.h +++ b/include/kernel/kconfig.h @@ -13,6 +13,13 @@ extern "C" { //#define ENABLE_USB //#define ENABLE_NETWORK +typedef struct { + bool enable_debug; + bool enable_fs; + bool enable_ide; + bool enable_usb; + bool enable_networking; +} kconf_t; static inline kconf_t get_kconfig(void) { diff --git a/include/kincl.h b/include/kincl.h new file mode 100644 index 0000000..6785c75 --- /dev/null +++ b/include/kincl.h @@ -0,0 +1,6 @@ +#ifndef _KERNEL_INCLUDES_H +#define _KERNEL_INCLUDES_H + +#define KERNEL_VERSION "0.0.1e" + +#endif diff --git a/include/panic.h b/include/panic.h deleted file mode 100644 index f96cda6..0000000 --- a/include/panic.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _KERNEL_PANIC_H -#define _KERNEL_PANIC_H - -#include -#include - -void panic(const char* arr) -{ - - uint8_t color = 0x1F; - uint8_t blank = 0xFF; - - for (size_t y = 0; y < VGA_HEIGHT; y++) - { - for (size_t x = 0; x < VGA_WIDTH; x++) - { - const size_t index = y * VGA_WIDTH + x; - VGA_MEMORY[index] = (uint16_t) ' ' | (uint16_t) blank << 8; - } - } - - int i; - for (i = 0; i < 75; i += 2) - { - VGA_MEMORY[i] = arr[i]; - VGA_MEMORY[i + 1] = color; - } -} - -#endif diff --git a/include/syscall.h b/include/syscall.h deleted file mode 100644 index e3f9d1a..0000000 --- a/include/syscall.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _SYSCALL_H -#define _SYSCALL_H - - - -#endif diff --git a/kernel/kernel.c b/kernel/kernel.c index d0a76b0..05a8e5a 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -45,6 +45,15 @@ extern void _hang_asm(void); extern void _sti_asm(void); +char* espresso_str = "" +"####### ##### ###### ###### ####### ##### ##### #######\n" +"# # # # # # # # # # # # # #\n" +"# # # # # # # # # # #\n" +"##### ##### ###### ###### ##### ##### ##### # #\n" +"# # # # # # # # # #\n" +"# # # # # # # # # # # # #\n" +"####### ##### # # # ####### ##### ##### #######\n"; + void kernel_main(multiboot_info_t* mbd, uint32_t magic) { @@ -142,16 +151,23 @@ void kernel_main(multiboot_info_t* mbd, uint32_t magic) /*pit_sleep(4000); begin_anim(espresso_kernel_version);*/ - /*printf("here\n"); + printf("Guten tag and welcome to Espresso %s\n", espresso_kernel_version); + + printf("%s\n", espresso_str); + + char buffer[512] = { 0 }; - printf("%i\n", sfs_init(false)); + int32_t i = sfs_read_file("test.txt", buffer, -1); - printf("here\n");*/ + printf("%i\n", i); - printf("Guten tag and welcome to Espresso\n"); + if (i == 0) + { + printf("%s\n", buffer); + } while (true) { - + /* Loop infinitely. We only do something when a syscall happens now. */ } } diff --git a/lib/mm/paging.c b/lib/mm/paging.c index 6e45cf5..c20d73f 100644 --- a/lib/mm/paging.c +++ b/lib/mm/paging.c @@ -23,7 +23,7 @@ void paging_init(void) page_directory = (page_directory_entry_t*)alloc_page(); memset(page_directory, 0, PAGE_SIZE); - /* Allocate and set up the first identity-mapped page table (0–4MB) */ + /* Allocate and set up the first identity-mapped page table (0-4MB) */ page_tables[0] = (page_table_entry_t*)alloc_page(); memset(page_tables[0], 0, PAGE_SIZE); for (uint32_t i = 0; i < PAGE_TABLE_ENTRIES; i++) diff --git a/lib/vector_extensions/sse.c b/lib/vector_extensions/sse.c index befb329..d0ebba5 100644 --- a/lib/vector_extensions/sse.c +++ b/lib/vector_extensions/sse.c @@ -99,41 +99,43 @@ void sse2_add_int32_arrays(int32_t *dst, const int32_t *a, const int32_t *b, siz __attribute__((force_align_arg_pointer)) void *sse2_memcpy(void *dst, const void *src, uint32_t n) { - uintptr_t i; + uint8_t *d = (uint8_t *)dst; + const uint8_t *s = (const uint8_t *)src; + uintptr_t i = 0; - /* Align to 16 bytes if necessary */ - while (((uintptr_t)dst & 15) && n > 0) + /* Align destination to 16 bytes */ + while (((uintptr_t)d & 15) && n > 0) { - *((uint8_t*)dst) = *((uint8_t*)src); - dst = (uint8_t*)dst + 1; - src = (uint8_t*)src + 1; + *d++ = *s++; n--; } - /* Copy 16-byte chunks with SSE2 */ - for (i = 0; i + 15 < n; i += 16) + /* Use SSE2 for 16-byte aligned blocks */ + for (; i + 15 < n; i += 16) { asm volatile ( - "movdqa (%1), %%xmm0\n\t" /* Load 16 bytes from source into xmm0 */ - "movdqa %%xmm0, (%0)\n\t" /* Store 16 bytes to destination */ + "movdqa (%1), %%xmm0\n\t" + "movdqa %%xmm0, (%0)\n\t" : - : "r"(dst + i), "r"(src + i) + : "r"(d + i), "r"(s + i) : "xmm0", "memory" ); } - /* Handle remaining bytes (less than 16) */ - while (n > 0) + d += i; + s += i; + n -= i; + + /* Copy any remaining bytes */ + while (n--) { - *((uint8_t*)dst) = *((uint8_t*)src); - dst = (uint8_t*)dst + 1; - src = (uint8_t*)src + 1; - n--; + *d++ = *s++; } - return dst; /* Return pointer to destination */ + return dst; } + __attribute__((force_align_arg_pointer)) char *sse2_strncpy(char *dest, const char *src, uint32_t n) {