G A C E T A   D E   L I N U X
...haciendo a Linux un poco más divertido!
¿Así que quieres crear tu propio Sistema Operativo x86?
Por Patrick Mahoney
Traducción al español por Daniel Guerrero
el día 13 de Diciembre 2002, para La Gaceta de Linux

1. Introducción

Una de las grandes dificultades que un programador por hobbie enfrenta cuando inicia el desarrollo de su propio OS es encontrar por dónde empezar. Muchos libros describen a profundidad conceptos teóricos de los SO, aún ninguno parece llevar de la mano al programador por hobby y enfrentarlo cara a cara con estos conceptos. Esto es precisamente lo que este artículo pretende hacer.

Muchos artículos relacionados a este tema han aparecido en las últimas ediciones de la Gaceta de Linux. Planeo aprovecharlas en una manera mucho menos orientada a la programación, sólo presentar al lector las herramientas y las sugerencias que necesitará para desarrollar su propio SO. Una vez concluido este artículo, el lector interesado debe estar preparado para inciar la búsqueda de los recursos que le están disponibles e iniciar el diseño y la codificación.

No debes estar al tanto de esto, pero el desarrollo de un sistema operativo no empieza al inicio. (!!) Escribir un cargador de inicio es un proyecto por si solo, y no aconsejaría a alguien a iniciar un proyecto de desarollo de SO escribiendo un cargador de inicio. Hay muchos confiables disponibles de forma gratuita (Grub, lilo, ppcboot, etc...). Si planeas escribir el tuyo propio, te sugiero que retrases esta tarea a una etapa posterior del proyecto. En este artículo, estaré usando GNU Grub, el Gran Cargador de Inicio Unificado (Grand Unified Bootloader, por sus siglas en inglés).

2. Descripción del ambiente de desarrollo

Para facilitar el dolor que el desarrollar SO te acarreará. necesitarás configurar un ambiente de desarollo adaptado que necesita un cierto número de requerimentos:

Este artículo te presentará uno de muchos posibles ambientes que tiene esos requerimentos. Consistirá de una máquina de desarrollo y una máquina de pruebas, ambas yacen en una red común.

2.1 La máquina de desarrollo

Obviamente, esta máquina necesitará estar equipada con un buen conjunto de herramientas de programación: ensambladores y compiladores de C, un ligador y una utilidad 'make' son necesarias.

Una herramienta que encontré más útil que de lo que pensaba fue un emulador. Esta herramienta te ayudará a depurar tu kernel y te permitirá probar rápidamente tu nueva línea agregada de código. No te engañes, aunque, un emulador nunca reemplazará una buena máquina de pruebas.

Lo siguiente, necesitas un servidor TFTP. Esta herraminta le permitirá al cargador de inicio habilitado por tftp de tu máquina de pruebas adquirir un kernel de tu máquina de desarrollo por medio de la conexión de red.

2.2 La máquina de pruebas

Todo lo que esta máquina necesita es una tarjeta de red y un cargador de inicio habilitado por TFTP que lo soporte.

3. Instalación del ambiente de desarrollo

3.1 La máquina de desarollo

Las herramientas de programación escogidas son:

Bochs version 1.4.1 es el emulador x86 escogido. Cuida de compilarlo con el modo de depuración habilitado. Estos comandos deben hacer el trabajo:

	$ ./configure --enable-x86-debugger
	$ make
Para poder utilizar apropiadamente Bochs, necesitarás crear una imagen de disco. Esta imagen necesita tener tanto un cargador de inicio como un sistema de archivos. Esto puede ser hecho usando el script de mkbimage. Si eres demasiado perezoso para hacerlo por ti mismo, toma esta imagen de disco comprimida de 10MB disk y agrégale
	diskc: file=c.img, cyl=24, heads=16, spt=63
a tu archivo .bochrc.

También para el servidor TFTP, escogí usar atftpd. Es una implementación basada en el servidor TFTP de linux fácil de usar.

3.2 La máquina de pruebas

El cargador de inicio escogido es GNU Grub versión 0.92. Se debe cuidar que sea habilitado que el cliente tftp de Grub se comunique con tu tarjeta de red. Mi máquina de pruebas tiene un clónico barato del NE2000 ISA. Siguiendo cuidadosamente las instrucciones netboot/README.netboot, use estos comandos:
	$ ./configure --enable-ne --enable-ne-scan=0x220
	$ make
Date cuenta que una tarjeta PCI PnP debe ser más fácil de configurar. Ahora puedes instalar las imagenes de Grub en el sector de arranque de la máquina de pruebas o en un floppy de donde iniciará tu máquina de pruebas. Prefiero lo último, debido a que mi máquina de pruebas es también usada para otros propósitos y por tanto, prefiero no jugar con su Disco Duro.
	$ cat ./stage1/stage1 ./stage2/stage2 > /dev/fd0
Insertamos el floppy en tu máquina de prueba para ver si tu tarjeta de red es reconocida. Puedes configurarla de forma manual o usando un servidor dhcp, si existe.
	grub> dhcp
	Probing... [NE*000]
	NE2000 base 0x220, addr 00:C0:A8:4E:5A:76
	Address: 192.168.22.14
	Netmask: 255.255.255.0
	Server: 192.168.22.1
	Gateway: 192.168.22.1
Date cuenta que no tendrás que configurar cada uno de esos parámetros manualmente cuando inicias. Ve la documentación de GNU Grub y el script 'grub-install' para los detalles.

¡Eso es! ¡Esta todo configurado para probar tu instalación!

4. Probando la instalación de tu ambiente de desarrollo...

Como mencioné anteriormente, dejaré las cosas relacionadas a la programación interna del SO, usaremos el kernel de ejemplo de las fuentes GNU Grub localizadas en el directorio /docs.

El kernel es construido de tres archivos fuentes: boot.S, kernel.c y multiboot.h. Puedes construir el kernel mediante:

	$ gcc -I. -c ./boot.S
	$ gcc -I. -c ./kernel.c
	$ ld ./kernel.o ./boot.o -o kernel -Ttext 100000
Aquí hay una rápida e incompleta explicación. Multiboot es un estándar que define la manera con la que el cargador de inicio pasa información al kernel cuando intenta cargarlo. boot.S acepta esta información, configura una pila, y llama a 'cmain'. Esta función configura la salida vga, lee la información que se le pasa, imprime algunas cosas y sale. Entonces, boot.S obtiene de nuevo el control, imprime la cadena 'Halted', y entra a un ciclo infinito. Algo muy simple, ¿no?. Se invita al lector a escarbar en el código para obtener mas detalles.

4.1 ...con Bochs

El plan es montar tu imagen del disco por medio de un dispositivo loopback, copia tu kernel en tu sistema de archivos de la imagen, desmóntalo, y enciende Bochs. Claro, tienes que agregar un offset al inicio del sistema de archivos. Pero sabes eso, ¿correcto?
	# /sbin/losetup -o 32256 /dev/loop1 ./c.img
	# /bin/mount -t ext2 /dev/loop1 /mnt/osdev/
	# cp /docs/kernel /mnt/osdev
	# umount /mnt/osdev/
	# /sbin/losetup /dev/loop1 -d
	$ bochs
Claro, esto puede ser automatizado por tu Makefile. Una vez en Grub, simplemente haz:
	grub> kernel (hd0,0)/kernel
	grub> boot
Bochs screenshot
(Haz Click en la imagen para el tamaño completo.)

4.2 ...con tu máquina de pruebas

Primero, configura tu TFTP server así el cliente puede recuperar tu kernel:
	# /usr/sbin/atftpd --daemon /home/bono/src/grub-0.92/docs
Enciende máquina de pruebas. Configura tu conexión de red como se muestra abajo. Ahora, especifica la dirección ip de tu máquina de desarrollo como la dirección del servidor TFTP y la localidad de la imagen del kernel. Date cuenta que esta opción puede ser usada por el servidor dhcp. Finalmente, empieza el proceso inicio.
	(...)

	grub> tftpserver 192.168.22.36
	Address: 192.168.22.14
	Netmask: 255.255.255.0
	Server: 192.168.22.36
	Gateway: 192.168.22.1

	grub> kernel (nd)/kernel
	[Multiboot-elf, <0x100000:0x807:0x0>, <0x101808:0x0:0x4018>,
	shtab=0x106190, entry=0x100568]

	grub> boot
Una pantalla similar a la de Bochs debería aparecer en tu pantalla de la máquina de pruebas.

5. A donde ir desde aquí

Bueno estas mucho más cerca de iniciar el desarrollo de tu SO. Mucha buena documentación reside en la red. Navégala, envía, pregunta, piensa. ¿Monolítico o micro kernel? ¿Segmentación o paginación?

Si tu depuración necesita crecer tanto en el emulador y en tus printk's del kernel, una configuración que le puedes agregar a tu SO es la depuración serial. Esto puede ir de algunos bytes en el puerto serial, a una extensión remota de depuración compatible con gdb. Esta información puede ser rescatada y procesada por tu máquina de desarrollo a través de un cable serial sin modem. Es una práctica común en el desarrollo de SO.

6. Recursos

7. Agradecimientos

Muchas gracias a aquellos que aceptaron a responderme pacientemente mis interminables preguntas en #osdev: pavloskii, geist, oink, byrdkernel, air.
Copyright © 2002, Patrick Mahoney. Licencia de Copiado http://www.linuxgazette.com/copying.html
Publicado originalmente en la edición 85 de Linux Gazette, Diciembre 2002