下面是我对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的主要功能是在设备启动时初始化硬件环境,设置内存空间,初始化设备外设,然后加载操作系统内核到RAM中去运行。本篇文章将详细介绍UBOOT启动过程的各个方面,为读者提供一个全面的了解。 1. 启动过程概述 ...
本文将重点探讨U-Boot的启动过程以及它如何将参数传递给内核并启动内核。 首先,U-Boot在启动过程中可以分为两个阶段。第一阶段负责硬件的初始化,而第二阶段则负责加载并启动操作系统内核。 在第一阶段,U-Boot...
UBoot源码分析涉及到对Bootloader概念的理解、UBoot项目的起源和演变、UBoot存储空间分布的解析、UBoot与Linux内核的交互机制、以及UBoot如何调用Linux内核和传递启动参数的具体步骤。了解这些内容对于嵌入式系统...
### Uboot 移植原理与源码分析 #### 一、概述 U-Boot(Universal Boot Loader)是一种广泛应用于嵌入式系统的引导加载程序。它能够支持多种处理器架构及操作系统,具备灵活性高、可移植性强的特点。对于嵌入式...
总结来说,"正点原子Uboot和Linux出厂源码"为开发者提供了一个宝贵的资源库,涵盖了从系统启动到运行的整个过程。无论是初学者还是经验丰富的工程师,都能从中获益,提高自己的专业技能。通过实际操作和实践,你将...
《UBoot源码分析及在S3C2440的移植过程》是针对嵌入式系统开发者的一份宝贵资源,主要涵盖了UBoot的源码分析以及如何将其移植到S3C2440处理器平台上的详细步骤。这篇文章将深入探讨这一主题,旨在帮助读者理解和实践...
- **启动流程**:从最开始的启动汇编代码,到初始化硬件设备,再到加载内核,U-Boot的启动过程涉及多个阶段。 - **数据结构**:U-Boot中使用了丰富的数据结构来管理和组织各种资源,如链表、队列等。 - **内存分配**...
《深入解析2440UBoot启动源码》 2440UBoot是针对Samsung S3C2440微处理器的引导加载程序,它在嵌入式系统开发中扮演着至关重要的角色。UBoot全称为Universal Boot Loader,是一款开放源代码的、功能强大的嵌入式...
通过分析源码,本分析报告详细阐述了U-Boot启动过程中函数调用的流程,帮助读者深入理解U-Boot从初始化到加载操作系统内核的整个过程。 U-Boot启动过程可以分为以下几个主要阶段: 1. **SPL(Secondary Program ...
2. **内核读取参数**:内核启动后,可以通过特定的数据结构(如`struct tag`)来读取U-Boot传递过来的参数。 ### U-Boot源码分析及移植 #### 源码分析 1. **总体结构**:U-Boot由多个模块组成,包括启动代码、...
- **启动流程源码分析**:深入了解UBoot的启动流程,包括如何处理硬件中断、如何加载操作系统内核等,是移植成功的关键。这需要仔细阅读和理解UBoot的源码,尤其是那些与硬件交互紧密的函数和模块。 #### 结论 ...
通过《UBoot源码分析.pdf》,我们可以了解到UBOOT启动流程的细节,比如如何解析设备树,如何处理各种存储设备(如NAND、eMMC)的加载,以及如何优化UBOOT以适应不同平台的需求。 对于想要深入学习Android驱动和...
Uboot(Uniform Bootloader)是一款开放源码的引导加载程序,它在启动过程中执行的任务包括硬件初始化、加载操作系统内核到内存、传递控制权给内核等。Uboot的源码结构清晰,模块化程度高,适合进行定制和扩展。 ...
UBoot源码提供了丰富的调试选项,可以帮助开发者理解启动过程并解决可能出现的问题。 6. **源码资源分析** "uboot-NAND启动详解"提供的源码资源可以进一步帮助开发者深入理解UBoot与NAND Flash的交互细节。通过...
【uboot 源码分析】 UBoot,全称Universal Boot Loader,是一个开源的嵌入式设备引导加载程序,广泛应用于各种嵌入式系统,如单片机、SoC(System on Chip)以及嵌入式计算机等。它负责在硬件初始化后加载操作系统...
`uboot`,全称是`U-Boot`,是通用引导加载程序(Universal Boot Loader)的缩写,它是一个开源项目,用于嵌入式设备的启动过程。uboot的主要任务是在系统硬件初始化之后加载操作系统内核,并将控制权传递给内核,...
在嵌入式系统领域,UBoot(Universal Boot Loader)作为一款广泛应用的引导加载器,其源码分析对于理解设备启动流程、系统初始化以及硬件驱动等核心概念至关重要。本文将围绕UBoot的三个关键阶段:Stage 1、Stage 2...
《UBoot启动过程详解:深入剖析start.s》 在嵌入式系统的世界里,UBoot作为引导加载器,是系统启动过程中的关键角色。本文将深入解析UBoot启动过程中的核心部分——`start.s`,它是UBoot启动的第一步,负责初始化...
通过分析和修改Uboot源码,开发者可以实现对硬件特性的精细控制,例如串口设置、网络配置、设备树修改等,进一步优化系统的启动流程和性能。 Linux作为一款广泛使用的开源操作系统,其源码是理解系统工作原理、进行...