Adrianistán

El blog de Adrián Arroyo


Artículos con etiqueta «kernel»

Emulando a Linus Torvalds: Crea tu propio sistema operativo desde 0 (VIII)

Este artículo lo escribí para el blog en español DesdeLinux el 23 de diciembre de 2014 y ahora lo dejo aquí, en mi blog personal. El artículo está tal cual, sin ninguna modificación desde aquella fecha.
Volvemos a la serie de tutoriales sobre como crear nuestro propio sistema operativo. Supongo que este capítulo os gustará mucho porque por fin podremos interactuar con nuestro sistema operativo. Hoy leeremos la entrada del teclado. Para ello el esquema es similar al del timer. Tenemos que usar los IRQ igualmente así que empezaremos igual que con el timer
Seguir leyendo

Emulando a Linus Torvalds: Crea tu propio sistema operativo desde 0 (VII)

Este artículo lo escribí para el blog en español DesdeLinux el 25 de agosto de 2014 y ahora lo dejo aquí, en mi blog personal. El artículo está tal cual, sin ninguna modificación desde aquella fecha.
Bienvenidos a otro post sobre cómo crear nuestro propio sistema operativo. Ha pasado mucho tiempo desde el último post, debido principalmente a un bug que encontré en lo que nos toca hoy. Veremos cómo manejar el reloj en arquitecturas x86
Seguir leyendo

Emulando a Linus Torvalds: Crea tu propio sistema operativo desde 0 (VI)

Este artículo lo escribí para el blog en español DesdeLinux el 11 de enero de 2014 y ahora lo dejo aquí, en mi blog personal. El artículo está tal cual, sin ninguna modificación desde aquella fecha.
Bien, después de un pequeño paréntesis seguimos con nuestra serie de tutoriales. Si retomamos el código anterior debemos de tener el ISR de la división por cero. Ahora debemos de rellenar el resto de las ISR para las que habíamos puesto mensaje (las 32 primeras). Bien ahora vamos a seguir programando interrupciones, vamos a hacer las IRQ también conocidas como Interrupts Requests. Estas IRQ se generan por los dispositivos de hardware tales como teclados, ratones, impresoras, etc. Inicialmente las primeras 8 IRQ se mapean automáticamente en las posiciones de la IDT del 8 al 15. Como hemos usado las 32 primeras para las excepciones ahora tenemos que remapearlas. Nosotros pondremos la IRQ desde la 32 hasta la 45. Para ello primero debemos remapear los los IRQ:
void ND::IRQ::Remap(int pic1, int pic2)
{
    #define PIC1 0x20
    #define PIC2 0xA0
    #define ICW1 0x11
    #define ICW4 0x01
    /* send ICW1 */

    ND::Ports::OutputB(PIC1, ICW1);
    ND::Ports::OutputB(PIC2, ICW1);

    /* send ICW2 */

    ND::Ports::OutputB(PIC1 + 1, pic1); /* remap */
    ND::Ports::OutputB(PIC2 + 1, pic2); /* pics */

    /* send ICW3 */

    ND::Ports::OutputB(PIC1 + 1, 4); /* IRQ2 -> connection to slave */
    ND::Ports::OutputB(PIC2 + 1, 2);

    /* send ICW4 */

    ND::Ports::OutputB(PIC1 + 1, ICW4);
    ND::Ports::OutputB(PIC2 + 1, ICW4);

    /* disable all IRQs */

    ND::Ports::OutputB(PIC1 + 1, 0xFF);
}
Ahora creamos una función para instalar los IRQ:
void ND::IRQ::Install()
{
    ND::Screen::SetColor(ND_SIDE_FOREGROUND,ND_COLOR_BLACK);
    ND::Screen::PutString("\nInstalling IRQ...");
    ND::IRQ::Remap(0x20,0x28);
    ND::IDT::SetGate(32,(unsigned)ND::IRQ::IRQ1,0x08,0x8E);
    ND::IDT::SetGate(33,(unsigned)ND::IRQ::IRQ2,0x08,0x8E);
    ND::IDT::SetGate(34,(unsigned)ND::IRQ::IRQ3,0x08,0x8E);
    ND::IDT::SetGate(35,(unsigned)ND::IRQ::IRQ4,0x08,0x8E);
    ND::IDT::SetGate(36,(unsigned)ND::IRQ::IRQ5,0x08,0x8E);
    ND::IDT::SetGate(37,(unsigned)ND::IRQ::IRQ6,0x08,0x8E);
    ND::IDT::SetGate(38,(unsigned)ND::IRQ::IRQ7,0x08,0x8E);
    ND::IDT::SetGate(39,(unsigned)ND::IRQ::IRQ8,0x08,0x8E);
    ND::IDT::SetGate(40,(unsigned)ND::IRQ::IRQ9,0x08,0x8E);
    ND::IDT::SetGate(41,(unsigned)ND::IRQ::IRQ10,0x08,0x8E);
    ND::IDT::SetGate(42,(unsigned)ND::IRQ::IRQ11,0x08,0x8E);
    ND::IDT::SetGate(43,(unsigned)ND::IRQ::IRQ12,0x08,0x8E);
    ND::IDT::SetGate(44,(unsigned)ND::IRQ::IRQ13,0x08,0x8E);
    ND::IDT::SetGate(45,(unsigned)ND::IRQ::IRQ14,0x08,0x8E);
    ND::IDT::SetGate(46,(unsigned)ND::IRQ::IRQ15,0x08,0x8E);
    ND::IDT::SetGate(47,(unsigned)ND::IRQ::IRQ16,0x08,0x8E);
    ND::Screen::SetColor(ND_SIDE_FOREGROUND,ND_COLOR_GREEN);
    ND::Screen::PutString("done");
    asm volatile("sti");
}
La sentencia de asm sti nos activa los IRQ. Bien ahora vamos con algo similar a los ISR. Las funciones de un IRQ básico:
void ND::IRQ::IRQ1()
{
	asm volatile(
	"cli \n"
	"pushl 0\n"
	"pushl 32\n"
	"jmp ND_IRQ_Common"
	);
}
Una parte común (igual que la de los ISR):
extern "C"
void ND_IRQ_Common()
{
    asm volatile(
    "pusha \n"
    "push %ds\n"
    "push %es\n"
    "push %fs\n"
    "push %gs\n"
    "movw $0x10, %ax \n"
    "movw %ax, %ds \n"
    "movw %ax, %es \n"
    "movw %ax, %fs \n"
    "movw %ax, %gs \n"
    "movl %esp, %eax \n"
    "push %eax \n"
    "movl $ND_IRQ_Handler, %eax \n"
    "call *%eax \n"
    "popl %eax \n"
    "popl %ds \n"
    "popl %es \n"
    "popl %fs \n"
    "popl %gs \n"
    "popa \n"
    "addl 8, %esp \n"
    "iret \n"
    );
}
Y un handler básico:
extern "C"
void ND_IRQ_Handler(struct regs* r)
{
	void (*handler)(struct regs *r);
	if(r->int_no >= 40)
	{
	ND::Ports::OutputB(0xA0,0x20);
	}
	ND::Ports::OutputB(0x20,0x20);
}
Con esto ya deberíamos tener activados los IRQ aunque todavía no hagan nada. En el siguiente capítulo veremos como obtener datos a partir de estos IRQ como el reloj o el teclado
Seguir leyendo

Emulando a Linus Torvalds: Crea tu propio sistema operativo desde 0 (V)

Este artículo lo escribí para el blog en español DesdeLinux el 11 de enero de 2014 y ahora lo dejo aquí, en mi blog personal. El artículo está tal cual, sin ninguna modificación desde aquella fecha.
En esta quinta entrega veremos una tabla bastante parecida a la GDT tanto en teoría como en uso, nos referimos a la IDT. Las siglas de IDT hacen referencia a Interrupts Description Table y es una tabla que se usa para manejar las interrupciones que se produzcan. Por ejemplo, alguien hace una división entre 0, se llama a la función encargada de procesar. Estas funciones son los ISR (Interrupt Service Routines). Así pues vamos a crear la IDT y añadir algunos ISR
Seguir leyendo

Emulando a Linus Torvalds: Crea tu propio sistema operativo desde 0 (IV)

Este artículo lo escribí para el blog en español DesdeLinux el 5 de enero de 2014 y ahora lo dejo aquí, en mi blog personal. El artículo está tal cual, sin ninguna modificación desde aquella fecha.
Bienvenidos de nuevo a esta serie de posts titulada “Emulando a Linus Torvalds”. Hoy veremos la GDT. Primero tenemos que ver que es la GDT. Según Wikipedia:
The Global Descriptor Table or GDT is a data structure used by Intel x86-family processors starting with the 80286 in order to define the characteristics of the various memory areas used during program execution, including the base address, the size and access privileges like executability and writability
Que traducido sería una Tabla de Descriptores Global, una estructura de datos usada en los procesadores Intel x86 desde el 80286 para definir las características de varias áreas de memoria usadas durante la ejecución del programa
Seguir leyendo

Emulando a Linus Torvalds: Crea tu propio sistema operativo desde 0 (III)

Este artículo lo escribí para el blog en español DesdeLinux el 1 de enero de 2014 y ahora lo dejo aquí, en mi blog personal. El artículo está tal cual, sin ninguna modificación desde aquella fecha.
NextDivel-3 Continuamos esta serie de posts sobre cómo crear nuestro sistema operativo. Hoy no nos vamos a centrar en un tema sino que vamos a definir algunas funciones útiles de ahora en adelante. En primer lugar vamos a definir 3 funciones que cumplan la función de memcpy, memset y memcmp:
void* ND::Memory::Set(void* buf, int c, size_t len)
{
	unsigned char* tmp=(unsigned char*)buf;
	while(len--)
	{
		*tmp++=c;
	}
	return buf;
}
void* ND::Memory::Copy(void* dest,const void* src, size_t len)
{
	const unsigned char* sp=(const unsigned char*)src;
	unsigned char* dp=(unsigned char*)dest;
	for(;len!=0;len--) *dp++=*sp++;
	return dest;
}
int ND::Memory::Compare(const void* p1, const void* p2, size_t len)
{
	const char* a=(const char*)p1;
	const char* b=(const char*)p2;
	size_t i=0;
	for(;i<len;i++)
	{
		if(a[i] < b[i])
			return -1;
		else if(a[i] > b[i])
			return 1;
	}
	return 0;
}
Todas ellas se auto-implementan. Estas funciones yo las he sacado de una pequeña librería del C, la implementación suele ser parecida en todos los sistemas operativos. Ahora vamos a hacer 3 funciones simulares pero para manipular strings. Cumplirían la función de strcpy, strcat y strcmp
Seguir leyendo

Emulando a Linus Torvalds: Crea tu propio sistema operativo desde 0 (II)

Este artículo lo escribí para el blog en español DesdeLinux el 29 de diciembre de 2013 y ahora lo dejo aquí, en mi blog personal. El artículo está tal cual, sin ninguna modificación desde aquella fecha.
Bienvenidos a otro post sobre como crear nuestro propio sistema operativo, en este caso NextDivel
Seguir leyendo

Emulando a Linus Torvalds: Crea tu propio sistema operativo desde 0 (I)

Este artículo lo escribí para el blog en español DesdeLinux el 27 de diciembre de 2013 y ahora lo dejo aquí, en mi blog personal. El artículo está tal cual, sin ninguna modificación desde aquella fecha.
En esta serie vamos a emular a Linus Torvalds, vamos a crear nuestro sistema operativo desde 0. En este primer episodio vamos a ver el arranque y pondremos un texto en pantalla desde nuestro kernel
Seguir leyendo