blob: 275d39946a923a4c533e32207f8e307c6dcc45da [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
Julian Hall32798ff2022-12-19 13:33:42 +00007#include "fwu_provider.h"
8
Gyorgy Szing3c446242023-03-31 01:53:15 +02009#include <stddef.h>
10
11#include "common/uuid/uuid.h"
12#include "protocols/rpc/common/packed-c/status.h"
13#include "protocols/service/fwu/packed-c/opcodes.h"
14#include "service/fwu/agent/update_agent.h"
15#include "service/fwu/provider/serializer/fwu_provider_serializer.h"
16
Julian Hall32798ff2022-12-19 13:33:42 +000017/* Service request handlers */
18static rpc_status_t begin_staging_handler(void *context, struct call_req *req);
19static rpc_status_t end_staging_handler(void *context, struct call_req *req);
20static rpc_status_t cancel_staging_handler(void *context, struct call_req *req);
21static rpc_status_t open_handler(void *context, struct call_req *req);
22static rpc_status_t write_stream_handler(void *context, struct call_req *req);
23static rpc_status_t read_stream_handler(void *context, struct call_req *req);
24static rpc_status_t commit_handler(void *context, struct call_req *req);
25static rpc_status_t accept_image_handler(void *context, struct call_req *req);
26static rpc_status_t select_previous_handler(void *context, struct call_req *req);
27
28/* Handler mapping table for service */
29static const struct service_handler handler_table[] = {
Gyorgy Szing3c446242023-03-31 01:53:15 +020030 { TS_FWU_OPCODE_BEGIN_STAGING, begin_staging_handler },
31 { TS_FWU_OPCODE_END_STAGING, end_staging_handler },
32 { TS_FWU_OPCODE_CANCEL_STAGING, cancel_staging_handler },
33 { TS_FWU_OPCODE_OPEN, open_handler },
34 { TS_FWU_OPCODE_WRITE_STREAM, write_stream_handler },
35 { TS_FWU_OPCODE_READ_STREAM, read_stream_handler },
36 { TS_FWU_OPCODE_COMMIT, commit_handler },
37 { TS_FWU_OPCODE_ACCEPT_IMAGE, accept_image_handler },
38 { TS_FWU_OPCODE_SELECT_PREVIOUS, select_previous_handler }
Julian Hall32798ff2022-12-19 13:33:42 +000039};
40
Gyorgy Szing3c446242023-03-31 01:53:15 +020041struct rpc_interface *fwu_provider_init(struct fwu_provider *context,
42 struct update_agent *update_agent)
Julian Hall32798ff2022-12-19 13:33:42 +000043{
44 /* Initialise the fwu_provider */
45 context->update_agent = update_agent;
46
47 for (size_t encoding = 0; encoding < TS_RPC_ENCODING_LIMIT; ++encoding)
48 context->serializers[encoding] = NULL;
49
Gyorgy Szing3c446242023-03-31 01:53:15 +020050 service_provider_init(&context->base_provider, context, handler_table,
51 sizeof(handler_table) / sizeof(struct service_handler));
Julian Hall32798ff2022-12-19 13:33:42 +000052
53 /* Initialise the associated discovery_provider and attach it */
54 discovery_provider_init(&context->discovery_provider);
Gyorgy Szing3c446242023-03-31 01:53:15 +020055 service_provider_extend(&context->base_provider,
56 &context->discovery_provider.base_provider);
Julian Hall32798ff2022-12-19 13:33:42 +000057
58 return service_provider_get_rpc_interface(&context->base_provider);
59}
60
Gyorgy Szing3c446242023-03-31 01:53:15 +020061void fwu_provider_deinit(struct fwu_provider *context)
Julian Hall32798ff2022-12-19 13:33:42 +000062{
63 discovery_provider_deinit(&context->discovery_provider);
64}
65
Gyorgy Szing3c446242023-03-31 01:53:15 +020066void fwu_provider_register_serializer(struct fwu_provider *context, unsigned int encoding,
67 const struct fwu_provider_serializer *serializer)
Julian Hall32798ff2022-12-19 13:33:42 +000068{
69 if (encoding < TS_RPC_ENCODING_LIMIT) {
Julian Hall32798ff2022-12-19 13:33:42 +000070 context->serializers[encoding] = serializer;
Gyorgy Szing3c446242023-03-31 01:53:15 +020071 discovery_provider_register_supported_encoding(&context->discovery_provider,
72 encoding);
Julian Hall32798ff2022-12-19 13:33:42 +000073 }
74}
75
Gyorgy Szing3c446242023-03-31 01:53:15 +020076static const struct fwu_provider_serializer *get_fwu_serializer(struct fwu_provider *this_instance,
77 const struct call_req *req)
Julian Hall32798ff2022-12-19 13:33:42 +000078{
Gyorgy Szing3c446242023-03-31 01:53:15 +020079 const struct fwu_provider_serializer *serializer = NULL;
Julian Hall32798ff2022-12-19 13:33:42 +000080 unsigned int encoding = call_req_get_encoding(req);
81
82 if (encoding < TS_RPC_ENCODING_LIMIT)
83 serializer = this_instance->serializers[encoding];
84
85 return serializer;
86}
87
88static rpc_status_t begin_staging_handler(void *context, struct call_req *req)
89{
90 struct fwu_provider *this_instance = (struct fwu_provider *)context;
91
92 int op_status = update_agent_begin_staging(this_instance->update_agent);
93
94 call_req_set_opstatus(req, op_status);
95
96 return TS_RPC_CALL_ACCEPTED;
97}
98
99static rpc_status_t end_staging_handler(void *context, struct call_req *req)
100{
101 struct fwu_provider *this_instance = (struct fwu_provider *)context;
102
103 int op_status = update_agent_end_staging(this_instance->update_agent);
104
105 call_req_set_opstatus(req, op_status);
106
107 return TS_RPC_CALL_ACCEPTED;
108}
109
110static rpc_status_t cancel_staging_handler(void *context, struct call_req *req)
111{
112 struct fwu_provider *this_instance = (struct fwu_provider *)context;
113
114 int op_status = update_agent_cancel_staging(this_instance->update_agent);
115
116 call_req_set_opstatus(req, op_status);
117
118 return TS_RPC_CALL_ACCEPTED;
119}
120
121static rpc_status_t open_handler(void *context, struct call_req *req)
122{
123 rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
124 struct call_param_buf *req_buf = call_req_get_req_buf(req);
125 struct fwu_provider *this_instance = (struct fwu_provider *)context;
126 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
127 struct uuid_octets image_type_uuid;
128
129 if (serializer)
130 rpc_status = serializer->deserialize_open_req(req_buf, &image_type_uuid);
131
132 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
Julian Hall32798ff2022-12-19 13:33:42 +0000133 uint32_t handle = 0;
Gyorgy Szing3c446242023-03-31 01:53:15 +0200134 int op_status =
135 update_agent_open(this_instance->update_agent, &image_type_uuid, &handle);
Julian Hall32798ff2022-12-19 13:33:42 +0000136
137 if (!op_status) {
Julian Hall32798ff2022-12-19 13:33:42 +0000138 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
139 rpc_status = serializer->serialize_open_resp(resp_buf, handle);
140 }
141
142 call_req_set_opstatus(req, op_status);
143 }
144
145 return rpc_status;
146}
147
148static rpc_status_t write_stream_handler(void *context, struct call_req *req)
149{
150 rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
151 struct call_param_buf *req_buf = call_req_get_req_buf(req);
152 struct fwu_provider *this_instance = (struct fwu_provider *)context;
153 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
154 uint32_t handle = 0;
155 size_t data_len = 0;
156 const uint8_t *data = NULL;
157
158 if (serializer)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200159 rpc_status = serializer->deserialize_write_stream_req(req_buf, &handle, &data_len,
160 &data);
Julian Hall32798ff2022-12-19 13:33:42 +0000161
162 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
Gyorgy Szing3c446242023-03-31 01:53:15 +0200163 int op_status = update_agent_write_stream(this_instance->update_agent, handle, data,
164 data_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000165
166 call_req_set_opstatus(req, op_status);
167 }
168
169 return rpc_status;
170}
171
172static rpc_status_t read_stream_handler(void *context, struct call_req *req)
173{
174 rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
175 struct call_param_buf *req_buf = call_req_get_req_buf(req);
176 struct fwu_provider *this_instance = (struct fwu_provider *)context;
177 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
178 uint32_t handle = 0;
179
180 if (serializer)
181 rpc_status = serializer->deserialize_read_stream_req(req_buf, &handle);
182
183 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
Julian Hall32798ff2022-12-19 13:33:42 +0000184 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
185 uint8_t *payload_buf;
186 size_t max_payload;
187 size_t read_len = 0;
188 size_t total_len = 0;
189
190 serializer->read_stream_resp_payload(resp_buf, &payload_buf, &max_payload);
191
Gyorgy Szing3c446242023-03-31 01:53:15 +0200192 int op_status = update_agent_read_stream(this_instance->update_agent, handle,
193 payload_buf, max_payload, &read_len,
194 &total_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000195
196 if (!op_status)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200197 rpc_status = serializer->serialize_read_stream_resp(resp_buf, read_len,
198 total_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000199
200 call_req_set_opstatus(req, op_status);
201 }
202
203 return rpc_status;
204}
205
206static rpc_status_t commit_handler(void *context, struct call_req *req)
207{
208 rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
209 struct call_param_buf *req_buf = call_req_get_req_buf(req);
210 struct fwu_provider *this_instance = (struct fwu_provider *)context;
211 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
212 uint32_t handle = 0;
213 bool accepted = false;
214 size_t max_atomic_len = 0;
215
216 if (serializer)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200217 rpc_status = serializer->deserialize_commit_req(req_buf, &handle, &accepted,
218 &max_atomic_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000219
220 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
Gyorgy Szing3c446242023-03-31 01:53:15 +0200221 int op_status = update_agent_commit(this_instance->update_agent, handle, accepted);
Julian Hall32798ff2022-12-19 13:33:42 +0000222
223 if (!op_status) {
Julian Hall32798ff2022-12-19 13:33:42 +0000224 struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
225 rpc_status = serializer->serialize_commit_resp(resp_buf, 0, 0);
226 }
227
228 call_req_set_opstatus(req, op_status);
229 }
230
231 return rpc_status;
232}
233
234static rpc_status_t accept_image_handler(void *context, struct call_req *req)
235{
236 rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
237 struct call_param_buf *req_buf = call_req_get_req_buf(req);
238 struct fwu_provider *this_instance = (struct fwu_provider *)context;
239 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
240 struct uuid_octets image_type_uuid;
241
242 if (serializer)
243 rpc_status = serializer->deserialize_accept_req(req_buf, &image_type_uuid);
244
245 if (rpc_status == TS_RPC_CALL_ACCEPTED) {
Julian Hall32798ff2022-12-19 13:33:42 +0000246 int op_status = update_agent_accept(this_instance->update_agent, &image_type_uuid);
247
248 call_req_set_opstatus(req, op_status);
249 }
250
251 return rpc_status;
252}
253
254static rpc_status_t select_previous_handler(void *context, struct call_req *req)
255{
256 struct fwu_provider *this_instance = (struct fwu_provider *)context;
257
258 int op_status = update_agent_select_previous(this_instance->update_agent);
259
260 call_req_set_opstatus(req, op_status);
261
262 return TS_RPC_CALL_ACCEPTED;
263}