G A C E T A   D E   L I N U X
...haciendo a Linux un poco más divertido!
Haciendo tu Propio Floppy de Arranque de Juguete
Por Muhammad Torabi Dashti
Traducción al español por Daniel Guerrero
el día 1 de Febrero 2003, para La Gaceta de Linux

 

Estaba leyendo un artículo fascinante en la Gaceta de Linux #77 Escribiendo tu Propio SO de Juguete-Parte I por Krishnakumar [1]; donde observé algo extraño, los dos últimos bytes del sector de arranque deben ser 0x55AA! Y la respuesta al texto prueba que no era el único jugando con este número mágico. De cualquier forma, reecribí el sector de arranque de Krishnakumar con nasm [2] (no conozco as86) y quité la línea que insertaba el 0x55AA de write.c. Adivina que sucedió, ¡mi PC arrancó! ¿Porqué Krishnakumar escribió ese trozo? o de forma más general ¿quién lee y decide el sector de arranque? La respuesta fue rápida, !lo hace el BIOS! Y otro hecho interesante fue que la IBM publicó su fuente del código del BIOS de la XT en la Referencia Técnica de XT [3]. Así que vamos a echarle un vistazo: (le hice algunos cambios, así que no es el completo y original).

;---INT 19H
BOOT_STRAP:
;ALGUNAS INICIALIZACIONES
	MOV CX,3	;CONTADOR DE INTENTOS
H1:
	PUSH CX
	SUB DX,DX
	SUB AX,AX
	INT 13H	;FLOPPY DE INICIO
	JC H2
	MOV AX,0201H
	SUB DX,DX
	MOV ES,DX
	;PREVIAMENTE BOOT_LOCN FUE DEFINIDO
	;ORG 7C00H
	;ETIQUETA FAR PARA BOOT_LOCN
	MOV BX, OFFSET BOOT_LOCN
	MOV CX,1
	INT 13H	;LEER EL SECTOR 0 DEL FLOPPY
H2:
	POP CX
	JNC H4
	CMP AH,80H	;VERIFICAR TIEMPO AGOTADO
	JZ H5
	LOOP H1
	JMP H5
H4:
	JMP BOOT_LOCN
H5:
	;INTENTAR EN EL DISCO DURO
	SUB AX,AX
	SUB DX,DX
	INT 13H
	MOV CX,3
H6:
	PUSH CX
	MOV DX,0080H
	SUB AX,AX
	INT 13H
	JC H7
	MOV AX,0201H
	SUB BX,BX
	MOV ES,BX
	MOV BX,OFFSET BOOT_LOCN
	MOV DX,80H
	MOV CX,1
	INT 13H
H7:
	POP CX
	JC H8
	MOV AX, WORD PTR BOOT_LOCN+510D
	CMP AX,0AA55H	;¡NUMERO MAGICO!
	JZ H4
H8:
	LOOP H6
	INT 18H	;¡TODO HA FALLADO!

¡Está bien! todo se volvió claro acerca de que 0x55AA es verificado sólo si el sector de arranque es cargado de un disco duro, así que Krishnakumar lo usó para asegurarse de la compatibilidad. También date cuenta que cualquier cadena aleatoria en el sector 0 de un floppy es considerada como el sector de arranque y ¡el sistema lo ejecuta!.

Debido a que uso Windows 2000 aparte de mi Linux y mis floppies siempre tienen el sistema de archivos de msdos (fat 12) así que ambos SO's pueden leerlos. Ahora realiza un simple experimento: formatea un floppy usando Windows (o cualquier sistema operativo basado en DOS) y deja que el sistema inicie desde tu floppy. Verás un mensaje que indica que no es un disco de arranque y te solicita que lo sustituyas y presiones cualquier tecla. Este es el caso cuando formateas el floppy en Linux y le pones un sistema de archivos msdos en el también (mkfs -V -t msdos /dev/fd0, puede ser el comando o si usas KDE, su utilidad de formateo de floppy puede hacer lo mismo). Y las cosas se vuelven más extrañas cuando pones un sistema de archivos ext2 en un floppy (#mkfs -V -t ext2 /dev/fd0). Tu PC simplemente ifnora el floppy y el control es transfeido al sector de inicio de tu disco duro (p.e. Lilo). Así que ¿cuál es la diferencia entre estos dos formatos y con tu propio disco floppy de inicio? He cambiado el achivo write.c de Krishnakumar y su archivo read.c lee el sector de inicio de un floppy y lo guarda en un archivo boot.sec; también lo vacía de una manera bastante formateada. Si quieres usar las herramientas propias de Linx para hacer lo mismo: para escribir el sector de arranque en el floppy (#dd if=boot.sec of=/dev/fd0 bs=1 count=512) y para leer el sector de arranque de un floppy (#dd if=boot.sec of=/dev/fd0 bs=1 count=512 skip=0).

Observa el sector de arranque de ext2. !Son puros ceros! pero el sector de arranque de msdos contiene algunos comandos. Vamos a desensamblarlo (yo uso ndisasm[2]):

1.inserta un floppy formateado con msdos

2. ejecuta "./read"

3. ejecuta "ndisasm boot.sec | more"

4.La primera instrucción es un salto a 0x3e pero el código no está alineado correctamente.

5. ejecuta "ndisasm -s 0x3e boot.sec | more" para ver el código alineado

Así que en este caso, tenemos un pequeño cargador de inicio, simplemente muestra un mensaje (el mensaje es dependiente del SO, y puedes cambiarlo con cualquier editor binario como alguno en KDE. Por ejemplo cambia boot.sec para que despliegue un mensaje gracioso y después ¡reescríbelo usando el archivo write.c de Krishnakumar en el floppy!) entonces espera por una tecla e invoca nuevamente a int 0x19 (el procedimiento del BIOS boot_starp). De hecho, MS DOS usa para almacenar alguna información (FAT) en el espacio entre los jmp 0x3e 0x3e en si mismo y esta forma es seguida por sus sucesores; eso es porqué existe un salto ahí. Puedes encontrar algo de información sobre el sistema de archivos de MS DOS en la red o consultando [4].

En este punto todo es lógico, el BIOS simplemente ejecuta lo que encuentra en el sector de rranque, puede ser nuestro juguete "muestra una A y detente" o un sector de arranque elegante como msdos. Pero cuando desensamblé el sector de arranque ext2, nada me fue claro, ¡estaba lleno de ceros que significaban muchas instrucciones ADD ridículas! ¿porqué el BIOS la ignora simplemente y no se estanca ahí? La respuesta es que el BIOS ¡cambió de XT a AT! y pude encontrar una fuente AT BIOS en la red (desafortunadamente no tiene la referencia, pero probablemente la Referencia Técnica de la AT de IBM incluía este código boot_strap también)

;---INT  19H
BOOT_STRAP_1	PROC 	NEAR
;ALGUNAS INICIALIZACIONES
;LIMPIAR @BOOT_LOCN
	STI
	MOV	CX,4
H1:	PUSH	CX
	KTOV	AH,0
	INT	13H
	JC	H2
	MOV	AX,201H
	SUB	DX,DX
	MOV	ES,DX
	MOV	SX,OFFSET @BOOT_LOCN
	MOV	CX,1
	INT	13H
H2:	POP	CX
	JNC	H4
	CMP	AH,80H
	JZ	H5
	LOOP	H1
	JMP	SHORT H5
H4:	CMP	BYTE PTR @BOOT_LOCN,06H	;PRUEBA #1
	JB	H10
	MOV	DI,OFFSET @BOOT_LOCN
	MOV	CX,8
	MOV	AX,WORD PTR @BOOT_LOCN
H4A:	ADD	DI,2
	CMP	AX,[DI]	;PRUEBA #2
	LOOPZ	H4A
	JZ	H10
H4_A:	JMP	@BOOT_LOCN
H5:	
	;ALGUNAS INICIALIZACIONES y PRE-PRUEBAS
	SUB	AX,AX
	SUB	DX,DX
	INT	13H
	MOV	CX,3
H6:
	PUSH	CX
	MOV	DX,0080H
	MOV	AX,0201H
	SUB	BX,BX
	MOV	ES,BX
	MOV	BX,OFFSET @BOOT_LOCN
	MOV	CX,1
	INT	13H
	POP	CX
	JC	H8
	CMP	WORD PTR @BOOT_LOCN+510D,0AA55H ; ¡NUMERO MAGICO!
	JZ	H4_A
H8:	PUSH	CX
	MOV	DX,0080H
	SUB	AX,AX
	INT	13H
	POP	CX
	JC	H10A
	LOOP	H6
H9:	
	;ALGUNAS COSAS QUE NO SON DE NUESTRO INTERES
	INT	18H
H10A:	LOOP	H8
	JMP	H9
H10:	;IMPRIMIR UN MENSAJE
H11:	jmp H11
BOOT_STRAP_1	ENDP

Dos nuevas pruebas son agregadas al sector de arranque del floppy:

1. ¡Su primer byte debe ser más que 0x6! lo que significa que la primera instrucción no puede ser ADD (El OpCode 0 a 5 son para diferentes modos de ADD). ¿Porqué? Es lógico, debido a que ningún programador sabio agregaría valores casi desconocidos del registro al inicio. Y si esto sucede (como en el caso de ext2) un mensaje se muestra y la PC espera para resetearse. ¡el rompecabzas se resolvió parcialmente!. En mi PC, el control simplemente es pasado al sector de arranque del disco duro. Claro es mejor, en estos días casi cualquier PC tiene un disco duro. Quizas ese es un cambio en el BIOS después de los iniciantes AT.

2.Las primeras 8 palabras no pueden ser lo mismo. ¿porqué? no lo sé. Parece ser sólo una decisión, puedes probarlo fácilmente, agregar 16 NOPs (0x90) al sector de inicio de Krishnakumar, y entonces no iniciará tu PC.

Ahora puedes usar esas herramientas (read.c y write.c) o las herramientas propias de Linux (e.g. el adorable comando 'dd') para investigar más sobre la estructura de los sectores de arranque. Como un experimento interesante para cualquiera que tiene Windows así mismo como Linux y usa Lilo como su cargador de inicio (que resida en el MBR): ¡hacer un menú de inicio recursivo! Los pasos necesarios son:

1. utiliza 'dd' o 'read.c' para leerel MBR: #dd if=/dev/hda of=mbr.sec bs=1 count=512 skip=0

2. de alguna forma copia el archivo mbr.sec a tu partición de inicio (casi siempre c:\), puedes usar estos programas elegantes de John Newbigin cuando todas tus soluciones fallen.

3. edita boot.ini y agrega una línea al final: c:\mbr.sec = "LiLo Again!"

Y así es como el proceso de inicio sucede.

Referencias:

[1]http://www.tldp.org/LDP/LG/issue77/krishnakumar.html 

[2]http://nasm.sourceforge.net/ 

[3]IBM, "IBM Personal Computer XT Technical Reference", Vol.2,1981. 

[4]M.A.Mazidi, J.G.Mazidi, "The 80X86 IBM PC & Compatible Computers",Vol.2, Prentice Hall, 1995.


Copyright © 2002, Muhammad Torabi Dashti. Licencia de Copiado http://www.linuxgazette.com/copying.html
Publicado en la edición 84 de Linux Gazette, Noviembre 2002