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

Heinrich Schuchardt xypron.glpk at gmx.de
Fri Mar 8 20:39:12 UTC 2019


On 3/7/19 11:29 PM, Heinrich Schuchardt wrote:
> 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
> 

On 3/8/19 2:12 PM, Adam Podogrocki wrote:> Hello Heinrich,
>
> Just for clarification
> -
http://git.savannah.gnu.org/cgit/grub.git/commit/?id=35b909062e7b334eb4af372be3260d0f62d85375
> - it is a commit I am referring to as GRUB #35b909062
>
> I truly appreciate your help.
>
> Regards,
> Adam Podogrocki

Thanks for pointing me to that commit.

I now have built that GRUB version with

./configure --target=arm-linux-gnueabihf --with-platform=efi \
  --disable-grub-emu-usb TARGET_CC=arm-linux-gnueabihf-gcc

Now I tried to find out what grub_main() looks like:

$ objdump -D -marm  grub-core/foo/usr/local/lib/grub/arm-efi/kernel.img

00005ce4 <grub_main>:
    5ce4:       b583            push    {r0, r1, r7, lr}
    5ce6:       f7ff fffe       bl      48 <grub_machine_init>
    5cea:       2002            movs    r0, #2
    5cec:       4e74            ldr     r6, [pc, #464]
    5cee:       f7ff ffc3       bl      5c78 <grub_list_remove+0x16>
    5cf2:       4874            ldr     r0, [pc, #464]
    5cf4:       f7ff fffe       bl      69b0 <grub_err_printf>
    5cf8:       2000            movs    r0, #0
    5cfa:       f7ff ffbd       bl      5c78 <grub_list_remove+0x16>

I found that code in your grub_arm.efi:

$ hexedit grub-arm.efi

                                                  v
00006D00   C0 18 70 47  18 C9 00 00  6D 69 6D 67 >83 B5 FA F7
00006D10   9B F9 02 20  74 4E FF F7  C3 FF 74 48  00 F0 6C FE
00006D20   00 20 FF F7  BD FF 33 68  E3 B1 19 68  70 4A 91 42

So what remains to find out, is why function _start() in
grub-core/kern/arm/efi/startup.S is not jumping to 0x6D0d but to 0x610D.

This is the start of the relocation table:

00054000   00 10 00 00  88 00 00 00  18 30 1C 30  20 30 2C 30
00054010   44 30 80 30  84 30 88 30  94 30 C4 30  C8 30 34 31
00054020   38 31 3C 31  40 31 44 31  B8 31 BC 31  C0 31 E8 33
00054030   EC 33 FC 33  00 34 04 34  08 34 0C 34  10 34 14 34

So we start with
Page RVA = 0x1000
Block Size = 0x88

and these relocations
Type 3 - E_REL_BASED_HIGHLOW @ 0x018
Type 3 - E_REL_BASED_HIGHLOW @ 0x01c
Type 3 - E_REL_BASED_HIGHLOW @ 0x020

This matches the three addresses used in _start().

According to the PE-COFF spec:
"To apply a base relocation, the difference is calculated between the
preferred base address and the base where the image is actually loaded.
If the image is loaded at its preferred base, the difference is zero and
thus the base relocations do not have to be applied."

The preferred load address of the image is ImageBase = 0 and the section
starting at 0x1000 has a VirtualAddress of 0x1000. So in our analysis
above no relocation has to be considered.

Thus I would consider this a bug in GRUB.

Best regards

Heinrich


More information about the U-Boot mailing list