1 /*
2 * Copyright (C) 2018-2020 Texas Instruments Incorporated - http://www.ti.com/
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the
14 * distribution.
15 *
16 * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33 #include <ti/csl/tistdtypes.h>
34 #include <ti/csl/soc.h>
35 #include <ti/csl/arch/csl_arch.h>
36 #include <ti/csl/hw_types.h>
37 #include <ti/drv/uart/UART_stdio.h>
38 #include <ti/drv/uart/soc/UART_soc.h>
39 #include <ti/board/board.h>
40 #include <sbl_soc.h>
41 #include <sbl_soc_cfg.h>
42 #include <sbl_err_trap.h>
43 #include <sbl_sci_client.h>
45 #if defined(SBL_ENABLE_HLOS_BOOT) && defined(SOC_AM65XX)
46 const uint32_t gSciclient_boardCfgLow_hlos_rm[(SCICLIENT_BOARDCFG_RM_LINUX_SIZE_IN_BYTES+3U)/4U]
47 __attribute__(( aligned(128), section(".boardcfg_data") ))
48 = SCICLIENT_BOARDCFG_RM_LINUX;
49 #endif
51 #ifdef __cplusplus
52 #pragma DATA_SECTION(".firmware")
53 #else
54 #pragma WEAK (SBL_ReadSysfwImage)
55 #pragma DATA_SECTION(gSciclient_firmware, ".firmware")
56 #endif
57 uint32_t gSciclient_firmware[1];
59 #if SCICLIENT_FIRMWARE_SIZE_IN_BYTES > SBL_SYSFW_MAX_SIZE
60 #error "SYSFW too large...update SBL_SYSFW_MAX_SIZE"
61 #endif
63 #if (!defined(SBL_SKIP_BRD_CFG_PM)) || (!defined(SBL_SKIP_BRD_CFG_RM))
64 static int32_t Sciclient_setBoardConfigHeader ();
65 #endif
66 #if defined(SOC_AM65XX) || defined(SOC_J721E) || defined(SOC_J7200)
67 /* Firewall ID for MCU_FSS0_S0 */
68 #define MCU_FSS0_S0_FWID (1036)
69 #define MCU_FSS0_S0_FW_REGIONS (8)
71 #if defined (SOC_J721E) || defined (SOC_J7200)
72 /** \brief Aligned address at which the X509 header is placed. */
73 #define SCISERVER_COMMON_X509_HEADER_ADDR (0x41cffb00U)
75 /** \brief Aligned address at which the Board Config header is placed. */
76 #define SCISERVER_BOARDCONFIG_HEADER_ADDR (0x41c80000U)
78 /** \brief Aligned address at which the Board Config is placed. */
79 #define SCISERVER_BOARDCONFIG_DATA_ADDR (0x41c80040U)
81 #endif
82 #endif
84 uint32_t SBL_IsAuthReq(void)
85 {
86 uint32_t retVal = SBL_ALWAYS_AUTH_APP;
87 uint32_t dev_type;
88 uint32_t dev_subtype;
90 SBL_ADD_PROFILE_POINT;
92 dev_type = CSL_REG32_RD(SBL_SYS_STATUS_REG) & SBL_SYS_STATUS_DEV_TYPE_MASK;
93 dev_subtype = CSL_REG32_RD(SBL_SYS_STATUS_REG) & SBL_SYS_STATUS_DEV_SUBTYPE_MASK;
95 /* No auth possible, if valid SMPK/BMPK is not present */
96 if ((dev_subtype == SBL_SYS_STATUS_DEV_SUBTYPE_FS) ||
97 (dev_type == SBL_SYS_STATUS_DEV_TYPE_GP) ||
98 (dev_type == SBL_SYS_STATUS_DEV_TYPE_TEST))
99 {
100 retVal = SBL_NEVER_AUTH_APP;
101 }
103 SBL_ADD_PROFILE_POINT;
105 return retVal;
106 }
108 #ifndef SBL_SKIP_SYSFW_INIT
109 Sciclient_BoardCfgPrms_t sblBoardCfgPrms = {0};
110 Sciclient_BoardCfgPrms_t sblBoardCfgPmPrms = {0};
111 Sciclient_BoardCfgPrms_t sblBoardCfgRmPrms = {0};
112 #ifndef SBL_SKIP_BRD_CFG_SEC
113 Sciclient_BoardCfgPrms_t sblBoardCfgSecPrms = {0};
114 #endif
115 #endif
117 #ifndef SBL_SKIP_BRD_CFG_RM
118 uint16_t gCertLength = 0;
119 #endif
120 static uint16_t boardcfgRmFindCertSize(uint32_t *msg_recv)
121 {
122 uint16_t cert_len = 0;
123 uint8_t *cert_len_ptr = (uint8_t *)&cert_len;
124 uint8_t *x509_cert_ptr;
126 x509_cert_ptr = (uint8_t *)msg_recv;
129 if (*x509_cert_ptr != 0x30)
130 {
131 /* The data does not contain a certificate - return */
132 return 0;
133 }
135 cert_len = *(x509_cert_ptr + 1);
137 /* If you need more than 2 bytes to store the cert length */
138 /* it means that the cert length is greater than 64 Kbytes */
139 /* and we do not support it */
140 if ((cert_len > 0x80) &&
141 (cert_len != 0x82))
142 {
143 return 0;
144 }
146 if (cert_len == 0x82)
147 {
148 *cert_len_ptr = *(x509_cert_ptr + 3);
149 *(cert_len_ptr + 1) = *(x509_cert_ptr + 2);
151 /* add current offset from start of x509 cert */
152 cert_len += 3;
153 }
154 else
155 {
156 /* add current offset from start of x509 cert */
157 /* if cert len was obtained from 2nd byte i.e. */
158 /* cert size is 127 bytes or less */
159 cert_len += 1;
160 }
162 /* cert_len now contains the offset of the last byte */
163 /* of the cert from the ccert_start. To get the size */
164 /* of certificate, add 1 */
166 return cert_len + 1;
167 }
169 void SBL_SciClientInit(void)
170 {
171 int32_t status = CSL_EFAIL;
172 void *sysfw_ptr = gSciclient_firmware;
174 #ifndef SBL_SKIP_SYSFW_INIT
175 /* SYSFW board configurations */
176 Sciclient_DefaultBoardCfgInfo_t boardCfgInfo;
177 Sciclient_ConfigPrms_t config;
178 Sciclient_configPrmsInit(&config);
179 config.opModeFlag = SCICLIENT_SERVICE_OPERATION_MODE_POLLED;
180 config.pBoardCfgPrms = NULL;
181 config.isSecureMode = 1;
182 config.c66xRatRegion = 0;
183 config.skipLocalBoardCfgProcess = TRUE;
185 #if defined(SOC_AM65XX)
186 config.isSecureMode = 0U;
187 #endif /* AM65xx the default board cfg is for non-secure mode */
189 #endif
191 SBL_ADD_PROFILE_POINT;
193 status = SBL_ReadSysfwImage(&sysfw_ptr, SBL_SYSFW_MAX_SIZE);
194 if (status != CSL_PASS)
195 {
196 #if defined(SOC_J721E) || defined(SOC_J7200)
197 SBL_log(SBL_LOG_ERR,"TIFS read...FAILED \n");
198 #else
199 SBL_log(SBL_LOG_ERR,"SYSFW read...FAILED \n");
200 #endif
201 SblErrLoop(__FILE__, __LINE__);
202 }
204 #ifndef SBL_SKIP_SYSFW_INIT
205 SBL_ADD_PROFILE_POINT;
207 status = Sciclient_getDefaultBoardCfgInfo(&boardCfgInfo);
209 #if defined(SBL_ENABLE_HLOS_BOOT) && defined(SOC_AM65XX)
210 /* Replace default Sciclient boardCfgLowRm with alternate version for HLOS boot */
211 boardCfgInfo.boardCfgLowRm = &gSciclient_boardCfgLow_hlos_rm[0U];
212 boardCfgInfo.boardCfgLowRmSize = SCICLIENT_BOARDCFG_RM_LINUX_SIZE_IN_BYTES;
213 #endif
215 if (status != CSL_PASS)
216 {
217 SBL_log(SBL_LOG_ERR,"Sciclient get default board config...FAILED \n");
218 SblErrLoop(__FILE__, __LINE__);
219 }
221 status = Sciclient_loadFirmware((const uint32_t *) sysfw_ptr);
222 if (status != CSL_PASS)
223 {
224 #if defined(SOC_J721E) || defined(SOC_J7200)
225 SBL_log(SBL_LOG_ERR,"TIFS load...FAILED \n");
226 #else
227 SBL_log(SBL_LOG_ERR,"SYSFW load...FAILED \n");
228 #endif
229 SblErrLoop(__FILE__, __LINE__);
230 }
232 SBL_ADD_PROFILE_POINT;
233 status = Sciclient_init(&config);
234 if (status != CSL_PASS)
235 {
236 SBL_log(SBL_LOG_ERR,"Sciclient init ...FAILED \n");
237 SblErrLoop(__FILE__, __LINE__);
238 }
240 #ifndef SBL_SKIP_BRD_CFG_BOARD
241 SBL_ADD_PROFILE_POINT;
242 sblBoardCfgPrms.boardConfigLow = (uint32_t)boardCfgInfo.boardCfgLow;
243 sblBoardCfgPrms.boardConfigHigh = 0;
244 sblBoardCfgPrms.boardConfigSize = boardCfgInfo.boardCfgLowSize;
245 sblBoardCfgPrms.devGrp = SBL_DEVGRP;
246 status = Sciclient_boardCfg(&sblBoardCfgPrms);
247 if (status != CSL_PASS)
248 {
249 SBL_log(SBL_LOG_ERR,"Sciclient board config ...FAILED \n");
250 SblErrLoop(__FILE__, __LINE__);
251 }
252 #endif
254 #ifndef SBL_SKIP_BRD_CFG_PM
255 if (SBL_LOG_LEVEL > SBL_LOG_NONE)
256 {
257 SBL_ADD_PROFILE_POINT;
258 UART_stdioDeInit();
259 }
260 SBL_ADD_PROFILE_POINT;
261 sblBoardCfgPmPrms.boardConfigLow = (uint32_t)boardCfgInfo.boardCfgLowPm;
262 sblBoardCfgPmPrms.boardConfigHigh = 0;
263 sblBoardCfgPmPrms.boardConfigSize = boardCfgInfo.boardCfgLowPmSize;
264 sblBoardCfgPmPrms.devGrp = SBL_DEVGRP;
265 status = Sciclient_boardCfgPm(&sblBoardCfgPmPrms);
266 if (status != CSL_PASS)
267 {
268 SBL_log(SBL_LOG_ERR,"Sciclient board config pm...FAILED \n")
269 SblErrLoop(__FILE__, __LINE__);
270 }
272 if (SBL_LOG_LEVEL > SBL_LOG_NONE)
273 {
274 /* Re-init UART for logging */
275 UART_HwAttrs uart_cfg;
277 SBL_ADD_PROFILE_POINT;
278 UART_socGetInitCfg(BOARD_UART_INSTANCE, &uart_cfg);
279 uart_cfg.frequency = SBL_SYSFW_UART_MODULE_INPUT_CLK;
280 UART_socSetInitCfg(BOARD_UART_INSTANCE, &uart_cfg);
281 UART_stdioInit(BOARD_UART_INSTANCE);
282 }
283 #endif
285 #ifndef SBL_SKIP_BRD_CFG_SEC
286 SBL_ADD_PROFILE_POINT;
287 sblBoardCfgSecPrms.boardConfigLow = (uint32_t)boardCfgInfo.boardCfgLowSec;
288 sblBoardCfgSecPrms.boardConfigHigh = 0;
289 sblBoardCfgSecPrms.boardConfigSize = boardCfgInfo.boardCfgLowSecSize;
290 sblBoardCfgSecPrms.devGrp = SBL_DEVGRP;
291 status = Sciclient_boardCfgSec(&sblBoardCfgSecPrms);
292 if (status != CSL_PASS)
293 {
294 SBL_log(SBL_LOG_ERR,"Sciclient board config sec...FAILED \n");
295 SblErrLoop(__FILE__, __LINE__);
296 }
297 #if defined(SOC_AM65XX) || defined(SOC_J721E) || defined(SOC_J7200)
298 /* Secure ROM has left firewall regions for FSS DAT0 set. Disable them for DMA usage. */
299 uint16_t i;
300 struct tisci_msg_fwl_set_firewall_region_resp respFwCtrl = {0};
301 struct tisci_msg_fwl_set_firewall_region_req reqFwCtrl =
302 {
303 .fwl_id = (uint16_t) MCU_FSS0_S0_FWID,
304 .region = (uint16_t) 0,
305 .n_permission_regs = (uint32_t) 3,
306 /* Set .control to zero to disable the firewall region */
307 .control = (uint32_t) 0,
308 .permissions[0] = (uint32_t) 0,
309 .permissions[1] = (uint32_t) 0,
310 .permissions[2] = (uint32_t) 0,
311 .start_address = 0,
312 .end_address = 0
313 };
315 for (i = 0; i < MCU_FSS0_S0_FW_REGIONS; i++)
316 {
317 reqFwCtrl.region = i;
318 status = Sciclient_firewallSetRegion(&reqFwCtrl, &respFwCtrl, SCICLIENT_SERVICE_WAIT_FOREVER);
319 if (status != CSL_PASS)
320 {
321 SBL_log(SBL_LOG_ERR,"MCU FSS0_S0 firewall region # %d disable...FAILED \n", i);
322 }
323 }
324 #endif
325 #endif
327 #ifndef SBL_SKIP_BRD_CFG_RM
328 SBL_ADD_PROFILE_POINT;
329 sblBoardCfgRmPrms.boardConfigLow = (uint32_t)boardCfgInfo.boardCfgLowRm;
330 sblBoardCfgRmPrms.boardConfigHigh = 0;
331 sblBoardCfgRmPrms.boardConfigSize = boardCfgInfo.boardCfgLowRmSize;
332 sblBoardCfgRmPrms.devGrp = SBL_DEVGRP;
333 gCertLength = boardcfgRmFindCertSize((uint32_t*)boardCfgInfo.boardCfgLowRm);
334 status = Sciclient_boardCfgRm(&sblBoardCfgRmPrms);
335 if (status != CSL_PASS)
336 {
337 SBL_log(SBL_LOG_ERR,"Sciclient board config rm...FAILED \n");
338 SblErrLoop(__FILE__, __LINE__);
339 }
340 #endif
342 /* Get SYSFW/TIFS version */
343 SBL_ADD_PROFILE_POINT;
345 if (SBL_LOG_LEVEL > SBL_LOG_ERR)
346 {
347 struct tisci_msg_version_req req = {0};
348 const Sciclient_ReqPrm_t reqPrm =
349 {
350 TISCI_MSG_VERSION,
351 TISCI_MSG_FLAG_AOP,
352 (const uint8_t *)&req,
353 sizeof(req),
354 SCICLIENT_SERVICE_WAIT_FOREVER
355 };
357 struct tisci_msg_version_resp response;
358 Sciclient_RespPrm_t respPrm =
359 {
360 0,
361 (uint8_t *) &response,
362 (uint32_t)sizeof (response)
363 };
365 status = Sciclient_service(&reqPrm, &respPrm);
366 if (CSL_PASS == status)
367 {
368 if (respPrm.flags == (uint32_t)TISCI_MSG_FLAG_ACK)
369 {
370 SBL_ADD_PROFILE_POINT;
371 #if defined(SOC_J721E) || defined(SOC_J7200)
372 SBL_log(SBL_LOG_MIN,"TIFS ver: %s\n", (char *) response.str);
373 #else
374 SBL_log(SBL_LOG_MIN,"SYSFW ver: %s\n", (char *) response.str);
375 #endif
376 }
377 else
378 {
379 #if defined(SOC_J721E) || defined(SOC_J7200)
380 SBL_log(SBL_LOG_ERR,"TIFS Get Version failed \n");
381 #else
382 SBL_log(SBL_LOG_ERR,"SYSFW Get Version failed \n");
383 #endif
384 SblErrLoop(__FILE__, __LINE__);
385 }
386 }
387 }
390 #if (!defined(SBL_SKIP_BRD_CFG_PM)) || (!defined(SBL_SKIP_BRD_CFG_RM))
391 status = Sciclient_setBoardConfigHeader();
392 if (CSL_PASS == status)
393 {
394 SBL_log(SBL_LOG_MAX,"Sciclient_setBoardConfigHeader... PASSED\n");
395 }
396 else
397 {
398 SBL_log(SBL_LOG_ERR,"Sciclient_setBoardConfigHeader... FAILED\n");
399 SblErrLoop(__FILE__, __LINE__);
400 }
401 #endif
404 #if !defined(SBL_SKIP_MCU_RESET)
405 /* RTI seems to be turned on by ROM. Turning it off so that Power domain can transition */
406 Sciclient_pmSetModuleState(SBL_DEV_ID_RTI0, TISCI_MSG_VALUE_DEVICE_SW_STATE_AUTO_OFF, TISCI_MSG_FLAG_AOP, SCICLIENT_SERVICE_WAIT_FOREVER);
407 Sciclient_pmSetModuleState(SBL_DEV_ID_RTI1, TISCI_MSG_VALUE_DEVICE_SW_STATE_AUTO_OFF, TISCI_MSG_FLAG_AOP, SCICLIENT_SERVICE_WAIT_FOREVER);
408 #if defined(SOC_AM64X)
409 Sciclient_pmSetModuleState(SBL_DEV_ID_RTI8, TISCI_MSG_VALUE_DEVICE_SW_STATE_AUTO_OFF, TISCI_MSG_FLAG_AOP, SCICLIENT_SERVICE_WAIT_FOREVER);
410 Sciclient_pmSetModuleState(SBL_DEV_ID_RTI9, TISCI_MSG_VALUE_DEVICE_SW_STATE_AUTO_OFF, TISCI_MSG_FLAG_AOP, SCICLIENT_SERVICE_WAIT_FOREVER);
411 Sciclient_pmSetModuleState(SBL_DEV_ID_RTI10, TISCI_MSG_VALUE_DEVICE_SW_STATE_AUTO_OFF, TISCI_MSG_FLAG_AOP, SCICLIENT_SERVICE_WAIT_FOREVER);
412 Sciclient_pmSetModuleState(SBL_DEV_ID_RTI11, TISCI_MSG_VALUE_DEVICE_SW_STATE_AUTO_OFF, TISCI_MSG_FLAG_AOP, SCICLIENT_SERVICE_WAIT_FOREVER);
413 Sciclient_pmSetModuleState(SBL_DEV_ID_MCU_RTI0, TISCI_MSG_VALUE_DEVICE_SW_STATE_AUTO_OFF, TISCI_MSG_FLAG_AOP, SCICLIENT_SERVICE_WAIT_FOREVER);
414 #endif
415 #endif
418 #endif
420 SBL_ADD_PROFILE_POINT;
421 }
423 #if (!defined(SBL_SKIP_BRD_CFG_PM)) || (!defined(SBL_SKIP_BRD_CFG_RM))
424 static int32_t Sciclient_setBoardConfigHeader ()
425 {
426 int32_t status = CSL_PASS;
427 #if defined (SOC_J7200) || defined (SOC_J721E)
428 //uint32_t alignedOffset = ((SCICLIENT_BOARDCFG_PM_SIZE_IN_BYTES + 128U)/128U)*128U;
429 uint32_t alignedOffset = SCICLIENT_BOARDCFG_PM_SIZE_IN_BYTES;
430 Sciclient_BoardCfgPrms_t boardCfgPrms_pm =
431 {
432 .boardConfigLow = (uint32_t)SCISERVER_BOARDCONFIG_DATA_ADDR,
433 .boardConfigHigh = 0,
434 .boardConfigSize = SCICLIENT_BOARDCFG_PM_SIZE_IN_BYTES,
435 .devGrp = DEVGRP_ALL
436 };
437 Sciclient_BoardCfgPrms_t boardCfgPrms_rm =
438 {
439 .boardConfigLow =
440 (uint32_t) SCISERVER_BOARDCONFIG_DATA_ADDR + alignedOffset,
441 .boardConfigHigh = 0,
442 .boardConfigSize = SCICLIENT_BOARDCFG_RM_SIZE_IN_BYTES - gCertLength,
443 .devGrp = DEVGRP_ALL
444 };
445 status = Sciclient_boardCfgPrepHeader (
446 (uint8_t *) SCISERVER_COMMON_X509_HEADER_ADDR,
447 (uint8_t *) SCISERVER_BOARDCONFIG_HEADER_ADDR,
448 &boardCfgPrms_pm, &boardCfgPrms_rm);
449 if (CSL_PASS == status)
450 {
451 SBL_log(SBL_LOG_MAX,"SCISERVER Board Configuration header population... ");
452 SBL_log(SBL_LOG_MAX,"PASSED\n");
453 }
454 else
455 {
456 SBL_log(SBL_LOG_MIN,"SCISERVER Board Configuration header population... ");
457 SBL_log(SBL_LOG_MIN,"FAILED\n");
458 }
459 memcpy((void *)boardCfgPrms_pm.boardConfigLow, (void *) sblBoardCfgPmPrms.boardConfigLow, SCICLIENT_BOARDCFG_PM_SIZE_IN_BYTES);
460 memcpy((void *)boardCfgPrms_rm.boardConfigLow, (void *) sblBoardCfgRmPrms.boardConfigLow, SCICLIENT_BOARDCFG_RM_SIZE_IN_BYTES - gCertLength);
461 #endif
462 return status;
463 }
464 #endif