TA的每日心情 | 开心 2024-11-20 21:23 |
---|
签到天数: 597 天 连续签到: 1 天 [LV.9]以坛为家II
|
本文基于 米尔 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 函数
- init_sequence_f (uboot\common\board_f.c)
- int env_init(void)
- {
- /* use default */
- gd->env_addr = (ulong)&default_environment[0]; // default_environment 是静态数组变量
- gd->env_valid = 1;
- return 0;
- }
复制代码
这个是静态变量,default_environment, 是个静态数组,可以往里面随意添加环境变量,但是往这里添加环境变量不是很方便,要注意格式。不过还有更方便的方法,看这个数组最后一个元素,CONFIG_EXTRA_ENV_SETTINGS,可以找找 这个宏,从这个宏里面添加环境变量更方便
- // -----------------------------------------------
- (uboot\include\env_default.h)
- static char default_environment[] = { //
- #else
- const uchar default_environment[] = {
- #endif
- #ifdef CONFIG_ENV_CALLBACK_LIST_DEFAULT
- ENV_CALLBACK_VAR "=" CONFIG_ENV_CALLBACK_LIST_DEFAULT "\0"
- #endif
- #ifdef CONFIG_ENV_FLAGS_LIST_DEFAULT
- ENV_FLAGS_VAR "=" CONFIG_ENV_FLAGS_LIST_DEFAULT "\0"
- #endif
- #ifdef CONFIG_BOOTARGS
- "bootargs=" CONFIG_BOOTARGS "\0"
- #endif
- #ifdef CONFIG_BOOTCOMMAND
- "bootcmd=" CONFIG_BOOTCOMMAND "\0"
- #endif
- #ifdef CONFIG_RAMBOOTCOMMAND
- "ramboot=" CONFIG_RAMBOOTCOMMAND "\0"
- #endif
- #ifdef CONFIG_NFSBOOTCOMMAND
- "nfsboot=" CONFIG_NFSBOOTCOMMAND "\0"
- #endif
- #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
- "bootdelay=" __stringify(CONFIG_BOOTDELAY) "\0"
- #endif
- #if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
- "baudrate=" __stringify(CONFIG_BAUDRATE) "\0"
- #endif
- #ifdef CONFIG_LOADS_ECHO
- "loads_echo=" __stringify(CONFIG_LOADS_ECHO) "\0"
- #endif
- #ifdef CONFIG_ETHPRIME
- "ethprime=" CONFIG_ETHPRIME "\0"
- #endif
- #ifdef CONFIG_IPADDR
- "ipaddr=" __stringify(CONFIG_IPADDR) "\0"
- #endif
- #ifdef CONFIG_SERVERIP
- "serverip=" __stringify(CONFIG_SERVERIP) "\0"
- #endif
- #ifdef CONFIG_SYS_AUTOLOAD
- "autoload=" CONFIG_SYS_AUTOLOAD "\0"
- #endif
- #ifdef CONFIG_PREBOOT
- "preboot=" CONFIG_PREBOOT "\0"
- #endif
- #ifdef CONFIG_ROOTPATH
- "rootpath=" CONFIG_ROOTPATH "\0"
- #endif
- #ifdef CONFIG_GATEWAYIP
- "gatewayip=" __stringify(CONFIG_GATEWAYIP) "\0"
- #endif
- #ifdef CONFIG_NETMASK
- "netmask=" __stringify(CONFIG_NETMASK) "\0"
- #endif
- #ifdef CONFIG_HOSTNAME
- "hostname=" __stringify(CONFIG_HOSTNAME) "\0"
- #endif
- #ifdef CONFIG_BOOTFILE
- "bootfile=" CONFIG_BOOTFILE "\0"
- #endif
- #ifdef CONFIG_LOADADDR
- "loadaddr=" __stringify(CONFIG_LOADADDR) "\0"
- #endif
- #ifdef CONFIG_CLOCKS_IN_MHZ
- "clocks_in_mhz=1\0"
- #endif
- #if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
- "pcidelay=" __stringify(CONFIG_PCI_BOOTDELAY)"\0"
- #endif
- #ifdef CONFIG_ENV_VARS_UBOOT_CONFIG
- "arch=" CONFIG_SYS_ARCH "\0"
- "cpu=" CONFIG_SYS_CPU "\0"
- "board=" CONFIG_SYS_BOARD "\0"
- "board_name=" CONFIG_SYS_BOARD "\0"
- #ifdef CONFIG_SYS_VENDOR
- "vendor=" CONFIG_SYS_VENDOR "\0"
- #endif
- #ifdef CONFIG_SYS_SOC
- "soc=" CONFIG_SYS_SOC "\0"
- #endif
- #endif
- #ifdef CONFIG_EXTRA_ENV_SETTINGS
- CONFIG_EXTRA_ENV_SETTINGS
- #endif
- "\0"
- #ifdef DEFAULT_ENV_INSTANCE_EMBEDDED
- }
- #endif
- };
复制代码 以上是环境变量数组,实际在 uboot 中以 hash 表的形式管理,数组到 hash 表,在 initr_env 函数中:
- init_sequence_r(uboot\common\board_r.c)
- static int initr_env(void)
- {
- /* initialize environment */
- if (should_load_env())
- env_relocate();
- else
- set_default_env(NULL); // 1111
- #ifdef CONFIG_OF_CONTROL
- setenv_addr("fdtcontroladdr", gd->fdt_blob);
- #endif
- /* Initialize from environment */
- load_addr = getenv_ulong("loadaddr", 16, load_addr);
- #if defined(CONFIG_SYS_EXTBDINFO)
- #if defined(CONFIG_405GP) || defined(CONFIG_405EP)
- #if defined(CONFIG_I2CFAST)
- /*
- * set bi_iic_fast for linux taking environment variable
- * "i2cfast" into account
- */
- {
- char *s = getenv("i2cfast");
- if (s && ((*s == 'y') || (*s == 'Y'))) {
- gd->bd->bi_iic_fast[0] = 1;
- gd->bd->bi_iic_fast[1] = 1;
- }
- }
- #endif /* CONFIG_I2CFAST */
- #endif /* CONFIG_405GP, CONFIG_405EP */
- #endif /* CONFIG_SYS_EXTBDINFO */
- return 0;
- }
- // -----------------------------------------------
- void set_default_env(const char *s)
- {
- int flags = 0;
- if (sizeof(default_environment) > ENV_SIZE) {
- puts("*** Error - default environment is too large\n\n");
- return;
- }
- if (s) {
- if (*s == '!') {
- printf("*** Warning - %s, "
- "using default environment\n\n",
- s + 1);
- } else {
- flags = H_INTERACTIVE;
- puts(s);
- }
- } else {
- puts("Using default environment\n\n");
- }
- if (himport_r(&env_htab, (char *)default_environment, // 创建 htab ,并添加 env 环境变量
- sizeof(default_environment), '\0', flags, 0,
- 0, NULL) == 0)
- error("Environment import failed: errno = %d\n", errno);
- gd->flags |= GD_FLG_ENV_READY;
- }
- // -----------------------------------------------
- int himport_r(struct hsearch_data *htab,
- const char *env, size_t size, const char sep, int flag,
- int crlf_is_lf, int nvars, char * const vars[])
- {
- char *data, *sp, *dp, *name, *value;
- char *localvars[nvars];
- int i;
- /* Test for correct arguments. */
- if (htab == NULL) {
- __set_errno(EINVAL);
- return 0;
- }
- /* we allocate new space to make sure we can write to the array */
- if ((data = malloc(size + 1)) == NULL) {
- debug("himport_r: can't malloc %zu bytes\n", size + 1);
- __set_errno(ENOMEM);
- return 0;
- }
- memcpy(data, env, size);
- data[size] = '\0';
- dp = data;
- /* make a local copy of the list of variables */
- if (nvars)
- memcpy(localvars, vars, sizeof(vars[0]) * nvars);
- if ((flag & H_NOCLEAR) == 0) {
- /* Destroy old hash table if one exists */
- debug("Destroy Hash Table: %p table = %p\n", htab,
- htab->table);
- if (htab->table)
- hdestroy_r(htab);
- }
- /*
- * Create new hash table (if needed). The computation of the hash
- * table size is based on heuristics: in a sample of some 70+
- * existing systems we found an average size of 39+ bytes per entry
- * in the environment (for the whole key=value pair). Assuming a
- * size of 8 per entry (= safety factor of ~5) should provide enough
- * safety margin for any existing environment definitions and still
- * allow for more than enough dynamic additions. Note that the
- * "size" argument is supposed to give the maximum environment size
- * (CONFIG_ENV_SIZE). This heuristics will result in
- * unreasonably large numbers (and thus memory footprint) for
- * big flash environments (>8,000 entries for 64 KB
- * envrionment size), so we clip it to a reasonable value.
- * On the other hand we need to add some more entries for free
- * space when importing very small buffers. Both boundaries can
- * be overwritten in the board config file if needed.
- */
- if (!htab->table) {
- int nent = CONFIG_ENV_MIN_ENTRIES + size / 8;
- if (nent > CONFIG_ENV_MAX_ENTRIES)
- nent = CONFIG_ENV_MAX_ENTRIES;
- debug("Create Hash Table: N=%d\n", nent);
- if (hcreate_r(nent, htab) == 0) {
- free(data);
- return 0;
- }
- }
- if (!size) {
- free(data);
- return 1; /* everything OK */
- }
- if(crlf_is_lf) {
- /* Remove Carriage Returns in front of Line Feeds */
- unsigned ignored_crs = 0;
- for(;dp < data + size && *dp; ++dp) {
- if(*dp == '\r' &&
- dp < data + size - 1 && *(dp+1) == '\n')
- ++ignored_crs;
- else
- *(dp-ignored_crs) = *dp;
- }
- size -= ignored_crs;
- dp = data;
- }
- /* Parse environment; allow for '\0' and 'sep' as separators */
- do {
- ENTRY e, *rv;
- /* skip leading white space */
- while (isblank(*dp))
- ++dp;
- /* skip comment lines */
- if (*dp == '#') {
- while (*dp && (*dp != sep))
- ++dp;
- ++dp;
- continue;
- }
- /* parse name */
- for (name = dp; *dp != '=' && *dp && *dp != sep; ++dp)
- ;
- /* deal with "name" and "name=" entries (delete var) */
- if (*dp == '\0' || *(dp + 1) == '\0' ||
- *dp == sep || *(dp + 1) == sep) {
- if (*dp == '=')
- *dp++ = '\0';
- *dp++ = '\0'; /* terminate name */
- debug("DELETE CANDIDATE: "%s"\n", name);
- if (!drop_var_from_set(name, nvars, localvars))
- continue;
- if (hdelete_r(name, htab, flag) == 0)
- debug("DELETE ERROR ##############################\n");
- continue;
- }
- *dp++ = '\0'; /* terminate name */
- /* parse value; deal with escapes */
- for (value = sp = dp; *dp && (*dp != sep); ++dp) {
- if ((*dp == '\\') && *(dp + 1))
- ++dp;
- *sp++ = *dp;
- }
- *sp++ = '\0'; /* terminate value */
- ++dp;
- if (*name == 0) {
- debug("INSERT: unable to use an empty key\n");
- __set_errno(EINVAL);
- free(data);
- return 0;
- }
- /* Skip variables which are not supposed to be processed */
- if (!drop_var_from_set(name, nvars, localvars))
- continue;
- /* enter into hash table */
- e.key = name;
- e.data = value;
- hsearch_r(e, ENTER, &rv, htab, flag);
- if (rv == NULL)
- printf("himport_r: can't insert "%s=%s" into hash table\n",
- name, value);
- debug("INSERT: table %p, filled %d/%d rv %p ==> name="%s" value="%s"\n",
- htab, htab->filled, htab->size,
- rv, name, value);
- } while ((dp < data + size) && *dp); /* size check needed for text */
- /* without '\0' termination */
- debug("INSERT: free(data = %p)\n", data);
- free(data);
- /* process variables which were not considered */
- for (i = 0; i < nvars; i++) {
- if (localvars[i] == NULL)
- continue;
- /*
- * All variables which were not deleted from the variable list
- * were not present in the imported env
- * This could mean two things:
- * a) if the variable was present in current env, we delete it
- * b) if the variable was not present in current env, we notify
- * it might be a typo
- */
- if (hdelete_r(localvars[i], htab, flag) == 0)
- printf("WARNING: '%s' neither in running nor in imported env!\n", localvars[i]);
- else
- printf("WARNING: '%s' not in imported env, deleting it!\n", localvars[i]);
- }
- debug("INSERT: done\n");
- return 1; /* everything OK */
- }
复制代码 以上内容更新到 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
<完>
|
|