Raspberry Pi e o processo de boot
- por Sergio Prado
Uma das primeiras coisas que você precisa fazer quando começar a trabalhar com uma nova plataforma de hardware é entender o seu processo de boot.
E o processo de boot da Raspberry Pi é um pouco diferente comparado às outras plataformas comuns que rodam Linux como a Beagleboard, Beaglebone ou i.MX53. A começar pelo hardware…
Quando você energiza o SoC da Broadcom (BCM2835), quem assume o controle não é a CPU (ARM1176JZ-F), mas sim a GPU, responsável pelo processamento gráfico do chip! Sim, caros leitores. Ao ser energizada, o processador principal da placa é a GPU, e o co-processador é o ARM11, que fica ali, paradinho, esperando sua vez para entrar na brincadeira.
Outra diferença é que a Raspberry Pi (pelo menos por enquanto) não usa o U-Boot como bootloader padrão para carregar e executar o kernel Linux. Mas vamos começar pelo começo…
O PRIMEIRO ELÉTRON
Conforme descrevi mais acima, ao energizar a Raspberry Pi, quem assume o controle da placa é o core da GPU. E o primeiro código a ser executado esta armazenado em ROM, dentro do SoC, inacessível a nós, meros mortais que não trabalhamos na Broadcom.
Este código é responsável por procurar um código de boot em algumas interfaces de armazenamento, carregar este código para uma memória interna (cache L2 do SoC para ser mais preciso) e executar. E que tipos de interfaces de armazenamento o SoC reconhece como dispositivo de boot? Não dá para saber, já que não temos o datasheet do SoC. Temos disponível apenas uma parte do datasheet, que descreve o acesso aos periféricos do SoC, mas que não descreve o processo de boot (este documento pode ser acessado aqui). Mas se você quiser o datasheet do BCM2835 é fácil, é só assinar um NDA com a Broadcom…:)
Voltando ao processo de boot, o que sabemos é que o SoC procura na primeira partição do cartão SD um arquivo chamado bootcode.bin. Esta partição do cartão SD precisa estar formatada com FAT32, e o bootcode.bin é um código compilado para ser executado na GPU. Sim, você adivinhou, não temos os fontes deste bootloader de primeiro estágio… :(
Resumindo a primeira etapa de boot: você liga a Raspberry Pi, a GPU assume, procura o arquivo bootcode.bin na primeira partição do cartão SD, carrega para a memória cache L2 e executa.
Mas o que então faz este bootcode.bin?
O SEGUNDO ESTÁGIO
O bootcode.bin tem duas responsabilidades principais: inicializar a SDRAM e carregar um bootloader de segundo estágio para ela. Este bootloader de segundo estágio é um arquivo chamado start.elf que também deve estar na primeira partição do cartão SD.
O start.elf também é um binário compilado para ser executado na GPU, e com a ajuda de um outro binário chamado fixup.dat, também possui duas responsabilidades principais: configurar o hardware de acordo com um arquivo de configuração e carregar o kernel Linux.
O arquivo de configuração é chamado config.txt, e também deve estar na primeira partição do cartão SD. Neste arquivo de configuração você pode configurar o hardware, definir mapeamento de memória, especificar parâmetros para carregar o kernel Linux, etc. Uma especificação completa do arquivo encontra-se aqui.
Após ler o arquivo de configuração, ele irá carregar o arquivo kernel.img, que também deve estar na primeira partição do cartão SD. Esse arquivo nada mais é do que a imagem do kernel Linux. Antes de executar a imagem do kernel, ele é capaz de passar a linha de comandos para o kernel, que pode ser definida no arquivo cmdline.txt, ou em uma variável no arquivo config.txt.
Resumo da ópera: você energiza a placa, a GPU assume, carrega o bootcode.bin para a memória cache L2 e executa. O bootcode.bin inicializa a SDRAM, carrega o start.elf para a RAM externa e executa. O start.elf configura o hardware de acordo com o arquivo config.txt, carrega a imagem do kernel em kernel.img, lê a linha de comandos do kernel no cmdline.txt, e dá vida ao pinguim mais famoso do universo. Todos estes arquivos devem estar na primeira partição do cartão SD, que deve estar formatado com FAT32:
$ ls /media/raspberrypi bootcode.bin cmdline.txt config.txt fixup.dat kernel.img start.elf |
Obs: Em uma versão mais antiga do firmware de boot, existia um passo adicional. Em vez do bootcode.bin carregar diretamente o start.elf, ele carregava o loader.bin, e este era o responsável por carregar o start.elf. Este passo adicional foi removido nas versões mais novas do firmware do boot.
O FIRMWARE
Todo o firmware descrito aqui, com exceção da imagem do kernel (kernel.img) pode ser baixado no repositório oficial do projeto no github em https://github.com/raspberrypi/firmware. Mas nada de fontes, você só vai encontrar neste projeto os binários e alguma documentação, o suficiente para você carregar e executar o seu sistema Linux na Raspberry Pi.
No próximo artigo vamos construir um sistema Linux do zero para a Raspberry Pi. Até lá!
Um abraço,
Sergio Prado