Lo hice y lo entendí

El blog de Vicente Navarro
20 feb

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.

Entradas relacionadas

Tema LHYLE09, creado por Vicente Navarro