[U-Boot] [BUG] Crash when starting grub-arm.efi on BeagleBone Black
Heinrich Schuchardt
xypron.glpk at gmx.de
Fri Mar 8 21:09:32 UTC 2019
On 3/8/19 9:39 PM, Heinrich Schuchardt wrote:
> 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
>
Leif pointed me to this patch series:
https://lists.gnu.org/archive/html/grub-devel/2019-01/msg00113.html
He assumes than one of
[PATCH v4 1/2] mkimage: Use EFI32_HEADER_SIZE define in arm-efi case
[PATCH v4 2/2] mkimage: Align efi sections on 4k boundary
broke GRUB on armhf.
Best regards
Heinrich
More information about the U-Boot
mailing list