多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內(nèi)最全I(xiàn)T社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > php開源 > 綜合技術(shù) > 函數(shù)main_loop和u-boot命令執(zhí)行

函數(shù)main_loop和u-boot命令執(zhí)行

來源:程序員人生   發(fā)布時(shí)間:2016-12-20 16:36:10 閱讀次數(shù):3783次
1.main_loop函數(shù)履行流程和命令解釋器
run_main_loop是board_r中函數(shù)運(yùn)行列表init_fnc_t init_sequence_r[]最后1個(gè)函數(shù),它又調(diào)用了main_loop,且run_main_loop永不返回。
static int run_main_loop(void) { /* main_loop() can return to retry autoboot, if so just run it again */ for (;;) main_loop(); return 0; }
main_loop定義在common/main.c中:
void main_loop(void) { const char *s; bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop"); modem_init(); #ifdef CONFIG_VERSION_VARIABLE setenv("ver", version_string); /* set version variable */ #endif /* CONFIG_VERSION_VARIABLE */ cli_init(); run_preboot_environment_command(); s = bootdelay_process(); if (cli_process_fdt(&s)) cli_secure_boot_cmd(s); autoboot_command(s); cli_loop(); }
bootstage_mark_name函數(shù)調(diào)用了show_boot_progress,利用它顯示啟動進(jìn)程(progress),此處為空函數(shù)。
setenv設(shè)置環(huán)境變量ver為version_string,后者在common/cmd_version.c中定義為:
const char __weak version_string[] = U_BOOT_VERSION_STRING;

U_BOOT_VERSION_STRING在version.h中定義為:

#define U_BOOT_VERSION_STRING U_BOOT_VERSION " (" U_BOOT_DATE " - " \ U_BOOT_TIME " " U_BOOT_TZ ")" CONFIG_IDENT_STRING
其中U_BOOT_VERSION ,U_BOOT_DATE,U_BOOT_TIME,U_BOOT_TZ均由u-boot構(gòu)建系統(tǒng)自動產(chǎn)生,
它們分別代表u-boot版本號,編譯日期和時(shí)間,和時(shí)間區(qū)。
如果定義了CONFIG_SYS_HUSH_PARSER,那末配置u-boot使用hush shell來作為履行器。hush shell是1種輕量型的shell。
cli_init用來初始化hush shell使用的1些變量。hush shell的實(shí)現(xiàn)機(jī)制比較復(fù)雜,以下的hush shell相干實(shí)現(xiàn)代碼都不做詳實(shí)跟蹤分析。
有興趣的可參見源代碼和相干的網(wǎng)絡(luò)文章。

run_preboot_environment_command函數(shù)從環(huán)境變量中獲得"preboot"的定義,該變量包括了1些預(yù)啟動命令,
1般環(huán)境變量中不包括該項(xiàng)配置。
bootdelay_process從環(huán)境變量中取出"bootdelay"和"bootcmd"的配置值,將取出的"bootdelay"配置值轉(zhuǎn)換成整數(shù),
賦值給全局變量stored_bootdelay,最后返回"bootcmd"的配置值。bootdelay為u-boot的啟動延時(shí)計(jì)數(shù)值,計(jì)數(shù)期間內(nèi)
如無用戶按鍵輸入干預(yù),那末將履行"bootcmd"配置中的命令。
由于沒有定義CONFIG_OF_CONTROL,函數(shù)cli_process_fdt返回false,接下來履行autoboot_command,
該函數(shù)在common/autoboot.c中實(shí)現(xiàn):

void autoboot_command(const char *s) { if (stored_bootdelay != ⑴ && s && !abortboot(stored_bootdelay)) { run_command_list(s, ⑴, 0); } }
全局變量stored_bootdelay在上面已做說明。靜態(tài)函數(shù)abortboot中包括了CONFIG_AUTOBOOT_KEYED宏預(yù)處理分支,該宏定義用來使能用戶名密碼登錄,這里它沒有定義,而后調(diào)用了abortboot_normal,在履行的時(shí)間stored_bootdelay(秒)內(nèi),如無用戶按鍵輸入干預(yù),那末abortboot_normal函數(shù)將返回0,否則返回1。 當(dāng)無用戶按鍵干預(yù)時(shí),接下來將調(diào)用run_command_list履行上述從環(huán)境變量中讀取的"bootcmd"配置值。注意該函數(shù)的參數(shù)s。run_command_list中調(diào)用了hush shell的命令解釋器(parse_stream_outer函數(shù)),解釋bootcmd中的啟動命令。環(huán)境變量bootcmd中的啟動命令,用來設(shè)置linux必要的啟動環(huán)境,然后加載和啟動linux內(nèi)核。u-boot啟動linux內(nèi)核后,將控制權(quán)交給linux內(nèi)核,至此不再返回。
如用戶在設(shè)定的bootdelay內(nèi)無按鍵輸入,那末將運(yùn)行cli_loop履行hush shell命令解釋器:
void cli_loop(void) { parse_file_outer(); /* This point is never reached */ for (;;); }
parse_file_outer進(jìn)行必要的初始化后,也將調(diào)用hush shell的命令解釋器,即parse_stream_outer函數(shù):
static int parse_stream_outer(structin_str*inp,intflag) { do { ... ... run_list(...); } while (rcode != ⑴ && !(flag & FLAG_EXIT_FROM_LOOP) && //#define FLAG_EXIT_FROM_LOOP 1 (inp->peek != static_peek || b_peek(inp))); }
上面的do-while會循環(huán)命令解析器的"命令輸入解析--履行"運(yùn)行模式。
其中的函數(shù)run_list履行以下的函數(shù)調(diào)用流程:
run_list-->run_list_real-->run_pipe_real
最后在函數(shù)run_pipe_real中有:
return cmd_process(...);
函數(shù)cmd_process最后完成u-boot命令的定位和履行。
2.u-boot命令履行
命令處理函數(shù)均在common/command.c中實(shí)現(xiàn),上述函數(shù)cmd_process定義以下:
enum command_ret_t cmd_process(int flag, int argc, char * const argv[], int *repeatable, ulong *ticks) { enum command_ret_t rc = CMD_RET_SUCCESS; cmd_tbl_t *cmdtp; /* Look up command in command table */ cmdtp = find_cmd(argv[0]); if (cmdtp == NULL) { printf("Unknown command '%s' - try 'help'\n", argv[0]); return 1; } /* found - check max args */ if (argc > cmdtp->maxargs) rc = CMD_RET_USAGE; /* If OK so far, then do the command */ if (!rc) { if (ticks) *ticks = get_timer(0); rc = cmd_call(cmdtp, flag, argc, argv); if (ticks) *ticks = get_timer(*ticks); *repeatable &= cmdtp->repeatable; } if (rc == CMD_RET_USAGE) rc = cmd_usage(cmdtp); return rc; }
u-boot中使用宏U_BOOT_CMD來定義命令,該宏在include/command.h中定義以下:
#define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help) \ U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL)
U_BOOT_CMD是宏U_BOOT_CMD_COMPLETE最后1個(gè)參數(shù)_comp為NULL的特例,_comp表示變量是不是自動完成:
#define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp) \ ll_entry_declare(cmd_tbl_t, _name, cmd) = \ /*注意這里是cmd而非_cmd*/ U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \ _usage, _help, _comp);
其中包括的宏U_BOOT_CMD_MKENT_COMPLETE定義為:
#define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \ _usage, _help, _comp) \ { #_name, _maxargs, _rep, _cmd, _usage, \ _CMD_HELP(_help) _CMD_COMPLETE(_comp) }

上面的_CMD_HELP根據(jù)配置可選為使用完全或簡短幫助說明。_CMD_COMPLETE則根據(jù)配置決定是不是使用自動完成函數(shù)。U_BOOT_CMD_MKENT_COMPLETE宏實(shí)際上是組織輸入?yún)?shù),對ll_entry_declare進(jìn)行數(shù)據(jù)填充。ll_entry_declare在文件include/linker_lists.h中定義:

#define ll_entry_declare(_type, _name, _list) \ _type _u_boot_list_2_##_list##_2_##_name __aligned(4) \ __attribute__((unused, \ section(".u_boot_list_2_"#_list"_2_"#_name)))
參數(shù)_type為cmd_tbl_t,這里定義1個(gè)cmd_tbl_t結(jié)構(gòu)體,并把它放在符號段.u_boot_list_2_"#_list"_2_"#_name中,其中的_list和_name根據(jù)宏參數(shù)進(jìn)行字符串替換。
下面,我們舉例說明上述宏的實(shí)現(xiàn)機(jī)制。比如有以下的定義:
U_BOOT_CMD( env, CONFIG_SYS_MAXARGS, 1, do_env, "environment handling commands", env_help_text );

U_BOOT_CMD_COMPLETE ( env, CONFIG_SYS_MAXARGS, 1, do_env, "environment handling commands", env_help_text,NULL );
帶入宏參及其展開為 :
U_BOOT_CMD_COMPLETE(env, CONFIG_SYS_MAXARGS , 1, do_env , "environment handling commands" , env_help_text , NULL ) \ ll_entry_declare(cmd_tbl_t, env , cmd) = \ U_BOOT_CMD_MKENT_COMPLETE(env , CONFIG_SYS_MAXARGS , 1, do_env , "environment handling commands" , env_help_text , NULL);
其中的ll_entry_declare帶入宏參及其展開為 :
ll_entry_declare(cmd_tbl_t , env , cmd ) \ cmd_tbl_t _u_boot_list_2_cmd_2_env __aligned(4) \ __attribute__((unused, \ section(".u_boot_list_2_cmd_2_env )))
其中的U_BOOT_CMD_MKENT_COMPLETE帶入宏參及其展開為:
U_BOOT_CMD_MKENT_COMPLETE(env , CONFIG_SYS_MAXARGS , 1, do_env , _usage, _help, _comp) \ { "env", CONFIG_SYS_MAXARGS , 1, do_env , "environment handling commands" , env_help_text ,NULL}
那末上述U_BOOT_CMD_COMPLETE終究展開為:
cmd_tbl_t _u_boot_list_2_cmd_2_env __aligned(4) \ __attribute__((unused, section(".u_boot_list_2_cmd_2_env ))) = { "env", CONFIG_SYS_MAXARGS , 1, do_env , "environment handling commands" , env_help_text ,NULL}
其中的cmd_tbl_t定義為:
<pre code_snippet_id="1890747" snippet_file_name="blog_20160921_20_3676404" name="code" class="cpp">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 * const []); char *usage; /* Usage message (short) */ #ifdef CONFIG_SYS_LONGHELP char *help; /* Help message (long) */ #endif #ifdef CONFIG_AUTO_COMPLETE /* do auto completion on the arguments */ int (*complete)(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]); #endif };
typedef struct cmd_tbl_s    cmd_tbl_t;

該結(jié)構(gòu)體包括了命令名,命令實(shí)現(xiàn)函數(shù),命令使用簡短說明usage的輸出字符串,幫助回調(diào)函數(shù),參數(shù)變量自動完成函數(shù)等。u-boot使用該結(jié)構(gòu)體來描寫1個(gè)完全的命令。

U_BOOT_CMD_COMPLETE宏用來定義1個(gè)cmd_tbl_t結(jié)構(gòu)體變量,初始化該結(jié)構(gòu)體中的相應(yīng)成員,并把該結(jié)構(gòu)體變量寄存在4字節(jié)對齊的.u_boot_list_2_cmd_2_env符號段中。如前所述,宏U_BOOT_CMD將最后1個(gè)參數(shù)_comp置為NULL,對U_BOOT_CMD_COMPLETE做了進(jìn)1步的封裝。所有使用U_BOOT_CMD和U_BOOT_CMD_COMPLETE定義的命令最后都集中放在以.u_boot_list_2_cmd_2開頭的符號段中。即.u_boot_list_2_cmd_2_##name,這里的name是命令名。

我們回到函數(shù)上述的命令處理函數(shù)cmd_process,被其調(diào)用的find_cmd將根據(jù)命令名查找相應(yīng)的cmd_tbl_t變量符號段,其實(shí)現(xiàn)以下:

cmd_tbl_t *find_cmd(const char *cmd) { cmd_tbl_t *start = ll_entry_start(cmd_tbl_t, cmd); const int len = ll_entry_count(cmd_tbl_t, cmd); return find_cmd_tbl(cmd, start, len); }
ll_entry_start定義以下:
#define ll_entry_start(_type, _list) \ ({ \ static char start[0] __aligned(4) __attribute__((unused, \ section(".u_boot_list_2_"#_list"_1"))); \ (_type *)&start; \ })
那末,在上述函數(shù)find_cmd中,語句  
cmd_tbl_t *start = ll_entry_start(cmd_tbl_t, cmd);
定義1個(gè)包括0個(gè)字節(jié)的數(shù)組start[0],且把它放在.u_boot_cmd_2_list_1段中,該段屬性為unsued。注意在u-boot.lds中有:
.u_boot_list : { KEEP(*(SORT(.u_boot_list*)));
.u_boot_list中所有符號是按字符表的前后順序排列的,.u_boot_list_2_list_1會放在所有使用U_BOOT_CMD和U_BOOT_CMD_COMPLETE
定義的符號段的最前面,即.u_boot_cmd_2_list_1為以.u_boot_list_2_cmd_2開頭的符號段中的第1個(gè)。它定義為0個(gè)字節(jié)的數(shù)組start[0],
編譯器其實(shí)不為它分配存儲空間,那末它將指向以.u_boot_list_2_cmd_2開頭的符號段中的第1個(gè)符號。
同理ll_entry_end用end[0]來標(biāo)識.u_boot_list_2_cmd_2_xxx段的結(jié)尾,接下來的函數(shù)ll_entry_count返回的就是start - end的值,
即符號段.u_boot_list_2_cmd_2_xxx總字節(jié)長度。然后調(diào)用find_cmd_tbl,根據(jù)傳入的.u_boot_list_2_cmd_2_xxx段的首地址和
函數(shù)ll_entry_count 返回的長度,根據(jù)命令名查找相應(yīng)的符號段,即相命令對應(yīng)的cmd_tbl_t結(jié)構(gòu)體變量,然后返回該結(jié)構(gòu)體指針。
find_cmd_tbl的實(shí)現(xiàn)以下:
cmd_tbl_t *find_cmd_tbl(const char *cmd, cmd_tbl_t *table, int table_len) { cmd_tbl_t *cmdtp; cmd_tbl_t *cmdtp_temp = table; /* Init value */ const char *p; int len; int n_found = 0; if (!cmd) return NULL; len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd); for (cmdtp = table; cmdtp != table + table_len; cmdtp++) { if (strncmp(cmd, cmdtp->name, len) == 0) { if (len == strlen(cmdtp->name)) return cmdtp; /* full match */ cmdtp_temp = cmdtp; /* abbreviated command ? */ n_found++; } } if (n_found == 1) { /* exactly one match */ return cmdtp_temp; } return NULL; /* not found or ambiguous command */ }
查找到命令名對應(yīng)的cmd_tbl_t結(jié)構(gòu)體變量后,cmd_process接下來將調(diào)用函數(shù)cmd_call履行cmd_tbl_t中的命令。
cmd_process中相應(yīng)的代碼段以下:
if (!rc) { if (ticks) *ticks = get_timer(0); rc = cmd_call(cmdtp, flag, argc, argv); if (ticks) *ticks = get_timer(*ticks); *repeatable &= cmdtp->repeatable; } if (rc == CMD_RET_USAGE) rc = cmd_usage(cmdtp);
變量ticks用來記錄命令的履行時(shí)間,repeatable為命令是不是自動重復(fù)履行標(biāo)志。這兩個(gè)變量都將返回到上層的調(diào)用函數(shù)。
函數(shù)cmd_call利用傳入的參數(shù),直接調(diào)用cmdtp->cmd,即:
 (cmdtp->cmd)(cmdtp, flag, argc, argv);
最后,如果命令履行的返回值為CMD_RET_USAGE,代表命令履行出錯(cuò),且置標(biāo)CMD_RET_USAGE ,那末將調(diào)用cmd_usage,
輸出簡短的命令使用幫助信息。cmd_usage實(shí)現(xiàn)以下:
int cmd_usage(const cmd_tbl_t *cmdtp) { printf("%s - %s\n\n", cmdtp->name, cmdtp->usage); #ifdef CONFIG_SYS_LONGHELP printf("Usage:\n%s ", cmdtp->name); if (!cmdtp->help) { puts ("- No additional help available.\n"); return 1; } puts(cmdtp->help); putc('\n'); #endif /* CONFIG_SYS_LONGHELP */ return 1; }
3.u-boot中的子命令
部份u-boot的命令包括子命令,如env命令,它由子命令save,set,edit等組成。類似的還有sf命令。這些主命令履行時(shí)必須指定子命令。
u-boot中子命令的實(shí)現(xiàn)不再使用上面的gcc關(guān)鍵字section來指定段,只是直接定義了1個(gè)cmd_tbl_t表,并使用子命令及其運(yùn)行參數(shù)初始化該表。對上述討論中使用U_BOOT_CMD定義的命令,它們是散放在文件各處的,很難用1個(gè)全局的cmd_tbl_t表將這些命令統(tǒng)1定義初始化。而子命令不同,它只定義在1個(gè)或少許文件中,該cmd_tbl_t表為static類型,可以在定義時(shí)直接填充。固然,主命令還是由宏U_BOOT_CMD來定義引入。

生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 欧美v片| jizz18免费视频| 2019国内精品久久久久久 | 亚洲综合色网站 | 男女爽爽无遮挡午夜视频在线观看 | 国产呦合第一系 | 九九精品视频在线播放8 | 精品中文字幕在线 | 免费女人18毛片a级毛片视频 | 最新中文字幕免费视频 | 成人污片 | 欧美色图一区二区 | 日本中文在线视频 | 亚洲国产精品日韩一线满 | 久久伊人成人 | 色猫咪av在线网址 | 欧美亚洲日本在线 | 五月婷婷视频 | 亚洲国产精品a一区二区三区 | 色午夜日本高清视频www | 羞羞视频免费网站入口 | 国产精品爱久久久久久久 | 手机福利视频一区二区 | 欧美高清一级 | 成人欧美一区二区三区 | 成人精品一区二区不卡视频 | 劲爆欧美精品13页 | 国产91久久精品 | 成人精品一区二区三区中文字幕 | 综合亚洲色图 | 一区二区三区毛片免费 | 免费xxx视频 | 欧美成人免费大片888 | 久久精品国产一区 | 男人和女人全黄一级毛片 | 播放个毛片看看 | 国产精品一区二区三区免费视频 | 欧美人成人亚洲专区中文字幕 | 性色aⅴ闺蜜一区二区三区 性色aⅴ在线观看swag | 69久久 | 波多野结衣与公中出中文字幕 |