Laboratorio de Sistemas Operativos

Anuncio
Laboratorio de Sistemas Operativos
Primer Parcial
Fecha de entrega: Jueves 14 de octubre de 2010
Planteamiento del problema
Se deberá desarrollar un sector de arranque y un minikernel que lea una tabla de
particiones de una imagen de disco duro, y que imprima la información de las
particiones descritas en dicha tabla.
El sector de arranque y el mini-kernel se ubicarán en una imagen de floppy, dese la
cual debe arrancar el emulador (bochs o qemu). El sector de arranque, leído por la
BIOS a la posición de memoria 0x7C001 deberá copiarse a sí mismo a la posición de
memoria 0x500 (la primera posición de memoria disponible en modo real), y luego
deberá leer el mini-kernel que se encuentra contiguo al sector de arranque en la
imagen de diskette a la posición de memoria 0x1000.
El mini-kernel leído deberá implementar la funcionalidad básica para leer a RAM el
primer sector de una imagen de disco duro (suministrada por el profesor). De este
primer sector deberá extraer la tabla de particiones (1), (2) que se encuentra en una
posición fija dentro del primer sector. Ver documentación adicional suministrada.
De la tabla de particiones extraída, el mini-kernel deberá interpretar cada entrada (que
corresponde a una partición) e imprimir por pantalla la estructura de cada una de ellas.
Esta se compone de:
 Tipo de partición
 Inicio de la partición
 Fin de la partición
 Tamaño de la partición
Para imprimir la información por pantalla, el mini-kernel no podrá usar los servicios de
la BIOS. En vez de ello, el mini-kernel deberá imprimir los caracteres directamente en
la memoria de video que se encuentra mapeada a la RAM, como se explica en la
documentación adicional suministrada.
Se puede tomar como base para resolver el parcial el código del proyecto
„05_load_kernel‟ de los ejemplos de modo real para el aprendizaje de sistemas
operativos.
Condiciones de entrega
Se deberá entregar un archivo comprimido (en formato zip) que contenga una carpeta
con nombre login1_login2 (donde login1_login2 son los login de usuario del correo
electrónico de los integrantes del grupo). Esta carpeta deberá contener los siguientes
archivos:

1
README.txt: archivo que contiene el nombre y el código de los integrantes.
También puede incluir aclaraciones, comentarios inconvenientes y soluciones
relacionadas con el problema.
La representación numérica 0X#### se usa para expresar un número en formato
hexadecimal. También se puede utilizar la representación ####h ó ####H.




bochsrc.txt: archivo de configuración de bochs para ejecutar la imagen de disco
creada
bootsect.s: código fuente del sector de arranque
kernel.s: código fuente del kernel
Makefile: archivo de configuración de la utilidad make, que deberá contener
como mínimo las siguientes reglas:
o all: crear la imagen de disco (floppy)
o bochs: arrancar el emulador bochs para ejecutar el bootsector creado
o qemu: arrrancar el emulador qemu para ejecutar el bootsector creado
o clean: borrar los archivos de compilación y la imagen de disco
Calificación
La lista de verificación que se usará para calificar el parcial es la siguiente:
LISTA DE VERIFICACIÓN
1. Aspectos generales
CUMPLE
(S/N)
1.1 (5 puntos) El programa se entregó de acuerdo con las condiciones
estipuladas y el la fecha indicada
1.2 (2 puntos) El programa incluye documentación que indica los
autores, la fecha de creación y el problema que soluciona
1.3 (2 puntos) El programa se encuentra estructurado (en rutinas) de
acuerdo con las características del problema
1.4 (2 puntos) Las rutinas se encuentran correctamente documentadas
en términos de parámetros de entrada y descripción general de su
funcionamiento
1.5 (2 puntos) Las secciones críticas del programa se encuentran
documentadas
1.6 (2 punto) El código fuente se encuentra estructurado correctamente
(por ejemplo, permite ver con claridad el inicio y fin de las rutinas y los
ciclos)
2. Funcionamiento del programa
2.1 (15 puntos) El sector de arranque se copia en la posición 0x500, y
una vez copiado carga el mini-kernel de la imagen de floppy a la
posición 0x1000 y le pasa el control al kernel
2.2 (70 puntos) El kernel implementa en forma correcta la funcionalidad
requerida en el planteamiento del problema:
 (15 puntos)Leer el primer sector de una imagen de disco duro a
memoria RAM
 (15 puntos) Extraer la tabla de particiones del primer sector
 (40 puntos)Para cada entrada de la tabla de particiones,
imprimir
o Tipo de partición
o Inicio
o Fin
o Tamaño
En caso que alguna de las características no se cumpla completamente, se podrá
asignar una calificación proporcional con su cumplimiento.
Anexo. Documentación básica para la solución del
problema
A continuación se presentan algunos aspectos básicos que se deben considerar para
la solución del problema. Si se desea mayor profundidad en los temas presentados, se
deberá recurrir a asesoría o a la revisión de las referencias y el código suministrado
por el profesor en la página web de la asignatura (3).
Proceso general de arranque del computador
Cuando se enciende el computador o se envía la señal RESET a la unidad de control,
el procesador ejecuta la instrucción que se encuentra en el límite de la memoria RAM.
Esta dirección generalmente es mapeada a la BIOS, que a su vez busca el primer
sector del dispositivo configurado como de arranque. Si no lo encuentra en este
dispositivo, continúa con el siguiente dispositivo hasta encontrar un sector de arranque
valido. Si no puede encontrar ningún sector de arranque valido, imprime un mensaje
de error y detiene su ejecución.
El sector de arranque (de 512 bytes) es cargado por la BIOS a la dirección de memoria
0x7C00 (31744 bytes), que es el límite de memoria de 32 K (31744 + 512 = 32256 =
32K). Luego le pasa el control de la ejecución a este sector de arranque.
Además, la BIOS almacena en los 8 bits menos significativos del registro EDX (es
decir, en DL) un valor que indica la unidad desde la cual se cargó el sector de
arranque, el cual puede ser:
1h = floppy
80h = disco duro primario.
Debido al tamaño limitado que tiene un sector de arranque (512 bytes incluyendo la
tabla de particiones), este sólo contiene la funcionalidad necesaria para continuar con
la carga del kernel. De esta forma, la carga de un sistema operativo completo
generalmente se realiza por medio de pequeños programas que se cargan y se
transfieren el control en forma secuencial (el primero de ellos es lógicamente el sector
de arranque). A este proceso e le conoce como “arranque por fases”.
Todo sector de arranque tiene un tamaño predeterminado de 512 bytes, y sus últimos
2 bytes (510 y 511) deberán contener la palabra 0xAA55, que se conoce como la
"firma del sector de arranque", o bootsector signature.
Modo real (Procesadores x86)
Cuando un procesador x86 inicia (luego de PWR o RESET) se establece un entorno
de ejecución de modo real, en el cual se comporta básicamente como un 8086 con un
conjunto de instrucciones muy limitado, y en el cual sólo son válidas operaciones de
16 bits. Adicionalmente, en modo real sólo es posible acceder al primer Megabyte de
memoria RAM, debido a que la línea de dirección 20 (conocida como la puerta A20) se
encuentra desactivada. Un esquema de los registros del procesador en modo real se
muestra a continuación:
MODO REAL (16 bits)
15
Registros de
propósito
general
(No se usa en
modo real)
Registros de
segmento
0
15
31
0
CS
(E)
AX
DS
(E)
BX
ES
(E)
CX
FS
(E)
DX
GS
(E)
SI
(E)
DI
(E)
SP
(E)
BP
SS
Organización de memoria en modo real
Debido a que en modo real todo procesador se comporta como un 8086 (registros de
16 bits), con estos registros sólo es posible referenciar regiones de memoria de 64 KB
(cuando todos los bits de un registro de 16 bits se encuentran en 1, la máxima
dirección de memoria es 2 16 = 65535). Los diseñadores de Intel desarrollaron una
estrategia que permitía acceder hasta 1 MB de memoria, basada en el concepto de
segmentación.
La segmentación se implementa por medio de dos clases de registros: los registros de
segmento (CS para el segmento de código, SS para la pila, DS para el segmento de
datos, y ES, FS y GS como segmentos adicionales de datos) y los registros de
propósito general (AX, BX, CX, DX, SI y DI, además de SP y BP).
Los valores de estos registros se combinan para crear una dirección lógica (de la
forma segmento : offset), que permite referenciar cualquier dirección lineal desde 0
hasta 1 Megabye. Con el fin de permitir que el procesador pudiera acceder a un mayor
espacio de memoria, el valor que se almacena en los registos de segmento (la
dirección lineal de inicio del segmento en memoria) se encuentra dividido por 16.
La siguiente figura ilustra cómo se puede obtener una dirección lineal (de memoria) a
partir de una dirección lógica.
Ejemplo: para la dirección 0x7C00
Dir. Lógica (seg:offset)
Reg. de segmento
* 16
Reg. de propósito general
+
DS
0x7C0
* 16
SI
0x00
+
=
Dirección lineal (20 bits)
0x7C00
Por ejemplo, para referenciar la dirección de memoria en la cual se carga el sector de
arranque (0x7C00), haciendo uso del registro de segmento DS (datos), y del registro
de propósito general SI, DS deberá contener 0x7C0 y SI deberá contener 0x00. Al
multiplicar DS por 16 (que en un número hexadecimal implica desplazar un dígito a la
izquierda), se obtiene:
DS*16 + SI = (0x7C0 * 0X10) + 0x00 = 0x7C00 + 0x00 = 0x7C00.
De la misma forma, para referenciar la dirección inicial de la memoria de video
(0xB8000), por ejemplo se puede hacer uso de los registros ES y DI de la siguiente
forma:
ES = 0xB800, DI = 0x00, entonces:
ES:DI = ES * 0X10 + %di = (0xB800 * 0X10) + 0x00 = 0xB8000.
Se puede ver que la dirección física obtenida contiene 20 bits, con la siguiente gráfica:
Segmento * 16
Desplazamiento
Dirección
física
Como se mencionó en clase, la misma dirección lineal (físca) en modo real se puede
obtener usando 4096 combinaciones diferentes de valores para segmento y
desplazamiento.
Es importante resaltar que no se puede asignar un valor directamente en un registro
de de adtps. Para lograr este propósito, primero se asigna el valor al registro AX, y
luego el valor se pasa de AX al registro de segmento indicado. Por ejemplo, para
mover 0xB800 al registro ES, se deben realizar los siguientes pasos en ensamblador
(sintaxis Intel):
mov ax, 0xB800
mov es, ax
Mapa de memoria en modo real
Cuando el computador arranca y pasa el control a la BIOS, ésta realiza un diagnóstico
inicial del hardware y configura el primer Megabyte de memoria RAM como se
presenta a continuación (las direcciones se presentan en formato hexadecimal).
00
Inicio
Fin
3FF
Tamaño
400
500
4FF
7BFF
255 bytes
30643 bytes (aprox
59 sectores, 30 KB)
7C00
7DFF
512 bytes
7E00
80000
9FC00
A0000
7FFF
9FBFF
9FFFF
FFFFF
480 KB (aprox)
120 KB (aprox)
1 KB
384 KB (aprox)
1 KB
Descripción
Tabla de interrupciones del modo
real
Área de datos de la BIOS
Memoria convencional (usable).
En esta región se deberá copiar el
sector de arranque y el minikernel.
Posición de memoria en la cual la
BIOS carga el sector de arranque
Memoria convencional (usable)
Memoria convencional (usable)
Área de datos de la BIOS extendida
Área de ROM
A su vez, el área de ROM (ubicada de de A0000 a FFFF) se divide de la siguiente
forma:
Inicio
A0000
B0000
Fin
AFFFF
B7FFF
64 KB
32 KB
Tamaño
B8000
BFFFF
32 KB
C0000
C8000
C7000
EFFFF
32 KB
160 KB
F0000
FFFFF
64 KB
Descripción
Framebuffer VGA
Memoria de video en modo texto,
monocromático
Memoria de video en modo texto,
a color
BIOS de Video (ROM)
Hardware mapeado en memoria y
dispositivos varios
BIOS
Memoria de video en modo texto
La memoria de video en modo texto a color (que en la pantalla se dispone en 25 líneas
de 80 caracteres cada una) inicia en la dirección 0xB8000, y es un espacio lineal que
ocupa 32 KB de memoria. Cada carácter en que se muestra en la pantalla ocupa 2
bytes en la memoria de video (un word): un byte contiene el código ASCII del carácter,
y el otro byte contiene los atributos de color de texto y color de fondo del carácter.
La siguiente figura ilustra cómo se encuentra mapeada la memoria de video a la
dirección de memoria RAM 0xB8000.
Pantalla
RAM
0
A B
…
…
Atributos de texto
0xB8002
0x42 = „B‟
0xB8001
Atributos de texto
0xB8000
0x41 = „A‟
80x25
Bootsector
0x7C00
IVT
A su vez, el byte para los atributos de texto (color de texto y de fondo) se divide en
fracciones, que representan el color de texto y el color de fondo (4 bits cada uno).
Esto quiere decir que en modo texto a color se tienen 16 combinaciones diferentes (24
= 16) para los colores de texto y de fondo.
Lo anterior se ilustra en el siguiente esquema:
Atributos de texto
Carácter ASCII
7
15
0
b = blink
b
fondo
texto
De esta forma, para mostrar un carácter en la esquina superior de la pantalla (línea 0,
carácter 0) se deberá escribir un word (2 bytes) en la dirección de memoria 0xB8000.
El primer byte de este word será el código ascii a mostrar, y los siguientes bytes
representarán el color de texto y de fondo del carácter. El siguiente word (ubicado en
la dirección de memoria 0xB8002) corresponde al segundo carácter en la pantalla, y
así sucesivamente.
Los colores válidos se muestran en la siguiente tabla2:
Valor
Color
Valor
Color
0
black
8
dark gray
1
blue
9
bright blue
2
green
10
bright green
3
cyan
11
bright cyan
4
red
12
pink
5
magenta 13
bright magenta
6
brown
14
yellow
7
white
15
bright white
Los colores 0-15 son válidos para el color de texto. Sin embargo para el fondo solo es
posible utilizar los colores del 0 al 7, debido al que el 8 bit se utiliza para el “blink”
(texto que aparece y desaparece).
Por ejemplo, para imprimir el carácter „A‟, (al cual le corresponde el código ASCII 65,
0x41 en hexadecimal) con color blanco sobre fondo negro en la esquina superior de la
pantalla, se deberá copiar el word 0x0741 en la dirección de memoria 0xB8000.
Se puede observar la posición XY de un carácter en la pantalla se puede obtener de la
siguiente forma:
Pos_XY = 0xB8000 + ((80*i) + j) *2
En donde 0xB8000 es la dirección base de la memoria de video (esquina superior
izquierda), i representa la fila, j representa la columna. Se debe multiplicar por 2
debido a que cada carácter en la pantalla en realidad ocupa 2 bytes, uno para el
código ascii y otro para los atributos de color de texto y fondo.
Servicios de la BIOS
La BIOS (Basic Input/Output System) ofrece una serie de servicios que pueden ser
utilizados en modo real. Los servicios necesarios para este parcial se explican en
forma general a continuación3:
Servicio
INT
Leer sectores de un 13h
dispositivo
2
Descripción
Los registros deberán contener los siguientes
valores:
Información extractada de http://files.osdev.org/mirrors/geezer/osd/cons/index.htm.
Aquí se utiliza la notación ##h para representar un número hexadecimal. En GNU Assembler
(sintaxis Intel), la instrucción para invocar la interrupción 13h sería: int 0x13
Para una lista completa de los servicios de la BIOS, consultar el enlace a la documentación
presentado en la página de la asignatura.
3
AH = 02h (Read sectors from drive)
AL = Número de sectores a leer
CH = 8 bits menos significativos del cilindro
CL = (bits 0-5) número del sector, (bits 6-7) 2 bits
más significativos del cilindro
DH = Cabeza
DL = Dispositivo del cual se desean leer los
sectores (0x00 = floppy, 0x80=disco duro)
ES:BX deberá contener la dirección lógica de la
posición de memoria en la cual se desean
almacenar los lectores leídos.
Este servicio guarda en AL el número de sectores
leídos, y establece el Flag de Acarreo en 0 si la
lectura fue correcta, o 1 si se presentó algún error.
Lee una tecla
16h
AH = 00h (Read Character)
Este servicio guarda el character leído en AX:
AH contiene el scan code
AL contiene el código ASCII del carácter que se
leyó.
Es importante resaltar que el servicio de la BIOS para leer sectores de disco funciona
con una geometría de Cilindros, Cabezas (Heads) y Sectores (C/H/S). Por esta razón
tiene algunas limitaciones:
Debido a que el número de la cabeza se almacena en DL (registro de 8 bits), sólo es
posible referenciar de la cabeza 0 a la cabeza 255 (2 8 = 256 cabezas). Igualmente,
como sólo se cuenta con 10 bits para el cilindro (8 bits en CH y 2 bits en CL), sólo se
puede referenciar del cilindro 0 al 1023 (2 10 = 1024 cilindros). De la misma forma, solo
se cuenta con 6 bits para el número del sector, por lo cual sólo es posible referenciar
del sector 0 al sector 63 (2 6 = 64). De esta forma, los servicios de la BIOS sólo
permiten referenciar los primeros 8.5 GB de un disco duro:
(Cilindros * Heads * Sectores) * 512 = 8.5 GB
Como se mencionó anteriormente, cuando se utiliza el servicio de leer sectores de un
drive, la BIOS guarda en AL el número de sectores leídos, y establece el Bit de
Acarreo dentro del registro FLAGS en 0 si la lectura fue correcta, o 1 si se presentó
algún error. Generalmente no se deberían presentar errores al leer el kernel, pero es
aconsejable validar si la lectura fue correcta.
Tabla de particiones
La tabla de particiones se encuentra dentro del primer sector de la imagen de disco, a
un desplazamiento exacto de 446 bytes (0x1BE) desde el inicio del sector. Una tabla
de particiones tiene el siguiente formato (1), (2):
Desplazamiento dentro del
sector
Hex
Decimal
0x1BE
446
0x1CE
462
0x1DE
478
0x1EE
494
Tamaño
(bytes)
16
16
16
16
Descripción
Descriptor de la primera partición
Descriptor de la segunda partición
Descriptor de la tercera partición
Descriptor de la cuarta partición
Cada entrada de la tabla describe una partición, por lo cual solo es posible tener
cuatro particiones primarias en un disco duro4.
Descriptores de partición
Cada descriptor ocupa exactamente 16 bytes, y describe las siguientes características
de una partición:
 Indicador de arranque (1 byte). Indica si la partición está habilitada para que
desde ella la BIOS lea el sector de arranque. En cualquier momento sólo puede
existir una partición de arranque. Los valores válidos son: 0x00 (inactiva), y
0x80 (arranque)
 Inicio de la partición (3 bytes): Contiene la dirección de inicio de la partición, en
formato C/H/S.
 Tipo de la partición (1 byte): Describe el tipo del sistema de archivos presente
en la partición.
 Fin de la partición (3 bytes): Contiene la dirección de fin de la partición, en
formato C/H/S
 Sector de inicio de la partición (4 bytes): Contiene el sector absoluto de inicio
de la partición (en formato LBA). Para un disco con N sectores, este atributo
tiene un valor entre 0 (primer sector) y N-1 (último sector)
 Tamaño de la partición (4 bytes). Especifica el tamaño en sectores de la
partición.
Para mayor información acerca de la tabla de particiones, consultar las referencias (1)
y (2).
Bibliografía
1. Partition Table - OsDevWiki. [En línea] [Citado el: 30 de Septiembre de 2010.]
http://wiki.osdev.org/Partition_Table.
2. Sedory, Daniel B. MBR/EBR Partition Tables. [En línea] 2004-2007. [Citado el: 30
de Septiembre de 2010.] http://mirror.href.com/thestarman/asm/mbr/PartTables.htm.
3. Meza, Erwin. Laboratorio de Sistemas Operativos. [En línea] 2010. [Citado el: 30 de
Septiembre de 2010.] http://artemisa.unicauca.edu.co/~emezav/operativos_lab.
4
No obstante, una de ellas puede ser de un tipo especial, llamado “partición extendida”, y
dentro de esta partición extendida es posible definir hasta 24 “sub-particiones” llamadas
“particiones lógicas”. Por esta razón es posible crear más de cuatro particiones en un disco
duro.
Descargar