¿Cómo carga Linux la imagen 'initrd'?

13

He estado tratando de entender el proceso de arranque, pero solo hay una cosa que me pasa por la cabeza ...

Tan pronto como se haya arrancado el kernel de Linux y se haya montado el sistema de archivos raíz (/), se pueden ejecutar programas y se pueden integrar otros módulos del kernel para proporcionar funciones adicionales. Para montar el sistema de archivos raíz, se deben cumplir ciertas condiciones. El núcleo necesita los controladores correspondientes para acceder al dispositivo en el que se encuentra el sistema de archivos raíz (especialmente los controladores SCSI). El núcleo también debe contener el código necesario para leer el sistema de archivos (ext2, reiserfs, romfs, etc.). También es concebible que el sistema de archivos raíz ya esté encriptado. En este caso, se necesita una contraseña para montar el sistema de archivos.

El ramdisk inicial (también llamado initdisk o initrd) resuelve con precisión los problemas descritos anteriormente. El kernel de Linux ofrece la opción de cargar un pequeño sistema de archivos en un disco RAM y ejecutar programas allí antes de montar el sistema de archivos raíz real. La carga de initrd es manejada por el gestor de arranque (GRUB, LILO, etc.). Los cargadores de arranque solo necesitan rutinas de BIOS para cargar datos desde el medio de arranque. Si el gestor de arranque puede cargar el kernel, también puede cargar el disco RAM inicial. No se requieren controladores especiales.

Si / boot no es una partición diferente, pero está presente en la partición /, ¿no debería el cargador de arranque requerir los controladores SCSI para acceder a la imagen 'initrd' y la imagen del núcleo? Si puede acceder a las imágenes directamente, ¿por qué necesitamos exactamente los controladores SCSI?

rpthms
fuente

Respuestas:

20

Nighpher, intentaré responder a tu pregunta, pero para una descripción más completa del proceso de arranque, prueba el artículo de IBM .

Ok, supongo que está utilizando GRUB o GRUB2 como su gestor de arranque para la explicación. En primer lugar, cuando el BIOS accede a su disco para cargar el gestor de arranque, utiliza sus rutinas integradas para el acceso al disco, que se almacenan en la famosa interrupción de 13 h. El cargador de arranque (y el núcleo en la fase de configuración) hacen uso de esas rutinas cuando acceden al disco. Tenga en cuenta que el BIOS se ejecuta en modo real (16 bits) del procesador, por lo tanto, no puede direccionar más de 2 ^ 20 bytes de RAM (2 ^ 20 no 2 ^ 16 porque cada dirección en modo real se compone de segmento_dirección * 16 + desplazamiento , donde la dirección del segmento y el desplazamiento son de 16 bits, consulte http://en.wikipedia.org/wiki/X86_memory_segmentation ). Por lo tanto, estas rutinas no pueden acceder a más de 1 MiB de RAM, lo cual es una limitación estricta y un gran inconveniente.

El BIOS carga el código del gestor de arranque directamente desde el MBR: los primeros 512 bytes de su disco y lo ejecuta. Si está utilizando GRUB, ese código es GRUB etapa 1. Ese código carga GRUB etapa 1.5, que se encuentra en los primeros 32 KiB de espacio en disco, denominado región de compatibilidad de DOS o desde una dirección fija del sistema de archivos. No es necesario comprender el sistema de archivos para hacer esto, porque incluso si la etapa 1.5 está en el sistema de archivos, es un código "en bruto" y se puede cargar directamente en la RAM y ejecutar: http://www.pixelbeat.org/ docs / disk / . La carga de stage1.5 desde el disco a la RAM hace uso de las rutinas de acceso al disco del BIOS.

ingrese la descripción de la imagen aquí

Stage1.5 contiene las utilidades del sistema de archivos, para que pueda leer el stage2 del sistema de archivos (bueno, todavía usa BIOS 13h para leer desde el disco a la RAM, pero ahora puede descifrar la información del sistema de archivos sobre inodes, etc. y extraer el código sin procesar del disco). Es posible que las BIOS más antiguas no puedan acceder a toda la HD debido a limitaciones en su modo de direccionamiento de disco; pueden usar el sistema Cylinder-Head-Sector, incapaz de abordar más de los primeros 8 GiB de espacio en disco: http: //en.wikipedia. org / wiki / Cylinder-head-sector .

Stage2 carga el kernel en la RAM (nuevamente, utilizando las utilidades de disco del BIOS). Si es un kernel 2.6+, también tiene initramfs compilado, por lo que no es necesario cargarlo. Si se trata de un kernel más antiguo, el gestor de arranque también carga una imagen initrd independiente en la memoria, para que el kernel pueda montarlo y obtener controladores para montar el sistema de archivos real desde el disco.

El problema es que el kernel (y el ramdisk) pesan más de 1 MiB, por lo tanto, para cargarlos en la RAM, debe cargar el kernel al primer 1 MiB, luego saltar al modo protegido (32 bits), mover el kernel cargado a la memoria alta (libre el primer 1 MiB para el modo real), luego regrese al modo real (16 bits) nuevamente, obtenga el disco RAM del disco al primer 1 MiB (si es un initrd separado y un kernel anterior), posiblemente cambie nuevamente al modo protegido (32 bits), póngalo donde corresponde, posiblemente regrese al modo real (o no: /programming/4821911/does-grub-switch-to-protected-mode ) y ejecute el código del núcleo. Advertencia: no estoy completamente seguro acerca de la minuciosidad y precisión de esta parte de la descripción.

Ahora, cuando finalmente ejecuta el kernel, ya lo tiene y el ramdisk cargado en la RAM por el gestor de arranque , por lo que el kernel puede usar las utilidades de disco de ramdisk para montar su sistema de archivos raíz real y pivotearlo. Los controladores de ramfs están presentes en el núcleo, por lo que puede comprender el contenido de initramfs, por supuesto.

Boris Burkov
fuente
¿No puede el gestor de arranque simplemente cargar el kernel en fragmentos, en lugar de saltar al modo protegido? Y cuál es la necesidad de liberar ese 1 MB ... (Lo siento ... no podía entender eso ...)
rpthms
La necesidad de liberar primero 1MiB es la siguiente: el gestor de arranque puede acceder a su disco duro solo en modo real, porque lo hace con las utilidades del BIOS, que son en modo real (operan con argumentos de 16 bits y utilizan operaciones de 16 bits). El modo real simplemente no ve ninguna RAM, excepto por el primer 1 MiB. Pero debe cargar kernel + initramfs en RAM y ocupan ~ 5 MiB de espacio en RAM. Esas utilidades de BIOS simplemente no podrán exprimir 5 MiB en el primer 1 MiB. Por lo tanto, el gestor de arranque debe copiarlos del disco al primer 1 MiB, luego pasar al modo protegido y moverlos del primer 1Mb de RAM a un RAM más alto. ¿Está más claro ahora? :)
Boris Burkov
1
Todo el material de la etapa 1 / 1.5 / 2 es legado de grub.
psusi
1
@CMCDragonkai Sí, el gestor de arranque stage2 está en el sistema de archivos (es decir, en la /bootpartición). El kernel no está cargado en este momento: es grub stage1.5, que accede a stage2 en el /bootsistema de archivos (por ejemplo, en el /boot/grubarchivo) a través de sus controladores minimalistas del sistema de archivos. El núcleo también podrá leer desde la /bootpartición, pero sucederá más tarde, después de la ejecución del código grub2 y la carga del núcleo y después de que el núcleo lea initramfs. ¿Estás hablando init.shde los initramfs? Reside en la /bootpartición de su disco duro, luego la etapa 2 de grub lo coloca en la RAM y Kernel lo lee desde la RAM.
Boris Burkov, el
1
Initrd tenía que ser un archivo separado. Los initramfs más nuevos se pueden vincular al kernel, pero no es necesario ; el cargador de arranque también puede cargarlo como un archivo separado. Dado que el archivo initramfs se define como una secuencia de archivos cpio, algunos cargadores de arranque (por ejemplo, iPXE) incluso permiten múltiples archivos initramfs, que se cargarán en la memoria uno tras otro. Además, algunas distribuciones de Linux usan nombres de archivo de estilo initrd para la compatibilidad con versiones anteriores, aunque la tecnología real utilizada ahora es initramfs.
telcoM
1

Creo que se reduce a las características que admite el gestor de arranque en particular. P.ej. no tiene que conocer un sistema de archivos particular de su partición combinada (arranque + raíz). En ese caso, simplemente cree una partición de arranque separada en condiciones que funcione con su gestor de arranque, y cualquier otra complejidad de cómo montar su partición raíz se deja en el núcleo y la imagen initrd arrancada desde la partición de arranque. El gestor de arranque sabe cómo acceder a los dispositivos SCSI (y también a otros dispositivos, dependiendo de qué gestor de arranque se use) ya sea utilizando sus propios controladores o utilizando rutinas de BIOS. Además, sabe leer algunos sistemas de archivos, etc.

Considere, por ejemplo. Modo de arranque UEFI, donde el firmware UEFI ya sabe cómo acceder a la partición EFI, leerlo y cargar el kernel de Linux desde allí sin necesidad de un cargador de arranque intermedio. En ese caso, la imagen de Linux vive separada de la partición raíz y el firmware UEFI no tiene que conocer todos los sistemas de archivos exóticos para acceder a ella. Creo que la separación de las imágenes "de arranque" de la partición "raíz" tiene mucho sentido. Si no es por otra cosa, esto es necesario al configurar el cifrado del sistema de archivos raíz.

Miroslav Koškár
fuente
0

Solo para el registro, si un gestor de arranque no carga initrd, vale la pena probar otro gestor de arranque; Acabo de encontrarme con una situación como esta cuando LILO ignoró silenciosamente un initrd de tamaño mediano (<4Mb; un solo ext4 rootfs en un SSD SATA; GPT) y GRUB 2.00 tuvo éxito.

El proceso de arranque finalizó rápidamente con un típico

RAMDISK: Couldn't find valid RAM disk image starting at 0.
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(8,3)
Michael Shigorin
fuente