Commit initial

This commit is contained in:
2020-04-17 17:44:23 +02:00
commit ea623dfa61
54 changed files with 7297 additions and 0 deletions

39
kernel/Makefile Normal file
View File

@ -0,0 +1,39 @@
.PHONY: clean
.SUFFIXES:
include_dir=include/
CC=gcc
CFLAGS= -m32 -march=i486 -fno-stack-protector -fno-zero-initialized-in-bss -I $(include_dir)
kobj_core=src/main.o \
src/print.o \
src/memory.o \
src/interrupt.o \
src/utils.o \
src/systemCall.o \
src/process.o \
src/ipc.o \
src/scheduler.o \
src/elf_loader.o \
src/signal.o
kobj_asm_x86=src/asm/isr.o \
src/asm/asm_utils.o \
src/asm/io_port.o \
src/asm/sched.o
all: NOS-kernel32.bin
NOS-kernel32.bin: $(kobj_core) $(kobj_asm_x86)
ld -melf_i386 --oformat=binary --Ttext=100000 --entry=main $^ -o $@
%.o: %.asm
nasm -f elf -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c $^ -o $@
clean:
-rm -f $(kobj_core) $(kobj_asm_x86)
-rm -f NOS-kernel32.bin

50
kernel/include/args.h Normal file
View File

@ -0,0 +1,50 @@
/* args.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef ARGS_H
#define ARGS_H
#include "types.h"
/* Strcutres de r<>cup<75>ration de contexte */
typedef struct {
T_dword baseAddr_1;
T_dword baseAddr_2;
T_dword size_1;
T_dword size_2;
T_dword type;
T_dword unused;
}__attribute__((packed)) T_memMapEntry;
typedef struct {
T_byte cursor_X;
T_byte cursor_Y;
T_dword phyMemSize;
T_byte memListEntryNumber;
T_dword initProcessAddr;
T_dword initProcessSize;
T_memMapEntry* memMap;
}__attribute__((packed)) T_kernelArgs;
T_kernelArgs* args;
#endif

51
kernel/include/asm_x86.h Normal file
View File

@ -0,0 +1,51 @@
/* asm_x86.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef ASM_X86_H
#define ASM_X86_H
#include "types.h"
#include "memory.h"
#include "interrupt.h"
void _loadGdtR(T_gdt*);
void _loadTaskRegister();
void _loadIdtR(T_idt*);
void _clearInterrupt();
void _startInterrupt();
void _out(T_word, T_byte);
T_byte _in(T_word);
void _outw(T_word, T_word);
T_word _inw(T_word);
void _outdw(T_word, T_dword);
T_dword _indw(T_word);
void _enablePaging();
void _emptyTLB();
void _loadCr3(T_dword);
T_dword _readCr3();
T_dword _readCr2();
T_dword _saveEflags();
T_dword _restoreEflags(T_dword);
T_dword _atomicTestAndSet(unsigned int*);
T_dword _getStackFrameAddr(unsigned int);
#endif

View File

@ -0,0 +1,32 @@
/* elf_loader.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef ELF_LOADER_H
#define ELF_LOADER_H
#include "types.h"
#include "utils.h"
int ELF32_checkFile(void*);
unsigned int ELF32_load(void*, T_list*);
#endif

View File

@ -0,0 +1,99 @@
/* interrupt.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef INTERRUPT_H
#define INTERRUPT_H
#include "types.h"
/* === Configuration du PIC 8259A === */
#define PIC_MASTER_CMD_REG 0x20
#define PIC_MASTER_DATA_REG 0x21
#define PIC_MASTER_IDT_OFFSET 0x20
#define PIC_SLAVE_CMD_REG 0xA0
#define PIC_SLAVE_DATA_REG 0xA1
#define PIC_SLAVE_IDT_OFFSET 0x28
#define PIC_EOI 0x20
void PIC_init();
void PIC_maskIRQ(T_byte);
void PIC_sendEOI();
/* ======================================================================== */
/* ===== Manipulation de l'IDT ===== */
#define IDT_BASE 0x200800
#define INT_DESC_SIZE 8
#define IDT_SIZE 256
#define DIVIDE_BY_0_INT 0
#define NMI_INT 2
#define BREAKPOINT_INT 3
#define OVERFLOW_INT 4
#define INVALID_TSS_INT 10
#define SEG_FAULT_INT 11
#define STACK_SEG_FAULT_INT 12
#define GP_FAULT_INT 13
#define PAGE_FAULT_INT 14
#define TIMER_INT 32
#define KB_INT 33
#define SYS_CALL_INT 64
typedef struct {
T_word offset0_15;
T_word segment;
T_word type;
T_word offset16_31;
}__attribute__((packed)) T_IDT_desc;
typedef struct {
T_word limite;
T_dword base;
}__attribute__((packed)) T_IDT_reg;
void IDT_init();
void IDT_createDesc(T_dword, T_word, T_word, unsigned int);
/* ======================================================================== */
/* Routine d'interruption en assembleur (redirection vers routines en C) */
void _defaultInt();
void _SEG_fault();
void _GP_fault();
void _page_fault();
void _clockInterrupt();
void _syscall();
/* ======================================================================== */
#endif

31
kernel/include/ipc.h Normal file
View File

@ -0,0 +1,31 @@
/* ipc.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef IPC_H
#define IPC_H
#include "types.h"
void IPC_mutexLock(unsigned int*);
void IPC_mutexUnlock(unsigned int*);
#endif

223
kernel/include/memory.h Normal file
View File

@ -0,0 +1,223 @@
/* memory.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef MEMORY_H
#define MEMORY_H
#include "types.h"
/* ###### Main Memory Management ###### */
#define KERNEL_SPACE_SIZE 0x10000000 /* Mémoire potentiellement utilisable par le kernel, adresse virtuelle de fin de l'espace noyau, aligné sur 4 Mo */
/* Configation dynamique */
#define KERNEL_SPACE_PT_COUNT (KERNEL_SPACE_SIZE / (PAGE_PER_PT * PAGE_SIZE))
#define KERNEL_SPACE_PAGE_COUNT (KERNEL_SPACE_PT_COUNT * PAGE_PER_PT)
#define KERNEL_PHY_SPACE_SIZE (KERNEL_PT_ADDR + (KERNEL_SPACE_PT_COUNT * PT_SIZE))
#define KERNEL_PHY_SPACE_PAGE_COUNT (KERNEL_PHY_SPACE_SIZE / PAGE_SIZE)
#define KERNEL_VM_SIZE (KERNEL_SPACE_SIZE - KERNEL_PHY_SPACE_SIZE)
#define KERNEL_VM_PAGE_COUNT (KERNEL_VM_SIZE / PAGE_SIZE)
/* ----------------------- */
/* Configation statique */
#define KERNEL_PD_ADDR 0x303000
#define KERNEL_PT_ADDR 0x304000
#define PD_SIZE 4096
#define PT_SIZE 4096
#define PAGE_SIZE 4096
#define MAX_PT_COUNT 1024
#define MAX_PAGE_COUNT 1048576
#define PAGE_OFFSET_BITS 12
#define PAGE_PER_PT 1024
/* ----------------------- */
/* Special types */
typedef T_dword T_page;
typedef T_Page* T_pageTable;
typedef T_pageTable* T_pageDir;
/* ----------------------- */
#ifdef MEMORY_PRIVATE
T_PageDirectory kpageDir;
T_PageTable kageTable;
unsigned int KernPageTableMutex;
#endif
void kinitSpace();
unsigned int kaddPage(T_Page);
void kremovePage(T_Page);
T_Page kgetPage();
void* kgetPhyAddr(void*);
/* ##################################### */
/* ###### Segment Management ###### */
#define GDT_BASE 0x200000
#define SEG_DESC_SIZE 8
#define SEG_DESC_NUMBER 256
#define MAIN_KERNEL_STACK 0xA0000
#define TSS_BASE 0x201000
struct MemSegDescriptor
{
bits16 limite0_15;
bits16 base0_15;
bits8 base16_23;
bits8 acces;
bits8 limite16_19:4;
bits8 other:4;
bits8 base24_31;
}__attribute__((packed));
struct GdtReg
{
bits16 limite;
bits32 base;
}__attribute__((packed));
struct TaskStateSegment
{
bits16 prevTask;
bits16 reserved_1;
bits32 esp0;
bits16 ss0;
bits16 reserved_2;
bits32 esp1;
bits16 ss1;
bits16 reserved_3;
bits32 esp2;
bits16 ss2;
bits16 reserved_4;
bits32 cr3;
bits32 eip;
bits32 eflags;
bits32 eax;
bits32 ecx;
bits32 edx;
bits32 ebx;
bits32 esp;
bits32 ebp;
bits32 esi;
bits32 edi;
bits16 es;
bits16 reserved_5;
bits16 cs;
bits16 reserved_6;
bits16 ss;
bits16 reserved_7;
bits16 ds;
bits16 reserved_8;
bits16 fs;
bits16 reserved_9;
bits16 gs;
bits16 reserved_10;
bits16 ldtSegSelect;
bits16 reserved_11;
bits16 flagDebug;
bits16 io_map;
}__attribute__((packed));
/* Special types */
typedef struct MemSegDescriptor T_GdtDesc;
typedef struct GdtReg T_GDT;
typedef struct TaskStateSegment T_TSS;
/* ----------------------- */
T_TSS *tss;
void InitGDT();
void CreateSegDescriptor(bits32, bits32, bits8, bits8, unsigned int);
/* ##################################### */
/* ###### Page Management ###### */
#ifdef MEMORY_PRIVATE
#define PHY_PAGE_MAP_ADDR 0x203000
#define PAGE_FREE 0
#define PAGE_USED 1
#define PAGE_NOT_PRESENT 4
bits8 *PageMap;
unsigned int PhyPageMapMutex;
#endif
#define PAGE_FLAG_PRESENT 1
#define PAGE_FLAG_RW 2
#define PAGE_FLAG_USER 4
T_Page GetPhyPage();
void ReleasePhyPage(T_Page);
/* ##################################### */
/* ###### Alloc Management ###### */
#ifdef MEMORY_PRIVATE
#define FREE 0
#define USED 1
unsigned int KERNEL_HEAP_BASE;
unsigned int KERNEL_HEAP_LIMIT;
struct AllocAreaModel {
T_byte state; /* 1:used 0:free */
struct AllocAreaModel *next;
}__attribute__((packed));
unsigned int AllocMutex;
#endif
void* malloc(unsigned int);
void free(void*);
struct AllocAreaModel* EnlargeHeap();
/* ##################################### */
/* ###### Paging Management ###### */
T_PageDirectory CreateTaskPageDirectory();
void DestroyTaskPageDirectory(T_PageDirectory);
unsigned int AddPage(T_Page, bits32);
void RemovePage(T_Page);
unsigned int LinkPhyPage(T_Page, T_Page, bits32);
void UnlinkPhyPage(T_Page);
void* GetPhyAddr(void*);
/* ##################################### */
#endif

58
kernel/include/print.h Normal file
View File

@ -0,0 +1,58 @@
/* print.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef PRINT_H
#define PRINT_H
#include <stdarg.h>
#include "types.h"
#define TEXTCOLOR_BLACK 0x0
#define TEXTCOLOR_DARK_BLUE 0x1
#define TEXTCOLOR_DARK_GREEN 0x2
#define TEXTCOLOR_DARK_CYAN 0x3
#define TEXTCOLOR_DARK_RED 0x4
#define TEXTCOLOR_DARK_MAGENTA 0x5
#define TEXTCOLOR_DARK_BROWN 0x6
#define TEXTCOLOR_DARK_GRAY 0x8
#define TEXTCOLOR_LIGHT_GRAY 0x7
#define TEXTCOLOR_LIGHT_BLUE 0x9
#define TEXTCOLOR_LIGHT_GREEN 0xA
#define TEXTCOLOR_LIGHT_CYAN 0xB
#define TEXTCOLOR_LIGHT_RED 0xC
#define TEXTCOLOR_LIGHT_MAGENTA 0xD
#define TEXTCOLOR_LIGHT_YELLOW 0xE
#define TEXTCOLOR_WHITE 0xF
#define BACK_BLUE 0x1
#define BACK_GREEN 0x2
#define BACK_CYAN 0x3
#define BACK_RED 0x4
#define BACK_MAGENTA 0x5
#define BACK_BROWN 0x6
#define BACK_GRAY 0x7
void printError(char*, ...);
void print(char*, ...);
void printColor(char*, T_byte, ...);
#endif

126
kernel/include/process.h Normal file
View File

@ -0,0 +1,126 @@
/* process.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef PROCESS_H
#define PROCESS_H
#include "types.h"
#include "memory.h"
#include "utils.h"
#include "ipc.h"
#define USER_SPACE_BASE_ADDR (KERNEL_SPACE_SIZE)
#define USER_STACK_ADDR 0xFFBFF000
#define USER_SPACE_END_ADDR 0xFFBFE000
#define PROCESS_STATUS_RUNNING 0
#define PROCESS_STATUS_WAIT_MUTEX 1
#define PROCESS_STATUS_SLEEP 2
#define PROCESS_STATUS_ZOMBIE 3
struct ProcessModel
{
struct ProcessModel* next; /* 0 */
struct ProcessModel* prev; /* 4 */
bits32 reg_EAX; /* 8 */
bits32 reg_EBX; /* 12 */
bits32 reg_ECX; /* 16 */
bits32 reg_EDX; /* 20 */
bits32 reg_ESI; /* 24 */
bits32 reg_EDI; /* 28 */
bits32 reg_EBP; /* 32 */
bits32 reg_ESP; /* 36 */
bits32 reg_EIP; /* 40 */
bits32 reg_EFLAGS; /* 44 */
bits16 reg_CS; /* 48 */
bits16 reg_DS; /* 50 */
bits16 reg_ES; /* 52 */
bits16 reg_FS; /* 54 */
bits16 reg_GS; /* 56 */
bits16 reg_SS; /* 58 */
bits32 reg_CR3; /* 60 */
bits32 kernelStackPtr;
T_PageDirectory pageDir;
T_LinkedList processRegionsList;
unsigned int pid;
struct ProcessModel* parent;
T_LinkedList processChildrenList;
unsigned int signal;
void* signalAction[32];
bits8 status; /* 0:actif 1:wait mutex 2:sleep 3:zombie */
unsigned int* ipcWaitMutex;
unsigned int ipcInSection;
};
typedef struct ProcessModel T_Process;
#ifdef PROCESS_PRIVATE
#define PROCESS_REGION_RO 0
#define PROCESS_REGION_RW 1
#define PROCESS_REGION_HEAP 3
struct ProcessRegion
{
struct ProcessRegion* next;
struct ProcessRegion* prev;
T_Page startPage;
T_Page endPage;
unsigned char type;
};
struct ProcessChild
{
struct ProcessChild* next;
struct ProcessChild* prev;
T_Process* process;
};
unsigned int PidCounter;
#endif
T_LinkedList Processes;
T_Process* CurrentProcess;
T_Process Process_0;
void InitProcessManager();
unsigned int CreateProcess(void*);
/* Fonctions éxécutées par le processus lui meme */
void DestroyProcess();
unsigned int ProcessCreateRegion_RO(T_Page, T_Page*, unsigned int, T_LinkedList*);
unsigned int ProcessCreateRegion_RW(T_Page, unsigned int, T_LinkedList*);
void ProcessRemoveRegion(T_Page, unsigned int, T_LinkedList*);
/* ############################################# */
/* Fonctions d'ordonnancement */
void _LoadContext(T_Process*);
bits32* _SaveContex();
T_Process* SchedulingAlgorithm();
void Schedule();
void ScheduleAtClock();
/* ############################################# */
#endif

40
kernel/include/signal.h Normal file
View File

@ -0,0 +1,40 @@
/* signal.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef SIGNAL_H
#define SIGNAL_H
#include "process.h"
/* Du plus important au moins important */
#define SIGNAL_KILL 0
#define SIGNAL_TERM 1
#define SIGNAL_KCHILD 2
void SendSignal(unsigned int, T_Process*);
void ClearSignal(unsigned int, T_Process*);
unsigned int FetchSignal(unsigned int, T_Process*);
void HandleSignal(unsigned int, T_Process*);
#endif

31
kernel/include/types.h Normal file
View File

@ -0,0 +1,31 @@
/* types.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef TYPES_H
#define TYPES_H
typedef unsigned char T_byte;
typedef unsigned short T_word;
typedef unsigned int T_dword;
#endif

57
kernel/include/utils.h Normal file
View File

@ -0,0 +1,57 @@
/* utils.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef UTILS_H
#define UTILS_H
#include "types.h"
void memcopy(char*, char*, unsigned int);
int strcmp(char*, char*);
void IntToChar(bits32, char*, int);
unsigned int expo(unsigned int, unsigned int);
struct List
{
unsigned int entryCount;
struct ElementModel *firstEntry;
struct ElementModel *lastEntry;
};
typedef struct List T_LinkedList;
struct ElementModel
{
struct ElementModel *next;
struct ElementModel *prev;
}__attribute__((packed));
void LinkedListPushFront(void*, T_LinkedList*);
void LinkedListPopFront(T_LinkedList*);
void LinkedListPushBack(void*, T_LinkedList*);
void LinkedListPopBack(T_LinkedList*);
void LinkedListInsert(void*, void*, void*, T_LinkedList*);
void LinkedListRemove(void*, T_LinkedList*);
void InsertElement(void*, void*, void*);
void RemoveElement(void*);
#endif

77
kernel/src/asm/io.asm Normal file
View File

@ -0,0 +1,77 @@
; io_port.asm - This file is a part of NutsOS
; NutsOS
; Copyright (C) 2013 Free Software Foundation, Inc.
; NutsOS is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
; NutsOS is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License along
; with NutsOS; If not, see <http://www.gnu.org/licenses/>.
; Valentin Verdier <valentin.verdier03@gmail.com>
[BITS 32]
[SECTION .text]
global _out, _in, _outw, _inw, _outdw, _indw
_out:
push eax
push edx
mov dx, [esp+12]
mov al, [esp+16]
out dx, al
pop edx
pop eax
ret
_in:
push edx
xor eax, eax
mov dx, [esp+8]
in al, dx
pop edx
ret
_outw:
push eax
push edx
mov dx, [esp+12]
mov ax, [esp+16]
out dx, ax
pop edx
pop eax
ret
_inw:
push edx
xor eax, eax
mov dx, [esp+8]
in ax, dx
pop edx
ret
_outdw:
push eax
push edx
mov dx, [esp+12]
mov eax, [esp+16]
out dx, eax
pop edx
pop eax
ret
_indw:
push edx
mov dx, [esp+8]
in eax, dx
pop edx
ret

94
kernel/src/asm/isr.asm Normal file
View File

@ -0,0 +1,94 @@
; isr.asm - This file is a part of NutsOS
; NutsOS
; Copyright (C) 2013 Free Software Foundation, Inc.
; NutsOS is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
; NutsOS is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License along
; with NutsOS; If not, see <http://www.gnu.org/licenses/>.
; Valentin Verdier <valentin.verdier03@gmail.com>
[BITS 32]
[SECTION .text]
extern IsrDefault, IsrGPFault, IsrSegFault, IsrPageFault, IsrClock, IsrKeyboard, ExecSystemCall, PIC_Send_EOI
global _DefaultInterrupt, _SEG_Fault, _GP_Fault, _Page_Fault, _KeyboardInterrupt, _ClockInterrupt, _SystemCall
%macro REGS_SAVE 0
pushad
push ds
push es
push fs
push gs
push ebx
mov bx, 0x10
mov ds, bx
pop ebx
%endmacro
%macro REGS_RESTORE 0
pop gs
pop fs
pop es
pop ds
popad
%endmacro
_DefaultInterrupt:
REGS_SAVE
call IsrDefault
call PIC_Send_EOI
REGS_RESTORE
iret
_SEG_Fault:
REGS_SAVE
call IsrSegFault
REGS_RESTORE
iret
_GP_Fault:
REGS_SAVE
call IsrGPFault
REGS_RESTORE
add esp, 4 ; Pour le décalage créé par le code d'erreur dans la pile
iret
_Page_Fault:
REGS_SAVE
call IsrPageFault
REGS_RESTORE
add esp, 4 ; Pour le décalage créé par le code d'erreur dans la pile
iret
_KeyboardInterrupt:
REGS_SAVE
call IsrKeyboard
call PIC_Send_EOI
REGS_RESTORE
iret
_ClockInterrupt:
REGS_SAVE
call IsrClock
call PIC_Send_EOI
REGS_RESTORE
iret
_SystemCall:
REGS_SAVE
push eax
call ExecSystemCall
pop eax
REGS_RESTORE
iret

88
kernel/src/asm/sched.asm Normal file
View File

@ -0,0 +1,88 @@
; sched.asm - This file is a part of NutsOS
; NutsOS
; Copyright (C) 2013 Free Software Foundation, Inc.
; NutsOS is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
; NutsOS is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License along
; with NutsOS; If not, see <http://www.gnu.org/licenses/>.
; Valentin Verdier <valentin.verdier03@gmail.com>
[BITS 32]
[SECTION .text]
global _LoadContext, _SaveContex
_SaveContex:
pushfd
pushad
push dword ds
push dword es
push dword fs
push dword gs
mov eax, [esp + 52] ; On retrouve l'adresse de retour empilée lors de l'appel
push eax ; eip ret
mov eax, esp
add eax, 4
ret
_LoadContext:
mov esi, [esp + 4]
mov ax, [esi + 48] ; cs
cmp ax, 0x08
je .kernMode
.userMode:
mov ax, 0x18
mov ss, ax
mov esp, [esi + 64] ; Kstack_ptr
push dword [esi + 58] ; ss
push dword [esi + 36] ; esp
jmp .next
.kernMode:
mov ax, [esi + 58] ; ss
mov ss, ax
mov esp, [esi + 36] ; esp
.next:
push dword [esi + 44] ; eflags
push dword [esi + 48] ; cs
push dword [esi + 40] ; eip
push dword [esi + 8] ; eax
push dword [esi + 12] ; ebx
push dword [esi + 16] ; ecx
push dword [esi + 20] ; edx
push dword [esi + 24] ; esi
push dword [esi + 28] ; edi
push dword [esi + 32] ; ebp
push dword [esi + 50] ; ds
push dword [esi + 52] ; es
push dword [esi + 54] ; fs
push dword [esi + 56] ; gs
mov eax, [esi + 60]
mov cr3, eax
pop gs
pop fs
pop es
pop ds
pop ebp
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
iret

133
kernel/src/asm/syslib.asm Normal file
View File

@ -0,0 +1,133 @@
; asm_utils.asm - This file is a part of NutsOS
; NutsOS
; Copyright (C) 2013 Free Software Foundation, Inc.
; NutsOS is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
; NutsOS is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License along
; with NutsOS; If not, see <http://www.gnu.org/licenses/>.
; Valentin Verdier <valentin.verdier03@gmail.com>
[BITS 32]
[SECTION .text]
global _ClearInterrupt, _StartInterrupt, _EnablePaging, _LoadGdtR, _LoadIdtR, _LoadTaskRegister, _EmptyTLB, _LoadCr3, _ReadCr3, _ReadCr2, _SaveEflags, _RestoreEflags, _GetStackFrameAddr, _AtomicTestAndSet
_ClearInterrupt:
cli
ret
_StartInterrupt:
sti
ret
_EnablePaging:
push eax
mov eax, 0x303000
mov cr3, eax
mov eax, cr0
or eax, 0x80000000
mov cr0, eax
pop eax
ret
_LoadGdtR:
mov eax, [esp+4]
lgdt [eax]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ax, 0x18
mov ss, ax
jmp 0x08:.next
.next:
ret
_LoadIdtR:
push eax
mov eax, [esp+8]
lidt [eax]
pop eax
ret
_LoadTaskRegister:
push ax
mov ax, 0x38
ltr ax
pop ax
ret
_EmptyTLB:
push eax
mov eax, cr3
mov cr3, eax
pop eax
ret
_LoadCr3:
push eax
mov eax, [esp+8]
mov cr3, eax
pop eax
ret
_ReadCr3:
mov eax, cr3
ret
_ReadCr2:
mov eax, cr2
ret
_SaveEflags:
pushfd
pop eax
ret
_RestoreEflags:
push eax
mov eax, [esp+8]
push eax
popfd
pop eax
ret
_AtomicTestAndSet:
push ebx
push edx
xor eax, eax
mov edx, 1
mov ebx, [esp + 12]
lock cmpxchg [ebx], edx
pop edx
pop ebx
ret
_GetStackFrameAddr:
push ebx
push ecx
mov ecx, [esp + 12]
mov ebx, ebp
.loopTop:
cmp ecx, 0
je .loopEnd
mov eax, [ebx]
mov ebx, eax
dec ecx
jmp .loopTop
.loopEnd:
mov eax, ebx
pop ecx
pop ebx
ret

222
kernel/src/elf_loader.c Normal file
View File

@ -0,0 +1,222 @@
/* elf_loader.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#define ELF_LOADER_PRIVATE
#include "elf_loader.h"
#include "types.h"
#include "print.h"
#include "utils.h"
#include "memory.h"
#include "process.h"
/* Index dans id[] */
#define ID_MAG_0 0
#define ID_MAG_1 1
#define ID_MAG_2 2
#define ID_MAG_3 3
#define ID_CLASS 4
#define ID_DATA 5
#define ID_VERSION 6
#define ID_PAD 7
/* Classes ELF */
#define ELF_CLASS_NONE 0
#define ELF_CLASS_32 1
#define ELF_CLASS_64 2
/* Encodage des données */
#define ELF_DATA_NONE 0
#define ELF_DATA_LSB 1
#define ELF_DATA_MSB 2
/* Types de fichier ELF */
#define ELF_TYPE_NONE 0
#define ELF_TYPE_RELOC 1
#define ELF_TYPE_EXEC 2
#define ELF_TYPE_DYN 3
#define ELF_TYPE_CORE 4
/* Version */
#define ELF_VERSION_NONE 0
#define ELF_VERSION_CURRENT 1
/* Architectures cible */
#define ELF_ARCH_NONE 0
#define ELF_ARCH_M32 1
#define ELF_ARCH_SPARC 2
#define ELF_ARCH_386 3
#define ELF_ARCH_68K 4
#define ELF_ARCH_88K 5
#define ELF_ARCH_860 7
#define ELF_ARCH_MIPS 8
#define ELF_ARCH_MIPS_RS4_BE 10
/* Structure de l'entête des fichier ELF32 */
typedef struct {
T_byte id[16];
T_word type;
T_word targetArch;
T_dword version;
T_dword entry;
T_dword prgHdrTblOff;
T_dword secHdrTblOff; /* Pas utilisé ici */
T_dword flags; /* Pas utilisé ici */
T_word hdrSize;
T_word prgHdrTblEntrySize;
T_word prgHdrTblEntryCount;
T_word secHdrTblEntrySize; /* Pas utilisé ici */
T_word secHdrTblEntryCount; /* Pas utilisé ici */
T_word strTblIndex; /* Pas utilisé ici */
}__attribute__((packed)) T_ELF32_hdr;
/* Types de segment */
#define ELF_SEG_NULL 0
#define ELF_SEG_LOAD 1
#define ELF_SEG_DYNAMIC 2
#define ELF_SEG_INTERP 3
#define ELF_SEG_NOTE 4
#define ELF_SEG_SHLIB 5
#define ELF_SEG_PHDR 6
/* Permissions R|W|X */
#define ELF_SEG_PERM_READ 4
#define ELF_SEG_PERM_WRITE 2
#define ELF_SEG_PERM_EXEC 1
/* Structure d'une entrée du Program header */
typedef struct {
T_dword type;
T_dword offset;
T_dword vaddr;
T_dword paddr;
T_dword sizeInFile;
T_dword sizeInMem;
T_dword flags;
T_dword align;
}__attribute__((packed)) T_ELF32_prgHdrEntry;
int ELF32_checkFile(void *file)
{
T_ELF32_hdr* elfHdr = file;
if(elfHdr->id[ID_MAG_0] != 0x7F || elfHdr->id[ID_MAG_1] != 'E' || elfHdr->id[ID_MAG_2] != 'L' || elfHdr->id[ID_MAG_3] != 'F') {
print("[ELF Loader] : The file at 0x%x is not ELF type\n", DEFAULT_COLOR, file);
return 0;
}
if(elfHdr->id[ID_CLASS] != ELF_CLASS_32) {
print("[ELF Loader] : The file at 0x%x is not a 32 bits ELF\n", DEFAULT_COLOR, file);
return 0;
}
if(elfHdr->id[ID_DATA] != ELF_DATA_LSB) {
print("[ELF Loader] : The ELF file at 0x%x has a bad encoding\n", DEFAULT_COLOR, file);
return 0;
}
if(elfHdr->type == ELF_TYPE_EXEC) {
print("[ELF Loader] : The ELF file at 0x%x is not executable\n", DEFAULT_COLOR, file);
return 0;
}
if(elfHdr->targetArch == ELF_ARCH_386) {
print("[ELF_Loader] : The ELF file at 0x%x is not a x86 executable\n", DEFAULT_COLOR, file);
return 0;
}
if(elfHdr->entry >= KERNEL_SPACE_SIZE) {
return 1;
} else {
print("[ELF_Loader] : The ELF file at 0x%x has a bad entry point\n", DEFAULT_COLOR, file);
return 0;
}
}
unsigned int ELF32_Load(void *file, T_LinkedList* regionsList)
{
if(ELF32_checkFile(file)) {
T_ELF32_hdr* elfHdr = file;
unsigned int i, sc;
for(i = 0, sc = 0; i < elfHdr->prgHdrTblEntryCount; i++, sc++) {
T_ELF32_prgHdrEntry* prgHdrEntry = file + elfHdr->prgHdrTblOff + i * elfHdr->prgHdrTblEntrySize;
if(prgHdrEntry->type == ELF_SEG_LOAD) {
if(!prgHdrEntry->sizeInMem) {
goto error;
}
T_Page segStartPage = prgHdrEntry->vaddr & 0xFFFFF000;
unsigned int pageCount = prgHdrEntry->sizeInMem & 0xFFFFF000;
if(prgHdrEntry->sizeInMem & 0x00000FFF) {
pageCount++;
}
if((prgHdrEntry->vaddr & 0x00000FFF) >= PAGE_SIZE - (prgHdrEntry->sizeInMem & 0x00000FFF)) {
pageCount++;
}
if(prgHdrEntry->flags == (ELF_SEG_PERM_READ | ELF_SEG_PERM_EXEC)) {
T_Page* pglist = malloc(sizeof(T_Page) * pageCount);
if(!pglist) {
goto error;
}
unsigned int j;
for(j = 0; j < pageCount; j++) {
pglist[j] = ((T_Page) file + prgHdrEntry->offset & 0xFFFFF000) + (j << PAGE_OFFSET_BITS);
}
if(!ProcessCreateRegion_RO(segStartPage, pglist, pageCount, regionsList)) {
free(pglist);
goto error;
}
free(pglist);
} else if(prgHdrEntry->flags == (ELF_SEG_PERM_READ | ELF_SEG_PERM_WRITE)) {
if(!ProcessCreateRegion_RW(segStartPage, pageCount, regionsList)) {
goto error;
}
unsigned int j;
for(j = 0; j < pageCount; j++) {
memcopy((char*) (((unsigned int) file + prgHdrEntry->offset & 0xFFFFF000) + (j << PAGE_OFFSET_BITS)),(char*) (segStartPage + (j << PAGE_OFFSET_BITS)), PAGE_SIZE);
}
}
}
}
return elfHdr->entry;
error:
for(i = 0; i < sc; i++) {
T_ELF32_prgHdrEntry* prgHdrEntry = file + elfHdr->prgHdrTblOff + i * elfHdr->prgHdrTblEntrySize;
if(prgHdrEntry->type == ELF_SEG_LOAD) {
T_Page segStartPage = prgHdrEntry->vaddr & 0xFFFFF000;
unsigned int pageCount;
if(prgHdrEntry->sizeInMem & 0x00000FFF) {
pageCount = (prgHdrEntry->sizeInMem & 0xFFFFF000) + 1;
}
if(prgHdrEntry->align > 0) {
pageCount++;
}
ProcessRemoveRegion(segStartPage, pageCount, regionsList);
}
}
return 0;
} else {
return 0;
}
}

165
kernel/src/interrupt.c Normal file
View File

@ -0,0 +1,165 @@
/* interrupt.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "interrupt.h"
#include "types.h"
#include "asm_x86.h"
#include "print.h"
#include "process.h"
/* ============ Configuration du PIC 8259A ============ */
void PIC_Init()
{
_out(PIC_MASTER_CMD_REG, 0x11);
_out(PIC_SLAVE_CMD_REG, 0x11);
_out(PIC_MASTER_DATA_REG, PIC_MASTER_IDT_OFFSET);
_out(PIC_SLAVE_DATA_REG, PIC_SLAVE_IDT_OFFSET);
_out(PIC_MASTER_DATA_REG, 4);
_out(PIC_SLAVE_DATA_REG, 2);
_out(PIC_MASTER_DATA_REG, 1);
_out(PIC_SLAVE_DATA_REG, 1);
_out(PIC_MASTER_DATA_REG, 0);
_out(PIC_SLAVE_DATA_REG, 0);
}
void PIC_MaskIRQ(bits8 irq)
{
bits8 mask;
if(irq < 8)
{
mask = _in(PIC_MASTER_DATA_REG) & ~(1 << irq);
_out(PIC_MASTER_DATA_REG, mask);
}
else
{
mask = _in(PIC_SLAVE_DATA_REG) & ~(1 << (irq - 8));
_out(PIC_SLAVE_DATA_REG, mask);
}
}
void PIC_Send_EOI()
{
_out(PIC_MASTER_CMD_REG, PIC_EOI);
_out(PIC_SLAVE_CMD_REG, PIC_EOI);
}
/* ===================================================== */
/* ========= Manipulation de l'IDT ========= */
void InitIDT()
{
unsigned int i;
T_IDT IdtR;
PIC_Init();
/* Initialisation de l'IDT */
for(i = 0; i < IDT_SIZE; i++)
{
CreateInterruptDescriptor((bits32) &_DefaultInterrupt, 0x08, 0x8E00, i);
}
/* Configuration de l'IDT */
CreateInterruptDescriptor((bits32) &_SEG_Fault, 0x08, 0x8E00, SEG_FAULT_INT);
CreateInterruptDescriptor((bits32) &_SEG_Fault, 0x08, 0x8E00, STACK_SEG_FAULT_INT);
CreateInterruptDescriptor((bits32) &_GP_Fault, 0x08, 0x8E00, GP_FAULT_INT);
CreateInterruptDescriptor((bits32) &_Page_Fault, 0x08, 0xEF00, PAGE_FAULT_INT);
CreateInterruptDescriptor((bits32) &_ClockInterrupt, 0x08, 0x8E00, TIMER_INT);
CreateInterruptDescriptor((bits32) &_KeyboardInterrupt, 0x08, 0x8E00, KB_INT);
CreateInterruptDescriptor((bits32) &_SystemCall, 0x08, 0xEF00, SYS_CALL_INT);
/* Pointeur sur l'IDT pour lidt */
IdtR.limite = (bits16) (INT_DESC_SIZE * IDT_SIZE);
IdtR.base = IDT_BASE;
_LoadIdtR(&IdtR);
}
void CreateInterruptDescriptor(bits32 offset, bits16 seg, bits16 type, unsigned int desc)
{
T_IdtDesc *idt = (T_IdtDesc*) IDT_BASE;
idt[desc].offset0_15 = (offset & 0xFFFF);
idt[desc].segment = seg;
idt[desc].type = type;
idt[desc].offset16_31 = (offset & 0xFFFF0000) >> 16;
}
/* ===================================================== */
/* ========== Routines d'interruption en C ============ */
void IsrDefault()
{
//print("int\n", 0x47);
return;
}
void IsrGPFault()
{
print("ERROR : X86 GENERAL PROTECTION FAULT\n", 0x47);
_ClearInterrupt();
while(1)
{
asm("hlt");
}
}
void IsrSegFault()
{
print("ERROR : X86 SEGMENTATION FAULT\n", 0x47);
_ClearInterrupt();
while(1)
{
asm("hlt");
}
}
void IsrPageFault()
{
bits32 cr2 = _ReadCr2();
/*if(CurrentProcess)
{
ProcessAddPage(cr2 & 0xFFFFF000);
}
else*/
{
print("ERROR : PAGE FAULT (ADDR = %x)\n", 0x47, cr2);
_ClearInterrupt();
while(1)
{
asm("hlt");
}
}
}
void IsrClock()
{
KBD_LedsControl(7);
ScheduleAtClock();
}
/* ========================================================= */

55
kernel/src/ipc.c Normal file
View File

@ -0,0 +1,55 @@
/* ipc.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "ipc.h"
#include "types.h"
#include "asm_x86.h"
#include "process.h"
void IPC_MutexLock(unsigned int* mutex)
{
if(CurrentProcess)
{
if(_AtomicTestAndSet(mutex))
{
CurrentProcess->ipcWaitMutex = mutex;
CurrentProcess->status = 1;
Schedule();
}
else
{
CurrentProcess->ipcInSection++;
}
}
}
void IPC_MutexUnlock(unsigned int* mutex)
{
if(CurrentProcess)
{
if(CurrentProcess->ipcInSection > 0)
{
*mutex = 0;
CurrentProcess->ipcInSection--;
}
}
}

77
kernel/src/main.c Normal file
View File

@ -0,0 +1,77 @@
/* main.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "args.h"
#include "types.h"
#include "print.h"
#include "interrupt.h"
#include "utils.h"
#include "memory.h"
#include "asm_x86.h"
#include "process.h"
void main()
{
arg = (struct ArgModel*) 0x1400;
CurrentProcess = 0;
print("\nNutsOS Kernel ( NOS-kernel32.bin build 2013-12-01 )\n", 0x6F);
print("[Kernel] useable memory -> %d Ko\n", DEFAULT_COLOR, (arg->phyMemSize / 1024));
if(arg->phyMemSize / 1024 < 10240)
{
print("ERROR : A USEABLE SYSTEM MUST HAVE MORE THAN 10 Mo", 0x47);
asm("hlt");
}
print("[Kernel] initializing memory managment...", DEFAULT_COLOR);
InitGDT();
InitKernelSpace();
_EnablePaging();
print("ok\n", 0x02);
print("[Kernel] setting up interrupts...", DEFAULT_COLOR);
InitIDT();
//setTimerDivid(11932); /* (1193181Hz / div) div = 1193 pour 1KHz, div = 11932 pour 100Hz */
print("ok\n", 0x02);
print("[Kernel] setting up processes scheduler...", DEFAULT_COLOR);
InitProcessManager();
print("ok\n", 0x02);
print("[Kernel] end of initialisation, switch to the god process\n", DEFAULT_COLOR);
CurrentProcess = &Process_0;
tss->ss0 = 0x18;
tss->esp0 = CurrentProcess->kernelStackPtr;
_LoadContext(CurrentProcess);
/*print("[Kernel] detect PCI devices...\n", DEFAULT_COLOR);
PciDetectDevices();
print("done\n", DEFAULT_COLOR);*/
/* Normalement, c'est impossible d'arriver jusque ici */
while(1)
{
asm("hlt");
}
}

790
kernel/src/memory.c Normal file
View File

@ -0,0 +1,790 @@
/* memory.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#define MEMORY_PRIVATE
#include "memory.h"
#include "types.h"
#include "print.h"
#include "args.h"
#include "asm_x86.h"
#include "ipc.h"
/* Initialise les principaux segments utilis<69>s par le kernel */
void InitGDT()
{
T_GDT GdtR;
/* Adresse du TSS en m<>moire */
tss = (T_TSS*) TSS_BASE;
/* Configuration du TSS */
tss->flagDebug = 0x00;
tss->io_map = 0x00;
tss->esp0 = MAIN_KERNEL_STACK;
tss->ss0 = 0x18;
/* Configuration de la GDT */
CreateSegDescriptor(0x0, 0x0, 0x0, 0x0, 0); /* Segment nul */
CreateSegDescriptor(0x0, 0xFFFFF, 0x9B, 0x0D, 1); /* Code noyau */
CreateSegDescriptor(0x0, 0xFFFFF, 0x93, 0x0D, 2); /* Donn<6E>es noyau */
CreateSegDescriptor(0x0, 0x0, 0x97, 0x0D, 3); /* Pile noyau */
CreateSegDescriptor(0x0, 0xFFFFF, 0xFF, 0x0D, 4); /* Code user */
CreateSegDescriptor(0x0, 0xFFFFF, 0xF3, 0x0D, 5); /* Donn<6E>es user */
CreateSegDescriptor(0x0, 0x0, 0xF7, 0x0D, 6); /* Pile user */
CreateSegDescriptor((bits32) tss, 0x67, 0xE9, 0x00, 7); /* TSS */
/* Pointeur sur GDT pour lgdt */
GdtR.limite = (bits16) (SEG_DESC_NUMBER * SEG_DESC_SIZE);
GdtR.base = GDT_BASE;
_LoadGdtR(&GdtR);
_LoadTaskRegister();
}
void CreateSegDescriptor(bits32 base, bits32 limite, bits8 acces, bits8 other, unsigned int desc)
{
T_GdtDesc *gdt = (T_GdtDesc*) GDT_BASE;
gdt[desc].limite0_15 = (limite & 0xFFFF);
gdt[desc].base0_15 = (base & 0xFFFF);
gdt[desc].base16_23 = (base & 0xFF0000) >> 16;
gdt[desc].acces = acces;
gdt[desc].limite16_19 = (limite & 0xF0000) >> 16;
gdt[desc].other = (other & 0xF);
gdt[desc].base24_31 = (base & 0xFF000000) >> 24;
}
/* Cr<43><72> l'espace virtuel lin<69>aire du noyau qui couvre 4 Go */
void InitKernelSpace()
{
bits32 i, j, page, size;
/* === On cr<63><72> l'espace d'adressage du kernel (espace physique fixe : 7184 Ko, espace virtuel dynamique : 254960 Ko, total : 256 Mo) === */
PageDirectory = (T_PageDirectory) KERNEL_PD_ADDR;
PageTable = (T_PageTable) KERNEL_PT_ADDR;
/* On initialise le PageDirectory du kernel */
for(i = 0; i < MAX_PT_COUNT; i++)
{
if(i < KERNEL_SPACE_PT_COUNT)
{
PageDirectory[i] = KERNEL_PT_ADDR + i * PT_SIZE;
PageDirectory[i] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW;
}
else
{
PageDirectory[i] = 0;
}
}
/* On initialise les tables de pages du kernel */
for(i = 0; i < KERNEL_SPACE_PAGE_COUNT; i++)
{
if(i < KERNEL_PHY_SPACE_PAGE_COUNT)
{
PageTable[i] = i * PAGE_SIZE;
PageTable[i] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW;
}
else
{
PageTable[i] = 0;
}
}
/* ============================================== */
/* ==== On initialise la table d'<27>tat des pages physiques en utilisant la Memory Map ==== */
PageMap = (bits8*) PHY_PAGE_MAP_ADDR;
for(i = 0; i < MAX_PAGE_COUNT; i++) /* Initialisation */
{
PageMap[i] = PAGE_NOT_PRESENT;
}
/* On parcout la Memory Map */
for(i = 0; i < arg->memListEntryNumber; i++)
{
/* On calcul le num<75>ro de la page de base puis la taille en nombre de page */
page = arg->memMap[i].baseAddr_1 / PAGE_SIZE;
size = arg->memMap[i].size_1 / PAGE_SIZE;
if(arg->memMap[i].size_1 % PAGE_SIZE > 0)
{
size++;
}
/* Si la zone m<>moire est utilisable */
if(arg->memMap[i].type == 1)
{
/* On parcourt la section de la table d'<27>tat correspondant <20> la zone m<>moire */
for(j = page; j < page + size; j++)
{
PageMap[j] = FREE;
}
}
}
/* =============================================================== */
/* ===== Structures d'allocation ===== */
KERNEL_HEAP_BASE = KERNEL_PHY_SPACE_PAGE_COUNT << PAGE_OFFSET_BITS;
if(!KernelAddPage(KERNEL_HEAP_BASE))
{
fatalError("MEGA ERROR OF DEATH !!");
}
KERNEL_HEAP_LIMIT = KERNEL_HEAP_BASE + PAGE_SIZE;
struct AllocAreaModel *firstArea = (struct AllocAreaModel*) KERNEL_HEAP_BASE;
firstArea->state = 0;
firstArea->next = 0;
/* ================================================================= */
PhyPageMapMutex = 0;
KernPageTableMutex = 0;
AllocMutex = 0;
}
unsigned int KernelAddPage(T_Page addr)
{
unsigned int vpage = addr >> PAGE_OFFSET_BITS;
unsigned int ret;
if(vpage < KERNEL_SPACE_PAGE_COUNT && vpage >= KERNEL_PHY_SPACE_PAGE_COUNT)
{
IPC_MutexLock(&KernPageTableMutex);
if(PageTable[vpage] == 0)
{
PageTable[vpage] = GetPhyPage();
if(PageTable[vpage])
{
PageTable[vpage] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW;
ret = 1;
}
else
{
ret = 0;
}
}
else
{
print("[KernelAddPage] vaddr = 0x%x is already used\n", 0x47, addr);
ret = 0;
}
IPC_MutexUnlock(&KernPageTableMutex);
}
else
{
print("[KernelAddPage] vaddr = 0x%x isn't in virtual kernel space\n", 0x47, addr);
ret = 0;
}
return ret;
}
void KernelRemovePage(T_Page vaddr)
{
unsigned int vpage = vaddr >> PAGE_OFFSET_BITS;
if(vpage < KERNEL_SPACE_PAGE_COUNT && vpage >= KERNEL_PHY_SPACE_PAGE_COUNT)
{
IPC_MutexLock(&KernPageTableMutex);
if(PageTable[vpage] != 0)
{
ReleasePhyPage(PageTable[vpage] & 0xFFFFF000);
PageTable[vpage] = 0;
_EmptyTLB();
}
else
{
print("[KernelRemovePage] vaddr = 0x%x is already released\n", 0x47);
}
IPC_MutexUnlock(&KernPageTableMutex);
}
else
{
print("[KernelRemovePage] vaddr = 0x%x isn't in virtual kernel space\n", 0x47);
}
}
T_Page KernelGetPage()
{
unsigned int i;
T_Page ret;
for(i = KERNEL_SPACE_PAGE_COUNT - 1; i >= KERNEL_HEAP_LIMIT >> PAGE_OFFSET_BITS; i--)
{
IPC_MutexLock(&KernPageTableMutex);
if(PageTable[i] == 0)
{
PageTable[i] = GetPhyPage();
if(PageTable[i])
{
PageTable[i] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW;
ret = i << PAGE_OFFSET_BITS;
}
else
{
ret = 0;
}
IPC_MutexUnlock(&KernPageTableMutex);
break;
}
else
{
ret = 0;
}
IPC_MutexUnlock(&KernPageTableMutex);
}
return ret;
}
void* KernelGetPhyAddr(void *vaddr)
{
unsigned int vpage = (unsigned int) vaddr >> PAGE_OFFSET_BITS;
void *ret;
if(vpage < KERNEL_SPACE_PAGE_COUNT && vpage >= KERNEL_PHY_SPACE_PAGE_COUNT)
{
IPC_MutexLock(&KernPageTableMutex);
if(PageTable[vpage])
{
ret = (void*) (PageTable[vpage] & 0xFFFFF000 | (unsigned int) vaddr & 0x00000FFF);
}
else
{
ret = 0;
}
IPC_MutexUnlock(&KernPageTableMutex);
}
else
{
ret = 0;
}
return ret;
}
T_Page GetPhyPage()
{
unsigned int i;
for(i = KERNEL_PHY_SPACE_PAGE_COUNT; i < MAX_PAGE_COUNT; i++)
{
IPC_MutexLock(&PhyPageMapMutex);
if(PageMap[i] == FREE)
{
PageMap[i] = USED;
IPC_MutexUnlock(&PhyPageMapMutex);
return i << PAGE_OFFSET_BITS;
}
IPC_MutexUnlock(&PhyPageMapMutex);
}
print("[GetPhyPage] no enough physical pages\n", 0x47);
return 0;
}
void ReleasePhyPage(T_Page addr)
{
unsigned int page = addr >> PAGE_OFFSET_BITS;
if(page >= KERNEL_PHY_SPACE_PAGE_COUNT)
{
IPC_MutexLock(&PhyPageMapMutex);
if(PageMap[page] != PAGE_NOT_PRESENT)
{
PageMap[page] = FREE;
}
else
{
print("[ReleasePhyPage] unable to release a not present page\n", 0x47);
}
IPC_MutexUnlock(&PhyPageMapMutex);
}
else
{
print("[ReleasePhyPage] unable to release a kernel physical page\n", 0x47);
}
}
void* malloc(unsigned int size)
{
IPC_MutexLock(&AllocMutex);
struct AllocAreaModel *area = (struct AllocAreaModel*) KERNEL_HEAP_BASE;
void *ptr = 0;
start:
while(area != 0)
{
if(((unsigned int) area + sizeof(struct AllocAreaModel) < KERNEL_HEAP_LIMIT))
{
if(area->next >= (struct AllocAreaModel*) KERNEL_HEAP_LIMIT)
{
fatalError("MEMORY MANAGMENT DATA STRUCTURES ARE DAMAGED");
}
if(area->state == FREE)
{
unsigned int areaBase = (unsigned int) area + sizeof(struct AllocAreaModel);
unsigned int areaSize;
if(area->next == 0)
{
areaSize = KERNEL_HEAP_LIMIT - areaBase;
}
else
{
areaSize = (unsigned int) area->next - areaBase;
}
if(areaSize == size)
{
area->state = USED;
ptr = (void*) areaBase;
break;
}
else if(areaSize > size)
{
struct AllocAreaModel *newArea = (struct AllocAreaModel*) (areaBase + size);
if(newArea + sizeof(struct AllocAreaModel) < (struct AllocAreaModel*) KERNEL_HEAP_LIMIT)
{
newArea->state = FREE;
newArea->next = area->next;
area->next = newArea;
}
else
{
area->next = 0;
}
area->state = USED;
ptr = (void*) areaBase;
break;
}
}
}
else
{
fatalError("MEMORY MANAGMENT DATA STRUCTURES ARE DAMAGED");
}
area = area->next;
}
if(!ptr)
{
area = EnlargeHeap();
if(area)
{
goto start;
}
}
/*print("MALLOC -> ", 0x04);
area = KERNEL_HEAP_BASE;
while(area)
{
print("base : 0x%x, next : 0x%x, state : %d\n", 0x04, (unsigned int) area + sizeof(struct AllocAreaModel), area->next, area->state);
area = area->next;
}*/
IPC_MutexUnlock(&AllocMutex);
return ptr;
}
void free(void *addr)
{
IPC_MutexLock(&AllocMutex);
struct AllocAreaModel *area = (struct AllocAreaModel*) KERNEL_HEAP_BASE;
while(area != 0)
{
if(area->next >= (struct AllocAreaModel*) KERNEL_HEAP_LIMIT)
{
fatalError("MEMORY MANAGMENT DATA STRUCTURES ARE DAMAGED");
}
if(area->state == USED)
{
unsigned int areaBase = (unsigned int) area + sizeof(struct AllocAreaModel);
if(areaBase == (unsigned int) addr)
{
area->state = FREE;
while(area->next != 0)
{
if(area->next >= (struct AllocAreaModel*) KERNEL_HEAP_LIMIT)
{
fatalError("MEMORY MANAGMENT DATA STRUCTURES ARE DAMAGED");
}
if(area->next->state == FREE)
{
area->next = area->next->next;
}
else
{
break;
}
}
IPC_MutexUnlock(&AllocMutex);
return;
}
}
area = area->next;
}
/*print("FREE -> ", 0x04);
area = KERNEL_HEAP_BASE;
while(area)
{
print("base : 0x%x, next : 0x%x, state : %d\n", 0x04, (unsigned int) area + sizeof(struct AllocAreaModel), area->next, area->state);
area = area->next;
}*/
fatalError("IMPOSSIBLE TO FREE MEMORY");
IPC_MutexUnlock(&AllocMutex);
}
struct AllocAreaModel* EnlargeHeap()
{
if(KernelAddPage(KERNEL_HEAP_LIMIT))
{
struct AllocAreaModel *area = (struct AllocAreaModel*) KERNEL_HEAP_BASE;
while(area->next != 0)
{
area = area->next;
}
struct AllocAreaModel *lastArea = area;
if(area->state == USED)
{
lastArea = (struct AllocAreaModel*) KERNEL_HEAP_LIMIT;
lastArea->next = 0;
lastArea->state = FREE;
area->next = lastArea;
}
KERNEL_HEAP_LIMIT += PAGE_SIZE;
return lastArea;
}
else
{
print("[EnlargeHeap] unable to enlarge kernel heap, no enough kernel pages\n", 0x47);
return 0;
}
}
T_PageDirectory CreateTaskPageDirectory()
{
/* #-----# 0xFFFFFFFF
* |-----| pageDir user
* | |
* | |
* | |
* | |
* | |
* |-----|
* | |
* #-----# espace noyau */
unsigned int i;
T_PageDirectory PageDir = (T_PageDirectory) KernelGetPage();
if(PageDir)
{
for(i = 0; i < MAX_PT_COUNT; i++) /* Initialisation du r<>pertoire de pages*/
{
PageDir[i] = 0;
}
for(i = 0; i < KERNEL_SPACE_PT_COUNT; i++) /* Construction de la partie noyau */
{
PageDir[i] = PageDirectory[i];
}
/* La table de pages 1023 couvre le PageDir et les table de pages, de 0xFFC00000 <20> 0xFFFFFFFF */
PageDir[1023] = (T_Page) KernelGetPhyAddr(PageDir);
PageDir[1023] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW;
return PageDir;
}
else
{
return 0;
}
}
void DestroyTaskPageDirectory(T_PageDirectory PageDir)
{
unsigned int i;
for(i = KERNEL_SPACE_PAGE_COUNT; i < MAX_PT_COUNT; i++)
{
if(PageDir[i])
{
ReleasePhyPage(PageDir[i] & 0xFFFFF000);
}
}
KernelRemovePage((T_Page) PageDir);
}
/* Alloue une nouvelle page physique et la fait correspondre <20> l'adresse virtuelle vaddr */
unsigned int AddPage(T_Page vaddr, bits32 perm)
{
unsigned int i;
T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000;
T_PageTable PageTableAddr;
T_PageTable PageTableVaddr;
bits32 ptNum = (vaddr & 0xFFC00000) >> 22;
bits32 pgNum = (vaddr & 0x003FF000) >> 12;
/* On regarde si la table de pages est cr<63><72>e */
if(PageDir[ptNum] == 0) /* Si elle n'<27>xiste pas */
{
/* On cr<63><72> la table de pages */
PageTableAddr = (T_PageTable) GetPhyPage(); /* Adresse physique, donc inaccessible ici */
if(PageTableAddr)
{
/* On ajoute la table de pages cr<63>e dans le r<>pertoire */
PageDir[ptNum] = (T_Page) PageTableAddr;
PageDir[ptNum] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW | PAGE_FLAG_USER;
PageTableVaddr = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); /* On acc<63>de <20> la table de pages depuis l'espace de mappage virtuel */
for(i = 0; i < 1024; i++)
{
PageTableVaddr[i] = 0;
}
PageTableVaddr[pgNum] = GetPhyPage();
if(PageTableVaddr[pgNum])
{
PageTableVaddr[pgNum] |= perm;
return 1;
}
else
{
PageDir[ptNum] = 0;
ReleasePhyPage((T_Page) PageTableAddr);
_EmptyTLB();
return 0;
}
}
else
{
return 0;
}
}
else /* Si elle <20>xiste */
{
PageTableVaddr = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); /* On acc<63>de <20> la table de pages depuis l'espace de mappage virtuel */
/* On test pour savoir si la page voulue est d<>j<EFBFBD> pr<70>sente */
if(PageTableVaddr[pgNum] == 0)
{
/* Si elle ne l'est pas on ajoute <20> la table de pages la page voulue */
PageTableVaddr[pgNum] = GetPhyPage();
if(PageTableVaddr[pgNum])
{
PageTableVaddr[pgNum] |= perm;
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
}
void RemovePage(T_Page vaddr)
{
unsigned int i;
T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000;
T_PageTable PageTable;
int empty;
bits32 ptNum = (vaddr & 0xFFC00000) >> 22;
bits32 pgNum = (vaddr & 0x003FF000) >> 12;
if(PageDir[ptNum] != 0)
{
PageTable = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE);
if(PageTable[pgNum] != 0)
{
ReleasePhyPage(PageTable[pgNum] & 0xFFFFF000);
PageTable[pgNum] = 0;
for(i = 0; i < PAGE_PER_PT; i++)
{
if(PageTable[i] == 0)
{
empty = 1;
}
else
{
empty = 0;
break;
}
}
if(empty)
{
ReleasePhyPage(PageDir[ptNum] & 0xFFFFF000);
PageDir[ptNum] = 0;
}
_EmptyTLB();
}
}
}
unsigned int LinkPhyPage(T_Page vaddr, T_Page addr, bits32 perm)
{
unsigned int i;
T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000;
T_PageTable PageTableAddr;
T_PageTable PageTableVaddr;
bits32 ptNum = (vaddr & 0xFFC00000) >> 22;
bits32 pgNum = (vaddr & 0x003FF000) >> 12;
/* On regarde si la table de pages est cr<63><72>e */
if(PageDir[ptNum] == 0) /* Si elle n'<27>xiste pas */
{
/* On cr<63><72> la table de pages */
PageTableAddr = (T_PageTable) GetPhyPage(); /* Adresse physique, donc inaccessible ici */
if(PageTableAddr)
{
/* On ajoute la table de pages cr<63>e dans le r<>pertoire */
PageDir[ptNum] = (T_Page) PageTableAddr;
PageDir[ptNum] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW | PAGE_FLAG_USER;
PageTableVaddr = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); /* On acc<63>de <20> la table de pages depuis l'espace de mappage virtuel */
for(i = 0; i < 1024; i++)
{
PageTableVaddr[i] = 0;
}
PageTableVaddr[pgNum] = addr & 0xFFFFF000;
PageTableVaddr[pgNum] |= perm;
return 1;
}
else
{
return 0;
}
}
else /* Si elle <20>xiste */
{
PageTableVaddr = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); /* On acc<63>de <20> la table de pages depuis l'espace de mappage virtuel */
/* On test pour savoir si la page voulue est d<>j<EFBFBD> pr<70>sente */
if(PageTableVaddr[pgNum] == 0)
{
/* Si elle ne l'est pas on ajoute <20> la table de pages la page voulue */
PageTableVaddr[pgNum] = addr & 0xFFFFF000;
PageTableVaddr[pgNum] |= perm;
return 1;
}
else
{
return 0;
}
}
}
void UnlinkPhyPage(T_Page vaddr)
{
unsigned int i;
T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000;
T_PageTable PageTable;
int empty;
bits32 ptNum = (vaddr & 0xFFC00000) >> 22;
bits32 pgNum = (vaddr & 0x003FF000) >> 12;
if(PageDir[ptNum] != 0)
{
PageTable = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE);
if(PageTable[pgNum] != 0)
{
PageTable[pgNum] = 0;
for(i = 0; i < PAGE_PER_PT; i++)
{
if(PageTable[i] == 0)
{
empty = 1;
}
else
{
empty = 0;
break;
}
}
if(empty)
{
ReleasePhyPage(PageDir[ptNum] & 0xFFFFF000);
PageDir[ptNum] = 0;
}
_EmptyTLB();
}
}
}
void* GetPhyAddr(void *vaddr)
{
T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000;
T_PageTable PageTable;
bits32 ptNum = ((bits32) vaddr & 0xFFC00000) >> 22;
bits32 pgNum = ((bits32) vaddr & 0x003FF000) >> 12;
bits32 offset = (bits32) vaddr & 0x00000FFF; /* Offset par rapport au d<>but de la page */
if(PageDir[ptNum] != 0)
{
PageTable = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE);
if(PageTable[pgNum] != 0)
{
return (void*) (PageTable[pgNum] & 0xFFFFF000 | offset);
}
}
return 0;
}

129
kernel/src/print.c Normal file
View File

@ -0,0 +1,129 @@
/* print.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "print.h"
#include "types.h"
#include "utils.h"
#include "asm_x86.h"
#include <stdarg.h>
static printArgs(char* str, T_byte color, va_list args) {
}
void fatalError(char *str)
{
print("FATAL ERROR : %s\n", 0x47, str);
_ClearInterrupt();
asm("hlt");
}
void putc(char c) {
}
void print(char *str, char color, ...)
{
va_list arg;
va_start(arg, color);
while(*str != 0)
{
if(*str == '%')
{
if(str[1] == 'd')
{
printDec(va_arg(arg, bits32), color);
str+=2;
}
else if(str[1] == 'x')
{
printHex(va_arg(arg, bits32), color);
str+=2;
}
else if(str[1] == 'b')
{
printBin(va_arg(arg, bits32), color);
str+=2;
}
else if(str[1] == 's')
{
print(va_arg(arg, char*), color);
str+=2;
}
else
{
PutCharVterm('%', color, VirtualTerminal_0);
str++;
}
}
else
{
putcVterm(*str, color, VirtualTerminal_0);
str++;
}
}
va_end(arg);
}
void printDec(bits32 a, char color)
{
char buffer[11];
char *str = buffer;
IntToChar(a, str, 10);
while(*str != 0)
{
PutCharVterm(*str, color, VirtualTerminal_0);
str++;
}
}
void printHex(bits32 a, char color)
{
char buffer[9];
char *str = buffer;
IntToChar(a, str, 16);
while(*str != 0)
{
PutCharVterm(*str, color, VirtualTerminal_0);
str++;
}
}
void printBin(bits32 a, char color)
{
char buffer[33];
char *str = buffer;
IntToChar(a, str, 2);
while(*str != 0)
{
PutCharVterm(*str, color, VirtualTerminal_0);
str++;
}
}

408
kernel/src/process.c Normal file
View File

@ -0,0 +1,408 @@
/* process.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#define PROCESS_PRIVATE
#include "process.h"
#include "types.h"
#include "display.h"
#include "asm_x86.h"
#include "memory.h"
#include "utils.h"
#include "args.h"
#include "elf_loader.h"
void Process_0_Task();
void InitProcessManager()
{
Process_0.pid = 0;
Process_0.reg_EAX = 0x00;
Process_0.reg_EBX = 0x00;
Process_0.reg_ECX = 0x00;
Process_0.reg_EDX = 0x00;
Process_0.reg_ESI = 0x00;
Process_0.reg_EDI = 0x00;
Process_0.reg_EBP = 0x00;
Process_0.reg_ESP = MAIN_KERNEL_STACK;
Process_0.reg_CS = 0x08;
Process_0.reg_DS = 0x10;
Process_0.reg_ES = 0x10;
Process_0.reg_FS = 0x10;
Process_0.reg_GS = 0x10;
Process_0.reg_SS = 0x18;
Process_0.reg_EIP = (bits32) &Process_0_Task;
Process_0.reg_EFLAGS = 0x200;
Process_0.pageDir = (T_PageDirectory) KERNEL_PD_ADDR;
Process_0.reg_CR3 = KERNEL_PD_ADDR;
Process_0.kernelStackPtr = MAIN_KERNEL_STACK;
/* Pas de mode user, donc pas de régions */
Process_0.processRegionsList.firstEntry = 0;
Process_0.processRegionsList.lastEntry = 0;
Process_0.processRegionsList.entryCount = 0;
Process_0.parent = 0; /* Pas de parent */
Process_0.processChildrenList.firstEntry = 0;
Process_0.processChildrenList.lastEntry = 0;
Process_0.processChildrenList.entryCount = 0;
Process_0.signal = 0;
Process_0.status = PROCESS_STATUS_RUNNING;
Process_0.ipcWaitMutex = 0;
Process_0.ipcInSection = 0;
Processes.firstEntry = 0;
Processes.lastEntry = 0;
Processes.entryCount = 0;
LinkedListPushBack(&Process_0, &Processes);
PidCounter = 1;
}
unsigned int CreateProcess(void *file)
{
unsigned int i;
/* On initialise une entrée dans la table des processus */
T_Process* process = malloc(sizeof(T_Process));
struct ProcessChild* child = malloc(sizeof(struct ProcessChild));
if(!process || !child)
{
if(child)
{
free(child);
}
if(process)
{
free(process);
}
print("[CreateProcess] unable to create process, not enough kernel memory\n", 0x47);
return 0;
}
process->pid = PidCounter;
process->status = PROCESS_STATUS_RUNNING;
process->ipcWaitMutex = 0;
process->ipcInSection = 0;
process->processRegionsList.firstEntry = 0;
process->processRegionsList.lastEntry = 0;
process->processRegionsList.entryCount = 0;
child->process = process;
process->parent = CurrentProcess;
process->processChildrenList.firstEntry = 0;
process->processChildrenList.lastEntry = 0;
process->processChildrenList.entryCount = 0;
process->signal = 0;
process->reg_EAX = 0x00;
process->reg_EBX = 0x00;
process->reg_ECX = 0x00;
process->reg_EDX = 0x00;
process->reg_ESI = 0x00;
process->reg_EDI = 0x00;
process->reg_EBP = 0x00;
process->reg_ESP = (bits32) USER_STACK_ADDR + PAGE_SIZE;
process->reg_CS = 0x23;
process->reg_DS = 0x2B;
process->reg_ES = 0x2B;
process->reg_FS = 0x2B;
process->reg_GS = 0x2B;
process->reg_SS = 0x33;
process->reg_EFLAGS = 0x200;
/* ======================================================= */
/* On créé le répertoire de pages */
process->pageDir = CreateTaskPageDirectory();
if(!process->pageDir)
{
free(process);
free(child);
print("[CreateProcess] unable to create process, not enough kernel memory\n", 0x47);
return 0;
}
process->reg_CR3 = (bits32) KernelGetPhyAddr(process->pageDir);
/* ================================================= */
/* La pile noyau */
process->kernelStackPtr = KernelGetPage();
if(!process->kernelStackPtr)
{
DestroyTaskPageDirectory(process->pageDir);
free(process);
free(child);
print("[CreateProcess] unable to create process, not enough kernel memory\n", 0x47);
return 0;
}
process->kernelStackPtr += PAGE_SIZE;
/* ================================================== */
/* On change d'espace d'adressage */
bits32 cr3 = _ReadCr3();
CurrentProcess->reg_CR3 = process->reg_CR3;
_LoadCr3(process->reg_CR3);
/* On créé la pile utilisateur */
if(!AddPage((T_Page) USER_STACK_ADDR, PAGE_FLAG_PRESENT | PAGE_FLAG_RW | PAGE_FLAG_USER))
{
CurrentProcess->reg_CR3 = cr3;
_LoadCr3(cr3);
KernelRemovePage(process->kernelStackPtr - PAGE_SIZE);
DestroyTaskPageDirectory(process->pageDir);
free(process);
free(child);
print("[CreateProcess] unable to create process, not enough memory\n", 0x47);
return 0;
}
/* ====================================================== */
process->reg_EIP = ELF32_Load(file, &process->processRegionsList);
if(!process->reg_EIP)
{
RemovePage((T_Page) USER_STACK_ADDR);
CurrentProcess->reg_CR3 = cr3;
_LoadCr3(cr3);
KernelRemovePage(process->kernelStackPtr - PAGE_SIZE);
DestroyTaskPageDirectory(process->pageDir);
free(process);
free(child);
print("[CreateProcess] unable to create process, elf error\n", 0x47);
return 0;
}
/* On restaure l'espace d'adressage */
CurrentProcess->reg_CR3 = cr3;
_LoadCr3(cr3);
/* On met à jour les tables */
PidCounter++;
LinkedListPushBack(child, &CurrentProcess->processChildrenList);
LinkedListPushBack(process, &Processes);
print("[CreateProcess] new process created with PID %d\n", DEFAULT_COLOR, process->pid);
return 1;
}
void DestroyProcess()
{
/*unsigned int i;
for(i = 0; i < ProcessNumber; i++)
{
struct ProcessModel *process = GetEntry(i, &Processes);
if(process == CurrentProcess)
{
unsigned int j;
print("Stopping process with PID %d\n", DEFAULT_COLOR, CurrentProcess->pid);
for(j = 0; j < CurrentProcess->codePageCount; j++)
{
RemovePage((bits32) USER_SPACE_BASE_ADDR + (j * PAGE_SIZE));
}
for(j = 0; j < CurrentProcess->allocatedPageCount; j++)
{
struct ProcessAllocatedPageModel *page = GetEntry(0, &CurrentProcess->allocatedPageList);
RemovePage(page->page_vaddr);
free(page);
RemoveEntry(0, &CurrentProcess->allocatedPageList);
}
RemovePage((bits32) USER_STACK_ADDR);
CurrentProcess->status = PROCESS_STATUS_ZOMBIE;
while(1)
{
asm("hlt");
}
KernelRemovePage(CurrentProcess->kernelStackPtr - PAGE_SIZE);
DestroyTaskPageDirectory(CurrentProcess->pageDir);
free(process);
bits32 eflags = _SaveEflags();
_ClearInterrupt();
RemoveEntry(i, &Processes);
ProcessNumber--;
_RestoreEflags(eflags)
}
}*/
}
void Process_0_Task()
{
print("[God] create Init process with PID 1\n", DEFAULT_COLOR);
CreateProcess((void*) arg->initProcessAddr);
while(1)
{
asm("hlt");
}
}
unsigned int ProcessCreateRegion_RO(T_Page startPage, T_Page* pglist, unsigned int pageCount, T_LinkedList* regionsList)
{
startPage &= 0xFFFFF000;
T_Page endPage = startPage + (pageCount << PAGE_OFFSET_BITS);
if(!pageCount || startPage < USER_SPACE_BASE_ADDR || startPage >= USER_SPACE_END_ADDR || endPage >= USER_SPACE_END_ADDR)
{
print("[ProcessCreateRegion_RO] invalid region location\n", 0x47);
return 0;
}
struct ProcessRegion* entry = (struct ProcessRegion*) regionsList->firstEntry;
while(entry)
{
if(endPage > entry->startPage && endPage <= entry->endPage
|| startPage >= entry->startPage && startPage < entry->endPage
|| startPage <= entry->startPage && endPage >= entry->endPage)
{
print("[ProcessCreateRegion_RO] conflict between regions\n", 0x47);
return 0;
}
entry = entry->next;
}
unsigned int i, pc;
for(i = 0, pc = 0; i < pageCount; i++, pc++)
{
if(!LinkPhyPage(startPage + (i << PAGE_OFFSET_BITS), pglist[i] & 0xFFFFF000, PAGE_FLAG_PRESENT | PAGE_FLAG_USER))
{
goto error;
}
}
struct ProcessRegion* region = malloc(sizeof(struct ProcessRegion));
if(region)
{
region->startPage = startPage;
region->endPage = endPage;
region->type = (unsigned char) PROCESS_REGION_RO;
LinkedListPushBack(region, regionsList);
return 1;
}
error:
print("[ProcessCreateRegion_RO] unable to add region\n", 0x47);
for(i = 0; i < pc; i++)
{
UnlinkPhyPage(startPage + (i << PAGE_OFFSET_BITS));
}
return 0;
}
unsigned int ProcessCreateRegion_RW(T_Page startPage, unsigned int pageCount, T_LinkedList* regionsList)
{
startPage &= 0xFFFFF000;
T_Page endPage = startPage + (pageCount << PAGE_OFFSET_BITS);
if(!pageCount || startPage < USER_SPACE_BASE_ADDR || startPage >= USER_SPACE_END_ADDR || endPage >= USER_SPACE_END_ADDR)
{
print("[ProcessCreateRegion_RW] invalid region location\n", 0x47);
return 0;
}
struct ProcessRegion* entry = (struct ProcessRegion*) regionsList->firstEntry;
while(entry)
{
if(endPage > entry->startPage && endPage <= entry->endPage
|| startPage >= entry->startPage && startPage < entry->endPage
|| startPage <= entry->startPage && endPage >= entry->endPage)
{
print("[ProcessCreateRegion_RW] conflict between regions\n", 0x47);
return 0;
}
entry = entry->next;
}
unsigned int i, pc;
for(i = 0, pc = 0; i < pageCount; i++, pc++)
{
if(!AddPage(startPage + (i << PAGE_OFFSET_BITS), PAGE_FLAG_PRESENT | PAGE_FLAG_RW | PAGE_FLAG_USER))
{
goto error;
}
}
struct ProcessRegion* region = malloc(sizeof(struct ProcessRegion));
if(region)
{
region->startPage = startPage;
region->endPage = endPage;
region->type = (unsigned char) PROCESS_REGION_RW;
LinkedListPushBack(region, regionsList);
return 1;
}
error:
print("[ProcessCreateRegion_RW] unable to add region\n", 0x47);
for(i = 0; i < pc; i++)
{
RemovePage(startPage + (i << PAGE_OFFSET_BITS));
}
return 0;
}
void ProcessRemoveRegion(T_Page startPage, unsigned int pageCount, T_LinkedList* regionsList)
{
startPage &= 0xFFFFF000;
T_Page endPage = startPage + (pageCount << PAGE_OFFSET_BITS);
struct ProcessRegion* entry = (struct ProcessRegion*) regionsList->firstEntry;
while(entry)
{
if(startPage == entry->startPage && endPage == entry->endPage)
{
unsigned int i;
if(entry->type == PROCESS_REGION_RO)
{
for(i = 0; i < pageCount; i++)
{
UnlinkPhyPage(startPage + (i << PAGE_OFFSET_BITS));
}
LinkedListRemove(entry, regionsList);
free(entry);
break;
}
else if(entry->type == PROCESS_REGION_RW)
{
for(i = 0; i < pageCount; i++)
{
RemovePage(startPage + (i << PAGE_OFFSET_BITS));
}
LinkedListRemove(entry, regionsList);
free(entry);
break;
}
}
entry = entry->next;
}
}

173
kernel/src/scheduler.c Normal file
View File

@ -0,0 +1,173 @@
/* scheduler.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "process.h"
#include "types.h"
#include "asm_x86.h"
#include "interrupt.h"
#include "signal.h"
T_Process* SchedulingAlgorithm()
{
T_Process *process = CurrentProcess;
do
{
if(process->next)
{
process = process->next;
}
else
{
process = (T_Process*) Processes.firstEntry;
}
if(process != CurrentProcess)
{
unsigned int i;
for(i = 0; i < 32; i++)
{
if(FetchSignal(i, process))
{
HandleSignal(i, process);
break;
}
}
if(process->status == PROCESS_STATUS_RUNNING)
{
return process;
}
else if(process->status == PROCESS_STATUS_WAIT_MUTEX) /* Si on attend un mutex */
{
/* On regard son etat */
if(!(*process->ipcWaitMutex))
{
process->status = PROCESS_STATUS_RUNNING;
*process->ipcWaitMutex = 1;
process->ipcWaitMutex = 0;
process->ipcInSection++;
return process;
}
}
/*else if(process->status == PROCESS_STATUS_SLEEP) si le processus est en sommeil
{
On regard si un wakeup à été envoyé
}*/
}
else
{
break;
}
}while(1);
if(Process_0.status == PROCESS_STATUS_RUNNING)
{
return &Process_0;
}
else
{
return CurrentProcess;
}
}
void Schedule()
{
bits32 *context = _SaveContex();
bits32 *curStackFrame = (bits32*) _GetStackFrameAddr(0);
_ClearInterrupt();
CurrentProcess->reg_GS = (bits16) context[0];
CurrentProcess->reg_FS = (bits16) context[1];
CurrentProcess->reg_ES = (bits16) context[2];
CurrentProcess->reg_DS = (bits16) context[3];
CurrentProcess->reg_EDI = context[4];
CurrentProcess->reg_ESI = context[5];
CurrentProcess->reg_EBP = curStackFrame[0]; /* ebp de la fonction précédente */
CurrentProcess->reg_EBX = context[8];
CurrentProcess->reg_EDX = context[9];
CurrentProcess->reg_ECX = context[10];
CurrentProcess->reg_EAX = context[11];
CurrentProcess->reg_EIP = curStackFrame[1]; /* eip de retour */
CurrentProcess->reg_CS = 0x08;
CurrentProcess->reg_EFLAGS = (context[12] | 0x200) & 0xFFFFBFFF;
CurrentProcess->reg_ESP = (bits32) &curStackFrame[2];
CurrentProcess->reg_SS = 0x18;
CurrentProcess = SchedulingAlgorithm();
tss->ss0 = 0x18;
tss->esp0 = CurrentProcess->kernelStackPtr;
_LoadContext(CurrentProcess);
}
void ScheduleAtClock()
{
if(!CurrentProcess && Processes.entryCount > 0)
{
CurrentProcess = (T_Process*) Processes.firstEntry;
}
else if(Processes.entryCount <= 1)
{
return;
}
else if(Processes.entryCount > 1)
{
bits32 *context = (bits32*) (_GetStackFrameAddr(1) + 8);
/* Registre empilés manuellement */
CurrentProcess->reg_GS = (bits16) context[0];
CurrentProcess->reg_FS = (bits16) context[1];
CurrentProcess->reg_ES = (bits16) context[2];
CurrentProcess->reg_DS = (bits16) context[3];
CurrentProcess->reg_EDI = context[4];
CurrentProcess->reg_ESI = context[5];
CurrentProcess->reg_EBP = context[6];
/* ESP context[7] inutile */
CurrentProcess->reg_EBX = context[8];
CurrentProcess->reg_EDX = context[9];
CurrentProcess->reg_ECX = context[10];
CurrentProcess->reg_EAX = context[11];
/* registres empliés automatiquement */
CurrentProcess->reg_EIP = context[12];
CurrentProcess->reg_CS = (bits16) context[13];
CurrentProcess->reg_EFLAGS = (context[14] | 0x200) & 0xFFFFBFFF;
if(CurrentProcess->reg_CS == 0x08)
{
CurrentProcess->reg_ESP = (bits32) &context[15];
CurrentProcess->reg_SS = 0x18;
}
else
{
CurrentProcess->reg_ESP = context[15];
CurrentProcess->reg_SS = (bits16) context[16];
}
CurrentProcess = SchedulingAlgorithm();
}
tss->ss0 = 0x18;
tss->esp0 = CurrentProcess->kernelStackPtr;
PIC_Send_EOI();
_LoadContext(CurrentProcess);
}

79
kernel/src/signal.c Normal file
View File

@ -0,0 +1,79 @@
/* signal.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "signal.h"
#include "process.h"
void SendSignal(unsigned int num, T_Process* process)
{
if(num < 32)
{
process->signal |= (1 << num);
}
}
void ClearSignal(unsigned int num, T_Process* process)
{
if(num < 32)
{
process->signal &= ~(1 << num);
}
}
unsigned int FetchSignal(unsigned int num, T_Process* process)
{
if(num < 32)
{
if(process->signal & (1 << num))
{
return 1;
}
else
{
return 0;
}
}
}
void HandleSignal(unsigned int signal, T_Process* process)
{
switch(signal)
{
case SIGNAL_KILL:
print("Process with PID %d received the signal 0 (KILL)\n", DEFAULT_COLOR, process->pid);
break;
case SIGNAL_TERM:
print("Process with PID %d received the signal 1 (TERM)\n", DEFAULT_COLOR, process->pid);
break;
case SIGNAL_KCHILD:
print("Process with PID %d received the signal 2 (KCHILD)\n", DEFAULT_COLOR, process->pid);
break;
default:
print("Process with PID %d received an unknown signal\n", DEFAULT_COLOR, process->pid);
break;
}
ClearSignal(signal, process);
}

72
kernel/src/systemCall.c Normal file
View File

@ -0,0 +1,72 @@
/* systemCall.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "types.h"
#include "print.h"
#include "process.h"
#include "asm_x86.h"
void ExecSystemCall(int sc_num)
{
bits8 *arg;
int i;
unsigned int a = 1;
switch(sc_num)
{
case 1:
asm("mov %%ebx, %0" :: "m" (arg));
PutCharVterm(*arg, 0x0F, CurrentProcess->vterm);
break;
case 2:
asm("mov %%ebx, %0" :: "m" (arg));
ReadInputVterm(arg, CurrentProcess->vterm);
break;
case 3:
/*asm("mov %%ebx, %0" :: "m" (arg));
if(!CreateProcess(arg, 1))
{
CurrentProcess->status = 2;
Schedule();
}*/
break;
case 4:
DestroyProcess();
case 5:
CurrentProcess->status = 2;
Schedule();
/*while(CurrentProcess->status == 2)
{
asm("hlt");
}*/
break;
default:
print("ERREUR : UNKNOW SYSTEM CALL !\n", 0x47);
_ClearInterrupt();
asm("hlt");
break;
}
return;
}

321
kernel/src/utils.c Normal file
View File

@ -0,0 +1,321 @@
/* utils.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "utils.h"
#include "types.h"
#include "asm_x86.h"
void memcopy(char *src, char *dst, unsigned int n)
{
unsigned int i;
for(i = 0; i < n; i++)
{
dst[i] = src[i];
}
}
int strcmp(char *str1, char *str2)
{
unsigned int i;
int length1 = 0;
int length2 = 0;
while(str1[length1] != 0)
{
length1++;
}
while(str2[length2] != 0)
{
length2++;
}
if(length1 == length2)
{
for(i = 0; i < length1; i++)
{
if(str1[i] != str2[i])
{
return 0;
}
}
}
else
{
return 0;
}
return 1;
}
void IntToChar(bits32 num, char *str, int base)
{
const char digit[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
int i, j, a;
int length;
int tmp = 0;
int counter = 0;
for(i = 0; i < 10; i++)
{
if(num / expo(base, i) < base)
{
length = i;
break;
}
}
j = length;
for(i = 0; i <= length; i++)
{
a = num / expo(base, j);
str[counter] = digit[a - base * tmp];
tmp = a;
counter++;
j--;
}
str[counter] = 0;
}
unsigned int expo(unsigned int x, unsigned int y)
{
if(y > 0)
{
unsigned int i, res = x;
for(i = 1; i < y; i++)
{
res *= x;
}
return res;
}
else
{
return 1;
}
}
void LinkedListPushFront(void *addr, T_LinkedList *list)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *entry = addr;
if(list->entryCount > 0)
{
InsertElement(0, entry, list->firstEntry);
}
else
{
InsertElement(0, entry, 0);
list->lastEntry = entry;
}
list->firstEntry = entry;
list->entryCount++;
_RestoreEflags(eflags);
}
void LinkedListPopFront(T_LinkedList *list)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *nextEntry = list->firstEntry->next;
if(list->entryCount > 1)
{
RemoveElement(list->firstEntry);
list->firstEntry = nextEntry;
}
else
{
list->firstEntry = 0;
list->lastEntry = 0;
}
list->entryCount--;
_RestoreEflags(eflags);
}
void LinkedListPushBack(void *addr, T_LinkedList *list)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *entry = addr;
if(list->entryCount > 0)
{
InsertElement(list->lastEntry, entry, 0);
}
else
{
InsertElement(0, entry, 0);
list->firstEntry = entry;
}
list->lastEntry = entry;
list->entryCount++;
_RestoreEflags(eflags);
}
void LinkedListPopBack(T_LinkedList *list)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *previousEntry = list->lastEntry->prev;
if(list->entryCount > 1)
{
RemoveElement(list->lastEntry);
list->lastEntry = previousEntry;
}
else
{
list->firstEntry = 0;
list->lastEntry = 0;
}
list->entryCount--;
_RestoreEflags(eflags);
}
void LinkedListInsert(void *prev, void *addr, void *next, T_LinkedList *list)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *previousEntry = prev;
struct ElementModel *entry = addr;
struct ElementModel *nextEntry = next;
if(nextEntry == list->firstEntry)
{
LinkedListPushFront(entry, list);
}
else if(previousEntry == list->lastEntry)
{
LinkedListPushBack(entry, list);
}
else
{
InsertElement(previousEntry, entry, nextEntry);
list->entryCount++;
}
_RestoreEflags(eflags);
}
void LinkedListRemove(void *addr, T_LinkedList *list)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *entry = addr;
if(entry == list->firstEntry)
{
LinkedListPopFront(list);
}
else if(entry == list->lastEntry)
{
LinkedListPopBack(list);
}
else
{
RemoveElement(entry);
list->entryCount--;
}
_RestoreEflags(eflags);
}
void InsertElement(void *prev, void *addr, void *next)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *previousEntry = prev;
struct ElementModel *entry = addr;
struct ElementModel *nextEntry = next;
if(previousEntry)
{
entry->prev = previousEntry;
previousEntry->next = entry;
}
else
{
entry->prev = 0;
}
if(nextEntry)
{
entry->next = nextEntry;
nextEntry->prev = entry;
}
else
{
entry->next = 0;
}
_RestoreEflags(eflags);
}
void RemoveElement(void *addr)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *entry = addr;
struct ElementModel *previousEntry = entry->prev;
struct ElementModel *nextEntry = entry->next;
if(previousEntry)
{
if(nextEntry)
{
previousEntry->next = nextEntry;
}
else
{
previousEntry->next = 0;
}
}
if(nextEntry)
{
if(previousEntry)
{
nextEntry->prev = previousEntry;
}
else
{
nextEntry->prev = 0;
}
}
_RestoreEflags(eflags);
}