日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Uboot 命令是如何被使用的?

發布時間:2023/11/30 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Uboot 命令是如何被使用的? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

有什么問題請 發郵件至syyxy@outlook.com, 歡迎交流~??

?

在uboot代碼中命令的模式是這個樣子:

?

?

?

這樣是如何和命令行交互的呢?

?

在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(

???????? md,? 3,????? 1,????? do_mem_md,

???????? "memory display",

???????? "[.b, .w, .l] address [# of objects]"

);

?被define成了:

U_BOOT_CMD_COMPLETE(

???????? md,? 3,????? 1,????? do_mem_md,

???????? "memory display",

???????? "[.b, .w, .l] address [# of objects]",NULL

);

?

繼續:

?

#define U_BOOT_CMD_COMPLETE(name,maxargs,rep,cmd,usage,help,comp) \

???????? cmd_tbl_t __u_boot_cmd_##name Struct_Section = \

?????????????????? U_BOOT_CMD_MKENT_COMPLETE(name,maxargs,rep,cmd,usage,help,comp)

?

其中,##name 意思是 使用 name 替換 ##name

?

由此可見,上述被define成了:

cmd_tbl_t? ?__u_boot_cmd_md? Struct_Section = \

U_BOOT_CMD_MKENT_COMPLETE(md,????? 3,????? 1,????? do_mem_md, "memory display","[.b, .w, .l] address [# of objects]",NULL);

?

?

繼續:

?

#define U_BOOT_CMD_MKENT_COMPLETE(name,maxargs,rep,cmd,usage,help,comp) \

?

???????? {#name, maxargs, rep, cmd, usage, _CMD_HELP(help) _CMD_COMPLETE(comp)}

?

?

?

其中,#的作用是字符串化,意思是將 name 轉化成一個字符串。

?

具體## 和 # 請參閱如下文檔。

?

https://wenku.baidu.com/view/56ed000216fc700abb68fcdd.html

?

?

?

可以看到,U_BOOT_CMD_MKENT_COMPLETE(md,???????? 3,????? 1,????? do_mem_md, "memory display","[.b, .w, .l] address [# of objects]"); ??被define成了

{“md”, 3, 1, do_mem_md, "memory display", _CMD_HELP("[.b, .w, .l] address [# of objects]")? ?_CMD_COMPLETE(NULL)}

?

因此 U_BOOT_CMD_COMPLETE被定義成了:

cmd_tbl_t? ?__u_boot_cmd_md? Struct_Section = \

{

“md”,

?3,

1,

?do_mem_md,

?"memory display",

?_CMD_HELP("[.b, .w, .l] address [# of objects]")? _CMD_COMPLETE(NULL)

}

?

繼續:

由于 #define Struct_Section? __attribute__((unused, section(".u_boot_cmd"), aligned(4))),而

# define _CMD_COMPLETE(x)? ?x,

# define _CMD_HELP(x)? ?x,

(注意最后都有一個逗號) , 因此 上述被定義成了

cmd_tbl_t ?__u_boot_cmd_md ?__attribute__((unused, section(".u_boot_cmd"), aligned(4))) =

{

“md”,

?3,

1,

?do_mem_md,

?"memory display",

?"[.b, .w, .l] address [# of objects]",

?NULL

}

上述是我們的分析,接下來?通過將cmd_mem.c 預編譯得到

cmd_tbl_t __u_boot_cmd_md __attribute__((unused, section(".u_boot_cmd"), aligned(4))) =

{"md",

?3,

?1,

do_mem_md,

?"memory display",

"[.b, .w, .l] address [# of objects]",

((void *)0),};

完全一致,因此上述分析正確。

=================================我是分割線===================================

?

接下來第二步,這些命令是如何被使用的?

首先分析我們在第一步得到的結構體:

?

cmd_tbl_t __u_boot_cmd_md ?__attribute__((unused, section(".u_boot_cmd"), aligned(4))) =

{"md",

?3,

?1,

do_mem_md,

?"memory display",

"[.b, .w, .l] address [# of objects]",

((void *)0),};

?

__attribute__((unused, section(".u_boot_cmd"), aligned(4))) 說明,將這個結構體放到 .u_boot_cmd 段中,該段4字節對其,unused 代表 告訴編譯器 該函數或者變量可能不使用,GGC不要對其報警告。

請注意, 這里是將該結構體放到編譯出來的.o 文件的 .u_boot_cmd段,? ?沒有放到輸出文件的.u_boot_cmd。當鏈接的時候才能放到 輸出文件的?.u_boot_cmd段。

我們知道 GCC 默認的段中沒有 .u_boot_cmd 這個段,那么就要手動創建這個段。Uboot通過鏈接腳本創建的這個段, 圖片截取自u-boot.lds

?

?

?

既然說在會將指令放到 .u_boot_cmd 這個段,那么能不能證明呢?

以瀾起平臺為例,找到生成的中間文件 u-boot 通過objdump –t 找到symbol table 然后 grep 出u_boot_cmd使用如下指令,

/opt/Montage-tech/mips-4.3/bin/mips-linux-gnu-objdump -t u-boot |grep u_boot_cmd >~/u-boot.txt 可以得到 如下cmd , 其中加紅 的是我們上述 md 命令 :8017964c l d .u_boot_cmd 00000000 .u_boot_cmd80179b70 g O .u_boot_cmd 0000001c __u_boot_cmd_nf80179b1c g O .u_boot_cmd 0000001c __u_boot_cmd_macmode801799e8 g O .u_boot_cmd 0000001c __u_boot_cmd_cpu80179dbc g O .u_boot_cmd 0000001c __u_boot_cmd_freeze_with_dioff80179c6c g O .u_boot_cmd 0000001c __u_boot_cmd_sspi80179a90 g O .u_boot_cmd 0000001c __u_boot_cmd_macinit8017964c g O .u_boot_cmd 0000001c __u_boot_cmd_runapp801798d0 g O .u_boot_cmd 0000001c __u_boot_cmd_mm80179b8c g O .u_boot_cmd 0000001c __u_boot_cmd_env80179da0 g O .u_boot_cmd 0000001c __u_boot_cmd_av_launch801797b8 g O .u_boot_cmd 0000001c __u_boot_cmd_fatls8017987c g O .u_boot_cmd 0000001c __u_boot_cmd_loady80179d14 g O .u_boot_cmd 0000001c __u_boot_cmd_version80179b54 g O .u_boot_cmd 0000001c __u_boot_cmd_ntt80179cf8 g O .u_boot_cmd 0000001c __u_boot_cmd_usbboot80179748 g O .u_boot_cmd 0000001c __u_boot_cmd_coninfo80179be0 g O .u_boot_cmd 0000001c __u_boot_cmd_setenv80179d68 g O .u_boot_cmd 0000001c __u_boot_cmd_tsi80179940 g O .u_boot_cmd 0000001c __u_boot_cmd_cp801796bc g O .u_boot_cmd 0000001c __u_boot_cmd_reset80179ca4 g O .u_boot_cmd 0000001c __u_boot_cmd_false80179994 g O .u_boot_cmd 0000001c __u_boot_cmd_loop80179a04 g O .u_boot_cmd 0000001c __u_boot_cmd_nand801796d8 g O .u_boot_cmd 0000001c __u_boot_cmd_bootm80179a58 g O .u_boot_cmd 0000001c __u_boot_cmd_mpw80179978 g O .u_boot_cmd 0000001c __u_boot_cmd_base 80179bc4 g O .u_boot_cmd 0000001c __u_boot_cmd_printenv 80179c34 g O .u_boot_cmd 0000001c __u_boot_cmd_snf 801799cc g O .u_boot_cmd 0000001c __u_boot_cmd_sleep 80179ac8 g O .u_boot_cmd 0000001c __u_boot_cmd_macrx 80179c18 g O .u_boot_cmd 0000001c __u_boot_cmd_sf 80179d84 g O .u_boot_cmd 0000001c __u_boot_cmd_show_logo 80179764 g O .u_boot_cmd 0000001c __u_boot_cmd_echo 8017980c g O .u_boot_cmd 0000001c __u_boot_cmd_help 80179844 g O .u_boot_cmd 0000001c __u_boot_cmd_itest 80179df4 g .u_boot_cmd 00000000 __u_boot_cmd_end 80179d4c g O .u_boot_cmd 0000001c __u_boot_cmd_secure 80179780 g O .u_boot_cmd 0000001c __u_boot_cmd_exit 801796a0 g O .u_boot_cmd 0000001c __u_boot_cmd_goo 80179bfc g O .u_boot_cmd 0000001c __u_boot_cmd_run 80179c88 g O .u_boot_cmd 0000001c __u_boot_cmd_test 80179828 g O .u_boot_cmd 0000001c __u_boot_cmd_question_mark 80179908 g O .u_boot_cmd 0000001c __u_boot_cmd_mw 80179dd8 g O .u_boot_cmd 0000001c __u_boot_cmd_jpeg_logo 80179d30 g O .u_boot_cmd 0000001c __u_boot_cmd_vid 80179a3c g O .u_boot_cmd 0000001c __u_boot_cmd_mpr 80179ae4 g O .u_boot_cmd 0000001c __u_boot_cmd_bootp 80179ba8 g O .u_boot_cmd 0000001c __u_boot_cmd_editenv 80179898 g O .u_boot_cmd 0000001c __u_boot_cmd_loadimg 80179924 g O .u_boot_cmd 0000001c __u_boot_cmd_cmp 8017972c g O .u_boot_cmd 0000001c __u_boot_cmd_iminfo 80179860 g O .u_boot_cmd 0000001c __u_boot_cmd_loadb 801798ec g O .u_boot_cmd 0000001c __u_boot_cmd_nm 801797f0 g O .u_boot_cmd 0000001c __u_boot_cmd_fatwrite 801799b0 g O .u_boot_cmd 0000001c __u_boot_cmd_mtest 8017995c g O .u_boot_cmd 0000001c __u_boot_cmd_crc32 80179b38 g O .u_boot_cmd 0000001c __u_boot_cmd_dhcp 8017979c g O .u_boot_cmd 0000001c __u_boot_cmd_fatload 801797d4 g O .u_boot_cmd 0000001c __u_boot_cmd_fatinfo 80179cc0 g O .u_boot_cmd 0000001c __u_boot_cmd_true 801798b4 g O .u_boot_cmd 0000001c __u_boot_cmd_md 80179c50 g O .u_boot_cmd 0000001c __u_boot_cmd_source 80179aac g O .u_boot_cmd 0000001c __u_boot_cmd_mactx 80179cdc g O .u_boot_cmd 0000001c __u_boot_cmd_usb 80179b00 g O .u_boot_cmd 0000001c __u_boot_cmd_tftpboot 80179668 g O .u_boot_cmd 0000001c __u_boot_cmd_bdinfo 80179710 g O .u_boot_cmd 0000001c __u_boot_cmd_bootd 80179a20 g O .u_boot_cmd 0000001c __u_boot_cmd_nboot 8017964c g .u_boot_cmd 00000000 __u_boot_cmd_start 801796f4 g O .u_boot_cmd 0000001c __u_boot_cmd_boot 80179684 g O .u_boot_cmd 0000001c __u_boot_cmd_go 80179a74 g O .u_boot_cmd 0000001c __u_boot_cmd_macfilter

如上,就是定義的結構如何被使用, 并且得到了證明。

=================================我是分割線===================================

接下來是最后一步,我們從命令行輸入指令是是如何和我們的 .u_boot_cmd 段連接起來的?

?

在 command.c 中的 num command_ret_t cmd_process(int flag, int argc, char * const argv[],

??????????????????????????? ?????? int *repeatable) 函數中 調用了 find_cmd, 以下為其實現。

cmd_tbl_t *find_cmd (const char *cmd)

{

???????? int len = &__u_boot_cmd_end - &__u_boot_cmd_start;

???????? return find_cmd_tbl(cmd, &__u_boot_cmd_start, len);

}

?

其中 __u_boot_cmd_end 和 __u_boot_cmd_start 為在u-boot.lds 中定義的字段

.u_boot_cmd : {

?__u_boot_cmd_start = .;

?*(.u_boot_cmd)

?__u_boot_cmd_end = .;

?}

?

等號后面的 ' . '?代表鏈接后的當前位置。在上一步中我們查到了 __u_boot_cmd_start 位置為 0x8017964c , __u_boot_cmd_end 位置為 0x80179df4。Len = 0x7A8

?

當我們輸入一個存在的指令后, ?find_cmd_tbl(cmd, &__u_boot_cmd_start, len); 會得到該指令的地址, ?然后調用 cmd_call 執行, 具體請看command.c 下的cmd_process 函數。

=================================我是分割線===================================

?

至此,Uboot 命令的流程已經說明白了。

?

=================================我是分割線===================================

此外, 對Uboot 有所研究的朋友在makefile 中發現了這么一句話:

?

GEN_UBOOT = \
UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
  sed -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\
  cd $(LNDIR) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) $$UNDEF_SYM $(__OBJS) \
  --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
  -Map u-boot.map -o u-boot

這句話解析如下 :

首先 在Makefile中,??`?` 代表 執行shell代碼, 讓我們把該代碼拿出來 :

$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
  sed -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq?

$(OBJDUMP)? 代表 objdump 工具,??$(LIBBOARD)??$(LIBS) 明顯代表一些庫文件, $(SYM_PREFIX) 代表前綴,這些對我們分析問題無關緊要 ,這里我們將其簡化。于是上述代碼簡化成了:

objdump -x libtest.a | sed -n -e? 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq?

objudmp -x??libtest.a? 可以得到?libtest.a 庫中所有的 symbol, 包括函數,數組,文件等,這里我們簡稱為符號 .

然后將得到的符號通過"管道" 傳遞給sed 進行編輯。接下來對sed 進行分析:

sed -n -e??'s/.*\(__u_boot_cmd_.*\)/-u\1/p'?

sed -n -e 代表使用 silent 模式,以及直接在命令行進行編輯動作。

'? ?'? 兩個單引號之間表示將要進行的動作 。?

標記成黑色的?s 代表會進行替換操作('s/要被取代的字串/新的字串/').

p 代表打印出來。

因此上面的表達式的最淺顯的意思是:

將? ?.*\(__u_boot_cmd_.*\)??替換為??-u\1? ??

并且由于sed 支持正則表達式, 在正則表達式中括號()代表分組, 使用 \1 \2 \3 獲取第一個分組,第二個分組, 第三個分組。因此上述表達式進一步被理解為:

將???.*__u_boot_cmd_.*??替換為??-u.*__u_boot_cmd_.*??

請注意,? 上面的字符串和上上面字符串的不同。

在正則表達式中 . 代表任意字符(不包括空格),*? 代表任意個, 因此我們將上述語句按照漢語翻譯一遍:

使用?objdump -x? 解析???libtest.a 得到一些符號,將這些符號使用sed 進行處理, 處理方式是: 找到符號中有__u_boot_cmd_字段的那一部分, 然后在這些字段前面加上-u。

接下來?|sort|uniq? 就比較好理解了,就是進行排序和消除重復。

然后將其賦值給??UNDEF_SYM?. 至此?

UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \
  sed -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;? 這一部分分析完畢, 總結來說就是 找到一些字段,在字段前面加上-u ,最后賦值給?UNDEF_SYM 這個變量。

?

接下來分析:

cd $(LNDIR) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) $$UNDEF_SYM $(__OBJS) \
  --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \
  -Map u-boot.map -o u-boot

其實這一點沒什么好說的, 無非就是執行ld 鏈接,然后生成u-boot這個文件, 這里需要注意的是 在其中使用了??UNDEF_SYM 變量,UNDEF_SYM 代表-uxxx__u_boot_cmd_xxx ,這是什么意思呢??

通過 man ld 可以找到 :

-u symbol--undefined=symbolForce symbol to be entered in the output file as an undefined symbol. Doing this may, for example, trigger linking of additional modules from standard libraries. -u may be repeated with different option argumentsto enter additional undefined symbols. This option is equivalent to the "EXTERN" linker script command.

?


也就是說在可執行文件中通過-u可以插入未定義變量。

?這樣一來, 也就明白了 這段代碼的目的是u_boot_cmd?變量插入到可執行文件中。?

?

接下來繼續最開始的問題:? 既然u-boot 使用?__attribute__((unused, section(".u_boot_cmd"), aligned(4)))? 的方式將uboot 的指令插入到 輸出文件的? .u_boot_cmd? 段, 那??GEN_UBOOT? 這個 ‘函數' 的意義是什么呢? 將重復的工作在做一遍嗎 ?

?

這個問題也困擾了我很久,直到本篇文檔寫完也沒有頭緒, 我的分析過程簡單的說一下,?

使用ld -u 插入符號, 一般都會在 ?.strtab? ?這個段中,? 可以通過 readelf -S test.out,可以找到???.strtab? ?這個段的index ,比如說是 38, 然后通過 readelf? -x38??test.out ,查看源文件??梢郧宄目吹竭@些字段。

但是使用???__attribute__((unused, section(".u_boot_cmd"), aligned(4)))?? 的方式鏈接器會自動的將 我們定義的變量的字段系寫入到? ??.strtab? 這個section 中(大家可以寫一個簡單的小程序驗證下,我之前驗證過,但是代碼沒有保存下來)。 這樣看來 就重復了。 因此從目前來看,?GEN_UBOOT? 是沒有什么用的。當然, 如果果有哪位朋友知道原因,請發郵件給我 syyxy@outlook.com 或者評論一下,感激不盡。

?

轉載于:https://www.cnblogs.com/syyxy/p/8992446.html

總結

以上是生活随笔為你收集整理的Uboot 命令是如何被使用的?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。