查看: 3859|回复: 0

[原创] uboot env 环境变量解析注释

[复制链接]
  • TA的每日心情
    开心
    2024-1-16 17:48
  • 签到天数: 592 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2019-6-9 13:59:38 | 显示全部楼层 |阅读模式
    分享到:
    本文基于 米尔  mys_y6ull  开发板 uboot 源码 2016.03 版本:

    先写结论:
    env 分两部分处理:
    1,init_sequence_f
    中添加 env 指针,添加 env_valid 标记
    2,init_sequence_r
    中创建 htab ,解析 env,并添加 env 到 htab 中
    (并设置 load_addr (从环境变量获取值, kernel 需要用))

    再看源码:代码比较简单,init_sequence_f 部分的 env_init 函数
    1. init_sequence_f (uboot\common\board_f.c)

    2. int env_init(void)
    3. {
    4.         /* use default */
    5.         gd->env_addr        = (ulong)&default_environment[0];          // default_environment 是静态数组变量
    6.         gd->env_valid        = 1;

    7.         return 0;
    8. }
    复制代码

    这个是静态变量,default_environment, 是个静态数组,可以往里面随意添加环境变量,但是往这里添加环境变量不是很方便,要注意格式。不过还有更方便的方法,看这个数组最后一个元素,CONFIG_EXTRA_ENV_SETTINGS,可以找找 这个宏,从这个宏里面添加环境变量更方便

    1. // -----------------------------------------------
    2. (uboot\include\env_default.h)
    3. static char default_environment[] = {                          //
    4. #else
    5. const uchar default_environment[] = {
    6. #endif
    7. #ifdef        CONFIG_ENV_CALLBACK_LIST_DEFAULT
    8.         ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0"
    9. #endif
    10. #ifdef        CONFIG_ENV_FLAGS_LIST_DEFAULT
    11.         ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\0"
    12. #endif
    13. #ifdef        CONFIG_BOOTARGS
    14.         "bootargs="        CONFIG_BOOTARGS                        "\0"
    15. #endif
    16. #ifdef        CONFIG_BOOTCOMMAND
    17.         "bootcmd="        CONFIG_BOOTCOMMAND                "\0"
    18. #endif
    19. #ifdef        CONFIG_RAMBOOTCOMMAND
    20.         "ramboot="        CONFIG_RAMBOOTCOMMAND                "\0"
    21. #endif
    22. #ifdef        CONFIG_NFSBOOTCOMMAND
    23.         "nfsboot="        CONFIG_NFSBOOTCOMMAND                "\0"
    24. #endif
    25. #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
    26.         "bootdelay="        __stringify(CONFIG_BOOTDELAY)        "\0"
    27. #endif
    28. #if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
    29.         "baudrate="        __stringify(CONFIG_BAUDRATE)        "\0"
    30. #endif
    31. #ifdef        CONFIG_LOADS_ECHO
    32.         "loads_echo="        __stringify(CONFIG_LOADS_ECHO)        "\0"
    33. #endif
    34. #ifdef        CONFIG_ETHPRIME
    35.         "ethprime="        CONFIG_ETHPRIME                        "\0"
    36. #endif
    37. #ifdef        CONFIG_IPADDR
    38.         "ipaddr="        __stringify(CONFIG_IPADDR)        "\0"
    39. #endif
    40. #ifdef        CONFIG_SERVERIP
    41.         "serverip="        __stringify(CONFIG_SERVERIP)        "\0"
    42. #endif
    43. #ifdef        CONFIG_SYS_AUTOLOAD
    44.         "autoload="        CONFIG_SYS_AUTOLOAD                "\0"
    45. #endif
    46. #ifdef        CONFIG_PREBOOT
    47.         "preboot="        CONFIG_PREBOOT                        "\0"
    48. #endif
    49. #ifdef        CONFIG_ROOTPATH
    50.         "rootpath="        CONFIG_ROOTPATH                        "\0"
    51. #endif
    52. #ifdef        CONFIG_GATEWAYIP
    53.         "gatewayip="        __stringify(CONFIG_GATEWAYIP)        "\0"
    54. #endif
    55. #ifdef        CONFIG_NETMASK
    56.         "netmask="        __stringify(CONFIG_NETMASK)        "\0"
    57. #endif
    58. #ifdef        CONFIG_HOSTNAME
    59.         "hostname="        __stringify(CONFIG_HOSTNAME)        "\0"
    60. #endif
    61. #ifdef        CONFIG_BOOTFILE
    62.         "bootfile="        CONFIG_BOOTFILE                        "\0"
    63. #endif
    64. #ifdef        CONFIG_LOADADDR
    65.         "loadaddr="        __stringify(CONFIG_LOADADDR)        "\0"
    66. #endif
    67. #ifdef        CONFIG_CLOCKS_IN_MHZ
    68.         "clocks_in_mhz=1\0"
    69. #endif
    70. #if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
    71.         "pcidelay="        __stringify(CONFIG_PCI_BOOTDELAY)"\0"
    72. #endif
    73. #ifdef        CONFIG_ENV_VARS_UBOOT_CONFIG
    74.         "arch="                CONFIG_SYS_ARCH                        "\0"
    75.         "cpu="                CONFIG_SYS_CPU                        "\0"
    76.         "board="        CONFIG_SYS_BOARD                "\0"
    77.         "board_name="        CONFIG_SYS_BOARD                "\0"
    78. #ifdef CONFIG_SYS_VENDOR
    79.         "vendor="        CONFIG_SYS_VENDOR                "\0"
    80. #endif
    81. #ifdef CONFIG_SYS_SOC
    82.         "soc="                CONFIG_SYS_SOC                        "\0"
    83. #endif
    84. #endif
    85. #ifdef        CONFIG_EXTRA_ENV_SETTINGS
    86.         CONFIG_EXTRA_ENV_SETTINGS
    87. #endif
    88.         "\0"
    89. #ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
    90.         }
    91. #endif
    92. };
    复制代码
    以上是环境变量数组,实际在 uboot 中以 hash 表的形式管理,数组到 hash 表,在 initr_env 函数中:
    1. init_sequence_r(uboot\common\board_r.c)
    2. static int initr_env(void)
    3. {
    4.         /* initialize environment */
    5.         if (should_load_env())
    6.                 env_relocate();
    7.         else
    8.                 set_default_env(NULL);                                  // 1111
    9. #ifdef CONFIG_OF_CONTROL
    10.         setenv_addr("fdtcontroladdr", gd->fdt_blob);
    11. #endif

    12.         /* Initialize from environment */
    13.         load_addr = getenv_ulong("loadaddr", 16, load_addr);
    14. #if defined(CONFIG_SYS_EXTBDINFO)
    15. #if defined(CONFIG_405GP) || defined(CONFIG_405EP)
    16. #if defined(CONFIG_I2CFAST)
    17.         /*
    18.          * set bi_iic_fast for linux taking environment variable
    19.          * "i2cfast" into account
    20.          */
    21.         {
    22.                 char *s = getenv("i2cfast");

    23.                 if (s && ((*s == 'y') || (*s == 'Y'))) {
    24.                         gd->bd->bi_iic_fast[0] = 1;
    25.                         gd->bd->bi_iic_fast[1] = 1;
    26.                 }
    27.         }
    28. #endif /* CONFIG_I2CFAST */
    29. #endif /* CONFIG_405GP, CONFIG_405EP */
    30. #endif /* CONFIG_SYS_EXTBDINFO */
    31.         return 0;
    32. }

    33. // -----------------------------------------------
    34. void set_default_env(const char *s)
    35. {
    36.         int flags = 0;

    37.         if (sizeof(default_environment) > ENV_SIZE) {
    38.                 puts("*** Error - default environment is too large\n\n");
    39.                 return;
    40.         }

    41.         if (s) {
    42.                 if (*s == '!') {
    43.                         printf("*** Warning - %s, "
    44.                                 "using default environment\n\n",
    45.                                 s + 1);
    46.                 } else {
    47.                         flags = H_INTERACTIVE;
    48.                         puts(s);
    49.                 }
    50.         } else {
    51.                 puts("Using default environment\n\n");
    52.         }

    53.         if (himport_r(&env_htab, (char *)default_environment,                 // 创建 htab ,并添加 env 环境变量
    54.                         sizeof(default_environment), '\0', flags, 0,
    55.                         0, NULL) == 0)
    56.                 error("Environment import failed: errno = %d\n", errno);

    57.         gd->flags |= GD_FLG_ENV_READY;
    58. }

    59. // -----------------------------------------------
    60. int himport_r(struct hsearch_data *htab,
    61.                 const char *env, size_t size, const char sep, int flag,
    62.                 int crlf_is_lf, int nvars, char * const vars[])
    63. {
    64.         char *data, *sp, *dp, *name, *value;
    65.         char *localvars[nvars];
    66.         int i;

    67.         /* Test for correct arguments.  */
    68.         if (htab == NULL) {
    69.                 __set_errno(EINVAL);
    70.                 return 0;
    71.         }

    72.         /* we allocate new space to make sure we can write to the array */
    73.         if ((data = malloc(size + 1)) == NULL) {
    74.                 debug("himport_r: can't malloc %zu bytes\n", size + 1);
    75.                 __set_errno(ENOMEM);
    76.                 return 0;
    77.         }
    78.         memcpy(data, env, size);
    79.         data[size] = '\0';
    80.         dp = data;

    81.         /* make a local copy of the list of variables */
    82.         if (nvars)
    83.                 memcpy(localvars, vars, sizeof(vars[0]) * nvars);

    84.         if ((flag & H_NOCLEAR) == 0) {
    85.                 /* Destroy old hash table if one exists */
    86.                 debug("Destroy Hash Table: %p table = %p\n", htab,
    87.                        htab->table);
    88.                 if (htab->table)
    89.                         hdestroy_r(htab);
    90.         }

    91.         /*
    92.          * Create new hash table (if needed).  The computation of the hash
    93.          * table size is based on heuristics: in a sample of some 70+
    94.          * existing systems we found an average size of 39+ bytes per entry
    95.          * in the environment (for the whole key=value pair). Assuming a
    96.          * size of 8 per entry (= safety factor of ~5) should provide enough
    97.          * safety margin for any existing environment definitions and still
    98.          * allow for more than enough dynamic additions. Note that the
    99.          * "size" argument is supposed to give the maximum environment size
    100.          * (CONFIG_ENV_SIZE).  This heuristics will result in
    101.          * unreasonably large numbers (and thus memory footprint) for
    102.          * big flash environments (>8,000 entries for 64 KB
    103.          * envrionment size), so we clip it to a reasonable value.
    104.          * On the other hand we need to add some more entries for free
    105.          * space when importing very small buffers. Both boundaries can
    106.          * be overwritten in the board config file if needed.
    107.          */

    108.         if (!htab->table) {
    109.                 int nent = CONFIG_ENV_MIN_ENTRIES + size / 8;

    110.                 if (nent > CONFIG_ENV_MAX_ENTRIES)
    111.                         nent = CONFIG_ENV_MAX_ENTRIES;

    112.                 debug("Create Hash Table: N=%d\n", nent);

    113.                 if (hcreate_r(nent, htab) == 0) {
    114.                         free(data);
    115.                         return 0;
    116.                 }
    117.         }

    118.         if (!size) {
    119.                 free(data);
    120.                 return 1;                /* everything OK */
    121.         }
    122.         if(crlf_is_lf) {
    123.                 /* Remove Carriage Returns in front of Line Feeds */
    124.                 unsigned ignored_crs = 0;
    125.                 for(;dp < data + size && *dp; ++dp) {
    126.                         if(*dp == '\r' &&
    127.                            dp < data + size - 1 && *(dp+1) == '\n')
    128.                                 ++ignored_crs;
    129.                         else
    130.                                 *(dp-ignored_crs) = *dp;
    131.                 }
    132.                 size -= ignored_crs;
    133.                 dp = data;
    134.         }
    135.         /* Parse environment; allow for '\0' and 'sep' as separators */
    136.         do {
    137.                 ENTRY e, *rv;

    138.                 /* skip leading white space */
    139.                 while (isblank(*dp))
    140.                         ++dp;

    141.                 /* skip comment lines */
    142.                 if (*dp == '#') {
    143.                         while (*dp && (*dp != sep))
    144.                                 ++dp;
    145.                         ++dp;
    146.                         continue;
    147.                 }

    148.                 /* parse name */
    149.                 for (name = dp; *dp != '=' && *dp && *dp != sep; ++dp)
    150.                         ;

    151.                 /* deal with "name" and "name=" entries (delete var) */
    152.                 if (*dp == '\0' || *(dp + 1) == '\0' ||
    153.                     *dp == sep || *(dp + 1) == sep) {
    154.                         if (*dp == '=')
    155.                                 *dp++ = '\0';
    156.                         *dp++ = '\0';        /* terminate name */

    157.                         debug("DELETE CANDIDATE: "%s"\n", name);
    158.                         if (!drop_var_from_set(name, nvars, localvars))
    159.                                 continue;

    160.                         if (hdelete_r(name, htab, flag) == 0)
    161.                                 debug("DELETE ERROR ##############################\n");

    162.                         continue;
    163.                 }
    164.                 *dp++ = '\0';        /* terminate name */

    165.                 /* parse value; deal with escapes */
    166.                 for (value = sp = dp; *dp && (*dp != sep); ++dp) {
    167.                         if ((*dp == '\\') && *(dp + 1))
    168.                                 ++dp;
    169.                         *sp++ = *dp;
    170.                 }
    171.                 *sp++ = '\0';        /* terminate value */
    172.                 ++dp;

    173.                 if (*name == 0) {
    174.                         debug("INSERT: unable to use an empty key\n");
    175.                         __set_errno(EINVAL);
    176.                         free(data);
    177.                         return 0;
    178.                 }

    179.                 /* Skip variables which are not supposed to be processed */
    180.                 if (!drop_var_from_set(name, nvars, localvars))
    181.                         continue;

    182.                 /* enter into hash table */
    183.                 e.key = name;
    184.                 e.data = value;

    185.                 hsearch_r(e, ENTER, &rv, htab, flag);
    186.                 if (rv == NULL)
    187.                         printf("himport_r: can't insert "%s=%s" into hash table\n",
    188.                                 name, value);

    189.                 debug("INSERT: table %p, filled %d/%d rv %p ==> name="%s" value="%s"\n",
    190.                         htab, htab->filled, htab->size,
    191.                         rv, name, value);
    192.         } while ((dp < data + size) && *dp);        /* size check needed for text */
    193.                                                 /* without '\0' termination */
    194.         debug("INSERT: free(data = %p)\n", data);
    195.         free(data);

    196.         /* process variables which were not considered */
    197.         for (i = 0; i < nvars; i++) {
    198.                 if (localvars[i] == NULL)
    199.                         continue;
    200.                 /*
    201.                  * All variables which were not deleted from the variable list
    202.                  * were not present in the imported env
    203.                  * This could mean two things:
    204.                  * a) if the variable was present in current env, we delete it
    205.                  * b) if the variable was not present in current env, we notify
    206.                  *    it might be a typo
    207.                  */
    208.                 if (hdelete_r(localvars[i], htab, flag) == 0)
    209.                         printf("WARNING: '%s' neither in running nor in imported env!\n", localvars[i]);
    210.                 else
    211.                         printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]);
    212.         }

    213.         debug("INSERT: done\n");
    214.         return 1;                /* everything OK */
    215. }

    复制代码
    以上内容更新到 github :
    笔记:https://github.com/robe-zhang/mys_y6ulx/blob/master/note_robe/note_uboot/note_uboot_env
    源码:https://github.com/robe-zhang/mys_y6ulx/tree/master/MYiR-iMX-uboot

    <完>











    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则



    手机版|小黑屋|与非网

    GMT+8, 2024-4-23 20:03 , Processed in 0.111389 second(s), 15 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.