Montar una imagen raw de Qemu. Los primeros 32 Kbytes de un disco.
El Qemu es un emulador con licencia GPL/LGPL. Podemos usarlo para, por ejemplo, arrancar un Windows 2000 dentro de Linux y tener esas poquitas cosas que aún no se pueden hacer en Linux. En mi caso, sobre todo, usar el Internet Explorer para ciertas webs de ciertas empresas que suponen que todos pasamos por la caja de Microsoft a pagarles una licencia de su sistema operativo.
El Qemu emula diferentes plataformas sobre diferentes sistemas operativos. Si usamos el KQemu, recientemente liberado como GPL, el emulador pasa a usar virtualización y la velocidad del sistema operativo “virtualizado” está en el orden de la que obtendríamos con, por ejemplo, VMWare. VMWare es más maduro y estable pero el Qemu tiene muchas opciones con las que jugar fácilmente.
Pues bien, el Qemu soporta varios tipos de formato de imágenes del disco duro. Una de ellas es la “raw”, que es como si fuera un dd completo de un disco físico. Para montar una imagen “raw” del qemu se puede usar el siguiente comando:
mount -o loop,offset=32256 imagen_disco /path/punto_montaje
Está claro que lo que hace el comando es buscar el sitio dónde empieza la primera partición para usar la imagen como si se tratara de una “imagen de la partición”, no una “imagen del disco”, pero ¿por qué 32256? ¿tanto espacio hay libre antes de la primera partición? ¿casi 32Kb?
Los primeros 512 bytes de un disco contienen el MBR, de los cuales, los primeros 446 bytes (bytes 0-445) pueden contener el código para el arranque de la máquina y el resto ya es la tabla de particiones. Tan cierto es esto que podemos hacer:
dd if=/dev/zero of=/dev/disco bs=446 count=1
y aunque este disco deja de ser botable las particiones quedan intactas.
Si usamos el comando “sfdisk” para ver dónde están las particiones:
# sfdisk -d /dev/hda # partition table of /dev/hda unit: sectors /dev/hda1 : start= 63, size= 78156162, Id=83 /dev/hda2 : start= 0, size= 0, Id= 0 /dev/hda3 : start= 0, size= 0, Id= 0 /dev/hda4 : start= 0, size= 0, Id= 0
vemos que la primera partición siempre empieza en el sector 63. Esto es porque, como vemos en la salida del “fdisk” de Linux, hay 63 sectores por pista, lo que quiere decir que la primera partición empieza en la pista 1 (que es la segunda, ya que la primera pista es la 0):
Command (m for help): p Disk /dev/hda: 40.0 GB, 40020664320 bytes 255 heads, 63 sectors/track, 4865 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Device Boot Start End Blocks Id System /dev/hda1 1 4865 39078081 83 Linux
Como 63×512=32256, ya hemos aclarado el misterio inicial.
Y nos podemos preguntar… ¿siempre tiene 63 sectores una pista? ¿sólo caben 63×512 bytes en una pista? ¿incluso en los discos modernos enormes (en espacio) o incluso en los diminutos (en tamaño) de 1.8″? La respuesta es que esto era así en los discos antiguos, pero en los IDE esto es algo que se usa sólo por compatibilidad hacia atrás en las BIOS, pero que internamente la controladora de la unidad hace el mapeo de sectores que quiera, tal y como nos explica la WikiPedia en el artículo sobre CHS, sección “History”.
Y ya bien metidos en harina como estamos, podemos querer ver que, efectivamente, en el sector 63 del disco hay un sector de arranque. Para ello, se me ocurre que podemos hacer:
dd if=/dev/hda of=/tmp/bs1 skip=63 bs=512 count=1 dd if=/dev/hda1 of=/tmp/bs21 bs=512 count=1 diff /tmp/bs1 /tmp/bs2
Y, efectivamente, lo son. ¡Pero ojo! Si haces la prueba anterior en un sistema que sólo tiene Linux y que tiene el GRUB en el MBR, la prueba anterior puede no aportar nada, porque el sector estaría vacío (el GRUB y el LILO pueden arrancar Linux sin usar el sector de arranque de la partición para nada):
# hexdump -C /tmp/bs1 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000200
Pero si la prueba la hacemos en un disco con Windows en la primera partición, el sector sí que tiene toda la pinta de ser un sector de arranque de Windows:
# hexdump -C /tmp/bs2 |cut -b 61- |ëR.NTFS .....| |.....ø..?.ÿ.?...| |........ïäç.....| |................| |ö.......ö-÷`;÷`H| |....ú3À.м.|û¸À.| |.Øè..¸...À3ÛÆ...| |.èS.h..hj.Ë..$.´| |.Í.s.¹ÿÿ.ñf.¶Æ@f| |.¶Ñ.â?÷â.ÍÀí.Af.| |·Éf÷áf£ .ôA»ªU.| |.$.Í.r..ûUªu.öÁ.| |t.þ...Ãf`..f¡..f| |....f;. ...:..fj| |.fP.Sfh.....>...| |....è³ÿ.>.....a.| |´B..$....ôÍ.fX[.| |fXfX.ë-f3Òf.·...| |f÷ñþÂ.Êf.ÐfÁê.÷6| |...Ö..$..èÀä..̸| |..Í......À. ..Àf| |ÿ...ÿ.....oÿ..fa| |à ø.è.. û.è..ûëþ| |´..ð¬<.t.´.»..Í.| |ëòÃ..A disk read| | error occurred.| |..NTLDR is missi| |ng...NTLDR is co| |mpressed...Press| | Ctrl+Alt+Del to| | restart........| |......... ³É..Uª|
Para finalizar, ¿se pueden usar para algo esos 31Kbytes libres ((32256-512)/1024) al principio del disco? Pues el GRUB los usa para el Stage 1.5. El GRUB mete un “Stage 1″ en el sector de arranque (512bytes), y como en ese espacio hay lugar para tan pocas cosas, lo único que hace es cargar el “Stage 1.5″ que viene justo a continuación del MBR y que es un programa que sabe cómo gestionar los distintos tipos de filesystem para poder cargar el “Stage 2″ desde el filesystem donde esté. El “Stage 2″ es el programa que finalmente nos saca el menú de GRUB tal y como lo conocemos y que es a muchos efectos como un mini sistema operativo.
Mirando los ficheros del directorio “/boot/grub” vemos los 512 bytes del stage1, los *_stage1_5 de los distintos filesystems de tamaño inferior a 31 Kbytes y el stage2 que puede estar en una partición FAT, ext2/3, Reiser, etc.
# ll /boot/grub total 204 drwxr-xr-x 3 root root 4096 2007-02-20 11:01 ./ drwxr-xr-x 3 root root 4096 2007-02-20 10:27 ../ -rw-r--r-- 1 root root 197 2007-02-20 10:27 default -rw-r--r-- 1 root root 15 2005-01-10 23:49 device.map -rw-r--r-- 1 root root 7584 2007-02-20 10:27 e2fs_stage1_5 -rw-r--r-- 1 root root 7424 2007-02-20 10:27 fat_stage1_5 -rw-r--r-- 1 root root 8192 2007-02-20 10:27 jfs_stage1_5 -rw-r--r-- 1 root root 4171 2007-02-08 22:50 menu.lst -rw-r--r-- 1 root root 6848 2007-02-20 10:27 minix_stage1_5 -rw-r--r-- 1 root root 9280 2007-02-20 10:27 reiserfs_stage1_5 -rw-r--r-- 1 root root 512 2007-02-20 10:27 stage1 -rw-r--r-- 1 root root 108360 2007-02-20 10:27 stage2 -rw-r--r-- 1 root root 8904 2007-02-20 10:27 xfs_stage1_5
Y si aún nos queda incredulidad, podemos ver que, efectivamente, en el segundo sector hay algo que parece el “Stage 1.5″ del GRUB:
# dd if=/dev/hda of=/tmp/stage1 skip=1 bs=512 count=1 1+0 records in 1+0 records out 512 bytes (512 B) copied, 0.000194666 seconds, 2.6 MB/s # strings /tmp/stage1 pPf1 Loading stage1.5 Geom Read Error
Actualización 30/3/07 21:03: En el blog de Miriam Ruiz leo una entrada titulada Montando particiones especificas de una imagen de un disco completo en la que vemos que para montar una de las particiones de una imagen de un disco completo podemos mirar el número de sector de comienzo de la partición en la columna Start de la salida del comando:
fdisk -l -u disco.img
y como cada sector tiene 512 bytes podemos montar la partición que nos interese con este comando poniendo en la variable de entorno START el sector de comienzo de la partición que nos interese montar:
mount -o loop,offset=`echo "512*$START" | bc` disco.img /mnt/image
Miriam se ha basado en el artículo Mounting disks with Linux’s loopback device.