u-boot源碼分析 --- 啓動第二階段005

接下來我們主要分析main_loop()

common/main.c:

void main_loop (void)

{

#ifndef CFG_HUSH_PARSER

    static char lastcommand[CFG_CBSIZE] = { 0, };

    int len;

    int rc = 1;

    int flag;

#endif

 

#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)

    char *s;

    int bootdelay;

#endif

#ifdef CONFIG_PREBOOT

    char *p;

#endif

#ifdef CONFIG_BOOTCOUNT_LIMIT

    unsigned long bootcount = 0;

    unsigned long bootlimit = 0;

    char *bcs;

    char bcs_set[16];

#endif /* CONFIG_BOOTCOUNT_LIMIT */

 

#if defined(CONFIG_VFD) && defined(VFD_TEST_LOGO)   /*smdk2410沒定義*/

    ulong bmp = 0;     /* default bitmap */

    extern int trab_vfd (ulong bitmap);

 

#ifdef CONFIG_MODEM_SUPPORT

    if (do_mdm_init)

        bmp = 1;    /* alternate bitmap */

#endif

    trab_vfd (bmp);

#endif  /* CONFIG_VFD && VFD_TEST_LOGO */

 

#ifdef CONFIG_BOOTCOUNT_LIMIT   /*smdk2410沒定義*/

    bootcount = bootcount_load();

    bootcount++;

    bootcount_store (bootcount);

    sprintf (bcs_set, "%lu", bootcount);

    setenv ("bootcount", bcs_set);

    bcs = getenv ("bootlimit");

    bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0;

#endif /* CONFIG_BOOTCOUNT_LIMIT */

 

#ifdef CONFIG_MODEM_SUPPORT /*smdk2410沒定義*/

    debug ("DEBUG: main_loop:   do_mdm_init=%d/n", do_mdm_init);

    if (do_mdm_init) {

        uchar *str = strdup(getenv("mdm_cmd"));

        setenv ("preboot", str);  /* set or delete definition */

        if (str != NULL)

            free (str);

        mdm_init(); /* wait for modem connection */

    }

#endif  /* CONFIG_MODEM_SUPPORT */

 

#ifdef CONFIG_VERSION_VARIABLE /*smdk2410沒定義*/

    {

        extern char version_string[];

 

        setenv ("ver", version_string);  /* set version variable */

    }

#endif /* CONFIG_VERSION_VARIABLE */

 

#ifdef CFG_HUSH_PARSER /*smdk2410沒定義*/

    u_boot_hush_start ();

#endif

 

#ifdef CONFIG_AUTO_COMPLETE /*smdk2410沒定義*/

    install_auto_complete();

#endif

 

#ifdef CONFIG_PREBOOT /*smdk2410沒定義*/

    if ((p = getenv ("preboot")) != NULL) {

# ifdef CONFIG_AUTOBOOT_KEYED /*smdk2410沒定義*/

        int prev = disable_ctrlc(1);   /* disable Control C checking */

# endif

 

# ifndef CFG_HUSH_PARSER /*smdk2410沒定義*/

        run_command (p, 0);

# else

        parse_string_outer(p, FLAG_PARSE_SEMICOLON |

                    FLAG_EXIT_FROM_LOOP);

# endif

 

# ifdef CONFIG_AUTOBOOT_KEYED /*smdk2410沒定義*/

        disable_ctrlc(prev);   /* restore Control C checking */

# endif

    }

#endif /* CONFIG_PREBOOT */

 

/**/

#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)

    s = getenv ("bootdelay");

    bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;

 

    debug ("### main_loop entered: bootdelay=%d/n/n", bootdelay);

 

# ifdef CONFIG_BOOT_RETRY_TIME

    init_cmd_timeout ();

# endif /* CONFIG_BOOT_RETRY_TIME */

 

#ifdef CONFIG_BOOTCOUNT_LIMIT

    if (bootlimit && (bootcount > bootlimit)) {

        printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd./n",

                (unsigned)bootlimit);

        s = getenv ("altbootcmd");

    }

    else

#endif /* CONFIG_BOOTCOUNT_LIMIT */

        s = getenv ("bootcmd");  /*smdk2410下這個環境變量是空的*/

 

    debug ("### main_loop: bootcmd=/"%s/"/n", s ? s : "<UNDEFINED>");

 

    if (bootdelay >= 0 && s && !abortboot (bootdelay)) {

# ifdef CONFIG_AUTOBOOT_KEYED

        int prev = disable_ctrlc(1);   /* disable Control C checking */

# endif

 

# ifndef CFG_HUSH_PARSER

        run_command (s, 0);

# else

        parse_string_outer(s, FLAG_PARSE_SEMICOLON |

                    FLAG_EXIT_FROM_LOOP);

# endif

 

# ifdef CONFIG_AUTOBOOT_KEYED

        disable_ctrlc(prev);   /* restore Control C checking */

# endif

    }

 

# ifdef CONFIG_MENUKEY

    if (menukey == CONFIG_MENUKEY) {

        s = getenv("menucmd");

        if (s) {

# ifndef CFG_HUSH_PARSER

        run_command (s, 0);

# else

        parse_string_outer(s, FLAG_PARSE_SEMICOLON |

                    FLAG_EXIT_FROM_LOOP);

# endif

        }

    }

#endif /* CONFIG_MENUKEY */

#endif  /* CONFIG_BOOTDELAY */

 

#ifdef CONFIG_AMIGAONEG3SE

    {

        extern void video_banner(void);

        video_banner();

    }

#endif

 

    /*

     * Main Loop for Monitor Command Processing

     */

     /*

      * 最核心的就是下面這個死循環了

      */

#ifdef CFG_HUSH_PARSER

    parse_file_outer();

    /* This point is never reached */

    for (;;);

#else

    for (;;) {

#ifdef CONFIG_BOOT_RETRY_TIME

        if (rc >= 0) {

            /* Saw enough of a valid command to

             * restart the timeout.

             */

            reset_cmd_timeout();

        }

#endif

        len = readline (CFG_PROMPT);

 

        flag = 0;   /* assume no special flags for now */

        if (len > 0)

            strcpy (lastcommand, console_buffer);

        else if (len == 0)

            flag |= CMD_FLAG_REPEAT;

#ifdef CONFIG_BOOT_RETRY_TIME

        else if (len == -2) {

            /* -2 means timed out, retry autoboot

             */

            puts ("/nTimed out waiting for command/n");

# ifdef CONFIG_RESET_TO_RETRY

            /* Reinit board to run initialization code again */

            do_reset (NULL, 0, 0, NULL);

# else

            return;     /* retry autoboot */

# endif

        }

#endif

 

        if (len == -1)

            puts ("<INTERRUPT>/n");

        else

            rc = run_command (lastcommand, flag);

 

        if (rc <= 0) {

            /* invalid command or not repeatable, forget it */

            lastcommand[0] = 0;

        }

    }

#endif /*CFG_HUSH_PARSER*/

}

該函數比較長,但核心就是不停的從串口獲取命令並解析執行此命令, 這個功能就在函數尾部的那個死循環裏, 我們重點就是分析這個循環。

 

先看readline()

common/main.c:

/****************************************************************************/

/*

 * Prompt for input and read a line.

 * If  CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0,

 * time out when time goes past endtime (timebase time in ticks).

 * Return:  number of read characters

 *      -1 if break

 *      -2 if timed out

 * 上面的註釋說的很清楚了,就是提示用戶輸入命令,並讀取這個命令

*/

int readline (const char *const prompt)

{

    char   *p = console_buffer;   /* console_buffer 是個全局變量*/

    int n = 0;             /* buffer index    */

    int plen = 0;          /* prompt length   */

    int col;               /* output column cnt   */

    char    c;

 

    /* print prompt */

    if (prompt) { /*如果要輸出提示符,則輸出*/

        plen = strlen (prompt);

        puts (prompt);  //前面分析過了

    }

    col = plen;

 

    for (;;) {

#ifdef CONFIG_BOOT_RETRY_TIME  /*sdmk2410沒定義*/

        while (!tstc()) {  /* while no incoming data */

            if (retry_time >= 0 && get_ticks() > endtime)

                return (-2);    /* timed out */

        }

#endif

        WATCHDOG_RESET();      /* Trigger watchdog, if needed */

 

#ifdef CONFIG_SHOW_ACTIVITY /*sdmk2410沒定義*/

        while (!tstc()) {

            extern void show_activity(int arg);

            show_activity(0);

        }

#endif

        c = getc();  /*從串口獲取用戶輸入的命令*/

 

        /*

         * Special character handling

         */

        /*下面這個switch就是處理不同的字符了*/

        switch (c) {

        case '/r':             /* Enter        */

        case '/n':

            *p = '/0';

            puts ("/r/n");

            return (p - console_buffer);  /*輸入結束*/

 

        case '/0':             /* nul          */  /*忽略,繼續*/

            continue;

 

        case 0x03:             /* ^C - break*//*呵呵,linux下的ctrl+c功能*/

            console_buffer[0] = '/0';  /* discard input */

            return (-1);

 

        case 0x15:             /* ^U - erase line */ /*刪除*/

            while (col > plen) {

                puts (erase_seq);

                --col;

            }

            p = console_buffer;

            n = 0;

            continue;

 

        case 0x17:             /* ^W - erase word *//*刪除*/

            p=delete_char(console_buffer, p, &col, &n, plen);

            while ((n > 0) && (*p != ' ')) {

                p=delete_char(console_buffer, p, &col, &n, plen);

            }

            continue;

 

        case 0x08:             /* ^H  - backspace */

        case 0x7F:             /* DEL - backspace */

            p=delete_char(console_buffer, p, &col, &n, plen);/*刪除*/

            continue;

 

        default:   /*獲取常規字符*/

            /*

             * Must be a normal character then

             */

            if (n < CFG_CBSIZE-2) {

                if (c == '/t') {   /* expand TABs     */

#ifdef CONFIG_AUTO_COMPLETE

                   /* if auto completion triggered just continue */

                    /*自動補全功能,熟悉linux的肯定知道*/

                   *p = '/0';

                   if (cmd_auto_complete(prompt, console_buffer, &n, &col)) {

                       p = console_buffer + n; /* reset */

                       continue;

                   }

#endif

                   puts (tab_seq+(col&07));

                   col += 8 - (col&07);

                } else {

                    ++col;      /* echo input      */

                   putc (c);

                }

                *p++ = c;/*把字符保存在buffer中*/

                ++n;

            } else {           /* Buffer full     */

                putc ('/a');

            }

        }

    }

}

上面這個函數就是提示用戶輸入,然後一直等待用戶輸入,指到用戶輸入完成, 然後獲取用戶數據,並存入全局變量console_buffer中。

 

再來回顧下那個for循環

common/main.c:

void main_loop (void)

{

……

#ifdef CFG_HUSH_PARSER

    parse_file_outer();

    /* This point is never reached */

    for (;;);

#else

    for (;;) {

#ifdef CONFIG_BOOT_RETRY_TIME

        if (rc >= 0) {

            /* Saw enough of a valid command to

             * restart the timeout.

             */

            reset_cmd_timeout();

        }

#endif

        len = readline (CFG_PROMPT); /*獲取用戶下的command*/

 

        flag = 0;   /* assume no special flags for now */

        if (len > 0)

            strcpy (lastcommand, console_buffer);  /*把command存入lastcommand中*/

        else if (len == 0)

            flag |= CMD_FLAG_REPEAT;

#ifdef CONFIG_BOOT_RETRY_TIME

        else if (len == -2) {

            /* -2 means timed out, retry autoboot

             */

            puts ("/nTimed out waiting for command/n");

# ifdef CONFIG_RESET_TO_RETRY

            /* Reinit board to run initialization code again */

            do_reset (NULL, 0, 0, NULL);

# else

            return;     /* retry autoboot */

# endif

        }

#endif

 

        if (len == -1)

            puts ("<INTERRUPT>/n");

        else

            rc = run_command (lastcommand, flag); /*執行command*/

 

        if (rc <= 0) {

            /* invalid command or not repeatable, forget it */

            lastcommand[0] = 0;

        }

    }

#endif /*CFG_HUSH_PARSER*/

}

OK!核心中的核心就是run_command函數了,一猜就知道是用戶執行所有用戶下達命令的函數。Let’s go


轉自http://blog.csdn.net/aaronychen/article/details/2815040

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章