uboot linux内核传递参数,Uboot与Linux之间的参数传递详解
原标题:Uboot与Linux之间的参数传递详解
U-boot会给Linux Kernel传递很多参数,如:串口,RAM,videofb等。而Linux kernel也会读取和处理这些参数。两者之间通过struct tag来传递参数。U-boot把要传递给kernel的东西保存在struct tag数据结构中,启动kernel时,把这个结构体的物理地址传给kernel;Linux kernel通过这个地址,用parse_tags分析出传递过来的参数。
这里主要以U-boot传递RAM和Linux kernel读取RAM参数为例进行说明。
1、u-boot给kernel传RAM参数
./common/cmd_bootm.c文件中(指Uboot的根目录),bootm命令对应的do_bootm函数,当分析uImage中信息发现OS是Linux时,调用./lib_arm/bootm.c文件中的do_bootm_linux函数来启动Linux kernel。
在do_bootm_linux函数中:
void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
ulong addr, ulong *len_ptr, int verify)
{
......
#if defined (CONFIG_SETUP_MEMORY_TAGS) ||
defined (CONFIG_CMDLINE_TAG) ||
defined (CONFIG_INITRD_TAG) ||
defined (CONFIG_SERIAL_TAG) ||
defined (CONFIG_REVISION_TAG) ||
defined (CONFIG_LCD) ||
defined (CONFIG_VFD)
setup_start_tag (bd); //初始化tag结构体开始
#ifdef CONFIG_SERIAL_TAG
setup_serial_tag (¶ms);
#endif
#ifdef CONFIG_REVISION_TAG
setup_revision_tag (¶ms);
#endif
#ifdef CONFIG_SETUP_MEMORY_TAGS
setup_memory_tags (bd); //设置RAM参数
#endif
#ifdef CONFIG_CMDLINE_TAG
setup_commandline_tag (bd, commandline);
#endif
#ifdef CONFIG_INITRD_TAG
if (initrd_start && initrd_end)
setup_initrd_tag (bd, initrd_start, initrd_end);
#endif
#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
setup_videolfb_tag ((gd_t *) gd);
#endif
setup_end_tag (bd); //初始化tag结构体结束
#endif
......
......
theKernel (0, machid, bd->bi_boot_params);
//传给Kernel的参数= (struct tag *)型的bd->bi_boot_params
//bd->bi_boot_params在board_init函数中初始化,如对于at91rm9200,初始化在at91rm9200dk.c的board_init中进行:bd->bi_boot_params=PHYS_SDRAM + 0x100;
//这个地址也是所有taglist的首地址,见下面的setup_start_tag函数
}
对于setup_start_tag和setup_memory_tags函数说明如下。
函数setup_start_tag也在此文件中定义,如下:
static void setup_start_tag (bd_t *bd)
{
params = (struct tag *) bd->bi_boot_params;
//初始化(struct tag *)型的全局变量params为bd->bi_boot_params的地址,之后的setup tags相关函数如下面的setup_memory_tags就把其它tag的数据放在此地址的偏移地址上。
params->hdr.tag = ATAG_CORE;
params->hdr.size = tag_size (tag_core);
params->u.core.flags = 0;
params->u.core.pagesize = 0;
params->u.core.rootdev = 0;
params = tag_next (params);
}
RAM相关参数在bootm.c中的函数setup_memory_tags中初始化:
static void setup_memory_tags (bd_t *bd)
{
int i;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
params->hdr.tag = ATAG_MEM;
params->hdr.size = tag_size (tag_mem32);
params->u.mem.start = bd->bi_dram[i].start;
params->u.mem.size = bd->bi_dram[i].size;
params = tag_next (params);
} //初始化内存相关tag
}
2、Kernel读取U-boot传递的相关参数
对于Linux Kernel,ARM平台启动时,先执行arch/arm/kernel/head.S,此文件会调用arch/arm/kernel/head-common.S和arch/arm/mm/proc-arm920.S中的函数,并最后调用start_kernel:
......
b start_kernel
......
init/main.c中的start_kernel函数中会调用setup_arch函数来处理各种平台相关的动作,包括了u-boot传递过来参数的分析和保存:
start_kernel()
{
......
setup_arch(&command_line);
......
}
其中,setup_arch函数在arch/arm/kernel/setup.c文件中实现,如下:
void __init setup_arch(char **cmdline_p)
{
struct tag *tags = (struct tag *)&init_tags;
struct machine_desc *mdesc;
char *from = default_command_line;
setup_processor();
mdesc = setup_machine(machine_arch_type);
machine_name = mdesc->name;
if (mdesc->soft_reboot)
reboot_setup("s");
if (__atags_pointer)
//指向各种tag起始位置的指针,定义如下:
//unsigned int __atags_pointer __initdata;
//此指针指向__initdata段,各种tag的信息保存在这个段中。
tags = phys_to_virt(__atags_pointer);
else if (mdesc->boot_params)
tags = phys_to_virt(mdesc->boot_params);
if (tags->hdr.tag != ATAG_CORE)
convert_to_tag_list(tags);
if (tags->hdr.tag != ATAG_CORE)
tags = (struct tag *)&init_tags;
if (mdesc->fixup)
mdesc->fixup(mdesc, tags, &from, &meminfo);
if (tags->hdr.tag == ATAG_CORE) {
if (meminfo.nr_banks != 0)
squash_mem_tags(tags);
save_atags(tags);
parse_tags(tags);
//处理各种tags,其中包括了RAM参数的处理。
//这个函数处理如下tags:
__tagtable(ATAG_MEM, parse_tag_mem32);
__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
__tagtable(ATAG_SERIAL, parse_tag_serialnr);
__tagtable(ATAG_REVISION, parse_tag_revision);
__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
}
init_mm.start_code = (unsigned long) &_text;
init_mm.end_code = (unsigned long) &_etext;
init_mm.end_data = (unsigned long) &_edata;
init_mm.brk = (unsigned long) &_end;
memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
boot_command_line[COMMAND_LINE_SIZE-1] = '0';
parse_cmdline(cmdline_p, from); //处理编译内核时指定的cmdline或u-boot传递的cmdline
paging_init(&meminfo, mdesc);
request_standard_resources(&meminfo, mdesc);
#ifdef CONFIG_SMP
smp_init_cpus();
#endif
cpu_init();
init_arch_irq = mdesc->init_irq;
system_timer = mdesc->timer;
init_machine = mdesc->init_machine;
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
conswitchp = &dummy_con;
#endif
#endif
early_trap_init();
}
对于处理RAM的tag,调用了parse_tag_mem32函数:
static int __init parse_tag_mem32(const struct tag *tag)
{
......
arm_add_memory(tag->u.mem.start, tag->u.mem.size);
......
}
__tagtable(ATAG_MEM, parse_tag_mem32);
上述的arm_add_memory函数定义如下:
static void __init arm_add_memory(unsigned long start, unsigned long size)
{
struct membank *bank;
size -= start & ~PAGE_MASK;
bank = &meminfo.bank[meminfo.nr_banks++];
bank->start = PAGE_ALIGN(start);
bank->size = size & PAGE_MASK;
bank->node = PHYS_TO_NID(start);
}
如上可见,parse_tag_mem32函数调用arm_add_memory函数把RAM的start和size等参数保存到了meminfo结构的meminfo结构体中。最后,在setup_arch中执行下面语句:
paging_init(&meminfo, mdesc);
对没有MMU的平台上调用arch/arm/mm/nommu.c中的paging_init,否则调用arch/arm/mm/mmu.c中的paging_init函数。这里暂不分析mmu.c中的paging_init函数。
3、关于U-boot中的bd和gd
U-boot中有一个用来保存很多有用信息的全局结构体--gd_t(global data缩写),其中包括了bd变量,可以说gd_t结构体包括了u-boot中所有重要全局变量。最后传递给内核的参数,都是从gd和bd中来的,如上述的setup_memory_tags函数的作用就是用bd中的值来初始化RAM相应的tag。
对于ARM平台这个结构体的定义大致如下:
include/asm-arm/global_data.h
typedef struct global_data {
bd_t *bd;
unsigned long flags;
unsigned long baudrate;
unsigned long have_console; /* serial_init() was called */
unsigned long reloc_off; /* Relocation Offset */
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 */
void **jt; /* jump table */
} gd_t;
在U-boot中使用gd结构之前要用先用宏DECLARE_GLOBAL_DATA_PTR来声明。这个宏的定义如下:
include/asm-arm/global_data.h
#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r8")
从这个宏的定义可以看出,gd是一个保存在ARM的r8寄存器中的gd_t结构体的指针。
本文的版本为U-boot-1.3.4、Linux-2.6.28,平台是ARM。返回搜狐,查看更多
责任编辑:
uboot linux内核传递参数,Uboot与Linux之间的参数传递详解相关推荐
- 使用ioctl向linux内核传递参数的方法实例
该篇实例是摘自网络(无法追根溯源倒低是哪位"前"辈写的了) 一.应用层 uint16 data16; if ((fd = socket(AF_INET, SOCK_STREAM, ...
- linux 内核定时器精度_linux使用select实现精确定时器详解
在编写程序时,我们经常会用到定时器.首先看看select函数原型如下: int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set * ...
- linux内核镜像的分层,Docker镜像分层的原理详解
base镜像 base镜像有两层含义: 不依赖其他镜像,从scratch构建 其他镜像可以之为基础进行扩展 所以,base镜像一般都是各种Linux发行版本的Docker镜像,比如:Ubuntu,De ...
- linux ssh keygen参数,SSH的ssh-keygen命令基本用法详解
ssh 公钥认证是ssh认证的方式之一.通过公钥认证可实现ssh免密码登陆,git的ssh方式也是通过公钥进行认证的. 在用户目录的home目录下,有一个.ssh的目录,和当前用户ssh配置认证相关的 ...
- uboot环境变量(设置bootargs向linux内核传递正确的参数)
http://blog.csdn.net/workhorse/article/details/7071428 这是我uboot的环境变量设置,在该设置下可以运行initram内核(从内存下载到nand ...
- 指出Linux内核中boot,uBoot和Linux内核中涉及到的几个地址参数的理解
************************************************* arch/arm/Makefile //内核运行虚拟地址TEXTADDR = 0xC0008000 ...
- linux内核网络参数tcp_tw_recycle 和 tcp_tw_reuse 你搞清楚了吗?
Docker 技术鼻祖系列 原文链接:https://blog.csdn.net/u010278923/article/details/102663535 今天在生产环境遇到了一个奇怪的网络现象,通过 ...
- 移植linux内核-映像文件,移植Linux内核-映像文件
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明 http://tigerwang202.blogbus.com/logs/43927976.html 首先从Blackfin uCli ...
- Linux内核编程(二)-----------Linux内核初探
写在前面:本篇主要介绍Linux内核的开发模式.linux代码的组成.vmlinux zImage uImage的区别,以及编译下内核. 正文: 一.Linux内核的开发模式 1.git:是一个分 ...
最新文章
- 教育部发文:AI、算法等2018年进入全国高中课程!
- 当会打王者荣耀的AI学会踢足球,一不小心拿下世界冠军!
- rust军用船指令_Rust基础学习笔记(五):Cargo与Crates.io
- GridView 通用分页
- 测试工程师职业素养:懂得拒绝无效工作
- 51Nod-1002 数塔取数问题【DP】
- python,tensorflow,CNN实现mnist数据集的训练与验证正确率
- 安徽省考计算机专业知识分值分布,安徽省考行测题型分布和分值
- 傻瓜式自制鼠标光标,超简单
- 如何活跃社群,提高转化
- 特殊符号,emoji表情,四字节去除问题
- freebsd MySQL 提权_Intel Sysret (CVE-2012-0217)内核提权漏洞
- 汉化MapGuide
- 2015NOIP初赛错题整理
- Java版工程行业管理系统源码-专业的工程管理软件-提供一站式服务
- A-Frame基础用法
- IIS中没有frontpage服务器扩展解决方法
- 10.4.4 51单片机控制系统8个LED“跑马灯”实验
- 手机移动端可滚动的导航代码--css解决方案
- Openssl-rc5
热门文章
- R语言使用upper.tri函数、lower.tri函数、diag函数改变matrix矩阵上三角形、下三角形、对角线的数值
- R语言ggplot2可视化使用facet_grid构建多个子图(facet、面图)并自定义每个子图(facet、面图)的文本实战
- Error in install.packages : cannot remove prior installation of package
- 病理分析常见数据集及常用模型方法总结
- 如何理解python的类与对象
- 生命科学领域颠覆性技术——基因测序
- MATLAB 半球面
- 计算机应用基础 网上教学设计方案,《计算机应用基础》(本)教学设计方案.doc...
- 3dsmax biped 骨骼的创建和修改
- element ui input 无法输入的解决办法