blob: fe750f5b6882977feda0dbe44db2da4f915f3342 [file] [log] [blame]
Julian Hall32798ff2022-12-19 13:33:42 +00001/*
2 * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <stddef.h>
8#include <common/uuid/uuid.h>
9#include <protocols/service/fwu/packed-c/opcodes.h>
10#include <protocols/rpc/common/packed-c/status.h>
11#include <service/fwu/agent/update_agent.h>
12#include <service/fwu/provider/serializer/fwu_provider_serializer.h>
13#include "fwu_provider.h"
14
15/* Service request handlers */
16static rpc_status_t begin_staging_handler(void *context, struct call_req *req);
17static rpc_status_t end_staging_handler(void *context, struct call_req *req);
18static rpc_status_t cancel_staging_handler(void *context, struct call_req *req);
19static rpc_status_t open_handler(void *context, struct call_req *req);
20static rpc_status_t write_stream_handler(void *context, struct call_req *req);
21static rpc_status_t read_stream_handler(void *context, struct call_req *req);
22static rpc_status_t commit_handler(void *context, struct call_req *req);
23static rpc_status_t accept_image_handler(void *context, struct call_req *req);
24static rpc_status_t select_previous_handler(void *context, struct call_req *req);
25
26/* Handler mapping table for service */
27static const struct service_handler handler_table[] = {
28 {TS_FWU_OPCODE_BEGIN_STAGING, begin_staging_handler},
29 {TS_FWU_OPCODE_END_STAGING, end_staging_handler},
30 {TS_FWU_OPCODE_CANCEL_STAGING, cancel_staging_handler},
31 {TS_FWU_OPCODE_OPEN, open_handler},
32 {TS_FWU_OPCODE_WRITE_STREAM, write_stream_handler},
33 {TS_FWU_OPCODE_READ_STREAM, read_stream_handler},
34 {TS_FWU_OPCODE_COMMIT, commit_handler},
35 {TS_FWU_OPCODE_ACCEPT_IMAGE, accept_image_handler},
36 {TS_FWU_OPCODE_SELECT_PREVIOUS, select_previous_handler}
37};
38
39struct rpc_interface *fwu_provider_init(
40 struct fwu_provider *context,
41 struct update_agent *update_agent)
42{
43 /* Initialise the fwu_provider */
44 context->update_agent = update_agent;
45
46 for (size_t encoding = 0; encoding < TS_RPC_ENCODING_LIMIT; ++encoding)
47 context->serializers[encoding] = NULL;
48
49 service_provider_init(&context->base_provider, context,
50 handler_table, sizeof(handler_table)/sizeof(struct service_handler));
51
52 /* Initialise the associated discovery_provider and attach it */
53 discovery_provider_init(&context->discovery_provider);
54 service_provider_extend(
55 &context->base_provider,
56 &context->discovery_provider.base_provider);
57
58 return service_provider_get_rpc_interface(&context->base_provider);
59}
60
61void fwu_provider_deinit(
62 struct fwu_provider *context)
63{
64 discovery_provider_deinit(&context->discovery_provider);
65}
66
67void fwu_provider_register_serializer(
68 struct fwu_provider *context,
69 unsigned int encoding,
70 const struct fwu_provider_serializer *serializer)
71{
72 if (encoding < TS_RPC_ENCODING_LIMIT) {
73
74 context->serializers[encoding] = serializer;
75 discovery_provider_register_supported_encoding(
76 &context->discovery_provider, encoding);
77 }
78}
79
80static const struct fwu_provider_serializer* get_fwu_serializer(
81 struct fwu_provider *this_instance,
82 const struct call_req *req)
83{
84 const struct fwu_provider_serializer* serializer = NULL;
85 unsigned int encoding = call_req_get_encoding(req);
86
87 if (encoding < TS_RPC_ENCODING_LIMIT)
88 serializer = this_instance->serializers[encoding];
89
90 return serializer;
91}
92
93static rpc_status_t begin_staging_handler(void *context, struct call_req *req)
94{
95 struct fwu_provider *this_instance = (struct fwu_provider *)context;
96
97 int op_status = update_agent_begin_staging(this_instance->update_agent);
98
99 call_req_set_opstatus(req, op_status);
100
101 return TS_RPC_CALL_ACCEPTED;
102}
103
104static rpc_status_t end_staging_handler(void *context, struct call_req *req)
105{
106 struct fwu_provider *this_instance = (struct fwu_provider *)context;
107
108 int op_status = update_agent_end_staging(this_instance->update_agent);
109
110 call_req_set_opstatus(req, op_status);
111
112 return TS_RPC_CALL_ACCEPTED;
113}
114
115static rpc_status_t cancel_staging_handler(void *context, struct call_req *req)
116{
117 struct fwu_provider *this_instance = (struct fwu_provider *)context;
118
119 int op_status = update_agent_cancel_staging(this_instance->update_agent);
120
121 call_req_set_opstatus(req, op_status);
122
123 return TS_RPC_CALL_ACCEPTED;
124}
125
126static rpc_status_t open_handler(void *context, struct call_req *req)
127{
128 rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
129 struct call_param_buf *req_buf = call_req_get_req_buf(req);
130 struct fwu_provider *this_instance = (struct fwu_provider *)context;
131 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
132 struct uuid_octets image_type_uuid;
133
134 if (serializer)
135 rpc_status = serializer->deserialize_open_req(req_buf, &image_type_uuid);
136
137 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
138
139 uint32_t handle = 0;
140 int op_status = update_agent_open(this_instance->update_agent,
141 &image_type_uuid, &handle);
142
143 if (!op_status) {
144
145 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
146 rpc_status = serializer->serialize_open_resp(resp_buf, handle);
147 }
148
149 call_req_set_opstatus(req, op_status);
150 }
151
152 return rpc_status;
153}
154
155static rpc_status_t write_stream_handler(void *context, struct call_req *req)
156{
157 rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
158 struct call_param_buf *req_buf = call_req_get_req_buf(req);
159 struct fwu_provider *this_instance = (struct fwu_provider *)context;
160 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
161 uint32_t handle = 0;
162 size_t data_len = 0;
163 const uint8_t *data = NULL;
164
165 if (serializer)
166 rpc_status = serializer->deserialize_write_stream_req(
167 req_buf, &handle, &data_len, &data);
168
169 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
170
171 int op_status = update_agent_write_stream(this_instance->update_agent,
172 handle, data, data_len);
173
174 call_req_set_opstatus(req, op_status);
175 }
176
177 return rpc_status;
178}
179
180static rpc_status_t read_stream_handler(void *context, struct call_req *req)
181{
182 rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
183 struct call_param_buf *req_buf = call_req_get_req_buf(req);
184 struct fwu_provider *this_instance = (struct fwu_provider *)context;
185 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
186 uint32_t handle = 0;
187
188 if (serializer)
189 rpc_status = serializer->deserialize_read_stream_req(req_buf, &handle);
190
191 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
192
193 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
194 uint8_t *payload_buf;
195 size_t max_payload;
196 size_t read_len = 0;
197 size_t total_len = 0;
198
199 serializer->read_stream_resp_payload(resp_buf, &payload_buf, &max_payload);
200
201 int op_status = update_agent_read_stream(this_instance->update_agent,
202 handle, payload_buf, max_payload,
203 &read_len, &total_len);
204
205 if (!op_status)
206 rpc_status = serializer->serialize_read_stream_resp(resp_buf,
207 read_len, total_len);
208
209 call_req_set_opstatus(req, op_status);
210 }
211
212 return rpc_status;
213}
214
215static rpc_status_t commit_handler(void *context, struct call_req *req)
216{
217 rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
218 struct call_param_buf *req_buf = call_req_get_req_buf(req);
219 struct fwu_provider *this_instance = (struct fwu_provider *)context;
220 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
221 uint32_t handle = 0;
222 bool accepted = false;
223 size_t max_atomic_len = 0;
224
225 if (serializer)
226 rpc_status = serializer->deserialize_commit_req(req_buf,
227 &handle, &accepted, &max_atomic_len);
228
229 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
230
231 int op_status = update_agent_commit(
232 this_instance->update_agent, handle, accepted);
233
234 if (!op_status) {
235
236 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
237 rpc_status = serializer->serialize_commit_resp(resp_buf, 0, 0);
238 }
239
240 call_req_set_opstatus(req, op_status);
241 }
242
243 return rpc_status;
244}
245
246static rpc_status_t accept_image_handler(void *context, struct call_req *req)
247{
248 rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
249 struct call_param_buf *req_buf = call_req_get_req_buf(req);
250 struct fwu_provider *this_instance = (struct fwu_provider *)context;
251 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
252 struct uuid_octets image_type_uuid;
253
254 if (serializer)
255 rpc_status = serializer->deserialize_accept_req(req_buf, &image_type_uuid);
256
257 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
258
259 int op_status = update_agent_accept(this_instance->update_agent, &image_type_uuid);
260
261 call_req_set_opstatus(req, op_status);
262 }
263
264 return rpc_status;
265}
266
267static rpc_status_t select_previous_handler(void *context, struct call_req *req)
268{
269 struct fwu_provider *this_instance = (struct fwu_provider *)context;
270
271 int op_status = update_agent_select_previous(this_instance->update_agent);
272
273 call_req_set_opstatus(req, op_status);
274
275 return TS_RPC_CALL_ACCEPTED;
276}