개발/arm64 linux 6 분석

early_param (setup_arch)

clucle 2025. 5. 31. 19:06
void __init __no_sanitize_address setup_arch(char **cmdline_p)
{
    parse_early_param();

early param 이란 어떤것이고, 어떻게 사용하는지 알아보자.

early param

.init.setup 섹션에 미리 등록한 parameter 가 early param 으로 사용 가능합니다.

__setup_start 에 들어갈 수 있도록 매크로로 정의합니다.

extern const struct obs_kernel_param __setup_start[], __setup_end[];

/*
 * Only for really core code.  See moduleparam.h for the normal way.
 *
 * Force the alignment so the compiler doesn't space elements of the
 * obs_kernel_param "array" too far apart in .init.setup.
 */
#define __setup_param(str, unique_id, fn, early)            \
    static const char __setup_str_##unique_id[] __initconst        \
        __aligned(1) = str;                     \
    static struct obs_kernel_param __setup_##unique_id        \
        __used __section(".init.setup")                \
        __aligned(__alignof__(struct obs_kernel_param))        \
        = { __setup_str_##unique_id, fn, early }

/*
 * NOTE: __setup functions return values:
 * @fn returns 1 (or non-zero) if the option argument is "handled"
 * and returns 0 if the option argument is "not handled".
 */
#define __setup(str, fn)                        \
    __setup_param(str, fn, fn, 0)
// cmd line 을 복사후 파싱
void __init parse_early_param(void)
{
    strscpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
    parse_early_options(tmp_cmdline);
}

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

static int __init do_early_param(char *param, char *val,
                 const char *unused, void *arg)
{
    const struct obs_kernel_param *p;

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

커널의 parameter

커널파라미터를 내부적으로 관리하기 위한 구조체

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

parse_one 의 동작

for (i = 0; i < num_params; i++) {
    if (parameq(param, params[i].name)) {
        // 인자로 들어온 param 이 있다면 set 후 return

// 찾지 못한경우 handle_unknown 호출
if (handle_unknown) { handle_unknown(); }