设备树chosen节点的bootargs参数介绍

设备树的根目录下的chosen节点是一个特殊的节点, 它用作uboot 像内核传递参数.这里简单介绍如何使用bootargs参数从uboot传递参数到内核.

1. 如何查看bootargs的值?

        cat /sys/firmware/devicetree/base/chosen/bootargs 命令可以查看最终的bootargs值.

        bootargs会作为linux内核启动时的命令行参数,在内核启动过程中也会打印bootargs参数,关键字"Kernel command line:"

2. uboot中如何添加传递到内核的参数.

        uboot传递参数到内核的实现原理:uboot启动内核时会先加载设备树. uboot加载设备树后就可以读取设备树里的内容,这里就是读取chose节点的bootargs属性, 然后在bootargs属性中追加要传递到内核的属性,最后写回到设备树即可.

        uboot提供了一组fdt_xxx()函数,定义在lib/libfdt 目录下, 使用库里面提供的API即可修改,添加设备树节点的属性.例如下面是一个封装好的,用于向bootargs追加属性的函数实现:

/**
 * @brief 向 bootargs 添加属性
 * 
 * @param fdt 加载到内存中的设备树起始地址
 * @param append_args 要添加的属性字符串,例如"lcd_id=0x98"
 * @param force 强制写,这是自定义的.
 * @return int 
 */
int fdt_chosen_bootargs_append(void *fdt, char *append_args, int force)
{
	int nodeoffset;
	int err;
	const char *path;
	char *strargs;
	int size;

	if (!append_args)
		return -1;

    /**
     * @brief fdt 是加载的设备树在内存中的起始地址.
     *      fdt_check_header函数可以检查这个地址是不是一个有效的设备树
     */
	err = fdt_check_header(fdt);
	if (err < 0) {
		errorf("fdt_chosen_bootargs_append: %s\n", fdt_strerror(err));
		return err;
	}

	/*
	 * 查找 "chosen" 节点.
     * 成功返回节点的偏移地址,失败返回负数.
	 */
	nodeoffset = fdt_path_offset(fdt, "/chosen");


	/*
	 * If the property exists, update it only if the "force" parameter
	 * is true.
     * 如果设备树里bootargs属性存在 fdt_getprop 返回属性字符串,否则返回0
	 */
	path = fdt_getprop(fdt, nodeoffset, "bootargs", NULL);
	if ((path == NULL) || force) {
		strargs = malloc(MAX_BOOTARG_LEN+1);
		if (!strargs)
			return -1;

        /**
         * @brief 这里bootargs 属性的最大限制是4K
         * 
         */
		memset(strargs, 0, MAX_BOOTARG_LEN+1);
		if(path != NULL)
		{
			size = strlen(path) + strlen(append_args);
			if (size > (MAX_BOOTARG_LEN - 1)) {
				errorf("bootargs len:%d overflow (MAX_BOOTARG_LEN-1)\n", size);
				free(strargs);
				return -1;
			}
			sprintf(strargs, "%s %s", path, append_args);
		}
		else
		{
			size = strlen(append_args);
			if (size > MAX_BOOTARG_LEN) {
				errorf("bootargs len:%d overflow MAX_BOOTARG_LEN\n", size);
				free(strargs);
				return -1;
			}
			sprintf(strargs, "%s", append_args);
		}

        /**
         * @brief 设置好bootargs后就写回去.
         * 
         */
		err = fdt_setprop(fdt, nodeoffset, "bootargs", strargs, strlen(strargs) + 1);
		if (err < 0)
			errorf("could not set bootargs %s.\n", fdt_strerror(err));
		free(strargs);
	}

	return err;
}

        追加的属性是形如"lcd_id=0x96" xxx=xxx的字符串.这和linux内核设备树中的设置是一致的.

3.  linux驱动中是否如何获取uboot传递过来的参数?

        linux驱动中可以使用内核提供的宏定义直接得到uboot传递过来的参数如下:

static int __init chipid_base_get(char *str)
{
	printk(KERN_ERR "chipid_base_get = %s",str);
	return 0;
}
__setup("msocid=", chipid_base_get);

例如在uboot里使用函数fdt_chosen_bootargs_append(xxx,"msocid=hello\0",1); 添加了属性. 驱动里就可以按照上方的定义,linux内核启动后就会执行chipid_base_get 函数. 宏定义__setup() 介绍可以参考"linux kernel中__setup()函数介绍_setup linux kernel-CSDN博客"
文章参考:

linux kernel中__setup()函数介绍_setup linux kernel-CSDN博客

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值