linux 传参解析过程

 
bootargs=console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc 
rootfstype=ext3

console=ttySAC2,115200 控制台使用串口2,波特率115200.
root=/dev/mmcblk0p2 rw 
根文件系统在SD卡端口0设备(iNand)第2分区,根文件系统是读可写的
init=/linuxrc linux的进程1(init进程)的路径
rootfstype=ext3 根文件系统的类型是ext3

uboot中有一个命令叫bdinfo,这个命令可以打印出gd->
bd中记录的所有硬件相关的全局变量的值,因此可以得知DDR配置信息

#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
#define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2)
/* The list must start with an ATAG_CORE node 
列表必须以ATAG_CORE节点开始*/
#define ATAG_CORE    0x54410001  atag list启动幻数

    /*
     * r1 = machine no机器编号, r2 = atags标签,
     * r8 = phys_offset, r9 = cpuid, r10 = procinfo
     */

__vet_atags:
    tst    r2, #0x3            @ aligned?对齐  11
    bne    1f

    ldr    r5, [r2, #0]            @ is first tag ATAG_CORE?
    cmp    r5, #ATAG_CORE_SIZE
    cmpne    r5, #ATAG_CORE_SIZE_EMPTY
    bne    1f
    ldr    r5, [r2, #4]
    ldr    r6, =ATAG_CORE
    cmp    r5, r6
    bne    1f

    mov    pc, lr                @ atag pointer is ok

1:    mov    r2, #0
    mov    pc, lr
ENDPROC(__vet_atags)

void __vet_atags(struct tag* atag_list)
{
    if(atag_list & 0x3)
        goto err_clear;

    if(!(atag_list->hdr.size == ARAG_CORE_SIZE && agag_list->hdr.tag == 
ATAG_CORE)){
        goto err_clear;
    }

    return;

err_clear:
    atag_list = 0;
    return;
}

1内核选中CONFIG_ARM_APPENDED_DTB,这样编译出的dtb就存放在内核i
mg的末尾,内核可以自己取出dtb。
2内核选中CONFIG_ARM_ATAG_DTB_COMPAT,指定atags和dtb的兼容。
3uboot传递atags指针到r2,启动内核
4内核自己取出dtb,然后将r2指针内的atags通过atags_to_fdt()
函数解析并合并到dtb中,最后使用合并好的dtb。

上面是内核初步的对照查看结构是否合适(tag的头部是否正)

/* Arch code calls this early on, or if not, just before other parsing. */
Arch代码会在其他解析之前尽早调用此功能,如果不是,则调
用此功能
#define COMMAND_LINE_SIZE    256
/* Untouched command line saved by arch-specific code. */
拱形特定代码保存的未修改的命令行。
char __initdata boot_command_line[COMMAND_LINE_SIZE];
引导完成后,将删除标记为__ 
init的函数和标记为__initdata的数据结构

void __init parse_early_param(void)
{
    static __initdata int done = 0;
    static __initdata char tmp_cmdline[COMMAND_LINE_SIZE];

    if (done)
        return;

    /* All fall through to do_early_param. */
    strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
    parse_early_options(tmp_cmdline);
    done = 1;
}

void __init parse_early_options(char *cmdline)
{
    parse_args("early options", cmdline, NULL, 0, do_early_param);
}

/* Check for early params. */
检查早期参数。
static int __init do_early_param(char *param, char *val)
{
    const struct obs_kernel_param *p;

    for (p = __setup_start; p < __setup_end; p++) {
        if ((p->early && strcmp(param, p->str) == 0) ||
            (strcmp(param, "console") == 0 &&
             strcmp(p->str, "earlycon") == 0)
        ) {
            if (p->setup_func(val) != 0)
                printk(KERN_WARNING
                       "Malformed early option '%s'\n", param);
        }
    }
    /* We accept everything at this stage. */
    return 0;
}

#if 0
#define DEBUGP printk
#else
#define DEBUGP(fmt, a...)
#endif
/* Args looks like "foo=bar,bar2 baz=fuz wiz". */
int parse_args(const char *name,
           char *args,
           const struct kernel_param *params,
           unsigned num,
           int (*unknown)(char *param, char *val))
{
    char *param, *val;

    DEBUGP("Parsing ARGS: %s\n", args);

    /* Chew leading spaces */
    args = skip_spaces(args);

    while (*args) {
        int ret;
        int irq_was_disabled;

        args = next_arg(args, &param, &val);
        irq_was_disabled = irqs_disabled();
        ret = parse_one(param, val, params, num, unknown);
        if (irq_was_disabled && !irqs_disabled()) {
            printk(KERN_WARNING "parse_args(): option '%s' enabled "
                    "irq's!\n", param);
        }
        switch (ret) {
        case -ENOENT:
            printk(KERN_ERR "%s: Unknown parameter `%s'\n",
                   name, param);
            return ret;
        case -ENOSPC:
            printk(KERN_ERR
                   "%s: `%s' too large for parameter `%s'\n",
                   name, val ?: "", param);
            return ret;
        case 0:
            break;
        default:
            printk(KERN_ERR
                   "%s: `%s' invalid for parameter `%s'\n",
                   name, val ?: "", param);
            return ret;
        }
    }

    /* All parsed OK. */
    return 0;
}

 

struct kernel_param {
    const char *name;
    const struct kernel_param_ops *ops;
    u16 perm;
    u16 flags;
    union {
        void *arg;
        const struct kparam_string *str;
        const struct kparam_array *arr;
    };
};

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值