1. 程式人生 > >u-boot(四)命令實現

u-boot(四)命令實現

目錄


title: u-boot(四)命令實現
tags: linux
date: 2018-09-25 23:13:05
---

u-boot(四)命令實現

命令是如何實現的?

  1. 輸入命令
  2. 執行函式,根據命令去尋找函式

所以會有一個命令的結構體[name,fun]

分析run_command

函式原型如下 int run_command (const char *cmd, int flag)

  1. 處理, 空格,;

  2. 解析引數parse_line (finaltoken, argv)

    example: md.w 0 ------>argv[0]= "md.w", argv[1]=" 0"
    
    ​```
    /* Extract arguments */
    if ((argc = parse_line (finaltoken, argv)) == 0) {
        rc = -1; /* no command at all */
        continue;
    }
    ​```
  3. 命令搜尋if ((cmdtp = find_cmd(argv[0])) == NULL),可以發現結構體

    struct cmd_tbl_s {
     char        *name;      /* Command Name         */
     int     maxargs;    /* maximum number of arguments  */
     int     repeatable; /* autorepeat allowed?      */
                     /* Implementation function  */
     int     (*cmd)(struct cmd_tbl_s *, int, int, char *[]);
     char        *usage;     /* Usage message    (short) */
    #ifdef   CFG_LONGHELP
     char        *help;      /* Help  message    (long)  */
    #endif
    #ifdef CONFIG_AUTO_COMPLETE
     /* do auto completion on the arguments */
     int     (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
    #endif
    };
    • repeatable 可重複,指的是直接按回車是否繼續執行上次命令
    • usage,短的help,指的是直接輸入help檢視的所有命令顯示的幫助
    • help,具體的help,指的是help cmd 檢視的具體的資訊

    檢視函式,可以發現是在__u_boot_cmd_start__u_boot_cmd_end中遍歷,這個地址是在連結指令碼中定義的,也就是命令這個東西,有一個特殊的屬性,定位到某個地址.

     . = .;
     __u_boot_cmd_start = .;
     .u_boot_cmd : { *(.u_boot_cmd) }
     __u_boot_cmd_end = .;

    搜尋這個段屬性.u_boot_cmd,在include\command.h有這麼一個巨集

    #define Struct_Section  __attribute__ ((unused,section (".u_boot_cmd")))

    再搜尋下這個巨集

    #define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
    cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}

    再搜尋一下這個U_BOOT_CMD,可以發現其實就是命令了,搜尋下命令bootm,在common\cmd_bootm.c

    U_BOOT_CMD(
         bootm,  CFG_MAXARGS,    1,  do_bootm,
         "bootm   - boot application image from memory\n",//注意,下面的幾個是沒有逗號,是整體
         "[addr [arg ...]]\n    - boot application image stored in memory\n"
         "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
         "\t'arg' can be the address of an initrd image\n"
    );

    嘗試著展開這個巨集,可以發現就是定義了一個段屬性特殊的結構體,也就是命令結構體

    cmd_tbl_t  __u_boot_cmd_bootm  Struct_Section=
    {
        "bootm",
        CFG_MAXARGS,
        1,
        do_bootm,
        "bootm   - boot application image from memory\n",
        //下面的字串是一個整體
        "[addr [arg ...]]\n    - boot application image stored in memory\n"
         "\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
         "\t'arg' can be the address of an initrd image\n"
    }

小結

  1. U-boot 的命令是用結構體儲存的,這些結構體是用特殊的段屬性集合到一塊區域裡面去,分散在各個檔案中

  2. 命令解析的時候是去這個段去搜索的,這個段屬性的地址是從__u_boot_cmd_start__u_boot_cmd_end,在連結指令碼中定義的.

  3. 命令結構體

    struct cmd_tbl_s ;

自定義一個命令

參考common/cmd_bootm.c的標頭檔案,編寫原始碼cmd_hello.c

程式碼

#include <common.h>
#include <watchdog.h>
#include <command.h>
#include <image.h>
#include <malloc.h>
#include <zlib.h>
#include <bzlib.h>
#include <environment.h>
#include <asm/byteorder.h>
int do_hello (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
    int i ;
    printf ("hello world %d \n,", argc);
    //列印下引數
    for(i=0;i<argc;i++)
    {
        printf ("argv[%d] is %s \n",i,argv[i]);
    }
    return 0;
}

U_BOOT_CMD(
    hello,  CFG_MAXARGS,    1,  do_hello,
    "this is short help for hello  just test\n",
    "this is long help for hello  just test\n"
);

makefile

修改commonmakefile,只需要在COBJS上加上cmd_hello.o