Construindo um Sistema Linux Mínimo com BusyBox

Ambiente de Desenvolvimento

WSL (Ubuntu 22.04)

Criação da Imagem de Disco

Para alocar espaço para a imagem de disco, utilize o comando fallocate ou gere um arquivo de zeros com dd if=/dev/zero of=$imagem bs=1M count=$tamanho_MB.

Formate o arquivo de imagem com mkfs.ext4 e monte-o com mount -o loop $imagem /mnt.

Caso necessite particionar a imagem, utilize fdisk ou cfdisk para criar as partições. Em seguida, use losetup -fP $imagem para associá-la a um dispositivo de loop. O parâmetro -f encontra automaticamente um dispositivo disponível, e -P faz com que as partições dentro da imagem sejam reconhecidas. Após a associação, monte as partições usando comandos como mount $dispositivo_loop1 /mnt/ponto_montagem.

Compilando o BusyBox

Obtenha o código-fonte do BusyBox. Esta demonstração utiliza a versão 1.36.1.

Opções de compilação principais:

  • Binário estático: Ative a opção STATIC (Build static binary (no shared libs)) em Settings para gerar binários independentes.
  • Suporte a Unicode: As opções UNICODE_SUPPORT e UNICODE_WIDE_WCHARS já vêm ativadas por padrão nesta versão, oferecendo suporte a caracteres Unicode.

Execute make para compilar e make install para instalar os binários e links simbólicos. Para instalar em um diretório específico (como o nosso ponto de montagem), use make install CONFIG_PREFIX=$mnt.

Compilando o Kernel Linux

Obtenha o código-fonte do kernel. Este guia utiliza o Linux 6.12.7. Configure o kernel conforme suas necessidades com make menuconfig ou similar.

Criando o Sistema de Arquivos Raiz (rootfs)

A instalação do BusyBox fornece apenas os diretórios bin, sbin, usr e o link simbólico linuxrc. É necessário criar a estrutura completa de diretórios do sistema:

bin boot dev etc home lib mnt opt proc root run sbin sys tmp usr var

Crie esses diretórios dentro do ponto de montagem $mnt. Como as operações de montagem requerem privilégios elevados, é provável que seja necessário usar sudo para criar os arquivos. Teste o ambiente com chroot $mnt /bin/sh.

Executando com QEMU

Crie um script para iniciar a VM com o QEMU:

#!/bin/sh
qemu-system-x86_64 \
  -kernel /caminho/para/bzImage \
  -hda /caminho/para/rootfs.img \
  -nographic \
  -append "console=ttyS0 root=/dev/sda init=/linuxrc"

Parâmetros principais:

  • -kernel: Define o arquivo de imagem do kernel (bzImage).
  • -hda: Especifica a imagem de disco rígido virtual.
  • -nographic: Redireciona a saída para o terminal em vez de abrir uma janela gráfica.
  • -append: Passa argumentos para o kernel na inicialização.
    • console=ttyS0: Redireciona a saída do console para a porta serial, visível no terminal do host.
    • root=/dev/sda: Indica o dispositivo da partição raiz (geralmente sda em VMs).
    • init=/linuxrc: Especifica o processo inicial a ser executado, que é o BusyBox.

Configuração da Inicialização

O BusyBox, ao atuar como init, procura pelo arquivo /etc/inittab. Crie-o com o seguinte conteúdo básico:

::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r

Formato: <id>:<runlevel>:<ação>:<processo>

A primeira linha instrui o sistema a executar o script /etc/init.d/rcS durante a inicialização (sysinit). A segunda abre um shell interativo (respawn).

Crie e configure o script /etc/init.d/rcS:

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATH

# Montagem de sistemas de arquivos
mount -a
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
mount -o remount,rw /

# Popule o diretório /dev com base no kernel
mdev -s

Lembre-se de tornar o script executável: chmod +x /etc/init.d/rcS. Após esta configuração, a VM deve iniciar e fornecer um shell.

Configurações Adicionais

Usuário e Login

Para identificar o usuário root, crie o arquivo /etc/passwd:

root:x:0:0::/root:/bin/sh

Crie também o arquivo /etc/shadow para definir senhas:

root::1::::::

Uma senha vazia no campo :: permite login sem senha. Use o comando passwd dentro da VM para definir uma senha segura, que será gravada neste arquivo.

Modifique o /etc/inittab para exigir login:

::sysinit:/etc/init.d/rcS
::respawn:/sbin/getty -L console 0 vt100
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r

Nome do Host

Defina o nome do host no arquivo /etc/hostname (ex: meu-host). Carregue-o adicionando a seguinte linha ao final do script /etc/init.d/rcS:

hostname -F /etc/hostname

Configuração de Rede (dentro da VM)

Adicione as seguintes linhas ao /etc/init.d/rcS para configurar a interface de loopback e uma interface de rede estática:

# Rede
ifconfig lo up
ifconfig eth0 192.168.1.100 netmask 255.255.255.0 up
route add default gw 192.168.1.1 eth0

Configure um servidor DNS editando /etc/resolv.conf:

nameserver 8.8.8.8

Configuração da Rede no Host (WSL)

No host WL, execute os seguintes comandos para criar um dispositivo TAP que atuará como gateway para a VM:

ip tuntap add dev tap0 mode tap
ip link set dev tap0 up
ip addr add 192.168.1.1/24 dev tap0
iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.1/24 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward

Isso configura o tap0 com o IP 192.168.1.1 (o gateway para a VM) e habilita o mascaraemnto de rede (NAT), permitindo que a VM acesse a rede externa. Teste a conectividade da VM com ping 192.168.1.1 e, após configurar o DNS, com ping www.example.com.

Tags: BusyBox Linux QEMU Embedded Systems Virtualization

Publicado em 6-2 23:22 por Thomas