u-boot es un bootloader libre para dispositivos empotrados de bajo poder computacional. Para los no versados en el tema, es algo así como el grub de tu PDA o de tu navegador GPS, pero con notables diferencias, claro está. En ésta receta hablaré sobre como instalarlo y como usarlo para crear distintas particiones en la memoria Flash de tu handheld para, de este modo, poder instalar un sistema arrancable. Para ello, pondré como ejemplo la tarjeta mini2440 que compré hace unos días.
Introducción
Como he comentado anteriormente, u-boot es un bootloader totalmente libre para dispositivos empotrados de bajo poder computacional. Entre sus múltiples posibilidades, están las de particionar la memoría flash del dispostivo en el que se encuentre corriendo, asignar nombre a dichas particiones, cargar imágenes en RAM desde distintas fuentes, volcarlas a flash, y un largo etcétera....
Aquí hablaré de las opciones que a mi juicio pueden ser mas socorridas para la instalación de un Sistema Operativo en un dispositivo empotrado, en mi caso, tomando como ejemplo la tarjeta de desarrollo mini2440 comentada anteriormente, aunque como es de suponer, las mismas operaciones pueden ser realizadas en distintas plataformas hardware.
Así pues vamos a lo divertido del asunto ¡¡Empezamos!!
Instalando
El proceso de instalación de u-boot consiste básicamente en cargar una imagen de u-boot en la RAM de nuestrá máquina, bien a través de su propio bootloader, bien a través de un JTAG. Una vez cargado en RAM, se lanza y se le dice que se (auto)guarde en la flash de nuestra tarjeta. En este caso y dependiendo de nuestro hardware, puede sobreescribir a su bootloader original o bien coexistir con él. En cualquier caso, deberás consultar el manual de tu tarjeta para comprobarlo.
Para el caso de la MINI2440, ésta viene con dos memorias Flash distintas: por un lado hay una flash NOR de 2MB en la que se encuentra almacenado el bootloader específico para los micros de Samsung (mirco de mi tarjeta de desarrollo): supervivi. Por otro lado, tenemos una memoria flash NAND de 128MB en la que se supone que irá nuestro sistema. En ésta memoria será en la que instalaremos u-boot, configurando posteriormente nuestra mini2440 para que arranque desde ahí (utilizando un conmutador que a tal efecto lleva instalado).
Para comenzar, necesitaremos descargarnos tanto el código fuente de u-boot como el software necesario para poder comunicarnos con supervivi y un compilador cruzado para ARM:
* u-boot:
* toolchain: Compiladores cruzados para ARM los hay muchos en esto de GNU. Yo, que seguí al dedillo todo lo que leí en montónes de blogs, usé el siguiente:
* Friendlyarm package: Se trata de un paquete con un uploader ya compilado para comunicarse con supervivi y de una imagen ya compilada de u-boot, que deberemos utilizar para cargar la imagen que compilemos nosotros. El por qué de usar dos imágenes de u-boot se explicará mas adelante.
Una vez que lo tenemos todo descargado, empezaremos por compilar el bootloader, para ello no debemos olvidar añadir a nuestro PATH la ruta en la que se encuentran los binarios de la toolchain que usemos (como hicimos anteriormente). Una vez hecho esto, podemos pasar a compilar:
Después de no mucho tiempo y si todo ha ido bien, deberemos tener un archivo llamado u-boot.bin en la carpeta donde hemos llevado a cabo la compilación. Esa es la imagen de u-boot que se almacenará en la flash de nuestra tarjeta, pero para poder llevar a cabo dicho proceso, necesitaremos otra versión de u-boot (sé que suena bastante raro, y de hecho lo es. Mas adelante explicaré el por qué de ello).
Bueno, llegados a este punto, cogemos nuestra mini2440, deslizamos el conmutador superior hacia la izquierda (para configurar el arranque desde la NOR), conectamos un módem nulo desde su puerto serie a un puerto serie de nuestra máquina y el device USB a un puerto USB libre. Tras ésto, arramcamos minicom y configuramos el puerto serie a 115200 Baudios, 8N1 y sin ningún tipo de contol de flujo.
Hecho ésto, solo queda encender nuestra tarjeta y comprobar que supervivi arranca:
Seleccionamos la opción q para acceder a la shell de superivi y después le diremos que queremos cargar una imagen en la memoria y arrancar, pero para ello, antes deberemos saber cuando ocupa el bootloader que vamos a cargar (el que ya viene compilado), así que volvemos a la carpeta en la que lo descomprimimos y lo comprobamos:
Podemos ver que ocupa 239016 bytes. Guardamos este dato, nos será util para lo que comentamos anteriormente.
Con esto le hemos dicho a supervivi que queremos cargar 239016 bytes de datos (observad que es la misma cantidad de bytes que ocupa la imagen de u-boot) en la RAM de la tarjeta. Ahora supervivi se ha quedado esperando los datos, que deberemos envíarselos vía USB. Habiendo conectado el cable USB como se indicó antes ejecutamos el uploader:
que deberá ser llamado desde la carpeta friendlyarm2440-package y con sudo para poder tener acceso al puerto USB.
Si todo ha ido bien, supervivi debería mostar algo como esto:
Ahora, arrancamos u-boot:
y ya está, nuestra tarjeta arrancará u-boot:
Lo primero que ha hecho u-boot al arrancar, ha sido darnos un mensaje de alerta indicando que el contenido de la NAND no es el que debiera, ya que no está formateada, así que éste será el siguiente paso:
La NAND tiene almacenada (o debería tener) una lista de bloques defectuosos, pero nosotros limpiaremos completamente la NAND borrando dicha lista y reconstruyéndola después con los bloques que nosotros detectemos como defectuosos. El comando nand scrub se encarga precisamente de limpiar la NAND.
Después de haber hecho la limpieza, creamos nuestra propia BBT:
Éste proceso es relativamente lento, por lo que habrá que esperar que esperar (3-4 minutillos), así que mientras tanto, busca una tarjeta SD y copia el binario u-boot.bin QUE COMPILASTE en dicha tarjeta. La cargaremos desde ahí.
Una vez que tenemos nuestra SD con el binario cargado y que ya se ha generado la nueva BBT, introducimos la tarjeta en el lector de la mini2440 y le decimos a u-boot que la detecte:
Con la tarjeta ya detectada, cargamos u-boot.bin en la RAM:
¿Qué ha pasado? pues que le hemos dicho a u-boot que cargue el archivo binario u-boot.bin desde un sistema de archivos FAT (fatload), ubicado en la SD (mmc), dispositivo 1, primera partición (0:1), a partir de la dirección de memoria 0x32000000.
Una vez que tenemos el archivo en RAM, lo volcamos a la NAND:
Bueno, en este caso, hemos escrito 0x38fc4 bytes (233412, para que nos entendamos), al comienzo de la NAND. El numerajo hexadecimal, como hemos visto corresponde al peso de u-boot.bin pero ésta vez del que hemos compilado NOSOTROS, no del que cargamos en RAM al principio. Importante no confundir ésto. Un apunte importante es que en ésta parte del proceso, la longitud deberá darse en hexadecimal, no en decimal, ya que ello puede dar lugar a errores.
Por lo que he leído por ahí, el modificador .e del comando write se utiliza para generar códigos de correción de errores y evitar así lo posibles bloques defectuosos que pueda haber en la NAND (recordad el comando createbbt de antes).
Una vez hecho esto, podemos reiniciar tranquilos nuestra mini2440: u-boot la hará arrancar. Aunque no hará mucho mas ya que la NAND está completamente borrada y no hay sistema.
Antes comenté que explicaría el por qué de usar dos versiones distintas de uboot. El motivo es que para instalar uboot, primero debe residir en la RAM y poderse ejecutar desde ahí, ya que hay que hacer una limpieza de la NAND antes de llevar a cabo la instalación propiamente dicha. Lo que observé entonces fue que las versiones de uboot que conseguían arrancar desde la RAM, no eran capaces de hacerlo luego una vez que se instalaban en NAND (en efecto, según los manuales que leí, una vez creada la BBT, se escribía el contenido de la RAM a la NAND, ya que allí es donde está uboot) y viceversa, las imágenes que si que eran capaces de arrancar desde la NAND no lo podían hacer desde la RAM. No sé si esto es por algún bug en uboot (que deberían ser entonces bugs distintos en cada una de las versiones) o porque yo hice algo mal (repetí montones de veces lo que vi en tutos, blogs y demás paso por paso). El caso es que después de varios intentos sin mucho éxito, decidí hacerlo tal y como lo he explicado aquí.
En el futuro....
En próximas recetas, explicaré qué comandos básicos utilizar en u-boot para cargar imágenes en RAM o NAND, configurar el arranque automático desde distintas fuentes, particionar la NAND, configurar opciones de arranque para el S.O. que tengamos y alguna cosilla mas. Evito poner esa información aquí para no sobrecargar demasíado esta receta, que se supone que tienen que ser breves y concisas.
Referencias
Muchas y muy variadas, aunque las mas importantes son éstas.