1*62be2a1aSMahesh Rao /* 2*62be2a1aSMahesh Rao * Copyright (c) 2024, Intel Corporation. All rights reserved. 3*62be2a1aSMahesh Rao * 4*62be2a1aSMahesh Rao * SPDX-License-Identifier: BSD-3-Clause 5*62be2a1aSMahesh Rao */ 6*62be2a1aSMahesh Rao 7*62be2a1aSMahesh Rao /* system header files*/ 8*62be2a1aSMahesh Rao #include <assert.h> 9*62be2a1aSMahesh Rao #include <endian.h> 10*62be2a1aSMahesh Rao #include <string.h> 11*62be2a1aSMahesh Rao 12*62be2a1aSMahesh Rao /* CRC function header */ 13*62be2a1aSMahesh Rao #include <common/tf_crc32.h> 14*62be2a1aSMahesh Rao 15*62be2a1aSMahesh Rao /* Cadense qspi driver*/ 16*62be2a1aSMahesh Rao #include <qspi/cadence_qspi.h> 17*62be2a1aSMahesh Rao 18*62be2a1aSMahesh Rao /* Mailbox driver*/ 19*62be2a1aSMahesh Rao #include <socfpga_mailbox.h> 20*62be2a1aSMahesh Rao 21*62be2a1aSMahesh Rao #include <socfpga_ros.h> 22*62be2a1aSMahesh Rao 23*62be2a1aSMahesh Rao static void swap_bits(char *const data, uint32_t len) 24*62be2a1aSMahesh Rao { 25*62be2a1aSMahesh Rao uint32_t x, y; 26*62be2a1aSMahesh Rao char tmp; 27*62be2a1aSMahesh Rao 28*62be2a1aSMahesh Rao for (x = 0U; x < len; x++) { 29*62be2a1aSMahesh Rao tmp = 0U; 30*62be2a1aSMahesh Rao for (y = 0U; y < 8; y++) { 31*62be2a1aSMahesh Rao tmp <<= 1; 32*62be2a1aSMahesh Rao if (data[x] & 1) { 33*62be2a1aSMahesh Rao tmp |= 1; 34*62be2a1aSMahesh Rao } 35*62be2a1aSMahesh Rao data[x] >>= 1; 36*62be2a1aSMahesh Rao } 37*62be2a1aSMahesh Rao data[x] = tmp; 38*62be2a1aSMahesh Rao } 39*62be2a1aSMahesh Rao } 40*62be2a1aSMahesh Rao 41*62be2a1aSMahesh Rao static uint32_t get_current_image_index(spt_table_t *spt_buf, uint32_t *const img_index) 42*62be2a1aSMahesh Rao { 43*62be2a1aSMahesh Rao if (spt_buf == NULL || img_index == NULL) { 44*62be2a1aSMahesh Rao return ROS_RET_INVALID; 45*62be2a1aSMahesh Rao } 46*62be2a1aSMahesh Rao 47*62be2a1aSMahesh Rao uint32_t ret; 48*62be2a1aSMahesh Rao unsigned long current_image; 49*62be2a1aSMahesh Rao uint32_t rsu_status[RSU_STATUS_RES_SIZE]; 50*62be2a1aSMahesh Rao 51*62be2a1aSMahesh Rao if (spt_buf->partitions < SPT_MIN_PARTITIONS || spt_buf->partitions > SPT_MAX_PARTITIONS) { 52*62be2a1aSMahesh Rao return ROS_IMAGE_PARTNUM_OVFL; 53*62be2a1aSMahesh Rao } 54*62be2a1aSMahesh Rao 55*62be2a1aSMahesh Rao ret = mailbox_rsu_status(rsu_status, RSU_STATUS_RES_SIZE); 56*62be2a1aSMahesh Rao if (ret != MBOX_RET_OK) { 57*62be2a1aSMahesh Rao return ROS_RET_NOT_RSU_MODE; 58*62be2a1aSMahesh Rao } 59*62be2a1aSMahesh Rao 60*62be2a1aSMahesh Rao current_image = ADDR_64(rsu_status[1], rsu_status[0]); 61*62be2a1aSMahesh Rao NOTICE("ROS: Current image is at 0x%08lx\n", current_image); 62*62be2a1aSMahesh Rao 63*62be2a1aSMahesh Rao *img_index = 0U; 64*62be2a1aSMahesh Rao for (uint32_t index = 0U ; index < spt_buf->partitions; index++) { 65*62be2a1aSMahesh Rao if (spt_buf->partition[index].offset == current_image) { 66*62be2a1aSMahesh Rao *img_index = index; 67*62be2a1aSMahesh Rao break; 68*62be2a1aSMahesh Rao } 69*62be2a1aSMahesh Rao } 70*62be2a1aSMahesh Rao 71*62be2a1aSMahesh Rao if (*img_index == 0U) { 72*62be2a1aSMahesh Rao return ROS_IMAGE_INDEX_ERR; 73*62be2a1aSMahesh Rao } 74*62be2a1aSMahesh Rao 75*62be2a1aSMahesh Rao return ROS_RET_OK; 76*62be2a1aSMahesh Rao } 77*62be2a1aSMahesh Rao 78*62be2a1aSMahesh Rao static uint32_t load_and_check_spt(spt_table_t *spt_ptr, size_t offset) 79*62be2a1aSMahesh Rao { 80*62be2a1aSMahesh Rao 81*62be2a1aSMahesh Rao if (spt_ptr == NULL || offset == 0U) { 82*62be2a1aSMahesh Rao return ROS_RET_INVALID; 83*62be2a1aSMahesh Rao } 84*62be2a1aSMahesh Rao 85*62be2a1aSMahesh Rao int ret; 86*62be2a1aSMahesh Rao uint32_t calc_crc; 87*62be2a1aSMahesh Rao static spt_table_t spt_data; 88*62be2a1aSMahesh Rao 89*62be2a1aSMahesh Rao ret = cad_qspi_read(spt_ptr, offset, SPT_SIZE); 90*62be2a1aSMahesh Rao if (ret != 0U) { 91*62be2a1aSMahesh Rao return ROS_QSPI_READ_ERROR; 92*62be2a1aSMahesh Rao } 93*62be2a1aSMahesh Rao 94*62be2a1aSMahesh Rao if (spt_ptr->magic_number != SPT_MAGIC_NUMBER) { 95*62be2a1aSMahesh Rao return ROS_SPT_BAD_MAGIC_NUM; 96*62be2a1aSMahesh Rao } 97*62be2a1aSMahesh Rao 98*62be2a1aSMahesh Rao if (spt_ptr->partitions < SPT_MIN_PARTITIONS || spt_ptr->partitions > SPT_MAX_PARTITIONS) { 99*62be2a1aSMahesh Rao return ROS_IMAGE_PARTNUM_OVFL; 100*62be2a1aSMahesh Rao } 101*62be2a1aSMahesh Rao 102*62be2a1aSMahesh Rao memcpy_s(&spt_data, SPT_SIZE, spt_ptr, SPT_SIZE); 103*62be2a1aSMahesh Rao spt_data.checksum = 0U; 104*62be2a1aSMahesh Rao swap_bits((char *)&spt_data, SPT_SIZE); 105*62be2a1aSMahesh Rao 106*62be2a1aSMahesh Rao calc_crc = tf_crc32(0, (uint8_t *)&spt_data, SPT_SIZE); 107*62be2a1aSMahesh Rao if (bswap32(spt_ptr->checksum) != calc_crc) { 108*62be2a1aSMahesh Rao return ROS_SPT_CRC_ERROR; 109*62be2a1aSMahesh Rao } 110*62be2a1aSMahesh Rao 111*62be2a1aSMahesh Rao NOTICE("ROS: SPT table at 0x%08lx is verified\n", offset); 112*62be2a1aSMahesh Rao return ROS_RET_OK; 113*62be2a1aSMahesh Rao } 114*62be2a1aSMahesh Rao 115*62be2a1aSMahesh Rao static uint32_t get_spt(spt_table_t *spt_buf) 116*62be2a1aSMahesh Rao { 117*62be2a1aSMahesh Rao if (spt_buf == NULL) { 118*62be2a1aSMahesh Rao return ROS_RET_INVALID; 119*62be2a1aSMahesh Rao } 120*62be2a1aSMahesh Rao 121*62be2a1aSMahesh Rao uint32_t ret; 122*62be2a1aSMahesh Rao uint32_t spt_offset[RSU_GET_SPT_RESP_SIZE]; 123*62be2a1aSMahesh Rao 124*62be2a1aSMahesh Rao /* Get SPT offset from SDM via mailbox commands */ 125*62be2a1aSMahesh Rao ret = mailbox_rsu_get_spt_offset(spt_offset, RSU_GET_SPT_RESP_SIZE); 126*62be2a1aSMahesh Rao if (ret != MBOX_RET_OK) { 127*62be2a1aSMahesh Rao WARN("ROS: Not booted in RSU mode\n"); 128*62be2a1aSMahesh Rao return ROS_RET_NOT_RSU_MODE; 129*62be2a1aSMahesh Rao } 130*62be2a1aSMahesh Rao 131*62be2a1aSMahesh Rao /* Print the SPT table addresses */ 132*62be2a1aSMahesh Rao VERBOSE("ROS: SPT0 0x%08lx\n", ADDR_64(spt_offset[0], spt_offset[1])); 133*62be2a1aSMahesh Rao VERBOSE("ROS: SPT1 0x%08lx\n", ADDR_64(spt_offset[2], spt_offset[3])); 134*62be2a1aSMahesh Rao 135*62be2a1aSMahesh Rao /* Load and validate SPT1*/ 136*62be2a1aSMahesh Rao ret = load_and_check_spt(spt_buf, ADDR_64(spt_offset[2], spt_offset[3])); 137*62be2a1aSMahesh Rao if (ret != ROS_RET_OK) { 138*62be2a1aSMahesh Rao /* Load and validate SPT0*/ 139*62be2a1aSMahesh Rao ret = load_and_check_spt(spt_buf, ADDR_64(spt_offset[0], spt_offset[1])); 140*62be2a1aSMahesh Rao if (ret != ROS_RET_OK) { 141*62be2a1aSMahesh Rao WARN("Both SPT tables are unusable\n"); 142*62be2a1aSMahesh Rao return ret; 143*62be2a1aSMahesh Rao } 144*62be2a1aSMahesh Rao } 145*62be2a1aSMahesh Rao 146*62be2a1aSMahesh Rao return ROS_RET_OK; 147*62be2a1aSMahesh Rao } 148*62be2a1aSMahesh Rao 149*62be2a1aSMahesh Rao uint32_t ros_qspi_get_ssbl_offset(unsigned long *offset) 150*62be2a1aSMahesh Rao { 151*62be2a1aSMahesh Rao if (offset == NULL) { 152*62be2a1aSMahesh Rao return ROS_RET_INVALID; 153*62be2a1aSMahesh Rao } 154*62be2a1aSMahesh Rao 155*62be2a1aSMahesh Rao uint32_t ret, img_index; 156*62be2a1aSMahesh Rao char ssbl_name[SPT_PARTITION_NAME_LENGTH]; 157*62be2a1aSMahesh Rao static spt_table_t spt; 158*62be2a1aSMahesh Rao 159*62be2a1aSMahesh Rao ret = get_spt(&spt); 160*62be2a1aSMahesh Rao if (ret != ROS_RET_OK) { 161*62be2a1aSMahesh Rao return ret; 162*62be2a1aSMahesh Rao } 163*62be2a1aSMahesh Rao 164*62be2a1aSMahesh Rao ret = get_current_image_index(&spt, &img_index); 165*62be2a1aSMahesh Rao if (ret != ROS_RET_OK) { 166*62be2a1aSMahesh Rao return ret; 167*62be2a1aSMahesh Rao } 168*62be2a1aSMahesh Rao 169*62be2a1aSMahesh Rao if (strncmp(spt.partition[img_index].name, FACTORY_IMAGE, 170*62be2a1aSMahesh Rao SPT_PARTITION_NAME_LENGTH) == 0U) { 171*62be2a1aSMahesh Rao strlcpy(ssbl_name, FACTORY_SSBL, SPT_PARTITION_NAME_LENGTH); 172*62be2a1aSMahesh Rao } else { 173*62be2a1aSMahesh Rao strlcpy(ssbl_name, spt.partition[img_index].name, 174*62be2a1aSMahesh Rao SPT_PARTITION_NAME_LENGTH); 175*62be2a1aSMahesh Rao strlcat(ssbl_name, SSBL_SUFFIX, SPT_PARTITION_NAME_LENGTH); 176*62be2a1aSMahesh Rao } 177*62be2a1aSMahesh Rao 178*62be2a1aSMahesh Rao for (uint32_t index = 0U; index < spt.partitions; index++) { 179*62be2a1aSMahesh Rao if (strncmp(spt.partition[index].name, ssbl_name, 180*62be2a1aSMahesh Rao SPT_PARTITION_NAME_LENGTH) == 0U) { 181*62be2a1aSMahesh Rao *offset = spt.partition[index].offset; 182*62be2a1aSMahesh Rao NOTICE("ROS: Corresponding SSBL is at 0x%08lx\n", *offset); 183*62be2a1aSMahesh Rao return ROS_RET_OK; 184*62be2a1aSMahesh Rao } 185*62be2a1aSMahesh Rao } 186*62be2a1aSMahesh Rao 187*62be2a1aSMahesh Rao return ROS_IMAGE_INDEX_ERR; 188*62be2a1aSMahesh Rao } 189