Global variable relocation and kernelrelocate Functions

Source: Internet
Author: User

 

1. Why do we need to relocate global variables?

First, we need to study why we need to re-locate the global variables of bootloader. It is inevitable to define some global variables in the source code of bootloader. These global variables are placed in the Data Segment Storage Area of the compiled executable binary file. The bootloader image file is either run in the xip mode in the ROM or copied to one disk. the area defined as ramimage In the bib project file is used as a rom even though it is located in the system RAM memory. Therefore, no matter how the bootloader image runs, the storage region of the bootloader image is read-only. Therefore, it is necessary to read the data segment in the image to the program memory to ensure that the global variables in the image can be written, this is why global variables of bootloader are relocated.

In addition, we will later understand that global variables in Windows CE also need to be relocated. The functions that implement global variable relocation include kernelrelocate, this function is located at % _ winceroot %/private/winceos/coreos/nk/LDR/ldrcen. c source file.

2 understand ptoc pointers

 

Before continuing to introduce global variable relocation, it is necessary to introduce the ptoc pointer. First, let's look at the definition of this pointer, as shown below.

Code 1. Excerpt from % _ winceroot %/private/winceos/coreos/nk/LDR/ldrcen. c

Romhdr * const volatile ptoc = (romhr *)-1; // gets replaced by romloader with real address

During definition, ptoc is defined as a global constant. You can think about why it cannot be defined as a global variable. In addition, ptoc points to an invalid address because the value assigned to it is-1. This makes the role a little mysterious. In fact, the romimagelevel 1 will be changed by romimage.exe [1], which will be mentioned later.

Next we will talk about the type of data stored in the address space pointed by the ptoc pointer to romhdr. So what kind of romhdr is? Below we find the romhr type definition prototype, as shown below.

Code 2. Excerpt from % _ winceroot %/public/common/oak/INC/romldr. h

1 typedef struct romhdr {

2 ulong dllfirst; // first DLL address

3 ulong dlllast; // last DLL address

4 ulong physfirst; // first physical address

5 ulong physlast; // highest physical address

6 ulong nummod; // Number of tocentry's

7 ulong ulramstart; // start of RAM

8 ulong ulramfree; // start of Ram free space

9 ulong ulramend; // end of RAM

10 ulong ulcopyentries; // Number of copy section entries

11 ulong ulcopyoffset; // offset to copy Section

12 ulong ulprofilelen; // length of profentries Ram

13 ulong ulprofileoffset; // offset to profentries

14 ulong numfiles; // number of files

15 ulong ulkernelflags; // optional kernel flags from romflags. bib config Option

16 ulong ulfsrampercent; // percentage of RAM used for filesystem

17 // from fsrampercent. bib config Option

18 // byte 0 = #4 K chunks/Mbyte of RAM for filesystem 0-2 Mbytes 0-255

19 // byte 1 = #4 K chunks/Mbyte of RAM for filesystem 2-4mbytes 0-255

20 // byte 2 = #4 K chunks/Mbyte of RAM for filesystem 4-6mbytes 0-255

21 // byte 3 = #4 K chunks/Mbyte of RAM for filesystem> 6 Mbytes 0-255

22 ulong uldrivglobstart; // Device Driver global starting address

23 ulong uldrivgloblen; // Device Driver global Length

24 ushort uscputype; // CPU (MACHINE) Type

25 ushort usmiscflags; // miscellaneous flags

26 pvoid pextensions; // pointer to Rom header extensions

27 ulong ultrackingstart; // tracking memory starting address

28 ulong ultrackinglen; // tracking memory ending address

29} romhdr;

In the romimagestage, romimage.exe directly fills 84 bytes of data to form romhdr.

In the romimagestage, romimage.exe directly fills 84 bytes of data to form the romhdr data structure, modifies the ptoc pointer address, and points it to the filled romhdr data structure.

For the moment, I will not fully introduce the meaning of each data member in romhdr. I will only mention two members related to the global variable relocation operation. They are ulcopyentries and ulcopyoffset. The meaning is the number of copyentries and the address of 1st copyentries.

3. How to relocate global variables

Global variable relocation is implemented by the kernelrelocate function. Before analyzing the kernelrelocate function, we should first understand copyentry. To put it simply, copyentry is a data structure that represents the copy entry information. We can further understand it from its definition. Its definition and various data member functions are as follows.

Code 3. Excerpt from % _ winceroot %/public/common/oak/INC/romldr. h

1 typedef struct copyentry {

2 ulong ulsource; // copy Source Address

3 ulong uldest; // copy Destination Address

4 ulong ulcopylen; // copy Length

5 ulong uldestlen; // copy destination Length

6 // (zero fill to end if> ulcopylen)

7} copyentry;

 

Table. copyentry struct data member meaning

Member name

Member description

Ulsource

Starting address of the global variable in ROM

Uldest

Destination Address for copying global variables to ram

Ulcopylen

The actual length of the global variable.

Uldestlen

The expected length of the global variable.

 

The actual length and expected length of global variables expressed by ulcopylen and uldestlen are described as follows: uldestlen must be no less than ulcopylen, if uldestlen is greater than ulcopylen, it indicates that the global variable of the region has several bytes of space to be cleared in addition to non-zero data.

After understanding copyentry, it is easy to understand the process of copying global variables by the kernelrelocate function. The following is the source code of the kernelrelocate function.

Code 4. Excerpt from % _ winceroot %/private/winceos/coreos/nk/LDR/ldrcen. c

1 void kernelrelocate (romhdr * const ptoc ){

2 ulong loop;

3 copyentry * cptr;

4 // copy globals

5 For (loop = 0; loop <ptoc-> ulcopyentries; loop ++ ){

6 cptr = (copyentry *) (ptoc-> ulcopyoffset + loop * sizeof (copyentry ));

7 if (cptr-> ulcopylen ){

8 memcpy (lpvoid) cptr-> uldest, (lpvoid) cptr-> ulsource, cptr-> ulcopylen );

9}

10 if (cptr-> ulcopylen! = Cptr-> uldestlen ){

11 memset (lpvoid) (cptr-> uldest + cptr-> ulcopylen), 0, cptr-> uldestlen-cptr-> ulcopylen );

12}

13}

14}

5th ~ 13 sentences use the for statement to form a loop structure. The number of loops equals to the number of copytentry, that is, the value of the ulcopyentries member in the data structure pointed to by the ptoc pointer. Each loop is copied once. The copy entry information is obtained before copying (6th sentences ). Copy is executed in two steps. First, if there is a data copy (7th sentences), the data is copied (8th sentences). Then, if the expected size is larger than the actual size (10th sentences), fill the remaining part with 0 (11th sentences ).

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.