Load a binary into flash memory using gdb - arm

I'd like to flash a binary file into my ARM MCU flash memory using gdb.
Currently I'm able to load an elf like this:
# arm-none-eabi-gdb --command=flash.gdb "myfirmware.elf"
# cat flash.gdb
set confirm off
target remote 127.0.0.1:7224
monitor reset
load
detach
quit
Basically the load command is good at loading elf sections to the right addresses.
However to put multiple firmware in the MCU flash memory, I'd like to send a complete binary image.
In order to test it, I made a zero.bin image (containing nothing but 0):
# hexdump zero.bin
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
0020000
# arm-none-eabi-gdb
(gdb) target remote 127.0.0.1:7224
(gdb) mon reset halt
(gdb) mon reset init
(gdb) set arm fallback-mode auto
(gdb) set debug arm
(gdb) restore zero.bin binary 0x0
Restoring binary file zero.bin into memory (0x0 to 0x20000)
Writing to flash memory forbidden in this context
(gdb) info mem
Using memory regions provided by the target.
Num Enb Low Addr High Addr Attrs
0 y 0x00000000 0x00020000 flash blocksize 0x800 nocache
1 y 0x00020000 0x100000000 rw nocache
(gdb) delete mem 1
warning: Switching to manual control of memory regions; use "mem auto" to fetch regions from the target again.
(gdb) delete mem 0
(gdb) mem 0 0x100000000 rw nocache
(gdb) info mem
Using user-defined memory regions.
Num Enb Low Addr High Addr Attrs
1 y 0x00000000 0x100000000 rw nocache
(gdb) restore zero.bin binary 0x0
Restoring binary file zero.bin into memory (0x0 to 0x20000)
(gdb) x/10 0x0
0x0: 0x20003000 0x00003c5d 0x00003c7d 0x00003c7d
0x10: 0x00000000 0x00000000 0x00000000 0x00000000
0x20: 0x00000000 0x00000000
So this doesn't seem to work, as you can see in 0x0 it should be full of '0' but it still contains my previous firmware (the vector table actually)
What do I miss? Or maybe there is another way to load a binary using gdb?

If you are using OpenOCD,
mon flash write_bank <num> <file_name> <offset>
should help you.
For example, if your flash starts at 0x400000,
mon flash write_bank 0 zero.bin 0x100000
will write the zero.bin file at 0x500000, assuming that address is writable.

You can't delete memory region. Because GDB uses vFlashWrite packet for writing to flash memory and M or X packets for writing to RAM.
I know only one way to write binary data to flash memory using gdb.
You need to transform your binary image to elf-file with one single .data section.
powerpc-objcopy -I binary -O elf32-powerpc -B PowerPC -S zero.bin zero.elf
For checking your new elf-file use readelf.
powerpc-readelf -h -t zero.elf
In the end just use load command with flash base address, because this elf-file has not any address information. (or you can use --change-addresses 0x0 option with objcopy)
load zero.elf 0x0
I checked this on PowerPC. GDB version is 8.1.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=powerpc-eabi".

Related

How to compare two memory location using CMP command in u-boot

I'm trying to compare two memory locations using the u-boot (CMP) command. I've u-boot-swap.bin which is flashed at the MTD partition (/dev/mtd2). There is the same u-boot-swap.bin file present at MMC. I want to see if the u-boot flashed at the MTD location (/dev/mtd2) & one present at MMC partition is the same or not.
I tried following commands,
Read u-boot-swap.bin from /dev/mtd2 to memory address 0x81000000
=> sf read 0x81000000 0x40000 0xc0000
device 0 offset 0x40000, size 0xc0000
SF: 786432 bytes # 0x40000 Read: OK
Read u-boot-swap.bin from MMC to memory address 0x82000000
=> ext4load mmc 0:2 0x82000000 /boot/u-boot-swap.bin
445512 bytes read in 144 ms (2.9 MiB/s)
Then I tried to compare two memory locations using cmp command, But I'm getting mismatch
=> cmp 0x81000000 0x82000000 445512
word at 0x8105c7dc (0x76203033) != word at 0x8205c7dc (0x76203130)
Total of 94711 word(s) were the same
=> cmp 0x81000000 0x82000000 786432
word at 0x8105c7dc (0x76203033) != word at 0x8205c7dc (0x76203130)
Total of 94711 word(s) were the same
What I'm doing wrong here? How to compare two memory location?
First of all, some u-boot commands assume arguments are hexadecimal values, you should try replacing cmp 0x81000000 0x82000000 445512 by cmp 0x81000000 0x82000000 0x0006cc48 (0x0006cc48= 445512d) or use the $filesize variable which is populated after loading a file.
This being said, if you have the original u-boot-swap.bin available, a convenient way to understand what exactly is going on would be to compare the content of your file with the content of the two memory area you loaded using sf and ext4load. This can be done by computing an MD5 hash on the file and the two memory areas (I created one for the purpose of my answer):
On my PC:
dd if=/dev/random of=u-boot-swap.bin bs=445512 count=1
ls -l u-boot-swap.bin
md5sum -b u-boot-swap.bin
def7d2bd063bc9d383889a4fc148aff6 *u-boot-swap.bin
On the system running u-boot, loading u-boot-swap.bin and verifying the MD5 hash computed on the memory area that received u-boot-swap.bin has the same MD5 hash:
=> loadb
## Ready for binary (kermit) download to 0x80800000 at 115200 bps...
CACHE: Misaligned operation at range [80800000, 8086cc48]
## Total Size = 0x0006cc48 = 445512 Bytes
## Start Addr = 0x80800000
=> hash md5 0x80800000 0x0006cc48
md5 for 80800000 ... 8086cc47 ==> def7d2bd063bc9d383889a4fc148aff6
The two computed MD5 hashes are the same.
If you don't have the original file available, you wil just be able to compute the MD5 hashes on the two memory areas, but you will not be able to know which one (if any) matches the content of your original file. On my system:
# Copying file content previously loaded at `0x80800000` to `0x81000000` and `0x820000001 :
cp.b 80800000 0x81000000 0x0006cc48
cp.b 80800000 0x82000000 0x0006cc48
hash md5 0x81000000 0x0006cc48
md5 for 81000000 ... 8106cc47 ==> def7d2bd063bc9d383889a4fc148aff6
hash md5 0x82000000 0x0006cc48
md5 for 82000000 ... 8206cc47 ==> def7d2bd063bc9d383889a4fc148aff6
If your u-boot does not have the hash command available, you may use crc32 instead - on my PC:
sudo apt install libarchive-zip-perl
crc32 u-boot-swap.bin
b952fb8d
On my system running u-boot:
crc32 80800000 0x0006cc48
crc32 for 80800000 ... 8086cc47 ==> b952fb8d
crc32 0x81000000 0x0006cc48
crc32 for 81000000 ... 8106cc47 ==> b952fb8d
crc32 0x82000000 0x0006cc48
crc32 for 82000000 ... 8206cc47 ==> b952fb8d
In the case you would not have any of the hash and crc32 commands available, I would strongly suggest to rebuild your u-boot with the hash command and update it on your target system.

memory location for linux kernel for u-boot

Currently, I have a ARM device that uses U-boot to load android OS. I wish to replace android with linux. So what I've done is loaded a copy of linux compiled for ARM devices onto a sd-card, boot into the U-boot bootloader. The problem now is what memory location do I tell U-boot to boot up the vmlinuz linux kernel?
How do I find this out? Or pointing out some resources would be great as well.
Thanks.
The following is the current boot up sequence from connecting to the serial port
Reg Version: v1.1.0
Reg Time: 2014-10-115:15:35
Reg Name: hi3719cdmo1a_hi3719cv100_ddr3_1gbyte_16bitx2_2layers_emmc.reg
Fastboot 3.3.0 (zengzhiliang#server180) (Nov 21 2014 - 13:41:16)
Fastboot: Version 3.3.0
Build Date: Nov 21 2014, 13:41:29
CPU: Hi3719Cv100
Boot Media: eMMC
DDR Size: 1GB
Check nand flash controller v610. found
Special NAND id table Version 1.36
Nand ID: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
No NAND device found!!!
Check spi flash controller v350. found
Can't find a valid spi flash chip.
Can't find a valid spi flash chip.
MMC/SD controller initialization.
MMC/SD Card:
MID: 0xfe
Read Block: 512 Bytes
Write Block: 512 Bytes
Chip Size: 3656M Bytes (High Capacity)
Name: "P1XXX"
Chip Type: MMC
Version: 4.0
Speed: 25000000Hz
Bus Width: 8bit
Boot Addr: 0 Bytes
*** Warning - bad CRC or eMMC, using default environment
Boot Env on eMMC
Env Offset: 0x00100000
Env Size: 0x00010000
Env Range: 0x00010000
SDK Version: HiSTBAndroidV500R001C01CP0002_v2014070614
[Android_Main,34] begin
[sw_set_gpio,85] ok
[sw_ptable_init,66] begin
partition addr : [0x200000]
[swfastboot_flash_read,31]BaseAddress:0x200000, DataSize:0x100000, offset:0x0, b ytes:0xa10
[sw_ptable_check,176]cksum [0x6c94], ptable->checksum[0x6c94]
[sw_ptable_init,79] data at 0x200000 is ok
0 fastboot 0x00000000 0x00200000
1 partition 0x00200000 0x00200000
2 recovery 0x00400000 0x01000000
3 deviceinfo 0x01400000 0x00200000
4 baseparam 0x01600000 0x00800000
5 pqparam 0x01E00000 0x00800000
6 logo 0x02600000 0x00800000
7 fastplay 0x02E00000 0x02800000
8 boot 0x05600000 0x01000000
9 misc 0x06600000 0x00200000
10 system 0x06800000 0x27000000
11 cache 0x2D800000 0x19000000
12 backup 0x46800000 0x19000000
13 swdb 0x5F800000 0x03000000
14 userdata 0x62800000 0x80000000
ptable info:2M(fastboot),2M(partition),16M(recovery),2M(deviceinfo),8M(baseparam ),8M(pqparam),8M(logo),40M(fastplay),16M(boot),2M(misc),624M(system),400M(cache) ,400M(backup),48M(swdb),2048M(userdata)
[sw_ptable_init,104] ok
[sw_devinfo_init,25] begin
deviceinfo addr : [0x01400000]
[swfastboot_flash_read,31]BaseAddress:0x1400000, DataSize:0x100000, offset:0x0, bytes:0x514
[sw_devinfo_check,166] start...
[sw_devinfo_check,184] ok,checksum:0x9aad
[sw_devinfo_init,44] data at 0x1400000 is ok
[0] count:[4] name:[serialno] value:[xxxxxxxxxxxxxxxx]
[1] count:[4] name:[mac] value:[00:03:63:f4:33:12]
[2] count:[4] name:[standard] value:[1080i_50Hz]
[3] count:[4] name:[secureline] value:[20100]
[sw_devinfo_init,71] ok
[swfastboot_flash_read,31]BaseAddress:0x6600000, DataSize:0x100000, offset:0x0, bytes:0x10000
boot normal!!!
[swfastboot_flash_read,31]BaseAddress:0x5602000, DataSize:0x100000, offset:0x0, bytes:0x2000
use boot cmdline,disable serial, cmdline:[mem=1G console=NULL,115200 blkdevparts =mmcblk0:]
bootargs:[mem=1G console=NULL,115200 blkdevparts=mmcblk0:2M(fastboot),2M(partiti on),16M(recovery),2M(deviceinfo),8M(baseparam),8M(pqparam),8M(logo),40M(fastplay ),16M(boot),2M(misc),624M(system),400M(cache),400M(backup),48M(swdb),2048M(userd ata) androidboot.mac=00:03:63:f4:33:12 androidboot.standard=1080i_50Hz androidbo ot.serialno=xxxxxxxxxxxxxxx]
authenticat kernel begin
CA_GetFlashImgInfoByAddr,683: Img has already be encrypted
CA_GetFlashImgInfoByAddr,689: Magic number check right
CA_FlashAuthenticateByAddr,898: CA_FlashAuthenticateByAddr 0x5600000 successe d
offset = 0x5600000 KernelImgInDDRAddress = 0x4002000bootimg now: bootm 4002000
[Android_Main,52] ok
stDispParam.enFormat = 6
sw_EdidAll[0] = 10
sw_EdidAll[1] = 5
sw_EdidAll[2] = 9
sw_EdidAll[3] = 8
sw_EdidAll[4] = 7
sw_EdidAll[5] = 6
sw_EdidAll[6] = 5
sw_EdidAll[7] = 1
sw_EdidAll[8] = 0
sw_EdidAll[9] = 101
use baseparam format [6]
Reserve Memory
Start Addr: 0xFFFF000
Bound Addr: 0x8D3B000
Free Addr: 0xF2FA000
Alloc Block: Addr Size
0xF2FA000 8192
0xF2FD000 2764800
0xF5A1000 3686400
0xF926000 1658880
0xFABC000 3686400
0xFE41000 12288
0xFE45000 1048576
0xFF46000 212992
0xFF7B000 8192
0xFF7E000 524288
Press Ctrl+C to stop autoboot
Found Initrd at 0x04E00000 (Size 535422 Bytes), align at 2048 Bytes
## Booting kernel from Legacy Image at 04002800 ...
Image Name: Linux-3.10.0_s40
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 8925824 Bytes = 8.5 MiB
Load Address: 02000000
Entry Point: 02000000
Loading Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux... done, booting the kernel.
So what I've done is loaded a copy of linux compiled for ARM devices onto a sd-card ...
Unlike x86, there is no one build of a Linux kernel that executes on all "ARM devices".
Older ARM Linux kernels (i.e. pre-Device Tree) were configured and built specifically for each SoC/board variation.
Modern ARM Linux kernels can be built for one or more SoCs, and the kernel is booted with a Device Tree blob to describe the board in use.
You haven't provided any details to indicate if the kernel you have is sufficient to boot your "ARM device".
The problem now is what memory location do I tell U-boot to boot up the vmlinuz linux kernel?
ARM Linux should boot using a zImage file, not a vmlinuz file.
What is the start address of physical RAM on your device?
The convention is that the ARM Linux kernel will execute at the base of physical RAM plus an offset of 0x8000 (32K). See this answer for more details.
The zImage file is self-extracting, and can be loaded (by U-Boot from your SD card) to any suitable memory address above the kernel's load/execute address (while leaving room for the DT blob and not clobber U-Boot).
Or pointing out some resources would be great as well.
Try Russel King's Booting ARM Linux and Vincent Sanders' Booting ARM Linux.

U-Boot: Application crashes - but why

I'm trying to get a stand-alone application for U-Boot running.
Target is a LEGO EV3 brick - it has an TI OMAP (ARM9) CPU.
The output of U-Boot before hanging is:
U-Boot > fatload mmc 0:1 c0007FC0 uimage
reading uimage
384 bytes read
U-Boot > bootm
## Booting kernel from Legacy Image at c0007fc0 ...
Image Name: ITK EV3 sample OS
Image Type: ARM Linux Standalone Program (uncompressed)
Data Size: 320 Bytes = 0.3 kB
Load Address: c0008000
Entry Point: c0008000
Loading Standalone Program ... OK
OK
I tried the following commands to be located at address 0xC0008000 in "uimage":
mov pc, lr (ARM code)
bx lr (ARM code)
bx lr (Thumb code)
These commands should simply return (depending on ARM or Thumb mode being active). However all three commands result in U-Boot hanging so no more output is done after the last "OK".
Why does U-Boot hang?
I found out the answer myself:
In the version of u-boot used on the EV3 brick there is a bug: The starting address that is already converted to little-endian is converted twice so the result is - of course - wrong.
By storing the number little endian in the file the output of u-boot will be wrong:
Image Type: ARM Linux Standalone Program (uncompressed)
Data Size: 320 Bytes = 0.3 kB
Load Address: c0008000
Entry Point: 008000c0 <--- actually 0xC0008000!!!
Loading Standalone Program ... OK
OK
U-Boot >
however booting will work. This bug only affects stand-alone programs and not Linux kernels.
My problem is that the program will possibly be published so it must work with both buggy and bug-fixed u-boot versions.
Therefore I think about loading the program to an address like
0xC00101C0
which is stored little and big endian the same way.

Why does arm-none-eabi-size report the .data section to be 0 even though I am using initialized RAM?

I am a bit confused by the results I am getting when I use my toolchain's (Yagarto and codesourcery) size utility. it is reporting that I am using 0 bytes in the data section. see below
$ arm-none-eabi-size.exe rest-server-example.crazy-horse.elf
text data bss dec hex filename
79364 0 34288 113652 1bbf4 rest-server-example.crazy-horse.elf
I know my code is using and initializing static RAM variables to values other than 0.
interestingly enough when I pass the size tool directly some of the object files that are getting linked I see .data section being reported
example:
text data bss dec hex filename
1648 0 20 1668 684 obj_crazy-horse/uip-nd6.o
200 12 2652 2864 b30 obj_crazy-horse/uip-packetqueue.o
12 0 0 12 c obj_crazy-horse/uip-split.o
1816 24 48 1888 760 obj_crazy-horse/usb-core.o
284 0 0 284 11c obj_crazy-horse/usb-interrupt.o
2064 20 188 2272 8e0 obj_crazy-horse/xmac.o
Why would the elf file report 0 for the .data section when the object files that make it are reporting non-zero values?
FYI I am working on embedded software for a AT91SAM7x256 Micro
edit:
adding the CFLAGS and LDFLAGS
CFLAGS += -O -DRUN_AS_SYSTEM -DROM_RUN -ffunction-sections
LDFLAGS += -L $(CPU_DIRECTORY) -T $(LINKERSCRIPT) -nostartfiles -Wl,-Map,$(TARGET).map
edit #2:
from the object dump we can clearly see that the .data section has data assigned to it but the size utility is not picking it up for some reason
objdump link
All I am looking for is to get an exact usage of my RAM I am not trying to figure out whether one of my variables was optimized out.
edit 3:
more information showing that the size utility does see something in the .data section
$ arm-none-eabi-size.exe -A -t -x rest-server-example.crazy-horse.elf
rest-server-example.crazy-horse.elf :
section size addr
.vectrom 0x34 0x100000
.text 0x10fc8 0x100038
.rodata 0x149c 0x111000
.ARM.extab 0x30 0x11249c
.ARM.exidx 0xe0 0x1124cc
.data 0x1028 0x200000
.bss 0x7bec 0x201028
.stack 0xa08 0x20f5f8
.ARM.attributes 0x32 0x0
.comment 0x11 0x0
.debug_aranges 0xc68 0x0
.debug_info 0x2b87e 0x0
.debug_abbrev 0x960b 0x0
.debug_line 0x9bcb 0x0
.debug_frame 0x4918 0x0
.debug_str 0x831d 0x0
.debug_loc 0x13fad 0x0
.debug_ranges 0x620 0x0
Total 0x7c4c5
My interpretation would be that the linker script creates a single loadable section, which contains the initial values of the data section and a piece of startup code that copies the data to the uninitialized data section.
This is necessary if you want to have a single image file that can be run from read-only memory, as there is no ELF loader in front then that would perform that copy for you.
Normally, this is only done in the section to segment mapping (i.e. the output sections are arranged in the linker script using the > section placement command) rather than by mapping the input section twice, but that is certainly possible as well.
The usage numbers are quite accurate: the text size is the amount of Flash space needed, the BSS size is the amount of RAM needed. Initialized data is counted twice, once for the initial data in Flash, and once for the modifiable data in RAM.
Your .data section have the CODE attribute set, and this confuses "arm-none-eabi-size". The size of the .data section is incorrectly added to the total text size instead of the data size.
My guess is that you have some code that is stored in flash but is copied to ram at run time such as a fast interrupt handler or flash reprogramming that must run from RAM. This will set the CODE attribute for the data segment, and "size" believes that all of .data is text.

How to use cross gdb to examine core file from crosstarget machine

I have a core file from embedded SH3 linux device, and gdb of the cross compiler environment (sh3-linux-gdb) in my host linux.
But I have problems loading the core file with gdb:
$ sh3-linux-gdb ./myprogram ./core
GNU gdb 6.3
Copyright 2004 Free Software Foundation, Inc.
...
This GDB was configured as "--host=i386-pc-linux-gnu --target=sh3-linux"...
GDB can't read core files on this machine.
(gdb)
Why it can't read the core file?
Is there any way to read the core file from target system to the cross gdb?
There is gdbserver in target machine (SH3-linux), but not gdb itself.
I am able to do runtime debuging of processes of target machine with gdbserver and sh3-linux-gdb, so sh3-linux-gdb should be correctly compiled.
EDIT:
readelf dump was requested:
[build]$ sh3-linux-readelf -a core
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: CORE (Core file)
Machine: Renesas / SuperH SH
Version: 0x1
Entry point address: 0x0
Start of program headers: 52 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 51
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 in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
NOTE 0x000694 0x00000000 0x00000000 0x00200 0x00000 0
LOAD 0x001000 0x00400000 0x00000000 0x00000 0x01000 R E 0x1000
----- several boring lines removed -----
LOAD 0x05a000 0x29952000 0x00000000 0x01000 0x01000 RW 0x1000
LOAD 0x05b000 0x7be48000 0x00000000 0x15000 0x15000 RWE 0x1000
There is no dynamic section in this file.
There are no relocations in this file.
There are no unwind sections in this file.
No version information found in this file.
Notes at offset 0x00000694 with length 0x00000200:
Owner Data size Description
CORE 0x000000a8 NT_PRSTATUS (prstatus structure)
CORE 0x0000007c NT_PRPSINFO (prpsinfo structure)
CORE 0x000000a0 NT_AUXV (auxiliary vector)
[build]$
EDIT2: Same problem with --core option:
$ sh3-linux-gdb ./myprogram --core=./core
GNU gdb 6.3
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "--host=i386-pc-linux-gnu --target=sh3-linux"...RUN GDB INIT
GDB can't read core files on this machine.
(gdb)
Try according to http://forums.freescale.com/t5/68K-ColdFire-reg-Microprocessors/GDB-can-t-read-core-files/td-p/70181
sh3-linux-gdb ./myprogram --core=./core
It may be a bug in the old gdb http://sourceware.org/bugzilla/show_bug.cgi?id=9542 - so try newer gdb (7) too.
Also possible that core was dumped in unsupported format. What is target's OS, version?
Can you post the output or readelf -a core ?
It is possible to debug your application, not with gdb directly but with gdb server. The first thing you have to do is to call gdbserver in the target system (you said in your question that this package is already installed) :
gdbserver AAA.BBB.CCC.DDD:port ./myprogram
It is assume that the target machine is accessible to an IP address : AAA.BBB.CCC.DDD:port. Once, you have done that, you can call gdb in your development machine by specifying the target remote server :
% gdb ./myprogram
% [...]
(gdb) target remote AAA.BBB.CCC.DDD:port
Note that the target remote server IP address are the same of the gdbserver.

Resources