Commit initial
This commit is contained in:
39
kernel/Makefile
Normal file
39
kernel/Makefile
Normal 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
50
kernel/include/args.h
Normal 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
51
kernel/include/asm_x86.h
Normal 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
|
32
kernel/include/elf_loader.h
Normal file
32
kernel/include/elf_loader.h
Normal 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
|
99
kernel/include/interrupt.h
Normal file
99
kernel/include/interrupt.h
Normal 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
31
kernel/include/ipc.h
Normal 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
223
kernel/include/memory.h
Normal 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
58
kernel/include/print.h
Normal 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
126
kernel/include/process.h
Normal 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
40
kernel/include/signal.h
Normal 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
31
kernel/include/types.h
Normal 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
57
kernel/include/utils.h
Normal 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
77
kernel/src/asm/io.asm
Normal 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
94
kernel/src/asm/isr.asm
Normal 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
88
kernel/src/asm/sched.asm
Normal 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
133
kernel/src/asm/syslib.asm
Normal 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
222
kernel/src/elf_loader.c
Normal 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
165
kernel/src/interrupt.c
Normal 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
55
kernel/src/ipc.c
Normal 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
77
kernel/src/main.c
Normal 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
790
kernel/src/memory.c
Normal 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
129
kernel/src/print.c
Normal 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
408
kernel/src/process.c
Normal 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
173
kernel/src/scheduler.c
Normal 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
79
kernel/src/signal.c
Normal 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
72
kernel/src/systemCall.c
Normal 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
321
kernel/src/utils.c
Normal 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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user