ARM Linux boot process analysis is the content of this article. The portability of embedded Linux allows us to see it on various electronic products. The Linux boot process is different for processors of different architectures.
This paper takes the S3C2410 ARM processor as an example to analyze the execution flow of the bootloader and the startup process of ARM Linux after the system is powered on.
1 Introduction
Linux was originally developed in 1991 by Linus Torvalds, a student at the University of Helsinki in Sweden. After that, with the support of GNU, Linux has grown tremendously. Although Linux is far less popular on desktop PCs than Microsoft's Windows operating system, its rapid development and increasing number of users are something that Microsoft cannot ignore. In recent years, the rapid development of Linux in the embedded field has injected new vitality into Linux.
An embedded Linux system can be divided into four parts from a software perspective: a bootloader, a Linux kernel, a file system, and an application.
The bootloader is the first piece of code executed after the system is started or reset. It is mainly used to initialize the processor and peripherals, and then call the Linux kernel.
After the Linux kernel completes the initialization of the system, it needs to mount a file system as the root file system.
The root file system is a core component of a Linux system. It can be used as a storage area for files and data in a Linux system. It usually includes system configuration files and libraries needed to run application software.
An application can be said to be the "soul" of an embedded system. The function it implements is usually the goal of designing the embedded system. Without the support of the application, any well-designed embedded system on hardware has no practical meaning.
From the above analysis, we can see the relationship and role of the bootloader and the Linux kernel in the embedded system.
Although the bootloader has the functions of initializing the system and executing user input during the running process, its most fundamental function is to start the Linux kernel. In the process of embedded system development, a lot of energy is spent on the development or porting of bootloader and Linux kernel.
If you can clearly understand the bootloader execution process and the Linux boot process, it will help to clarify the work required in the development process, thus accelerating the development process of the embedded system. And this is what this article is about.
2, Bootloader
(1) The concept and role of the bootloader
Bootloader is the boot loader of the embedded system. It is the first program that runs after the system is powered on. Its function is similar to the BIOS on the PC. After completing the initialization task for the system, it will copy the Linux kernel in the non-volatile memory (usually Flash or DOC, etc.) into RAM, and then jump to the first instruction of the kernel to continue execution. Start the Linux kernel. It can be seen that the bootloader and the Linux kernel are inextricably linked. To understand the boot process of the Linux kernel clearly, we must first understand the execution process of the bootloader, so that we can have a clear grasp of the entire startup process of the embedded system.
(2) Bootloader execution process
The address of the first instruction executed after a different processor is powered up or reset is not the same. For an ARM processor, the address is 0x00000000. For a typical embedded system, a non-volatile memory such as Flash is usually mapped to this address, and the bootloader is located at the front end of the memory, so the first program executed after the system is powered on or reset is the bootloader. Because the storage of the bootloader is different, the execution process of the bootloader is not the same, as will be analyzed in detail below.
The non-volatile memory widely used in embedded systems is usually Flash, and Flash is divided into Nor Flash and Nand Flash. The difference between them is: Nor Flash supports in-chip execution (XIP, eXecute In Place), so that code can be executed directly on Flash without having to copy it to RAM for execution. Nand Flash does not support XIP, so to execute the code on Nand Flash, you must first copy it to RAM and then jump to RAM to execute it.
In actual application, the bootloader can be designed to be complicated according to the required functions. In addition to basic tasks such as completing the basic initialization system and calling the Linux kernel, you can also execute many user-entered commands, such as setting Linux startup parameters and assigning Flash partitions. Etc.; it can also be designed to be simple, with only the most basic functions. However, in order to achieve the purpose of booting the Linux kernel, all bootloaders must have the following features:
Initialize RAM
Because the Linux kernel generally runs in RAM, the bootloader must set up and initialize RAM before calling the Linux kernel, in preparation for calling the Linux kernel. The task of initializing the RAM involves setting the control register parameters of the CPU so that the RAM can be used normally and the RAM size can be detected.
Initialize the serial port
The serial port plays a very important role in the Linux boot process. It is one of the ways the Linux kernel interacts with the user. Linux can output information through the serial port during startup, so that you can clearly understand the Linux boot process. Although it is not a work that the bootloader must do, outputting information through the serial port is a powerful tool for debugging the bootloader and the Linux kernel. Therefore, the general bootloader will initialize a serial port as a debug port during execution.
Detect processor type
The bootloader must detect the processor type of the system before calling the Linux kernel and save it to a constant to provide to the Linux kernel. The Linux kernel calls the appropriate initializer based on the processor type during startup.
Set Linux boot parameters
The bootloader must set and initialize the kernel boot parameters for Linux during execution. Currently, there are two main ways to pass the startup parameters: the struct param_struct and the struct tag (tagged list). Struct param_struct is an older method of parameter passing, which is used more in kernels prior to 2.4. Since the 2.4 release, the Linux kernel basically uses a tag list. However, in order to maintain compatibility with previous versions, it still supports the struct param_struct parameter passing method, except that it will be converted to a tag list mode during kernel startup. The tag list mode is a relatively new way of parameter passing, it must start with ATAG_CORE and end with ATAG_NONE. You can add other lists as needed in the middle. The Linux kernel will perform the corresponding initialization work according to the startup parameters during the startup process.
Calling the Linux kernel image
The last job done by the bootloader is to call the Linux kernel. If the Linux kernel is stored in Flash and can be run directly on it (where Flash refers to Nor Flash), then you can jump directly to the kernel to execute. However, due to the limitations of executing code in Flash, and the speed is far less than RAM, the general embedded system copies the Linux kernel into RAM and then jumps to RAM for execution. In either case, the CUP register must satisfy the following conditions before jumping to the Linux kernel: r0=0, r1=processor type, r2=the address of the tag list in RAM.
3, the Linux kernel startup process
After the bootloader copies the Linux kernel image to RAM, you can start the Linux kernel with the following code: call_linux(0, machine_type, kernel_params_base).
Among them, machine_tpye is the type of processor detected by the bootloader, and kernel_params_base is the address of the startup parameter in RAM. In this way, the parameters required for Linux boot are passed from the bootloader to the kernel.
The Linux kernel has two types of images: one is an uncompressed kernel called Image, and the other is a compressed version of it, called zImage.
The booting of the Linux kernel varies from start to start depending on the kernel image.
zImage is an Image that is compressed, so it is smaller than Image. However, in order to use zImage, you must add decompressed code at the beginning of it to decompress the zImage before it can be executed, so it will execute slower than Image. However, considering the storage system's storage capacity is generally small, using zImage can take up less storage space, so it is worthwhile to sacrifice a bit of performance. Therefore, the general embedded system adopts the method of compressing the kernel.
For ARM series processors, the zImage entry program is arch/arm/boot/compressed/head.S. It does the following things in turn: turn on the MMU and Cache, call decompress_kernel() to decompress the kernel, and finally call the call_kernel() to start the boot of the uncompressed kernel Image. The following is a detailed analysis of the boot process of the Linux kernel after this.
(1) Linux kernel entry
The entry for the Linux uncompressed kernel is located in the stext section of the file /arch/arm/kernel/head-armv.S. The base address of the segment is the jump address after the compressed kernel is decompressed. If the kernel loaded in the system is an uncompressed Image, the bootloader will jump directly to the address after copying the kernel from Flash to RAM, thus booting the Linux kernel. The entry files for Linux systems of different architectures are different, and because the files are related to the specific architecture, they are generally written in assembly language. For ARM-based Linux systems, this file is head-armv.S. The program calls the corresponding initialization function by looking up the processor core type and processor type, then builds the page table, and finally jumps to the start_kernel() function to start the initialization of the kernel.
Detecting the processor core type is done in the assembly subfunction __lookup_processor_type. Call to it with the following code: bl __lookup_processor_type. When the __lookup_processor_type call returns to the original program, the returned result is saved to the register. Where r8 holds the flag of the page table, r9 holds the ID number of the processor, and r10 holds the address of the struproc_info_list structure associated with the processor.
The detection processor type is done in the assembly subfunction __lookup_architecture_type. Similar to __lookup_processor_type, it implements the call to it via the code: "bl __lookup_processor_type". When the function returns, the return structure is stored in three registers, r5, r6, and r7. Where r5 holds the starting base address of the RAM, r6 holds the I/O base address, and r7 holds the page table offset address of the I/O. When the processor core and processor type are detected, the __create_page_tables subfunction is called to create the page table. All that is done is to map the physical address of the 4M space starting at the RAM base address to the virtual address starting at 0xC0000000. For the author's S3C2410 development board, the RAM is connected to the physical address 0x30000000. When __create_page_tables is called, the 0x30000000 to 0x30400000 physical addresses are mapped to the 0xC0000000~0xC0400000 virtual addresses.
When all initialization is complete, use the following code to jump to the C program's entry function start_kernel() and start the kernel initialization work:
b SYMBOL_NAME(start_kernel)
(2) start_kernel function
Start_kernel is the entry function of all Linux platforms after entering the system kernel initialization. It mainly completes the remaining hardware platform-related initialization work. After a series of kernel-related initialization, the first user process -init process is called and the user is awaited. The execution of the process, so that the entire Linux kernel is started. The specific work done by this function is to call the setup_arch() function to perform the first initialization work related to the architecture; the function has different definitions for different architectures. For the ARM platform, this function is defined in arch/arm/kernel/Setup.c. It first initializes the processor core through the detected processor type, then initializes the memory structure according to the system-defined meminfo structure through the bootmem_init() function, and finally calls paging_init() to start the MMU, create a kernel page table, and map all the Physical memory and IO space.
a, create an exception vector table and initialize the interrupt handler function;
b, initialize the system core process scheduler and clock interrupt processing mechanism;
c, initialize the serial console (serial-console);
d. ARM-Linux generally initializes a serial port as the console of the kernel during the initialization process, so that the kernel can output information through the serial port during the startup process so that the developer or the user can understand the startup process of the system.
e. Create and initialize system caches to provide caching for various memory invocation mechanisms, including; dynamic memory allocation, virtual file system (VirtualFile System) and page cache.
f, initialize memory management, detect the size of the memory and the memory occupied by the kernel;
g. Initialize the inter-process communication mechanism (IPC) of the system;
When all of the above initialization is complete, the start_kernel() function calls the rest_init() function for the final initialization, including creating the first process of the system, the -init process, to end the kernel. The Init process first performs a series of hardware initializations and then mounts the root file system through the parameters passed from the command line. Finally, the init process executes the "init=" startup parameter passed by the user to execute the user-specified command, or performs one of the following processes:
1 execve("/sbin/init",argv_init,envp_init);2 execve("/etc/init",argv_init,envp_init);3 execve("/bin/init",argv_init,envp_init);4 execve("/ Bin/sh", argv_init, envp_init).
When all initialization is complete, the cpu_idle() function is called to put the system in an idle state and wait for the user program to execute. At this point, the entire Linux kernel is booted.
4 Conclusion
The Linux kernel is a very large project. After more than a decade of development, it has grown from the initial hundreds of KB to hundreds of megabytes. It is very difficult to clearly understand every process it performs. However, in the embedded development process, we do not need to be very clear about the internal workings of Linux. As long as the hardware-related parts of the Linux kernel are properly modified, Linux can be ported to other target platforms. Through the analysis of the Linux boot process, we can see which are related to the hardware, which are the functions that have been implemented inside the Linux kernel, so that it is targeted in the process of porting Linux. The layered design of the Linux kernel will make the porting of Linux easier.
Usb C Cable is also known as Usb Cable Type C interface,is an interface specification consisting of a Type-C plug and a type-C socket.Its highlights are thinner design,faster transmission speed (up to 10Gbps),stronger power transmission (up to 100W).In addition, USB-C interface also supports double-sided insertion,front and back can be inserted at will, compared with USB2.0/USB3.0 more advanced.Usb-c has been given better media properties,faster transfer speeds,and better compatibility with charging.The new generation USB-C has faster transmission speed than USB,stronger power transmission, smaller interface size,and supports bidirectional transmission with stronger compatibility.
Thinner bodies require thinner ports,which is one of the reasons USB-C is here to stay.The USB-C port is 0.83 cm long and 0.26 cm wide.The old USB port measuring 1.4cm long and 0.65cm wide looks outdated.This also means that the end of USB Cable will be one-third the size of the plug of A standard USB-A cable.The USB-C port is the same on the front and back.This means that no matter how you insert the port,it will be correct.Users do not have to worry about the pros and cons of traditional USB ports.
Usb C Cable,Custom Usb C Cable,Flexible Usb C Cable,Braided Coiled Usb C Cable
Henan Yijiao Trading Co., Ltd , https://www.yjusbhubs.com