Commit initial

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

14
boot/Makefile Normal file
View File

@ -0,0 +1,14 @@
.PHONY: bin clean
all: bin
bin:
make -C bootloader/
make -C kernloader/
-mkdir bin
mv bootloader/bootsect.bin bin/
mv kernloader/NOS-kernldr.bin bin/
clean:
make -C bootloader/ clean
make -C kernloader/ clean
-rm -rf bin/

8
boot/bootloader/Makefile Normal file
View File

@ -0,0 +1,8 @@
.PHONY: clean
all: bootsect.bin
bootsect.bin: bootsect.asm
nasm -f bin -o $@ $^
clean:
-rm -f bootsect.bin

View File

@ -0,0 +1,173 @@
; bootsect.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>
; Code placé dans le MBR du disque
; ####################################
; BootLoader principal
; ####################################
; Le code est copié par le BIOS à l'adresse 0x7C00, soit à la base du segment 0x07C0
; 0x0:0x7C00 <=> 0x07C0:0000 0x07C0 x 0x10 = 0x7C00
; adresse physique = segment x 16 + offset
%define BOOT_SEG 0x07C0
%define KERN_LDR_SEG 0x07E0
%define KERN_LDR_LBA_ADDR 1
[BITS 16]
[ORG 0] ; Par rapport au segment 0x07C0
boot:
; On fait pointer les registres de segments sur le segment 0x07C0
; On ne fait rien pour CS car le bios s'en ait déjà occupé
mov ax, BOOT_SEG
mov ds, ax
mov ax, 0x9F00 ; On définit l'adresse de base de la pile à la base du segment 0x9F00, soit à l'adresse 0x9F000
mov ss, ax
mov sp, 0xFFF ; On définit le pointeur de pile à l'offset 0xFFFF ce qui correspond à l'adresse 0x9FFFF
mov [bootdisk], dl ; On sauvegarde le numéro de l'unité de disque utilisée par le BIOS
xor ax, ax ; int 0x13 fonction 0x00
int 0x13
call load_kern_ldr
jmp KERN_LDR_SEG:0x0000 ; On saute vers le code de kernLdr
; Fonction load_kern_ldr
; Charge kernLdr qui commence au 30ème secteur du disque
load_kern_ldr:
push ax
push ebx
push dx
push di
mov ax, 63 ; On charge 63 secteurs
mov dx, KERN_LDR_SEG
xor di, di
mov ebx, KERN_LDR_LBA_ADDR
call build_DAPS
call read_sector
pop di
pop dx
pop ebx
pop ax
ret
; Fonction print
; Params : pointeur sur str -> ds:si
print:
push ax
push bx
.top:
lodsb
cmp al, 0
jz .end
mov ah, 0x0E ; int 0x10 fonction 0x0E
mov bx, 0x07 ; attribut du caractère
int 0x10
jmp .top
.end:
pop bx
pop ax
ret
read_sector:
push ax
push dx
push si
xor ax, ax
add ax, 0 ; On met le flag de retenue à 0
mov si, DAPS
mov ah, 0x42
mov dl, [bootdisk]
int 0x13
jc .error
jmp .no_error
.error:
mov si, error_int13h
call print
call stop
.no_error:
pop si
pop dx
pop ax
ret
; Fonction build_DAPS
; Params: Nombre de secteur -> ax, Adresse LBA -> ebx, destination -> dx:di
build_DAPS:
mov [DAPS + 2], ax ; Nombre de secteurs
mov [DAPS + 4], di ; Offset du segment de destination
mov [DAPS + 6], dx ; Segment de destination
; adresse LBA
mov [DAPS + 8], ebx
xor ax, ax
mov [DAPS + 12], ax
mov [DAPS + 14], ax
ret
; Fonction Error
stop:
.loop:
hlt
jmp .loop
; Variables
; ############################################
DAPS: ; Disk Address Packet Structure
db 16 ; Taille de la structure
db 0 ; Toujours à 0
dw 0 ; Nombre de secteurs à transfèrer
dw 0 ; Offset du segment de buffer
dw 0 ; segment de buffer
dd 0 ; Adresse LBA de début
dd 0 ; Partie haute de l'adresse LBA (pour LBA 48 bits) non utilisée ici
error_int13h: db "BIOS 13H extension error !", 13, 10, 0
boot_disk: db 0
; ############################################
times 446-($-$$) db 144

33
boot/kernloader/Makefile Normal file
View File

@ -0,0 +1,33 @@
.PHONY: clean
CC=gcc
CFLAGS= -m32 -march=i486 -fno-stack-protector -fno-zero-initialized-in-bss
kernldr_obj_core=kernldr_init.o \
kernldr_main.o \
kernldr_print.o \
kernldr_utils.o \
asm_utils.o
kernldr_obj_drivers=drivers/ATA.o
all: NOS-kernldr.bin
NOS-kernldr.bin: kernldr_1 kernldr_2
dd if=kernldr_1 of=$@ bs=512 count=1
dd if=kernldr_2 of=$@ bs=512 seek=1
rm kernldr_1 kernldr_2
kernldr_1: startup.asm
nasm -f bin -o $@ $^
kernldr_2: $(kernldr_obj_core) $(kernldr_obj_drivers)
ld -melf_i386 --oformat=binary --Ttext=8000 --entry=kernldr_init $^ -o $@
clean:
-rm -f NOS-kernldr.bin $(kernldr_obj_core) $(kernldr_obj_drivers)
%.o:%.c
$(CC) $(CFLAGS) -c $^ -o $@
%.o:%.asm
nasm -f elf -o $@ $^

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,150 @@
/* ATA.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 "../kernLdr.h"
#include "ATA.h"
int ATA_getDevice(unsigned int ataNumber, unsigned int drive, T_ATA_device* dev) {
ataNumber &= 0x3;
drive &= 0x1;
print("-> Device : ATA %d ", DEFAULT_COLOR, ataNumber);
switch(ataNumber) {
case 0:
dev->ata_port = ATA_0_PORT;
dev->ata_ctrl_port = ATA_0_CTRL_PORT;
break;
case 1:
dev->ata_port = ATA_1_PORT;
dev->ata_ctrl_port = ATA_1_CTRL_PORT;
break;
case 2:
dev->ata_port = ATA_2_PORT;
dev->ata_ctrl_port = ATA_2_CTRL_PORT;
break;
case 3:
dev->ata_port = ATA_3_PORT;
dev->ata_ctrl_port = ATA_3_CTRL_PORT;
break;
}
if(drive) {
print("Slave drive\n", DEFAULT_COLOR);
dev->drive = ATA_SLAVE;
} else {
print("Master drive\n", DEFAULT_COLOR);
dev->drive = ATA_MASTER;
}
/* On vérifie si les ports I/O sont reliés à un contrôleur */
T_byte testByte;
_out(dev->ata_port + 2, 0x45);
_in(dev->ata_port + 2, &testByte);
if(testByte == 0x45) { /* Le contrôleur éxiste */
T_byte a, b, status;
/* On se prépare à utiliser la commande IDENTIFY pour connaitre le type de disque ATA */
_out(dev->ata_port + 6, ATA_CHS_MODE | dev->drive); /* On selectionne le disque */
delay(1000);
_out(dev->ata_port + 2, 0);
_out(dev->ata_port + 3, 0);
_out(dev->ata_port + 4, 0);
_out(dev->ata_port + 5, 0);
_out(dev->ata_port + 7, ATA_CMD_IDENTIFY); /* envoie de la commande */
_in(dev->ata_port + 7, &status);
if(status == 0) { /* Si le status est à 0, il n'y à pas de disque */
print("-> ERROR : Drive doesn't exist !\n", DEFAULT_COLOR);
return 0;
} else { /* Sinon on attend que le disque soit prêt */
while(status & 0x80) {
_in(dev->ata_port + 7, &status);
}
}
/* On récupère les octets de signature */
_in(dev->ata_port + 4, &a);
_in(dev->ata_port + 5, &b);
if((a == 0) && (b == 0)) { /* Disque dur ATA */
while(!(status & 0x08)) { /* On attend que le disque soit prêt pour la lecture des données d'identification */
_in(dev->ata_port + 7, &status);
}
unsigned int i;
T_word trash;
for(i = 0; i < 256; i++) { /* Pas besoin des info d'identification, mais on les transfert pour que le contrôleur termine la commande normalement */
_inw(dev->ata_port, &trash);
}
return 1;
} else {
print("-> ERROR : Drive is not ATA !\n", DEFAULT_COLOR);
}
} else {
print("-> ERROR : Controller doesn't exist !\n", DEFAULT_COLOR);
}
return 0;
}
void ATA_read(T_ATA_device dev, T_dword baseLBA, T_byte sectorCount, void* baddr) {
T_byte* buffer = baddr;
T_byte status = 0;
unsigned int i, j;
T_word word;
_out(dev.ata_port + 1, 0); /* Octet nul */
_out(dev.ata_port + 2, sectorCount);
_out(dev.ata_port + 3, (T_byte) (baseLBA & 0xFF)); /* 8 bits de poids faible de l'adresse LBA */
_out(dev.ata_port + 4, (T_byte) ((baseLBA >> 8) & 0xFF));
_out(dev.ata_port + 5, (T_byte) ((baseLBA >> 16) & 0xFF));
_out(dev.ata_port + 6, ATA_LBA_MODE | dev.drive | ((baseLBA >> 24) & 0x0F));
for(i = 0; i < 4; i++) {
_in(dev.ata_port + 7, &status);
}
_out(dev.ata_port + 7, ATA_CMD_READ);
/* On attend que le contrôleur soit prêt */
for(i = 0; i < sectorCount; i++) {
do {
_in(dev.ata_port + 7, &status);
}while((status & 0x80) || !(status & 0x08));
for(j = 0; j < 256; j++) {
_inw(dev.ata_port, &word);
buffer[(i * 512) + (j * 2)] = (T_byte) (word & 0xFF);
buffer[(i * 512) + (j * 2) + 1] = (T_byte) ((word >> 8) & 0xFF);
}
}
}

View File

@ -0,0 +1,57 @@
/* ATA.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 NOS_ATA_H
#define NOS_ATA_H
#include "../types.h"
#define ATA_LBA_MODE 0xE0
#define ATA_CHS_MODE 0xA0
#define ATA_MASTER 0x00
#define ATA_SLAVE 0x10
#define ATA_0_PORT 0x1F0
#define ATA_1_PORT 0x170
#define ATA_2_PORT 0x1E8
#define ATA_3_PORT 0x168
#define ATA_0_CTRL_PORT 0x3F6
#define ATA_1_CTRL_PORT 0x376
#define ATA_2_CTRL_PORT 0x3E6
#define ATA_3_CTRL_PORT 0x366
#define ATA_CMD_READ 0x20
#define ATA_CMD_IDENTIFY 0xEC
typedef struct {
T_word ata_port;
T_word ata_ctrl_port;
T_byte drive;
} T_ATA_device;
int ata_select_drive(unsigned int, unsigned int, T_ATA_device*);
void ata_read(T_ATA_device, T_dword, T_byte, void*);
#endif

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

77
boot/kernloader/io.asm Normal file
View File

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

209
boot/kernloader/kernldr.h Normal file
View File

@ -0,0 +1,209 @@
/* kernLdr.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 NOS_KERNLDR_H
#define NOS_KERNLDR_H
#include <stdarg.h>
#include "types.h"
#include "drivers/ATA.h"
/* Structure de passage d'arguments */
typedef struct {
T_dword low_addr;
T_dword high_addr;
T_dword low_size;
T_dword high_size;
T_dword type;
T_dword unused;
}__attribute__((packed)) T_mmap_entry;
#define BOOT_ARGS_ADDR 0x1000
typedef struct {
T_byte cursor_x;
T_byte cursor_y;
T_byte mmap_entry_count;
T_mmap_entry mmap[30]; /* Taille fixée arbitrairement */
}__attribute__((packed)) T_boot_args;
#define KERNEL_ARGS_ADDR 0x1400
typedef struct {
T_byte cursor_x;
T_byte cursor_x;
T_dword pmem_size;
T_byte mmap_entry_count;
T_dword init_proc_addr;
T_dword init_proc_size;
T_mmap_entry* mmap;
}__attribute__((packed)) T_kernel_args;
/* ############################## */
/* ######### Affichage ########## */
#define VIDEO_ADDR 0xB8000
#define VIDEO_SIZE 0xFA0
#define VIDEO_END_OFFSET 0xB8FA0
#define DEFAULT_COLOR 0x0F
char pos_x;
char pos_y;
int enable_cursor;
void scrollup(int);
void write_char(char, char);
void print(char*, ...);
void clear();
void show_cursor();
void hide_cursor();
void move_cursor(char, char);
/* ############################## */
/* ####### Fonctions I/O ######## */
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);
/* ############################## */
/* ########### Divers ########### */
void memcopy(char*, char*, unsigned int);
int strcmp(char*, char*);
void int_to_str(unsigned int, char*, int);
unsigned int expo(int, int);
void delay(unsigned int);
/* ############################## */
/* ###### Structure MBR et Table de partition */
#define PARTITION_BOOT_SIGN 0x80
#define VFAT32_PARTITION_ID 0x07
typedef struct {
T_byte bootsign;
T_byte chs_start_head;
T_byte chs_start_sector:6;
T_word chs_start_cylinder:10;
T_byte fs_id;
T_byte chs_end_head;
T_byte chs_end_sector:6;
T_word chs_end_cylinder:10;
T_dword lba_start_sector;
T_dword lba_sector_count;
}__attribute__((packed)) T_partition_entry;
#define MBR_BOOT_SIGN 0xAA55
typedef struct {
T_byte bootcode[446];
T_partition_entry pt[4];
T_word bootsign;
}__attribute__((packed)) T_MBR;
/* ########################################## */
/* ###### Fat32 structure ####### */
typedef struct {
T_byte jumpcode[3];
char OEM_identifier[8];
T_word byte_per_sect;
T_byte sect_per_cluster;
T_word reserved_sect_count;
T_byte fat_count;
T_word unused_1;
T_word total_sect_count_16;
T_byte media_desc_type;
T_word unused_2;
T_word sect_per_track;
T_word head_count;
T_dword hidden_sect_lba;
T_dword total_sect_count_32;
T_dword sect_per_fat;
T_word fat_info;
T_word fat_ver;
T_dword rootdir_first_cluster;
T_word fs_info_sect;
T_word dbr_cpy_sect;
T_byte reserved[12];
T_byte bios_disk_id;
T_byte reserved_NT; /* Windows NT flags */
T_byte sign;
T_dword serial_num;
char label[11];
char identifier_str[8];
T_byte bootcode[420];
T_word bootsign;
}__attribute__((packed)) T_FAT32_dbr;
#define FAT32_DIR_ENTRY_SIZE 32
typedef struct {
T_byte entry_num;
char char_part1[10];
T_byte attribute;
T_byte lfn_entry_type;
T_byte checksum;
char char_part2[12];
T_word null;
char char_part3[4];
}__attribute__((packed)) T_FAT32_lfn_entry;
typedef struct {
char filename[8];
char extention[3];
T_byte attribute;
T_byte reserved; /* Windows NT */
T_byte creation_time_1;
T_word creation_time_2;
T_word creation_date;
T_word last_acces;
T_word high_first_cluster;
T_word modif_time;
T_word modif_date;
T_word low_first_cluster;
T_dword file_size;
}__attribute__((packed)) T_FAT32_std_entry;
typedef struct {
T_ATA_device device;
T_FAT32_dbr dbr;
/* Buffer de lecture */
unsigned int loaded_fat_sect;
T_dword fat_sect_buf[128]; /* 512 octets */
T_dword* dir_cluster_buf;
/* Adresses LBA des structures sur le disque */
T_dword LBA_dbr;
T_dword LBA_fat;
T_dword LBA_first_sata_sect; /* cluster 2 */
} T_FAT32_partition;
#endif

View File

@ -0,0 +1,77 @@
; kernLdr_init.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 kernLdr_init
extern kernLdr_main
kernldr_init:
; On initialise tous les segments de données pour le mode protégé
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; Segment de pile
mov ax, 0x18
mov ss, ax
mov esp, 0xA0000 ; Pile à 0xA0000
push eax
; on vérifie que la ligne a20 est activée
call check_a20_line
cmp eax, 0
je .next ; Si activée, on passe
call enable_a20_line ; Sinon on l'active
.next:
; On appel le fonction principale qui :
; - calcul la taille de la mémoire utilisable à partir de la liste de plage mémoire communiquée par kernldr_1
; - charge la partition FAT32 définit
; - charge KERNEL32 à l'adresse 0x100000, et init à l'adresse 0x28000 depuis le répertoire /boot
; - construit la structure de passage d'argument
call kernldr_main
; On saute vers le kernel
mov esp, 0xA0000
jmp 0x08:0x100000
; Retourne 0xFFFFFFFF si déactivée, 0 si activée
check_a20_line:
mov dword [0x500], 0
mov dword [0x100500], 0xFFFFFFFF
mov eax, [0x500]
ret
enable_a20_line:
push eax
in al, 0x92
test al, 0x02
jnz .end
or al, 0x02
and al, 0xFE
out 0x92, al
.end:
pop eax
ret

View File

@ -0,0 +1,268 @@
/* kernLdr_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 "types.h"
#include "kernLdr.h"
#include "drivers/ATA.h"
static void detectMemory(T_bootArgs* bargs, T_kernelArgs* kargs)
{
T_dword* test1 = (T_dword*) 0x500;
T_dword* test2 = (T_dword*) 0x100500;
*test1 = 0;
*test2 = 0xFFFFFFFF;
if(*test1 == 0) {
print("-> A20 line enabled\n", DEFAULT_COLOR);
} else {
print("-> A20 line disabled\n", DEFAULT_COLOR);
asm("hlt");
}
unsigned int i;
kargs->phyMemSize = 0;
for(i = 0; i < bargs->memListEntryCount; i++) {
//print("-> (0x%x - 0x%x) type=%d\n", DEFAULT_COLOR, bargs->memMap[i].baseAddr_1, bargs->memMap[i].baseAddr_1 + bargs->memMap[i].size_1, bargs->memMap[i].type);
if(bargs->memMap[i].type == 1) {
kargs->phyMemSize += bargs->memMap[i].size_1;
}
}
print("-> Physical memory size : %d Ko\n", DEFAULT_COLOR, (kargs->phyMemSize / 1024));
}
static int getPartition(unsigned int partNumber, T_ATA_device device, T_FAT32_partition* part)
{
partNumber &= 0x3;
print("-> Partition : %d\n", DEFAULT_COLOR, partNumber);
/* On récupère le MBR */
T_mbr* mbr = (T_mbr*) 0x15000;
ATA_read(device, 0, 1, mbr);
if(mbr->partitionTable[partNumber].fileSytemID == VFAT32_PARTITION_ID) {
part->device = device;
part->LBA_dbr = mbr->partitionTable[partNumber].startingLBA;
// On charge le Dos Boot Record de la partition
ATA_read(part->device, part->LBA_dbr, 1, (void*) &part->dbr);
// On calcul l'adresse de la FAT ainsi que l'adresse du premier cluster
if(part->dbr.fatInfo >> 7) {
unsigned int activeFAT = part->dbr.fatInfo & 0x0F;
part->LBA_fileAllocationTable = part->LBA_dbr + part->dbr.reservedSectors + (activeFAT * part->dbr.sectorsPerFat);
} else {
part->LBA_fileAllocationTable = part->LBA_dbr + part->dbr.reservedSectors;
}
ATA_read(part->device, part->LBA_fileAllocationTable, 1, part->fatSectorBuffer);
part->LBA_firstDataSector = part->LBA_dbr + part->dbr.reservedSectors + (part->dbr.fatNumber * part->dbr.sectorsPerFat);
return 1;
} else {
print("-> ERROR : The partition is not VFAT32 type\n", DEFAULT_COLOR);
return 0;
}
}
static T_dword getFat32ClusterLBA(unsigned int clusterNum, T_FAT32_partition* part) {
return ((clusterNum - 2) * part->dbr.sectorsPerCluster) + part->LBA_firstDataSector;
}
static unsigned int getFat32NextClusterNum(unsigned int clusterNum, T_FAT32_partition* part) {
unsigned int nextCluster;
unsigned int sector = part->LBA_fileAllocationTable + ((clusterNum * 4) / 512);
if(sector != part->loadedFatSector) {
ATA_read(part->device, sector, 1, part->fatSectorBuffer);
part->loadedFatSector = sector;
}
nextCluster = part->fatSectorBuffer[((clusterNum * 4) % 512) / 4];
if(nextCluster >= 0x0FFFFFF8) {
return 0;
} else if(nextCluster == 0x0FFFFFF7) {
print("-> ERROR : A BAD CLUSTER WAS FOUND (PREVIOUS CLUSTER = %d)\n", DEFAULT_COLOR, clusterNum);
asm("hlt");
} else {
return nextCluster;
}
}
static unsigned int loadFile(char *target, T_dword destAddr, T_FAT32_partition* part)
{
print("-> Loading '%s'\n", DEFAULT_COLOR, target);
unsigned int currentCluster = part->dbr.rootDirFirstCluster; /* Numéro d'un cluster du répertoire courant */
T_FAT32_stdEntry* entry = (T_FAT32_stdEntry*) part->dirClusterBuffer; /* Buffer utilisé pour stocker un cluster du répertoire courant */
ATA_read(part->device, getFat32ClusterLBA(currentCluster, part), part->dbr.sectorsPerCluster, entry);
unsigned int i = 0;
while(target[i] != 0) {
char entity[256];
unsigned int j;
char isDirectory = 0, isFile = 0;
for(j = 0; target[i] != 0; i++, j++) {
if(j >= 256) {
print("-> ERROR : INVALID TARGET '%s'\n", DEFAULT_COLOR, target);
return 0;
} else if(target[i] == '/') {
isDirectory = 1;
i++;
break;
} else {
entity[j] = target[i];
}
}
/* On ferme la chaine de caractères */
entity[j] = '\0';
if(!isDirectory) {
isFile = 1;
}
/* Chargement */
if(entity[0] != '\0') {
unsigned int lfnAvailable = 0;
unsigned int stopLoop = 0;
while(currentCluster && (!stopLoop)) {
unsigned int k;
char *entityLFN = (char*) 0x4200;
for(k = 0; k < ((part->dbr.sectorsPerCluster * 512) / FAT32_DIR_ENTRY_SIZE); k++) {
if((entry[k].fileName[0] != 0) && (entry[k].fileName[0] != 0xE5)) { /* Si l'entrée est valide */
if(entry[k].attribute == 0x0F) { /* Si on trouve une entrée LFN */
T_FAT32_lfnEntry* lfnEntry = (T_FAT32_lfnEntry*) &entry[k];
lfnAvailable = 1;
/* On récupère les parties de nom */
unsigned int l;
unsigned int offset = ((lfnEntry->entryNum & 0x3F) - 1) * 13; /* offset de la section du nom dans la chaine finale */
for(l = 0; l < 13; l++) {
if(l < 5) {
entityLFN[offset + l] = lfnEntry->char_part1[l * 2];
} else if(l < 11) {
entityLFN[offset + l] = lfnEntry->char_part2[(l - 5) * 2];
} else if(l < 13) {
entityLFN[offset + l] = lfnEntry->char_part3[(l - 11) * 2];
}
}
} else { /* Sinon c'est une entrée standard */
char *entityNameCmp;
if(lfnAvailable) {
entityNameCmp = entityLFN;
lfnAvailable = 0;
} else {
entityNameCmp = (char*) 0x4400;
unsigned int l, m;
for(l = 0; l < 8 && entry[k].fileName[l] != ' '; l++) {
entityNameCmp[l] = entry[k].fileName[l];
}
entityNameCmp[l] = '.';
for(m = 0; m < 3 && entry[k].extention[m] != ' '; m++, l++) {
entityNameCmp[l] = entry[k].extention[m];
}
entityNameCmp[l] = '\0';
}
if(isDirectory) {
if((strcmp(entity, entityNameCmp)) && (entry[k].attribute & 0x10)) {
currentCluster = ((T_dword) entry[k].firstCluster_high << 16) | entry[k].firstCluster_low;
ATA_read(part->device, getFat32ClusterLBA(currentCluster, part), part->dbr.sectorsPerCluster, part->dirClusterBuffer);
stopLoop = 1;
break;
}
} else if(isFile) {
if((strcmp(entity, entityNameCmp)) && (entry[k].attribute & 0x20)) {
unsigned int cluster = ((T_dword) entry[k].firstCluster_high << 16) | entry[k].firstCluster_low;
unsigned int size = 0;
while(cluster) {
ATA_read(part->device, getFat32ClusterLBA(cluster, part), part->dbr.sectorsPerCluster, (void*) destAddr);
destAddr += (part->dbr.sectorsPerCluster * 512);
cluster = getFat32NextClusterNum(cluster, part);
size += (part->dbr.sectorsPerCluster * 512);
}
return size;
}
}
}
}
}
if(!stopLoop) {
currentCluster = getFat32NextClusterNum(currentCluster, part);
}
}
if(!stopLoop) {
print("-> ERROR : UNABLE TO FIND '%s' FOR '%s'\n", DEFAULT_COLOR, entity, target);
return 0;
}
}
}
}
void kernLdr_main()
{
/* On définit les adresse des structure en mémoire */
T_bootArgs* bootArgs = (T_bootArgs*) BOOT_ARGS_ADDR;
T_kernelArgs* kernelArgs = (T_kernelArgs*) KERNEL_ARGS_ADDR;
/* Position du curseur */
posX = bootArgs->cursor_X;
posY = bootArgs->cursor_Y;
showCursor();
print("Welcome to NutsOS KernelLoader v1.0.0\n", DEFAULT_COLOR);
/* On affiche la memory map */
print("[MEMORY DETECTION]\n", 0x02);
detectMemory(bootArgs, kernelArgs);
T_ATA_device bootDevice;
T_FAT32_partition bootPartition;
bootPartition.loadedFatSector = 0;
bootPartition.dirClusterBuffer = (T_dword*) 0x2000;
print("[FILES LOADING]\n", 0x02);
if(!ATA_getDevice(0, 0, &bootDevice)) {
asm("hlt");
}
if(!getPartition(0, bootDevice, &bootPartition)) {
asm("hlt");
}
if(loadFile("/boot/NOS-kernel32.bin", 0x100000, &bootPartition)) { /* On charge KERNEL32 à la bonne adresse et on passe les arguments */
kernelArgs->initProcessAddr = 0x28000;
kernelArgs->initProcessSize = loadFile("/boot/init", kernelArgs->initProcessAddr, &bootPartition);
if(!kernelArgs->initProcessSize) {
asm("hlt");
} else if(kernelArgs->initProcessSize > 819200) {
print("ERROR : INIT PROCESS IS TOO LARGE\n", DEFAULT_COLOR);
asm("hlt");
} else {
print("[BOOTING]\n", 0x02);
kernelArgs->cursor_X = posX;
kernelArgs->cursor_Y = posY;
kernelArgs->memListEntryCount = bootArgs->memListEntryCount;
kernelArgs->memMap = bootArgs->memMap;
}
} else {
asm("hlt");
}
}

View File

@ -0,0 +1,187 @@
/* kernLdr_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 "kernLdr.h"
#define DEFAULT_COLOR 0x0F
char color = (char) DEFAULT_COLOR;
void scrollup(int lines) {
char* vid;
char* offset;
for(vid = (char*) VIDEO_ADDR; vid < (char*) VIDEO_END_OFFSET; vid += 2) {
offset = (char*) (vid + lines * 160);
if(offset < (char*) VIDEO_END_OFFSET) {
vid[0] = offset[0];
vid[1] = offset[1];
} else {
vid[0] = 0;
vid[1] = color;
}
}
pos_y -= lines;
if(pos_y < 0) {
pos_y = 0;
}
}
void write_char(char c_ascii) {
char* vid;
vid = (char*) (VIDEO_ADDR + pos_y * 160 + pos_x * 2);
switch(c_ascii) {
case 0:
break;
case 8:
vid[-2] = 0;
vid[-1] = color;
pos_x--;
break;
case 10: // Ligne suivante
pos_x = 0;
pos_y++;
break;
case 13: // Retour debut de ligne
pos_x = 0;
break;
default:
vid[0] = c_ascii;
vid[1] = color;
pos_x++;
break;
}
if(pos_x > 79) {
pos_x = 0;
pos_y++;
}
if(pos_y > 24) {
scrollup(1);
}
if(posX < 0) {
posX = 79;
posY--;
}
if(posY < 0) {
posX = 0;
posY = 0;
}
if(enable_cursor) {
move_cursor(pos_x, pos_y);
}
}
static void print_dec(unsigned int a, char color) {
char str[11];
int_to_str(a, str, 10);
unsigned int i;
for(i = 0; str[i] != 0; i++) {
write_char(str[i]);
}
}
static void print_hex(unsigned int a, char color) {
char str[9];
int_to_str(a, str, 16);
unsigned int i;
for(i = 0; str[i] != 0; i++) {
write_char(str[i]);
}
}
static void print_bin(unsigned int a, char color) {
char str[33];
int_to_str(a, str, 2);
unsigned int i;
for(i = 0; str[i] != 0; i++) {
write_char(str[i]);
}
}
void print(char *str, ...) {
va_list arg;
va_start(arg, str);
while(str[0] != 0) {
if(str[0] == '%') {
if(str[1] == 'd') {
print_dec(va_arg(arg, T_dword), color);
str += 2;
} else if(str[1] == 'x') {
print_hex(va_arg(arg, T_dword), color);
str += 2;
} else if(str[1] == 'b') {
print_bin(va_arg(arg, T_dword), color);
str += 2;
} else if(str[1] == 's') {
print(va_arg(arg, char*), color);
str += 2;
} else if(str[1] == 'C') {
} else {
write_char(*str, color);
str++;
}
} else {
write_char(*str, color);
str++;
}
}
va_end(arg);
}
void clear() {
char* vid;
for(vid = (char*) VIDEO_ADDR; vid <= (char*) VIDEO_END_OFFSET; vid += 2) {
vid[0] = 0;
vid[1] = ;
}
}
void show_cursor() {
enable_cursor = 1;
move_cursor(pos_x, pos_y);
}
void hide_cursor() {
enable_cursor = 0;
move_cursor(-1, -1);
}
void move_cursor(char x, char y) {
T_word c_pos = (T_word) (y * 80 + x);
_out(0x3D4, 0x0F);
_out(0x3D5, (T_byte) cpos);
_out(0x3D4, 0x0E);
_out(0x3D5, (T_byte) (cpos >> 8));
}

View File

@ -0,0 +1,92 @@
/* kernLdr_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 "drivers/ATA.h"
#include "kernLdr.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) {
int length1 = 0;
int length2 = 0;
int i;
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 intToStr(T_dword num, char *str, int base) {
const char decimal[] = {'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] = decimal[a - (base * tmp)];
tmp = a;
counter++;
j--;
}
str[counter] = 0;
}
T_dword expo(int x, int y) {
return (y > 0) ? (x * expo(x, y-1)) : 1;
}
void delay(unsigned int n) {
unsigned int i;
for(i = 0; i < n; i++);
}

197
boot/kernloader/startup.asm Normal file
View File

@ -0,0 +1,197 @@
; startup.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>
%define ARGS_SEG 0x100
%define KERN_LDR_SEG 0x07E0
%define ARGS_CURSOR_POSX_OFFSET 0
%define ARGS_CURSOR_POSY_OFFSET 1
%define ARGS_MEMMAP_ENTRY_COUNT_OFFSET 2
%define ARGS_MEMMAP_OFFSET 3
[BITS 16]
[ORG 0] ; Par rapport au segment 0x07E0
startup:
mov ax, KERN_LDR_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ax, 0x500
mov ss, ax
mov sp, 0xFF0
mov si, start_msg
call print
call build_args
; On passe en mode protégé
cli
lgdt [gdtreg]
mov eax, cr0
or eax, 1
mov cr0, eax
; Segment 0x07E0 en mode réel = adresse physique 0x7E00
; Le seconde partie du code de kernLdr est situé 512 octets plus loin
; On saute dans le seconde partie de kernLdr et en même temps on réinitialise le segment de code
jmp 0x08:0x8000
build_args:
push eax
push ebx
push ecx
push edx
push es
push di
mov ax, ARGS_SEG
mov es, ax
mov ah, 3
xor bh, bh
int 0x10 ; On demande la position du curseur
; On passe la position du curseur en argument
mov [es:ARGS_CURSOR_POSX_OFFSET], dl
mov [es:ARGS_CURSOR_POSY_OFFSET], dh
; Memory map initialisation
mov di, ARGS_MEMMAP_OFFSET
mov eax, 0xE820
xor ebx, ebx
mov ecx, 24
mov edx, 0x534D4150
int 0x15
jc error
cmp eax, 0x534D4150
jne error
cmp ebx, 0
je error
xor bp, bp
; récupération des entrées de la Memory Map
.loop:
inc bp
add di, 24
mov eax, 0xE820
mov ecx, 24
int 0x15
jc .end_loop
cmp ebx, 0
jne .loop
.end_loop:
mov ax, bp
mov [es:ARGS_MEMMAP_ENTRY_COUNT_OFFSET], al
pop di
pop es
pop edx
pop ecx
pop ebx
pop eax
ret
; Fonction print
; Params : pointeur sur str -> ds:si
print:
push ax
push bx
.top:
lodsb
cmp al, 0
jz .end
mov ah, 0x0E ; int 0x10 fonction 0x0E
mov bx, 0x07 ; attribut du caractère
int 0x10
jmp .top
.end:
pop bx
pop ax
ret
error:
mov si, error_msg
call print
.loop:
hlt
jmp .loop
; Variables
; #################################
; kernLdrContext:
; - cursorX
; - cursorY
; - biosBootDisk
; - listSize
; - memStructureList
start_msg: db "Starting NutsOS KernelLoader...", 13, 10, 0
error_msg: db "Fatal Error !", 0
gdt_reg:
dw (gdt_end - gdt_start) ; taille de la gdt
dd (KERN_LDR_SEG << 4) + gdt_start ; adresse de base dur 32 bits
gdt_start:
.null_seg: ; descripteur nul
times 8 db 0
.code_seg: ; Segment de code [0x0 - 0xFFFFFFFF]
dw 0xFFFF ; limite0_15
dw 0x0000 ; base0_15
db 0x00 ; base16_23
db 0x9A ; acces
db 0xCF ; Flags, limite16_19
db 0x00 ; base24_31
.data_seg: ; Segment de données [0x0 - 0xFFFFFFFF]
dw 0xFFFF ; limite0_15
dw 0x0000 ; base0_15
db 0x00 ; base16_23
db 0x92 ; acces
db 0xCF ; Flags, limite16_19
db 0x00 ; base24_31
.stack_seg: ; Segment de pile [... - 0x9F000]
dw 0x0000 ; limite0_15, (0x009F + intel vt-x = O_o bug)
dw 0x0000 ; base0_15
db 0x00 ; base16_23
db 0x96 ; acces
db 0xC0 ; Flags, limite16_19
db 0x00 ; base24_31
gdt_end:
; #################################
times 512-($-$$) db 144

31
boot/kernloader/types.h Normal file
View File

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