[U-Boot] [BUG] Crash when starting grub-arm.efi on BeagleBone Black

Heinrich Schuchardt xypron.glpk at gmx.de
Thu Mar 7 22:29:57 UTC 2019


On 3/7/19 12:05 PM, Adam Podogrocki wrote:
>>     Hello Heinrich,
>>
>>     I've checked U-Boot behaviour in following setups:
>>
>>      1. U-Boot v2018.09/v2018.11 and GRUB commit 72e80c025 (used by us
>>         in other setups)
>>      2. U-Boot v2019.01 and GRUB commit 72e80c025 (used by us in other
>>         setups)
>>      3. U-Boot v2019.01 and GRUB latest commit 9223eff8f

These are not commit numbers from git://git.savannah.gnu.org/grub.git
So to which repository do they relate?

On Google drive you supplied to me GRUB 35b909062. This is also not a
valid commit number.

First I tried to find the location of the crash that you reported:

$ hexedit grub-arm.efi # GRUB 35b909062

000060D4   33 7B 31 68  03 F0 0F 02  4F EA 13 1B  02 9B 5F 18
000060E4   2F 44 04 2A  78 D8 DF E8  02 F0 03 03  43 6A 75 00
000060F4   F0 89 11 B3  08 BB 79 1E  11 F8 01 2F  6A B9 40 F2
00006104   FD 11 00 EB  50 10 FB F7  F8 FC 60 4B  03 EB 81 01
                        ^^^^^^^^^^^

I analyzed the file with the tool available at
https://github.com/xypron/efi_analyzer

$ efianalyze grub-arm.efi # GRUB 35b909062

Offset to PE = 80
Machine type: 0x01c2, ARM or Thumb ("interworking")
Characteristics 0x30e
Image type: PE32
EFI application
ImageBase=0x0
SectionAlignment=0x1000
SizeOfImage=0x55000
.reloc.address=0x54000
.reloc.size=0x1000
BaseOfCode=0x1000
AddressOfEntryPoint=0x1000
Number of Sections 4
Section[0] .text
Virtual size 0x8000
Virtual address 0x1000
Size of raw data 0x8000
Pointer to raw data 0x1000
End of raw data 0x9000
Section[1] .data
Virtual size 0xb000
Virtual address 0x9000
Size of raw data 0xb000
Pointer to raw data 0x9000
End of raw data 0x14000
Section[2] mods
Virtual size 0x40000
Virtual address 0x14000
Size of raw data 0x40000
Pointer to raw data 0x14000
End of raw data 0x54000
Section[3] .reloc
Virtual size 0x1000
Virtual address 0x54000
Size of raw data 0x1000
Pointer to raw data 0x54000
End of raw data 0x55000

So the entry-point is 0x1000 and the virtual address 0x1000 matches the
position in the file. That makes things easy.

$ /usr/bin/arm-linux-gnueabihf-objdump -D -b binary -marm grub-arm.efi

    1000:       e59fc010        ldr     ip, [pc, #16]   ; 0x1018
    1004:       e58c0000        str     r0, [ip]
    1008:       e59fc00c        ldr     ip, [pc, #12]   ; 0x101c
    100c:       e58c1000        str     r1, [ip]
    1010:       e59fc008        ldr     ip, [pc, #8]    ; 0x1020
    1014:       e12fff1c        bx      ip
    1018:       0000c914        andeq   ip, r0, r4, lsl r9
    101c:       0000c910        andeq   ip, r0, r0, lsl r9
    1020:       0000610d        andeq   r6, r0, sp, lsl #2

This matches function _start() in grub-core/kern/arm/efi/startup.S:

        ldr     ip, =EXT_C(grub_efi_image_handle)
        str     r0, [ip]
        ldr     ip, =EXT_C(grub_efi_system_table)
        str     r1, [ip]
        ldr     ip, =EXT_C(grub_main)
        bx      ip
        END

So here we first store the image handle and the system table. Then we
branch to 610C in thumb mode (bit 0 is set in the address).

The entry point is called in U-Boot via

0x47f8765c <efi_start_image+100>        ldr    r0, [sp, #4]

0x47f87660 <efi_start_image+104>        blx    r3

So we have first a blx jump to ARM and then a bx jump to THUMB.

TODO for me:

According to
http://infocenter.arm.com/help/topic/com.arm.doc.uan0002a/UAN002A_1176-pan_use_of_blx.pdf
depending on the alignment of the blx command this sequence of commands
may fail on some ARM11 processors.

But the BeagleBone Black has an ARMv7-A and not an ARM11 processor. So
nothing to worry us.

The further disassembly depends on the start address:

/usr/bin/arm-linux-gnueabihf-objdump -D -b binary -marm \
--disassembler-options=force-thumb grub-arm.efi --start-addr=0x6100

00006100 <.data+0x6100>:
    6100:       b96a            cbnz    r2, 0x611e
    6102:       f240 11fd       movw    r1, #509        ; 0x1fd
    6106:       eb00 1050       add.w   r0, r0, r0, lsr #5
    610a:       f7fb fcf8       bl      0x1afe
    610e:       4b60            ldr     r3, [pc, #384]  ; (0x6290)
    6110:       eb03 0181       add.w   r1, r3, r1, lsl #2
    6114:       684a            ldr     r2, [r1, #4]
    6116:       b942            cbnz    r2, 0x612a

/usr/bin/arm-linux-gnueabihf-objdump -D -b binary -marm \
--disassembler-options=force-thumb grub-arm.efi --start-addr=0x610c

0000610c <.data+0x610c>:
    610c:       fcf8 4b60       ldc2l   11, cr4, [r8], #384
				; 0x180 ; <UNPREDICTABLE>
    6110:       eb03 0181       add.w   r1, r3, r1, lsl #2
    6114:       684a            ldr     r2, [r1, #4]
    6116:       b942            cbnz    r2, 0x612a
    6118:       463a            mov     r2, r7
    611a:       495e            ldr     r1, [pc, #376]  ; (0x6294)

So the next instruction after branching is
`ldc2l   11, cr4, [r8], #384`.

Next I put your grub_arm.efi into directory tftp/ and started U-Boot
qemu_arm_defconfig with:

qemu-system-arm -machine virt -cpu cortex-a15 \
-bios u-boot.bin -nographic -gdb tcp::1234 -netdev \
user,id=eth0,tftp=tftp,net=192.168.76.0/24,dhcpstart=192.168.76.9 \
-device e1000,netdev=eth0

I displayed the relocation offset with command bdinfo:

=> bdinfo
arch_number = 0x00000000
boot_params = 0x00000000
DRAM bank   = 0x00000000
-> start    = 0x40000000
-> size     = 0x08000000
baudrate    = 115200 bps
TLB addr    = 0x47ff0000
relocaddr   = 0x47f4f000 <<<<<< You need this address
reloc off   = 0x47f4f000
irq_sp      = 0x46e0dec0
sp start    = 0x46e0deb0
Early malloc usage: 11c / 400
fdt_blob    = 0x46e0ded8

In a separate mode I opened GDB:

gdb-multiarch u-boot -ex 'target remote localhost:1234'

(gdb) add-symbol-file u-boot 0x47f4f000
add symbol table from file "u-boot" at
        .text_addr = 0x47f4f000
(y or n) y
Reading symbols from u-boot...done.
(gdb) b efi_start_image
Breakpoint 1 at 0x385f8: efi_start_image. (2 locations)
(gdb) c
Continuing

When debugging the ldc2l instruction at 610c caused the same error that
you already observed:

=> bootefi $kernel_addr_r $fdtcontroladdr
Found 0 disks
## Starting EFI application at 40400000 ...
undefined instruction
pc : [<45cb610a>]          lr : [<47f87664>]
reloc pc : [<fdd6710a>]    lr : [<00038664>]
sp : 46e0dc28  ip : 45cb610d     fp : 47f6a324
r10: 00000003  r9 : 00000000     r8 : 46f11080
r7 : 40400000  r6 : 45e0c040     r5 : 00000000  r4 : 47f4f7c8
r3 : 45cb1000  r2 : 00000000     r1 : 47f4f7c8  r0 : 46f18010
Flags: nZCv  IRQs off  FIQs off  Mode SVC_32
Code: 1e79bb08 2f01f811 f240b96a eb0011fd (f7fb1050)
UEFI image [0x45cb0000:0x45d04fff] pc=0x610a '/grub_arm.efi'
Resetting CPU ...

I have no clue why GRUB would try to transfer data to a co-processor
(ldc2l   11, cr4, [r8], #384).

As I cannot find a match in git://git.savannah.gnu.org/grub.git I wonder
how you ended up with this in your GRUB.

I will stop my analysis here. I hope with the information provided you
are able to take over.

Best regards

Heinrich


More information about the U-Boot mailing list