blob: 747337af38de356dca8a549afb2c43538eb943e7 [file] [log] [blame]
Antonio Nino Diaz89036412018-10-18 14:54:57 +01001/*
2 * Copyright (c) 2018, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
8#include <platform_def.h>
9#include <spinlock.h>
10#include <utils_def.h>
11
12/*******************************************************************************
13 * Secure Service response global array. All the responses to the requests done
14 * to the Secure Partition are stored here. They are removed from the array as
15 * soon as their value is read.
16 ******************************************************************************/
17struct sprt_response {
18 int is_valid;
19 uint32_t token;
20 uint16_t client_id, handle;
21 u_register_t x1, x2, x3;
22};
23
24static struct sprt_response responses[PLAT_SPM_RESPONSES_MAX];
25
26static spinlock_t responses_lock;
27
28/* Add response to the global response buffer. Returns 0 on success else -1. */
29int spm_response_add(uint16_t client_id, uint16_t handle, uint32_t token,
30 u_register_t x1, u_register_t x2, u_register_t x3)
31{
32 spin_lock(&responses_lock);
33
34 /* Make sure that there isn't any other response with the same token. */
35 for (unsigned int i = 0U; i < ARRAY_SIZE(responses); i++) {
36 struct sprt_response *resp = &(responses[i]);
37
38 if ((resp->is_valid == 1) && (resp->token == token)) {
39 return -1;
40 }
41 }
42
43 for (int i = 0; i < ARRAY_SIZE(responses); i++) {
44 struct sprt_response *resp = &(responses[i]);
45
46 if (resp->is_valid == 0) {
47 resp->token = token;
48 resp->client_id = client_id;
49 resp->handle = handle;
50 resp->x1 = x1;
51 resp->x2 = x2;
52 resp->x3 = x3;
53
54 dmbish();
55
56 resp->is_valid = 1;
57
58 spin_unlock(&responses_lock);
59
60 return 0;
61 }
62 }
63
64 spin_unlock(&responses_lock);
65
66 return -1;
67}
68
69/*
70 * Returns a response from the requests array and removes it from it. Returns 0
71 * on success, -1 if it wasn't found.
72 */
73int spm_response_get(uint16_t client_id, uint16_t handle, uint32_t token,
74 u_register_t *x1, u_register_t *x2, u_register_t *x3)
75{
76 spin_lock(&responses_lock);
77
78 for (unsigned int i = 0U; i < ARRAY_SIZE(responses); i++) {
79 struct sprt_response *resp = &(responses[i]);
80
81 /* Ignore invalid entries */
82 if (resp->is_valid == 0) {
83 continue;
84 }
85
86 /* Make sure that all the information matches the stored one */
87 if ((resp->token != token) || (resp->client_id != client_id) ||
88 (resp->handle != handle)) {
89 continue;
90 }
91
92 *x1 = resp->x1;
93 *x2 = resp->x2;
94 *x3 = resp->x3;
95
96 dmbish();
97
98 resp->is_valid = 0;
99
100 spin_unlock(&responses_lock);
101
102 return 0;
103 }
104
105 spin_unlock(&responses_lock);
106
107 return -1;
108}