官术网_书友最值得收藏!

The U-Boot bootloader

There are many open source bootloaders available today. Almost all of them have features to load and execute a program, which usually involves the operating system, and its features are used for serial interface communication. However, not all of them have the possibility to communicate over Ethernet or update themselves. Another important factor is represented by the widespread use of the bootloader. It is very common for organizations and companies to choose only one bootloader for the persity of boards, processors, and architectures that they support. A similar thing happened with the Yocto Project when a bootloader was chosen to represent the official supported bootloader. They, and other similar companies, chose U-Boot bootloader, which is quite well known in the Linux community.

The U-Boot bootloader, or Das U-Boot as its official name, is developed and maintained by Wolfgang Denx with the support of the community behind it. It is licensed under GPLv2, its source code is freely available inside a git repository, as shown in the first chapter, and it has a two month intervals between releases. The release version name is shown as U-boot vYYYY.MM. The information about U-Boot loader is available at http://www.denx.de/wiki/U-Boot/ReleaseCycle.

The U-Boot source code has a very well defined directory structure. This can be easily seen with this console command:

tree -d -L 1
.
├── api
├── arch
├── board
├── common
├── configs
├── disk
├── doc
├── drivers
├── dts
├── examples
├── fs
├── include
├── lib
├── Licenses
├── net
├── post
├── scripts
├── test
└── tools
19 directories

The arch directory contains architecture-specific files and directories-specific to each architecture, CPU or development board. An api contains external applications that are independent of a machine or architecture type. A board contains inside boards with specific names of directories for all board-specific files. A common is a place where misc functions are located. A disk contains disk drive handling functions, and documentation is available inside the doc directory. Drivers are available in the drivers directory. The filesystem-specific functionality is available inside the fs directory. There are still some directories that would need mentioning here, such as the include directory, which contains the header files; the lib directory contains generic libraries with support for various utilities, such as the flatten device tree, various decompressions, a post (Power On Self-Test) and others, but I will let them be discovered by the reader's curiosity, one small hint would be to inspect the README file in the Directory Hierachy section.

Moving through the U-Boot sources, which were downloaded in the previous chapter inside the ./include/configs file, configuration files can be found for each supported board. These configuration file is an .h file that contains a number of CONFIG_ files and defines information on memory mapping, peripherals and their setup, command line output, such as the boot default addresses used for booting a Linux system, and so on. More information on the configuration files could be found inside the README file in the Configuration Options, section or in a board specific configuration file. For Atmel SAMA5D3-Xplained, the configuration file is include/configs/sama5d3_xplained.h. Also, there are two configurations available for this board in the configs directory, which are as follows:

  • configs/sama5d3_xplained_mmc_defconfig
  • configs/sama5d3_xplained_nandflash_defconfig

These configurations are used to define the board Secondary Program Loader (SPL) initialization method. SPL represents a small binary built from the U-Boot source code that is placed on the SRAM memory and is used to load the U-Boot into the RAM memory. Usually, it has less than 4 KB of memory, and this is how the booting sequence looks:

Before actually starting the build for the U-Boot source code for a specific board, the board configuration must be specified. For the Atmel SAMA5_Xplained development board, as presented in the preceding image, there are two available configurations that could be done. The configuration is done with the make ARCH=arm CROSS_COMPILE=${CC} sama5d3_xplained_nandflash_defconfig command. Behind this command, the include/config.h file is created. This header include definitions that are specific for the chosen board, architecture, CPU, and also board-specific header includes. The defined CONFIG_* variable read from the include/config.h file includes determining the compilation process. After the configuration is completed, the build can be started for the U-Boot.

Another example that can be very useful when inspected relates to the other scenario of booting an embedded system, one that requires the use of a NOR memory. In this situation, we can take a look at a particular example. This is also well described inside the Embedded Linux Primer by Christopher Hallinan, where a processor of the AMCC PowerPC 405GP is discussed. The hardcoded address for this processor is 0xFFFFFFFC and is visible using .resetvec , the reset vector placement. There also specifies the fact that the rest of this section is completed with only the value 1 until the end of the 0xFFFFFFFF stack; this implies that an empty flash memory array is completed only with values of 1. The information about this section is available in resetvec.S file, which is located at arch/powerpc/cpu/ppc4xx/resetvec.S. The contents of resetvec.S file is as follows:

 /* Copyright MontaVista Software Incorporated, 2000 */
#include <config.h>
  .section .resetvec,"ax"
#if defined(CONFIG_440)
  b _start_440
#else
#if defined(CONFIG_BOOT_PCI) && defined(CONFIG_MIP405)
  b _start_pci
#else
  b _start
#endif
#endif

On inspection of this file's source code, it can be seen that only an instruction is defined in this section independently of the available configuration options.

The configuration for the U-Boot is done through two types of configuration variables. The first one is CONFIG_*, and it makes references to configuration options that can be configured by a user to enable various operational features. The other option is called CFG_* and this is used for configuration settings and to make references to hardware-specific details. The CFG_* variable usually requires good knowledge of a hardware platform, peripherals and processors in general. The configure file for the SAMA5D3 Xplained hardware platform is available inside the include/config.h header file, as follows:

/* Automatically generated - do not edit */
#define CONFIG_SAMA5D3  1
#define CONFIG_SYS_USE_NANDFLASH        1
#define CONFIG_SYS_ARCH  "arm"
#define CONFIG_SYS_CPU   "armv7"
#define CONFIG_SYS_BOARD "sama5d3_xplained"
#define CONFIG_SYS_VENDOR "atmel"
#define CONFIG_SYS_SOC    "at91"
#define CONFIG_BOARDDIR board/atmel/sama5d3_xplained
#include <config_cmd_defaults.h>
#include <config_defaults.h>
#include <configs/sama5d3_xplained.h>
#include <asm/config.h>
#include <config_fallbacks.h>
#include <config_uncmd_spl.h>

The configuration variables available here represent the corresponding configurations for the SAMA5D3 Xplained board. A part of these configurations refer to a number of standard commands available for user interactions with the bootloader. These commands can be added or removed for the purpose of extending or subtracting commands from the available command line interface.

More information on the U-Boot configurable command interface can be found at http://www.denx.de/wiki/view/DULG/UBootCommandLineInterface.

Booting the U-Boot options

In an industrial environment, interaction with the U-Boot is mainly done through the Ethernet interface. Not only does an Ethernet interface enable the faster transfer of operating system images, but it is also less prone to errors than a serial connection.

One of the most important features available inside a bootloader is related to the support for Dynamic Host Control Protocol (DHCP), Trivial File Transfer Protocol (TFTP), and even Bootstrap Protocol (BOOTP). BOOTP and DHPC enable an Ethernet connection to configure itself and acquire an IP address from a specialized server. TFTP enables the download of files through a TFTP server. The messages passed between a target device and the DHCP/BOOTP servers are represented in the following image in a more generic manner. Initially, the hardware platform sends a broadcast message that arrives at all the DHCP/BOOTP servers available. Each server sends back its offer, which also contains an IP address, and the client accepts the one that suits its purposes the best and declines the other ones.

After the target device has finished communication with DHCP/BOOTP, it remains with a configuration that is specific to the target and contains information, such as the hostname, target IP and hardware Ethernet address (MAC address), netmask, tftp server IP address and even a TFTP filename. This information is bound to the Ethernet port and is used later in the booting process.

To boot images, U-Boot offers a number of capabilities that refer to the support of storage subsystems. These options include the RAM boot, MMC boot, NAND boot, NFS boot and so on. The support for these options is not always easy and could imply both hardware and software complexity.

Porting U-Boot

I've mentioned previously that U-Boot is one of the most used and known bootloaders available. This is also due to the fact that its architecture enables the porting of new development platforms and processors in a very easy manner. At the same time, there are a huge number of development platforms available that could be used as references. The first thing that any developer who is interested in porting a new platform should do is to inspect the board and arch directories to establish their baselines, and, at the same time, also identify their similarities with other CPUs and available boards.

The board.cfg file is the starting point to register a new platform. Here, the following information should be added as a table line:

  • Status
  • Architecture
  • CPU
  • SOC
  • Vendor
  • Board name
  • Target
  • Options
  • Maintainers

To port a machine similar to SAMA5D3 Xplained, one of the directories that could be consulted is the arch directory. It contains files, such as board.c, with information related to the initialization process for boards and SOCs. The most notable processes are board_init_r(), which does the setup and probing for board and peripherals after its relocation in the RAM, board_init_f(), which identifies the stack size and reserved address before its relocation in the RAM, and init_sequence[], which is called inside the board_init_f for the setup of peripherals. Other important files inside the same locations are the bootm.c and interrupts.c files. The former has the main responsibility of the boot from memory of the operating system, and the latter is responsible for implementation of generic interrupts.

The board directory also has some interesting files and functions that need to be mentioned here, such as the board/atmel/sama5d3_xplained/sama5d3_xplained.c file. It contains functions, such as board_init(), dram_init(), board_eth_init(), board_mmc_init, spl_board_ init(), and mem_init() that are used for initialization, and some of them called by the arch/arm/lib/board.c file.

Here are some other relevant directories:

  • common: This holds information about user commands, middleware, APIs that perform the interfacing between the middleware and user commands, and other functions and functionalities used by all available boards.
  • drivers: This contains drivers for various device drivers and middleware APIs, such as drivers/mmc/mmc.c, drivers/pci/pci.c, drivers/watchdog/at91sam9_wdt.c and so on.
  • fs: Various supported filesystems, such as USB, SD Card, Ext2 FAT, and so on are available here.
  • include: This represents the location where all the headers necessary for most of the boards are present. SOCs and other software is also available. Inside include/configs, board-specific configurations are available, and include the headers imported from Linux; these could be used for various device drivers, porting, or other byte operations.
  • tools: This is the place where tools, such as checkpatch.pl, a patch examination tool used as a coding style check, are used before sending it to the mailing list or the mkimage.c tool. This is also used for the U-Boot generic header generation that makes Linux binaries, and assures that they are able to be booted using U-Boot.

More information about the SAMA5D3 Xplained board can be found by inspecting the corresponding doc directory and README files, such as README.at91, README.at91-soc, README.atmel_mci, README.atmel_pmecc, README.ARM-memory-map, and so on.

For people interested in committing to the changes they made while porting a new development board, CPU, or SOC to U-Boot, a few rules should be followed. All of these are related to the git interaction and help you to ensure the proper maintenance of your branches.

The first thing that a developer should do is to track the upstream branch that corresponds to a local branch. Another piece of advice would be to forget about git merge and instead use git rebase. Keeping in contact with the upstream repository can be done using the git fetch command. To work with patches, some general rules need to be followed, and patches need to have only one logical change, which can be any one of these:

  • Changes should not contain unrelated or different modifications; only one patch is available and acceptable per changeset
  • Commits should make the use of git-bisect where possible while detecting bugs in sources, when necessary
  • If multiple files are impacted by a set of modifications, all of them should be submitted in the same patch
  • Patches need to have review, and a very thorough one at that

Let's take a look at following diagram, which illustrates the git rebase operation:

As shown in both the preceding and following diagram, the git rebase operation has recreated the work from one branch onto another. Every commit from one branch is made available on the succeeding one, just after the last commit from it.

The git merge operation, on the other hand, is a new commit that has two parents: the branch from which it was ported, and the new branch on which it was merged. In fact, it gathers a series of commits into one branch with a different commit ID, which is why they are difficult to manage.

More information related to git interactions can be found at http://git-scm.com/documentation or http://www.denx.de/wiki/U-Boot/Patches.

Almost always when porting a new feature in U-Boot, debugging is involved. For a U-Boot debugger, there are two different situations that can occur:

  • The first situation is when lowlevel_init was not executed
  • The second situation is when the lowlevel_init was executed; this is the most well known scenario

In the next few lines, the second situation will be considered: the baseline enabling a debugging session for U-Boot. To make sure that debugging is possible, the elf file needs to be executed. Also, it cannot be manipulated directly because the linking address will be relocated. For this, a few tricks should be used:

  • The first step is to make sure that the environment is clean and that old objects are not available any more: make clean
  • The next step would be to make sure the dependencies are cleaned: find ./ | grep depend | xargs rm
  • After the cleaning is finished, the target build can start and the output can be redirected inside a log file: make sama5d3_xplained 2>&1 > make.log
  • The generated output should be renamed to avoid debugging problems for multiple boards: mv u-boot.bin u-boot_sama5d3_xplained.bin
  • It is important to enable DEBUG in the board configuration file; inside include/configs/ sama5d3_xplained.h, add the #define DEBUG line

An early development platform can be set up after relocation takes place and the proper breakpoint should be set after the relocation has ended. A symbol needs to be reloaded for U-Boot because the relocation will move the linking address. For all of these tasks, a gdb script is indicated as gdb gdb-script.sh:

#!/bin/sh
${CROSS_COMPILE}-gdb u-boot –command=gdb-command-script.txt

vim gdb-command-script.txt
target remote ${ip}:${port}
load
set symbol-reloading
# break the process before calling board_init_r() function
b start.S:79
c
…
# the symbol-file need to be align to the address available after relocation
add-symbol-file u-boot ${addr}
# break the process at board_init_r() function for single stepping b board.c:494
Note

More information on relocation can be found at doc/README.arm-relocation.

主站蜘蛛池模板: 城口县| 北票市| 潼南县| 黔东| 名山县| 铁岭市| 文昌市| 福州市| 梁山县| 富裕县| 通河县| 加查县| 江源县| 新干县| 安多县| 贵德县| 洛南县| 连云港市| 栖霞市| 五莲县| 宜章县| 饶平县| 新泰市| 芜湖县| 永年县| 离岛区| 类乌齐县| 淳化县| 通化市| 唐山市| 多伦县| 孝昌县| 怀安县| 镇康县| 昌江| 亚东县| 襄垣县| 宕昌县| 岳西县| 依安县| 罗平县|