[Uboot] Uboot start Kernel (ii)--BOOTM jump to Kernel process

Source: Internet
Author: User
Tags printf requires sub command
I. Description of BOOTM

BOOTM This command is used to start an operating system image. It obtains some information from the head of the image file, which includes the CPU architecture of the image file, its operating system type, the type of image, the compression method, the load address of the image file in memory, the entry address of the image file to run, the image filename, and so on.
The BOOTM then loads the image to the specified address and, if necessary, extracts the image and passes the necessary parameters to the kernel, and finally jumps to the ingress address to enter the kernel.
Here's a description reference (http://blog.chinaunix.net/uid-20799298-id-99666.html)

Macros that need to be opened

Config_bootm_linux=y
config_cmd_bootm=y
second, Bootm use way

In the Uboot launch Kernel (a)--legacy-uimage & Fit-uimage, we know that there are two formats of uimage. Legacy-uimage
For Legacy-uimage, we need to load the RAMDisk and FDT to ram separately.
The following commands are executed

Assuming that the load address of the legacy-uimage is 0x20008000,ramdisk load address is 0X21000000,FDT load address is 0x22000000

(1) Only load kernel case
BOOTM 0x20008000

(2) load kernel and RAMDisk
bootm 0x20008000 0x21000000

(3) load kernel and FDT bootm 0x20008000
- 0x22000000

(4) Loading kernel, RAMDisk, FDT bootm 0x20008000 0x21000000 0x22000000
Fit-uimage
For Fit-uimage,kernel mirrors, RAMDisk mirrors, and FDT are already packaged into the fit-uimage image.
The following commands are executed
Assuming that the Fit-uimage load address is 0x30000000, the command to start kernel is as follows:
BOOTM 0x30000000
Third, BOOTM implementation process

It is recommended that you refer to the [Uboot] (sixth chapter) uboot process-command line mode and command handling introduction. Correspondence U_boot_cmd
We found the BOOTM command corresponding to the U_boot_cmd as follows:
Cmd/bootm.c

U_boot_cmd (
    Bootm,  Config_sys_maxargs, 1,  Do_bootm,
    "BOOT application image from memory", Bootm_help _text
);
DO_BOOTM parameter Description
Through the [Uboot] (sixth chapter) uboot process-command line mode and command handling introduction, DO_BOOTM is invoked when the BOOTM command is executed, with the following parameters:
When executing ' bootm 0x20008000 0x21000000 0x22000000 '
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 
  CMDTP: Passed the BOOTM command table entry pointer, which is _U_BOOT_LIST_2_CMD_2_BOOTM's pointer
argc=4
argv[0]= "Bootm", argv[1]=0x20008000, arv[2]=0x21000000, argv[3]=0x22000000
DO_BOOTM implementation
The DO_BOOTM is implemented as follows:
/*******************************************************************//* bootm-boot application image from image in me Mory *//*******************************************************************/int Do_bootm (cmd_tbl_t *cmdtp, int flag
    , int argc, char * const argv[]) {/* Determine if we have a sub command */argc--; argv++;

        if (argc > 0) {char *ENDP;
        Simple_strtoul (Argv[0], &ENDP, 16); /* ENDP pointing to NULL means that argv[0] is just a * valid number, pass it along to the normal Bootm Processi
         NG * * If ENDP is ': ' or ' # ' assume a FIT identifier so pass * along for normal processing. * Right now we assume the first arg should never is '-' * * * ((*ENDP! = 0) &&
    (*ENDP! = ': ') && (*ENDP! = ' # ')) return Do_bootm_subcommand (CMDTP, Flag, argc, argv); }//above will determine whether there are subcommands, here we do not care//here, the parameters of the BOOTM parameter will be removed,//That is, when the ' Bootm 0x20008000 0x21000000 0x22000000 '//Argc=3, argv[0]=0x20008000, argv[1]=0x21000000, argv[2]=0x22000000 When ' Bootm 0x30000000 '//Argc=1, argv[0]=0x30000000 return do_bootm_states (CMDTP, Flag, argc, argv, bootm_
        State_start | Bootm_state_findos |
        Bootm_state_findother |
        Bootm_state_loados | Bootm_state_os_prep |
        Bootm_state_os_fake_go |
        Bootm_state_os_go, &images, 1); 
        Finally, for calls to Do_bootm_states, the operations performed in Do_bootm_states are as shown in the states identity://Bootm_state_start//Bootm_state_findos Bootm_state_findother//Bootm_state_loados//bootm_state_os_prep//Bootm_state_os_f Ake_go//Bootm_state_os_go}

So the core of Bootm is do_bootm_states, with the global variable bootm_headers_t images as the do_bootm_states parameter.
The function is described in detail below. iv. do_bootm_states Software Flow 1, data structure description bootm_headers_t
bootm_headers_t is used to represent the structure of some information Bootm start kernel, including OS/INITRD/FDT Images's information. The
Bootm populates the members of this structural question according to the parameters and the mirrors that the parameters point to. The
eventually uses the information inside the struct to populate the kernel boot information and jump to kernel. The
uses a global bootm_headers_t images in Uboot.

typedef struct BOOTM_HEADERS {/* * Legacy OS image header, if it is a multi component image * then Boot_get
     _ramdisk () and GET_FDT () would attempt to get * data from second and third component accordingly.     */image_header_t *legacy_hdr_os; /* Image Header pointer *///Legacy-uimage mirror image_header_t legacy_hdr_os_copy; /* Header Copy *///Legacy-uimage Mirror header back to ulong Legacy_hdr_valid; Legacy-uimage the presence of a mirrored header #if image_enable_fit const char *fit_uname_cfg;    /* Configuration node Unit name *//config node name void *fit_hdr_os;  /* OS FIT Image Header *///fit-uimage kernel Mirror head const char *fit_uname_os; /* OS subimage node Unit name *///Fit-uimage in kernel nodes name int fit_noffset_os;    /* OS subimage node offset *///Fit-uimage kernel nodes are shifted to void *fit_hdr_rd;  /* init RAMDisk FIT Image Header *///Fit-uimage RAMDisk in the Mirror head const char *FIT_UNAME_RD; /* init ramdisk subimage node Unit name *///Fit-uimaThe node name of RAMDisk in GE is int fit_noffset_rd;   /* init ramdisk subimage Node offset *///Fit-uimage in RAMDisk nodes offsets void *fit_hdr_fdt; /* FDT blob FIT Image Header *///Fit-uimage in FDT's mirrored head const char *FIT_UNAME_FDT; /* FDT blob subimage node unit name *///Fit-uimage in FDT nodes name int fit_noffset_fdt;/* FDT blob subimage node offset     *///Fit-uimage node offset in FDT #endif image_info_t os;     /* OS Image Info *////operating system information for the structure of ULONG EP;

    /* Entry point of OS *//Os entry address ulong Rd_start, rd_end;/* ramdisk start/end *//RAMDisk start address and end address in memory   Char *ft_addr;     /* Flat dev Tree address *////FDT on-memory addresses ulong Ft_len; /* Length of flat device tree *////FDT in memory of ULONG Initrd_start; ULONG Initrd_end; ULONG Cmdline_start; ULONG Cmdline_end; bd_t *KBD;     int verify; /* GETENV ("verify") [0]! = ' n '///Whether you need to verify int state; Status identification, which identifies the correspondingBootm What you need to do, see below 2.        #ifdef CONFIG_LMB struct LMB LMB; /* For Memory MGMT */#endif} bootm_headers_t;
2. Status DescriptionBootm_state_start
#define Bootm_state_start (0x00000001)
Start performing some preparatory actions for BOOTM. Bootm_state_findos
#define BOOTM_STATE_FINDOS (0x00000002)
Find operating System Image Bootm_state_findother
#define Bootm_state_findother (0x00000004)
Look for other mirrors outside the operating system image, such as fdt\ramdisk, etc. bootm_state_loados
#define BOOTM_STATE_LOADOS (0x00000008)
Load operating system Bootm_state_ramdisk
#define BOOTM_STATE_RAMDISK (0x00000010)
Operation RAMDisk BOOTM_STATE_FDT
#define BOOTM_STATE_FDT (0x00000020)
Operation Fdt Bootm_state_os_cmdline
#define Bootm_state_os_cmdline (0x00000040)
Operation CommandLine bootm_state_os_bd_t
#define BOOTM_STATE_OS_BD_T (0x00000080) bootm_state_os_prep
#define BOOTM_STATE_OS_PREP (0X00000100)
Jump to the front of the operating system for ready action Bootm_state_os_fake_go
#define BOOTM_STATE_OS_FAKE_GO (0x00000200)/* ' Almost ' run the OS */
Pseudo jump, generally can jump directly to the kernel to Bootm_state_os_go
#define BOOTM_STATE_OS_GO (0x00000400)
Jump to the kernel. 3. Software Process Description

do_bootm_states the action to be performed according to the states. A brief description of the main process is as follows:
BOOTM's Preparation action
Bootm_state_start Getting kernel information
Bootm_state_findos get information on RAMDisk and FDT
Bootm_state_findother load kernel to the corresponding position (possibly already in this position)
Bootm_state_loados redirect RAMDisk and FDT (not necessarily required)
Bootm_state_ramdisk, BOOTM_STATE_FDT perform pre-jump preparation action
Bootm_state_os_prep set the startup parameters and jump to the address where the kernel is located
Bootm_state_os_go

In these processes, the transfer is bootm_headers_t images this data structure, some of the process is to parse the image, to this structure to write data.
When jumping, you need to use the data inside the structure. The software code is as follows
Common/bootm.c

int Do_bootm_states (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], int states, bootm_headers_t *im
    ages, int boot_progress) {BOOT_OS_FN *boot_fn;
    ULONG Iflag = 0;

    int ret = 0, NEED_BOOT_FN;
       Images->state |= states; Put the states in bootm_headers_t images internal/* Work through the states and see how far we get.
     We Stop on * any error.
        *///Determine if states requires Bootm_state_start action, that is, BOOTM's readiness action, call Bootm_start if required (states & Bootm_state_start)

        ret = Bootm_start (CMDTP, Flag, argc, argv); Determine if States need bootm_state_findos action, that is, to get kernel information, if necessary, call Bootm_find_os if (!ret && (states & Bootm_state_

    Findos)) ret = Bootm_find_os (CMDTP, Flag, argc, argv);   · Determine if states requires bootm_state_findother action, that is, to obtain information about other images such as RAMDisk and FDT, and bootm_find_other if required (!ret && (states
        & bootm_state_findother) {ret = Bootm_find_other (CMDTP, Flag, argc, argv); ARGC = 0;  /* Consume the args */}//* Here to note that the previous steps are to parse the uimage mirror and populate bootm_headers_t images */* that is, parsing uimage Part of this before/* and follow-up is to use the contents of bootm_headers_t images for subsequent actions */* Load the OS *///Determine if states need Bootm_st Ate_loados action, that is, the action of loading the operating system, call Bootm_load_os if required (!ret && (states & Bootm_state_loados)) {ULONG

        Load_end;
        Iflag = Bootm_disable_interrupts ();
        ret = Bootm_load_os (images, &load_end, 0); if (ret = = 0) lmb_reserve (&IMAGES->LMB, Images->os.load, (load_end-images->
        Os.load));
        else if (ret && ret! = bootm_err_overlap) goto ERR;
else if (ret = = bootm_err_overlap) ret = 0; #if defined (config_silent_console) &&!defined (config_silent_u_boot_only) if (Images->os.os = = Ih_os_li
NUX) Fixup_silent_linux (); #endif}//Whether you need to redirect the RAMDINSK,DO_BOOTM process is not required//relocate the RAMDisk */#ifdef Config_sys_boot_ramdisk_high if (!ret && (states & Bootm_state_ramdisk)) {Ulon

        G Rd_len = images->rd_end-images->rd_start; ret = Boot_ramdisk_high (&IMAGES->LMB, Images->rd_start, Rd_len, &images->initrd_start, &i
        Mages->initrd_end);
            if (!ret) {Setenv_hex ("Initrd_start", Images->initrd_start);
        Setenv_hex ("Initrd_end", images->initrd_end); }} #endif//If you need to redirect the FDT,DO_BOOTM process is not required #if IMAGE_ENABLE_OF_LIBFDT && defined (CONFIG_LMB) if ( !ret && (states & Bootm_state_fdt)) {boot_fdt_add_mem_rsv_regions (&IMAGES->LMB, Images->ft_
        addr);
    ret = BOOT_RELOCATE_FDT (&IMAGES->LMB, &images->ft_addr, &images->ft_len);

        } #endif/* from "on, we need the OS boot function */if (ret) return ret; Get the startup function for the corresponding operating system and store it in Boot_fn BooT_FN = Bootm_os_get_boot_func (Images->os.os);
            NEED_BOOT_FN = states & (Bootm_state_os_cmdline | bootm_state_os_bd_t |
            Bootm_state_os_prep | Bootm_state_os_fake_go |
    BOOTM_STATE_OS_GO);
        if (Boot_fn = = NULL && need_boot_fn) {if (Iflag) enable_interrupts (); printf ("Error:booting os '%s ' (%d) is not supported\n", Genimg_get_os_name (Images->os.os), Images->o
        S.os);
        Bootstage_error (Bootstage_id_check_boot_os);
    return 1; }/* Call various other states that is not generally used * * * if (!ret && (states & BOOTM_STATE_OS_CM
    dline)) ret = BOOT_FN (Bootm_state_os_cmdline, argc, argv, images);

        if (!ret && (states & bootm_state_os_bd_t)) ret = BOOT_FN (bootm_state_os_bd_t, argc, argv, images);
        The start function is called directly before jumping to the operating system, but the identity is bootm_state_os_prep if (!ret && (states & Bootm_state_os_prep)) ret = BOOT_FN (BOotm_state_os_prep, argc, argv, images); /* Check for UNSUPPORTED subcommand.
        */if (ret) {puts ("subcommand not supported\n");
    return ret; }//Bootm_state_os_go ID, jump to the operating system, and should not return the/* now run the os! We hope this doesn ' t return */if (!ret && (states & Bootm_state_os_go)) ret = Boot_selected_os (ar

    GC, argv, Bootm_state_os_go, images, BOOT_FN);

    /* Deal with any fallout */err:if (Iflag) enable_interrupts ();
    if (ret = = bootm_err_unimplemented) bootstage_error (Bootstage_id_decomp_unimpl);

    else if (ret = = Bootm_err_reset) do_reset (CMDTP, Flag, argc, argv);
return ret; }

The main use of the following several functions to achieve: Bootm_start bootm_find_os bootm_find_other bootm_load_os bootm_os_get_boot_func boot_fn (BOOTM_STATE _os_prep, argc, argv, images); Boot_selected_os Boot_selected_os (argc, argv, Bootm_state_os_go,images, BOOT_FN); 4, Bootm_start & Bootm_find_os & Bootm_find_other

Mainly responsible for parsing environment variables, parameters, Uimage, to populate bootm_headers_t images this data structure.
The ultimate goal is to implement these members in the bootm_headers_t images :

typedef struct BOOTM_HEADERS {
    image_info_t    os;     /* OS image Info */
    ulong       EP;     /* Entry point of OS */

    ulong       Rd_start, rd_end;/* ramdisk start/end */

    char        *ft_addr;   /* Flat dev Tree address */
    ulong       Ft_len;     /* Length of flat device tree */

    ulong       Initrd_start;
    ULONG       Initrd_end;
    ULONG       Cmdline_start;
    ULONG       Cmdline_end;
    bd_t        *kbd;
    int     verify;     /* GETENV ("verify") [0]! = ' n '/*
#ifdef CONFIG_LMB
    struct LMB  LMB;        /* For Memory MGMT */
#endif
}
Bootm_start
Implement verify and LMB Bootm_find_os
Implement OS and EP.
In other words, whether it is legacy-uimage or Fit-uimage, the final resolution is to get the two members.
In the "Uboot start kernel (three)--analysis of uimage kernel mirror," the specific description. Bootm_find_other
Implement Rd_start, Rd_end,ft_addr and Initrd_end.
In other words, whether it is legacy-uimage or Fit-uimage, the final resolution is to get the two members.
Put in "Uboot start Kernel (iv)--analysis Uimage FDT" and "Uboot start Kernel Chapter (v)-uimage RAMDisk" explained in detail. 5, Bootm_load_os

Briefly, in Bootm_load_os, the kernel image is load to the corresponding position, and if the kernel image is compressed by mkimage, it will be decompressed before load. (note here that compression and image compression Here are not the same as zimage, but rather uboot compression on the basis of image or zimage ... )

static int Bootm_load_os (bootm_headers_t *images, unsigned long *load_end,
             int boot_progress)
{
    Image_ info_t OS = images->os;
    ULONG load = os.load; Kernel The address to load is
    ulong Blob_start = Os.start;
    ULONG blob_end = os.end;
    ULONG Image_start = Os.image_start; Kernel the location of the actual presence of
    ulong Image_len = os.image_len;//Kernel length
    bool no_overlap;
    void *load_buf, *image_buf;
    int err;

    Load_buf = map_sysmem (load, 0);
    Image_buf = Map_sysmem (Os.image_start, Image_len);

Call Bootm_decomp_image, unzip the image_buf image, and load to load_buf
    err = bootm_decomp_image (os.comp, load, Os.image_ Start, Os.type,
                 load_buf, Image_buf, Image_len,
                 Config_sys_bootm_len, load_end);

As a result, the kernel image is load to the corresponding position after the above steps. 6, Bootm_os_get_boot_func

The Bootm_os_get_boot_func is used to obtain the startup function for the corresponding operating system and is stored in the BOOT_FN.
As follows:

int Do_bootm_states (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
            int states, bootm_headers_t *images, in T boot_progress)
{
...
    BOOT_FN = Bootm_os_get_boot_func (Images->os.os);
...
}

BOOT_OS_FN *bootm_os_get_boot_func (int os)
{
    return boot_os[os];
Get to the corresponding operation function according to the operating system type
}

static BOOT_OS_FN *boot_os[] = {
...
#ifdef config_bootm_linux
    [Ih_os_linux] = Do_bootm_linux,
#endif
}

As you can see, the core function that eventually starts Linux is do_bootm_linux.
Several other functions are eventually called to BOOT_FN, which corresponds to Linux, which is do_bootm_linux, so this is not explained here.
The following continues to explain the process of Do_bootm_linux five, Do_bootm_linux

Arch/arm/lib/bootm.c

int do_bootm_linux (int flag, int argc, char * const argv[], bootm_headers_t *images) { /* No need for those on ARM */if (flag & bootm_state_os_bd_t | | Flag & bootm_state_os_cmdline) r

        eturn-1; When flag is bootm_state_os_prep, it means that only the preparation action is required Boot_prep_linux if (flag & Bootm_state_os_prep) {Boot_prep_linux (
        images);
    return 0; }//When flag is bootm_state_os_go, it is only necessary to do a jump action if flag & (Bootm_state_os_go |
        Bootm_state_os_fake_go)) {Boot_jump_linux (images, flag);
    return 0; } boot_prep_linux (images); The global variable bootm_headers_t images is passed to Boot_prep_linux boot_jump_linux (images, flag);//global variable bootm_headers_t
Images is passed to Boot_jump_linux return 0 for the parameter; }

The boot_prep_linux is used to prepare the action before jumping to Linux.
Instead, Boot_jump_linux is used to jump to Linux.
is the global variable bootm_headers_t images as the parameter, so that you can directly get to the previous step of the kernel image, RAMDisk and FDT information. Boot_prep_linux
First of all, explain the concept of LMB. LMB refers to logical memory blocks, which is mainly used to represent the reserved area, mainly FDT area, RAMDisk area and so on.
The main purpose of Boot_prep_linux is to fix the LMB and fill the LMB into the FDT.
The implementation is as follows:

static void Boot_prep_linux (bootm_headers_t *images)
{
    char *commandline = getenv ("Bootargs");

    if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
#ifdef CONFIG_OF_LIBFDT
        Debug ("using:fdt\n");
        if (Image_setup_linux (images)) {
            printf ("FDT creation failed! Hanging ... ");
            Hang ();
        }
#endif
    }

There is no in-depth study of image_setup_linux, and so on after the need for further in-depth. Boot_jump_linux
Take arm as an example:
Arch/arm/lib/bootm.c

static void Boot_jump_linux (bootm_headers_t *images, int flag) {unsigned long Machid = gd->bd->bi_arch_number;
    Get Machine-id,machine-id from BD in the Uboot start-up process the article has described the Char *s; void (*kernel_entry) (int zero, int arch, uint params);
    The kernel entry function, or kernel's entry address, corresponds to the _start address of the kernel.
    unsigned long R2; int fake = (flag & Bootm_state_os_fake_go); 
         Pseudo jump, does not really jump to kernel in kernel_entry = (void (*) (int, int, uint)) images->ep; Set the kernel_entry to images in the EP (Kernel's entry address), followed by the direct execution of Kernel_entry also jumped to the kernel//here to pay attention to the method of this jump Debug ("# # TRANSFE
    Rring control to Linux (at address%08lx) "\" ... \ n ", (ULONG) kernel_entry);
    Bootstage_mark (Bootstage_id_run_os);

        Announce_and_cleanup (fake);  Place the IMAGES->FT_ADDR (FDT address) in the R2 register if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) r2 = (unsigned
    Long) images->ft_addr;

    else R2 = gd->bd->bi_boot_params; if (!fake) {kernel_entry (0, MachiD, R2);
        Here by calling Kernel_entry, you jump to the IMAGES->EP, that is, jump to kernel, specifically the kernel of the _start symbol address. Parameter 0 is passed into the R0 register, the parameter Machid is passed into the R1 register, the IMAGES->FT_ADDR (FDT address) is placed in the R2 Register//meets the hardware requirements of the kernel boot}}

Here, after Kernel_entry, we jump to the kernel environment. It is interesting to look at the kernel start-up process.

================================================================================
Kernel START process article
[Kernel START process]--vmlinux.lds analysis of the previous chapter
[Kernel Start process] (chapter I) overview
[Kernel Start Process] (chapter II) Phase one--setting up the SVC, shutting down interrupts
[Kernel Start Process] (chapter III) acquisition of the first stage of--proc info
[Kernel Start process] (fourth) verification of the first phase of the--DTB
[Kernel Start process] (fifth) phase one--creation of temporary kernel page table
[Kernel Start process] (sixth) Phase I-Open the MMU
[Kernel Start process] (seventh) stage one--jump to Start_kernel

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.