Merge branch 'master' of github.com:wichtounet/thor-os

This commit is contained in:
Baptiste Wicht 2013-11-07 10:01:38 +01:00
commit fc6df08e76
36 changed files with 987 additions and 111 deletions

23
LICENSE
View File

@ -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.

View File

@ -4,3 +4,7 @@ thor-os
Thor is a minimalistic operating system created for learning reasons.
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.

11
add_license.bash Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

136
kernel/include/array.hpp Normal file
View File

@ -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<typename T, uint64_t N>
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<typename T>
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<T*>(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<uint64_t*>(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

View File

@ -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

View File

@ -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

61
kernel/include/disks.hpp Normal file
View File

@ -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<partition_descriptor> 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 <typename T>
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<uint64_t*>(pointer));
pointer = nullptr;
}
}
};
#endif

View File

@ -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);

View File

@ -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<drive_descriptor*>(k_malloc(4 * sizeof(drive_descriptor)));
void ata::detect_disks(){
drives = reinterpret_cast<drive_descriptor*>(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;

View File

@ -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 <stdarg.h>
#include "console.hpp"

200
kernel/src/disks.cpp Normal file
View File

@ -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::disk_descriptor, 4> _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<ata::drive_descriptor*>(disk.descriptor), start, count, destination);
default:
k_print_line("BOOH");
return false;
}
}
unique_heap_array<disks::partition_descriptor> disks::partitions(const disk_descriptor& disk){
unique_ptr<uint64_t> 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<boot_record_t*>(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<partition_descriptor> 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;
}

View File

@ -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;

View File

@ -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));
}

View File

@ -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<char>(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];
}

View File

@ -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<bool Debug>
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<uint64_t>(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<uint64_t>(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<malloc_header_chunk*>(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<malloc_footer_chunk*>(
reinterpret_cast<uintptr_t>(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<uintptr_t>(new_block) + new_block_size + sizeof(malloc_header_chunk));
new_footer->size = new_block_size;
debug_malloc<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<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<DEBUG_MALLOC>("after free");
}
void load_memory_map(){

View File

@ -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<uint16_t*>(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<uint64_t*>(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();
}

View File

@ -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"

View File

@ -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"

View File

@ -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;

7
license_header Normal file
View File

@ -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)
//=======================================================================

View File

@ -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:

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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