Manual

do

Maker

.

com

Compilar o kernel do Raspbian

Compilar o kernel do Raspbian

Compilar o kernel do Raspbian pode ser útil para adicionar ou remover recursos ao seu Raspberry. Nesse outro artigo mostrei como configurar um ambiente virtual para compilação, de forma a aproveitar o processamento de uma plataforma x86 invés de fazê-lo diretamente na ARM. Também citei esse outro artigo, onde mostro os diversos modos de compilação possíveis. Dessa vez vou mostrar como fazê-lo nessa máquina virtual que criamos no post anterior e também como fazer a compilação cruzada ou, "cross-compilling".

Processo para compilação local ou na VM

O processo é o mesmo para compilação nativa na board ou compilação nativa na máquina virtual que criamos no artigo anterior. Devo reafirmar a necessidade da leitura do post anterior devido às dependências que você precisará instalar antes de iniciar o processo de compilação. Mas aqui deixo uma dica; você pode fazer um dump do sistema que você tem rodando em sua RPi e então fazer a compilação na VM, desse modo você ganha em processamento. Posteriormente, você pode jogar essa imagem de volta para o cartão! Claro que seria melhor ter um segundo cartão para testar se a imagem não foi corrompida por qualquer razão, mas se desejar fazer esse processo, é bastante simples. Primeiro, a cópia do cartão para seu notebook:

dd if=/dev/$CARTAO of=raspbian-kernel.img

Troque essa variável $CARTAO pelo dispositivo. Para identificar o dispositivo, antes de inserí-lo no computador, faça:

tail -f /var/log/messages

Se o messages estiver desabilitado em seu sistema, então verifique o dispositvo adicionado ao sistema após inserí-lo no computador.

dmesg

Nas últimas linhas haverá alguma indicação do dispositivo inserido. Supondo /dev/sdb, basta substituir $CARTAO por sdb.

Atendidas as necessidades, vamos ao próximo passo.

Baixar os fontes do kernel

// Obviamente é o primeiro passo, considerando ser essa a nossa "matéria prima". Pegue-a então:

git clone --depth=1 https://github.com/raspberrypi/linux

Preparar o .config

Antes de compilar, você precisa preparar o arquivo .config, que conterá as informações necessárias do que deve ser habilitado ou desabilitado no kernel. Uma das formas de fazê-lo é copiar o arquivo de configuração através da instalação dos fontes do kernel através do repositório. Também mostrei isso no artigo anterior, leia-o se ainda não o fez. A outra maneira de fazer esse arquivo de configuração inicial é criando-o com as configurações padrão ou através de uma chamada especial para o Raspberry. Essa chamada varia apenas entre o RPi 1 e os demais RPi.

Para o Raspberry Pi 1:

cd linux
KERNEL=kernel
make bcmrpi_defconfig

Para o Raspberry Pi 2 e 3:

cd linux
KERNEL=kernel7
make bcm2709_defconfig

Repare que kernel7 é o nome do kernel que utilizamos pra fazer o boot da nossa VM do post anterior. Isto porque com o parâmetro '-M' utilizado na chamada do QEmu foi indicada que a máquina emularia um Raspberry Pi 2.

Esse processo eu estou fazendo em uma RPi 3, portanto sigo com o segundo comando.

Configurar as opções do kernel

Após criada a configuração, podemos incluir ou excluir algo através de um confortável menu gráfico chamando o comando:

make menuconfig

Essa opção só estará disponível se você tiver instalada a 'libncursesw5-dev'. E para instalá-la, use o apt-get:

sudo apt-get install libncursesw5-dev

Iniciar a compilação

Agora o processo de compilação é bastante simples e discorro em seguida.

make -j4 zImage modules dtbs
sudo make modules_install
sudo cp arch/arm/boot/dts/*.dtb /boot/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
sudo scripts/mkknlimg arch/arm/boot/zImage /boot/$KERNEL.img

A primeira linha tem muita informação importante pra quem não tem experiência com compilação de kernel ainda. Primeiro, o parâmetro '-j4' divida a tarefa pelo número de processadores indicados, o que certamente é mais eficiente em caso de compilação nativa na RPi. Se fosse uma Banana Pi M3, esse parâmetro poderia ser até '-j8'!

O parâmetro zImage significa que o kernel é pequeno o suficiente para ser colocado em memória baixa (até 640K). Em plataformas x86 o comum nos dias atuais é ver o uso do bzImage, que ao contrário do que muitos acham, não se trata de uma compressão do kernel com bz, mas sim uma referência à 'big zImage'. Eu trato desse assunto nesse outro artigo sobre embarcados.

O make também recebe o parâmetro 'modules' para criação dos módulos e o parâmetro 'dtbs', que é um arquivo blob do device tree. E o que é o device tree? - Eu pergunto, eu respondo, mas se você não entende o conceito do initrd, sugiro uma leitura nesse artigo que escrevi sobre sistemas embarcados.

// Você já reparou que o Raspbian não tem initrd? Pois é, então como fazer o preload das necessidades para o devido reconhecimento de hardware, naquilo que precisa ser carregado tão logo o kernel levante? É pra isso que existe o device tree, que tem um comportamento semelhante ao initrd, exceto que o initrd carrega todo um sistema raiz e depois migra para o disco, mas enfim, esse parâmetro não deve ser esquecido. Se filosofarmos um pouco mais, podemos também dizer que o device tree binary pode lembrar também a BIOS, que não existe nessas boards, por isso que se não tiver o sistema no cartão, sequer há um sinal que possa ser interpretado; toda a inteligência vem do software externo.

A primeira linha pode ser executada como usuário comum porque toda a compilação é feita localmente, mas adiante dela as outras linhas são precedidas pelo comando su. Se preferir, inicie a sequência de comandos com 'sudo su' e dispense sua chamada adiante:

sudo su
make -j4 zImage modules dtbs
make modules_install
cp arch/arm/boot/dts/*.dtb /boot/
cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
cp arch/arm/boot/dts/overlays/README /boot/overlays/
scripts/mkknlimg arch/arm/boot/zImage /boot/$KERNEL.img

Com isso, você já concluiu a tarefa. Agora se pretende um outro método, sigamos.

Compilação cruzada ou Cross-compilling

Se você usa Windows invés de Linux, talvez você já tenha aí uma máquina virtual com o pinguim instalado e pode ser mais simples pra você utilizar essa máquina invés de criar uma VM ARM. Por outro lado, se você tem uma máquina rodando Linux nativamente, o desempenho será consideravelmente maior fazendo compilação cruzada do que fazendo-a através de virtualização, por isso achei importante descrever mais esse modo para que você possa construir seu kernel.

Preparação do ambiente

Para tal, você precisará de um toolchain, que é o conjunto de ferramentas que permitirão gerar binários para uma plataforma diferente da que se está utilizando para a compilação. Felizmente, a propria fundação Raspberry oferece um git para facilitar as coisas, de modo que o primeiro passo será baixar as ferramentas:

git clone https://github.com/raspberrypi/tools

Ao término, você poderá mover o diretório para um lugar comum onde pretenda deixar a ferramenta. O mais comum é copiar para /opt/, mas você pode deixar até em seu home, isso é indeferente, uma vez que será necessário colocar o diretório binário no path do sistema:

mv diretorio-do-compilador /opt/
PATH=$PATH:/opt/bathbinario

Inclua também a linha do path ao seu aruivo .bashrc (no seu home) caso você compile como usuário. Porém, ainda que digitar 'sudo su' antes da compilação, basta digitar 'source /home/seuUsuario/.bashrc', ou adicione a linha de path também ao .bashrc em /root.

Mais uma vez, você pode baixar o kernel como mostrado mais acima.

Compilando

// E para compilar, é tão fácil quanto nativamente, agora que você já tem um toolchain para gerar o binário no formato certo. O que você fará de diferente é indicar um valor à variável de cross-compilação (agora misturei inglês com português, ficou chique).

Para RPi 1:

cd linux
KERNEL=kernel
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcmrpi_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs

E para o RPi 2 ou 3:

cd linux
KERNEL=kernel7
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs

Não é necessária muita explicação. Como você pode ver, a mudança no make está relacionada ao binário do cross-compiller, indicação da arquitetura para a qual será gerada o binário e mais uma vez, indica-se qual o processador.

A opção '-j' para o make continua sendo válida.

Copiar as coisas para o cartão

Se você optou por compilação cruzada, o lado negativo começa agora. Dá um pouco de trabalho pra copiar tudo para o cartão. Uma das opções é fazer uma cópia recursiva do diretório de compilação do kernel para o SD. Daí você faz o boot no sistema e então executar os comandos:

make modules_install
cp arch/arm/boot/dts/*.dtb /boot/
cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
cp arch/arm/boot/dts/overlays/README /boot/overlays/
scripts/mkknlimg arch/arm/boot/zImage /boot/$KERNEL.img

Onde a variável $KERNEL corresponde a um dos valores citados lá no começo desse artigo. Antes de tentar montar o cartão e acessar o sistema, é seguro fazer um dump do SD para ter um backup. Depois, haja como quiser, mas eu recomendo que se faça como descrito no post anterior para acessar os dados de uma partição a partir da imagem.

A outra opção é mais prática em relação ao tempo, porque copiar o diretório para um cartão e depois executar a instalação leva um tempinho.

Se já tiver feito o backup ou se decidir proceder qualquer execução diretamente no cartão SD, você precisará dispor das duas partições para a cópia, portanto, crie 2 diretórios temporários para o acesso ao cartão:

mkdir boot root

Supondo que o dispositivo relacionado ao seu cartão SD seja /dev/sdb, monte as duas partições do cartão, já proceda com a instalação dos módulos e a cópia dos dados relacionados ao boot:

sudo su
mount /dev/sdb1 boot
mount /dev/sdb2 root
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=root modules_install
scripts/mkknlimg arch/arm/boot/zImage boot/$KERNEL.img
cp arch/arm/boot/dts/*.dtb boot/
cp arch/arm/boot/dts/overlays/*.dtb* boot/overlays/
cp arch/arm/boot/dts/overlays/README boot/overlays/
sync
umount boot
umount root
rmdir boot root

Agora você já pode dr boot em seu próprio kernel! Em outro artigo vou mostrar uma coisa legal que qualquer um pode querer implementar para deixar o kernel mais bacana, acompanhe o nosso site!

Inscreva-se no nosso canal Manual do Maker Brasil no YouTube.

Próximo post a caminho!

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.