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