U-Boot first phase key code understanding

  

1. u-boot program entry address

To understand the program's entry address, naturally think of the connection file, first look at the connection file "/board /smdk2410/u-boot.lds"

ENTRY(_start)

SECTIONS

{

. = 0x00000000;

. = ALIGN(4);

.text :

{

cpu/arm920t/start.o (.text)

*(.text)

}

. = ALIGN(4);

.rodata : { *(.rodata) }

. = ALIGN(4);< Br>

.data : { *(.data) }

. = ALIGN(4);

.got : { *(.got) }

__u_boot_cmd_start = .;

.u_boot_cmd : { *(.u_boot_cmd) }

__u_boot_cmd_end = .;

. = ALIGN(4);

__bss_start = .;

.bss : { *(.bss) }

_end = .;

}

(1) From ENTRY(_start) Can see the entrance function of u-boot _start

(2) From . = 0x00000000, it may be seen that the address of _start is 0x00000000. This is not the case. 0x00000000 is invalid here, and will be replaced by TETX_BASE when connecting. Refer to the config.mk in the u-boot root directory.

(3) Many statements on the Internet are _start=TEXT_BASE. I think this statement is also correct. In fact, this code is not TEXT_BASE mapped to 0x0. The place, in fact, the compiler to compile, is in accordance with the link file. In other words, all addresses are compiled relative to TEXT_BASE at compile time. And this address is specified in the connection file is 0x338f0000, you can see the link file, you can see the address inside the disassembly, all 0x33f8XXXX address.

1.1 cpu/arm920t/start.S part of the code explanation

(1)

[html] view plaincopy _TEXT_BASE:

.word TEXT_BASE

Here an assembly language tag _TEXT_BASE is defined, the value of which is the link address value of the code " _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > (ie 0x33F80000). The value of TEXT_BASE can be obtained by referring to _TEXT_BASE later.

(2)

[html] view plaincopy .globl _armboot_start

_armboot_start:

.word _start

Defining external references The variable _armboot_start is the value of the link address where the code “.word _start" is located.

Figure 1 u-boot.map

After the compilation is complete, a u-boot.map file is generated, as shown in Figure 1. Figure 1 shows that the address value pointed to by _armboot_start is 0x33f80044. Open u-boot.bin with UltraEdit and locate offset 0x44 (0x44 is obtained by _armboot_start at address 0x33f80044-TEXT_BASE). As shown in Figure 2, this value is the value of the link address pointed to by _start 33 F8 00 00 (Little endian mode).

Figure 2 u-boot.bin

(3)

[html] view plaincopy .globl _bss_start

_bss_start:

.word __bss_start

The value of __bss_start is defined in the board/smdk2410/u-boot.lds file:

[html] view plaincopy . = ALIGN(4);

__bss_start = .;

.bss : { *(.bss) }

_end = .;

__bss_start = .; indicates that the __bss_start value is the value of the current position. What is the current position? From the following sentence .bss : { *(.ss) } Know. Immediately after the position, the bss segment data is placed. Therefore, __bss_start is of course the starting address of the bss segment. _end is the end address of the bss segment.

bss is the last paragraph of this link script. start.S is to calculate the size of the u-boot code to be carried by the starting address of this segment, that is, all the data in front of this segment will be moved to TEXT_BASE, and then jump to start_armboot, which is the entry code of C language. . What is the value of __bss_start? My compiled value is 0x33f979d4. Can be found in the u-boot.map file, as shown in Figure 3, the bss segment is allocated from 0x33f979d4.

Figure 3 u-boot.map

As can be seen from Figure 1, the link address pointed to by _bss_start is 0x33f80048, which stores the starting address of the bss segment. Open u-boot.bin and locate offset 0x48 (0x48 is obtained by _bss_start address 0x33f80048-TEXT_BASE) as shown in Figure 2. This value is indeed 33 F9 79 D4 (small end mode).

2.SDRAM initialization, lowleverl_init.S

_TEXT_BASE:

.word TEXT_BASE

.globl lowlevel_init

lowlevel_init:

/* memory control configuration */

/* make r0 relative the current location so that it */

/* reads SMRDATA out of FLASH rather than memory ! */< Br>

ldr r0, =SMRDATA

ldr r1, _TEXT_BASE

sub r0, r0, r1

ldr r1, =BWSCON /* Bus Width Status Controller * /

add r2, r0, #13*4

I don't understand what value SMRDATA and _TEXT_BASE are after subtracting. Why do we need to subtract it?

Our program is stored in Flash. The address here is called the load address. Of course, it starts from address 0x0, and the labels used in the program are compiled based on _TEXT_BASE address, which we call a link or run address. At this time, the load address and the run address are not the same, so our code is required to use these labels before moving to the TEXT_BASE (0x33f80000) position. If the label is called directly, the program flies and the label can only be called if it is running in SDRAM because 0x33f80000 is in SDRAM. Therefore, only one offset address relative to 0x0 can be found to get the real SMRDATA definition data, which means that this part of the code is independent of the address and is based on the PC offset. Let's analyze the code:

ldr r0, =SMRDATA takes the absolute address of the label SMRDATA, which is greater than _TEXT_BASE; ldr r1, _TEXT_BASE takes the base address (0x33f80000). Sub r0, r0, r1 are subtracted to get SMRDATA offset relative to _TEXT_BASE.

3.UBOOT startup code relocation

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

relocate: /* relocate U-Boot to RAM */

adr r0, _start /* r0 <- current position of code */

ldr r1, _TEXT_BASE /* test if we run from flash or RAM */

Always confused r0, when r1 is equal, When is it not to wait, look at the difference between adr and ldr pseudo-directors

adr is a small range of address read directives, instructions will be read into the register based on the PC relative offset address value; ldr is large The range read address directive is used to load 32 into an immediate or an address into the specified register.

The link address of _start is determined at the time of the link and the offset address between the instructions. Regardless of the position, the offset address is a negative value because _start is always the start address of the code segment. Assume that the offset between the link address of the instruction indicated by the PC and _start is x, which is negative, so when adr r0, _start is executed, it is equivalent to ldr r0, = PC + x (x < 0), this The value in r0 is the starting address of the code segment. Because the address in the PC is the loading address of the current code, and the link address of the instruction it refers to is added based on the offset of _start (the link start address of the code), it is the starting address stored in the code, that is, loading. starting address.

Copyright © Windows knowledge All Rights Reserved