67 lines
2.0 KiB
C
67 lines
2.0 KiB
C
/*
|
|
* Copyright 2020 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/* See https://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks
|
|
* for info on the general algorithm. We use the following configuration:
|
|
* 32-bit CRC
|
|
* Polynomial = 0x04C11DB7
|
|
* MSB-first
|
|
* Input and output complement
|
|
* Input and output bit reversal
|
|
*
|
|
* This implementation optimizes for size and readability. We only need this for
|
|
* 28 bytes of A/B booting metadata, so efficiency is largely irrelevant whereas
|
|
* a 1KiB lookup table can be a significant cost for bootloaders.
|
|
*/
|
|
|
|
#include "avb_util.h"
|
|
|
|
/* Lookup table for reversing 4 bits. */
|
|
/* clang-format off */
|
|
static uint8_t reverse_4bit_table[] = {
|
|
0x0, 0x8, 0x4, 0xC,
|
|
0x2, 0xA, 0x6, 0xE,
|
|
0x1, 0x9, 0x5, 0xD,
|
|
0x3, 0xB, 0x7, 0xF
|
|
};
|
|
/* clang-format on */
|
|
|
|
static uint8_t reverse_byte(uint8_t val) {
|
|
return (reverse_4bit_table[val & 0xF] << 4) | reverse_4bit_table[val >> 4];
|
|
}
|
|
|
|
static uint32_t reverse_uint32(uint32_t val) {
|
|
return (reverse_byte(val) << 24) | (reverse_byte(val >> 8) << 16) |
|
|
(reverse_byte(val >> 16) << 8) | reverse_byte(val >> 24);
|
|
}
|
|
|
|
uint32_t avb_crc32(const uint8_t* buf, size_t size) {
|
|
uint32_t crc = 0xFFFFFFFF;
|
|
|
|
for (size_t i = 0; i < size; ++i) {
|
|
crc = crc ^ ((uint32_t)reverse_byte(buf[i]) << 24);
|
|
for (int j = 0; j < 8; ++j) {
|
|
if (crc & 0x80000000) {
|
|
crc = (crc << 1) ^ 0x04C11DB7;
|
|
} else {
|
|
crc <<= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return reverse_uint32(~crc);
|
|
}
|