blob: a6d25d49bf956f8ce1390a402559e396125bfb88 [file] [log] [blame]
Vishal Bhoj82c80712015-12-15 21:13:33 +05301/*
2 * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <arch_helpers.h>
32#include <platform.h>
33#include "juno_def.h"
34#include "mhu.h"
35#include "scp_bootloader.h"
36#include "scpi.h"
37
38/* Boot commands sent from AP -> SCP */
39#define BOOT_CMD_START 0x01
40#define BOOT_CMD_DATA 0x02
41
42typedef struct {
43 uint32_t image_size;
44} cmd_start_payload;
45
46typedef struct {
47 uint32_t sequence_num;
48 uint32_t offset;
49 uint32_t size;
50} cmd_data_payload;
51
52#define BOOT_DATA_MAX_SIZE 0x1000
53
54/* Boot commands sent from SCP -> AP */
55#define BOOT_CMD_ACK 0x03
56#define BOOT_CMD_NACK 0x04
57
58typedef struct {
59 uint32_t sequence_num;
60} cmd_ack_payload;
61
62/*
63 * Unlike the runtime protocol, the boot protocol uses the same memory region
64 * for both AP -> SCP and SCP -> AP transfers; define the address of this...
65 */
66static void * const cmd_payload = (void *)(MHU_SECURE_BASE + 0x0080);
67
68static void *scp_boot_message_start(void)
69{
70 mhu_secure_message_start();
71
72 return cmd_payload;
73}
74
75static void scp_boot_message_send(unsigned command, size_t size)
76{
77 /* Make sure payload can be seen by SCP */
78 if (MHU_PAYLOAD_CACHED)
79 flush_dcache_range((unsigned long)cmd_payload, size);
80
81 /* Send command to SCP */
82 mhu_secure_message_send(command | (size << 8));
83}
84
85static uint32_t scp_boot_message_wait(size_t size)
86{
87 uint32_t response = mhu_secure_message_wait();
88
89 /* Make sure we see the reply from the SCP and not any stale data */
90 if (MHU_PAYLOAD_CACHED)
91 inv_dcache_range((unsigned long)cmd_payload, size);
92
93 return response & 0xff;
94}
95
96static void scp_boot_message_end(void)
97{
98 mhu_secure_message_end();
99}
100
101static int transfer_block(uint32_t sequence_num, uint32_t offset, uint32_t size)
102{
103 cmd_data_payload *cmd_data = scp_boot_message_start();
104 cmd_data->sequence_num = sequence_num;
105 cmd_data->offset = offset;
106 cmd_data->size = size;
107
108 scp_boot_message_send(BOOT_CMD_DATA, sizeof(*cmd_data));
109
110 cmd_ack_payload *cmd_ack = cmd_payload;
111 int ok = scp_boot_message_wait(sizeof(*cmd_ack)) == BOOT_CMD_ACK
112 && cmd_ack->sequence_num == sequence_num;
113
114 scp_boot_message_end();
115
116 return ok;
117}
118
119int scp_bootloader_transfer(void *image, unsigned int image_size)
120{
121 uintptr_t offset = (uintptr_t)image - MHU_SECURE_BASE;
122 uintptr_t end = offset + image_size;
123 uint32_t response;
124
125 mhu_secure_init();
126
127 /* Initiate communications with SCP */
128 do {
129 cmd_start_payload *cmd_start = scp_boot_message_start();
130 cmd_start->image_size = image_size;
131
132 scp_boot_message_send(BOOT_CMD_START, sizeof(*cmd_start));
133
134 response = scp_boot_message_wait(0);
135
136 scp_boot_message_end();
137 } while (response != BOOT_CMD_ACK);
138
139 /* Transfer image to SCP a block at a time */
140 uint32_t sequence_num = 1;
141 size_t size;
142 while ((size = end - offset) != 0) {
143 if (size > BOOT_DATA_MAX_SIZE)
144 size = BOOT_DATA_MAX_SIZE;
145 while (!transfer_block(sequence_num, offset, size))
146 ; /* Retry forever */
147 offset += size;
148 sequence_num++;
149 }
150
151 /* Wait for SCP to signal it's ready */
152 return scpi_wait_ready();
153}