小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

uboot參數(shù)表的結(jié)構(gòu)和操作

 WUCANADA 2012-08-25

uboot參數(shù)表的結(jié)構(gòu)和操作

uboot參數(shù)表的結(jié)構(gòu)和操作(R.wen)

1、參數(shù)表的結(jié)構(gòu)定義在environment.c中,如下:

#ifdef CFG_REDUNDAND_ENVIRONMENT

# define ENV_HEADER_SIZE       (sizeof(unsigned long) + 1)

#else

# define ENV_HEADER_SIZE       (sizeof(unsigned long))

#endif

//除去參數(shù)表頭后參數(shù)的長度最值

#define ENV_SIZE (CFG_ENV_SIZE - ENV_HEADER_SIZE)

typedef     struct environment_s {

unsigned long crc;        /* CRC32 over data bytes      */

#ifdef CFG_REDUNDAND_ENVIRONMENT

unsigned char flags;             /* active/obsolete flags   */

#endif

unsigned char data[ENV_SIZE]; /* Environment data         */

} env_t;

結(jié) 構(gòu)env_t參數(shù)表的結(jié)構(gòu)非常簡單,第一個成員就是crc,用于crc32校驗,第二個參數(shù)是冗余的標(biāo)志,最后一個就是參數(shù)數(shù)組了。所以參數(shù)頭的長度 ENV_HEADER_SIZE就是crc與flags之和,即為sizeof(long)+sizeof(char)。這個結(jié)構(gòu)就是在內(nèi)存和flash 上表示參數(shù)表的結(jié)構(gòu)。

參數(shù)表的最后一個成員data數(shù)組中存放所有的環(huán)境變量值,每個變量和值用‘=’號連接,而兩個變量之間則通過’\分開,如下:

uchar default_environment[] = {

#ifdef CONFIG_BOOTARGS

"bootargs="    CONFIG_BOOTARGS                "\0"

#endif

#ifdef CONFIG_BOOTCOMMAND

"bootcmd="    CONFIG_BOOTCOMMAND              "\0"

#endif

……

"\0"

};

2、環(huán)境變量的初始化env_relocate()

       Uboot在完成匯編部分的初始化之后,將跳到start_armboot()去執(zhí)行,其中便會執(zhí)行env_relocate()初始化環(huán)境變量。

去除了一些不執(zhí)行的代碼后,這個函數(shù)如下:

void env_relocate (void)

{

      /*

      * We must allocate a buffer for the environment

      */

      env_ptr = (env_t *)malloc (CFG_ENV_SIZE); // 1

      /*

      * After relocation to RAM, we can always use the "memory" functions

      */

      env_get_char = env_get_char_memory; // 2

      if (gd->env_valid==0)

             default_env();           // 3

      else {

             env_relocate_spec ();   // 4

      }

      gd->env_addr = (ulong)&(env_ptr->data); // 5

}

第一步,初始化一個全局指針,它被定義為:

env_t *env_ptr = 0;

第二步,重新初始化函數(shù)指針,

static uchar env_get_char_init (int index);

uchar (*env_get_char)(int) = env_get_char_init;

該函數(shù)指針原來被初始化為env_get_char_init,現(xiàn)在改為env_get_char_memory。對于nand flash,這兩個函數(shù)是一樣的。

第三步,如果flash沒有參數(shù)表,則使用默認(rèn)參數(shù),這里是通過default_env()來加載。

void default_env(void)

{

       memset (env_ptr, 0, sizeof(env_t));

       memcpy (env_ptr->data,

              default_environment,

              sizeof(default_environment)); //拷貝環(huán)境變量

#ifdef CFG_REDUNDAND_ENVIRONMENT

       env_ptr->flags = 0xFF;

#endif

       env_crc_update ();   //更新crc32校驗

       gd->env_valid = 1; //標(biāo)識環(huán)境變量可用

}

第四步,如果flash上有參數(shù)表可用,則從flash上加載,通過env_relocate_spec()來實現(xiàn):

void env_relocate_spec (void)

{

#if !defined(ENV_IS_EMBEDDED) //如果不是使用嵌入?yún)?shù)的形式,即為參數(shù)表的形式

       ulong total;

       int ret;

       total = CFG_ENV_SIZE; //參數(shù)表大小,包括參數(shù)表頭部

       //讀出操作,flash設(shè)備為nand_info,偏移為CFG_ENV_OFFSET,讀出的大小為total,目標(biāo)地址由env_ptr所指。

       ret = nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr);

       //如果讀出的長度不對或出錯,則使用默認(rèn)值

    if (ret || total != CFG_ENV_SIZE)

              return use_default();

       //如果校驗出錯,使用默認(rèn)值

       if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc)

              return use_default();

#endif /* ! ENV_IS_EMBEDDED */

}

此外,uboot的參數(shù)表還支持一種被稱為CFG_ENV_OFFSET_REDUND的冗余模式,它會在flash上保存兩個參數(shù)表副本,這樣在一個副本出錯的時候,還可以從另一個副本中去讀取,通過這種方式,提高了數(shù)據(jù)的安全性。

第五步,gd->env_addr = (ulong)&(env_ptr->data)

即將環(huán)境變量的值賦值給全局變量gd->env_addr,這樣只要通過這個全局變量就可以訪問這些變量了。

       值得一提的是,字符串?dāng)?shù)組data里面的變量與變量之間是通過’\來分割的。

3、環(huán)境變量的保存,保存是讀取的反過程,所以跟上面的過程相似,如下:

int saveenv(void)

{

      ulong total;

      int ret = 0;

      //先擦除

      if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE))

      //寫入

total = CFG_ENV_SIZE;

      ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr);

      if (ret || total != CFG_ENV_SIZE)

             return 1;

      puts ("done\n");

      return ret;

}

4、讀取環(huán)境變量

Uboot中經(jīng)常要讀取環(huán)境變量,這是通過getenv來實現(xiàn)的:

/ * Look up variable from environment,

* return address of storage for that variable,

* or NULL if not found

*/

char *getenv (char *name)

{

       int i, nxt;

       for (i=0; env_get_char(i) != '\0'; i=nxt+1) {

              int val;

              for (nxt=i; env_get_char(nxt) != '\0'; ++nxt) {

                     if (nxt >= CFG_ENV_SIZE) {

                            return (NULL);

                     }

              }

              if ((val=envmatch((uchar *)name, i)) < 0)

                     continue;

              //通過所得的下標(biāo)返回變量值的指針,由于是字符串指針,所以它在碰到’\符合時結(jié)束,即為該變量的值。

              return ((char *)env_get_addr(val));

       }

       return (NULL);

}

通過輸入變量的名字,返回變量的值。

前面已經(jīng)提到,函數(shù)指針env_get_char已經(jīng)被初始化為env_get_char_memory:

       該函數(shù)獲取環(huán)境變量數(shù)組中下標(biāo)為index的字符。

uchar env_get_char_memory (int index)

{

if (gd->env_valid) {

         return ( *((uchar *)(gd->env_addr + index)) );

} else {

         return ( default_environment[index] );

}

}

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

* Match a name / name=value pair

*

* s1 is either a simple 'name', or a 'name=value' pair.

* i2 is the environment index for a 'name2=value2' pair.

* If the names match, return the index for the value2, else NULL.

*/

查找符號變量,如果找到則返回等號后面的字符串指針,即為變量的值。

static int

envmatch (uchar *s1, int i2)

{

       while (*s1 == env_get_char(i2++))

              if (*s1++ == '=')

                     return(i2);

       if (*s1 == '\0' && env_get_char(i2-1) == '=')

              return(i2);

       return(-1);

}

如前所述,環(huán)境變量表是一個字符串?dāng)?shù)組,而其中的變量之間通過’\符號隔開,即是當(dāng)遇到該符號時,則表示一個變量結(jié)束而另一個變量開始。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多