I have IFS images supposed to run on board similar to OMAP5 uEVM. I am trying to run it on a QEMU virtual machine with the same Cortex-A15 CPU.
I have a bundle of questions, but first of all I would like to ask is it eminently doable?
TLDR
I decided to use U-Boot as a bootloader. I compiled it with arm-linux-gnueabi-gcc, arm-linux-gnueabihf-gcc from Ubuntu and arm-eabi-gcc-7.5 from linaro. All 3 U-Boot versions work. It looks like QNX binaries don't use hard float (armhf or armle-v7) even if target CPU support it. Is the gcc version important? Do I have to use one from the QNX toolchain to build U-Boot?
The image must be based on QNX 6.5. ifsdump gives me
Decompressed 3333189 bytes-> 9535664 bytes
Offset Size Name
0 8 *.boot
8 100 Startup-header flags1=0xd flags2=0 paddr_bias=0x7fce00000000
preboot_size=0x8
image_paddr=0x80100008 stored_size=0x347e78
startup_size=0x1a108 imagefs_size=0x9180b0
ram_paddr=0x80100008 ram_size=0x9321b8
startup_vaddr=0x8010097c
108 1a008 startup.*
1a110 5c Image-header mountpoint=/
flags=0x4 script=3 boot=3758096386 mntflg=0
1a16c 15b4 Image-directory
---- ---- Root-dirent
gid=0 uid=0 mode=0755 ino=1 mtime=606f22bf
1c000 94000 proc/boot/procnto-smp-instr
gid=0 uid=0 mode=0777 ino=3758096386 mtime=606f1eb4
----- procnto-smp-instr - ELF32LE ET_EXEC EM_ARM -----
e_flags : 0x5000002
e_entry : 0xfe051c60
e_phoff : 52
e_phentsize : 32
e_phnum : 4
segment 0
p_type : Unknown(1879048193)
p_offset : 566704
p_vaddr : 0xFE0A65B0
p_paddr : 0xFE0A65B0
p_filesz : 32
p_memsz : 32
p_flags : R--
p_align : 4
segment 1
p_type : PT_LOAD
p_offset : 4096
p_vaddr : 0xFE01D000
p_paddr : 0x8011D000
p_filesz : 550320
p_memsz : 550320
p_flags : R-X
p_align : 4096
segment 2
p_type : PT_LOAD
p_offset : 557056
p_vaddr : 0xFE0A4000
p_paddr : 0x801A4000
p_filesz : 46584
p_memsz : 46584
p_flags : RW-
p_align : 4096
segment 3
p_type : PT_NULL
p_offset : 0
p_vaddr : 0x0
p_paddr : 0x0
p_filesz : 0
p_memsz : 0
p_flags : ---
p_align : 4
I extracted the image with dumpifs -u QNX-IFS.raw QNX-IFS
and copied it to a virtual drive.
My RAM space starts at 0x40000000 (virt-6.0 machine) but the target board at 0x80100000. So I adjusted original startup_vaddr=0x8010097c
and executed
fatload virtio 0:1 0x40400000 QNX-IFS.raw
go 0x4040097c
It hangs forever. Startup-header and startup.* seems to be hardware specific, doesn’t it? But it’s goal is to run /proc/boot/procnto-smp-instr and startup scripts.
Next I tried to launch a kernel using bootelf. It crashes with:
=> bootelf 0x4041c000
## Starting application at 0xfe051c60 ...
prefetch abort
pc : [<fe051c5c>] lr : [<bff598e0>]
reloc pc : [<3e0fbc5c>] lr : [<000038e0>]
Prefetch abort means that it references memory out of range. This magic address comes from the elf header. It implies that it reads the elf-header correctly and tries to launch it.
readelf -a proc/boot/procnto-smp-instr
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0xfe051c60
Start of program headers: 52 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x5000002, Version5 EABI, <unknown>
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 4
Size of section headers: 0 (bytes)
Number of section headers: 0
Section header string table index: 0
There are no sections in this file.
There are no sections to group in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
EXIDX 0x08a5b0 0xfe0a65b0 0xfe0a65b0 0x00020 0x00020 R 0x4
LOAD 0x001000 0xfe01d000 0x8011d000 0x865b0 0x865b0 R E 0x1000
LOAD 0x088000 0xfe0a4000 0x801a4000 0x0b5f8 0x0b5f8 RW 0x1000
NULL 0x000000 0x00000000 0x00000000 0x00000 0x00000 0x4
Both boards have the same 2Gb of RAM but different virtual memory address space. I decided to extend my board memory to 3Gb that makes the entry point address in range. Then I tried to launch a kernel again. It crashes again with new error:
=> bootelf 0x4041c000
## Starting application at 0xfe051c60 ...
undefined instruction
pc : [<fee13c18>] lr : [<fff598e0>]
reloc pc : [<feebdc18>] lr : [<000038e0>]
sp : fee14d40 ip : 00000030 fp : 00000028
r10: 00000000 r9 : fef15ed8 r8 : 00000000
r7 : fef30620 r6 : 00000000 r5 : 00000000 r4 : 4041c000
r3 : fe051c60 r2 : 00000001 r1 : fef30620 r0 : 00000000
Flags: nZCv IRQs off FIQs off Mode SVC_32
Code: 00000000 00000000 00000000 00000000 (fee140cf)
Resetting CPU ...
On one hand /proc/boot/procnto-smp-instr is elf-executable for Cortex-A15, on the other hand kernel is not a regular executable. Header implies that it is hardware specific.
Is there any chase to run it?
Also I found a package with kernel for Cortex-A15 on community qnx web site. It contains four versions of procnto*. But they are relocatable object files for armle-v7. Is it possible to link it to make it executable?
I am really not experienced in arm development neither QNX. I would really appreciate any thought or advice.
Your main problem here is that Arm boards are generally pretty different from each other, and so bootloaders and OS kernels typically have to be built with support for whatever board they are going to run on. (This is very different from the x86 world, where basically every machine looks more-or-less like a standard PC and software is all built to run on that.)
So the short answer is that unless the QNX images you have were built to be pretty generic "run on a lot of different things, and take a device tree file to tell them about the hardware"[*], then they are only going to run on QEMU if QEMU has a model of the hardware that the QNX image is expecting. There is no QEMU model of OMAP5.
[*] You can build Linux like this. You can also build Linux to be very specifically targeted to a given board, with no extra device driver support for anything else. I don't know what QNX lets you do.