Emulando sistemas Linux embarcados com QEMU
1. Introdução
O desenvolvimento de software embarcado depende de dispositivos de hardware embarcados, como placas de desenvolvimento, dispositivos de módulos externos, etc., mas se o trabalho de depuração não tem nada a ver com periféricos, apenas a depuração do kernel pode ser simulada usando o QEMU sem a compra de hardware.
Está disponível para hosts Linux e Windows e destinos PowerPC, ARM, MIPS e SPARC emulados. O QEMU adota a abordagem de fornecer uma camada de tradução mínima entre o host e o processador de destino. O processador host é aquele que executa o emulador e o processador de destino é o que está sendo emulado.
A seguir, uma introdução detalhada ao processo de configuração do ambiente de desenvolvimento QEMU.
2. Ambiente
2.1 Ambiente usado
* Ubuntu-18.04.1
OU:
* PC: Windows10
* Máquina Virtual:VirtualBox-5.18
* SO Virtual:Ubuntu-18.04.1
* Placa de desenvolvimento simulado: vexpres
2.2 Ferramentas usadas na configuração do ambiente
* qemu-4.2.0
* linux-4.14.172 (Kernel Linux)
*u-boot-2017.05
* caixa ocupada-1.31.1
* braço-linux-gnueabi-gcc
Coloque todos os arquivos relacionados em /home/joe/qemu
3. Instale ferramentas de compilação cruzada
# sudo apt instalar gcc-brafrin-linux-gnueabi
Verifique se a instalação foi bem sucedida
$ arm-linux-gnueabi-gcc -v
Usando built-inspecs. COLLECT_GCC=arm-linux-gnueabi-gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc-cross/arm-linux-gnueabi/7/lto-wrapper Alvo: arm-linux-gnueabi Configurado com: ../src/configure -v –with-pkgversion='Ubuntu/Linaro 7.5.0-3ubuntu1~18.04′–with-bugurl=file:///usr Modelo de rosca: posix gcc versão 7.5.0 (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) |
4. Configurar e compilar o kernel do Linux
4.1 Baixe o Kernel Linux
Baixe a versão do kernel necessária em www.kernel.org.
Aqui eu baixo a versão relativamente mais recente do kernel com suporte de longo prazo linux-4.4.157
wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.157.tar.xz para o diretório /qemu
4.2 Descompacte o kernel do Linux
# tar xvJf linux-4.4.157.tar.xz
4.3 Compilar Kernel Linux
// Digite o diretório do arquivo de origem do kernel
#cd linux-4.4.157
make CROSS_COMPILE=arm-linux-gnueabi-ARCH=arm vexpress_defconfig
make CROSS_COMPILE=arm-linux-gnueabi-ARCH=arm menuconfig
Se a execução do menuconfig mostrar que o pacote ncurses está ausente, basta executar o seguinte comando para instalá-lo)
$ sudo apt-get install libncurses5-dev
Entre na configuração do menu e faça as seguintes configurações
Compilar com cadeia de ferramentas cruzada
Após a compilação bem-sucedida, gere um arquivo de imagem do kernel no diretório
arch/arm/boot, zImage e dtb podem ser copiados em uma pasta separada para uso conveniente
5. Instale as Ferramentas QEMU
5.1 Instalar o QEMU
* wget https://download.qemu.org/qemu-4.2.0.tar.xz
* tar xvJf qemu-4.2.0.tar.xz
*cd qemu-4.2.0
5.2 Instale pacotes dependentes antes de configurar o QEMU
# apt instala zlib1g-dev
# apt instalar libglib2.0-0 libglib2.0-dev
# apt instalar libsdl1.2-dev
# apto instalar libpixman-1-dev libfdt-dev
Para evitar que os arquivos fiquem confusos após a compilação, crie o diretório do construtor como o caminho de destino intermediário para a compilação.
Configure, compile e instale o QEMU.
5.3 Configure o QEMU para suportar todas as placas sob a arquitetura do braço
# ../configure -tart-list = braço-softmmu -Audio-drv-list =
Se o pixman estiver ausente quando o prompt a seguir for exibido,
use sudo apt-get install libpixman-1-dev para instalá-lo.
5.4 Ver versão do QEMU
5.5 Ver placas de desenvolvimento suportadas pelo QEMU
5.6 Executar QEMU
# qemu-system-arm -M vexpress-a9 -m 512M -kernel ./zImage -dtb ./vexpress-v2p-ca9.dtb -nographic -append “console=ttyAMA0”
OU:
$ pwd
/home/joe/qemu
# qemu-system-arm -M vexpress-a9 -m 512M -kernel linux-.4.157/arch/arm/boot/zImage -dtb linux-4.4.157/arch/arm/boot/dts/vexpress-v2p-ca9. dtb -nographic -append “console=ttyAMA0”
Para testar melhor e iniciar o qemu, você pode criar o script de inicialização start.sh e dar permissão ao script para executar chmod +x start.sh
#! / Bin / bash
braço do sistema qemu \
-M vexpress-a9 \
-m 512M\
-kernel /home/joe/jemu/linux-4.4.157/arch/arm/boot/zImage\
-dtb /home/joe/jemu/linux-4.4.157/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \
-nográfico \
-acrescentar “console=ttyAMA0”
6. Crie um sistema de arquivos raiz
Use o busybox para criar um sistema de arquivos raiz simples.
6.1 Baixe a ferramenta busybox
Baixe o busybox em https://busybox.net/downloads/
# wget https://busybox.net/downloads/busybox-1.31.1.tar.bz2
# tar xjvf busybox-1.31.1.tar.bz2
#cd busybox-1.31.1
# faz defconfig
# make CROSS_COMPILE=arm-linux-gnueabi-
# make install CROSS_COMPILE=arm-linux-gnueabi-
As informações a seguir são solicitadas, indicando que a instalação foi bem-sucedida.
Após a conclusão da instalação, o arquivo de destino gerado assume como padrão o diretório ./_install.
6.2 Gerar sistema de arquivos raiz
6.2.1 compilar e instalar o busybox
#mkdir rootfs
# sudo cp -r _install/* rootfs/
6.2.2 Adicionar biblioteca glibc, adicionar carregador e biblioteca dinâmica no sistema de arquivos raiz
# sudo cp -r _install/* rootfs/
# sudo cp -p /usr/arm-linux-gnueabi/lib/* rootfs/lib/
6.2.3 Crie 4 dispositivos terminais tty (c significa dispositivo de caractere, 4 é o número do dispositivo principal e 1~4 são os números do dispositivo secundário, respectivamente)
6.3 Faça a imagem do sistema de arquivos do cartão SD
6.3.1 Gerar uma imagem de cartão SD vazia
# dd if=/dev/zero of=rootfs.ext3 bs=1M contagem=32
6.3.2 Formatar cartão SD como sistema de arquivos exts
#mkfs.ext3 rootfs.ext3
6.3.3 Gravar rootfs no cartão SD
# sudo mount -t ext3 rootfs.ext3 /mnt -o loop
# sudo cp -rf rootfs/* /mnt/
# sudoumount /mnt
7. Verifique
7.1 Iniciar Qemu
Execute o seguinte comando para testar, verifique se o kernel compilado pode ser executado com sucesso
# sudo qemu-system-arm -M vexpress-a9 -m 512M -kernel ~/qemu/zImage –dtb ~/qemu/vexpress-v2p-ca9.dtb -nographic -append “console=ttyAMA0”
Ou usando o script:
No teste acima, o kernel reportará pânico, sugerindo que não temos o sistema de arquivos raiz.
O problema acima é devido à ferramenta busybox gerada no ambiente x86.
Usamos make install ao instalar o busybox, então você deve usar
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install |
A ferramenta de compilação gera a ferramenta busybox usada pela plataforma arm
# arquivo rootfs/bin/busybox
rootfs/bin/busybox: executável LSB de 32 bits ELF, ARM, EABI5 versão 1 (SYSV), vinculado dinamicamente, interpretador /lib/ld-, para GNU/Linux 3.2.0, BuildID[sha1]=cbcd33b8d6c946cb19408a5e8e714de554c87f52, removido
7.2 Verifique novamente
Agora, o Qemu iniciou o kernel Linux e montou o sistema de arquivos com sucesso, podendo interagir com o sistema com funções simples através do terminal serial. O problema de não poder rodar /etc/init.d/rcS no processo de impressão, você só precisa adicionar o arquivo /etc/init.d/rcS. O conteúdo do arquivo pode ser uma instrução de prompt.
7.3 Sair do QEMU
Duas maneiras de sair do qemu
* Em outra entrada de terminal: mate todos os qemu-system-arm
* Na entrada do Qemu: Ctrl+A; X
QEMU: Terminado
8. Inicie o kernel Linux através do u-boot
Os sistemas embarcados geralmente incluem: u-boot, kernel, rootfs e appfs. A relação posicional dessas peças na placa de desenvolvimento ARM mostrada na figura abaixo
Carregador de inicialização | Parâmetros de inicialização | Núcleo | rootfs | Aplicativos |
Rootfs pode ser executado em placa ou PC
8.1 Preparar o U-boot
8.1.1 Baixar u-boot
http://ftp.denx.de/pub/u-boot/, usamos: u-boot-2021.01.tar.bz2
# tar -jxvf u-boot-2018.09.tar.bz2
8.1.2 Compilar u-boot
# vim Makefile
CROSS_COMPILE = arm-linux-gnueabi-
#vimconfig.mk
ARCO = braço
# make vexpress_ca9x4_defconfig, erro
Necessidade: sudo apt install bison
sudo apt instalar flex
então: # make -j4 error
Necessário: export CROSS_COMPILE=arm-linux-gnueabi-
exportar ARCH = arm
novamente: # make vexpress_ca9x4_defconfig
# make -j4
8.1.3 Teste, inicie o u-boot
$ sudo qemu-system-arm -M vexpress-a9 -m 512M -kernel u-boot-2021.01/u-boot –nográfico
8.2 Compilação da configuração do kernel
Use u-boot para inicializar a imagem do kernel:
Precisa compilar o kernel no formato uImage,
Precisa especificar o endereço de carregamento de uImage na memória
Especifique ao compilar o kernel: make LOADADDR=? uImagem -j4
# cd /home/joe/qemu/linux-4.4.157
#faça LOADADDR=0x60003000 uImage -j4
Após a conclusão da compilação do u-boot, um arquivo mkimage será gerado na pasta de ferramentas, copie este arquivo para a pasta bin no diretório do compilador cruzado.
$cdqemu/linux-4.4.157
Erro:
$ sudo apt instalar u-boot-tools
Obter uImage
9. Configurações de função de rede QEMU
Quando a máquina virtual Qemu inicia no u-boot, o uImage precisa ser carregado na memória e o uImage pode ser baixado para o endereço especificado na memória através do servidor TFTP.
9.1 Verifique se o kernel do host suporta o módulo tun/tap
// Instala as duas ferramentas das quais a rede em ponte depende
# sudo apt install uml-utilities bridge-utils
Criar arquivo de dispositivo tun: /dev/net/tun (geralmente criado automaticamente)
Modifique o /etc/network/interfaces (configure a rede, reinicie para entrar em vigor)
# sudo vim /etc/network/interfaces
auto loiface lo inet loopbackauto enp0s3 // nome da placa de rede virtualauto br0iface br0 inet dhcpbridge_ports enp0s3 |
NUNCA Reinicie
# reinicializar
Em seguida, verifique o ambiente de rede do Qemu
A porta de rede virtual br0 é a porta de rede para a comunicação entre a máquina virtual Qemu e o host Linux.
10. Instale o servidor TFTP
Crie um servidor TFTP para baixar o uImage para a memória ao iniciar o uImage para a placa de desenvolvimento de simulação Qemu
10.1 Instale a ferramenta tftp
$ apt-get install tftp-hpa tftpd-hpa xinetd
10.2 Modifique o arquivo de configuração e defina o diretório do servidor TFTP
# sudo vim /etc/default/tftpd-hpa
...... TFTP_DIRECTORY =”/home/joe/tftpboot” ...... |
10.3 Crie um diretório tftp no host Linux
# mkdir /home/joe/tftpboot
#chmod 777 /home/joe/tftpboot
10.4 Reinicie o serviço tftp
# sudo /etc/init.d/tftpd-hpa reiniciar
10.5 Definir parâmetros de inicialização do kernel no u-boot
copie uImage e cexpress-v2p-ca9.dtb para tftpboot
Inicie o Qemu para verificar
$ sudo qemu-system-arm -M vexpress-a9 -m 512M -kernel u-boot-2021.01/u-boot –nographic -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 -sd rootfs. ramal3
Agora, o diretório rootfs é um sistema de arquivos raiz simples, que pode ser transformado em um arquivo espelho, e o arquivo espelho pode ser gravado na placa de desenvolvimento, ou o kernel Linux pode ser iniciado pelo u-boot no Qemu e montado no arquivo espelho. Ele também pode ser configurado para inicializar via sistema de arquivos de rede NFS.
11. Monte o sistema de arquivos NFS
11.1 Instalar e configurar o serviço NFS
NUNCA instale
$ sudo apt instalar servidor nfs-kernel
11.1.2 Configuração
$ sudo mkdir /home/joe/qemu/rootfs
$ sudo chown none:nogroup /home/joe/qemu/rootfs
$ sudo chmod 777 /home/joe/qemu/rootfs
$ sudo nano /etc/exportações
Adicione: /home/joe/qemu/rootfs *(rw,sync,no_root_squash)
Reinicie o servidor nfs:
$ sudo /etc/init.d/nfs-kernel-server restart
Ou: $systemctl restart nfs-kernel-server
Verifique se o diretório compartilhado NFS foi criado
$ sudo showmount –e
Ao usar o sistema de arquivos de rede NFS, o host Linux precisa fechar o firewall do sistema, caso contrário, ocorrerão anormalidades quando o sistema estiver em execução.
Conclusão
Espero que, com a ajuda deste blog, você saiba mais sobre o QEMU. Todas as técnicas demonstradas acima foram usadas em várias submissões ao nosso programa. Não há uma maneira única e fixa de emular com o QEMU. Explore diferentes técnicas e veja o que funciona para você. Familiarize-se com o conhecimento e você ficará surpreso em como ele pode ajudá-lo de maneiras inesperadas.