From d968266a3be79c449f62fdf6f19b8f8b5344eece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Zurcher?= Date: Mon, 2 Nov 2015 11:15:48 +0100 Subject: Initial commit --- TP1-Mini-kernel.pdf | Bin 0 -> 130414 bytes common/types.h | 15 ++++++++++++++ grub/grub.cfg | 5 +++++ kernel/bootloader.o | Bin 0 -> 256816 bytes kernel/bootloader.s | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/const.inc | 3 +++ kernel/gdt.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/gdt.h | 36 ++++++++++++++++++++++++++++++++ kernel/gdt.o | Bin 0 -> 1756 bytes kernel/gdt_asm.o | Bin 0 -> 608 bytes kernel/gdt_asm.s | 19 +++++++++++++++++ kernel/kernel.c | 15 ++++++++++++++ kernel/kernel.ld | 36 ++++++++++++++++++++++++++++++++ kernel/kernel.o | Bin 0 -> 932 bytes kernel/kernel_asm.s | 7 +++++++ kernel/makefile | 24 ++++++++++++++++++++++ kernel/x86.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ makefile | 15 ++++++++++++++ mini_kernel/grub.cfg | 5 +++++ 19 files changed, 349 insertions(+) create mode 100644 TP1-Mini-kernel.pdf create mode 100644 common/types.h create mode 100644 grub/grub.cfg create mode 100644 kernel/bootloader.o create mode 100644 kernel/bootloader.s create mode 100644 kernel/const.inc create mode 100644 kernel/gdt.c create mode 100644 kernel/gdt.h create mode 100644 kernel/gdt.o create mode 100644 kernel/gdt_asm.o create mode 100644 kernel/gdt_asm.s create mode 100644 kernel/kernel.c create mode 100644 kernel/kernel.ld create mode 100644 kernel/kernel.o create mode 100644 kernel/kernel_asm.s create mode 100644 kernel/makefile create mode 100644 kernel/x86.h create mode 100644 makefile create mode 100644 mini_kernel/grub.cfg diff --git a/TP1-Mini-kernel.pdf b/TP1-Mini-kernel.pdf new file mode 100644 index 0000000..9b82a19 Binary files /dev/null and b/TP1-Mini-kernel.pdf differ diff --git a/common/types.h b/common/types.h new file mode 100644 index 0000000..4c911ed --- /dev/null +++ b/common/types.h @@ -0,0 +1,15 @@ +#ifndef _TYPES_H_ +#define _TYPES_H_ + +#include +#include + +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + +#define NULL 0 + +#endif + diff --git a/grub/grub.cfg b/grub/grub.cfg new file mode 100644 index 0000000..420d048 --- /dev/null +++ b/grub/grub.cfg @@ -0,0 +1,5 @@ +set timeout=0 + +menuentry "Your_OS_name" { + multiboot /boot/kernel.elf +} diff --git a/kernel/bootloader.o b/kernel/bootloader.o new file mode 100644 index 0000000..96a1d55 Binary files /dev/null and b/kernel/bootloader.o differ diff --git a/kernel/bootloader.s b/kernel/bootloader.s new file mode 100644 index 0000000..36d516f --- /dev/null +++ b/kernel/bootloader.s @@ -0,0 +1,57 @@ +global entrypoint ; the entry point symbol defined in kernel.ld +extern mainKernel ; indique la fonction ne se trouve pas dans ce fichier + +; Values for the multiboot header +MULTIBOOT_HEADER_MAGIC equ 0x1BADB002 +MULTIBOOT_HEADER_FLAGS equ 0x0 +; magic + checksum + flags must equal 0 +MULTIBOOT_HEADER_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) +STACK_SIZE equ 256000 +;--------------------------------------------------------------------------------------------------- +; bootloader section +; This section must be located at the very beginning of the kernel image. + +section .bootloader +align 4 ; section aligned to a 4 bytes boundary + +; Minimum multiboot header +dd MULTIBOOT_HEADER_MAGIC +dd MULTIBOOT_HEADER_FLAGS +dd MULTIBOOT_HEADER_CHECKSUM + +entrypoint: + ; Bootloader code starts executing here + cli ; disable hardware interrupts + + ; TODO : initialiser le pointeur de pile ainsi qu'EBP (à la même valeur) + ; Rappel : la pile "grandi" en descendant ! + ; ... + mov esp, stack ; l'adresse de la pile est defini par le label 'stack' + add esp, STACK_SIZE ; on deplace le pointeur de pile a la fin de la pile + mov ebp, esp + + + ; TODO : appeler la fonction principale du kernel (code C) + ; Celle-ci doit etre visible par le linker + ; ... + + call mainKernel + + ; infinite loop (should never get here) +.forever: + hlt + jmp .forever + +;--------------------------------------------------------------------------------------------------- +; stack section + +; TODO : ajouter une section pour la pile kernel dans laquelle + + +; reserver au moins 256KB grace a la directive "resb". +; Cette section devra etre alignee sur 4 bytes. +; ... +section .stack + +stack: + resb STACK_SIZE diff --git a/kernel/const.inc b/kernel/const.inc new file mode 100644 index 0000000..17d17d0 --- /dev/null +++ b/kernel/const.inc @@ -0,0 +1,3 @@ +; Must match the values of the same constants in gdt.h! +GDT_KERNEL_CODE_SELECTOR equ 0x08 +GDT_KERNEL_DATA_SELECTOR equ 0x10 diff --git a/kernel/gdt.c b/kernel/gdt.c new file mode 100644 index 0000000..0a7cfdc --- /dev/null +++ b/kernel/gdt.c @@ -0,0 +1,57 @@ +#include "../common/types.h" +#include "gdt.h" +#include "x86.h" + +// TODO: déclarer la table GDT +// Pointeur sur la table GDT +static gdt_ptr_t gdt_ptr; + +// Build and return a GDT entry given the various arguments (see Intel manuals). +static gdt_entry_t build_entry(uint32_t base, uint32_t limit, uint8_t type, uint8_t s, uint8_t db, uint8_t granularity, uint8_t dpl) { + gdt_entry_t entry; + // For a TSS and LDT, base is the addresse of the TSS/LDT structure + // and limit is the size of the structure. + entry.lim15_0 = limit & 0xffff; + entry.base15_0 = base & 0xffff; + entry.base23_16 = (base >> 16) & 0xff; + entry.type = type; // See TYPE_xxx flags + entry.s = s; // 1 for segments; 0 for system (TSS, LDT, gates) + entry.dpl = dpl; // privilege level + entry.present = 1; // present in memory + entry.lim19_16 = (limit >> 16) & 0xf; + entry.avl = 0; // available for use + entry.l = 0; // should be 0 (64-bit code segment) + entry.db = db; // 1 for 32-bit code and data segments; 0 for system (TSS, LDT, gate) + entry.granularity = granularity; // granularity of the limit value: 0 = 1 byte; 1 = 4096 bytes + entry.base31_24 = (base >> 24) & 0xff; + return entry; +} + +// Return a NULL entry. +static gdt_entry_t null_segment() { + gdt_entry_t entry; + //memset(&entry, 0, sizeof(gdt_entry_t)); + return entry; +} + +// Return a code segment specified by the base, limit and privilege level passed in arguments. +static gdt_entry_t code_segment(uint32_t base, uint32_t limit, uint8_t dpl) { + return build_entry(base, limit, TYPE_CODE_EXECREAD, S_CODE_OR_DATA, DB_SEG, 1, dpl); +} + +// Return a data segment specified by the base, limit and privilege level passed in arguments. +static gdt_entry_t data_segment(uint32_t base, uint32_t limit, uint8_t dpl) { + return build_entry(base, limit, TYPE_DATA_READWRITE, S_CODE_OR_DATA, DB_SEG, 1, dpl); +} + +// Initialize the GDT +void gdt_init() { + // TODO: fixer la limite de gdt_ptr, puis la faire pointer sur la GDT + + // TODO: initialisation des trois descripteurs de segment: NULL, segment code, segment data + // Les descripteurs de code et data doivent avoir un DPL de 0. + + // Load the GDT + gdt_flush(&gdt_ptr); +} + diff --git a/kernel/gdt.h b/kernel/gdt.h new file mode 100644 index 0000000..03f575e --- /dev/null +++ b/kernel/gdt.h @@ -0,0 +1,36 @@ +#ifndef _GDT_H_ +#define _GDT_H_ + +// Structure of a GDT descriptor. There are 2 types of descriptors: segments and TSS. +// Section 3.4.5 of Intel 64 & IA32 architectures software developer's manual describes +// segment descriptors while section 6.2.2 describes TSS descriptors. +typedef struct gdt_entry_st { + uint16_t lim15_0; + uint16_t base15_0; + uint8_t base23_16; + + uint8_t type : 4; + uint8_t s : 1; + uint8_t dpl : 2; + uint8_t present : 1; + + uint8_t lim19_16 : 4; + uint8_t avl : 1; + uint8_t l : 1; + uint8_t db : 1; + uint8_t granularity : 1; + + uint8_t base31_24; +} __attribute__((packed)) gdt_entry_t; + +// Structure describing a pointer to the GDT descriptor table. +// This format is required by the lgdt instruction. +typedef struct gdt_ptr_st { + uint16_t limit; // Limit of the table (ie. its size) + uint32_t base; // Address of the first entry +} __attribute__((packed)) gdt_ptr_t; + +extern void gdt_init(); +extern void gdt_flush(gdt_ptr_t *gdt_ptr); + +#endif diff --git a/kernel/gdt.o b/kernel/gdt.o new file mode 100644 index 0000000..da9ac7d Binary files /dev/null and b/kernel/gdt.o differ diff --git a/kernel/gdt_asm.o b/kernel/gdt_asm.o new file mode 100644 index 0000000..f6e32e2 Binary files /dev/null and b/kernel/gdt_asm.o differ diff --git a/kernel/gdt_asm.s b/kernel/gdt_asm.s new file mode 100644 index 0000000..9e59544 --- /dev/null +++ b/kernel/gdt_asm.s @@ -0,0 +1,19 @@ +%include "const.inc" + +global gdt_flush + +section .text: ; start of the text (code) section +align 4 ; the code must be 4 byte aligned + +gdt_flush: + mov eax,[esp+4] ; Get the pointer to the GDT, passed as a parameter. + lgdt [eax] ; Load the new GDT pointer + mov ax,GDT_KERNEL_DATA_SELECTOR ; offset in the GDT of the kernel data segment + mov ds,ax ; Load all data segment selectors + mov es,ax + mov fs,ax + mov gs,ax + mov ss,ax + jmp GDT_KERNEL_CODE_SELECTOR:.flush ; far jump [selector:offset] +.flush: +ret diff --git a/kernel/kernel.c b/kernel/kernel.c new file mode 100644 index 0000000..d01eada --- /dev/null +++ b/kernel/kernel.c @@ -0,0 +1,15 @@ +extern void smiley(); + +void mainKernel(){ + + #ifdef TEST + // MODE TEST + smiley(); + + #else + //MODE NORMAL + #endif + + + while(1); +} diff --git a/kernel/kernel.ld b/kernel/kernel.ld new file mode 100644 index 0000000..da9e019 --- /dev/null +++ b/kernel/kernel.ld @@ -0,0 +1,36 @@ +ENTRY(entrypoint) /* the entry point */ + +SECTIONS { + . = 0x100000; /* all sections located above 1MB */ + + .bootloader ALIGN(4K): /* multiboot header first (needs to reside within the first 8KB) */ + { + *(.bootloader) + } + + .stack ALIGN(4K): /* kernel stack */ + { + *(.stack) + } + + .text ALIGN(4K) : /* code */ + { + *(.text*) + } + + .rodata ALIGN(4K) : /* read-only data */ + { + *(.rodata*) + } + + .data ALIGN(4K) : /* initialized data */ + { + *(.data*) + } + + .bss ALIGN(4K) : /* unitialized data */ + { + *(COMMON) + *(.bss*) + } +} diff --git a/kernel/kernel.o b/kernel/kernel.o new file mode 100644 index 0000000..b000856 Binary files /dev/null and b/kernel/kernel.o differ diff --git a/kernel/kernel_asm.s b/kernel/kernel_asm.s new file mode 100644 index 0000000..6005121 --- /dev/null +++ b/kernel/kernel_asm.s @@ -0,0 +1,7 @@ +global smiley + +section .text + +smiley: + mov eax,0xB8000 + mov word [eax],0x0E01 diff --git a/kernel/makefile b/kernel/makefile new file mode 100644 index 0000000..0173172 --- /dev/null +++ b/kernel/makefile @@ -0,0 +1,24 @@ +all: run + +run : ld + +ld: kernel.o bootloader.o gdt.o gdt_asm.o + ld -Tkernel.ld -melf_i386 gdt_asm.o bootloader.o kernel.o gdt.o -o kernel.elf + +kernel.o: kernel.c kernel_asm.o + gcc -DTEST -std=gnu99 -m32 -fno-builtin -ffreestanding -Wall -Wextra -c kernel.c + +kernel_asm.o: kernel_asm.s + nasm -f elf32 $< + +bootloader.o: bootloader.s + nasm -f elf32 bootloader.s + +gdt.o: gdt.c gdt.h + gcc -std=gnu99 -m32 -fno-builtin -ffreestanding -Wall -Wextra -c gdt.c + +gdt_asm.o: gdt_asm.s + nasm -f elf32 $< + +clean: + rm -f *.o \ No newline at end of file diff --git a/kernel/x86.h b/kernel/x86.h new file mode 100644 index 0000000..716cb6c --- /dev/null +++ b/kernel/x86.h @@ -0,0 +1,55 @@ +#ifndef _X86_H_ +#define _X86_H_ + +// Privilege levels +#define DPL_USER 0x3 +#define DPL_KERNEL 0x0 + +// Selectors +#define LDT_SELECTOR 0x4 + +// Descriptor types for code and data segments +#define TYPE_DATA_READONLY 1 +#define TYPE_DATA_READWRITE 3 +#define TYPE_CODE_EXECONLY 9 +#define TYPE_CODE_EXECREAD 11 + +// Descriptor types for system segments and gates +#define TYPE_LDT 2 +#define TYPE_TASK_GATE 5 +#define TYPE_TSS 9 +#define TYPE_CALL_GATE 12 +#define TYPE_TRAP_GATE 15 +#define TYPE_INTERRUPT_GATE 14 + +// Descriptor system bit (S) +// For code or data segments +#define S_CODE_OR_DATA 1 +// For TSS segment, LDT, call gate, interrupt gate, trap gate, task gate +#define S_SYSTEM 0 + +// D/B bit +#define DB_SEG 1 +#define DB_SYS 0 + +// kernel code and data selectors in the GDT +#define GDT_KERNEL_CODE_SELECTOR 0x08 +#define GDT_KERNEL_DATA_SELECTOR 0x10 + +// Disable hardware interrupts. +static inline void cli() { + asm volatile("cli"); +} + +// Enable hardware interrupts. +static inline void sti() { + asm volatile("sti"); +} + +// Halt the processor. +// External interrupts wake up the CPU, hence the cli instruction. +static inline void halt() { + while (1) asm volatile("cli\nhlt"); +} + +#endif diff --git a/makefile b/makefile new file mode 100644 index 0000000..24f21aa --- /dev/null +++ b/makefile @@ -0,0 +1,15 @@ +all: run + +run: create_iso + qemu-system-i386 -hda mini_kernel/mini_kernel.iso + +create_iso: cpy + grub-mkrescue -o mini_kernel/mini_kernel.iso mini_kernel + +cpy: + cp grub/grub.cfg mini_kernel/ + cp kernel/kernel.elf mini_kernel/ + +clean: + rm mini_kernel/*.iso mini_kernel/*.cfg mini_kernel/*.elf + \ No newline at end of file diff --git a/mini_kernel/grub.cfg b/mini_kernel/grub.cfg new file mode 100644 index 0000000..420d048 --- /dev/null +++ b/mini_kernel/grub.cfg @@ -0,0 +1,5 @@ +set timeout=0 + +menuentry "Your_OS_name" { + multiboot /boot/kernel.elf +} -- cgit v1.1-2-g2b99