From 872c87c6805bea08677de71b744cce7deb24903e Mon Sep 17 00:00:00 2001 From: Sungbo Eo Date: Tue, 4 Jan 2022 23:47:27 +0900 Subject: [PATCH] iptime-crc32: add image header tool for new ipTIME models Some ipTIME models (e.g. A8004T-XR) started to use a new 56-byte header format which uses accumulated CRC-32 for its checksum algorithm. This tool helps to pass through the factory image verification process on the applicable models. Signed-off-by: Sungbo Eo --- CMakeLists.txt | 1 + src/iptime-crc32.c | 147 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 src/iptime-crc32.c diff --git a/CMakeLists.txt b/CMakeLists.txt index bb4593f..4de70d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ FW_UTIL(encode_crc "" "" "") FW_UTIL(fix-u-media-header src/cyg_crc32.c "" "") FW_UTIL(hcsmakeimage src/bcmalgo.c "" "") FW_UTIL(imagetag "src/imagetag_cmdline.c;src/cyg_crc32.c" "" "") +FW_UTIL(iptime-crc32 src/cyg_crc32.c "" "") FW_UTIL(iptime-naspkg "" "" "") FW_UTIL(jcgimage "" "" "${ZLIB_LIBRARIES}") FW_UTIL(lxlfw "" "" "") diff --git a/src/iptime-crc32.c b/src/iptime-crc32.c new file mode 100644 index 0000000..51b0519 --- /dev/null +++ b/src/iptime-crc32.c @@ -0,0 +1,147 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021 Sungbo Eo + * + * This code is based on mkdhpimg.c and mkzcfw.c + * Copyright (C) 2010 Gabor Juhos + * Copyright (c) 2016 FUKAUMI Naoki + * + * Checksum algorithm is derived from add_iptime_fw_header.c + * Copyright (C) 2020 Jaehoon You + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cyg_crc.h" + +#if !defined(__BYTE_ORDER) +#error "Unknown byte order" +#endif + +#if (__BYTE_ORDER == __BIG_ENDIAN) +#define HOST_TO_LE32(x) bswap_32(x) +#elif (__BYTE_ORDER == __LITTLE_ENDIAN) +#define HOST_TO_LE32(x) (x) +#else +#error "Unsupported endianness" +#endif + +#define FW_VERSION "00_000" + +struct fw_header { + uint8_t model[8]; + uint8_t version[8]; + uint8_t reserved[32]; + uint32_t size; + uint32_t checksum; +} __attribute__ ((packed)); + +struct board_info { + const char *model; + size_t payload_offset; +}; + +struct board_info boards[] = { + { .model = "ax2004m", .payload_offset = 0x38 }, + { /* sentinel */ } +}; + +struct board_info *find_board(const char *model) +{ + struct board_info *ret = NULL; + struct board_info *board; + + for (board = boards; board->model != NULL; board++) { + if (strcmp(model, board->model) == 0) { + ret = board; + break; + } + } + + return ret; +} + +uint32_t make_checksum(struct fw_header *header, uint8_t *payload, int size) +{ + cyg_uint32 checksum; + + /* get CRC of header */ + checksum = cyg_crc32_accumulate(~0L, header, sizeof(*header)); + + /* get CRC of payload buffer with header CRC as initial value */ + return (uint32_t)cyg_crc32_accumulate(checksum, payload, size); +} + +void make_header(struct board_info *board, uint8_t *buffer, size_t img_size) +{ + struct fw_header *header = (struct fw_header *)buffer; + uint32_t checksum; + + strncpy((char *)header->model, board->model, sizeof(header->model)-1); + strncpy((char *)header->version, FW_VERSION, sizeof(header->version)-1); + header->size = HOST_TO_LE32(img_size); + checksum = make_checksum(header, buffer + board->payload_offset, img_size); + header->checksum = HOST_TO_LE32(checksum); +} + +int main(int argc, const char *argv[]) +{ + const char *model_name, *img_in, *img_out; + struct board_info *board; + int file_in, file_out; + struct stat stat_in; + size_t size_in, size_out; + uint8_t *buffer; + + if (argc != 4) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return EXIT_FAILURE; + } + model_name = argv[1]; + img_in = argv[2]; + img_out = argv[3]; + + board = find_board(model_name); + if (board == NULL) { + fprintf(stderr, "%s: Not supported model\n", model_name); + return EXIT_FAILURE; + } + + if ((file_in = open(img_in, O_RDONLY)) == -1) + err(EXIT_FAILURE, "%s", img_in); + + if (fstat(file_in, &stat_in) == -1) + err(EXIT_FAILURE, "%s", img_in); + + size_in = stat_in.st_size; + size_out = board->payload_offset + size_in; + + if ((buffer = malloc(size_out)) == NULL) + err(EXIT_FAILURE, "malloc"); + + read(file_in, buffer + board->payload_offset, size_in); + close(file_in); + + memset(buffer, 0, board->payload_offset); + + make_header(board, buffer, size_in); + + if ((file_out = creat(img_out, 0644)) == -1) + err(EXIT_FAILURE, "%s", img_out); + write(file_out, buffer, size_out); + close(file_out); + + free(buffer); + + return EXIT_SUCCESS; +} -- 2.30.2