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