u-boot를 사용하여 ARM에서 부팅할 빅엔디안 Linux 빌드 가져오기

u-boot를 사용하여 ARM에서 부팅할 빅엔디안 Linux 빌드 가져오기

ARM용 빅엔디안 Linux 배포판을 만들려고 합니다. 저는 Gentoo를 사용하고 있기 때문에 크로스 컴파일이 이보다 더 쉬울 수는 없습니다. 나는 이 모든 것을 구축했지만 커널을 시작하는 데 멈췄습니다.

내 목표는 AllWinner A10 CPU가 탑재된 Cubieboard입니다. 저는 u-boot를 부트로더로 사용합니다. u-boot는 빅엔디안 ARM을 지원하지 않기 때문에 제어권을 커널에 전달하기 전에 이를 패치했습니다.

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
 }

처음에는 몇 가지 다른 구문을 사용했지만 결국 APEX 부트로더(arm-kernel-shim)에서 작동하는 것으로 알려진 코드를 사용하게 되었습니다. (그럼에도 불구하고 레지스터는 내가 가지고 있는 것과 ARM 문서에서 읽은 것과 동일합니다.)

또한 u-boot에는 little-endian 바이트 순서가 필요하므로 이를 위한 또 다른 도구 체인인 target 을 준비했습니다 arm-linux-gnueabihf. 내가 아는 한, u-boot 자체는 정상적으로 부팅됩니다.

(메인라인) 커널은 대상의 툴체인을 사용하여 컴파일됩니다 armeb-linux-gnueabihf. 컴파일된 이미지( arch/arm/boot/Image커널 소스/빌드 트리)에서 부팅 가능한 이미지를 빌드했습니다( mkimageu-boot 빌드 사용).

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

또한 커널에서 DTB 파일을 얻었습니다.

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

모든 것을 µSD 카드에 로드하고 부팅을 시도하면 직렬 콘솔에 다음과 같은 출력이 나타납니다.

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 ...

진행도 없고 출력도 없고 아무 것도 없습니다. 제 질문은 여기에서 어떻게 갈 수 있느냐는 것입니다./실제로 무슨 일이 일어나고 있는지 어떻게 알 수 있습니까? 내가 뭔가 놓치고 있는 걸까요, 뭔가 잘못하고 있는 걸까요(또는 뭔가를 하고 있지 않은 걸까요)?

나는 또한 성공하지 못한 채 몇 가지를 시도했습니다.

  • APEX와 마찬가지로 커널 이미지 단어 교환( undefined instruction부팅 시 발생)

  • 압축된 커널 이미지를 사용하여,

  • FDT 대신 레거시 FEX 파일을 사용하십시오.


2017/07/21 업데이트: 문제 해결에 부분적으로 성공했습니다. Tom Rini의 의견에서 힌트를 얻어 zImage를 uImage로 패키징하여 커널을 부팅 가능하게 만들었습니다. init 프로그램(간단한 Hello World 컴파일된 BE 또는 LE)을 사용자 정의함으로써 Tom Rini의 또 다른 의심을 확인했습니다. 원래 커널은 빅 엔디안이 아니라 리틀 엔디안이었습니다. 이 문제를 해결하기 위해 커널 상단에 다음 두 줄을 추가했습니다 .config.

CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
CONFIG_CPU_BIG_ENDIAN=y

내 영감은 다음에서 비롯됩니다엔비디아 젯슨 TK1 사용법. 또한 arch/arm/mach-sunxi/KconfigA10 섹션 끝에 다음 줄을 추가했습니다.

select ARCH_SUPPORTS_BIG_ENDIAN

커널 자체가 CPU를 빅엔디안 모드로 전환하기 때문에 이것이 빅엔디안 커널을 빌드하고 부팅하기에 충분하다는 것이 밝혀졌습니다. 그러나 지침을 통해 그렇게 합니다 setend. 해당 범위는 사용자 공간이 아닌 커널 자체에만 적용됩니다(Murray Jensen의 답변 링크에서 설명).

나는 이것을 시도할 것이다:

  • 예외를 통해 커널의 압축 해제기 진입점으로 점프하거나 (실패한 경우)

  • 프로세스가 빅 엔디안으로 생성되도록 커널을 패치합니다(거기서 지뢰밭 냄새가 나긴 하지만...).

답변1

저는 아직 ARM에 대해 잘 모르지만,이것,"CP15 시스템 제어 레지스터(SCR)의 EE 비트는 예외 발생 시 설정된 엔디안(즉, 운영 체제 자체의 엔디안)을 결정합니다."...따라서 로드된 커널 이미지를 예외를 통해 어떻게든 공급해야 하는 것 같습니다. 즉, 해당 주소로 바로 이동할 수는 없습니다(U-Boot가 하는 것처럼 - boot_jump_linux()참조 ).이것).

관련 정보