Primeros Pasos Federico Raimondo PSO 1er cuat 2011 Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 1 / 44 Booteo ¿Qué? Bootloader wikipedia.org Es un programa sencillo diseñado exclusivamente para preparar todo lo que necesita el sistema operativo para funcionar. Normalmente se utilizan los cargadores de arranque multietapas, en los que varios programas pequeños se suman los unos a los otros, hasta que el último de ellos carga el sistema operativo. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 2 / 44 Booteo ¿Por qué? Bootloader ¿por qué? Intel determinó que, por cuestiones de compatibilidad, todas las PCs arrancan igual que un 8086. Este modo en el que arranca se lo llama modo real. En modo real, no tenemos para direccionar mas que 1114096 bytes en los CPUs modernos (1.062 Mb aprox.). Este lı́mite hace que tengamos que cambiar de modo e inicializar ciertas estructuras del CPU antes de cargar el kernel (salvo que nuestro kernel ocupe menos de 1 Mb). Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 3 / 44 Booteo ¿Cómo? Proceso de booteo Cuando la computadora se prende, corre una serie de diagnósticos llamados POST (Power On Self Test). Parte de esta secuencia es buscar un dispositivo booteable. Un dispositivo es booteable si tiene un sector de booteo cuyos bytes 511 y 512 son 0x55 y 0xAA respectivamente. Cuando la BIOS lo detecta, lo carga en una dirección predeterminada: 0x0000:0x7C00 o 0x07C0:0x0000. (Son la misma dirección fı́sica, lo veremos mas adelante) Luego se procede a ejecutar el código cargado. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 4 / 44 Booteo ¿Cómo? Memoria ¿Quién va a necesitar mas de 640 Kb? Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 5 / 44 Booteo ¿Cómo? Resumiendo Pasos a seguir en el booteo: 1 Determinar el disco y la partición a bootear. 2 Determinar dónde está la imagen del kernel en ese disco. 3 Cargar la imagen del kernel en memoria. 4 Pasar a modo protegido. 5 Preparar las estructuras para correr el kernel (Ej: preparar la pila). ¡Todo esto en 510 bytes! Dirı́a un conocido personaje del rock: “Esh imposhible, ¡esh imposhible!” Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 6 / 44 Booteo ¿Cómo? Resumiendo Pasos a seguir en el booteo: 1 Determinar el disco y la partición a bootear. 2 Determinar dónde está la imagen del kernel en ese disco. 3 Cargar la imagen del kernel en memoria. 4 Pasar a modo protegido. 5 Preparar las estructuras para correr el kernel (Ej: preparar la pila). ¡Todo esto en 510 bytes! Dirı́a un conocido personaje del rock: “Esh imposhible, ¡esh imposhible!” Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 6 / 44 Booteo ¿Cómo? Opciones wiki.osdev.org Geek loading: Apretar todo eso en 510 bytes. Casi imposible. One-stage loading: Hacer una rutina para preparar las estructuras y linkearlo en el inicio de la imagen del kernel. El bootloader salta ahi, esa rutina prepara todo y salta al kernel. Two-stage loading: Hacer la rutina anterior, pero fuera del kernel. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 7 / 44 Booteo ¿Cómo? El bootloader de PSO Vamos a dar un bootloader para que hagan sus ejercicios. El proceso que realiza es el siguiente: Se copia el Bootloader en la posición 0x1000 de la memoria. Se busca el archivo KERNEL.BIN en el diskette. Se copia ese archivo en la posición 0x1200 de la memoria. Se salta y se ejecuta la instrucción en la posición 0x1200 de la memoria. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 8 / 44 Booteo ¿Cómo? Memoria Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 9 / 44 Modo Real Programación en Modo Real ¿Y la programación en modo real? 16 bits. No hay protección de memoria, OJO. No se pueden restringir las instrucciones. AX, CX y DX no son de propósito general. No se pueden usar para acceder a memoria. Los compiladores modernos no generan código para modo real. No queda otra que el assembler. Podemos usar la BIOS tal cual esta (por ejemplo, para imprimir por pantalla). Menos modos de direccionamiento (a continuación). Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 10 / 44 Modo Real Programación en Modo Real Direccionamiento en modo real Únicas opciones: [BX + val] [SI + val] [DI + val] [BP + val] [BX + SI + val] [BX + DI + val] [BP + SI + val] [BP + DI + val] [val] Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 11 / 44 Modo Real Programación en Modo Real Direccionamiento en Modo Real Cada dirección de memoria esta definida por un segmento y un offset (de 16 bits cada uno, por supuesto): La forma de calcular a que dirección fisica que corresponde es: (segmento << 4) + offset En el ejemplo: (0x07C0 << 4) + 0x0120 = 0x7C00 + 0x0120 = 0x7D20 Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 12 / 44 Modo Real Programación en Modo Real Direccionamiento en Modo Real ¿Cómo especificamos los segmentos? CS: código DS: datos ES: datos FS: datos GS: datos SS: pila Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 13 / 44 Modo Real Programación en Modo Real Direccionamiento en Modo Real ¿Cómo especificamos los segmentos? CS: código DS: datos ES: datos FS: datos GS: datos SS: pila Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 13 / 44 Modo Real Programación en Modo Real Direccionamiento en Modo Real ¿Cómo especificamos los segmentos? CS:IP (Instruction Pointer) DS: datos ES: datos FS: datos GS: datos SS: pila Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 13 / 44 Modo Real Programación en Modo Real Direccionamiento en Modo Real ¿Cómo especificamos los segmentos? CS:IP (Instruction Pointer) MOV AX, [DS:SI] ES: datos FS: datos GS: datos SS: pila Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 13 / 44 Modo Real Programación en Modo Real Direccionamiento en Modo Real ¿Cómo especificamos los segmentos? CS:IP (Instruction Pointer) MOV AX, [DS:SI] MOV AX, [ES:SI] FS: datos GS: datos SS: pila Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 13 / 44 Modo Real Programación en Modo Real Direccionamiento en Modo Real ¿Cómo especificamos los segmentos? CS:IP (Instruction Pointer) MOV AX, [DS:SI] MOV AX, [ES:SI] MOV AX, [FS:SI] GS: datos SS: pila Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 13 / 44 Modo Real Programación en Modo Real Direccionamiento en Modo Real ¿Cómo especificamos los segmentos? CS:IP (Instruction Pointer) MOV AX, [DS:SI] MOV AX, [ES:SI] MOV AX, [FS:SI] MOV AX, [GS:SI] SS: pila Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 13 / 44 Modo Real Programación en Modo Real Direccionamiento en Modo Real ¿Cómo especificamos los segmentos? CS:IP (Instruction Pointer) MOV AX, [DS:SI] MOV AX, [ES:SI] MOV AX, [FS:SI] MOV AX, [GS:SI] SS:SP (tope de pila) Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 13 / 44 Modo Real Programación en Modo Real A tener en cuenta Estamos solos contra el mundo (no hay librerı́as, no hay printf, ¡no hay nada!). section .data .text .bss .rodata: Estan ligados a los formatos de archivos de los sistemas operativos. Ahora solo tenemos un binario plano, ¡Ojo con ejecutar los datos! ¡Ojo con modificar el código en tiempo de ejecución! No hay segmentation fault. Toda la memoria es “nuestra”. No tenemos protección ni de nosotros mismos. Podemos hacer lo que tenemos ganas, el CPU es nuestro. Hasta que no pasemos a modo protegido, tenemos el mejor 8086 de la historia. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 14 / 44 Modo protegido Comparación Modo Real vs Modo Protegido Diferencias generales: Real Memoria disp. ∼ 1 mb (*) Privilegios Interrupciones Todos hacen todo Llamada a rutina Instrucciones Todas Federico Raimondo (PSO) Protegido Toda (o 4GB por tarea con paginación) 4 anillos (0-3) Depende: interrupt, trap o task gate. Con privilegios Subconjunto, segun privilegio Primeros Pasos 1er cuat 2011 15 / 44 Modo protegido Definiciones Algunas definiciones: A20 Es el bit 20 en la representación de las direcciones de memoria fı́sica. Para poder direccionar mas de 220 direcciones, hay que habilitar el pin 20. Este pin se lo llama A20 Gate o Line. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 16 / 44 Modo protegido Definiciones Algunas definiciones: Tablas de descriptores wiki.osdev.org: En la arquitectura Intel, precisamente en modo protegido, la mayorı́a de las tareas de administración de memoria y manejo de interrupciones se controlan mediante tablas de descriptores. Cada descriptor contiene información sobre un objeto (rutina de interrupción, tarea, segmento de código, segmento de datos, etc) que el CPU puede necesitar. Si se intenta, por ejemplo, cargar un nuevo valor dentro de un registro de segmento, el CPU tiene que verificar los permisos para el area de memoria que se intenta acceder. Intel definió 3 tipos de tablas. La Tabla de Descriptores de Interrupciones (IDT), la Tabla de Descriptores Globales (GDT) y la Tabla de Descriptores Locales (LDT). Cada tabla se define como un par (tamaño, dirección) en los registros LIDT, LGDT, LLDT. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 17 / 44 Modo protegido Definiciones Algunas definiciones: GDT GDT: Global Descriptor Table Cada entrada es de 8 bytes y puede tener alguno de los siguientes descriptores: Descriptor de segmento de memoria. Descriptor de Task State Segment (TSS). Es el estado de la tarea, para hacer cambio de tareas a nivel CPU. Descriptor de LDT. Descriptor de call gate. Se utilizaban para transferir control entre niveles de privilegios. Actualmente no se usan en SO modernos. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 18 / 44 Modo protegido Definiciones Algunas definiciones: LDT LDT: Local Descriptor Table. Contiene lo mismo que la GDT. Y entonces... ¿en que se diferencian? La GDT tiene los descriptores globales y es una sola, mientras que los que tiene la LDT son locales y pueden ser mas de uno. Con locales se refiere a que son locales a una tarea. Cuando se cambia de tarea, se cambia de LDT (hay uno por tarea). Desde que se usa paginación, esta tabla quedo obsoleta. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 19 / 44 Modo protegido Definiciones Direccionamiento en modo protegido (memoria segmentada) Figura: Traducción de dirección lógica a fı́sica Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 20 / 44 Modo protegido Definiciones Direccionamiento en modo protegido (memoria segmentada) Figura: Selector de Segmento Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 21 / 44 Modo protegido Definiciones Algunas definiciones: Descriptores de Segmento Figura: Descriptor de Segmento Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 22 / 44 Modo protegido Definiciones Algunas definiciones: Descriptores de Segmento Figura: Tipos de Descriptores de Segmento Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 23 / 44 Modo protegido 1 Booteo 2 Modo Real 3 Modo protegido Switch a Modo Protegido Definiciones Switch a Modo Protegido 4 Compilación/Linkeo Consideraciones previas Compilación Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 24 / 44 Modo protegido Switch a Modo Protegido Activar Modo Protegido vs Pasar a Modo Protegido Activar el Modo protegido es poner en 1 el bit PE del registro CR0. mov eax, cr0 or eax, 0x1 mov cr0, eax El tema son las consecuencias catastróficas de hacer solamente esto. Por eso hablamos de pasar a modo protegido. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 25 / 44 Modo protegido Switch a Modo Protegido Activar Modo Protegido vs Pasar a Modo Protegido Activar el Modo protegido es poner en 1 el bit PE del registro CR0. mov eax, cr0 or eax, 0x1 mov cr0, eax El tema son las consecuencias catastróficas de hacer solamente esto. Por eso hablamos de pasar a modo protegido. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 25 / 44 Modo protegido Switch a Modo Protegido Activar Modo Protegido vs Pasar a Modo Protegido Activar el Modo protegido es poner en 1 el bit PE del registro CR0. mov eax, cr0 or eax, 0x1 mov cr0, eax El tema son las consecuencias catastróficas de hacer solamente esto. Por eso hablamos de pasar a modo protegido. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 25 / 44 Modo protegido Switch a Modo Protegido Analizando la catástrofe GDT Nulo Código Datos CS DS ES IP AX ... CPU 0x0000 0x0000 0xB800 0x03A6 0x024C ... Código mov eax, cr0 or eax, 0x1 mov cr0, eax Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 26 / 44 Modo protegido Switch a Modo Protegido Analizando la catástrofe GDT Nulo Código Datos CS DS ES IP AX ... CPU 0x0000 0x0000 0xB800 0x03A6 0x024C ... Código mov eax, cr0 or eax, 0x1 mov cr0, eax Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 26 / 44 Modo protegido Switch a Modo Protegido Analizando la catástrofe GDT Nulo Código Datos CS DS ES IP AX ... CPU 0x0000 0x0000 0xB800 0x03A6 0x024C ... Código mov eax, cr0 or eax, 0x1 mov cr0, eax <¿Y ahora?> Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 26 / 44 Modo protegido Switch a Modo Protegido Analizando la catástrofe GDT Nulo Código Datos Código mov eax, cr0 or eax, 0x1 mov cr0, eax CS DS ES IP AX ... CPU 0x0000 0x0000 0xB800 0x03A6 0x024C ... ¿Qué dice CS:EIP? <¿Y ahora?> Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 26 / 44 Modo protegido Switch a Modo Protegido Analizando la catástrofe GDT Nulo Código Datos Código mov eax, cr0 or eax, 0x1 mov cr0, eax CS DS ES IP AX ... CPU 0x0000 0x0000 0xB800 0x03A6 0x024C ... ¿Qué dice CS:EIP? <¿Y ahora?> Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 26 / 44 Modo protegido Switch a Modo Protegido Analizando la catástrofe GDT Nulo Código Datos Código mov eax, cr0 or eax, 0x1 mov cr0, eax CS DS ES IP AX ... CPU 0x0000 0x0000 0xB800 0x03A6 0x024C ... ¿Qué dice CS:EIP? BOOM <¿Y ahora?> Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 26 / 44 Modo protegido Switch a Modo Protegido Solucionando la catástrofe GDT Nulo Código Datos Código mov eax, cr0 or eax, 0x1 mov cr0, eax CS DS ES IP AX ... CPU 0x0000 0x0000 0xB800 0x03A6 0x024C ... ¿Qué dice CS:EIP? BOOM ¿Qué deberı́a decir CS? 0x0008 <¿Y ahora?> Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 26 / 44 Modo protegido Switch a Modo Protegido Solucionando la catástrofe GDT Nulo Código Datos Código mov eax, cr0 or eax, 0x1 mov cr0, eax CS DS ES IP AX ... CPU 0x0000 0x0000 0xB800 0x03A6 0x024C ... ¿Qué dice CS:EIP? BOOM ¿Qué deberı́a decir CS? 0x0008 ¿Y cómo cambiamos el registro CS? <¿Y ahora?> Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 26 / 44 Modo protegido Switch a Modo Protegido Solucionando la catástrofe GDT Nulo Código Datos Código mov eax, cr0 or eax, 0x1 mov cr0, eax CS DS ES IP AX ... CPU 0x0000 0x0000 0xB800 0x03A6 0x024C ... ¿Qué dice CS:EIP? BOOM ¿Qué deberı́a decir CS? 0x0008 ¿Y cómo cambiamos el registro CS? BOOM mov cs, 0x0008 Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 26 / 44 Modo protegido Switch a Modo Protegido Solucionando la catástrofe GDT Nulo Código Datos Código mov eax, cr0 or eax, 0x1 mov cr0, eax jmp 0x08:modoprotegido modoprotegido: ... Federico Raimondo (PSO) CS DS ES IP AX ... CPU 0x0008 0x0000 0xB800 0x03A6 0x024C ... ¿Qué dice CS:EIP? OK ¿Qué deberı́a decir CS? 0x0008 ¿Y cómo cambiamos el registro CS? OK Primeros Pasos 1er cuat 2011 26 / 44 Modo protegido Switch a Modo Protegido El switch, según intel (teorı́a) 1 Deshabilitamos las interrupciones. (CLI) 2 Cargamos el registro GDTR con la dirección base de la GDT. (LGDT) 3 Seteamos el bit PE del registro CR0. (MOV, OR, MOV) 4 Realizamos un FAR JUMP a la siguiente instrucción. 5 Si habilitamos la paginación, tenemos que tener en cuenta la ubicación de estos códigos antes y después del jump. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 27 / 44 Modo protegido Switch a Modo Protegido El switch, segun intel (continuación de la teorı́a) 6 Si se va a usar la LDT, cargar el registro LDTR. (LLDT) 7 Cargar el registro de tareas con el selector de segmento inicial o una porción de memoria donde se pueda guardar la información del TSS. (LTR) 8 Actualizar la información de los registros DS, ES, GS y FS. (actualmente tienen la información de modo real) 9 Cargar el registro IDTR con el valor de la dirección base y el lı́mite de la IDT. (LIDT). 10 Habilitar las interrupciones. (STI) Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 28 / 44 Modo protegido Switch a Modo Protegido El switch, bien basico 1 Deshabilitamos las interrupciones. (CLI) 2 Cargamos el registro GDTR con la direccion base de la GDT. (LGDT) 3 Seteamos el bit PE del registro CR0. (MOV, OR, MOV) 4 Realizamos un FAR JUMP a la siguiente instruccion. 5 Actualizar la informacion de los registros DS, ES, GS, FS y SS. (actualmente tienen la informacion de modo real) Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 29 / 44 Modo protegido 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Switch a Modo Protegido BITS 16 extern kernel_start extern GDT_DESC global start start : call enable_A20 lgdt [ GDT_DESC ] mov eax , cr0 or eax , 0 x1 mov cr0 , eax jmp 0 x08 : modo_protegido BITS 32 modo_ protegido : mov ax , 0 x10 mov ds , ax mov es , ax mov fs , ax mov ss , ax mov esp , 0 xA0000 mov ebp , 0 xA0000 xchg call jmp $ bx , bx kernel_start %include " a20 . asm " Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 30 / 44 Compilación/Linkeo 1 Booteo 2 Modo Real 3 Modo protegido Consideraciones previas Definiciones Switch a Modo Protegido 4 Compilación/Linkeo Consideraciones previas Compilación Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 31 / 44 Compilación/Linkeo Consideraciones previas Origen del programa Cuando compilamos bajo un sistema operativo, todos los compiladores asumen que la dirección de inicio de nuestro programa es la 0x00000000 . Cada etiqueta se traduce a una dirección, y en muchos casos se hacen saltos o llamadas a direcciónes absolutas. ¿Y si no estamos en un sistema operativo? Por ejemplo, el archivo KERNEL.BIN se carga en la dirección 0x1200 Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 32 / 44 Compilación/Linkeo Consideraciones previas Origen del programa Cuando compilamos bajo un sistema operativo, todos los compiladores asumen que la dirección de inicio de nuestro programa es la 0x00000000 . Cada etiqueta se traduce a una dirección, y en muchos casos se hacen saltos o llamadas a direcciónes absolutas. ¿Y si no estamos en un sistema operativo? Por ejemplo, el archivo KERNEL.BIN se carga en la dirección 0x1200 Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 32 / 44 Compilación/Linkeo Consideraciones previas Ejemplo Sin direccion de origen 0x0630 ciclo: nop ... call ciclo Con direccion de origen en 0x1200 0x1830 ciclo: nop ... call ciclo Si la version de la izquierda se carga en la posición 0x1200 , el call se sigue haciendo a la posición 0x0630 , o sea, a cualquier lado. El efecto de la direccion de origen es cambiar la forma en que se traducen las etiquetas en direcciones al momento de compilar. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 33 / 44 Compilación/Linkeo Consideraciones previas Origen del programa Hay 2 formas de hacerlo, segun como se compile: Si compilamos de assembler a binario, usamos la directiva ORG al inicio del archivo.asm para indicar la direccion de origen. Ej: ORG 0x1200 . Si compilamos de assembler a elf, usamos el parámetro -Ttext en el linker. Ej: -Ttext 0x1200 . Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 34 / 44 Compilación/Linkeo Compilación Compilación de assembly en formato bin roquenio@woody$ nasm -fbin archivo.asm -o archivo.bin Consideraciones: Todo el código ejecutable tiene que estar incluido (No hay librerı́as). Se ejecuta tal cual se escribió, no hay entry point. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 35 / 44 Compilación/Linkeo Compilación Compilación de assembly en formato elf32 y linkeo Compilación: roquenio@woody$ nasm -felf32 archivo.asm -o archivo.o Linkeo: roquenio@woody$ ld -static -m elf i386 --oformat binary -b elf32-i386 -e start -Ttext 0x1200 archivo.o -o archivo.bin Consideraciones: Se pueden usar librerı́as. No se respeta el entry point. El parámetro Ttext da el orı́gen de la sección .text. Por ejemplo, esto se usa para hacer saltos a posiciones absolutas de memoria. Si usan el Bootloader de Orga 2, deben usar 0x1200 como origen de la sección .text. Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 36 / 44 Compilación/Linkeo Compilación Compilación de C en formato elf32 y linkeo Ojo, solo sirve cuando ya estamos en modo protegido. Compilación: roquenio@woody$ gcc -m32 -g -ggdb -fno-zero-initialized-in-bss -fno-stack-protector -ffreestanding -c -o archivo.elf archivo.c Linkeo: roquenio@woody$ ld -static -m elf i386 -nostdlib -N -b elf32-i386 -e start -Ttext 0x1200 -o archivo.elf archivo.o Lo convertimos en binario: roquenio@woody$ objcopy -S -O binary archivo.elf archivo.bin Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 37 / 44 Compilación/Linkeo Compilación Compilacion de un bootloader y creacion de diskette Creamos un diskette vacio: roquenio@woody$ dd bs=512 count=2880 if=/dev/zero of=diskette.img Formateamos la imagen en FAT12: roquenio@woody$ sudo mkfs.msdos -F 12 diskette.img -n ETIQUETA Escribimos en el sector de booteo: roquenio@woody$ dd if=bootloader.bin of=diskette.img count=1 seek=0 conv=notrunc Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 38 / 44 Compilación/Linkeo Compilación Copiado del KERNEL.BIN adentro del diskette roquenio@woody$ mcopy -i diskette.img kernel.bin ::/ Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 39 / 44 Compilación/Linkeo Compilación Fin ¡GANÉ! Figura: Un groso Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 40 / 44 Compilación/Linkeo Compilación Ejercicio 1 Crear el archivo klib.c en el directorio kernel/ y su correspondiente klib.h en el directorio include/ que contendrán las funciones de biblioteca para usar dentro del kernel. Realizar todas las modificaciones necesarias para que sea incluido en la compilación. 2 Programar las funciones necesarias para poder escribir en pantalla un texto arbitrario en una posición y de color arbitrarios, similar. 3 Extienda la funcionalidad para poder escribir números en decimal o hexadecimal en pantalla. 4 Modificar el archivo kernel.c para que cuando empiece muestre el estado de todos los registros del procesador en la pantalla: De segmento: cs, ds, es, fs, gs, ss De control: cr0, cr2, cr3, cr4 Internos: gdtr, ldtr, idtr, tr Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 41 / 44 Compilación/Linkeo Compilación Código C, con una pisca de Assembler Desde C se puede ejecutar un poquito de assembler fácilmente como funciones. #define LS_INLINE static __inline __attribute__(( always_inline)) /* Prototipos */ LS_INLINE void lcr0(uint_32 val); LS_INLINE uint_32 rcr0(void); /* Funciones */ LS_INLINE void lcr0(uint_32 val) { __asm __volatile("movl %0, % %cr0" : : "r" (val)); } LS_INLINE uint_32 rcr0(void) { uint_32 val; __asm __volatile("movl % %cr0, %0" : "=r" (val)); return val; } Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 42 / 44 Compilación/Linkeo Compilación La memoria de video La memoria de video comienza en la dirección 0xB8000. La matriz de video tiene 80 columnas y 25 filas. Cada elemento es de 2 bytes. El primero es el modo y el segundo es el caracter ASCII. Cada bit del color del modo de video indica las componentes RGB (8 colores). Figura: Byte de modo de video Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 43 / 44 Compilación/Linkeo Compilación Caracteres ASCII Figura: tabla de caracteres ascii Federico Raimondo (PSO) Primeros Pasos 1er cuat 2011 44 / 44