|
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
|
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.
[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.