diff --git a/LICENSE b/LICENSE index e69de29b..36b7cd93 100644 --- a/LICENSE +++ b/LICENSE @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 00a608d3..d1c4950d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ thor-os ======= -Thor is a minimalistic operating system created for learning reasons. +Thor is a minimalistic operating system created for learning reasons. -It is currently a 64bit OS written in assembly and C++. +It is currently a 64bit OS written in assembly and C++. + +## License ## + +This project is distributed under the Boost Software License 1.0. Read `LICENSE_1_0.txt` for details. diff --git a/add_license.bash b/add_license.bash new file mode 100644 index 00000000..8f61c6aa --- /dev/null +++ b/add_license.bash @@ -0,0 +1,11 @@ +for file in "$@" +do + lines=`grep "Distributed under the Boost Software License" $file | wc -l` + + if [[ $lines == 0 ]] + then + cp ${file} ${file}.orig + cat license_header ${file}.orig > ${file} + rm ${file}.orig + fi +done diff --git a/bootloader/bootloader.asm b/bootloader/bootloader.asm index af0d5888..6d41c2b4 100644 --- a/bootloader/bootloader.asm +++ b/bootloader/bootloader.asm @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + [BITS 16] jmp rm_start diff --git a/bootloader/intel_16.asm b/bootloader/intel_16.asm index c3546a0b..70672783 100644 --- a/bootloader/intel_16.asm +++ b/bootloader/intel_16.asm @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + [BITS 16] ; Functions diff --git a/kernel/Makefile b/kernel/Makefile index b5dfc9bb..4ed3e92e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -5,7 +5,7 @@ CPP_FLAGS=-masm=intel -Iinclude/ -nostdlib -O1 -std=c++11 -fno-exceptions -fno-r KERNEL_FLAGS=$(CPP_FLAGS) KERNEL_LINK_FLAGS=-lgcc -T linker.ld $(CPP_FLAGS) -KERNEL_O_FILES=kernel.o keyboard.o console.o kernel_utils.o timer.o shell.o utils.o memory.o ata.o thor.o +KERNEL_O_FILES=kernel.o keyboard.o console.o kernel_utils.o timer.o shell.o utils.o memory.o ata.o thor.o disks.o CRTBEGIN_OBJ:=$(shell $(CC) $(CFLAGS) -print-file-name=crtbegin.o) CRTEND_OBJ:=$(shell $(CC) $(CFLAGS) -print-file-name=crtend.o) @@ -47,6 +47,9 @@ ata.o: src/ata.cpp thor.o: src/thor.cpp $(CC) $(KERNEL_FLAGS) -c src/thor.cpp -o thor.o +disks.o: src/disks.cpp + $(CC) $(KERNEL_FLAGS) -c src/disks.cpp -o disks.o + clean: rm -f *.o rm -f *.bin diff --git a/kernel/include/array.hpp b/kernel/include/array.hpp new file mode 100644 index 00000000..31774295 --- /dev/null +++ b/kernel/include/array.hpp @@ -0,0 +1,136 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef ARRAY_H +#define ARRAY_H + +#include "thor.hpp" + +template +class array { +private: + T data[N]; + +public: + typedef T value_type; + typedef value_type* iterator; + typedef const value_type* const_iterator; + typedef uint64_t size_type; + + T& operator[](size_type pos){ + return data[pos]; + } + + const T& operator[](size_type pos) const { + return data[pos]; + } + + size_type size(){ + return N; + } + + iterator begin(){ + return iterator(&data[0]); + } + + const_iterator begin() const { + return const_iterator(&data[0]); + } + + iterator end(){ + return iterator(&data[N]); + } + + const_iterator end() const { + return const_iterator(&data[N]); + } +}; + +template +class unique_heap_array { +public: + typedef T value_type; + typedef value_type* pointer_type; + typedef value_type* iterator; + typedef const value_type* const_iterator; + typedef uint64_t size_type; + +private: + T* array; + uint64_t _size; + +public: + unique_heap_array() : array(nullptr), _size(0) {} + + explicit unique_heap_array(T* a, size_type s) : array(a), _size(s) {} + explicit unique_heap_array(size_type s) : _size(s) { + array = reinterpret_cast(k_malloc(sizeof(T) * s)); + } + + unique_heap_array(unique_heap_array&& u) : array(u.release()), _size(u._size) { + u._size = 0; + } + + unique_heap_array& operator=(unique_heap_array&& u){ + _size = u._size; + reset(u.release()); + u._size = 0; + return *this; + } + + ~unique_heap_array(){ + reset(); + _size = 0; + } + + // Disable copy + unique_heap_array(const unique_heap_array& rhs) = delete; + unique_heap_array& operator=(const unique_heap_array& rhs) = delete; + + size_type size() const { + return _size; + } + + const T& operator[](size_type pos) const { + return array[pos]; + } + + T& operator[](size_type pos){ + return array[pos]; + } + + pointer_type release(){ + pointer_type p = array; + array = nullptr; + return p; + } + + void reset(pointer_type p = pointer_type()){ + if(array!= p){ + k_free(reinterpret_cast(array)); + array= nullptr; + } + } + + iterator begin(){ + return iterator(&array[0]); + } + + const_iterator begin() const { + return const_iterator(&array[0]); + } + + iterator end(){ + return iterator(&array[_size]); + } + + const_iterator end() const { + return const_iterator(&array[_size]); + } +}; + +#endif diff --git a/kernel/include/ata.hpp b/kernel/include/ata.hpp index d50056cf..89732bd6 100644 --- a/kernel/include/ata.hpp +++ b/kernel/include/ata.hpp @@ -1,8 +1,17 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #ifndef ATA_H #define ATA_H #include "types.hpp" +namespace ata { + struct drive_descriptor { uint16_t controller; uint8_t drive; @@ -14,6 +23,8 @@ void detect_disks(); uint8_t number_of_disks(); drive_descriptor& drive(uint8_t disk); -bool ata_read_sectors(drive_descriptor& drive, uint64_t start, uint8_t count, void* destination); +bool read_sectors(drive_descriptor& drive, uint64_t start, uint8_t count, void* destination); + +} #endif diff --git a/kernel/include/console.hpp b/kernel/include/console.hpp index 16db8f6a..f729abdf 100644 --- a/kernel/include/console.hpp +++ b/kernel/include/console.hpp @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #ifndef CONSOLE_H #define CONSOLE_H diff --git a/kernel/include/disks.hpp b/kernel/include/disks.hpp new file mode 100644 index 00000000..43f4efd9 --- /dev/null +++ b/kernel/include/disks.hpp @@ -0,0 +1,61 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef DISKS_H +#define DISKS_H + +#include "types.hpp" +#include "array.hpp" + +namespace disks { + +enum class disk_type { + ATA +}; + +struct disk_descriptor { + uint64_t uuid; + disk_type type; + void* descriptor; +}; + +enum class partition_type { + FAT32, + UNKNOWN +}; + +struct partition_descriptor { + uint64_t uuid; + partition_type type; + uint64_t start; + uint64_t sectors; +}; + +void detect_disks(); + +uint64_t detected_disks(); + +bool disk_exists(uint64_t uuid); + +const disk_descriptor& disk_by_index(uint64_t index); +const disk_descriptor& disk_by_uuid(uint64_t uuid); + +const char* disk_type_to_string(disk_type type); +const char* partition_type_to_string(partition_type type); + +bool read_sectors(const disk_descriptor& disk, uint64_t start, uint8_t count, void* destination); +unique_heap_array partitions(const disk_descriptor& disk); +bool partition_exists(const disk_descriptor& disk, uint64_t uuid); + +void mount(const disk_descriptor& disk, uint64_t uuid); + +const disk_descriptor* mounted_disk(); +const partition_descriptor* mounted_partition(); + +} + +#endif diff --git a/kernel/include/kernel_utils.hpp b/kernel/include/kernel_utils.hpp index 1558623a..44f43b69 100644 --- a/kernel/include/kernel_utils.hpp +++ b/kernel/include/kernel_utils.hpp @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #ifndef KERNEL_UTILS_H #define KERNEL_UTILS_H diff --git a/kernel/include/keyboard.hpp b/kernel/include/keyboard.hpp index 76b7bfc2..e840dc39 100644 --- a/kernel/include/keyboard.hpp +++ b/kernel/include/keyboard.hpp @@ -1,8 +1,24 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #ifndef KEYBOARD_H #define KEYBOARD_H #include "types.hpp" +namespace keyboard { + +const char KEY_ENTER = 0x1C; +const char KEY_BACKSPACE = 0x0E; + +void install_driver(); +char get_char(); char key_to_ascii(uint8_t key); +} + #endif diff --git a/kernel/include/memory.hpp b/kernel/include/memory.hpp index 572d4193..664d446e 100644 --- a/kernel/include/memory.hpp +++ b/kernel/include/memory.hpp @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #ifndef MEMORY_H #define MEMORY_H diff --git a/kernel/include/shell.hpp b/kernel/include/shell.hpp index 5ac9f09d..1663f990 100644 --- a/kernel/include/shell.hpp +++ b/kernel/include/shell.hpp @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #ifndef SHELL_H #define SHELL_ diff --git a/kernel/include/thor.hpp b/kernel/include/thor.hpp index 96905c1c..d4464551 100644 --- a/kernel/include/thor.hpp +++ b/kernel/include/thor.hpp @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #ifndef THOR_H #define THOR_H diff --git a/kernel/include/timer.hpp b/kernel/include/timer.hpp index 9d660628..f8cd0118 100644 --- a/kernel/include/timer.hpp +++ b/kernel/include/timer.hpp @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #ifndef TIMER_H #define TIMER_H diff --git a/kernel/include/types.hpp b/kernel/include/types.hpp index fda0a67f..f627074b 100644 --- a/kernel/include/types.hpp +++ b/kernel/include/types.hpp @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #ifndef TYPES_H #define TYPES_H diff --git a/kernel/include/unique_ptr.hpp b/kernel/include/unique_ptr.hpp new file mode 100644 index 00000000..7957fc59 --- /dev/null +++ b/kernel/include/unique_ptr.hpp @@ -0,0 +1,67 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef UNIQUE_PTR_H +#define UNIQUE_PTR_H + +#include "thor.hpp" + +template +class unique_ptr { +public: + typedef T* pointer_type; + typedef T element_type; + +private: + pointer_type pointer; + +public: + explicit unique_ptr(pointer_type p) : pointer(p){} + + unique_ptr() : pointer(pointer_type()) {} + + unique_ptr(unique_ptr&& u) : pointer(u.release()) {} + unique_ptr& operator=(unique_ptr&& u){ + reset(u.release()); + return *this; + } + + ~unique_ptr(){ + reset(); + } + + // Disable copy + unique_ptr(const unique_ptr& rhs) = delete; + unique_ptr& operator=(const unique_ptr& rhs) = delete; + + element_type& operator*() const { + return *get(); + } + + pointer_type operator->() const { + return get(); + } + + pointer_type get() const { + return pointer; + } + + pointer_type release(){ + pointer_type p = pointer; + pointer = nullptr; + return p; + } + + void reset(pointer_type p = pointer_type()){ + if(pointer != p){ + k_free(reinterpret_cast(pointer)); + pointer = nullptr; + } + } +}; + +#endif diff --git a/kernel/include/utils.hpp b/kernel/include/utils.hpp index 4e98a3d4..3a73afa5 100644 --- a/kernel/include/utils.hpp +++ b/kernel/include/utils.hpp @@ -1,9 +1,17 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #ifndef UTILS_H #define UTILS_H #include "types.hpp" uint64_t parse(const char* str); +uint64_t parse(const char* str, const char* end); bool str_equals(const char* a, const char* b); bool str_contains(const char* a, char c); diff --git a/kernel/src/ata.cpp b/kernel/src/ata.cpp index cbc78bb8..02266101 100644 --- a/kernel/src/ata.cpp +++ b/kernel/src/ata.cpp @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #include "ata.hpp" #include "kernel_utils.hpp" #include "timer.hpp" @@ -37,8 +44,7 @@ namespace { #define MASTER_BIT 0 #define SLAVE_BIT 1 -bool detected = false; -drive_descriptor* drives; +ata::drive_descriptor* drives; volatile bool primary_invoked = false; volatile bool secondary_invoked = false; @@ -88,7 +94,7 @@ static uint8_t wait_for_controller(uint16_t controller, uint8_t mask, uint8_t va return timeout; } -bool select_device(drive_descriptor& drive){ +bool select_device(ata::drive_descriptor& drive){ auto controller = drive.controller; if(in_byte(controller + ATA_STATUS) & (ATA_STATUS_BSY | ATA_STATUS_DRQ)){ @@ -107,47 +113,35 @@ bool select_device(drive_descriptor& drive){ } //end of anonymous namespace -void detect_disks(){ - if(!detected){ - drives = reinterpret_cast(k_malloc(4 * sizeof(drive_descriptor))); +void ata::detect_disks(){ + drives = reinterpret_cast(k_malloc(4 * sizeof(drive_descriptor))); - drives[0] = {ATA_PRIMARY, 0xE0, false, MASTER_BIT}; - drives[1] = {ATA_PRIMARY, 0xF0, false, SLAVE_BIT}; - drives[2] = {ATA_SECONDARY, 0xE0, false, MASTER_BIT}; - drives[3] = {ATA_SECONDARY, 0xF0, false, SLAVE_BIT}; + drives[0] = {ATA_PRIMARY, 0xE0, false, MASTER_BIT}; + drives[1] = {ATA_PRIMARY, 0xF0, false, SLAVE_BIT}; + drives[2] = {ATA_SECONDARY, 0xE0, false, MASTER_BIT}; + drives[3] = {ATA_SECONDARY, 0xF0, false, SLAVE_BIT}; - for(uint8_t i = 0; i < 4; ++i){ - auto& drive = drives[i]; + for(uint8_t i = 0; i < 4; ++i){ + auto& drive = drives[i]; - out_byte(drive.controller + 0x6, drive.drive); - sleep_ms(4); - drive.present = in_byte(drive.controller + 0x7) & 0x40; - } - - register_irq_handler<14>(primary_controller_handler); - register_irq_handler<15>(secondary_controller_handler); - - detected = true; + out_byte(drive.controller + 0x6, drive.drive); + sleep_ms(4); + drive.present = in_byte(drive.controller + 0x7) & 0x40; } + + register_irq_handler<14>(primary_controller_handler); + register_irq_handler<15>(secondary_controller_handler); } -uint8_t number_of_disks(){ - if(!detected){ - detect_disks(); - } - +uint8_t ata::number_of_disks(){ return 4; } -drive_descriptor& drive(uint8_t disk){ - if(!detected){ - detect_disks(); - } - +ata::drive_descriptor& ata::drive(uint8_t disk){ return drives[disk]; } -bool ata_read_sectors(drive_descriptor& drive, uint64_t start, uint8_t count, void* destination){ +bool ata::read_sectors(drive_descriptor& drive, uint64_t start, uint8_t count, void* destination){ //Select the device if(!select_device(drive)){ return false; diff --git a/kernel/src/console.cpp b/kernel/src/console.cpp index 477fd7d9..0c37ad59 100644 --- a/kernel/src/console.cpp +++ b/kernel/src/console.cpp @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #include #include "console.hpp" diff --git a/kernel/src/disks.cpp b/kernel/src/disks.cpp new file mode 100644 index 00000000..24cf7d24 --- /dev/null +++ b/kernel/src/disks.cpp @@ -0,0 +1,200 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include "disks.hpp" +#include "ata.hpp" +#include "thor.hpp" +#include "console.hpp" + +#include "unique_ptr.hpp" +#include "array.hpp" + +namespace { + +//For now, 4 is enough as only the ata driver is implemented +array _disks; + +uint64_t number_of_disks = 0; + +struct partition_descriptor_t { + uint8_t boot_flag; + uint8_t chs_begin[3]; + uint8_t type_code; + uint8_t chs_end[3]; + uint32_t lba_begin; + uint32_t sectors; +} __attribute__ ((packed)); + +static_assert(sizeof(partition_descriptor_t) == 16, "A partition descriptor is 16 bytes long"); + +struct boot_record_t { + uint8_t boot_code[446]; + partition_descriptor_t partitions[4]; + uint16_t signature; +} __attribute__ ((packed)); + +static_assert(sizeof(boot_record_t) == 512, "The boot record is 512 bytes long"); + +const disks::disk_descriptor* _mounted_disk; +const disks::partition_descriptor* _mounted_partition; + +} //end of anonymous namespace + +void disks::detect_disks(){ + ata::detect_disks(); + + for(uint8_t i = 0; i < ata::number_of_disks(); ++i){ + auto& descriptor = ata::drive(i); + + if(descriptor.present){ + _disks[number_of_disks] = {number_of_disks, disks::disk_type::ATA, &descriptor}; + ++number_of_disks; + } + } + + _mounted_disk = nullptr; + _mounted_partition = nullptr; +} + +uint64_t disks::detected_disks(){ + return number_of_disks; +} + +const disks::disk_descriptor& disks::disk_by_index(uint64_t index){ + return _disks[index]; +} + +const disks::disk_descriptor& disks::disk_by_uuid(uint64_t uuid){ + for(uint64_t i = 0; i < number_of_disks; ++i){ + if(_disks[i].uuid == uuid){ + return _disks[i]; + } + } + + //Unreachable +} + +bool disks::disk_exists(uint64_t uuid){ + for(uint64_t i = 0; i < number_of_disks; ++i){ + if(_disks[i].uuid == uuid){ + return true; + } + } + + return false; +} + +const char* disks::disk_type_to_string(disk_type type){ + switch(type){ + case disk_type::ATA: + return "ATA"; + default: + return "Invalid Type"; + } +} + +const char* disks::partition_type_to_string(partition_type type){ + switch(type){ + case partition_type::FAT32: + return "FAT32"; + case partition_type::UNKNOWN: + return "Unknown"; + default: + return "Invalid Type"; + } +} + +bool disks::read_sectors(const disk_descriptor& disk, uint64_t start, uint8_t count, void* destination){ + switch(disk.type){ + case disk_type::ATA: + return ata::read_sectors(*static_cast(disk.descriptor), start, count, destination); + + default: + k_print_line("BOOH"); + return false; + } +} + +unique_heap_array disks::partitions(const disk_descriptor& disk){ + unique_ptr buffer(k_malloc(512)); + + if(!read_sectors(disk, 0, 1, buffer.get())){ + k_print_line("Read Boot Record failed"); + + return {}; + } else { + auto* boot_record = reinterpret_cast(buffer.get()); + + if(boot_record->signature != 0xAA55){ + k_print_line("Invalid boot record signature"); + + return {}; + } + + uint64_t n = 0; + for(int i = 0; i < 4; ++i){ + if(boot_record->partitions[i].type_code > 0){ + ++n; + } + } + + unique_heap_array partitions(n); + uint64_t p = 0; + + for(uint64_t i = 0; i < 4; ++i){ + if(boot_record->partitions[i].type_code > 0){ + partition_type type; + if(boot_record->partitions[i].type_code == 0x0B || boot_record->partitions[i].type_code == 0x0C){ + type = partition_type::FAT32; + } else { + type = partition_type::UNKNOWN; + } + + partitions[p] = {p, type, boot_record->partitions[i].lba_begin, boot_record->partitions[i].sectors}; + + ++p; + } + } + + return partitions; + } +} + +bool disks::partition_exists(const disk_descriptor& disk, uint64_t uuid){ + for(auto& partition : partitions(disk)){ + if(partition.uuid == uuid){ + return true; + } + } + + return false; +} + +void disks::mount(const disk_descriptor& disk, uint64_t uuid){ + _mounted_disk = &disk; + + if(_mounted_partition){ + delete _mounted_partition; + } + + for(auto& partition : partitions(disk)){ + if(partition.uuid == uuid){ + auto p = new partition_descriptor(); + *p = partition; + _mounted_partition = p; + break; + } + } +} + +const disks::disk_descriptor* disks::mounted_disk(){ + return _mounted_disk; +} + +const disks::partition_descriptor* disks::mounted_partition(){ + return _mounted_partition; +} diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp index 71e8f888..9421e8e5 100644 --- a/kernel/src/kernel.cpp +++ b/kernel/src/kernel.cpp @@ -1,6 +1,15 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #include "memory.hpp" #include "timer.hpp" #include "shell.hpp" +#include "keyboard.hpp" +#include "disks.hpp" extern "C" { @@ -8,6 +17,8 @@ void __attribute__ ((section ("main_section"))) kernel_main(){ load_memory_map(); init_memory_manager(); install_timer(); + keyboard::install_driver(); + disks::detect_disks(); init_shell(); return; diff --git a/kernel/src/kernel_utils.cpp b/kernel/src/kernel_utils.cpp index 6be8ba80..f98536f4 100644 --- a/kernel/src/kernel_utils.cpp +++ b/kernel/src/kernel_utils.cpp @@ -1,21 +1,40 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #include "kernel_utils.hpp" uint8_t in_byte(uint16_t _port){ uint8_t rv; - __asm__ __volatile__ ("in %0, %1" : "=a" (rv) : "dN" (_port)); - return rv; -} -void out_byte (uint16_t _port, uint8_t _data){ - __asm__ __volatile__ ("out %0, %1" : : "dN" (_port), "a" (_data)); + __asm__ __volatile__ ("in %[data], %[port]" + : [data] "=a" (rv) + : [port] "dN" (_port)); + + return rv; } uint16_t in_word(uint16_t _port){ uint16_t rv; - __asm__ __volatile__ ("in %0, %1" : "=a" (rv) : "dN" (_port)); + + __asm__ __volatile__ ("in %[data], %[port]" + : [data] "=a" (rv) + : [port] "dN" (_port)); + return rv; } -void out_word(uint16_t _port, uint16_t _data){ - __asm__ __volatile__ ("out %0, %1" : : "dN" (_port), "a" (_data)); +void out_byte (uint16_t _port, uint8_t _data){ + __asm__ __volatile__ ("out %[port], %[data]" + : /* No outputs */ + : [port] "dN" (_port), [data] "a" (_data)); +} + +void out_word(uint16_t _port, uint16_t _data){ + __asm__ __volatile__ ("out %[port], %[data]" + : /* No outputs */ + : [port] "dN" (_port), [data] "a" (_data)); } diff --git a/kernel/src/keyboard.cpp b/kernel/src/keyboard.cpp index 586a9031..3b240415 100644 --- a/kernel/src/keyboard.cpp +++ b/kernel/src/keyboard.cpp @@ -1,4 +1,12 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #include "keyboard.hpp" +#include "kernel_utils.hpp" namespace { @@ -42,8 +50,50 @@ char qwertz[128] = 0, /* All other keys are undefined */ }; +const uint8_t BUFFER_SIZE = 64; + +char input_buffer[BUFFER_SIZE]; +volatile uint8_t start; +volatile uint8_t count; + +void keyboard_handler(){ + auto key = static_cast(in_byte(0x60)); + + if(count == BUFFER_SIZE){ + //The buffer is full, we loose the characters + } else { + auto end = (start + count) % BUFFER_SIZE; + input_buffer[end] = key; + ++count; + } } -char key_to_ascii(uint8_t key){ +} + +void keyboard::install_driver(){ + register_irq_handler<1>(keyboard_handler); + + start = 0; + count = 0; +} + +char keyboard::get_char(){ + //Wait for the buffer to contains something + while(count == 0){ + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + __asm__ __volatile__ ("nop"); + } + + auto key = input_buffer[start]; + start = (start + 1) % BUFFER_SIZE; + --count; + + return key; +} + +char keyboard::key_to_ascii(uint8_t key){ return qwertz[key]; } diff --git a/kernel/src/memory.cpp b/kernel/src/memory.cpp index 9cc97ab6..cce7dae5 100644 --- a/kernel/src/memory.cpp +++ b/kernel/src/memory.cpp @@ -1,7 +1,19 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #include "memory.hpp" +#include "console.hpp" namespace { +//Used to compile with malloc operations in the console +//can produce a lot of output +const bool DEBUG_MALLOC = false; + struct bios_mmap_entry { uint32_t base_low; uint32_t base_high; @@ -20,7 +32,12 @@ mmapentry e820_mmap[32]; void mmap_query(uint64_t cmd, uint64_t* result){ uint64_t tmp; - __asm__ __volatile__ ("mov r8, %0; int 62; mov %1, rax" : : "dN" (cmd), "a" (tmp)); + + __asm__ __volatile__ ("mov r8, %[port]; int 62; mov %[dst], rax" + : [dst] "=a" (tmp) + : [port] "dN" (cmd) + : "cc", "memory", "r8"); + *result = tmp; } @@ -104,6 +121,35 @@ uint64_t* allocate_block(uint64_t blocks){ return block; } +template +void debug_malloc(const char* point = nullptr){ + if(Debug){ + if(point){ + k_print_line(point); + } + + auto it = malloc_head; + + k_print("next: "); + do { + k_printf("%h -> ", reinterpret_cast(it)); + it = it->next; + } while(it != malloc_head); + + k_printf("%h\n", malloc_head); + + it = malloc_head; + + k_print("prev: "); + do { + k_printf("%h <- ", reinterpret_cast(it)); + it = it->prev; + } while(it != malloc_head); + + k_printf("%h\n", malloc_head); + } +} + } //end of anonymous namespace void init_memory_manager(){ @@ -141,12 +187,12 @@ uint64_t* k_malloc(uint64_t bytes){ auto header = reinterpret_cast(block); header->size = MIN_BLOCKS * BLOCK_SIZE - META_SIZE; + header->next = current->next; + header->prev = current; + current->next->prev = header; current->next = header; - header->next = current->next; - header->prev = current; - auto footer = reinterpret_cast( reinterpret_cast(block) + header->size + sizeof(malloc_header_chunk)); footer->size = header->size; @@ -154,7 +200,7 @@ uint64_t* k_malloc(uint64_t bytes){ //This block is big enough //Is it worth splitting the block ? - if(current->size - bytes - META_SIZE > MIN_SPLIT){ + if(current->size > bytes + META_SIZE + MIN_SPLIT){ auto new_block_size = current->size - bytes - META_SIZE; //Set the new size; @@ -177,12 +223,16 @@ uint64_t* k_malloc(uint64_t bytes){ reinterpret_cast(new_block) + new_block_size + sizeof(malloc_header_chunk)); new_footer->size = new_block_size; + debug_malloc("after malloc split"); + break; } else { //Remove this node from the free list current->prev->next = current->next; current->next->prev = current->prev; + debug_malloc("after malloc no split"); + break; } } @@ -213,6 +263,8 @@ void k_free(uint64_t* block){ header->next->prev = free_header; header->next = free_header; + + debug_malloc("after free"); } void load_memory_map(){ diff --git a/kernel/src/shell.cpp b/kernel/src/shell.cpp index fc99ffd0..e64fe244 100644 --- a/kernel/src/shell.cpp +++ b/kernel/src/shell.cpp @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #include "types.hpp" #include "keyboard.hpp" #include "kernel_utils.hpp" @@ -6,7 +13,7 @@ #include "timer.hpp" #include "utils.hpp" #include "memory.hpp" -#include "ata.hpp" +#include "disks.hpp" namespace { @@ -22,13 +29,16 @@ void echo_command(const char* params); void mmap_command(const char* params); void memory_command(const char* params); void disks_command(const char* params); +void partitions_command(const char* params); +void mount_command(const char* params); +void ls_command(const char* params); struct command_definition { const char* name; void (*function)(const char*); }; -command_definition commands[10] = { +command_definition commands[13] = { {"reboot", reboot_command}, {"help", help_command}, {"uptime", uptime_command}, @@ -39,6 +49,9 @@ command_definition commands[10] = { {"mmap", mmap_command}, {"memory", memory_command}, {"disks", disks_command}, + {"partitions", partitions_command}, + {"mount", mount_command}, + {"ls", ls_command}, }; uint64_t current_input_length = 0; @@ -46,45 +59,44 @@ char current_input[50]; void exec_command(); -#define KEY_ENTER 0x1C -#define KEY_BACKSPACE 0x0E +void start_shell(){ + while(true){ + auto key = keyboard::get_char(); -void keyboard_handler(){ - uint8_t key = in_byte(0x60); - - if(key & 0x80){ - //TODO Handle shift - } else { - if(key == KEY_ENTER){ - current_input[current_input_length] = '\0'; - - k_print_line(); - - exec_command(); - - if(get_column() != 0){ - set_column(0); - set_line(get_line() + 1); - } - - current_input_length = 0; - - k_print("thor> "); - } else if(key == KEY_BACKSPACE){ - if(current_input_length > 0){ - set_column(get_column() - 1); - k_print(' '); - set_column(get_column() - 1); - - --current_input_length; - } + if(key & 0x80){ + //TODO Handle shift } else { - auto qwertz_key = key_to_ascii(key); + if(key == keyboard::KEY_ENTER){ + current_input[current_input_length] = '\0'; - if(qwertz_key > 0){ - current_input[current_input_length++] = qwertz_key; - k_print(qwertz_key); - } + k_print_line(); + + exec_command(); + + if(get_column() != 0){ + set_column(0); + set_line(get_line() + 1); + } + + current_input_length = 0; + + k_print("thor> "); + } else if(key == keyboard::KEY_BACKSPACE){ + if(current_input_length > 0){ + set_column(get_column() - 1); + k_print(' '); + set_column(get_column() - 1); + + --current_input_length; + } + } else { + auto qwertz_key = keyboard::key_to_ascii(key); + + if(qwertz_key > 0){ + current_input[current_input_length++] = qwertz_key; + k_print(qwertz_key); + } + } } } } @@ -256,32 +268,79 @@ void memory_command(const char*){ k_printf("Total used memory: %m\n", used_memory()); k_printf("Total free memory: %m\n", free_memory()); } - - uint16_t* buffer = reinterpret_cast(k_malloc(512)); - - if(!ata_read_sectors(drive(0), 2048, 1, buffer)){ - k_print_line("Read failed"); - } else { - for(int i = 0; i < 80; i += 8){ - k_printf("%.4h %.4h %.4h %.4h %.4h %.4h %.4h %.4h\n", - (uint64_t) buffer[i+0], (uint64_t) buffer[i+1], (uint64_t) buffer[i+2], (uint64_t) buffer[i+3], - (uint64_t) buffer[i+4], (uint64_t) buffer[i+5], (uint64_t) buffer[i+6], (uint64_t) buffer[i+7]); - } - - k_free(reinterpret_cast(buffer)); - } } void disks_command(const char*){ - k_print_line("Controller Drive Present"); + k_print_line("UUID Type"); - for(uint64_t i = 0; i < number_of_disks(); ++i){ - auto& descriptor = drive(i); + for(uint64_t i = 0; i < disks::detected_disks(); ++i){ + auto& descriptor = disks::disk_by_index(i); - k_printf("%12h %8h %s\n", descriptor.controller, descriptor.drive, descriptor.present ? "Yes" : "No"); + k_printf("%10d %s\n", descriptor.uuid, disks::disk_type_to_string(descriptor.type)); } } +void partitions_command(const char* params){ + const char* delay_str = params + 11; + + auto uuid = parse(delay_str); + + if(disks::disk_exists(uuid)){ + auto partitions = disks::partitions(disks::disk_by_uuid(uuid)); + + if(partitions.size() > 0){ + k_print_line("UUID Type Start Sectors"); + + for(auto& partition : partitions){ + k_printf("%10d %12s %10d %d\n", partition.uuid, + disks::partition_type_to_string(partition.type), + partition.start, partition.sectors); + } + } + } else { + k_printf("Disks %d does not exist\n", uuid); + } +} + +void mount_command(const char* params){ + if(!*(params+5)){ + auto md = disks::mounted_disk(); + auto mp = disks::mounted_partition(); + + if(md && mp){ + k_printf("%d:%d is mounted\n", md->uuid, mp->uuid); + } else { + k_print_line("Nothing is mounted"); + } + } else { + const char* it = params + 6; + const char* it_end = it; + + while(*it_end != ' '){ + ++it_end; + } + + auto disk_uuid = parse(it, it_end); + auto partition_uuid = parse(it_end + 1); + + if(disks::disk_exists(disk_uuid)){ + auto& disk = disks::disk_by_uuid(disk_uuid); + if(disks::partition_exists(disk, partition_uuid)){ + disks::mount(disk, partition_uuid); + } else { + k_printf("Partition %d does not exist\n", partition_uuid); + } + } else { + k_printf("Disk %d does not exist\n", disk_uuid); + } + } +} + +void ls_command(const char*){ + //TODO Implement mount first + //TODO Implement ls +} + } //end of anonymous namespace void init_shell(){ @@ -291,5 +350,5 @@ void init_shell(){ k_print("thor> "); - register_irq_handler<1>(keyboard_handler); + start_shell(); } diff --git a/kernel/src/thor.cpp b/kernel/src/thor.cpp index c18b3220..e900ed28 100644 --- a/kernel/src/thor.cpp +++ b/kernel/src/thor.cpp @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #include "thor.hpp" #include "memory.hpp" diff --git a/kernel/src/timer.cpp b/kernel/src/timer.cpp index 68baa861..a965f350 100644 --- a/kernel/src/timer.cpp +++ b/kernel/src/timer.cpp @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #include "timer.hpp" #include "kernel_utils.hpp" diff --git a/kernel/src/utils.cpp b/kernel/src/utils.cpp index e60bd508..5f8b1f5a 100644 --- a/kernel/src/utils.cpp +++ b/kernel/src/utils.cpp @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + #include "utils.hpp" bool str_equals(const char* a, const char* b){ @@ -9,6 +16,20 @@ bool str_equals(const char* a, const char* b){ return *a == *b; } +uint64_t parse(const char* it, const char* end){ + int i = end - it - 1; + + uint64_t factor = 1; + uint64_t acc = 0; + + for(; i >= 0; --i){ + acc += (it[i] - '0') * factor; + factor *= 10; + } + + return acc; +} + uint64_t parse(const char* str){ int i = 0; diff --git a/license_header b/license_header new file mode 100644 index 00000000..9cd10d1e --- /dev/null +++ b/license_header @@ -0,0 +1,7 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + diff --git a/micro_kernel/interrupts.asm b/micro_kernel/interrupts.asm index 5964e393..d1b5d592 100644 --- a/micro_kernel/interrupts.asm +++ b/micro_kernel/interrupts.asm @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + ; Variables @@ -122,24 +129,28 @@ _irq%1: test rax, rax je .eoi - push rbx + push rax push rcx push rdx push rsi push rdi push r8 push r9 + push r10 + push r11 ; Call the handler call rax - push r9 - push r8 + pop r11 + pop r10 + pop r9 + pop r8 pop rdi pop rsi pop rdx pop rcx - pop rbx + pop rax .eoi: diff --git a/micro_kernel/micro_kernel.asm b/micro_kernel/micro_kernel.asm index 46a78494..0567a648 100644 --- a/micro_kernel/micro_kernel.asm +++ b/micro_kernel/micro_kernel.asm @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + [BITS 16] [ORG 0x1000] diff --git a/micro_kernel/utils/console.asm b/micro_kernel/utils/console.asm index 9382a5b2..72e1a863 100644 --- a/micro_kernel/utils/console.asm +++ b/micro_kernel/utils/console.asm @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + %define BLACK_F 0x0 %define BLUE_F 0x1 %define GREEN_F 0x2 diff --git a/micro_kernel/utils/macros.asm b/micro_kernel/utils/macros.asm index 32010f17..85e1dd26 100644 --- a/micro_kernel/utils/macros.asm +++ b/micro_kernel/utils/macros.asm @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + ; Some utility macros ; Define a string and a variable containing its length diff --git a/micro_kernel/utils/utils.asm b/micro_kernel/utils/utils.asm index e1454b8d..c8cfb1d0 100644 --- a/micro_kernel/utils/utils.asm +++ b/micro_kernel/utils/utils.asm @@ -1,3 +1,10 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + ; Compute the length of string representation of the integer ; in r8 = integer to print ; out rax = string length of int