blob: 3e0c9496fce0244a63663f572c0d7e1d34e430f7 [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)) {
41 return -1;
42 }
43 }
44
Ambroise Vincenta88a35d2019-02-14 09:48:21 +000045 for (unsigned int i = 0U; i < ARRAY_SIZE(responses); i++) {
Antonio Nino Diaz89036412018-10-18 14:54:57 +010046 struct sprt_response *resp = &(responses[i]);
47
48 if (resp->is_valid == 0) {
49 resp->token = token;
50 resp->client_id = client_id;
51 resp->handle = handle;
52 resp->x1 = x1;
53 resp->x2 = x2;
54 resp->x3 = x3;
55
56 dmbish();
57
58 resp->is_valid = 1;
59
60 spin_unlock(&responses_lock);
61
62 return 0;
63 }
64 }
65
66 spin_unlock(&responses_lock);
67
68 return -1;
69}
70
71/*
72 * Returns a response from the requests array and removes it from it. Returns 0
73 * on success, -1 if it wasn't found.
74 */
75int spm_response_get(uint16_t client_id, uint16_t handle, uint32_t token,
76 u_register_t *x1, u_register_t *x2, u_register_t *x3)
77{
78 spin_lock(&responses_lock);
79
80 for (unsigned int i = 0U; i < ARRAY_SIZE(responses); i++) {
81 struct sprt_response *resp = &(responses[i]);
82
83 /* Ignore invalid entries */
84 if (resp->is_valid == 0) {
85 continue;
86 }
87
88 /* Make sure that all the information matches the stored one */
89 if ((resp->token != token) || (resp->client_id != client_id) ||
90 (resp->handle != handle)) {
91 continue;
92 }
93
94 *x1 = resp->x1;
95 *x2 = resp->x2;
96 *x3 = resp->x3;
97
98 dmbish();
99
100 resp->is_valid = 0;
101
102 spin_unlock(&responses_lock);
103
104 return 0;
105 }
106
107 spin_unlock(&responses_lock);
108
109 return -1;
110}