7.6.3.4. Particularidades

7.6.3.4.1. Soporte multiarquitectura

Advertencia

Dicutiremos una solución para soportar BIOS y UEFI, aunque este último arranque siempre ha sido un poco problemático con syslinux. En principio, debe funcionar, aunque depende mucho de que la implementación PXE del firmware UEFI de la placa base no sea deficiente, como pasa en muchas ocasiones. La configuración se ha comprobado con OVMF que es una implementación de UEFI que utilizan Virtualbox o QEmu.

Nota

Si se quieren hacer pruebas con máquinas virtuales, deberá saber cómo arrancarlas en UEFI. Si se utiliza QEmu es necesario:

  • Instalar el paquete qemu-efi.

  • Utilizar como tarjeta de red virtio-net.

  • Añadir al ejecutable de qemu la opción -bios /usr/share/ovmf/OVMF.fd.

Ya se ha comentado que un ordenador puede disponer de BIOS, si es más antiguo, o de UEFI, si más moderno. Tal es así que nuestra estructura de ficheros está pensada para atender esta circunstancia. Sin embargo, en la configuración propuesta se carga de manera incondicional bios/pxelinux.0, por lo que sólo somos capaces de dar soporte a clientes PXE con BIOS o, si son UEFI, en modo compatibilidad con BIOS (Legacy). Sin embargo, comienzan a aparecer placas sin esta compatibilidad, por lo que sólo dar soporte a clientes BIOS empieza a no ser adminisible.

La solución, no obstante, es conceptualmente bastante sencilla: detectar de qué tipo de arquitectura es el cliente y enviar el fichero adecuado: bios/lpxelinux.0, efi32/syslinux.efi o efi64/syslinux.efi. Al determinar éste cuál es el directorio de trabajo, el resto de módulos necesarios también será de la arquitectura apropiada. Así pues, el objetivo es modificar la configuración del servidor DHCP (o del PXE dependiendo del escenario).

De acuerdo con el RFC 4578, el cliente PXE debe enviar la opción DHCP 93 con un número que identifica la arquitectura:

Tipo

Nombre de la arquitectura

CSA en dnsmasq

0

Intel X86PC

x86PC

1

NEC/PC98

PC98

2

EFI Itanium

IA64_EDI

3

DEC Alpha

Alpha

4

Arc x86

Arc_x86

5

Intel Lean Client

Intel_Lean_Client

6

EFI IA32

IA32_EFI

7

EFI BC

BC_EFI

8

EFI Xscale

Xscale_EFI

9

EFI x86-64

X86-64_EFI

10

EFI ARM32

ARM32_EFI

11

EFI ARM64

ARM64_EFI

Además, cambía tambien el valor enviado al servidor para la opción 60, que es de la forma «PXEClient:Arch:00NN:UNDI:XXXX». «NN» coincide con el número expuesto en la tabla: 00 para el primero tipo, 06 para el 6 y así sucesivamente.

Dependiendo de si el servicio PXE es independiente (segundo y tercer escenarios) o está incluido en el DHCP (1º escenario), habrá que hacer una cosa u otra.

7.6.3.4.1.1. DHCP

Si la información de red la facilita directamente el servidor DHCP entonces tendremos explícitamente que analizar la opción 93.

7.6.3.4.1.1.1. dnsmasq

dhcp-match=bios,93,0
dhcp-match=efi32,93,6
dhcp-match=efi64,93,7
dhcp-match=efi64,93,9

dhcp-boot=tag:bios,bios/lpxelinux.0
dhcp-boot=tag:efi32,efi32/syslinux.efi
dhcp-boot=tag:efi64,efi64/syslinux.efi

Y, si queremos que generar configuraciones dinámicas, esto es, menús de arranque cuyas entradas dependan del cliente que realiza la petición, entonces tendremos que obtener el fichero de configuración a través del protocolo HTTP:

dhcp-option=bios,encap:43,210,http://192.168.255.1/boot/bios/
dhcp-option=efi32,encap:43,210,http://192.168.255.1/boot/efi32/
dhcp-option=efi64,encap:43,210,http://192.168.255.1/boot/efi64/

7.6.3.4.1.1.2. Servidor del ISC

Hay que hacer exactamente lo mismo que en dnsmasq, aunque la sintaxis es algo más verborreica:

option arch code 93 = unsigned integer 16;
if option arch = 00:06 {
   filename "efi32/syslinux.efi";
} elsif option arch = 00:07 or option arch = 00:09 {
   filename "efi64/syslinux.efi";
}
else {
   filename "bios/lpxelinux.0";
}

Adicionalmente, podemos enviar la opción 210 para adelantar un paso del proceso de arranque.

7.6.3.4.1.2. PXE

Recordemos que dijimos que la forma de prestar el servicio era incluir esta línea:

pxe-service=x86PC,"Servicio de clonaciones",bios/lpxelinux.0

pero sin dar demasiadas explicaciones. El primer argumento es el tipo de arquitectura del cliente y la línea solamente se envía si el tipo de la línea coincide con el del cliente. Por tanto, nos basta con repetir la línea para las distintas arquitecturas que soportemos:

pxe-service=x86PC,"Servicio de clonaciones",bios/lpxelinux.0
pxe-service=IA32_EFI,"Servicio de clonaciones",efi32/syslinux.efi
pxe-service=BC_EFI,"Servicio de clonaciones",efi64/syslinux.efi
pxe-service=x86-64_EFI,"Servicio de clonaciones",efi64/syslinux.efi

Ahora bien, esta configuración no envía la opción 210 y en consecuencia, no podremos descargar por HTTP la configuracióni de syslinux. Para hacerlo necesitamos enriquecer la configuración:

dhcp-match=bios,93,0
dhcp-match=efi32,93,6
dhcp-match=efi64,93,7
dhcp-match=efi64,93,9

# Configuración para BIOS
pxe-service=x86PC,"Servicio de clonaciones",bios/lpxelinux.0
dhcp-option=tag:bios,encap:43,vendor:PXEClient,210,http://192.168.255.2/boot/bios/

pxe-prompt="Leyenda escondida...",0

# Configuración para EFI32
pxe-service=IA32_EFI,"Servicio de clonaciones",efi32/syslinux.efi
pxe-service=IA32_EFI,"Servicio de clonaciones",efi32/syslinux.efi
dhcp-option=tag:efi32,encap:43,vendor:PXEClient,210,http://192.168.255.2/boot/efi32/

# Configuración para EFI64
pxe-service=BC_EFI,"Servicio de clonaciones",efi64/syslinux.efi
pxe-service=BC_EFI,"Servicio de clonaciones",efi64/syslinux.efi
pxe-service=x86-64_EFI,"Servicio de clonaciones",efi64/syslinux.efi
pxe-service=x86-64_EFI,"Servicio de clonaciones",efi64/syslinux.efi
dhcp-option=tag:efi64,encap:43,vendor:PXEClient,210,http://192.168.255.2/boot/efi64/

La configuración requiere una aclaración. En principio, para cada arquitectura basta con encapsular la opción 210 en la 43 como se hace para la arquitectura BIOS, esto es, añadir una línea más. Sin embargo, para UEFI esto no basta, ya que para mejorar la compatibilidad con implementaciones deficientes de PXE en algunos firmwares UEFI, desde la versión 2.76 (véase las notas para esta versión en el changelog) cuando se envía una sola línea de menú PXE, en vez de enviar un menú de una sola línea, se envía directamente la IP del servidor TFTP y el nombre del fichero1. Esto provoca que no se envíe la opción 43 y no haya forma de informar a syslinux de que descargue a través de HTTP la configuración.

Para evitar este inconveniente (a costa por supuesto de perder compatibilidad con firmwares defectuosos) duplicamos las líneas de menú y añadimos la directiva pxe-prompt para reducir la temporización a 0. De este modo, se envía menú (pero sin percatarnomos de ello) y, como efecto secundario, sí se envía la opción 210.

7.6.3.4.2. Soporte para varias redes

Hasta ahora hemos supuesto que queremos dar servicio a una sola red y no a varias. Cuando se da este segundo caso es claro que el servidor DHCP tendrá que servir configuraciones de red a todas las redes y que, en consonancia, en el tercer escenario, habrá que definir el servidor proxyDHCP también para todas las redes. El resto de nuestra configuración es casi independiente de cuáles y cuántas sean las redes, y el script PHP es capaz de saber la IP del cliente con lo que conocerá la red de origen, si es que queremos particularizar el arranque para cada red.

Ahora bien, hemos dicho casi y no completamente, porque hay un punto de nuestra configuración que la hemos hecho depender de la IP del servidor y, por tanto, de la red en la que esté. Este punto es el envío de la opción 210 para cambiar del protocolo de TFTP a HTTP:

dhcp-option=encap:43,210,http://192.168.255.1/boot/bios/

Nota

De hecho, si nuestro escenario es el tercero, debíamos cambiar esta IP, por aquella del servidor PXE, que supusimos la 192.168.255.2.

Pues bien, al haber varias redes el servidor dispondrá de varias direcciones, una para cada red y, aunque tomar una de ellas funciona, podría aparecer algún problema si decidimos mantener totalmente separadas las redes impidiendo el acceso mediante cortafuegos de una al resto.

Una excelente solución es valernos del DNS, ya que pxelinux lo soporta y convertir la URL2:

http://192.168.255.1/boot/bios/

en:

http://pxeserver/boot/bios/

Tal nombre añadirá el dominio de búsqueda asociado a cada red (p.e. aula.ies, dpto.ies, admon.ies, direccion.ies, etc.) con lo que los nombres serán distintos y cada uno de ellos podremos asociarlo a la IP correspondiente. Configurar bind o dnsmasq para ello es absolutamente trivial.

7.6.3.4.3. Detección de hardware

hdt es una herramienta de detección del hardware integrada como módulo de syslinux (hdt.c32, que requiere, además, libmenu.c32 y libgpl.c32). Por ello, es interesante añadirlo a las posibiilidades de arranque:

LABEL hdt
   MENU LABEL Hardware Detection Tool (HDT)
   COM32 hdt.c32
   APPEND modules_alias=../cfg/files/hdt/modules.ali pciids=../cfg/files/hdt/pci.ids

Requiere dos ficheros:

  • pci.ids, que puede obtenerse del propio sistema dentro del directorio /usr/share/misc (al menos en debian) o bien descargarse directamente de aquí.

  • modules.ali, que es una copia de modules.alias, sito en /lib/modules/$(uname -r).

Ambos ficheros pueden comprimirse con gzip, para hacer más ligera la descarga.

7.6.3.4.4. Gráficos sin menú

Advertencia

En la versión 6 de syslinux el soporte para imágenes lss está roto.

La interfaz simple que proporciona syslinux es bastante espartana: alguna frase que podamos indicar con la directiva SAY y el prompt boot:. No obstante, es posible embeceller esta presentación gracias a la directiva DISPLAY y las explicaciones proporcionadas en la wiki de proyecto.

Groseramente explicado, podemos incluir en nuestro fichero de configuración la directiva referida para que cargue el fichero de definición:

DISPLAY ../cfg/files/gboot/boot.msg

y dentro de tal fichero incluir las órdenes que explica la wiki. Por ejemplo, podríamos incluir este contenido:

^L^X../cfg/files/gboot/logo.lss
^G^O03Escoja arranque

Nota

El significado de los caracteres especiales puede consultarse en la referida página.

Nota

En una terminal de linux, los caracteres especiales deben escribirse pulsando Ctrl+V y la letra indicada.

Es necesario aclarar, no obstante, cómo crear el gráfico del logo. Si lo tenemos en formato .png, es necesario utilizar ppmtolss16, que facilita el propio syslinux (en debian se encuentra en el paquete syslinux-utils):

$ convert logo.png logo.ppm
$ ppmtolss16 < logo.ppm > logo.lss

Nota

El gráfico está limitado a 16 colores, por lo que hay que tenerlo en cuenta al crear el logo original.

7.6.3.4.5. Arranque con iPXE

Aunque no hemos profundizado en la configuración de iPXE, éste puede usarse como trampolín para la carga de otro NBP o, mediante la escritura de un script, para presentar directamente un menú de arranque. Bajo este epígrafe nos limitaremos a exponer cómo usarlo, aunque no sea el firmware de arranque por red que use nuestra tarjeta.

En dnsmasq la configuración para el primer escenario (para el segundo y tercero basta con usar la versión con pxe-service) puede ser esta:

dhcp-match=ipxe,175

dhcp-boot=tag:!ipxe,ipxe.pxe
dhcp-boot=tag:ipxe,start.ipxe

donde start.ipxe es un script de iPXE. La configuración es tal que, cuando se arranca con un firmware PXE que no es iPXE, se lanzará iPXE y, cuando se arranca con iPXE, se obtiene el script para iPXE. La desventaja de este método es que, por lo general, se necesita obtener IP dos veces, una al obtener el fichero ipxe.pxe y otra al obtener posteriormente start.ipxe. Puede evitarse esto, incrustando el script start.ipxe dentro de ipxe.pxe, pero ello exige recompilar el programa.

Notas al pie

1

Este comportamiento deriva de este mensaje de la lista de discusión del programa.

2

Como pasamos a usar un nonbre específico para este servicio, podríamos prescindir de añadir a la URL /boot/ cambiando mínimamente la configuración de nginx.