Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15497044
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类:

2009-07-05 12:01:25

浅析redboot类似字典查询函数flash_get_config具体实现

    比如我们获取key键值为"boot_script"对应的value,结果存入use_boot_script中,该
value对应的type为CONFIG_BOOL[这种实现形式又有些类似dbus总线上wire数据压缩格式][luther.gliethttp]

执行语句为:flash_get_config("boot_script", &use_boot_script, CONFIG_BOOL);
来看看源码实现[luther.gliethttp]
bool
flash_get_config(char *key, void *val, int type)
{
    unsigned char *dp;
    void *val_ptr;
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
    struct _config *save_config = 0;
#endif

    if (!config_ok) return false; // config内容已经从flash安全加载到了指定heap堆空间[luther.gliethtp]

    // 下面查询键值"boot_script"对应的存储地址
    if ((dp = flash_lookup_config(key)) != (unsigned char *)NULL) {
        // 查看类型是否一致,
        // 理论上说,如果不一致应该出现了key值相同的类一个类型的dp空间,
        // 并不能说明我们不存在类型一致的key,所以应该continue继续下一个查找,
        // 但是可能redboot本身不需要这种需求,另外没人拿redboot只是玩,大家都是很严肃的
        // 来使用redboot,所以redboot这些必须的规则,大家都会严格来遵守,所以
        // 实现到这种程度的key字典查询也已经足够了[luther.gliethttp]
        if (CONFIG_OBJECT_TYPE(dp) == type) {
            val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);
            switch (type) {
                // Note: the data may be unaligned in the configuration data
            case CONFIG_BOOL:
                memcpy(val, val_ptr, sizeof(bool)); // 拷贝数据
                break;
            case CONFIG_INT:
                memcpy(val, val_ptr, sizeof(unsigned long)); // 拷贝数据
                break;
#ifdef CYGPKG_REDBOOT_NETWORKING
            case CONFIG_IP:
                memcpy(val, val_ptr, sizeof(in_addr_t));
                break;
            case CONFIG_ESA:
                memcpy(val, val_ptr, sizeof(enet_addr_t));
                break;
#endif
            case CONFIG_STRING:
            case CONFIG_SCRIPT:
                // Just return a pointer to the script/line
                *(unsigned char **)val = (unsigned char *)val_ptr; // 直接将字符串地址返回,不需要执行拷贝操作,因为config区
                // 是一个readonly区,没人去改动[luther.gliethttp].
                break;
            }
        } else {
            diag_printf("Request for config value '%s' - wrong type\n", key);
        }
        return true; // ok, 正常找到,直接return 返回
    }
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK
    // 我们定义了该宏,如果没有找到,那么
    // 怀疑是否config区域遭到灾难性破坏,于是尝试进行数据恢复[luther.gliethttp]
    // Did not find key. Is configuration data valid?
    // Check to see if the config data is valid, if not, revert to
    // readonly mode, by setting config to readonly_config.  We
    // will set it back before we leave this function.
    if ( (config != readonly_config) && ((cyg_crc32((unsigned char *)config,
               sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) ||
        (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2))) {
        save_config = config;
        config = readonly_config; // 那么使用readonly_config
        if ((cyg_crc32((unsigned char *)config,
                       sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) ||
            (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2)) {
            diag_printf("FLASH configuration checksum error or invalid key\n");
            config = save_config;
            return false;
        }
        else{
            diag_printf("Getting config information in READONLY mode\n");
            // 作最后查询,有就有,没有就没有了[luther.gliethttp]
            return flash_get_config(key, val, type);
        }
    }
#endif
    return false;
}

// 如下为plain数据区数据压缩存储格式
// Layout of config data
// Each data item is variable length, with the name, type and dependencies
// encoded into the object.
//  offset   contents
//       0   data type
//       1   length of name (N)
//       2   enable sense
//       3   length of enable key (M)
//       4   key name
//     N+4   enable key
//   M+N+4   data value

#define CONFIG_OBJECT_TYPE(dp)          (dp)[0]
#define CONFIG_OBJECT_KEYLEN(dp)        (dp)[1]
#define CONFIG_OBJECT_ENABLE_SENSE(dp)  (dp)[2]
#define CONFIG_OBJECT_ENABLE_KEYLEN(dp) (dp)[3]
#define CONFIG_OBJECT_KEY(dp)           ((dp)+4)
#define CONFIG_OBJECT_ENABLE_KEY(dp)    ((dp)+4+CONFIG_OBJECT_KEYLEN(dp))
#define CONFIG_OBJECT_VALUE(dp)         ((dp)+4+CONFIG_OBJECT_KEYLEN(dp)+CONFIG_OBJECT_ENABLE_KEYLEN(dp))

static int
config_length(int type)
{
    switch (type) {
    case CONFIG_BOOL:
        return sizeof(bool);
    case CONFIG_INT:
        return sizeof(unsigned long);
#ifdef CYGPKG_REDBOOT_NETWORKING
    case CONFIG_IP:
        return sizeof(in_addr_t);
    case CONFIG_ESA:
        // Would like this to be sizeof(enet_addr_t), but that causes much
        // pain since it fouls the alignment of data which follows.
        return 8;
#endif
    case CONFIG_STRING:
        return MAX_STRING_LENGTH;
    case CONFIG_SCRIPT:
        return MAX_SCRIPT_LENGTH;
    default:
        return 0;
    }
}
// 执行具体查询操作
static unsigned char *
flash_lookup_config(char *key)
{
    unsigned char *dp;
    int len;

    if (!config_ok) return (unsigned char *)NULL;

    dp = &config->config_data[0]; // plain数据区
    while (dp < &config->config_data[sizeof(config->config_data)]) {
    // 压缩存储格式见上面
    // 0,1,2,3,4前4个字节为控制信息,比如
    //    0字节对应数据类型
    //    1字节对应key键值字符串长度(包含字符串结尾0)
    //    2字节对应是否大小写敏感
    //    3字节对应enable key字符串长度(包含字符串结尾0)
    //    4字节开始存储key字符串数据N个字节,
    //  N+4紧随key字符串存储之后就是enable key字符串M个字节
    //M+N+4之后就是data数据值了[luther.gliethttp]
        len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +
            config_length(CONFIG_OBJECT_TYPE(dp)); // config_length返回该类型需要占用的存储空间.
    // 首先比较键值key是否相同
    // 为了加速比较,其实可以借鉴linux中的方法
    // 首先比较字符传长度是否相等,如果相等
    // 那么才继续进行如下耗cpu的字符串比较工作[luther.gliethttp]
        if (strcmp(key, CONFIG_OBJECT_KEY(dp)) == 0) {
            return dp; // ok, 该dp压缩结构体就是要找的key键值存储空间区[luther.gliethttp]
        }
        dp += len; // dp指向下一个压缩结构体开始处[luther.gliethttp]
    }
//    diag_printf("Can't find config data for '%s'\n", key);
    return false;
}
阅读(1783) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~