IMX8 UBOOT源码分析(十)fdtdec_setup函数分析

这篇博客主要分析 init_sequence_f 函数指针数组中的fdtdec_setup函数:

  #ifdef CONFIG_OF_CONTROL                                //在.config中CONFIG_OF_CONTROL=y
                      fdtdec_setup,
                #endif         

 int fdtdec_setup(void)
               {
               #if CONFIG_IS_ENABLED(OF_CONTROL)            //在.config中CONFIG_OF_CONTROL=y
               # if CONFIG_IS_ENABLED(MULTI_DTB_FIT)        //在.config中CONFIG_MULTI_DTB_FIT未定义
                              void *fdt_blob;
               # endif

               # ifdef CONFIG_OF_EMBED                                   //在.config中CONFIG_OF_EMBED未定义
               #  ifdef CONFIG_SPL_BUILD
                              gd->fdt_blob = __dtb_dt_spl_begin;
               #  else
                              gd->fdt_blob = __dtb_dt_begin;
               #  endif

               # elif defined(CONFIG_OF_BOARD) || defined(CONFIG_OF_SEPARATE)

                              //在.config中CONFIG_OF_BOARD未定义,CONFIG_OF_SEPARATE=y
                              gd->fdt_blob = board_fdt_blob_setup();

                               __weak void *board_fdt_blob_setup(void)
                               {
                                       void *fdt_blob = NULL;
                               
#ifdef CONFIG_SPL_BUILD
                                       if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS))
                                       fdt_blob = (ulong *)&_image_binary_end;
                                       else
                                              fdt_blob = (ulong *)&__bss_end;

                               #else
                                       fdt_blob = (ulong *)&_end;
                               #endif
                                       return fdt_blob;
                               }

                               //gd->fdt_blob=(ulong *)&_end;
               # elif defined(CONFIG_OF_HOSTFILE)
               if (sandbox_read_fdt_from_file()) {
                              puts("Failed to read control FDT\n");
                              return -1;
               }
               # endif

               # ifndef CONFIG_SPL_BUILD
               #  if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)                     //CONFIG_OF_PRIOR_STAGE在.config中设为未定义
                              gd->fdt_blob = (void *)prior_stage_fdt_address;
               #  else
                              gd->fdt_blob = map_sysmem(env_get_ulong("fdtcontroladdr", 16,(unsigned long)map_to_sysmem(gd->fdt_blob)), 0);

                             static inline phys_addr_t map_to_sysmem(const void *ptr)
                             {
                                        return (phys_addr_t)(uintptr_t)ptr;           
 //typedef unsigned long long phys_addr_t
                             }

                             //env_get_ulong的第三个参数default_val=gd->fdt_blob=&_end

                             ulong env_get_ulong(const char *name, int base, ulong default_val)
                             {
                                        const char *str = env_get(name);             
 //根据传入的fdtcontroladdr调用env_get查询变量值      

                                        char *env_get(const char *name)
                                        {
                                              
 if (gd->flags & GD_FLG_ENV_READY) {                    //gd->flags=0
                                               ENTRY e, *ep;

                                               WATCHDOG_RESET();

                                               e.key    = name;
                                               e.data    = NULL;
                                               hsearch_r(e, FIND, &ep, &env_htab, 0);

                                               return ep ? ep->data : NULL;
                                               }

                                               if (env_get_f(name, (char *)(gd->env_buf), sizeof(gd->env_buf)) > 0)
                                               return (char *)(gd->env_buf);

                                               return NULL;
                                        }

                                        //env_get调用env_get_f来查询fdtcontroladdr环境变量值                                  

                                        int env_get_f(const char *name, char *buf, unsigned len)
                                        {
                                               int i, nxt, c;

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

                                               //env_get_char(i)等价于default_environment[i]
                                                        int val, n;

                                                        for (nxt = i; (c = env_get_char(nxt)) != '\0'; ++nxt) {
                                                                  if (c < 0)
                                                                          return c;
                                                                  if (nxt >= CONFIG_ENV_SIZE)
                                                                          return -1;
                                                        }

                                                        val = envmatch((uchar *)name, i);   

                                                        //从default_environment中查询匹配name(fdtcontroladdr)的变量

                                                        static char default_environment[] = {
                                                                      "bootcmd="    CONFIG_BOOTCOMMAND        "\0"
                                                                      "bootdelay="    __stringify(CONFIG_BOOTDELAY)    "\0"
                                                                      "baudrate="    __stringify(CONFIG_BAUDRATE)    "\0"
                                                                      "loadaddr="    __stringify(CONFIG_LOADADDR)    "\0"
                                                                      "script=boot.scr\0" \
                                                                      "image=Image\0" \
                                                                      "panel=NULL\0" \
                                                                      "console=ttyLP0,${baudrate} earlycon=lpuart32,0x5a060000,${baudrate}\0" \
                                                                      "fdt_addr=0x83000000\0"            \
                                                                      "fdt_high=0xffffffffffffffff\0"        \
                                                                      "boot_fdt=try\0" \
                                                                      "fdt_file=fsl-imx8qxp-mek.dtb\0" \
                                                                      "initrd_addr=0x83800000\0"        \
                                                                      "initrd_high=0xffffffffffffffff\0" \
                                                                      "mmcdev="__stringify(CONFIG_SYS_MMC_ENV_DEV)"\0" \
                                                                      "mmcpart=" __stringify(CONFIG_SYS_MMC_IMG_LOAD_PART) "\0" \
                                                                      "mmcroot=" CONFIG_MMCROOT " rootwait rw\0" \
                                                                      "mmcautodetect=yes\0" \
                                                                      "mmcargs=setenv bootargs console=${console} root=${mmcroot}\0 " \
                                                                      "loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};\0" \
                                                                      "bootscript=echo Running bootscript from mmc ...; " \
                                                                      "source\0" \
                                                                      "loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}\0" \
                                                                      "loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}\0" \
                                                                      "mmcboot=echo Booting from mmc ...; " \
                                                                      "run mmcargs; " \
                                                                      "if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
                                                                      "if run loadfdt; then " \
                                                                               "booti ${loadaddr} - ${fdt_addr}; " \
                                                                      "else " \
                                                                               "echo WARN: Cannot load the DT; " \
                                                                      "fi; " \
                                                                      "else " \
                                                                               "echo wait for boot; " \
                                                                      "fi;\0" \
                                                                      "netargs=setenv bootargs console=${console} " \
                                                                      "root=/dev/nfs " \
                                                                      "ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0" \
                                                                      "netboot=echo Booting from net ...; " \
                                                                      "run netargs;  " \
                                                                      "if test ${ip_dyn} = yes; then " \
                                                                               "setenv get_cmd dhcp; " \
                                                                      "else " \
                                                                               "setenv get_cmd tftp; " \
                                                                      "fi; " \
                                                                      "${get_cmd} ${loadaddr} ${image}; " \
                                                                      "if test ${boot_fdt} = yes || test ${boot_fdt} = try; then " \
                                                                             "if ${get_cmd} ${fdt_addr} ${fdt_file}; then " \
                                                                                   "booti ${loadaddr} - ${fdt_addr}; " \
                                                                             "else " \
                                                                                    "echo WARN: Cannot load the DT; " \
                                                                              "fi; " \
                                                                      "else " \
                                                                              "booti; " \
                                                                      "fi;\0"
                                                                      "\0"
                                                        }

                                                        //在default_environment中没有fdtcontroladdr参数
                                                        if (val < 0)
                                                                 continue;
                                                       
 for (n = 0; n < len; ++n, ++buf) {
                                                                    c = env_get_char(val++);
                                                                    if (c < 0)
                                                                             return c;
                                                                    *buf = c;
                                                                    if (*buf == '\0')
                                                                             return n;
                                                        }

                                                        if (n)
                                                             *--buf = '\0';

                                                        printf("env_buf [%u bytes] too small for value of \"%s\"\n",len, name);

                                                        return n;
                                               }

                                               return -1;
                                        }

                                        //env_get_f返回-1,则env_get返回NULL,即str=NULL

                                        return str ? simple_strtoul(str, NULL, base) : default_val;
                             }

                             //env_get_ulong返回默认值default_val=gd->fdt_blob=&_end

                             static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
                             {
                                       return (void *)(uintptr_t)paddr;                   //typedef unsigned long int uintptr_t
                             }

                             //最终gd->fdt_blob=&_end
               #  endif
               # endif

               # if CONFIG_IS_ENABLED(MULTI_DTB_FIT)                 //CONFIG_MULTI_DTB_FIT在.config中设置为未定义
               if (uncompress_blob(gd->fdt_blob, 0x1000000, &fdt_blob) == 0)
                              gd->fdt_blob = fdt_blob;
               fdt_blob = locate_dtb_in_fit(gd->fdt_blob);
               if (fdt_blob) {
                              gd->multi_dtb_fit = gd->fdt_blob;
                              gd->fdt_blob = fdt_blob;
               }

               # endif
               #endif

                               return fdtdec_prepare_fdt();               //检查在gd->fdt_blob处是否存在dtb
               }

               通过本文的分析,我们知道dtb文件放在&_end处,_end在链接文件定义。

               fdtdec_setup的作用就是讲dtb文件的地址放入gd->fdt_blob处

猜你喜欢

转载自blog.csdn.net/yanggx0929/article/details/88785167