`

uboot内核启动过程源码分析

 
阅读更多

下面是我对uboot如何启动内核的代码进行的分析

需要了解的数据结构:

bd 数据结构:

typedef struct bd_info {
int bi_baudrate; /* serial console baudrate */
unsigned long bi_ip_addr; /* IP Address */
struct environment_s *bi_env;
unsigned long bi_arch_number; /* unique id for this board */
unsigned long bi_boot_params; /* where this board expects params */
struct /* RAM configuration */
{
unsigned long start;
unsigned long size;
}bi_dram[CONFIG_NR_DRAM_BANKS];
} bd_t;


gd的数据结构:
typedef struct global_data {
bd_t *bd;
unsigned long flags;
unsigned long baudrate;
unsigned long have_console; /* serial_init() was called */
unsigned long env_addr; /* Address of Environment struct */
unsigned long env_valid; /* Checksum of Environment valid? */
unsigned long fb_base; /* base address of frame buffer */
#ifdef CONFIG_VFD
unsigned char vfd_type; /* display type */
#endif
#ifdef CONFIG_FSL_ESDHC
unsigned long sdhc_clk;
#endif
#if 0
unsigned long cpu_clk; /* CPU clock in Hz! */
unsigned long bus_clk;
phys_size_t ram_size; /* RAM size */
unsigned long reset_status; /* reset status register at boot */
#endif
void **jt; /* jump table */

} gd_t;


函数的入口,也就是分析开始的地方:

这里是do_bootm_linux()函数,先要进行一些初始化操作
bd_t *bd = gd->bd; //重要的数据结构bd->得到gd中的bd数据结构
char *s;
int machid = bd->bi_arch_number; //获得机器号码
void (*theKernel)(int zero, int arch, uint params); //申明一个函数指针,注意观察结构


#ifdef CONFIG_CMDLINE_TAG
char *commandline = getenv ("bootargs"); //如果定义了命令参数
#endif


theKernel = (void (*)(int, int, uint))images->ep; //其实这个函数就是指向内核的入口地址的,
//参数可见下面的结构体:
还需要了解的一个数据结构uImage给内核加的头:
typedef struct bootm_headers {
/*
* Legacy os image header, if it is a multi component image
* then boot_get_ramdisk() and get_fdt() will attempt to get
* data from second and third component accordingly.
*/
image_header_t *legacy_hdr_os; /* image header pointer */
image_header_t legacy_hdr_os_copy; /* header copy */
ulong legacy_hdr_valid;


#if defined(CONFIG_FIT)
const char *fit_uname_cfg; /* configuration node unit name */


void *fit_hdr_os; /* os FIT image header */
const char *fit_uname_os; /* os subimage node unit name */
int fit_noffset_os; /* os subimage node offset */


void *fit_hdr_rd; /* init ramdisk FIT image header */
const char *fit_uname_rd; /* init ramdisk subimage node unit name */
int fit_noffset_rd; /* init ramdisk subimage node offset */


void *fit_hdr_fdt; /* FDT blob FIT image header */
const char *fit_uname_fdt; /* FDT blob subimage node unit name */
int fit_noffset_fdt;/* FDT blob subimage node offset */
#endif


#ifndef USE_HOSTCC
image_info_t os; /* os image info */
ulong ep; /* entry point of OS */


ulong rd_start, rd_end;/* ramdisk start/end */


#ifdef CONFIG_OF_LIBFDT
char *ft_addr; /* flat dev tree address */
#endif
ulong ft_len; /* length of flat device tree */


ulong initrd_start;
ulong initrd_end;
ulong cmdline_start;
ulong cmdline_end;
bd_t *kbd;
#endif


int verify; /* getenv("verify")[0] != 'n' */


#define BOOTM_STATE_START (0x00000001)
#define BOOTM_STATE_LOADOS (0x00000002)
#define BOOTM_STATE_RAMDISK (0x00000004)
#define BOOTM_STATE_FDT (0x00000008)
#define BOOTM_STATE_OS_CMDLINE (0x00000010)
#define BOOTM_STATE_OS_BD_T (0x00000020)
#define BOOTM_STATE_OS_PREP (0x00000040)
#define BOOTM_STATE_OS_GO (0x00000080)
int state;


#ifdef CONFIG_LMB
struct lmb lmb; /* for memory mgmt */
#endif
} bootm_headers_t;
从上面的结构体中是可以看出来ep的作用的!


下面这个函数就是来设置起始参数的:跟踪
setup_start_tag (bd);
static void setup_start_tag (bd_t *bd)
{
params = (struct tag *) bd->bi_boot_params; //获得参数的起始地址,并且转换成tag结构体类型


params->hdr.tag = ATAG_CORE; //初始化params->hdr->tag
params->hdr.size = tag_size (tag_core); //初始化params->hdr->size


params->u.core.flags = 0;
params->u.core.pagesize = 0;
params->u.core.rootdev = 0;


params = tag_next (params);
}




#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size))


这里列出参数的结构体:
struct tag {
struct tag_header hdr;
union {
struct tag_core core;
struct tag_mem32 mem;
struct tag_videotext videotext;
struct tag_ramdisk ramdisk;
struct tag_initrd initrd;
struct tag_serialnr serialnr;
struct tag_revision revision;
struct tag_videolfb videolfb;
struct tag_cmdline cmdline;


/*
* Acorn specific
*/
struct tag_acorn acorn;


/*
* DC21285 specific
*/
struct tag_memclk memclk;
} u;


展开struct tag_header hdr;得到
struct tag_header {
u32 size;
u32 tag;
};

接下来就执到了setup_commandline_tag (bd, commandline)函数 //设置命令行参数,跟踪调试
我们观察一下这个宏:#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size))
表示现在params结构体指向tag结构体后面的部分!
下面这个函数就是来设置命令后参数的:跟踪
setup_commandline_tag (bd, commandline); //设置命令行参数,跟踪调试
static void setup_commandline_tag (bd_t *bd, char *commandline)
{
char *p;


if (!commandline)
return;


/* eat leading white space */
for (p = commandline; *p == ' '; p++);


/* skip non-existent command lines so the kernel will still
* use its default command line.
*/
if (*p == '\0')
return;


params->hdr.tag = ATAG_CMDLINE;
params->hdr.size = (sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;



strcpy (params->u.cmdline.cmdline, p);


params = tag_next (params);
}只是简单的复制参数!
最后会通过一个函数指针调用,完成启动内核:
theKernel (0, machid, bd->bi_boot_params); //真正的启动内核
大家肯定会有疑问:bd->bi_boot_params是在哪里设置的呢?
还记得void setup_start_tag (bd_t *bd)这个函数把,里面有一句:
params = (struct tag *) bd->bi_boot_params;
具体的请参考c和指针!
分享到:
评论

相关推荐

    史上最详细最全面的uboot启动过程分析

    UBOOT的主要功能是在设备启动时初始化硬件环境,设置内存空间,初始化设备外设,然后加载操作系统内核到RAM中去运行。本篇文章将详细介绍UBOOT启动过程的各个方面,为读者提供一个全面的了解。 1. 启动过程概述 ...

    uboot启动过程分析

    本文将重点探讨U-Boot的启动过程以及它如何将参数传递给内核并启动内核。 首先,U-Boot在启动过程中可以分为两个阶段。第一阶段负责硬件的初始化,而第二阶段则负责加载并启动操作系统内核。 在第一阶段,U-Boot...

    UBoot源码分析

    UBoot源码分析涉及到对Bootloader概念的理解、UBoot项目的起源和演变、UBoot存储空间分布的解析、UBoot与Linux内核的交互机制、以及UBoot如何调用Linux内核和传递启动参数的具体步骤。了解这些内容对于嵌入式系统...

    Uboot 移植 原理与源码分析

    ### Uboot 移植原理与源码分析 #### 一、概述 U-Boot(Universal Boot Loader)是一种广泛应用于嵌入式系统的引导加载程序。它能够支持多种处理器架构及操作系统,具备灵活性高、可移植性强的特点。对于嵌入式...

    正点原子Uboot和linux源码

    总结来说,"正点原子Uboot和Linux出厂源码"为开发者提供了一个宝贵的资源库,涵盖了从系统启动到运行的整个过程。无论是初学者还是经验丰富的工程师,都能从中获益,提高自己的专业技能。通过实际操作和实践,你将...

    UBoot源码分析及在S3C2440的移植过程_Uboot源码分析_uboot_UBOOT移植_

    《UBoot源码分析及在S3C2440的移植过程》是针对嵌入式系统开发者的一份宝贵资源,主要涵盖了UBoot的源码分析以及如何将其移植到S3C2440处理器平台上的详细步骤。这篇文章将深入探讨这一主题,旨在帮助读者理解和实践...

    UBOOT代码详细分析(88页PDF)

    - **启动流程**:从最开始的启动汇编代码,到初始化硬件设备,再到加载内核,U-Boot的启动过程涉及多个阶段。 - **数据结构**:U-Boot中使用了丰富的数据结构来管理和组织各种资源,如链表、队列等。 - **内存分配**...

    uboot启动源码

    《深入解析2440UBoot启动源码》 2440UBoot是针对Samsung S3C2440微处理器的引导加载程序,它在嵌入式系统开发中扮演着至关重要的角色。UBoot全称为Universal Boot Loader,是一款开放源代码的、功能强大的嵌入式...

    u-boot2017.01启动过程分析.pdf

    通过分析源码,本分析报告详细阐述了U-Boot启动过程中函数调用的流程,帮助读者深入理解U-Boot从初始化到加载操作系统内核的整个过程。 U-Boot启动过程可以分为以下几个主要阶段: 1. **SPL(Secondary Program ...

    Uboot源码分析

    2. **内核读取参数**:内核启动后,可以通过特定的数据结构(如`struct tag`)来读取U-Boot传递过来的参数。 ### U-Boot源码分析及移植 #### 源码分析 1. **总体结构**:U-Boot由多个模块组成,包括启动代码、...

    UBoot源码分析及在S3C2440的移植过程

    - **启动流程源码分析**:深入了解UBoot的启动流程,包括如何处理硬件中断、如何加载操作系统内核等,是移植成功的关键。这需要仔细阅读和理解UBoot的源码,尤其是那些与硬件交互紧密的函数和模块。 #### 结论 ...

    UBOOT启动后到KERNEL的过程

    通过《UBoot源码分析.pdf》,我们可以了解到UBOOT启动流程的细节,比如如何解析设备树,如何处理各种存储设备(如NAND、eMMC)的加载,以及如何优化UBOOT以适应不同平台的需求。 对于想要深入学习Android驱动和...

    ARM上电启动及Uboot代码分析

    Uboot(Uniform Bootloader)是一款开放源码的引导加载程序,它在启动过程中执行的任务包括硬件初始化、加载操作系统内核到内存、传递控制权给内核等。Uboot的源码结构清晰,模块化程度高,适合进行定制和扩展。 ...

    uboot-NAND启动详解

    UBoot源码提供了丰富的调试选项,可以帮助开发者理解启动过程并解决可能出现的问题。 6. **源码资源分析** "uboot-NAND启动详解"提供的源码资源可以进一步帮助开发者深入理解UBoot与NAND Flash的交互细节。通过...

    uboot 源码分析

    【uboot 源码分析】 UBoot,全称Universal Boot Loader,是一个开源的嵌入式设备引导加载程序,广泛应用于各种嵌入式系统,如单片机、SoC(System on Chip)以及嵌入式计算机等。它负责在硬件初始化后加载操作系统...

    uboot-三星源码

    `uboot`,全称是`U-Boot`,是通用引导加载程序(Universal Boot Loader)的缩写,它是一个开源项目,用于嵌入式设备的启动过程。uboot的主要任务是在系统硬件初始化之后加载操作系统内核,并将控制权传递给内核,...

    uboot源码分析

    在嵌入式系统领域,UBoot(Universal Boot Loader)作为一款广泛应用的引导加载器,其源码分析对于理解设备启动流程、系统初始化以及硬件驱动等核心概念至关重要。本文将围绕UBoot的三个关键阶段:Stage 1、Stage 2...

    Uboot启动之start.doc

    《UBoot启动过程详解:深入剖析start.s》 在嵌入式系统的世界里,UBoot作为引导加载器,是系统启动过程中的关键角色。本文将深入解析UBoot启动过程中的核心部分——`start.s`,它是UBoot启动的第一步,负责初始化...

    正点原子imx6ul板的Uboot和Linux出厂源码

    通过分析和修改Uboot源码,开发者可以实现对硬件特性的精细控制,例如串口设置、网络配置、设备树修改等,进一步优化系统的启动流程和性能。 Linux作为一款广泛使用的开源操作系统,其源码是理解系统工作原理、进行...

Global site tag (gtag.js) - Google Analytics