Commit initial
This commit is contained in:
33
boot/kernloader/Makefile
Normal file
33
boot/kernloader/Makefile
Normal 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 $@ $^
|
1
boot/kernloader/drivers/AHCI.c
Normal file
1
boot/kernloader/drivers/AHCI.c
Normal file
@ -0,0 +1 @@
|
||||
|
1
boot/kernloader/drivers/AHCI.h
Normal file
1
boot/kernloader/drivers/AHCI.h
Normal file
@ -0,0 +1 @@
|
||||
|
150
boot/kernloader/drivers/ATA.c
Normal file
150
boot/kernloader/drivers/ATA.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
57
boot/kernloader/drivers/ATA.h
Normal file
57
boot/kernloader/drivers/ATA.h
Normal 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
|
1
boot/kernloader/drivers/ATAPI.c
Normal file
1
boot/kernloader/drivers/ATAPI.c
Normal file
@ -0,0 +1 @@
|
||||
|
1
boot/kernloader/drivers/ATAPI.h
Normal file
1
boot/kernloader/drivers/ATAPI.h
Normal file
@ -0,0 +1 @@
|
||||
|
77
boot/kernloader/io.asm
Normal file
77
boot/kernloader/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
|
209
boot/kernloader/kernldr.h
Normal file
209
boot/kernloader/kernldr.h
Normal 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
|
77
boot/kernloader/kernldr_init.asm
Normal file
77
boot/kernloader/kernldr_init.asm
Normal 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
|
268
boot/kernloader/kernldr_main.c
Normal file
268
boot/kernloader/kernldr_main.c
Normal 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");
|
||||
}
|
||||
}
|
187
boot/kernloader/kernldr_print.c
Normal file
187
boot/kernloader/kernldr_print.c
Normal 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));
|
||||
}
|
92
boot/kernloader/kernldr_utils.c
Normal file
92
boot/kernloader/kernldr_utils.c
Normal 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
197
boot/kernloader/startup.asm
Normal 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
31
boot/kernloader/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 NOS_TYPES_H
|
||||
#define NOS_TYPES_H
|
||||
|
||||
typedef unsigned char T_byte;
|
||||
typedef unsigned short T_word;
|
||||
typedef unsigned int T_dword;
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user