// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Copyright (c) 2019 Amlogic, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_CMD_CAR_PARAMS // calibrator_message used 1024K-1026K by misc partition typedef struct calibrator_message { uint32_t magic; //magic number uint8_t rsv[4]; int64_t camera[9]; //camera Internal parameter matrix int64_t distortion[5]; //Distortion matrix int64_t matrix_rtos[9]; //projection matrix for rtos int64_t matrix_gles[9];//projection matrix for gles int64_t car[5]; //car parameters // rounds up to 2048-byte. uint8_t reserve[1740]; // CRC32 of all 28 bytes preceding this field (little endian // format). uint32_t crc32_le; } calibrator_message; #define CALIBRATOR_OFFSET (1024 * 1024) #define CALIBRATOR_SIZE 2048 #define CALIBRATOR_MAGIC 0x51504948 /* magic number */ static uint32_t car_crc32(const uint8_t *buf, size_t size) { static uint32_t crc_table[256]; uint32_t ret = -1; // Compute the CRC-32 table only once. if (!crc_table[1]) { for (uint32_t i = 0; i < 256; ++i) { uint32_t crc = i; for (uint32_t j = 0; j < 8; ++j) { uint32_t mask = -(crc & 1); crc = (crc >> 1) ^ (0xEDB88320 & mask); } crc_table[i] = crc; } } for (size_t i = 0; i < size; ++i) ret = (ret >> 8) ^ crc_table[(ret ^ buf[i]) & 0xFF]; return ~ret; } bool calibrator_info_validate(calibrator_message *info) { uint32_t crc; if (info->magic != CALIBRATOR_MAGIC) { printf("Magic 0x%x is incorrect.\n", info->magic); return false; } crc = car_crc32((const uint8_t *)info, sizeof(calibrator_message) - sizeof(uint32_t)); if (info->crc32_le != crc) { printf("crc 0x%x != 0x%x\n", info->crc32_le, crc); return false; } return true; } void calibrator_info_reset(calibrator_message *info) { memset(info, '\0', sizeof(calibrator_message)); info->magic = CALIBRATOR_MAGIC; } void dump_info(calibrator_message *info) { int i; printf("info->magic = 0x%x\n", info->magic); for (i = 0; i < 9; ++i) { printf("info->camera[%d] = %lld\n", i, info->camera[i]); } for (i = 0; i < 5; ++i) { printf("info->distortion[%d] = %lld\n", i, info->distortion[i]); } for (i = 0; i < 9; ++i) { printf("info->matrix_rtos[%d] = %lld\n", i, info->matrix_rtos[i]); } for (i = 0; i < 9; ++i) { printf("info->matrix_gles[%d] = %lld\n", i, info->matrix_gles[i]); } for (i = 0; i < 5; ++i) { printf("info->car[%d] = %lld\n", i, info->car[i]); } } int calibrator_info_open_partition(unsigned char *miscbuf) { char *partition = "misc"; printf("Start read %s partition datas!\n", partition); if (store_read((const char *)partition, CALIBRATOR_OFFSET, CALIBRATOR_SIZE, miscbuf) < 0) { printf("failed to store read %s.\n", partition); return -1; } return 0; } bool calibrator_info_save(calibrator_message *info) { char *partition = "misc"; printf("save calibrator-info\n"); info->crc32_le = car_crc32((const uint8_t *)info, sizeof(calibrator_message) - sizeof(uint32_t)); dump_info(info); store_write((const char *)partition, CALIBRATOR_OFFSET, CALIBRATOR_SIZE, (unsigned char *)info); return true; } static int do_ReadCarParams(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { calibrator_message *info = NULL; unsigned char *loadaddr = 0; if (argc > 2) loadaddr = (unsigned char *)simple_strtoul(argv[2], NULL, 16); else loadaddr = (unsigned char *)simple_strtoul(env_get("car_mem_addr"), NULL, 16); info = (calibrator_message *)loadaddr; calibrator_info_open_partition(loadaddr); if (!calibrator_info_validate(info)) { printf("calibrator-info is invalid. resetting\n"); calibrator_info_reset(info); calibrator_info_save(info); } else { dump_info(info); } return 0; } #endif U_BOOT_CMD(read_car_params, 3, 0, do_ReadCarParams, "read_car_params", "\nThis command will read car params to mem\n" "partition by mark to decide whether execute command!\n" "So you can execute command: read_car_params" );