|
From: | ckim |
Subject: | RE: Please help.. I wish to load .elf file directly for baremetal run.. |
Date: | Wed, 24 Mar 2021 21:48:45 +0900 |
Hello all, I managed to make the baremetal program run using pflash in address 0~64KB and RAM starting from 0x40000000. (I wanted to reply as a follow-up to Jakob Bohm’s reply to my question, but I didn’t receive his email. It’s only in the email archive. His suggestion was that I have to do as I really have to do on a real bare-metal machine but it looked much more difficult so I devised a trick which I’ll explain below.)
In my case, when I analyze the test.elf file, I could see two programs listed from program header. Program loading is per program(=segment), not per section in .elf file. This is the Program Headers output of “readelf -lW test.elf” command. Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x010000 0x0000000000000000 0x0000000000000000 0x013bc8 0x013bc8 R E 0x10000 LOAD 0x030000 0x0000000040000000 0x0000000040000000 0x011178 0x0114cc RW 0x10000 From the ‘sections to segment mapping’ output of the readelf, I could see all .text and .rodata sections are in the first program (program #0), and .data other read/write sections are grouped into the second program (program #1). The first one (program #0) is for pflash (or ROM) starting at 0. Its size is 0x013bc8. The second one (program #1) is for RAM starting at 0x40000000. Its MemSize size is 0x011178 (its file size is smaller because program #1 contains .bss section, uninitialized data, which doesn’t need to take space in the file). Now make the pflash.img file using the program #0 like this. (program #0 is read-only data like .text. In the test.elf file, offset 0x010000 = 65536, size 0x013bc8 = 80840, but I used size 0x18000 = 98304, it won’t hurt to copy some more data to pflash) dd skip=65536 count=98304 if=test.elf of=pflash.img bs=1 truncate -s 67108864 pflash.img (the pflash size is 64MB in ‘virt’ machine)
And in arm_load_kernel function in hw/arm/boot.c , change as below. (block arm_setup_firmware_boot) if (!info->kernel_filename || info->firmware_loaded) { arm_setup_firmware_boot(cpu, info); } else { arm_setup_direct_kernel_boot(cpu, info); } if (0) { // (!info->kernel_filename || info->firmware_loaded) { arm_setup_firmware_boot(cpu, info); } /* else */ { arm_setup_direct_kernel_boot(cpu, info); }
In include/hw/elf_ops.h, in function load_elf64, (it’s shown as glue(load_elf, SZ) near line 315. Version 5.1.0) (this is skipping program #0 from being loaded, which is provided by pflash) total_size = 0; for(i = 0; i < ehdr.e_phnum; i++) { ph = &phdr[i]; if (ph->p_type == PT_LOAD) { total_size = 0; for(i = 1; i < ehdr.e_phnum; i++) { ph = &phdr[i]; if (ph->p_type == PT_LOAD) {
The command I used is : (it provides both -kernel and -drive if=pflash options. With the modifications above, it just runs ok.) qemu-system-aarch64 -machine type=virt,gic-version=3,secure=true,virtualization=true -cpu cortex-a72 -nographic -smp 1 -m 2048 -semihosting -kernel test.elf -drive if=pflash,file=pflash.img,format=raw,readonly=on I know this is not a normal method but it suffices my current need because I don’t have enough time. Hope this might be helpful to someone! Thank you. Chan Kim From: ckim@etri.re.kr <ckim@etri.re.kr> If I change the linker script so that the program loads and starts at RAM address, I can use -kernel test.elf and run the program. But I’m still curious if I can load the program at 0x0 (ROM area) and use some data at 0x40000000 (RAM) like we can do in rtl simulation. Thanks! Chan Kim From: ckim@etri.re.kr <ckim@etri.re.kr> Hello all, Using the help from this email list, I’m using command below for my baremetal program test on qemu. (-s -S for connecting with gdb) : $aarch64-none-elf-objcopy -O binary test.elf test.bin $cp test.bin pflash.img; truncate -s 67108864 pflash.img //to cut it down to 64MB because the pflash size is 64MB) $qemu-system-aarch64 -machine type=virt,gic-version=3,secure=true,virtualization=true -cpu cortex-a72 -nographic -smp 1 -m 2048 -drive if=pflash,file=pflash.img,format=raw,readonly=on -s - The entry address is 0. The problem is this test.bin can become very big when I have some space between section. For example, if I want to put some initialized data (that can be changed) in RAM at 0x40000000, this bin file becomes bigger than 1GB. (because it fills the in-between spaces in .bin file) I tried just using -kernel test.elf but it errors in rom_check_and_register_reset() inside qemu_init. And the arm64 virt machine places dtb in the first RAM area. Isn’t there any option though which I can just load the .elf file (each section to its address) and run from the entry address? and is it possible to disable dtb loading at the first RAM address? Thank you for any help. Chan Kim |
[Prev in Thread] | Current Thread | [Next in Thread] |