计算exFAT校验和

时间:2016-06-08 09:53:50

标签: c++ c++11 checksum fat

我目前正尝试使用微控制器将磁盘格式化为exFAT。我的问题是我需要计算校验和,该校验和使用VBR(卷引导区域)的扇区1到11中的字节将其存储到扇区12中,但我的结果不正确。当校验和不正确时,Windows或任何其他识别exFAT的操作系统都无法使用该磁盘,因为校验和已经过验证,如果不正确则会发生致命错误。

这是计算32位校验和的函数:

uint32_t BootChecksum(char * data, long bytes){
    uint32_t checksum = 0; 
    for (uint32_t i = 0 ; i < bytes ; i++){
        if (i == 106 || i == 107 || i == 112)
            continue;
        checksum = ((checksum << 31) | (checksum >> 1)) + (uint32_t) data[i];
        if(checksum == 0xF1924082){
            printf("%02X | i = %d", checksum, i);
        }
    }
    return checksum;
}

从我能够阅读的内容来看,该功能是正确的,所以我的猜测是我使用的数据不正确。我只需要占用所需的11个扇区,每个扇区512字节,就会产生5632字节的数组。

我使用类似的函数来计算入口集的校验和(16位校验和),结果是正确的,它实际上必须是数据,但我不明白我是什么&# 39;我在那里失踪了!

任何了解exFAT的人都可以帮助我吗?谢谢!

1 个答案:

答案 0 :(得分:1)

我怀疑这是运营商优先的问题。

this page中,我看到以这种方式修改checksum的crc定义

checksum = (checksum<<31) | (checksum>> 1) + data[i];

也就是说,如果我没错,相当于

checksum = (checksum<<31) | ((checksum>> 1) + data[i]);

因为(如果我记得很清楚),加号运算符(+)的优先级高于位或运算符(|)。

相反,您的代码是

checksum = ((checksum << 31) | (checksum >> 1)) + (uint32_t) data[i];

这是一个完全不同的代码,因为你首先应用按位或下一个加号。

我想可以使用

checksum = (checksum << 31) | ((checksum >> 1) + (uint32_t) data[i]);

p.s:抱歉我的英语不好

---编辑2016.06.09 ---

另一个问题应该是data的签名。

您将data定义为char的指针; ntfs.com将data定义为const unsigned char的数组。

指针/数组差异不是问题; const部分并不重要(但我建议您将data定义为const;问题(我想)是转换为uint32_t的{​​{1}},如果char使用负值而不是char进行签名。

示例:假设unsigned char的值为-1;使用data[i]时,如果我记得很清楚,首先(uint32_t) data[i]会转换为data[i],然后转换为int(-1)。所以你得到4294967295。

如果您的uint32_t(-1)data[i],则代替-1 unsigned char值为255;所以data[i]首先将255转换为(uint32_t) data[i],即int(255)旁边的255,仍为255。

简而言之,我的建议是:改变

uint32_t(255)

checksum = (checksum << 31) | ((checksum >> 1) + (uint32_t) data[i]);

或只是

checksum = (checksum << 31) | ((checksum >> 1) + (uint32_t) (unsigned char) data[i]);