-->

Type something and hit enter

By On
advertise here
 ARM Linux boot process -2

This will be a series of articles explaining how the Linux kernel boots into the ARM architecture. This is part one.

ARM Linux boot process:

We will explain the on-chip AT91RM9200 boot process, built around an ARM Thumb ARM920T processor. Kwickbyte creates a built-in board called kb9202 based on the AT91RM9200. We will take this board as an example and see how Linux boots on this board.

Before you start reading, you need to read the AT91RM9200 specification (specification).

For a better understanding of the boot process, you also need to read the ARM Architecture Reference Guide.

Components of the Linux boot process:

The Linux boot process includes the following components.

Loader
Core image
Root filesystem

Before we see how the above components work, the following is the call flow of the Linux kernel boot process for the arm. This gives a great picture for the entire Linux boot process. We use the U-boot loader.
ARM Linux boot process: large image
U-boot:

_start (cpu / arm920t / start.S)

start_code (cpu / arm920t / start.S)

start_armboot (lib_arm / board.c)

board_init (board / kb9202 / kb9202.c)

timer_init (cpu / arm920t / at91 / timer.c)

serial_init (drivers / serial / at91rm9200_usart.c)

main_loop (lib_arm / board.c)

Now u-boot is up and running on the u-boot command line and ready to accept commands. Suppose the kernel image is loaded into RAM and the bootm command is issued.

do_bootm (common / cmd_bootm.c)

bootm_start (common / cmd_bootm.c)

bootm_load_os (common / cmd_bootm.c)

do_bootm_linux (lib_arm / bootm.c)

stext (linux / arch / arm / kernel / head.S)

Control is provided by linux.

Linux kernel:

stext (arch / arm / kernel / head.S: 78)

__lookup_processor_type (arch / arm / kernel / head-common.S: 160)

__lookup_machine_type (arch / arm / kernel / head-common.S: 211)

__create_page_tables (arch / arm / kernel / head.S: 219)

__arm920_setup (arch / arm / mm / proc-arm920.S: 389)

__enable_mmu (arch / arm / kernel / head.S: 160)

__turn_mmu_on (arch / arm / kernel / head.S: 205)

__switch_data (arch / arm / kernel / head-common.S: 20)

start_kernel (init / main.c: 529)

start_kernel (init / main.c: 529)

tick_init (kernel / time / tick-common.c: 413)

setup_arch (arch / arm / kernel / setup.c: 666)

setup_machine (arch / arm / kernel / setup.c: 369)

lookup_machine_type ()

setup_command_line (init / main.c: 408)

build_all_zonelists (mm / page_alloc.c: 3031)

parse_args (kernel / params.c: 129)

mm_init (init / main.c: 516)

mem_init (arch / hand / mm / init.c: 528)

kmem_cache_init (mm / slab.c, mm / slob.c, mm / slub.c)

sched_init (kernel / sched.c)

init_IRQ (arch / arm / kernel / irq.c)

init_timers (kernel / timer.c: 1713)

hrtimers_init (kernel / hrtimer.c: 1741)

softirq_init (kernel / softirq.c: 674)

console_init (drivers / char / tty_io.c: 3084)

vfs_caches_init (fs / dcache.c: 2352)

mnt_init (fs / namespace.c: 2308)

init_rootfs ()

init_mount_tree (fs / namespace.c: 2285)

do_kern_mount (fs / namespace.c: 1053)

set_fs_pwd (fs / fs_struct.c: 29)

set_fs_root (fs / fs_struct.c: 12)

bdev_cache_init (fs / block_dev.c: 465)

chrdev_init (fs / char_dev.c: 566)

signals_init (kernel / signal.c: 2737)

rest_init (init / main.c: 425)

kernel_thread (431, arch / arm / kernel / process.c: 388)

kernel_thread () creates a kernel thread, and control is passed to kernel_init ().

kernel_init (431, init / main.c: 856)

do_basic_setup (888, init / main.c: 787)

init_workqueues (789, kernel / workqueue.c: 1204)

driver_init (793, drivers / base / init.c: 20)

do_initcalls (796, init / main.c: 769) / * Calls all subsystem initialization functions * /

prepare_namespace (906, init / do_mounts.c: 366)

initrd_load (399, init / do_mounts_initrd.c: 107)

rd_load_image (117, init / do_mounts_rd.c: 158) / * if the initrd is set * /

ident_ramdisk_image (179, init / do_mounts_rd.c: 53)

handle_initrd (119, init / do_mounts_initrd.c: 37) / * if rd_load_image is successful * /

mount_block_root (45, init / do_mounts.c: 233)

do_mount_root (247, init / do_mounts.: 218)

mount_root (417, init / do_mounts.c: 334) / * if initrd is not specified * /

mount_block_root (359, init / do_mounts.c: 233)

do_mount_root (247, init / do_mounts.c: 218)

init_post (915, init / main.c: 816)

run_init_process (847, init / main.c: 807)

kernel_execve (810, arch / arm / kernel / sys_arm.c: 81)

User space

init () / * userpace / sbin / init * /

Loader:

The boot loader is a small program that loads a kernel image into RAM and loads a kernel image. This is also called bootstrap, because it brings (pulls) the system, loading the operating system. The boot loader starts up before any other software is started and the processor is initialized and makes the processor ready for program execution, such as the operating system. Most processors have a default address from which the first bytes of the code are received when power is applied, or the board is reset. Hardware designers use this information to store bootloader code at this address in ROM or flash memory. Since it must initialize the processor and must run a program that is located at an address specific to the architecture, the boot loaders are loaded with a specific specific processor and are specific to the boards. Each integrated board comes with a boot load to load a kernel image or a standard application onto the board and start executing an image or kernel application. The loader will run when power is applied to the processor board. Basically he will have some minimal possibilities for image loading and uploading.

You can also control the system using a hardware debugging interface, such as JTAG. This interface can be used to write the boot loader program to non-volatile bootable memory (for example, flash), instructing the processor core to perform the necessary steps to program non-volatile memory. Usually performed for the first time to boot the base loader and for some recovery process. JTAG is a standard and popular interface provided by many motherboard manufacturers. Some microcontrollers provide special hardware interfaces that cannot be used to arbitrarily control the system or run code directly, but instead allow you to insert the boot code into non-volatile boot memory (for example, flash memory) through simple protocols. Then at the manufacturing stage, such interfaces are used to enter a boot code (and, possibly, another code) into non-volatile memory. After the system is reset, the microcontroller starts executing the code programmed into its non-volatile memory, just as conventional processors use a ROM to boot. In many cases, these interfaces are implemented using wired logic. In other cases, such interfaces can be created using software running on an embedded boot disk on a chip from the GPIO pins.

There are other third-party loaders that provide a rich set of functions and a convenient user interface. You can load these third-party bootloaders in the board and can make them the default bootloaders for your board. Usually, bootloaders provided by motherboard manufacturers are replaced by these third-party bootloaders. There are quite a few third-party booladers, and some of them are open source (or free downloaders), and some of them are commercial. Some of them are Das U-Boot, Red boot, GRUB (for desktop computers), LILO, Loadlin, bootsect-loader, SYSLINUX, EtherBoot, ELILO.

We load the U-boot bootloader as our bootloader. U-boot is a widely used boot loader in embedded systems. We will explain the code from the source u-boot-2010.03. You can download U-boot from the following site. http://www.denx.de/wiki/U-Boot

How a U-boot is created:

Based on the U-boot configuration, all build files (.s) and C. files (.c) are compiled using a cross-compiler that is built for a particular architecture, and object files (.o) will be created. All of these object files are linked by the linker, and an executable file will be created. An object file or an executable file is a set of sections of type .text, .data, .bss, etc. Object files and executable files have a file format, such as an elf. All sections of the object files will be ordered in a script-based executable file named scripter script. This script indicates where all partitions should be loaded into memory when it is started. Understanding this script is very important for understanding how the loader and the kernel are loaded, and how the various sections of the loader or the kernel are loaded into memory.

Usually, when a program is launched (executed), the loader reads the executable file and loads the various sections of the executable file into the specified memory location and starts the execution of the launch function (entry point) specified in the linker script. But if you want to start the boot loader, then the download (mostly for understanding the file format) of the boot files of the executable files will not be loaded. Then you need to use the objcopy tool, which will extract all partitions from the executable file and create a binary file that does not have any file format. This binary file can be loaded into memory and executed or it can be written to ROM at a specific address (architecture-specific) that will be executed by the processor when power is applied to the board.

Suppose that, based on the U-boot configuration, all files are compiled and object files are created. The u-boot makefile uses the following linker script (architecture-specific) to create an executable file.

File: cpu / arm920t / u-boot.lds

32 OUTPUT_FORMAT ("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

33 OUTPUT_ARCH (hand)

34 LOGIN (_start)

35 SECTIONS

36 {

37. = 0x00000000;

38

39. = ALIGN (4);

40.text:

41 {

42 cpu / arm920t / start.o (.text)

43 * (. Text)

44}

4546. = ALIGN (4);

47.rodata: {* (SORT_BY_ALIGNMENT (SORT_BY_NAME (.rodata *)))}

48

49. = ALIGN (4);

50.data: {* (. Data)}

51

52. = ALIGN (4);

53.got: {* (. Got)}

54

55. = .;

56 __u_boot_cmd_start = .;

57.u_boot_cmd: {* (. U_boot_cmd)}

58 __u_boot_cmd_end = .;

59

60. = ALIGN (4);

61 __bss_start = .;

62.bss (NOLOAD): {* (. Bss). = ALIGN (4); }

63 _end = .;

64}

OUTPUT_FORMAT in line # 32 Specify the format of the executable file. Here, the executable file format is elf32, and endianness is a bit endian. OUTPUT_ARCH in line # 33 indicates the architecture on which this code works. ENTRY in line # 34 indicates the launch function (starting point) of the u-boot program. Here is the _start entry point.

SECTIONS on line 35 determine how the various sections are displayed in the executable file. Loader uses the addresses listed in this section to load various sections of the program into memory.

& # 39; Line # 37 indicates the starting address to which the following sections should be uploaded. In this case, the starting address is 0x00000000. After that, in line # 39, the memory is aligned by 4 bytes, and the .text section follows in line # 40.

40.text:

41 {

42 cpu / arm920t / start.o (.text)

43 * (. Text)

44}

On & # 39; position (0x00000000) the code in the cpu / arm920t / start.o file is displayed and follows the code that is in the in.text sections of all other files (.o). cpu / arm920t / start.o contains the _start () function (in assembly language), which is the entry point of this program.

Now & # 39; will be set to 0x00000000 + sizeof (.text). Again, the memory is aligned by 4 bytes, and the .rodata section continues in line # 47.

, = ALIGN (4);

47.rodata: {* (SORT_BY_ALIGNMENT (SORT_BY_NAME (.rodata *)))}

Sections .rodata from all object files are displayed at this address. Follow the sections of the.data and.git.

49. = ALIGN (4);

50.data: {* (. Data)}

51

52. = ALIGN (4);

53.got: {* (. Got)}

Each U-boot command is an object of type & gt; cmd_tbl_t & # 39; which contains the name of the command, a help line and a function pointer that will be executed when this command is executed. All these command objects are stored in memory sequentially. Each of these command objects is embedded in the U-boot section specified in the .u_boot_cmd object file. These all.u_boot_cmd sections are placed in memory after the above sections (.data and.git).

,

56 __u_boot_cmd_start = .;

57.u_boot_cmd: {* (. U_boot_cmd)}

58 __u_boot_cmd_end = .;

__u_boot_cmd_start contains the beginning of command objects and __u_boot_cmd_end containing the end of command objects.

The following sections are the.bss (uninitialized global variables).

60. = ALIGN (4);

61 __bss_start = .;

62.bss (NOLOAD): {* (. Bss). = ALIGN (4); }

63 _end = .;

__bss_start points to the starting address. bss and _end contain the end of all sections.

Using this linker script linker, a u-boot executable file is created. The Objcopy tool is used to create a binary file from the u-boot executable file.

u-boot.bin: u-boot

$ (OBJCOPY) $ {OBJCFLAGS} -O binary $




 ARM Linux boot process -2


 ARM Linux boot process -2

Click to comment