blob: ed31dbd9ae60e257361e1c0febd84e6d32a1519c [file] [log] [blame]
Miklos Balint386b8b52017-11-29 13:12:32 +00001/*
2 * Copyright (c) 2017, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#ifndef __SPM_SPM_DB_H__
9#define __SPM_SPM_DB_H__
10
11#include <stdint.h>
12
13/* This limit is only used to define the size of the database reserved for
14 * services. There's no requirement that it match the number of services
15 * that get registered in a specific build
16 */
17#define SPM_MAX_SERVICES (6)
18
19#define SERVICE_ID_GET(id) (id - TFM_SEC_FUNC_BASE)
20
21typedef int32_t(*ss_init_function)(void);
22
23#if TFM_LVL == 1
24struct spm_service_region_t {
25 uint32_t service_id;
26 uint32_t stack_ptr;
27 uint32_t periph_start;
28 uint32_t periph_limit;
29 uint16_t periph_ppc_bank;
30 uint16_t periph_ppc_loc;
31 ss_init_function service_init;
32};
33#else
34struct spm_service_region_t {
35 uint32_t service_id;
36 uint32_t code_start;
37 uint32_t code_limit;
38 uint32_t ro_start;
39 uint32_t ro_limit;
40 uint32_t rw_start;
41 uint32_t rw_limit;
42 uint32_t zi_start;
43 uint32_t zi_limit;
44 uint32_t stack_bottom;
45 uint32_t stack_top;
46 uint32_t stack_ptr;
47 uint32_t periph_start;
48 uint32_t periph_limit;
49 uint16_t periph_ppc_bank;
50 uint16_t periph_ppc_loc;
51 ss_init_function service_init;
52};
53#endif
54
55struct spm_service_db_t {
56 uint32_t is_init;
57 uint32_t services_count;
58 struct spm_service_region_t services[SPM_MAX_SERVICES];
59};
60
61/* Macros to pick linker symbols and allow to form the service data base */
62#define REGION(a, b, c) a##b##c
63#define REGION_NAME(a, b, c) REGION(a, b, c)
64#if TFM_LVL == 1
65#define REGION_DECLARE(a, b, c)
66#else
67#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
68#endif
69
70#define SERVICE_DECLARE(service) \
71 REGION_DECLARE(Image$$, service, $$Base); \
72 REGION_DECLARE(Image$$, service, $$Limit); \
73 REGION_DECLARE(Image$$, service, $$RO$$Base); \
74 REGION_DECLARE(Image$$, service, $$RO$$Limit); \
75 REGION_DECLARE(Image$$, service, _DATA$$RW$$Base); \
76 REGION_DECLARE(Image$$, service, _DATA$$RW$$Limit); \
77 REGION_DECLARE(Image$$, service, _DATA$$ZI$$Base); \
78 REGION_DECLARE(Image$$, service, _DATA$$ZI$$Limit); \
79 REGION_DECLARE(Image$$, service, _STACK$$ZI$$Base); \
80 REGION_DECLARE(Image$$, service, _STACK$$ZI$$Limit); \
81
82
83#if TFM_LVL == 1
84#define SERVICE_ADD(service) { \
85 if (index >= max_services) { \
86 return max_services; \
87 } \
88 db_ptr = (uint32_t *)&(db->services[index]); \
89 *db_ptr++ = service##_ID; \
90 *db_ptr++ = 0U; /* stack pointer on service enter */ \
91 *db_ptr++ = 0U; /* peripheral start */ \
92 *db_ptr++ = 0U; /* peripheral limit */ \
93 *db_ptr++ = 0U; /* uint16_t[2] peripheral bank/loc */ \
94 *db_ptr++ = 0U; /* service init function*/ \
95 index++; \
96 }
97#else
98#define SERVICE_ADD(service) { \
99 if (index >= max_services) { \
100 return max_services; \
101 } \
102 db_ptr = (uint32_t *)&(db->services[index]); \
103 *db_ptr++ = service##_ID; \
104 *db_ptr++ = (uint32_t)&REGION_NAME(Image$$, service, $$Base); \
105 *db_ptr++ = (uint32_t)&REGION_NAME(Image$$, service, $$Limit); \
106 *db_ptr++ = (uint32_t)&REGION_NAME(Image$$, service, $$RO$$Base); \
107 *db_ptr++ = (uint32_t)&REGION_NAME(Image$$, service, $$RO$$Limit); \
108 *db_ptr++ = (uint32_t)&REGION_NAME(Image$$, service, _DATA$$RW$$Base); \
109 *db_ptr++ = (uint32_t)&REGION_NAME(Image$$, service, _DATA$$RW$$Limit); \
110 *db_ptr++ = (uint32_t)&REGION_NAME(Image$$, service, _DATA$$ZI$$Base); \
111 *db_ptr++ = (uint32_t)&REGION_NAME(Image$$, service, _DATA$$ZI$$Limit); \
112 *db_ptr++ = (uint32_t)&REGION_NAME(Image$$, service, _STACK$$ZI$$Base); \
113 *db_ptr++ = (uint32_t)&REGION_NAME(Image$$, service, _STACK$$ZI$$Limit); \
114 *db_ptr++ = (uint32_t)&REGION_NAME(Image$$, service, _STACK$$ZI$$Limit); \
115 *db_ptr++ = 0U; /* peripheral start */ \
116 *db_ptr++ = 0U; /* peripheral limit */ \
117 *db_ptr++ = 0U; /* uint16_t[2] peripheral bank/loc */ \
118 *db_ptr++ = 0U; /* service init function*/ \
119 index++; \
120}
121#endif
122
123#define SERVICE_ADD_PERIPHERAL(service, start, limit, bank, loc) { \
124 db_ptr = (uint32_t *)&(db->services[SERVICE_ID_GET(service##_ID)]); \
125 ((struct spm_service_region_t *)db_ptr)->periph_start = start; \
126 ((struct spm_service_region_t *)db_ptr)->periph_limit = limit; \
127 ((struct spm_service_region_t *)db_ptr)->periph_ppc_bank = bank; \
128 ((struct spm_service_region_t *)db_ptr)->periph_ppc_loc = loc; \
129 }
130
131#define SERVICE_ADD_INIT_FUNC(service, init_func) { \
132 extern int32_t init_func(void); \
133 db_ptr = (uint32_t *)&(db->services[SERVICE_ID_GET(service##_ID)]); \
134 ((struct spm_service_region_t *)db_ptr)->service_init = init_func; \
135 }
136
137/*This file is meant to be included twice*/
138#include "user_service_defines.inc"
139
140struct spm_service_db_t;
141
142uint32_t create_user_service_db(struct spm_service_db_t *db,
143 uint32_t max_services)
144{
145 uint32_t index = 0;
146 uint32_t *db_ptr;
147
148#include "user_service_defines.inc"
149
150 return index;
151}
152
153#endif /* __SPM_SPM_DB_H__ */