We know that bootloader is the code that is initially loaded and run after the system is power on. It provides the initialization code that needs to be executed at the beginning of the processor's power-on reset.
The boot program on the PC is typically started by the BIOS and then reads the bootloader (such as Lilo or GRUB) in the hard disk that is located in the MBR (main boot record, master boot recording) and further directs the boot of the operating system.
In embedded systems, however, there is usually no firmware program like BIOS, so the entire system is loaded and started completely by bootloader. Its main function is to load and boot the kernel image
An embedded storage device typically consists of four partitions:
First Partition: The storage of course is U-boot
Second partition: Storage of u-boot parameters to be passed to the system kernel
Third Partition: System kernel (kernel)
Fourth partition: The root file system
As shown in the following illustration:
--------------------------------------------------------------------------------------------------------------- ----------------------------
--------------------------------------------------------------------------------------------------------------- ----------------------------
U-boot is a kind of bootloader commonly used in embedded systems.
bootloader Introduction
Bootloader is a concept that is bound to come into contact with embedded development, which is an important part of embedded Linux system development in embedded college < embedded engineer Vocational training course > two. This article mainly explains the basic concept of bootloader and the internal principles, this part of the mastery of the embedded Linux system development will be very helpful to learn.
Bootloader definition: bootloader is a small program executed before the operating system runs, through this small program, we can initialize the hardware device, set up a mapping table of memory space, so as to establish the appropriate system hardware and software environment for the final call to the operating system kernel ready. This means that if we want an operating system to work on our board, we must first make some basic configuration and initialization of our board before the operating system can be booted in. What is done in bootloader we will analyze later, here we first recall the architecture of the PC: the boot loader in the PC is made up of BIOS and OS boot Loader (such as Lilo and Grub) in the hard disk MBR, After completing hardware detection and resource allocation, the BIOS reads Boot Loader from the hard disk MBR into the system's RAM and then gives control to OS boot Loader. The main running task of boot loader is to read the kernel image from the hard disk into RAM and then jump to the kernel entry point to run, starting the operating system. In embedded systems, there is usually no firmware program like the BIOS (note: Some embedded CPUs also embed a short startup program), so the entire system's load start-up task is entirely done by the boot loader. For example, in an embedded system based on ARM7TDMI core, the system usually executes from address 0x00000000 when power-up or reset, and the system's boot loader program is usually arranged at this address. (Think about why general-purpose PCs and embedded systems are so different here.) )
Bootloader is implemented on a specific hardware platform, so it is almost impossible to build a common bootloader for all embedded systems, and different processor architectures have different bootloader,bootloader that depend not only on the architecture of the CPU, Also relies on the configuration of the embedded system board-level devices. For 2 different boards, even if they are using the same processor, the bootloader program running on a board can also run on another board, and it is generally necessary to modify the bootloader source program.
How to start the bootloader
Bootloader startup mode mainly includes network boot mode, disk boot mode and Flash startup mode.
1. Network startup mode
Figure 1 bootloader network boot mode diagram
As shown in Figure 1, the inside of the host and the target board, they are connected through the network, the first target board Dhcp/bios through the BOOTP service to assign IP address for bootloader, configure network parameters, so as to support network transmission function. The u-boot that we use can set the network parameters directly, so there is no way to dynamically assign IP using DHCP. The bootloader of the target board then downloads the kernel image to the target board via the TFTP service, then establishes the file communication between the host and the target board through the network file system, and the subsequent system update is usually the mode of operation using the boot loader. The boot loader, which works in this mode, usually provides a simple command-line interface to its end users.
2, disk boot mode
This approach is mainly used on desktops and servers, these computers are booting with the BIOS, and using disk as storage media, two important to start Linux with Lilo and Grub, here is no longer specific.
3, Flash start mode
This is the most common way we use it. Flash has nor flash and NAND flash two kinds. NOR Flash can support random access, so the code can be directly executed on flash, bootloader is generally stored on the flash chip. In addition, the flash also stores parameters, kernel images and file systems. The difference between this startup mode and the network boot mode is that in the network boot mode, the kernel image and the file system are first placed on the host and then downloaded into the target board via network transmission, and the kernel image and file system are directly in Flash in the boot mode. These two points are used in the course of our u-boot.
definition of U-boot
U-boot, full name Universal Boot Loader, is an open source project developed by the Denx group that follows the GPL terms, its main function is to complete hardware device initialization, operating system code handling, and provide a console and a command set to manipulate the hardware devices before the operating system runs. The reason why U-boot is so versatile is that he has many features: open source, support for multiple embedded operating system cores, support for multiple processor families, high stability, highly flexible function settings, rich device-driven source code, and richer development and debugging documentation and strong network technical support. In addition, U-boot provides flexible and rich support for operating system and product development, mainly in: can guide the compression or non-compression system core, can flexibly set/pass several key parameters to the operating system, suitable for the system in different stages of development debugging requirements and product release, support a variety of file systems, Support a variety of target board environment parameter storage media, using CRC32 Check, can verify the kernel and image file is intact, provide a variety of console interface, so that users can not need ice in the case of the serial/Ethernet/ USB and other interfaces to download data and burn to the storage device (this function is very practical in the actual product, especially in the Software field upgrade time), as well as provide a wealth of device drivers.
u-boot directory structure of source code
1, board in the Development Board-related configuration files, each Development board in the form of sub-folders appear.
2, Commom folder implementation U-boot Line support commands, each command corresponding to a file.
3, the CPU contains a specific CPU architecture-related directories, each CPU architecture corresponds to a subdirectory.
4, Doc is the document directory, has u-boot very perfect document.
5. Drivers is the driver of various devices supported by U-boot.
6, FS is a supported file system, the most commonly used is the JFFS2 file system.
7. The Include folder is a header file used by U-boot, as well as a variety of hardware platforms supporting the assembly files, system configuration files and file system support files.
8, NET is the network protocol related Code, BOOTP protocol, TFTP Protocol, NFS file system to be implemented.
9, Tooles is the tool to generate U-boot.
After some understanding of the U-boot directory, the process of analyzing the startup code is much more convenient, and the more important directory is/board,/CPU,/drivers and/include directories, if you want to implement U-boot on a platform, These catalogs need to be analyzed in depth.
--------------------------------------------------------------------------------------------------------------- ----------------------------
--------------------------------------------------------------------------------------------------------------- ----------------------------
What is the "compile address". What is the "run address".
(a) compile address : 32-bit processor, each of its instructions is 4 bytes, in 4 bytes in the order of storage, executed sequentially, the CPU is executed sequentially, as long as there is no jump, it will be executed sequentially line , The compiler assigns a compile address to each instruction, which is the address assigned by the compiler to be allocated during compilation, which we call the compiled address.
(b) The operating address : refers to the program instructions really run the address, is specified by the user, the user will run the address burned to where , where is the address of the run .
For example, there is an instruction to compile the address is 0x5, the actual operation of the address is 0x200, if the user will burn instructions to 0x200, then this command is the operating address is 0x200,
What happens when the compile address and the run address are different. The result is not jump , compile will generate a jump address, if the actual address and the resulting address is not equal, then can not jump.
C language Compiler address: all want to put the compilation address and the actual running address together , but the assembly code because do not need to do C to the Assembly of the conversion, can be considered to write the address, so directly write is his running address This is why any bootloader is just beginning to have a piece of assembler code , because the starting code compiles the address and the actual address is unequal, this code is irrelevant to the Assembly, jumping to the running address of the switch.
how to calculate the compile address and run address.
1. If there are two compile address a=0x10,b=0x7,b the running address is 0x300, then A's run address is the run address of B plus the difference between the two compiled address, a-b=0x10-0x7=0x3,
The operating address of a is 0x300+0x3=0x303.
2. Assuming that the compilation address of the two instructions on the uboot is a=0x33000007 and b=0x33000001, the two instructions fall on the bank6, now to calculate their corresponding run address, to find out the starting address of the running address, this is the user burned in, Assuming that the first address of the run address is 0x0, then A's run address is 0x7,b to 0x1, which is how it is calculated.
Why to assign a compile address. What is the benefit of doing this, and what is the effect.
For example, in function A to define the function B, when the execution to function B to the instruction jump, to jump to the start address of the B function to go up, compile, the compiler to each instruction is assigned a compile address, if the compiler has assigned the address can be directly jump to find the B function jump instruction corresponding table, Make a direct jump, because there is a compile address and a table corresponding to the instruction, if there is no allocation, the compiler can not find this jump address, to calculate, very troublesome.
What is "relative address".
Take nor flash as an example, nor Falsh is mapped to bank0 above, SDRAM is mapped to bank6 above, uboot and the kernel is ultimately run on the SDRAM, at first we started from NOR Flash 0 address to burn back, Uboot at least one part of the code compile address and run address is not the same, compile uboot or kernel, will be compiled address into SDRAM, they eventually will be executed in SDRAM, just start uboot in nor Flash run, run address is a low-end address, is an address in the Bank0, but the compiled address is the address in the BANK6, which results in the failure of the absolute jump instruction execution,so it leads to the concept of relative address.。
So what is the relative address?
At least in the Bank0 uboot this code to know can not use B + to compile the address such a way to jump instructions, because this code compiled address and run address is not the same, then how to do it.
To calculate the real address of this command to run, and then make a jump, it should be a B + run address, can not appear B + compiled address, but the B + run address, and the running address is calculated.
_text_base:
. Word text_base//0x33f80000, in Board/config.mk
This phrase indicates that the user tells the compiler to compile the address of the start address
--------------------------------------------------------------------------------------------------------------- ----------------------------
--------------------------------------------------------------------------------------------------------------- ----------------------------
U-boot Work Process
Most boot Loader contain two different modes of operation: the boot load mode and the download mode, which makes sense only for the developer.
But from the end user's point of view, the role of Boot Loader is: To load the operating system, and there is no so-called boot loading mode and download mode of the difference.
(a) Boot load (boot loading) mode: This mode is also known as the "Autonomous" (autonomous) mode.
That is, Boot Loader loads the operating system into RAM from a solid-state storage device on the target, and the process does not involve the user.
This mode is the normal mode of boot Loader, so the boot Loader obviously must work in this mode when the embedded product is released.
(ii) Download (downloading) mode: In this mode, the Boot Loader on the target will download files from the host computer via a serial connection or network connection, such as downloading the kernel image and the root file system image. Files downloaded from the host are usually first saved to the target's RAM by Boot Loader, and then bootloader written to the Flash class solid state storage device on the target machine. This mode of boot Loader is typically used when installing the kernel and root file system for the first time, and later system updates will use the boot Loader mode of operation. The Boot Loader, which works in this mode, usually provides a simple command-line interface to its end users. This mode of operation is typically used when installing the kernel with the filesystem for the first time. Or use it when the system is updated. When debugging an embedded system, it is common for bootloader to work in this mode.
UBoot this powerful Boot Loader supports both modes of operation and allows users to switch between the two modes of operation.
Most bootloader are divided into phases 1 (stage1) and Phase 2 (Stage2), and Uboot is no exception. Code that relies on CPU architecture (such as CPU initialization code, etc.) is usually placed in phase 1 and is usually implemented in assembly language, while phase 2 is usually implemented in C, which allows for complex functionality and better readability and portability.
--------------------------------------------------------------------------------------------------------------- ----------------------------
first, approximate summary of the analysis
The entry point of the system startup. Now that we're going to analyze U-boot's start-up process, we must first find out what code U-boot first implemented and which tasks to complete first.
On the other hand an executable image must have an entry point, and there can be only one Global entry point , so tell the compiler where the entry is. Thus we can find the entry point of the program is specified in /board/lpc2210/u-boot.lds , where the entry (_start) Description program runs from _start, and he points to cpu/arm7tdmi/ START.O file.
Because we are using the ARM7TDMI CPU architecture, after the reset from address 0x00000000 fetch its first instruction, so we map flash to this address,
This allows the CPU to execute the U-BOOT program first when the system is power-up. U-boot's start-up process is multi-phased, with two stages.
code that relies on the CPU architecture (such as device initialization code, etc.) is usually placed in stage1, and is usually implemented in assembly language to achieve a short and concise purpose.
Stage2 is usually implemented in C, which enables complex functions, and the code is more readable and portable.
Let's look at the code in the next stage1 in detail, as shown in Figure 2:
Figure 2 Start.s Program flow
The code really starts at _start, sets the exception vector table , and jumps to /cpu/arm7tdmi/interrupts when the CPU goes down. execute The corresponding interrupt code .
in the interrupts file, most of the exception code does not implement the specific function, just print some exception message , the key is the reset interrupt code, jump to the Reset entry address .
Reset reset The entry with a few paragraphs before the declaration .
1. In reset, the first is to set the CPU to SVC32 mode and block all IRQ and Fiq.
2. In U-boot in addition to the timer used interrupt , the other basically do not need to use interrupts , such as serial communication and network communications, such as communication, in the u-boot as long as the completion of some simple communication can be, So all the interrupt responses are blocked out here.
3. Initialize the external bus. This section first sets the I/O port function, including the serial port, the network interface and so on the settings, other I/O ports are set to Gpio. Then set the BCFG0~BCFG3, which is the external bus controller. Here bank0 corresponds to Flash, set to 16-bit width, the bus speed is set to the slowest, in order to achieve stable operation; Bank1 corresponds to DRAM, the settings are the same as flash; Bank2 corresponds to RTL8019.
4. Next is the CPU-critical setting, including system remapping (tells the processor to read the interrupt vector table in the external memory when the system is interrupted) and the system frequency.
5.lowlevel_init, set the timing of the RAM and reset the interrupt controller to zero. These parts are related to a particular platform, but the general process is the same.
here is the move phase of the code. To get faster execution speed ,
The stage2 is typically loaded into RAM space to execute, so you must prepare a usable amount of RAM space for the stage2 that loads boot loader. The size of the space is preferably a multiple of the memory page size (usually 4KB)
Generally,1M of RAM space is sufficient.
In the u-boot executable file stored in Flash, the code snippets, data segments, and BSS segments are stored end-to-end,
So when calculating the size of the move is the use of the first address of the BSS section minus the first address of the code, so that the actual use of space.
The program uses a loop to move the code to 0x81180000, which is the 1M space at the bottom of RAM to store the code.
The program then continues to move the interrupt vector table to the top of the ram. Since Stage2 is usually a C-language code execution, there is also a stack to be built.
Before the stack area, the space allocated by malloc and the space required for global data are empty, and their size is given by the macro definition and can be modified at the appropriate location.
Basic Memory Distribution map:
Figure 3 Map of the memory distribution after removal
Down is the second phase of U-boot startup, written in C code,
This is part of some relatively minor changes, we change some of the initialization functions it invokes for different boards, and change the initialization process by setting some macro definitions.
So the code does not need to be modified during the porting process, and it is a relatively small number of errors.
At the beginning of the file, a function pointer array is defined, through which the program uses a loop to initialize the regular initialization in order, and then initializes some specific devices with some macro definitions.
In the last program enters a loop,main_loop. This loop receives the commands entered by the user to set parameters or initiate boot .
This article will focus on the analysis of the previous START.S, is because this part of the transplant or debugging process is the most prone to problems, to solve the problem requires the programmer to modify the code, so here is a brief introduction to the basic process of START.S, I hope to be helpful to everyone
--------------------------------------------------------------------------------------------------------------- ----------------------------
--------------------------------------------------------------------------------------------------------------- ----------------------------
second, code analysis