Obtendo o build do big endian linux para inicializar no ARM com o u-boot

1

Estou tentando fazer uma grande criação endian de uma distribuição do Linux para o ARM. Como estou no Gentoo, a compilação cruzada não poderia ser mais fácil. Eu já construí tudo, mas depois fiquei com a ideia de conseguir / o kernel inicializar.

Estou segmentando o Cubieboard com a CPU AllWinner A10. Como um bootloader eu uso o u-boot. Como o u-boot não suporta o big endian ARM, atualizei-o exatamente antes de passar o controle para o kernel:

diff -Naur u-boot-2016.01-1/arch/arm/lib/bootm.c u-boot-2016.01-2/arch/arm/lib/bootm.c
--- u-boot-2016.01-1/arch/arm/lib/bootm.c       2016-01-12 15:06:54.000000000 +0100
+++ u-boot-2016.01-2/arch/arm/lib/bootm.c       2017-07-09 14:13:29.675865446 +0200
@@ -315,7 +315,16 @@
                                                          0, machid, r2);
                } else
 #endif
+               {
+                       {
+                               unsigned long v;
+                               __asm volatile ("mrc p15, 0, %0, c1, c0, 0\n\t"
+                                               "orr %0, %0, #(1 << 7)\n\t" /* Switch to bigendian */
+                                               "mcr p15, 0, %0, c1, c0, 0" : "=&r" (v));
+                       }
+
                        kernel_entry(0, machid, r2);
+               }
        }
 #endif
 }

Eu originalmente usei uma sintaxe um pouco diferente, mas no final peguei um código conhecido para o trabalho do gerenciador de inicialização APEX (seu arm-kernel-shim). (No entanto, o registro é o mesmo que eu e o que li na documentação do ARM.)

Além disso, como o u-boot precisa ser little endian, preparei outro conjunto de ferramentas para ele - com o destino arm-linux-gnueabihf . Tanto quanto eu posso dizer, o próprio u-boot inicializa bem.

O kernel (principal) é compilado com um conjunto de ferramentas para o destino armeb-linux-gnueabihf . A partir da imagem compilada ( arch/arm/boot/Image dentro do kernel source / build tree) eu criei uma imagem inicializável (usando mkimage da minha compilação de inicialização):

mkimage -C none -A arm -T kernel -n Linux-4.9.9-gentoo -d /usr/armeb-linux-gnueabihf/usr/src/linux/arch/arm/boot/Image -ep 0x48000000 -a 0x48000000 /usr/armeb-linux-gnueabihf/boot/uimage

Eu peguei o arquivo DTB também do kernel:

cp /usr/armeb-linux-gnueabihf/usr/src/linux/arch/arm/boot/dts/sun4i-a10-cubieboard.dtb /usr/armeb-linux-gnueabihf/boot/

Quando eu carrego tudo no cartão µSD e tento inicializar, recebo a seguinte saída no console serial:

U-Boot SPL 2016.01 (Jul 16 2017 - 13:52:00)
DRAM: 1024 MiB
CPU: 1008000000Hz, AXI/AHB/APB: 3/2/2
Trying to boot from MMC


U-Boot 2016.01 (Jul 16 2017 - 13:52:00 +0200) Allwinner Technology

CPU:   Allwinner A10 (SUN4I)
I2C:   ready
DRAM:  1 GiB
MMC:   SUNXI SD/MMC: 0
In:    serial
Out:   serial
Err:   serial
SCSI:  SUNXI SCSI INIT
SATA link 0 timeout.
AHCI 0001.0100 32 slots 1 ports 3 Gbps 0x1 impl SATA mode
flags: ncq stag pm led clo only pmp pio slum part ccc apst
Net:   eth0: ethernet@01c0b000
starting USB...
USB0:   USB EHCI 1.00
USB1:   USB OHCI 1.0
USB2:   USB EHCI 1.00
USB3:   USB OHCI 1.0
scanning bus 0 for devices... 1 USB Device(s) found
scanning bus 2 for devices... 1 USB Device(s) found
Hit any key to stop autoboot:  0
=> setenv bootargs console=tty0 console=ttyS0,115200 earlyprintk hdmi.audio=EDID:0 disp.screen0_output_mode=EDID:1280x800p60 root=PARTUUID=AC9D6C6F-01 rootwait panic=10
=> ext2load mmc 0 0x48000000 boot/uimage
5025856 bytes read in 592 ms (8.1 MiB/s)
=> ext2load mmc 0 0x51000000 boot/sun4i-a10-cubieboard.dtb
28542 bytes read in 237 ms (117.2 KiB/s)
=> bootm 0x48000000 - 0x51000000
## Booting kernel from Legacy Image at 48000000 ...
   Image Name:   Linux-4.9.9-gentoo
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    5025792 Bytes = 4.8 MiB
   Load Address: 48000000
   Entry Point:  48000000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 51000000
   Booting using the fdt blob at 0x51000000
   Loading Kernel Image ... OK
   Loading Device Tree to 49ff6000, end 49ffff7d ... OK

Starting kernel ...

E ele simplesmente fica parado assim - sem progresso, sem saída, sem nada. Minha pergunta é: como proceder daqui / como descobrir o que está realmente acontecendo? Estou faltando alguma coisa, fiz alguma coisa errada (ou não fiz algo)?

Mais algumas coisas que tentei, mas sem sucesso:

  • troca de palavras da imagem do kernel (como o APEX faz) (resultou em undefined instruction na inicialização),

  • usando a imagem do kernel compactada,

  • usando o arquivo legado FEX em vez de FDT.

Atualização 2017/07/21: fui parcialmente bem-sucedido na solução do meu problema. Tomei a dica do comentário de Tom Rini e tentei compactar o zImage para a imagem que fez a inicialização do kernel. Com um programa init personalizado (apenas um simples Hello World compilado como BE ou LE), confirmei a suspeita do outro Tom Rini: meu kernel original não era grande, mas pouco. Para corrigir isso, adicionei as duas linhas a seguir ao início do .config do kernel:

CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
CONFIG_CPU_BIG_ENDIAN=y

Eu busquei minha inspiração de um como fazer para a Nvidia Jetson TK1 . Eu também adicionei a seguinte linha a arch/arm/mach-sunxi/Kconfig no final da seção A10:

select ARCH_SUPPORTS_BIG_ENDIAN

Descobriu-se que isso é suficiente para construir e inicializar um kernel big endian, já que o próprio kernel muda a CPU para o modo big endian. No entanto, ele faz isso com a instrução setend - seu escopo é apenas para o próprio kernel, não para o espaço do usuário (como explica o link na resposta de Murray Jensen).

Vou tentar:

  • ir para o ponto de entrada do descompactador do kernel por meio de exceção ou (se eu falhar)

  • remendando o kernel para que ele crie processos em grandes configurações de endian (apesar de eu sentir o cheiro de um campo minado lá ...).

por xHire 16.07.2017 / 14:44

1 resposta

0

Não sei muito sobre o ARM (ainda), mas de acordo com isto , " O bit EE no CP15 System Control Register (SCR) determina o endianness definido na exceção (ou seja, o endianness do próprio SO). " ... então parece-me que você precisa inserir a imagem do kernel carregada através de uma exceção de alguma forma, ou seja, você não pode simplesmente pular para o endereço (como o U-Boot parece fazer - veja boot_jump_linux() em this ).

    
por 17.07.2017 / 07:23