uboot内核启动过程源码分析
来源:互联网 发布:多玩魔兽盒子mac版 编辑:程序博客网 时间:2024/05/30 04:16
下面是我对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 structglobal_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_tlegacy_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_corecore;
struct tag_mem32mem;
struct tag_videotextvideotext;
struct tag_ramdiskramdisk;
struct tag_initrdinitrd;
struct tag_serialnrserialnr;
struct tag_revisionrevision;
struct tag_videolfbvideolfb;
struct tag_cmdlinecmdline;
/*
* Acorn specific
*/
struct tag_acornacorn;
/*
* DC21285 specific
*/
struct tag_memclkmemclk;
} 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 - 启动内核过程分析
- uboot源码及启动过程分析
- 分析uboot启动内核
- UBOOT启动过程分析
- uboot源码分析——启动linux内核
- 6、uboot源码——内核启动分析
- uboot分析之uboot启动内核分析
- 【一】Uboot-2017.11源码分析启动过程之汇编部分
- uboot分析之uboot启动过程分析
- uboot启动内核代码分析
- 简单分析uboot启动内核
- uboot启动过程完全分析
- uboot启动过程完全分析
- uboot启动过程完全分析
- Uboot 源码分析----启动代码
- uboot源码分析-启动第一阶段
- 嵌入式linux开发uboot移植(三)——uboot启动过程源码分析
- Java反射机制 访问类的私有成员
- 摄像测量学简介
- MVC 3 TempData深入研究(跳转Action中没有取TempData的思考)
- 在MSYS下用MingW GCC编译libgmp的一个小问题及解决方法
- rails3 数据 migration 之二 - 创建一个migration
- uboot内核启动过程源码分析
- Applet制作动态按钮(图像、声音的切换)
- 为什么父类指针可以指向子类反之则不行
- 制作ECC证书
- prim算法的简单证明
- 使用jQuery获得选中复选框个数
- poj 1028 stack模拟网页
- POJ 2575 Jolly Jumpers(我的水题之路——数组绝对差值为1到n-1)
- 使用jQuery操纵表格-增加、删除行和列