U-bootの分析(C)---実現ブートおよびカーネルブートコマンド

 

不十分なボーエンは、作業フローのu-ブートを総括し、今日我々が分析する必要があり、より多くの重要なコンテンツの2つのUブーツ

  1. 達成するために、U-bootコマンド
  2. U-ブートカーネルをブートする方法

リットル   を達成するためのコマンド

私たちのu-bootコマンドの入力は、プリント、のsetenv、saveenvコマンドとして、解決することができ、我々はそれまでの分析を実現します。

私たちは、最終的には、コマンド入力でmain_loopで停止し、確かに私たちは、この機能で実現し、我々は機能を見つけBL2に、昨日分析した私達の注意にmain_loop機能で簡単に機能をrun_command、その機能解析にジャンプ機能で、以下のいくつかの重要なポイントがあります

  1. 独立した、とのu-ブートサポートにコマンドのコード内のコメントから知っていることは容易である「;」別のコマンド。

 

 
1 / * 
 2 *区切り、または文字列の末尾検索
 * 3の簡単な脱出を許可します「;」「\;」を書き込むことにより、
 4 * / 
 5(inquotes = 0、9月= STR; * 9月、9月++){ 
 6 IF((* 9月== '\' ')&& 
 !7(*(SEP-1)= '\\'))
 8 inquotes = inquotes!; 
 9 
!10 IF(inquotes && 
11(* 9月== ';')&& / *分離* / 
!12(SEP = STR)&& / *過去の文字列* /開始
!13(*(SEP-1)=「を\ \ '))/ *と* /エスケープされません
14休憩を。
15}
 
  1. 分離パラメータ

 

1 / *抽出引数* / 
2 IF((ARGC = parse_line(finaltoken、ARGV))== 0){ 
3 RC = -1。/ *コマンドなしで、すべて* / 
4続けます。
5}
  1. [0]コマンドに対応するARGVコマンドリストの最初のパラメータを検索し、そして型cmd_tbl_tのインスタンスを返します。私たちは、このような構造は、一連のコマンドに関連して保証する必要があります推測することができます。
1 / * * /コマンド・テーブル内のコマンドを検索し
た場合2((cmdtp = find_cmd(ARGV [0]))== NULL){ 
3のprintf( "不明なコマンド'%s'は- N \ 'ヘルプ'を試す"、ARGV [0])。
4 RC = -1。/ * * /悪いコマンドの後にあきらめ
5続けます。
6}

 

nは我々がfind_cmd見て、我々は、コード追跡を通じてfind_cmd_tbl機能でコアコードを見つけます

 
1(cmdtp =表; 
 !2 cmdtp =表+ table_len; 
 3 cmdtp ++){ 
 4 IF(strncmpは(CMD、cmdtp->名前、LEN)== 0){ 
 5 IF(LEN == STRLEN(cmdtp->名))
 6リターンcmdtp。/ *完全一致* / 
 7 
 8 cmdtp_temp = cmdtp。/ *コマンドを省略?* / 
 9 n_found ++; 
10} 
11}
 

 

私たちは、その方法を見つけるために、上記のコードで知っているが、私は私のような多くの人々は非常にどこかで最後にコマンドテーブルを困惑と考えています。

上記のコードの私たちの読書によると、私たちは、この表のアドレスがテーブルで知って起動することができますね、我々は簡単にテーブルのソースを見つけることができます。

1 cmd_tbl_t * find_cmd(CONST文字* CMD)
2 { 
3 int型LEN =&__ u_boot_cmd_end - &__ u_boot_cmd_start。
4リターンfind_cmd_tbl(CMD、&__ u_boot_cmd_start、LEN); 
5}

 

私たちは、__u_boot_cmd_startに等しいテーブルの上のコードで知って、世界的な検索によって、我々は、このアドレスのソースは\アーチ\アームの\ CPU \のARMv7 \ u-boot.ldsです見つけます

1 __u_boot_cmd_start =。
2 .u_boot_cmd:{*(u_boot_cmd。)} 
3 __u_boot_cmd_end =;。

 

 

 

.u_boot_cmdセグメントを入れ__u_boot_cmd_startと__u_boot_cmd_endの間に、私たちは、このセグメントの名前を検索します次のマクロを見つけました

1の#define Struct_Section __attribute __((未使用、セクション( ".u_boot_cmd")))//必須属性設定期間.u_boot_cmd

 

それは確かに、このマクロは何かによって定義されており、私たちは次のような検索を見つけ、その後の後

1の#define U_BOOT_CMD_COMPLETE(名前、maxargs、担当者、CMD、使用、助ける、COMP)\ 
2 cmd_tbl_t __u_boot_cmd _ ##名Struct_Section = \ 
3 U_BOOT_CMD_MKENT_COMPLETE(名前、maxargs、担当者、CMD、使用、助ける、COMP)

 

今度は私たちが知ることができます読み取ることによって、マクロ、マクロを定義し、あなたは、U_BOOT_CMD_COMPLETEでこのマクロを構造型cmd_tbl_tを定義するプロパティのセグメント構造が.u_boot_cmdたを設定し、施行、その後、このマクロ検索、見つけることができます完全にはありませんが、我々は次のマクロを見つけるだけでいくつかのコマンド

1の#define U_BOOT_CMD(名前、maxargs、担当者、CMD、使用方法、ヘルプ)\ 
2 U_BOOT_CMD_COMPLETE(名前、maxargs、担当者、CMD、用法、助け、NULL)

 

U_BOOT_CMDを検索することによって、我々はコマンド定義の多くを見つけます。

この時点で、我々は完全なマクロコマンドU_BOOT_CMDを定義することです、このコマンドを、どのように表現するかを理解することができます。例を簡単に見つけることができます:

 
1 U_BOOT_CMD(
2ヘルプ、CONFIG_SYS_MAXARGS、1、のdo_help、
3 "印刷コマンド説明/使用"、
4 "\ n" 
5 " -全てのコマンド\ nの簡単な説明印刷" 
6 "... helpコマンドを\ n" 
7 " - 「」コマンド」の印刷の詳細な使用方法
8)。
 

 

nはコマンド名の内容を保証するcmd_tbl_t構造、最大のパラメータ、および機能に対応するように見えます。

 
1構造体cmd_tbl_s { 
 2のchar *名。/ *コマンド名* / 
 3 int型maxargs。/ *引数の最大数* / 
 4 INT再現可能。/ *オートリピート許さ?* / 
 5 / *実装関数* / 
 6 INT(* CMD)(構造体cmd_tbl_s *、INT、INT、チャー*のCONST [])。
 7のchar *の使用。/ *使用メッセージ(ショート)* / 
 8の#ifdefのCONFIG_SYS_LONGHELP 
 *ヘルプ9チャー。/ *ヘルプメッセージ(ロング)* / 
#endifの10を
CONFIG_AUTO_COMPLETEの#ifdef 11 
12 / *引数に自動補完を行います* / 
13 INT(*完全)(int型ARGC、[] ARGVするchar * CONST、チャーlast_char、INT MAXV、CHAR * CMDV [])。
14 #endifの
} 15。
 

 

この時点で、我々は上記で私たち自身のシンプルなU-bootコマンドを達成することができ、次は私が実現コマンドは、ハローです

 
1の#include <COMMON.H> 
 2の#include <command.h> 
 3 
 4 int型do_hello(cmd_tbl_t * [] ARGV cmdtp、INTフラグ、int型ARGC、チャー*のCONST)
 5 { 
 6のprintf( "ハローU-ブート") ; 
 7リターン0; 
 8} 
 9 
10 U_BOOT_CMD(
11こんにちは、CONFIG_SYS_MAXARGS、1、do_hello、
12 "プリントハロー"、/ *短帮助信息* / 
13 "\ NハローCMD ............" //长帮帮助信息
14)。
 

 

上記の内容に加え、共通カタログにメイクファイルを変更した後、U-ブートを再コンパイルし、分析が完了し達成するために、当社のu-bootコマンドをもたらし、私たち自身のu-bootコマンドを完了します。

リットル   カーネルブート

私たちのU-ブーツ等、TFTPをNANDことができ、私たちのカーネルがメモリにロードされ、このプロセスは、今日焦点を分析するためではない、そして今日我々はメモリからカーネルをブートする方法の分析に焦点を当て、我々はすべてのそのカーネルの起動時間を知っていますコマンドを使用するにはbootm、上記に従って達成コマンド解析の経験は、我々はそれがdo_bootm機能を実行するためにバインドされて推測することができます。ここでは、この機能の主な実装を分析します。

私たちはbootm uImage、しかしuImage = zImageの(本当のカーネル)+ヘッダ情報を開始することができます。したがって、我々は最初の眼鏡情報を見てみましょう。

 

 
typedefは構造体のimage_header { 
    ih_magicのuint32_t。/ *画像のヘッダマジック番号* / 
    のuint32_t ih_hcrc。/ *画像のヘッダCRCチェックサム* / 
    のuint32_t ih_time。/ *画像の作成タイムスタンプ* / 
    のuint32_t ih_size。/ *画像のデータサイズ* / 
    のuint32_t ih_load。/ *データのロードアドレス* / 
    のuint32_t ih_ep。/ *エントリ・ポイント・アドレス* / 
    のuint32_t ih_dcrc。/ *画像データのCRCチェックサム* / 
    uint8_tのih_os。/ *オペレーティングシステム* / 
    uint8_t ih_arch。/ * CPUアーキテクチャ* / 
    uint8_t ih_type。/ *イメージタイプ* /
    uint8_t ih_comp; / *圧縮タイプ* / 
    uint8_t ih_name [IH_NMLEN]。/ *イメージ名* / 
} image_header_t。
 

 

これは、コア情報を多数内部に格納され、我々はまた、do_bootmは、カーネル、負荷校正作業アドレスでこの情報を確認見つけることができます。

我々は、Linux(複数のブート用のu-ブートのサポート、次のコードリスト)を開始したと、私たちのU-ブーツはdo_bootm_linuxに機能を実行します

 

 
1静的boot_os_fn * boot_os [] = { 
 CONFIG_BOOTM_LINUXの#ifdef 2 
 3 [IH_OS_LINUX] = do_bootm_linux、
 4 #endifの
 5の#ifdef CONFIG_BOOTM_NETBSD 
 6 [IH_OS_NETBSD] = do_bootm_netbsd、
 7 #endifの
 CONFIG_LYNXKDIの#ifdef 8 
 9 [IH_OS_LYNXOS] = do_bootm_lynxkdi、
10# ENDIF 
11の#ifdef CONFIG_BOOTM_RTEMS 
12 [IH_OS_RTEMS] =のdo_bootm_rtems、
13 #endifの
14の#if定義(CONFIG_BOOTM_OSE)
15 [IH_OS_OSE] = do_bootm_ose、
16 #endifの
17の#if定義(CONFIG_CMD_ELF)
18 [IH_OS_VXWORKS] =のdo_bootm_vxworks、
19 [IH_OS_QNX] = do_bootm_qnxelf、
20 #endifの
21の#ifdef CONFIG_INTEGRITY 
[IH_OS_INTEGRITY] = do_bootm_integrity 22、
23 #endifの
} 24。
 

 

のは、主に以下の機能を分析してみましょうdo_bootm_linux

a)は、カーネルとカーネルにパラメータを設定するための作業の転送

 
#ifの定義(CONFIG_SETUP_MEMORY_TAGS)|| \ 
    (CONFIG_CMDLINE_TAG)に定義|| \ 
    (CONFIG_INITRD_TAG)に定義|| \ 
    (CONFIG_SERIAL_TAG)に定義|| \ 
    定義(CONFIG_REVISION_TAG)
    setup_start_tag(BD)。
#ifdef CONFIG_SERIAL_TAG 
    setup_serial_tag(&paramsは)。
#ENDIF 
の#ifdef CONFIG_REVISION_TAG 
    setup_revision_tag(&paramsは)。
#ENDIF 
の#ifdef CONFIG_SETUP_MEMORY_TAGS 
    setup_memory_tags(BD)。
#ENDIF 
の#ifdef CONFIG_CMDLINE_TAG 
    setup_commandline_tag(BD、コマンドライン)。
#endifの
CONFIG_INITRD_TAGの#ifdef 
    (images-> rd_start && images-> rd_end)の場合 
        setup_initrd_tag(BD、images-> rd_start、images-> rd_end)。
#endifの
    setup_end_tag(BD)。
#endifの
 

 

これらのコードは、主なパラメータであり、固定フォーマット一定の場所に書いています。このアドレス読みカーネルのブートパラメータに移動します。

b)は、カーネルが起動するエントリアドレスにジャンプ

1 kernel_entry =(ボイド(*)(INT、INT、UINT))images-> EP。
2 kernel_entry(0、machid、BD-> bi_boot_params)。

 

machid:私たちのマシンID

BD-> bi_boot_params:今述べたアドレスパラメータ

すべての上にこれまでのところ、私たちの仕事今日。

 

著者:wrjvszqの 
出典:HTTP:// HTTP://www.cnblogs.com/wrjvszq/ 
この記事は、執筆者に属し、公園の合計をブログ、転載を歓迎しますが、この節で宣言され、著者の同意なしに保持されなければならない、と記事のページの見かけの位置にあります元の接続、法的責任を追及するそうでない場合は権利を与えられました。 
-------------------------------------------------- -------- 
ご支援をありがとうございました、役立つ場合、右下隅をお勧めしてください、読んであなたの忍耐をありがとう

 

おすすめ

転載: www.cnblogs.com/FZLGYZ/p/11349798.html