blob: ea37384555d46e9f449679adb2481f0971f7f796 [file] [log] [blame]
Mahesh Rao01c564b2023-08-22 17:22:24 +08001/*
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
23static 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
41static 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
78static 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
115static 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
149uint32_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}