Compare commits
6 commits
4b67b84146
...
e4db0a38d8
Author | SHA1 | Date | |
---|---|---|---|
e4db0a38d8 | |||
84c5da93a7 | |||
0f77e1a450 | |||
ecf7b4a33b | |||
90b8d178a4 | |||
eb75299351 |
9 changed files with 3022 additions and 7 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,3 +1,8 @@
|
|||
doc
|
||||
iso
|
||||
os.iso
|
||||
stage2_eltorito
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/c,vim
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=c,vim
|
||||
|
||||
|
|
9
Makefile
9
Makefile
|
@ -1,4 +1,4 @@
|
|||
OBJECTS = loader.o framebuffer.o io.o kmain.o
|
||||
OBJECTS = loader.o serial.o framebuffer.o io.o kmain.o
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -m32 -nostdlib -nostdinc -fno-builtin -fno-stack-protector \
|
||||
|
@ -40,8 +40,13 @@ os.iso: kernel.elf
|
|||
-o os.iso \
|
||||
iso
|
||||
|
||||
doc:
|
||||
doxygen Doxyfile
|
||||
|
||||
.PHONY: run clean all
|
||||
|
||||
run: os.iso
|
||||
qemu-system-i386 -cdrom $< -serial stdio #-d cpu
|
||||
|
||||
clean:
|
||||
rm *.o kernel.elf os.iso
|
||||
rm -r *.o kernel.elf os.iso doc
|
||||
|
|
21
README.txt
21
README.txt
|
@ -3,3 +3,24 @@
|
|||
|
||||
Suivez les instructions pour pouvoir compiler l'image avec Grub :
|
||||
https://littleosbook.github.io/#obtaining-grub
|
||||
|
||||
Ressources
|
||||
==========
|
||||
|
||||
- The Little book about OS development :
|
||||
https://github.com/littleosbook/littleosbook
|
||||
- The Little book about OS development (fork avec des fix) :
|
||||
https://github.com/OrdoFlammae/littleosbook-src
|
||||
|
||||
ASM
|
||||
---
|
||||
|
||||
- x86 Assembly Guide : https://www.cs.virginia.edu/~evans/cs216/guides/x86.html
|
||||
- Intel x86 Instruction Set Reference : http://www.felixcloutier.com/x86/
|
||||
- Intel® 64 and IA-32 Architectures Software Developer Manuals (Volumes 2) :
|
||||
https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
|
||||
|
||||
Doxygen
|
||||
-------
|
||||
|
||||
- Doxygen Manual : https://www.star.bnl.gov/public/comp/sofi/doxygen/
|
||||
|
|
|
@ -28,14 +28,14 @@
|
|||
* Le port pour pouvoir indiquer le sous-registre que l'on souhaite modifier
|
||||
* dans le framebuffer VGA. Il s'agit du registre d'adresses.
|
||||
*/
|
||||
#define FB_ADDRESS_PORT 0x3D4
|
||||
#define FB_ADDRESS_PORT 0x03D4
|
||||
|
||||
/**
|
||||
* @def FB_DATA_PORT
|
||||
* Le port pour pouvoir indiquer des données à écrire dans un sous-registre du
|
||||
* framebuffer VGA. Il s'agit du registre de données.
|
||||
*/
|
||||
#define FB_DATA_PORT 0x3D5
|
||||
#define FB_DATA_PORT 0x03D5
|
||||
|
||||
/**
|
||||
* @def FB_HIGH_BYTE_COMMAND
|
||||
|
|
21
include/io.h
21
include/io.h
|
@ -1,6 +1,27 @@
|
|||
/** @file io.h
|
||||
* Fichier d'en-tête pour les entrées sorties.
|
||||
*/
|
||||
|
||||
#ifndef IO_H
|
||||
#define IO_H
|
||||
|
||||
/**
|
||||
* Fonction pour pouvoir envoyer des données à un port.
|
||||
*
|
||||
* Elle est définie dans le fichier @c io.s.
|
||||
*
|
||||
* @param port le port où envoyer les données
|
||||
* @param data les données
|
||||
*/
|
||||
void outb(unsigned short port, unsigned char data);
|
||||
|
||||
/**
|
||||
* Fonction pour pouvoir lire une donnée d'un port.
|
||||
*
|
||||
* Elle est définie dans le fichier @c io.s.
|
||||
*
|
||||
* @param port le port où envoyer les données
|
||||
* @return la valeur lue
|
||||
*/
|
||||
unsigned char inb(unsigned short port);
|
||||
#endif
|
||||
|
|
94
include/serial.h
Normal file
94
include/serial.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/** @file serial.h
|
||||
* Fichier d'en-tête pour les ports séries.
|
||||
*
|
||||
* Références:
|
||||
* - documentation sur les ports séries :
|
||||
* - https://wiki.osdev.org/Serial_Ports
|
||||
* - https://devse.wiki/x86_64/p%C3%A9riph%C3%A9riques/com
|
||||
* - https://www.sci.muni.cz/docs/pc/serport.txt
|
||||
* - `LCR (Line Control Register)`
|
||||
* - `FCR (FIFO Control Register)`
|
||||
* - `Excursion: Why and how to use the FIFOs (by Scott C. Sadow)`
|
||||
*/
|
||||
|
||||
#ifndef SERIAL_H
|
||||
#define SERIAL_H
|
||||
|
||||
#define COM1_PORT 0x03F8
|
||||
|
||||
#define COM_DATA(base) (base)
|
||||
#define COM_INTERRUPT(base) (base + 1)
|
||||
#define COM_FIFO(base) (base + 2)
|
||||
#define COM_LINE_CONTROL(base) (base + 3)
|
||||
#define COM_MODEM_CONTROL(base) (base + 4)
|
||||
#define COM_LINE_STATUS(base) (base + 5)
|
||||
#define COM_MODEM_STATUS(base) (base + 6)
|
||||
#define COM_SCRATCH(base) (base + 7)
|
||||
|
||||
#define DLAB_BYTE 0x80
|
||||
|
||||
/**
|
||||
* Fonction pour définir la vitesse de transmission du port série.
|
||||
*
|
||||
* L'UART (le controleur de série) a une horloge interne tournant à 115200
|
||||
* ticks par seconde. On peut modifier cette vitesse en la divisant. Cela se
|
||||
* fait en activant le DLAB.
|
||||
*
|
||||
* @param port le port série à configurer
|
||||
* @param div le diviseur du nombre de tick
|
||||
*/
|
||||
void serial_set_baud(unsigned short port, unsigned short div);
|
||||
|
||||
/**
|
||||
* Configuration du port série.
|
||||
*
|
||||
* On configure le port série via le canal de controle de ligne. Il prend un
|
||||
* byte découpé en plusieurs sous parties : (7) DBPPPSTT (0).
|
||||
*
|
||||
* - D = bit pour activer le DLAB;
|
||||
* - B = active le break (cf. section `LCR (Line Control Register)` de
|
||||
* https://www.sci.muni.cz/docs/pc/serport.txt);
|
||||
* - P = parité (cf. https://wiki.osdev.org/Serial_Ports#Parity);
|
||||
* - S = nombre de bits de stop (0 = 1, 1 = 1.5/2);
|
||||
* - T = taille de la communication (0 = 5; 3 = 8)
|
||||
*
|
||||
* Notre configuration étant basique, nous nous contentons d'utiliser la taille
|
||||
* maximale de données, sans parité et avec un bit de stop.
|
||||
*
|
||||
* @param port le port à configurer
|
||||
*/
|
||||
void serial_config(unsigned short port);
|
||||
|
||||
/**
|
||||
* Vérifie si la file d'envoie est vide.
|
||||
*
|
||||
* @param port le port à vérifier
|
||||
* @return 1 si la file est vide, 0 sinon
|
||||
*/
|
||||
int serial_is_fifo_empty(unsigned short port);
|
||||
|
||||
/**
|
||||
* Envoie une chaine de caractère à un port série.
|
||||
*
|
||||
* La fonction fait une attente active lorsque la chaine est trop grosse. À
|
||||
* corriger dans le futur.
|
||||
*
|
||||
* @param port le port où envoyer la chaine. Il doit être configuré avant.
|
||||
* @param buf la chaine de caractère
|
||||
* @param len la longueur de la chaine
|
||||
* @return la taille de la chaine envoyée
|
||||
*/
|
||||
unsigned int serial_write(unsigned short port, char *buf, unsigned int len);
|
||||
|
||||
/**
|
||||
* Vérifie si le port série marche bien.
|
||||
*
|
||||
* Configure le port avec un diviseur de 5 et active le drapeau de boucle du
|
||||
* modem.
|
||||
*
|
||||
* @param port le port où tester la configuration
|
||||
* @return 0 si tout est OK, un chiffre positif sinon
|
||||
*/
|
||||
int serial_test_configuration(unsigned short port);
|
||||
|
||||
#endif
|
15
src/io.s
15
src/io.s
|
@ -1,11 +1,20 @@
|
|||
global outb
|
||||
global inb
|
||||
|
||||
; permet de communiquer avec des ports
|
||||
; pile : [ esp + 8 ] la valeur à écrire
|
||||
; [ esp + 4 ] le port
|
||||
; [ esp ] l'adresse de retour
|
||||
; pile : [ esp + 8 ] la valeur à écrire
|
||||
; [ esp + 4 ] le port
|
||||
; [ esp ] l'adresse de retour
|
||||
outb:
|
||||
mov al, [esp + 8]
|
||||
mov dx, [esp + 4]
|
||||
out dx, al
|
||||
ret
|
||||
|
||||
; permet de récupérer la valeur d'un port
|
||||
; pile : [ esp + 4 ] le port
|
||||
; [ esp ] l'adresse de retour
|
||||
inb:
|
||||
mov dx, [esp + 4]
|
||||
in al, dx
|
||||
ret
|
||||
|
|
89
src/serial.c
Normal file
89
src/serial.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include "io.h"
|
||||
|
||||
void serial_set_baud(unsigned short port, unsigned short div)
|
||||
{
|
||||
outb(COM_LINE_CONTROL(port), DLAB_BYTE);
|
||||
outb(COM_DATA(port), (div >> 8) & 0x00FF);
|
||||
outb(COM_INTERRUPT(port), div & 0x00FF);
|
||||
outb(COM_LINE_CONTROL(port), 0);
|
||||
}
|
||||
|
||||
void serial_config(unsigned short port)
|
||||
{
|
||||
/* configuration de la façon d'envoyer des données. Ici, on envoie des
|
||||
caractères de 8 bits, avec 1 bit de stop et aucune parité. */
|
||||
outb(COM_LINE_CONTROL(port), 0x03);
|
||||
|
||||
/* configuration de la file FIFO. Lorsqu'on essaie d'envoyer trop de
|
||||
* caractères et que la vitesse du port ne suit pas, les caractères en trop
|
||||
* sont stockés dans cette file. Ici, on vide la file de réception et
|
||||
* d'envoie, on stocke 14 bytes dans les files et on l'active. cf. FCR (FIFO
|
||||
* Control Register) : https://www.sci.muni.cz/docs/pc/serport.txt
|
||||
*/
|
||||
outb(COM_FIFO(port), 0xC7);
|
||||
|
||||
/* configuration du modem, on active la réception et l'envoie de données */
|
||||
outb(COM_MODEM_CONTROL(port), 0x03);
|
||||
}
|
||||
|
||||
int serial_is_fifo_empty(unsigned short port)
|
||||
{
|
||||
return inb(COM_LINE_STATUS(port)) & 0x20;
|
||||
}
|
||||
|
||||
unsigned int serial_write(unsigned short port, char *buf, unsigned int len)
|
||||
{
|
||||
unsigned int ret;
|
||||
char tmp;
|
||||
|
||||
ret = 0;
|
||||
|
||||
while (ret < len)
|
||||
{
|
||||
tmp = *(buf + ret);
|
||||
|
||||
/* pas ouf, à trouver un meilleur moyen d'attendre lorsque la file est
|
||||
* pleine */
|
||||
while (!serial_is_fifo_empty(port));
|
||||
outb(COM_DATA(port), tmp);
|
||||
|
||||
ret++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int serial_test_configuration(unsigned short port)
|
||||
{
|
||||
char *tmp;
|
||||
char t;
|
||||
int i, ret;
|
||||
|
||||
serial_set_baud(port, 5);
|
||||
serial_config(port);
|
||||
/* activation du retour pour pouvoir tester */
|
||||
outb(COM_MODEM_CONTROL(port), 0x13);
|
||||
|
||||
i = 0;
|
||||
tmp = "coucou";
|
||||
|
||||
do
|
||||
{
|
||||
outb(COM_DATA(port), *(tmp + i));
|
||||
i++;
|
||||
}
|
||||
while (*(tmp + i) != '\0');
|
||||
|
||||
ret = 0;
|
||||
i = 0;
|
||||
|
||||
do
|
||||
{
|
||||
t = inb(COM_DATA(port));
|
||||
if (t != *(tmp + i)) ret++;
|
||||
i++;
|
||||
}
|
||||
while (t != '\0');
|
||||
|
||||
return ret;
|
||||
}
|
Loading…
Add table
Reference in a new issue