3.5.1.196. of_compat_cmp

#define of_compat_cmp(s1, s2, l) strcasecmp((s1), (s2))

of_compat_cmp 用于对比device-node的compatible属性字符串是否相同

3.5.1.197. _OF_DECLARE

#if defined(CONFIG_OF) && !defined(MODULE)
    #define _OF_DECLARE(table, name, compat, fn, fn_type)   \
        static const struct of_device_id __of_table_##name  \
            __used__section(__##table##of_table)            \
            = {.compatible = compat,                        \
            .data = (fn == (fn_type)NULL) ? fn : fn}
#else
    #define _OF_DECLARE(table, name, compat, fn, fn_type)   \
        static const struct of_device_id __of_table_##name  \
            __attribute__((unused))                         \
            = {.compatible = compat,
               .data = (fn == (fn_type)NULL) ? fn : fn}
#endif

_OF_DECLARE 用于定义个DTS compatible表,宏定义了一个struct of_devie_id结构,并将该数据结构存储在私有section内, 宏为数据结构提供了compat和fn两个初始参数

3.5.1.198. of_fdt_device_is_available

static bool of_fdt_device_is_available(const void *blob, unsigned long node)
{
    const char *status = fdt_getprop(blob, node, "status", NULL);

    if(!status)
        return true;

    if(!strcmp(status, "ok") || !strcmp(status, "okay"))
        return true;

    return false;
}

of_fdt_device_is_available 检查节点的”status”属性值是否为”okay”或”ok”

3.5.1.199. of_fdt_is_compatible

//blob: 指向dtb
//node: device-node在dtb devicetree structure内的偏移
//compat: 需要查找节点的compatible
static int of_fdt_is_compatible(const void *blob, unsigned long node, const char *compat)
{
    const char *cp;
    int cplen;
    unsigned long l, score = 0;

    //获取节点的compatible值
    cp = fdt_getprop(blob, node, "compatible", &cplen);
    if(cp == NULL)
        return 0;

    //循环对比节点的compatible属性值是否包含参数compat
    while(cplen > 0) {
        score++;
        if(of_compat_cmp(cp, compat, strlen(compat)) == 0)
            return score;
        l = strlen(cp) + 1;
        cp += l;
        cplen -= l;
    }

    return 0;
}

of_fdt_is_compatible 用于检查节点的compatible属性值是否与参数compat相同

3.5.1.200. of_flat_dt_is_compatible

int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
{
    return of_fdt_is_compatible(initial_boot_params, node, compat);
}

of_flat_dt_is_compatible 用于判断节点的compatible属性是否包含compat参数

3.5.1.201. of_flat_dt_match_machine

const void * __init of_flat_dt_match_machine(const void *default_match,
            const void *(*get_next_compat)(const char * const**))
{
    const void *data = NULL;
    const void *best_data = default_match;
    const char *const *compat;
    unsigned long dt_root;
    unsigned int best_score = ~1, score = 0;

    //获取dts根节点在dtb devicetree structure区域内的偏移
    dt_root = of_get_flat_dt_root();
    //获取machine对应的compatible属性
    while((data = get_next_compat(&compat))) {
        //对比machine提供的compatible与dtb根节点的compatible是否相同
        score = of_flat_dt_match(dt_root, compat);
        if(score > 0 && score < best_score) {
            //如果相同则将best_data设置为data
            best_data = data;
            best_score = score;
        }
    }
    //如果best_data为0,那么dtb不是有效的dtb
    if(!best_data) {
        const char *prop;
        int size;
        pr_err("\n unrecognized device tree list:\n[");

        prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
        if(prop) {
            while(size > 0) {
                printk("'%s' ", prop);
                size -= strlen(prop) + 1;
                prop += strlen(prop) + 1;
            }
        }
        printk("]\n\n");
        return NULL;
    }

    return best_data;
}

of_flat_dt_match_machine 用于对比dtb根节点的compatible属性值与machine_desc数据结构中dt_compat成员是否相同

3.5.1.202. of_get_flat_dt_prop

const void * __init of_get_flat_dt_prop(unsigned long node, const char *name, int *size)
{
    return fdt_getprop(initial_boot_params, node, name, size);
}

of_get_flat_dt_prop 用于从dtb中获得device-node name参数对应的属性值

3.5.1.203. of_get_flat_dt_root

unsigned long __int of_get_flat_dt_root(void)
{
    return 0;
}

of_get_flat_dt_root 用于获得dts根节点在dtb devicetree structure中的偏移,root的偏移为0

3.5.1.204. of_scan_flat_dt

int __init of_scan_flat_dt(int (*it)(unsigned long node, const char *uname, int depth, void *data), void *data)
{
    const void *blob = initial_boot_params;
    const char *pathp;
    int offset, rc = 0, depth = -1;

    if(!blob)
        return 0;

    for(offset = fdt_next_node(blob, -1, &depth);
            offset >= 0 && depth >= 0 && !rc;
            offset = fdt_next_node(blob, offset, &depth)) {
        pathp = fdt_get_name(blob, offset, NULL);
        if(*pathp == '/')
            pathp = kbasenname(pathp);
        rc = it(offset, pathp, depth, data);
    }
    return rc;
}

fdt_scan_flat_dt 用于遍历dtb中所有节点