First, I will reference this article "ARM Linux kernel startup requirements". ARM Linux kernel boot requirements was written by Russell king, the maintainer of the ARM Linux kernel.
* CPU register settings
O R0 = 0.
O R1 = machine type number.
O r2 = physical address of tagged list in system Ram.
* CPU Mode
O all forms of interrupts must be disabled (irqs and fiqs .)
O The CPU must be in SVC mode. (a special exception exists for Angel .)
* Caches, mmus
O the MMU must be off.
O instruction cache may be on or off.
O data cache must be off and must not contain any stale data.
* Devices
O dma to/from devices shoshould be quiesced.
* The Boot Loader is expected to call the kernel image by jumping directly to the first instruction of the kernel image.
This is basically the above conditions. Please pay special attention to the first one. This is basically the essential difference between the go command of U-boot and the bootm command. First, let's take a look at the implementation of the bootm command, starting from line 119th of common/consumer _bootm.c:
- # Ifdef config_ppc
- Static boot_ OS _fcn do_bootm_linux;
- # Else
- Extern boot_ OS _fcn do_bootm_linux;
- # Endif
Copy code
The precompiled macro here illustrates that the do_bootm_linux () function of the CPU that is not in the PPC architecture is not implemented in this file (extern ). It is conceivable that the implementation of this function should be related to the architecture. Specifically, the implementation of the ARM architecture is in the lib_arm/armlinux. c file. We can see that row 77th in lib_arm/armlinux. c is the implementation of the do_bootm_linux () function.
Row 3 declares a function pointer Thekernel:
- Void (* Thekernel) (INT zero, Int Arch, uint Params );
Copy code
Look at its name and parameter name. We can also guess that this is actually the pointer to the kernel entry function. The naming of several parameters also illustrates the first requirement for starting the ARM Linux kernel mentioned above, because according to the ACPs (ARM/thumb procedure call standard), these three parameters use R0 in sequence, r1 and R2.
The next row is to assign a value to the function pointer:
- Thekernel = (void (*) (INT, Int, uint) ntohl (HDR-> ih_ep );
Copy code
We can see that Thekernel is assigned a value of HDR-> ih_ep. This HDR refers to a header added before linux.bin.gz when uimageis produced using the tools/mkimagetool, ih_ep struct members store the value of the-e parameter specified when mkimage is used, that is, the entry point of the kernel ). After learning the meaning of HDR-> ih_ep, it is taken for granted to assign this value to Thekernel.
The last is the call to the kernel entry function, which occurs in row 270th:
- Thekernel (0, BD-> bi_arch_number, BD-> bi_boot_params );
Copy code
Assign a value to the parameter during the call. For example, R0 = 0, R1 = BD-> bi_arch_number, R2 = BD-> bi_boot_params. So far U-boot's mission has been completed, and it has begun to enter the beautiful new world of ARM Linux.
========================================================== ======================================
To know which address is to start the kernel and which address to start the file system, analyze the function do_bootm in common/cmd_bootm.c, because the bootstrap kernel is the work of the bootm command, do_bootm is the execution function of the bootm command.
Now let's analyze the do_bootm function in common/cmd_bootm.c, which is the processing function of the bootm command.
- ......
- Image_header_t header;
- Ulong load_addr = pai_load_addr;/* default load address */
- Int do_bootm (pai_tbl_t * cmdtp, int flag, int argc, char * argv [])
- {
- Ulong iflag;
- Ulong ADDR;
- Ulong data, Len, checksum;
- Ulong * len_ptr;
- Uint unc_len = 0x400000;
- Int I, verify;
- Char * Name, * s;
- INT (* appl) (INT, char * []);
- Image_header_t * HDR = & header;
Copy code
Read the uboot environment variable verify. If the environment variable verify is equal to 'n', the local variable verify is assigned 0; if the environment variable verify is empty (that is, no environment variable verify is defined) or if the environment variable verify is not equal to 'n', the local variable verify is assigned a value of 1.
- S = getenv ("verify ");
- Verify = (S & (* s = 'n '))? 0: 1;
Copy code
If the number of parameters is less than 2 (only bootm is input), use the default loading address pai_load_addr; otherwise, use the second parameter as the loading address.
- If (argc <2 ){
- ADDR = load_addr;
- } Else {
- ADDR = simple_strtoul (argv [1], null, 16 );
- }
- Show_boot_progress (1 );
- Printf ("# booting image at % 08lx... \ n", ADDR );
Copy code
Add mkimage to the header of the image file and extract it to the header of the image_header_t structure variable.
/* Copy header so we can blank CRC Field for re-calculation */
Config_has_dataflash is defined, indicating that Atmel data flash exists in the system.
- # Ifdef config_has_dataflash
- If (addr_dataflash (ADDR )){
- Read_dataflash (ADDR, sizeof (image_header_t), (char *) & header );
- } Else
- # Endif
- Memmove (& header, (char *) ADDR, sizeof (image_header_t ));
Copy code
Determine whether the magic of the image header matches. If the magic matches, an error occurs during the download process.
- If (ntohl (HDR-> ih_magic )! = Ih_magic ){
- # Ifdef _ i386 _/* correct image format not implemented yet-Fake It */
- If (fake_header (HDR, (void *) ADDR,-1 )! = NULL ){
- /* To compensate for the addition below */
- ADDR-= sizeof (image_header_t );
- /* Turnof verify,
- * Fake_header () does not fake the data CRC
- */
- Verify = 0;
- } Else
- # Endif/* _ i386 __*/
- {
- Puts ("Bad magic number \ n ");
- Show_boot_progress (-1 );
- Return 1;
- }
- }
- Show_boot_progress (2 );
Copy code
Check the CRC of the image header and the CRC of the image data. If the verification does not match, an error occurs during the download process.
- Data = (ulong) & header;
- Len = sizeof (image_header_t );
- Checksum = ntohl (HDR-> ih_hcrc );
- HDR-> ih_hcrc = 0;
- If (CRC32 (0, (char *) data, Len )! = Checksum ){
- Puts ("Bad header checksum \ n ");
- Show_boot_progress (-2 );
- Return 1;
- }
- Show_boot_progress (3 );
- /* For multi-file images we need the data part, too */
- Print_image_hdr (image_header_t *) ADDR );
- Data = ADDR + sizeof (image_header_t );
- Len = ntohl (HDR-> ih_size );
- # Ifdef config_has_dataflash
- If (addr_dataflash (ADDR )){
- Read_dataflash (data, Len, (char *) cfg_load_addr );
- Data = pai_load_addr;
- }
- # Endif
- If (verify ){
- Puts ("verifying checksum ...");
- If (CRC32 (0, (char *) data, Len )! = Ntohl (HDR-> ih_dcrc )){
- Printf ("Bad Data CRC \ n ");
- Show_boot_progress (-3 );
- Return 1;
- }
- Puts ("OK \ n ");
- }
- Show_boot_progress (4 );
Copy code
Judge the architecture.
- Len_ptr = (ulong *) data;
- # If defined (_ PPC __)
- If (HDR-> ih_arch! = Ih_cpu_ppc)
- # Elif defined (_ arm __)
- If (HDR-> ih_arch! = Ih_cpu_arm)
- # Elif defined (_ i386 __)
- If (HDR-> ih_arch! = Ih_cpu_i386)
- # Elif defined (_ MIPS __)
- If (HDR-> ih_arch! = Ih_cpu_mips)
- # Elif defined (_ NiO __)
- If (HDR-> ih_arch! = Ih_cpu_nio)
- # Elif defined (_ m68k __)
- If (HDR-> ih_arch! = Ih_cpu_m68k)
- # Elif defined (_ microblze __)
- If (HDR-> ih_arch! = Ih_cpu_microblze)
- # Else
- # Error unknown CPU type
- # Endif
- {
- Printf ("unsupported architecture 0x % x \ n", HDR-> ih_arch );
- Show_boot_progress (-4 );
- Return 1;
- }
- Show_boot_progress (5 );
Copy code
Determines the image type.
- Switch (HDR-> ih_type ){
- Case ih_type_standalone:
- Name = "standalone application ";
- /* A second argument overwrites the load address */
- If (argc> 2 ){
- HDR-> ih_load = simple_strtoul (argv [2], null, 16 );
- }
- Break;
- Case ih_type_kernel:
- Name = "kernel image ";
- Break;
- Case ih_type_multi:
- Name = "Multi-file image ";
- Len = ntohl (len_ptr [0]);
- /* OS kernel is always the first image */
- Data + = 8;/* kernel_len + Terminator */
- For (I = 1; len_ptr [I]; ++ I)
- Data + = 4;
- Break;
- Default: printf ("wrong image type for % s command \ n", required TP-> name );
- Show_boot_progress (-5 );
- Return 1;
- }
- Show_boot_progress (6 );
- /*
- * We have reached the point of no return: We are going
- * Overwrite all Exception vector code, so we cannot easily
- * Recover from any failures any more...
- */
- Iflag = disable_interrupts ();
- # Ifdef config_amigaoneg3se
- /*
- * We 've possible left the caches enabled
- * BIOS emulation, so turn them off again
- */
- Icache_disable ();
- Invalidate_l1_instruction_cache ();
- Flush_data_cache ();
- Dcache_disable ();
- # Endif
Copy code
Determine the image compression type
- Switch (HDR-> ih_comp ){
- Case ih_comp_none: no compression
- If (ntohl (HDR-> ih_load) = ADDR) {if the loading address indicated in the image header is the same as the address specified in parameter 2 in the bootm command, copy is not required, it can be executed locally.
- Printf ("xip % s...", name );
- } Else {
- # If defined (config_hw_watchdog) | defined (config_watchdog)
- Size_t L = Len;
- Void * To = (void *) ntohl (HDR-> ih_load );
- Void * From = (void *) data;
- Printf ("loading % s...", name );
- While (L> 0 ){
- Size_t tail = (L> chunksz )? Chunksz: L;
- Watchdog_reset ();
- Memmove (to, from, tail );
- To + = tail;
- From + = tail;
- L-= tail;
- }
- # Else /*! (Config_hw_watchdog | config_watchdog )*/
Copy code
If the loading address indicated in the image header is different from the address specified in parameter 2 in the bootm command, it indicates that the image data will be copied to the address specified by parameter 2 in the bootm command from the loading address indicated in the image header, and then executed.
- Memmove (void *) ntohl (HDR-> ih_load), (uchar *) data, Len );
- # Endif/* config_hw_watchdog | config_watchdog */
- }
- Break;
- Case ih_comp_gzip:
- Printf ("Uncompressing % s...", name );
- If (gunzip (void *) ntohl (HDR-> ih_load), unc_len,
- (Uchar *) data, (int *) & Len )! = 0 ){
- Puts ("gunzip error-must reset board to recover \ n ");
- Show_boot_progress (-6 );
- Do_reset (cmdtp, flag, argc, argv );
- }
- Break;
- # Ifdef config_bzip2
- Case ih_comp_bzip2:
- Printf ("Uncompressing % s...", name );
- /*
- * If we 've got less than 4 MB of malloc () space,
- * Use slower decompression algorithm which requires
- * At most 2300 KB of memory.
- */
- I = bz2_bzbufftobuffdecompress (char *) ntohl (HDR-> ih_load ),
- & Unc_len, (char *) data, Len,
- Performance_malloc_len <(4096*1024), 0 );
- If (I! = Bz_ OK ){
- Printf ("bunzip2 error % d-must reset board to recover \ n", I );
- Show_boot_progress (-6 );
- Udelay (100000 );
- Do_reset (cmdtp, flag, argc, argv );
- }
- Break;
- # Endif/* config_bzip2 */
- Default:
- If (iflag)
- Enable_interrupts ();
- Printf ("unimplemented compression type % d \ n", HDR-> ih_comp );
- Show_boot_progress (-7 );
- Return 1;
- }
- Puts ("OK \ n ");
- Show_boot_progress (7 );
Copy code
Determine how to boot based on the type of the image.
- Switch (HDR-> ih_type ){
- Case ih_type_standalone:
- If (iflag)
- Enable_interrupts ();
- /* Load (and uncompress), but don't start if "autostart"
- * Is set to "no"
- */
- If (S = getenv ("autostart "))! = NULL) & (strcmp (S, "no") = 0 )){
- Char Buf [32];
- Sprintf (BUF, "% lx", Len );
- Setenv ("filesize", Buf );
- Return 0;
- }
- Appl = (INT (*) (INT, char * []) ntohl (HDR-> ih_ep );
- (* Appl) (argc-1, & argv [1]);
- Return 0;
- Case ih_type_kernel:
- Case ih_type_multi:
- /* Handled below */
- Break; the following code specifically processes the two image types
- Default:
- If (iflag)
- Enable_interrupts ();
- Printf ("can't boot image type % d \ n", HDR-> ih_type );
- Show_boot_progress (-8 );
- Return 1;
- }
- Show_boot_progress (8 );
Copy code
Determine how to Boot Based on the image OS type
- Switch (HDR-> ih_ OS ){
- Default:/* handled by (original) Linux case */
- Case ih_ OS _linux:
- # Ifdef config_silent_console
- Fixup_silent_linux ();
- # Endif
- Do_bootm_linux (kernel TP, flag, argc, argv,
- ADDR, len_ptr, verify );
- Break;
- Case ih_ OS _netbsd:
- Do_bootm_netbsd (cmdtp, flag, argc, argv,
- ADDR, len_ptr, verify );
- Break;
- # Ifdef config_lynxkdi
- Case ih_ OS _lynxos:
- Do_bootm_lynxkdi (cmdtp, flag, argc, argv,
- ADDR, len_ptr, verify );
- Break;
- # Endif
- Case ih_ OS _rtems:
- Do_bootm_rtems (effectp, flag, argc, argv,
- ADDR, len_ptr, verify );
- Break;
- # If (config_commands & cmd_cmd_elf)
- Case ih_ OS _vxworks:
- Do_bootm_vxworks (cmdtp, flag, argc, argv,
- ADDR, len_ptr, verify );
- Break;
- Case ih_ OS _qnx:
- Do_bootm_qnxelf (cmdtp, flag, argc, argv,
- ADDR, len_ptr, verify );
- Break;
- # Endif/* pai_pai_elf */
- # Ifdef config_artos
- Case ih_ OS _artos:
- Do_bootm_artos (cmdtp, flag, argc, argv,
- ADDR, len_ptr, verify );
- Break;
- # Endif
- }
- Show_boot_progress (-9 );
- # Ifdef debug
- Puts ("\ n # control returned to monitor-Resetting... \ n ");
- Do_reset (cmdtp, flag, argc, argv );
- # Endif
- Return 1;
- }
Copy code
The bootm command is used to guide the kernel image packaged by the mkimage tool after U-boot. What is the kernel image packaged by the mkimage tool after U-boot, this depends on the mkimage code to see what it has done. Although I hope you will not be lazy and take a look at it seriously, I know that many people are too lazy to do this, then I will summarize the mkimage code and tell you what mkimage has done and how to use this tool.
Mkimage usage
The tools/directory of uboot Source Code contains the mkimage tool, which can be used to create a variety of startup image files without compression or compression.
When creating an image file, mkimage adds a 0x40 header before the original executable image file to record the information specified by the parameter, in this way, uboot can identify the CPU architecture, OS, type, memory location, the entry point, and image name of the image.
Root @ glym:/tftpboot #./mkimage
Usage:./mkimage-l Image
-L ==> list image header information
./Mkimage-A arch-O OS-T type-C comp-A ADDR-e EP-N name-D data_file [: data_file...] Image
-A ==> set architecture to 'arch'
-O => Set Operating System to 'OS'
-T => set image type to 'type'
-C ==> set compression type 'comp'
-A ==> Set Load address to 'addr '(HEX)
-E => set entry point to 'EP' (HEX)
-N => set image name to 'name'
-D => Use Image Data from 'datafile'
-X ==> set xip (execute in place)
Parameter description:
-A: Specify the CPU architecture:
Architecture represented by values
Alpha
Arm a RM
X86 Intel x86
IA64 IA64
MIPs
Mips64 MIPS 64 bit
PPC powerpc
S390 IBM s390
Sh superh
Type
Sparc64 iSCSI 64 bit
M68k mc68000
-O: Specifies the operating system type. The following values can be used:
OpenBSD, NetBSD, FreeBSD, 4_4bsd, Linux, svr4, esix, Solaris, Irix, SCO, Dell, NCR, lynxos, VxWorks, PSOs, QNX, U-boot, RTEMS, Artos
-T specifies the image type. The following values can be taken:
Standalone, kernel, ramdisk, multi, firmware, script, filesystem
-C: Specifies the image compression method. The following values can be taken:
None
Gzip Compression Method
Bzip2 is compressed with Bzip2
-A specifies the image loading address in the memory. When the image is downloaded to the memory, the image must be downloaded according to the address value specified by this parameter when the image is created using mkimage.
-E specifies the image running entry point address, which is the value specified by-a plus 0x40 (because there is a mkimage header with 0x40 bytes added)
-N indicates the image name.
-D specifies the source file for image creation.
This article from: http://blog.chinaunix.net/u/17660/showart_279896.html