blob: 3db5cf5850ae46f117243d0a1cdfee28542ab0a1 [file] [log] [blame]
Dan Handley9df48042015-03-19 18:58:55 +00001/*
Vikram Kanigiri72084192016-02-08 16:29:30 +00002 * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
Dan Handley9df48042015-03-19 18:58:55 +00003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Dan Handley9df48042015-03-19 18:58:55 +00005 */
6
7#include <arch_helpers.h>
Sandrine Bailleux04b66d82015-03-18 14:52:53 +00008#include <assert.h>
Dan Handley9df48042015-03-19 18:58:55 +00009#include <css_def.h>
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000010#include <debug.h>
Dan Handley9df48042015-03-19 18:58:55 +000011#include <platform.h>
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000012#include <stdint.h>
Soby Mathew200fffd2016-10-21 11:34:59 +010013#include "../drivers/scpi/css_mhu.h"
14#include "../drivers/scpi/css_scpi.h"
Dan Handley9df48042015-03-19 18:58:55 +000015#include "css_scp_bootloader.h"
Dan Handley9df48042015-03-19 18:58:55 +000016
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000017/* ID of the MHU slot used for the BOM protocol */
18#define BOM_MHU_SLOT_ID 0
Dan Handley9df48042015-03-19 18:58:55 +000019
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000020/* Boot commands sent from AP -> SCP */
21#define BOOT_CMD_INFO 0x00
22#define BOOT_CMD_DATA 0x01
Dan Handley9df48042015-03-19 18:58:55 +000023
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000024/* BOM command header */
Dan Handley9df48042015-03-19 18:58:55 +000025typedef struct {
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000026 uint32_t id : 8;
27 uint32_t reserved : 24;
28} bom_cmd_t;
Dan Handley9df48042015-03-19 18:58:55 +000029
30typedef struct {
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000031 uint32_t image_size;
32 uint32_t checksum;
33} cmd_info_payload_t;
Dan Handley9df48042015-03-19 18:58:55 +000034
35/*
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000036 * Unlike the SCPI protocol, the boot protocol uses the same memory region
Dan Handley9df48042015-03-19 18:58:55 +000037 * for both AP -> SCP and SCP -> AP transfers; define the address of this...
38 */
Vikram Kanigiri72084192016-02-08 16:29:30 +000039#define BOM_SHARED_MEM PLAT_CSS_SCP_COM_SHARED_MEM_BASE
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000040#define BOM_CMD_HEADER ((bom_cmd_t *) BOM_SHARED_MEM)
41#define BOM_CMD_PAYLOAD ((void *) (BOM_SHARED_MEM + sizeof(bom_cmd_t)))
Dan Handley9df48042015-03-19 18:58:55 +000042
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000043typedef struct {
44 /* Offset from the base address of the Trusted RAM */
45 uint32_t offset;
46 uint32_t block_size;
47} cmd_data_payload_t;
Dan Handley9df48042015-03-19 18:58:55 +000048
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000049static void scp_boot_message_start(void)
50{
51 mhu_secure_message_start(BOM_MHU_SLOT_ID);
Dan Handley9df48042015-03-19 18:58:55 +000052}
53
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000054static void scp_boot_message_send(size_t payload_size)
Dan Handley9df48042015-03-19 18:58:55 +000055{
Juan Castillo2e86cb12016-01-13 15:01:09 +000056 /* Ensure that any write to the BOM payload area is seen by SCP before
57 * we write to the MHU register. If these 2 writes were reordered by
58 * the CPU then SCP would read stale payload data */
59 dmbst();
Dan Handley9df48042015-03-19 18:58:55 +000060
61 /* Send command to SCP */
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000062 mhu_secure_message_send(BOM_MHU_SLOT_ID);
Dan Handley9df48042015-03-19 18:58:55 +000063}
64
65static uint32_t scp_boot_message_wait(size_t size)
66{
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000067 uint32_t mhu_status;
68
69 mhu_status = mhu_secure_message_wait();
70
71 /* Expect an SCP Boot Protocol message, reject any other protocol */
72 if (mhu_status != (1 << BOM_MHU_SLOT_ID)) {
73 ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n",
74 mhu_status);
75 panic();
76 }
Dan Handley9df48042015-03-19 18:58:55 +000077
Juan Castillo2e86cb12016-01-13 15:01:09 +000078 /* Ensure that any read to the BOM payload area is done after reading
79 * the MHU register. If these 2 reads were reordered then the CPU would
80 * read invalid payload data */
81 dmbld();
Dan Handley9df48042015-03-19 18:58:55 +000082
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000083 return *(uint32_t *) BOM_SHARED_MEM;
Dan Handley9df48042015-03-19 18:58:55 +000084}
85
86static void scp_boot_message_end(void)
87{
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000088 mhu_secure_message_end(BOM_MHU_SLOT_ID);
Dan Handley9df48042015-03-19 18:58:55 +000089}
90
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000091int scp_bootloader_transfer(void *image, unsigned int image_size)
Dan Handley9df48042015-03-19 18:58:55 +000092{
Sandrine Bailleux04b66d82015-03-18 14:52:53 +000093 uint32_t response;
94 uint32_t checksum;
95 cmd_info_payload_t *cmd_info_payload;
96 cmd_data_payload_t *cmd_data_payload;
Dan Handley9df48042015-03-19 18:58:55 +000097
Juan Castilloa72b6472015-12-10 15:49:17 +000098 assert((uintptr_t) image == SCP_BL2_BASE);
Dan Handley9df48042015-03-19 18:58:55 +000099
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000100 if ((image_size == 0) || (image_size % 4 != 0)) {
Juan Castilloa72b6472015-12-10 15:49:17 +0000101 ERROR("Invalid size for the SCP_BL2 image. Must be a multiple of "
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000102 "4 bytes and not zero (current size = 0x%x)\n",
103 image_size);
104 return -1;
105 }
Dan Handley9df48042015-03-19 18:58:55 +0000106
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000107 /* Extract the checksum from the image */
108 checksum = *(uint32_t *) image;
109 image = (char *) image + sizeof(checksum);
110 image_size -= sizeof(checksum);
Dan Handley9df48042015-03-19 18:58:55 +0000111
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000112 mhu_secure_init();
Dan Handley9df48042015-03-19 18:58:55 +0000113
Juan Castilloa72b6472015-12-10 15:49:17 +0000114 VERBOSE("Send info about the SCP_BL2 image to be transferred to SCP\n");
Dan Handley9df48042015-03-19 18:58:55 +0000115
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000116 /*
117 * Send information about the SCP firmware image about to be transferred
118 * to SCP
119 */
120 scp_boot_message_start();
121
122 BOM_CMD_HEADER->id = BOOT_CMD_INFO;
123 cmd_info_payload = BOM_CMD_PAYLOAD;
124 cmd_info_payload->image_size = image_size;
125 cmd_info_payload->checksum = checksum;
126
127 scp_boot_message_send(sizeof(*cmd_info_payload));
Sandrine Bailleux7da652d2015-04-13 11:47:48 +0100128#if CSS_DETECT_PRE_1_7_0_SCP
129 {
130 const uint32_t deprecated_scp_nack_cmd = 0x404;
131 uint32_t mhu_status;
132
133 VERBOSE("Detecting SCP version incompatibility\n");
134
135 mhu_status = mhu_secure_message_wait();
136 if (mhu_status == deprecated_scp_nack_cmd) {
137 ERROR("Detected an incompatible version of the SCP firmware.\n");
138 ERROR("Only versions from v1.7.0 onwards are supported.\n");
139 ERROR("Please update the SCP firmware.\n");
140 return -1;
141 }
142
143 VERBOSE("SCP version looks OK\n");
144 }
145#endif /* CSS_DETECT_PRE_1_7_0_SCP */
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000146 response = scp_boot_message_wait(sizeof(response));
147 scp_boot_message_end();
Dan Handley9df48042015-03-19 18:58:55 +0000148
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000149 if (response != 0) {
150 ERROR("SCP BOOT_CMD_INFO returned error %u\n", response);
151 return -1;
152 }
153
Juan Castilloa72b6472015-12-10 15:49:17 +0000154 VERBOSE("Transferring SCP_BL2 image to SCP\n");
Dan Handley9df48042015-03-19 18:58:55 +0000155
Juan Castilloa72b6472015-12-10 15:49:17 +0000156 /* Transfer SCP_BL2 image to SCP */
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000157 scp_boot_message_start();
Dan Handley9df48042015-03-19 18:58:55 +0000158
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000159 BOM_CMD_HEADER->id = BOOT_CMD_DATA;
160 cmd_data_payload = BOM_CMD_PAYLOAD;
Sandrine Bailleux47ea1bc2015-06-09 11:53:33 +0100161 cmd_data_payload->offset = (uintptr_t) image - ARM_TRUSTED_SRAM_BASE;
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000162 cmd_data_payload->block_size = image_size;
Dan Handley9df48042015-03-19 18:58:55 +0000163
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000164 scp_boot_message_send(sizeof(*cmd_data_payload));
165 response = scp_boot_message_wait(sizeof(response));
166 scp_boot_message_end();
Dan Handley9df48042015-03-19 18:58:55 +0000167
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000168 if (response != 0) {
169 ERROR("SCP BOOT_CMD_DATA returned error %u\n", response);
170 return -1;
Dan Handley9df48042015-03-19 18:58:55 +0000171 }
172
Sandrine Bailleux04b66d82015-03-18 14:52:53 +0000173 VERBOSE("Waiting for SCP to signal it is ready to go on\n");
174
Dan Handley9df48042015-03-19 18:58:55 +0000175 /* Wait for SCP to signal it's ready */
176 return scpi_wait_ready();
177}