blob: ded6db7d1427ec18a50cdd1c283b8f73cc9a18fc [file] [log] [blame]
Julian Hall32798ff2022-12-19 13:33:42 +00001/*
Imre Kisefadd3a2024-06-28 14:15:57 +02002 * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
Julian Hall32798ff2022-12-19 13:33:42 +00003 *
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"
Imre Kisefadd3a2024-06-28 14:15:57 +020014#include "service/fwu/common/update_agent_interface.h"
Gyorgy Szing3c446242023-03-31 01:53:15 +020015#include "service/fwu/provider/serializer/fwu_provider_serializer.h"
Imre Kise584a982023-07-04 17:59:18 +020016#include "fwu_uuid.h"
Gyorgy Szing3c446242023-03-31 01:53:15 +020017
Imre Kis18b387d2024-07-02 13:51:07 +020018#ifndef FWU_PROVIDER_MAX_PARTIAL_UPDATE_COUNT
19#define FWU_PROVIDER_MAX_PARTIAL_UPDATE_COUNT (4)
20#endif /* FWU_PROVIDER_MAX_PARTIAL_UPDATE_COUNT */
21
Julian Hall32798ff2022-12-19 13:33:42 +000022/* Service request handlers */
Imre Kis18b387d2024-07-02 13:51:07 +020023static rpc_status_t discover_handler(void *context, struct rpc_request *req);
Imre Kise584a982023-07-04 17:59:18 +020024static rpc_status_t begin_staging_handler(void *context, struct rpc_request *req);
25static rpc_status_t end_staging_handler(void *context, struct rpc_request *req);
26static rpc_status_t cancel_staging_handler(void *context, struct rpc_request *req);
27static rpc_status_t open_handler(void *context, struct rpc_request *req);
28static rpc_status_t write_stream_handler(void *context, struct rpc_request *req);
29static rpc_status_t read_stream_handler(void *context, struct rpc_request *req);
30static rpc_status_t commit_handler(void *context, struct rpc_request *req);
31static rpc_status_t accept_image_handler(void *context, struct rpc_request *req);
32static rpc_status_t select_previous_handler(void *context, struct rpc_request *req);
Julian Hall32798ff2022-12-19 13:33:42 +000033
34/* Handler mapping table for service */
35static const struct service_handler handler_table[] = {
Imre Kis18b387d2024-07-02 13:51:07 +020036 { FWU_FUNC_ID_DISCOVER, discover_handler },
37 { FWU_FUNC_ID_BEGIN_STAGING, begin_staging_handler },
38 { FWU_FUNC_ID_END_STAGING, end_staging_handler },
39 { FWU_FUNC_ID_CANCEL_STAGING, cancel_staging_handler },
40 { FWU_FUNC_ID_OPEN, open_handler },
41 { FWU_FUNC_ID_WRITE_STREAM, write_stream_handler },
42 { FWU_FUNC_ID_READ_STREAM, read_stream_handler },
43 { FWU_FUNC_ID_COMMIT, commit_handler },
44 { FWU_FUNC_ID_ACCEPT_IMAGE, accept_image_handler },
45 { FWU_FUNC_ID_SELECT_PREVIOUS, select_previous_handler }
Julian Hall32798ff2022-12-19 13:33:42 +000046};
47
Imre Kise584a982023-07-04 17:59:18 +020048struct rpc_service_interface *fwu_provider_init(struct fwu_provider *context,
Gyorgy Szing3c446242023-03-31 01:53:15 +020049 struct update_agent *update_agent)
Julian Hall32798ff2022-12-19 13:33:42 +000050{
Imre Kise584a982023-07-04 17:59:18 +020051 const struct rpc_uuid service_uuid = { .uuid = TS_FWU_SERVICE_UUID };
Julian Hall32798ff2022-12-19 13:33:42 +000052 /* Initialise the fwu_provider */
53 context->update_agent = update_agent;
54
55 for (size_t encoding = 0; encoding < TS_RPC_ENCODING_LIMIT; ++encoding)
56 context->serializers[encoding] = NULL;
57
Imre Kise584a982023-07-04 17:59:18 +020058 service_provider_init(&context->base_provider, context, &service_uuid, handler_table,
Gyorgy Szing3c446242023-03-31 01:53:15 +020059 sizeof(handler_table) / sizeof(struct service_handler));
Julian Hall32798ff2022-12-19 13:33:42 +000060
Julian Hall32798ff2022-12-19 13:33:42 +000061 return service_provider_get_rpc_interface(&context->base_provider);
62}
63
Gyorgy Szing3c446242023-03-31 01:53:15 +020064void fwu_provider_deinit(struct fwu_provider *context)
Julian Hall32798ff2022-12-19 13:33:42 +000065{
Imre Kise584a982023-07-04 17:59:18 +020066 (void)context;
Julian Hall32798ff2022-12-19 13:33:42 +000067}
68
Gyorgy Szing3c446242023-03-31 01:53:15 +020069void fwu_provider_register_serializer(struct fwu_provider *context, unsigned int encoding,
70 const struct fwu_provider_serializer *serializer)
Julian Hall32798ff2022-12-19 13:33:42 +000071{
72 if (encoding < TS_RPC_ENCODING_LIMIT) {
Julian Hall32798ff2022-12-19 13:33:42 +000073 context->serializers[encoding] = serializer;
Julian Hall32798ff2022-12-19 13:33:42 +000074 }
75}
76
Gyorgy Szing3c446242023-03-31 01:53:15 +020077static const struct fwu_provider_serializer *get_fwu_serializer(struct fwu_provider *this_instance,
Imre Kise584a982023-07-04 17:59:18 +020078 const struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +000079{
Gyorgy Szing3c446242023-03-31 01:53:15 +020080 const struct fwu_provider_serializer *serializer = NULL;
Imre Kise584a982023-07-04 17:59:18 +020081 unsigned int encoding = 0;
Julian Hall32798ff2022-12-19 13:33:42 +000082
83 if (encoding < TS_RPC_ENCODING_LIMIT)
84 serializer = this_instance->serializers[encoding];
85
86 return serializer;
87}
88
Imre Kis18b387d2024-07-02 13:51:07 +020089static uint16_t generate_function_presence(const struct update_agent *agent,
90 uint8_t function_presence[FWU_FUNC_ID_COUNT])
91{
92 uint16_t num_func = 0;
93
94#define ADD_FUNC_IF_PRESENT(func, id) \
95do { \
96 if (agent->interface->func != NULL) \
97 function_presence[num_func++] = (id); \
98} while (0)
99
100 ADD_FUNC_IF_PRESENT(discover, FWU_FUNC_ID_DISCOVER);
101 ADD_FUNC_IF_PRESENT(begin_staging, FWU_FUNC_ID_BEGIN_STAGING);
102 ADD_FUNC_IF_PRESENT(end_staging, FWU_FUNC_ID_END_STAGING);
103 ADD_FUNC_IF_PRESENT(cancel_staging, FWU_FUNC_ID_CANCEL_STAGING);
104 ADD_FUNC_IF_PRESENT(open, FWU_FUNC_ID_OPEN);
105 ADD_FUNC_IF_PRESENT(write_stream, FWU_FUNC_ID_WRITE_STREAM);
106 ADD_FUNC_IF_PRESENT(read_stream, FWU_FUNC_ID_READ_STREAM);
107 ADD_FUNC_IF_PRESENT(commit, FWU_FUNC_ID_COMMIT);
108 ADD_FUNC_IF_PRESENT(accept_image, FWU_FUNC_ID_ACCEPT_IMAGE);
109 ADD_FUNC_IF_PRESENT(select_previous, FWU_FUNC_ID_SELECT_PREVIOUS);
110
111#undef ADD_FUNC_IF_PRESENT
112
113 return num_func;
114}
115
116static rpc_status_t discover_handler(void *context, struct rpc_request *req)
117{
118 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
119 struct fwu_provider *this_instance = (struct fwu_provider *)context;
120 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
121 struct fwu_discovery_result discovery_result = { 0 };
122 struct rpc_buffer *resp_buf = &req->response;
123
124 if (!serializer)
125 return rpc_status;
126
127 req->service_status = update_agent_discover(this_instance->update_agent, &discovery_result);
128
129 if (!req->service_status) {
130 uint16_t num_func = 0;
131 uint8_t function_presence[FWU_FUNC_ID_COUNT] = { 0 };
132
133 num_func = generate_function_presence(this_instance->update_agent,
134 function_presence);
135
136 rpc_status = serializer->serialize_discover_resp(
137 resp_buf, discovery_result.service_status, discovery_result.version_major,
138 discovery_result.version_minor, num_func, discovery_result.max_payload_size,
139 discovery_result.flags, discovery_result.vendor_specific_flags,
140 function_presence);
141 } else {
142 /*
143 * The actual service call failed, but the request was successful on the RPC level
144 */
145 rpc_status = RPC_SUCCESS;
146 }
147
148 return rpc_status;
149}
150
Imre Kise584a982023-07-04 17:59:18 +0200151static rpc_status_t begin_staging_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000152{
Imre Kis18b387d2024-07-02 13:51:07 +0200153 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
154 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000155 struct fwu_provider *this_instance = (struct fwu_provider *)context;
Imre Kis18b387d2024-07-02 13:51:07 +0200156 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
157 uint32_t vendor_flags = 0;
158 uint32_t partial_update_count = 0;
159 struct uuid_octets update_guid[FWU_PROVIDER_MAX_PARTIAL_UPDATE_COUNT];
Julian Hall32798ff2022-12-19 13:33:42 +0000160
Imre Kis18b387d2024-07-02 13:51:07 +0200161 if (serializer)
162 rpc_status = serializer->deserialize_begin_staging_req(
163 req_buf, &vendor_flags, &partial_update_count,
164 FWU_PROVIDER_MAX_PARTIAL_UPDATE_COUNT, update_guid);
Julian Hall32798ff2022-12-19 13:33:42 +0000165
Imre Kis18b387d2024-07-02 13:51:07 +0200166 if (rpc_status == RPC_SUCCESS)
167 req->service_status = update_agent_begin_staging(
168 this_instance->update_agent, vendor_flags, partial_update_count,
169 update_guid);
170
171 return rpc_status;
Julian Hall32798ff2022-12-19 13:33:42 +0000172}
173
Imre Kise584a982023-07-04 17:59:18 +0200174static rpc_status_t end_staging_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000175{
176 struct fwu_provider *this_instance = (struct fwu_provider *)context;
177
Imre Kise584a982023-07-04 17:59:18 +0200178 req->service_status = update_agent_end_staging(this_instance->update_agent);
Julian Hall32798ff2022-12-19 13:33:42 +0000179
Imre Kise584a982023-07-04 17:59:18 +0200180 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +0000181}
182
Imre Kise584a982023-07-04 17:59:18 +0200183static rpc_status_t cancel_staging_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000184{
185 struct fwu_provider *this_instance = (struct fwu_provider *)context;
186
Imre Kise584a982023-07-04 17:59:18 +0200187 req->service_status = update_agent_cancel_staging(this_instance->update_agent);
Julian Hall32798ff2022-12-19 13:33:42 +0000188
Imre Kise584a982023-07-04 17:59:18 +0200189 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +0000190}
191
Imre Kise584a982023-07-04 17:59:18 +0200192static rpc_status_t open_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000193{
Imre Kise584a982023-07-04 17:59:18 +0200194 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
195 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000196 struct fwu_provider *this_instance = (struct fwu_provider *)context;
197 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
Imre Kis18b387d2024-07-02 13:51:07 +0200198 struct uuid_octets image_type_uuid = { 0 };
199 uint8_t op_type = 0;
Julian Hall32798ff2022-12-19 13:33:42 +0000200
201 if (serializer)
Imre Kis18b387d2024-07-02 13:51:07 +0200202 rpc_status = serializer->deserialize_open_req(req_buf, &image_type_uuid, &op_type);
Julian Hall32798ff2022-12-19 13:33:42 +0000203
Imre Kise584a982023-07-04 17:59:18 +0200204 if (rpc_status == RPC_SUCCESS) {
Julian Hall32798ff2022-12-19 13:33:42 +0000205 uint32_t handle = 0;
Imre Kise584a982023-07-04 17:59:18 +0200206 req->service_status =
Imre Kis18b387d2024-07-02 13:51:07 +0200207 update_agent_open(this_instance->update_agent, &image_type_uuid, op_type,
Imre Kisefadd3a2024-06-28 14:15:57 +0200208 &handle);
Julian Hall32798ff2022-12-19 13:33:42 +0000209
Imre Kise584a982023-07-04 17:59:18 +0200210 if (!req->service_status) {
211 struct rpc_buffer *resp_buf = &req->response;
Julian Hall32798ff2022-12-19 13:33:42 +0000212 rpc_status = serializer->serialize_open_resp(resp_buf, handle);
213 }
Julian Hall32798ff2022-12-19 13:33:42 +0000214 }
215
216 return rpc_status;
217}
218
Imre Kise584a982023-07-04 17:59:18 +0200219static rpc_status_t write_stream_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000220{
Imre Kise584a982023-07-04 17:59:18 +0200221 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
222 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000223 struct fwu_provider *this_instance = (struct fwu_provider *)context;
224 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
225 uint32_t handle = 0;
226 size_t data_len = 0;
227 const uint8_t *data = NULL;
228
229 if (serializer)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200230 rpc_status = serializer->deserialize_write_stream_req(req_buf, &handle, &data_len,
231 &data);
Julian Hall32798ff2022-12-19 13:33:42 +0000232
Imre Kise584a982023-07-04 17:59:18 +0200233 if (rpc_status == RPC_SUCCESS) {
234 req->service_status = update_agent_write_stream(this_instance->update_agent, handle,
235 data, data_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000236 }
237
238 return rpc_status;
239}
240
Imre Kise584a982023-07-04 17:59:18 +0200241static rpc_status_t read_stream_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000242{
Imre Kise584a982023-07-04 17:59:18 +0200243 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
244 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000245 struct fwu_provider *this_instance = (struct fwu_provider *)context;
246 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
247 uint32_t handle = 0;
248
249 if (serializer)
250 rpc_status = serializer->deserialize_read_stream_req(req_buf, &handle);
251
Imre Kise584a982023-07-04 17:59:18 +0200252 if (rpc_status == RPC_SUCCESS) {
253 struct rpc_buffer *resp_buf = &req->response;
Julian Hall32798ff2022-12-19 13:33:42 +0000254 uint8_t *payload_buf;
255 size_t max_payload;
256 size_t read_len = 0;
257 size_t total_len = 0;
258
259 serializer->read_stream_resp_payload(resp_buf, &payload_buf, &max_payload);
260
Imre Kise584a982023-07-04 17:59:18 +0200261 req->service_status = update_agent_read_stream(this_instance->update_agent, handle,
Gyorgy Szing3c446242023-03-31 01:53:15 +0200262 payload_buf, max_payload, &read_len,
263 &total_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000264
Imre Kise584a982023-07-04 17:59:18 +0200265 if (!req->service_status)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200266 rpc_status = serializer->serialize_read_stream_resp(resp_buf, read_len,
267 total_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000268
Julian Hall32798ff2022-12-19 13:33:42 +0000269 }
270
271 return rpc_status;
272}
273
Imre Kise584a982023-07-04 17:59:18 +0200274static rpc_status_t commit_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000275{
Imre Kise584a982023-07-04 17:59:18 +0200276 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
277 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000278 struct fwu_provider *this_instance = (struct fwu_provider *)context;
279 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
280 uint32_t handle = 0;
281 bool accepted = false;
282 size_t max_atomic_len = 0;
283
284 if (serializer)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200285 rpc_status = serializer->deserialize_commit_req(req_buf, &handle, &accepted,
286 &max_atomic_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000287
Imre Kise584a982023-07-04 17:59:18 +0200288 if (rpc_status == RPC_SUCCESS) {
Imre Kisefadd3a2024-06-28 14:15:57 +0200289 uint32_t progress = 0;
290 uint32_t total_work = 0;
291
Imre Kise584a982023-07-04 17:59:18 +0200292 req->service_status = update_agent_commit(this_instance->update_agent, handle,
Imre Kisefadd3a2024-06-28 14:15:57 +0200293 accepted, 0, &progress, &total_work);
Julian Hall32798ff2022-12-19 13:33:42 +0000294
Imre Kise584a982023-07-04 17:59:18 +0200295 if (!req->service_status) {
296 struct rpc_buffer *resp_buf = &req->response;
Imre Kisefadd3a2024-06-28 14:15:57 +0200297 rpc_status = serializer->serialize_commit_resp(resp_buf, progress, total_work);
Julian Hall32798ff2022-12-19 13:33:42 +0000298 }
Julian Hall32798ff2022-12-19 13:33:42 +0000299 }
300
301 return rpc_status;
302}
303
Imre Kise584a982023-07-04 17:59:18 +0200304static rpc_status_t accept_image_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000305{
Imre Kise584a982023-07-04 17:59:18 +0200306 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
307 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000308 struct fwu_provider *this_instance = (struct fwu_provider *)context;
309 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
310 struct uuid_octets image_type_uuid;
311
312 if (serializer)
313 rpc_status = serializer->deserialize_accept_req(req_buf, &image_type_uuid);
314
Imre Kise584a982023-07-04 17:59:18 +0200315 if (rpc_status == RPC_SUCCESS)
Imre Kisefadd3a2024-06-28 14:15:57 +0200316 req->service_status = update_agent_accept_image(this_instance->update_agent,
317 &image_type_uuid);
Julian Hall32798ff2022-12-19 13:33:42 +0000318
319 return rpc_status;
320}
321
Imre Kise584a982023-07-04 17:59:18 +0200322static rpc_status_t select_previous_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000323{
324 struct fwu_provider *this_instance = (struct fwu_provider *)context;
325
Imre Kise584a982023-07-04 17:59:18 +0200326 req->service_status = update_agent_select_previous(this_instance->update_agent);
Julian Hall32798ff2022-12-19 13:33:42 +0000327
Imre Kise584a982023-07-04 17:59:18 +0200328 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +0000329}