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