blob: 9085a98bb8a8e6086582b6f6d849abee0e63102c [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 };
Imre Kis6fd73d82024-07-04 13:36:10 +020052 struct rpc_service_interface *rpc_interface = NULL;
53
Julian Hall32798ff2022-12-19 13:33:42 +000054 /* Initialise the fwu_provider */
55 context->update_agent = update_agent;
56
57 for (size_t encoding = 0; encoding < TS_RPC_ENCODING_LIMIT; ++encoding)
58 context->serializers[encoding] = NULL;
59
Imre Kise584a982023-07-04 17:59:18 +020060 service_provider_init(&context->base_provider, context, &service_uuid, handler_table,
Gyorgy Szing3c446242023-03-31 01:53:15 +020061 sizeof(handler_table) / sizeof(struct service_handler));
Julian Hall32798ff2022-12-19 13:33:42 +000062
Imre Kis6fd73d82024-07-04 13:36:10 +020063 rpc_interface = service_provider_get_rpc_interface(&context->base_provider);
64 if (!rpc_interface)
65 return NULL;
66
67 return fwu_provider_shim_init(&context->shim, rpc_interface);
Julian Hall32798ff2022-12-19 13:33:42 +000068}
69
Gyorgy Szing3c446242023-03-31 01:53:15 +020070void fwu_provider_deinit(struct fwu_provider *context)
Julian Hall32798ff2022-12-19 13:33:42 +000071{
Imre Kise584a982023-07-04 17:59:18 +020072 (void)context;
Julian Hall32798ff2022-12-19 13:33:42 +000073}
74
Gyorgy Szing3c446242023-03-31 01:53:15 +020075void fwu_provider_register_serializer(struct fwu_provider *context, unsigned int encoding,
76 const struct fwu_provider_serializer *serializer)
Julian Hall32798ff2022-12-19 13:33:42 +000077{
78 if (encoding < TS_RPC_ENCODING_LIMIT) {
Julian Hall32798ff2022-12-19 13:33:42 +000079 context->serializers[encoding] = serializer;
Julian Hall32798ff2022-12-19 13:33:42 +000080 }
81}
82
Gyorgy Szing3c446242023-03-31 01:53:15 +020083static const struct fwu_provider_serializer *get_fwu_serializer(struct fwu_provider *this_instance,
Imre Kise584a982023-07-04 17:59:18 +020084 const struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +000085{
Gyorgy Szing3c446242023-03-31 01:53:15 +020086 const struct fwu_provider_serializer *serializer = NULL;
Imre Kise584a982023-07-04 17:59:18 +020087 unsigned int encoding = 0;
Julian Hall32798ff2022-12-19 13:33:42 +000088
89 if (encoding < TS_RPC_ENCODING_LIMIT)
90 serializer = this_instance->serializers[encoding];
91
92 return serializer;
93}
94
Imre Kis18b387d2024-07-02 13:51:07 +020095static uint16_t generate_function_presence(const struct update_agent *agent,
96 uint8_t function_presence[FWU_FUNC_ID_COUNT])
97{
98 uint16_t num_func = 0;
99
100#define ADD_FUNC_IF_PRESENT(func, id) \
101do { \
102 if (agent->interface->func != NULL) \
103 function_presence[num_func++] = (id); \
104} while (0)
105
106 ADD_FUNC_IF_PRESENT(discover, FWU_FUNC_ID_DISCOVER);
107 ADD_FUNC_IF_PRESENT(begin_staging, FWU_FUNC_ID_BEGIN_STAGING);
108 ADD_FUNC_IF_PRESENT(end_staging, FWU_FUNC_ID_END_STAGING);
109 ADD_FUNC_IF_PRESENT(cancel_staging, FWU_FUNC_ID_CANCEL_STAGING);
110 ADD_FUNC_IF_PRESENT(open, FWU_FUNC_ID_OPEN);
111 ADD_FUNC_IF_PRESENT(write_stream, FWU_FUNC_ID_WRITE_STREAM);
112 ADD_FUNC_IF_PRESENT(read_stream, FWU_FUNC_ID_READ_STREAM);
113 ADD_FUNC_IF_PRESENT(commit, FWU_FUNC_ID_COMMIT);
114 ADD_FUNC_IF_PRESENT(accept_image, FWU_FUNC_ID_ACCEPT_IMAGE);
115 ADD_FUNC_IF_PRESENT(select_previous, FWU_FUNC_ID_SELECT_PREVIOUS);
116
117#undef ADD_FUNC_IF_PRESENT
118
119 return num_func;
120}
121
122static rpc_status_t discover_handler(void *context, struct rpc_request *req)
123{
124 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
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 fwu_discovery_result discovery_result = { 0 };
128 struct rpc_buffer *resp_buf = &req->response;
129
130 if (!serializer)
131 return rpc_status;
132
133 req->service_status = update_agent_discover(this_instance->update_agent, &discovery_result);
134
135 if (!req->service_status) {
136 uint16_t num_func = 0;
137 uint8_t function_presence[FWU_FUNC_ID_COUNT] = { 0 };
138
139 num_func = generate_function_presence(this_instance->update_agent,
140 function_presence);
141
142 rpc_status = serializer->serialize_discover_resp(
143 resp_buf, discovery_result.service_status, discovery_result.version_major,
144 discovery_result.version_minor, num_func, discovery_result.max_payload_size,
145 discovery_result.flags, discovery_result.vendor_specific_flags,
146 function_presence);
147 } else {
148 /*
149 * The actual service call failed, but the request was successful on the RPC level
150 */
151 rpc_status = RPC_SUCCESS;
152 }
153
154 return rpc_status;
155}
156
Imre Kise584a982023-07-04 17:59:18 +0200157static rpc_status_t begin_staging_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000158{
Imre Kis18b387d2024-07-02 13:51:07 +0200159 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
160 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000161 struct fwu_provider *this_instance = (struct fwu_provider *)context;
Imre Kis18b387d2024-07-02 13:51:07 +0200162 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
163 uint32_t vendor_flags = 0;
164 uint32_t partial_update_count = 0;
165 struct uuid_octets update_guid[FWU_PROVIDER_MAX_PARTIAL_UPDATE_COUNT];
Julian Hall32798ff2022-12-19 13:33:42 +0000166
Imre Kis18b387d2024-07-02 13:51:07 +0200167 if (serializer)
168 rpc_status = serializer->deserialize_begin_staging_req(
169 req_buf, &vendor_flags, &partial_update_count,
170 FWU_PROVIDER_MAX_PARTIAL_UPDATE_COUNT, update_guid);
Julian Hall32798ff2022-12-19 13:33:42 +0000171
Imre Kis18b387d2024-07-02 13:51:07 +0200172 if (rpc_status == RPC_SUCCESS)
173 req->service_status = update_agent_begin_staging(
174 this_instance->update_agent, vendor_flags, partial_update_count,
175 update_guid);
176
177 return rpc_status;
Julian Hall32798ff2022-12-19 13:33:42 +0000178}
179
Imre Kise584a982023-07-04 17:59:18 +0200180static rpc_status_t end_staging_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000181{
182 struct fwu_provider *this_instance = (struct fwu_provider *)context;
183
Imre Kise584a982023-07-04 17:59:18 +0200184 req->service_status = update_agent_end_staging(this_instance->update_agent);
Julian Hall32798ff2022-12-19 13:33:42 +0000185
Imre Kise584a982023-07-04 17:59:18 +0200186 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +0000187}
188
Imre Kise584a982023-07-04 17:59:18 +0200189static rpc_status_t cancel_staging_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000190{
191 struct fwu_provider *this_instance = (struct fwu_provider *)context;
192
Imre Kise584a982023-07-04 17:59:18 +0200193 req->service_status = update_agent_cancel_staging(this_instance->update_agent);
Julian Hall32798ff2022-12-19 13:33:42 +0000194
Imre Kise584a982023-07-04 17:59:18 +0200195 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +0000196}
197
Imre Kise584a982023-07-04 17:59:18 +0200198static rpc_status_t open_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000199{
Imre Kise584a982023-07-04 17:59:18 +0200200 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
201 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000202 struct fwu_provider *this_instance = (struct fwu_provider *)context;
203 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
Imre Kis18b387d2024-07-02 13:51:07 +0200204 struct uuid_octets image_type_uuid = { 0 };
205 uint8_t op_type = 0;
Julian Hall32798ff2022-12-19 13:33:42 +0000206
207 if (serializer)
Imre Kis18b387d2024-07-02 13:51:07 +0200208 rpc_status = serializer->deserialize_open_req(req_buf, &image_type_uuid, &op_type);
Julian Hall32798ff2022-12-19 13:33:42 +0000209
Imre Kise584a982023-07-04 17:59:18 +0200210 if (rpc_status == RPC_SUCCESS) {
Julian Hall32798ff2022-12-19 13:33:42 +0000211 uint32_t handle = 0;
Imre Kise584a982023-07-04 17:59:18 +0200212 req->service_status =
Imre Kis18b387d2024-07-02 13:51:07 +0200213 update_agent_open(this_instance->update_agent, &image_type_uuid, op_type,
Imre Kisefadd3a2024-06-28 14:15:57 +0200214 &handle);
Julian Hall32798ff2022-12-19 13:33:42 +0000215
Imre Kise584a982023-07-04 17:59:18 +0200216 if (!req->service_status) {
217 struct rpc_buffer *resp_buf = &req->response;
Julian Hall32798ff2022-12-19 13:33:42 +0000218 rpc_status = serializer->serialize_open_resp(resp_buf, handle);
219 }
Julian Hall32798ff2022-12-19 13:33:42 +0000220 }
221
222 return rpc_status;
223}
224
Imre Kise584a982023-07-04 17:59:18 +0200225static rpc_status_t write_stream_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000226{
Imre Kise584a982023-07-04 17:59:18 +0200227 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
228 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000229 struct fwu_provider *this_instance = (struct fwu_provider *)context;
230 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
231 uint32_t handle = 0;
232 size_t data_len = 0;
233 const uint8_t *data = NULL;
234
235 if (serializer)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200236 rpc_status = serializer->deserialize_write_stream_req(req_buf, &handle, &data_len,
237 &data);
Julian Hall32798ff2022-12-19 13:33:42 +0000238
Imre Kise584a982023-07-04 17:59:18 +0200239 if (rpc_status == RPC_SUCCESS) {
240 req->service_status = update_agent_write_stream(this_instance->update_agent, handle,
241 data, data_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000242 }
243
244 return rpc_status;
245}
246
Imre Kise584a982023-07-04 17:59:18 +0200247static rpc_status_t read_stream_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000248{
Imre Kise584a982023-07-04 17:59:18 +0200249 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
250 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000251 struct fwu_provider *this_instance = (struct fwu_provider *)context;
252 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
253 uint32_t handle = 0;
254
255 if (serializer)
256 rpc_status = serializer->deserialize_read_stream_req(req_buf, &handle);
257
Imre Kise584a982023-07-04 17:59:18 +0200258 if (rpc_status == RPC_SUCCESS) {
259 struct rpc_buffer *resp_buf = &req->response;
Julian Hall32798ff2022-12-19 13:33:42 +0000260 uint8_t *payload_buf;
261 size_t max_payload;
262 size_t read_len = 0;
263 size_t total_len = 0;
264
265 serializer->read_stream_resp_payload(resp_buf, &payload_buf, &max_payload);
266
Imre Kise584a982023-07-04 17:59:18 +0200267 req->service_status = update_agent_read_stream(this_instance->update_agent, handle,
Gyorgy Szing3c446242023-03-31 01:53:15 +0200268 payload_buf, max_payload, &read_len,
269 &total_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000270
Imre Kise584a982023-07-04 17:59:18 +0200271 if (!req->service_status)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200272 rpc_status = serializer->serialize_read_stream_resp(resp_buf, read_len,
273 total_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000274
Julian Hall32798ff2022-12-19 13:33:42 +0000275 }
276
277 return rpc_status;
278}
279
Imre Kise584a982023-07-04 17:59:18 +0200280static rpc_status_t commit_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000281{
Imre Kise584a982023-07-04 17:59:18 +0200282 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
283 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000284 struct fwu_provider *this_instance = (struct fwu_provider *)context;
285 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
286 uint32_t handle = 0;
287 bool accepted = false;
288 size_t max_atomic_len = 0;
289
290 if (serializer)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200291 rpc_status = serializer->deserialize_commit_req(req_buf, &handle, &accepted,
292 &max_atomic_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000293
Imre Kise584a982023-07-04 17:59:18 +0200294 if (rpc_status == RPC_SUCCESS) {
Imre Kisefadd3a2024-06-28 14:15:57 +0200295 uint32_t progress = 0;
296 uint32_t total_work = 0;
297
Imre Kise584a982023-07-04 17:59:18 +0200298 req->service_status = update_agent_commit(this_instance->update_agent, handle,
Imre Kisefadd3a2024-06-28 14:15:57 +0200299 accepted, 0, &progress, &total_work);
Julian Hall32798ff2022-12-19 13:33:42 +0000300
Imre Kise584a982023-07-04 17:59:18 +0200301 if (!req->service_status) {
302 struct rpc_buffer *resp_buf = &req->response;
Imre Kisefadd3a2024-06-28 14:15:57 +0200303 rpc_status = serializer->serialize_commit_resp(resp_buf, progress, total_work);
Julian Hall32798ff2022-12-19 13:33:42 +0000304 }
Julian Hall32798ff2022-12-19 13:33:42 +0000305 }
306
307 return rpc_status;
308}
309
Imre Kise584a982023-07-04 17:59:18 +0200310static rpc_status_t accept_image_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000311{
Imre Kise584a982023-07-04 17:59:18 +0200312 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
313 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000314 struct fwu_provider *this_instance = (struct fwu_provider *)context;
315 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
316 struct uuid_octets image_type_uuid;
317
318 if (serializer)
319 rpc_status = serializer->deserialize_accept_req(req_buf, &image_type_uuid);
320
Imre Kise584a982023-07-04 17:59:18 +0200321 if (rpc_status == RPC_SUCCESS)
Imre Kisefadd3a2024-06-28 14:15:57 +0200322 req->service_status = update_agent_accept_image(this_instance->update_agent,
323 &image_type_uuid);
Julian Hall32798ff2022-12-19 13:33:42 +0000324
325 return rpc_status;
326}
327
Imre Kise584a982023-07-04 17:59:18 +0200328static rpc_status_t select_previous_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000329{
330 struct fwu_provider *this_instance = (struct fwu_provider *)context;
331
Imre Kise584a982023-07-04 17:59:18 +0200332 req->service_status = update_agent_select_previous(this_instance->update_agent);
Julian Hall32798ff2022-12-19 13:33:42 +0000333
Imre Kise584a982023-07-04 17:59:18 +0200334 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +0000335}