1 /*
2 * Copyright (c) 2026, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <stdint.h>
8
9 #include <arch.h>
10 #include <arch_features.h>
11 #include <common/debug.h>
12 #include <lib/gpt_rme/gpt_rme.h>
13 #include <lib/smccc.h>
14 #include <services/firme_svc.h>
15 #include <smccc_helpers.h>
16
17 /* Feature reg 0 indicates which ABIs are supported for base service. */
18 #define FEAT_REG_0_DEFAULT (FIRME_BASE_VERSION_BIT | FIRME_BASE_FEATURES_BIT)
19
20 /* Feature reg 1 shows available services and base functionalities. */
21 #define FEAT_REG_1_DEFAULT \
22 ((0x0 & FIRME_BASE_MAX_SH_BUF_PG_CNT_MASK)) \
23 << FIRME_BASE_MAX_SH_BUF_PG_CNT_SHIFT | \
24 ((0x0 & FIRME_BASE_MIN_SH_BUF_SZ_MASK) \
25 << FIRME_BASE_MIN_SH_BUF_SZ_SHIFT)
26
27 /* Structure describing base service. */
28 firme_service_info_t base_info = {
29 .version = FIRME_VERSION(FIRME_BASE_VERSION_MAJOR,
30 FIRME_BASE_VERSION_MINOR),
31 .instance_support =
32 (BIT(FIRME_SECURE) | BIT(FIRME_NONSECURE) | BIT(FIRME_REALM)),
33 .num_feature_regs = 2,
34 .feature_reg = { FEAT_REG_0_DEFAULT, FEAT_REG_1_DEFAULT },
35 };
36
firme_base_get_feat_reg_1(firme_instance_e instance)37 static uint64_t firme_base_get_feat_reg_1(firme_instance_e instance)
38 {
39 firme_service_info_t *info __unused;
40 uint64_t reg = base_info.feature_reg[1];
41
42 info = firme_granule_mgmt_service_get_info();
43 if ((info != NULL) &&
44 ((info->instance_support & BIT(instance)) != 0U)) {
45 reg |= FIRME_BASE_SERVICE_GRANULE_MGMT_BIT;
46 }
47
48 return reg;
49 }
50
get_firme_service_version(firme_instance_e instance,firme_service_id_e service_id)51 static int32_t get_firme_service_version(firme_instance_e instance,
52 firme_service_id_e service_id)
53 {
54 firme_service_info_t *info = NULL;
55
56 if (service_id >= FIRME_SERVICE_ID_MAX) {
57 return FIRME_NOT_SUPPORTED;
58 }
59
60 switch (service_id) {
61 case FIRME_BASE_ID:
62 info = &base_info;
63 break;
64 case FIRME_GRANULE_MGMT_ID:
65 info = firme_granule_mgmt_service_get_info();
66 break;
67 default:
68 return FIRME_NOT_SUPPORTED;
69 }
70
71 if ((info != NULL) && (info->instance_support & BIT(instance))) {
72 return info->version;
73 }
74
75 /* Return zero to indicate not supported. */
76 return FIRME_NOT_SUPPORTED;
77 }
78
get_firme_feature_reg(uint64_t * reg,firme_instance_e instance,uint8_t service_id,uint8_t reg_index)79 static int32_t get_firme_feature_reg(uint64_t *reg, firme_instance_e instance,
80 uint8_t service_id, uint8_t reg_index)
81 {
82 firme_service_info_t *info = NULL;
83
84 if (service_id >= FIRME_SERVICE_ID_MAX) {
85 return FIRME_NOT_SUPPORTED;
86 }
87
88 switch (service_id) {
89 case FIRME_BASE_ID:
90 if (reg_index < base_info.num_feature_regs) {
91 if (reg_index == 1) {
92 *reg = firme_base_get_feat_reg_1(instance);
93 } else {
94 *reg = base_info.feature_reg[reg_index];
95 }
96 return FIRME_SUCCESS;
97 }
98 break;
99 case FIRME_GRANULE_MGMT_ID:
100 info = firme_granule_mgmt_service_get_info();
101 break;
102 }
103
104 if ((info != NULL) && (reg_index < info->num_feature_regs) &&
105 (info->instance_support & BIT(instance))) {
106 *reg = info->feature_reg[reg_index];
107 return FIRME_SUCCESS;
108 }
109
110 return FIRME_NOT_SUPPORTED;
111 }
112
firme_base_service_handler(firme_instance_e instance,uint32_t smc_fid,uint64_t x1,uint64_t x2,uint64_t x3,uint64_t x4,void * cookie,void * handle,uint64_t flags)113 u_register_t firme_base_service_handler(firme_instance_e instance,
114 uint32_t smc_fid, uint64_t x1,
115 uint64_t x2, uint64_t x3, uint64_t x4,
116 void *cookie, void *handle,
117 uint64_t flags)
118 {
119 uint64_t reg;
120
121 switch (smc_fid) {
122 case FIRME_SERVICE_VERSION_FID:
123 SMC_RET1(handle,
124 get_firme_service_version(instance, (uint8_t)x1));
125 break;
126 case FIRME_SERVICE_FEATURES_FID:
127 if (get_firme_feature_reg(®, instance, (uint8_t)x1,
128 (uint8_t)x2) == FIRME_SUCCESS) {
129 SMC_RET2(handle, FIRME_SUCCESS, reg);
130 } else {
131 SMC_RET1(handle, FIRME_NOT_SUPPORTED);
132 }
133 break;
134 default:
135 ERROR("FIRME Base Service FID 0x%X not implemented\n", smc_fid);
136 SMC_RET1(handle, FIRME_NOT_SUPPORTED);
137 }
138 }
139