2016-06-08 26 views
1

В настоящее время я пытаюсь отформатировать диск exFAT с помощью микроконтроллера. Моя проблема в том, что мне нужно вычислить контрольную сумму, которая использует байты из сектора 1-11 VBR (регион загрузки томов), чтобы сохранить его в секторе 12, но мой результат неверен. Когда контрольная сумма неверна, диск не может использоваться Windows или любой другой ОС, которая распознает exFAT, поскольку контрольная сумма проверена и возникает фатальная ошибка, если она неверна.Расчет контрольной суммы 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-разрядная контрольная сумма), и результат верен, это действительно должны быть данные, но я не понимаю, что мне там не хватает !

Любой, кто знает об exFAT, может мне помочь? Благодаря!

ответ

1

Я подозреваю, что это проблема приоритета оператора.

В this page я вижу Crc определение где checksum модифицирован таким образом

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]); 

пс: простите за мой плохой английский

--- EDIT 2016.06.09 ---

Другая проблема должна быть подпись data.

В качестве указателя char вы определяете data; ntfs.com определяет data как массив const unsigned char.

Разница указателей/массивов не является проблемой; const часть не важна (но я предлагаю вам определить свой data как const); проблема (я полагаю) является преобразованием в uint32_t из char, если char подписан с отрицательными значениями, а не unsigned char.

Пример: предположим, что значение вашего data[i] равно -1; с (uint32_t) data[i], если я хорошо помню, первый data[i] преобразован в int(-1) и следующий в uint32_t(-1). Таким образом, вы получаете 4294967295.

Если ваш data[i] является unsigned char, вместо -1 data[i] значение 255; так (uint32_t) data[i] сначала преобразовать 255 в int(255), то есть 255, рядом с uint32_t(255), которые остаются 255.

Короче говоря, мое предложение: изменить

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

в

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

или просто

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

Вы действительно правы, я попытался с вашей скобкой nd без круглых скобок, и я получаю одинаковый результат для обоих, поэтому кажется, что я неверно истолковал приоритет оператора! Но все же результат неверен. Я получаю 0x95672D57, тогда как у меня должно быть 0xF1924082. Спасибо за вашу помощь! –

+1

@ArthurPenguin - решена проблема, посмотрим, сможем ли мы решить другую; Я редактировал мой anser, предлагая другое изменение в вашем коде для решения проблемы с подписью – max66

+0

Спасибо, что определенно решил! –

 Смежные вопросы

  • Нет связанных вопросов^_^