blob: 51b712dcdb5c2eff3654bb13639efa50799fcb7e [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"
Imre Kis7554c472024-07-04 10:09:31 +020013#include "protocols/service/fwu/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
Imre Kise584a982023-07-04 17:59:18 +020057 service_provider_init(&context->base_provider, context, &service_uuid, handler_table,
Gyorgy Szing3c446242023-03-31 01:53:15 +020058 sizeof(handler_table) / sizeof(struct service_handler));
Julian Hall32798ff2022-12-19 13:33:42 +000059
Imre Kis6fd73d82024-07-04 13:36:10 +020060 rpc_interface = service_provider_get_rpc_interface(&context->base_provider);
61 if (!rpc_interface)
62 return NULL;
63
64 return fwu_provider_shim_init(&context->shim, rpc_interface);
Julian Hall32798ff2022-12-19 13:33:42 +000065}
66
Gyorgy Szing3c446242023-03-31 01:53:15 +020067void fwu_provider_deinit(struct fwu_provider *context)
Julian Hall32798ff2022-12-19 13:33:42 +000068{
Imre Kise584a982023-07-04 17:59:18 +020069 (void)context;
Julian Hall32798ff2022-12-19 13:33:42 +000070}
71
Imre Kis18b387d2024-07-02 13:51:07 +020072static uint16_t generate_function_presence(const struct update_agent *agent,
73 uint8_t function_presence[FWU_FUNC_ID_COUNT])
74{
75 uint16_t num_func = 0;
76
77#define ADD_FUNC_IF_PRESENT(func, id) \
78do { \
79 if (agent->interface->func != NULL) \
80 function_presence[num_func++] = (id); \
81} while (0)
82
83 ADD_FUNC_IF_PRESENT(discover, FWU_FUNC_ID_DISCOVER);
84 ADD_FUNC_IF_PRESENT(begin_staging, FWU_FUNC_ID_BEGIN_STAGING);
85 ADD_FUNC_IF_PRESENT(end_staging, FWU_FUNC_ID_END_STAGING);
86 ADD_FUNC_IF_PRESENT(cancel_staging, FWU_FUNC_ID_CANCEL_STAGING);
87 ADD_FUNC_IF_PRESENT(open, FWU_FUNC_ID_OPEN);
88 ADD_FUNC_IF_PRESENT(write_stream, FWU_FUNC_ID_WRITE_STREAM);
89 ADD_FUNC_IF_PRESENT(read_stream, FWU_FUNC_ID_READ_STREAM);
90 ADD_FUNC_IF_PRESENT(commit, FWU_FUNC_ID_COMMIT);
91 ADD_FUNC_IF_PRESENT(accept_image, FWU_FUNC_ID_ACCEPT_IMAGE);
92 ADD_FUNC_IF_PRESENT(select_previous, FWU_FUNC_ID_SELECT_PREVIOUS);
93
94#undef ADD_FUNC_IF_PRESENT
95
96 return num_func;
97}
98
99static rpc_status_t discover_handler(void *context, struct rpc_request *req)
100{
101 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
102 struct fwu_provider *this_instance = (struct fwu_provider *)context;
Imre Kis18b387d2024-07-02 13:51:07 +0200103 struct fwu_discovery_result discovery_result = { 0 };
104 struct rpc_buffer *resp_buf = &req->response;
105
Imre Kis18b387d2024-07-02 13:51:07 +0200106 req->service_status = update_agent_discover(this_instance->update_agent, &discovery_result);
107
108 if (!req->service_status) {
109 uint16_t num_func = 0;
110 uint8_t function_presence[FWU_FUNC_ID_COUNT] = { 0 };
111
112 num_func = generate_function_presence(this_instance->update_agent,
113 function_presence);
114
Imre Kis86b1d672024-07-15 13:15:58 +0200115 rpc_status = fwu_serialize_discover_resp(
Imre Kis18b387d2024-07-02 13:51:07 +0200116 resp_buf, discovery_result.service_status, discovery_result.version_major,
117 discovery_result.version_minor, num_func, discovery_result.max_payload_size,
118 discovery_result.flags, discovery_result.vendor_specific_flags,
119 function_presence);
120 } else {
121 /*
122 * The actual service call failed, but the request was successful on the RPC level
123 */
124 rpc_status = RPC_SUCCESS;
125 }
126
127 return rpc_status;
128}
129
Imre Kise584a982023-07-04 17:59:18 +0200130static rpc_status_t begin_staging_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000131{
Imre Kis18b387d2024-07-02 13:51:07 +0200132 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
133 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000134 struct fwu_provider *this_instance = (struct fwu_provider *)context;
Imre Kis18b387d2024-07-02 13:51:07 +0200135 uint32_t vendor_flags = 0;
136 uint32_t partial_update_count = 0;
137 struct uuid_octets update_guid[FWU_PROVIDER_MAX_PARTIAL_UPDATE_COUNT];
Julian Hall32798ff2022-12-19 13:33:42 +0000138
Imre Kis86b1d672024-07-15 13:15:58 +0200139 rpc_status = fwu_deserialize_begin_staging_req(
140 req_buf, &vendor_flags, &partial_update_count,
141 FWU_PROVIDER_MAX_PARTIAL_UPDATE_COUNT, update_guid);
Julian Hall32798ff2022-12-19 13:33:42 +0000142
Imre Kis18b387d2024-07-02 13:51:07 +0200143 if (rpc_status == RPC_SUCCESS)
144 req->service_status = update_agent_begin_staging(
145 this_instance->update_agent, vendor_flags, partial_update_count,
146 update_guid);
147
148 return rpc_status;
Julian Hall32798ff2022-12-19 13:33:42 +0000149}
150
Imre Kise584a982023-07-04 17:59:18 +0200151static rpc_status_t end_staging_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000152{
153 struct fwu_provider *this_instance = (struct fwu_provider *)context;
154
Imre Kise584a982023-07-04 17:59:18 +0200155 req->service_status = update_agent_end_staging(this_instance->update_agent);
Julian Hall32798ff2022-12-19 13:33:42 +0000156
Imre Kise584a982023-07-04 17:59:18 +0200157 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +0000158}
159
Imre Kise584a982023-07-04 17:59:18 +0200160static rpc_status_t cancel_staging_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000161{
162 struct fwu_provider *this_instance = (struct fwu_provider *)context;
163
Imre Kise584a982023-07-04 17:59:18 +0200164 req->service_status = update_agent_cancel_staging(this_instance->update_agent);
Julian Hall32798ff2022-12-19 13:33:42 +0000165
Imre Kise584a982023-07-04 17:59:18 +0200166 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +0000167}
168
Imre Kise584a982023-07-04 17:59:18 +0200169static rpc_status_t open_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000170{
Imre Kise584a982023-07-04 17:59:18 +0200171 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
172 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000173 struct fwu_provider *this_instance = (struct fwu_provider *)context;
Imre Kis18b387d2024-07-02 13:51:07 +0200174 struct uuid_octets image_type_uuid = { 0 };
175 uint8_t op_type = 0;
Julian Hall32798ff2022-12-19 13:33:42 +0000176
Imre Kis86b1d672024-07-15 13:15:58 +0200177 rpc_status = fwu_deserialize_open_req(req_buf, &image_type_uuid, &op_type);
Julian Hall32798ff2022-12-19 13:33:42 +0000178
Imre Kise584a982023-07-04 17:59:18 +0200179 if (rpc_status == RPC_SUCCESS) {
Julian Hall32798ff2022-12-19 13:33:42 +0000180 uint32_t handle = 0;
Imre Kise584a982023-07-04 17:59:18 +0200181 req->service_status =
Imre Kis18b387d2024-07-02 13:51:07 +0200182 update_agent_open(this_instance->update_agent, &image_type_uuid, op_type,
Imre Kisefadd3a2024-06-28 14:15:57 +0200183 &handle);
Julian Hall32798ff2022-12-19 13:33:42 +0000184
Imre Kise584a982023-07-04 17:59:18 +0200185 if (!req->service_status) {
186 struct rpc_buffer *resp_buf = &req->response;
Imre Kis86b1d672024-07-15 13:15:58 +0200187 rpc_status = fwu_serialize_open_resp(resp_buf, handle);
Julian Hall32798ff2022-12-19 13:33:42 +0000188 }
Julian Hall32798ff2022-12-19 13:33:42 +0000189 }
190
191 return rpc_status;
192}
193
Imre Kise584a982023-07-04 17:59:18 +0200194static rpc_status_t write_stream_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000195{
Imre Kise584a982023-07-04 17:59:18 +0200196 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
197 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000198 struct fwu_provider *this_instance = (struct fwu_provider *)context;
Julian Hall32798ff2022-12-19 13:33:42 +0000199 uint32_t handle = 0;
200 size_t data_len = 0;
201 const uint8_t *data = NULL;
202
Imre Kis86b1d672024-07-15 13:15:58 +0200203 rpc_status = fwu_deserialize_write_stream_req(req_buf, &handle, &data_len, &data);
Julian Hall32798ff2022-12-19 13:33:42 +0000204
Imre Kise584a982023-07-04 17:59:18 +0200205 if (rpc_status == RPC_SUCCESS) {
206 req->service_status = update_agent_write_stream(this_instance->update_agent, handle,
207 data, data_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000208 }
209
210 return rpc_status;
211}
212
Imre Kise584a982023-07-04 17:59:18 +0200213static rpc_status_t read_stream_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000214{
Imre Kise584a982023-07-04 17:59:18 +0200215 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
216 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000217 struct fwu_provider *this_instance = (struct fwu_provider *)context;
Julian Hall32798ff2022-12-19 13:33:42 +0000218 uint32_t handle = 0;
219
Imre Kis86b1d672024-07-15 13:15:58 +0200220 rpc_status = fwu_deserialize_read_stream_req(req_buf, &handle);
Julian Hall32798ff2022-12-19 13:33:42 +0000221
Imre Kise584a982023-07-04 17:59:18 +0200222 if (rpc_status == RPC_SUCCESS) {
223 struct rpc_buffer *resp_buf = &req->response;
Julian Hall32798ff2022-12-19 13:33:42 +0000224 uint8_t *payload_buf;
225 size_t max_payload;
226 size_t read_len = 0;
227 size_t total_len = 0;
228
Imre Kis86b1d672024-07-15 13:15:58 +0200229 fwu_read_stream_resp_payload(resp_buf, &payload_buf, &max_payload);
Julian Hall32798ff2022-12-19 13:33:42 +0000230
Imre Kise584a982023-07-04 17:59:18 +0200231 req->service_status = update_agent_read_stream(this_instance->update_agent, handle,
Gyorgy Szing3c446242023-03-31 01:53:15 +0200232 payload_buf, max_payload, &read_len,
233 &total_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000234
Imre Kise584a982023-07-04 17:59:18 +0200235 if (!req->service_status)
Imre Kis86b1d672024-07-15 13:15:58 +0200236 rpc_status = fwu_serialize_read_stream_resp(resp_buf, read_len, total_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000237
Julian Hall32798ff2022-12-19 13:33:42 +0000238 }
239
240 return rpc_status;
241}
242
Imre Kise584a982023-07-04 17:59:18 +0200243static rpc_status_t commit_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000244{
Imre Kise584a982023-07-04 17:59:18 +0200245 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
246 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000247 struct fwu_provider *this_instance = (struct fwu_provider *)context;
Julian Hall32798ff2022-12-19 13:33:42 +0000248 uint32_t handle = 0;
249 bool accepted = false;
250 size_t max_atomic_len = 0;
251
Imre Kis86b1d672024-07-15 13:15:58 +0200252 rpc_status = fwu_deserialize_commit_req(req_buf, &handle, &accepted, &max_atomic_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000253
Imre Kise584a982023-07-04 17:59:18 +0200254 if (rpc_status == RPC_SUCCESS) {
Imre Kisefadd3a2024-06-28 14:15:57 +0200255 uint32_t progress = 0;
256 uint32_t total_work = 0;
257
Imre Kise584a982023-07-04 17:59:18 +0200258 req->service_status = update_agent_commit(this_instance->update_agent, handle,
Imre Kisefadd3a2024-06-28 14:15:57 +0200259 accepted, 0, &progress, &total_work);
Julian Hall32798ff2022-12-19 13:33:42 +0000260
Imre Kise584a982023-07-04 17:59:18 +0200261 if (!req->service_status) {
262 struct rpc_buffer *resp_buf = &req->response;
Imre Kis86b1d672024-07-15 13:15:58 +0200263 rpc_status = fwu_serialize_commit_resp(resp_buf, progress, total_work);
Julian Hall32798ff2022-12-19 13:33:42 +0000264 }
Julian Hall32798ff2022-12-19 13:33:42 +0000265 }
266
267 return rpc_status;
268}
269
Imre Kise584a982023-07-04 17:59:18 +0200270static rpc_status_t accept_image_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000271{
Imre Kise584a982023-07-04 17:59:18 +0200272 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
273 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000274 struct fwu_provider *this_instance = (struct fwu_provider *)context;
Julian Hall32798ff2022-12-19 13:33:42 +0000275 struct uuid_octets image_type_uuid;
276
Imre Kis86b1d672024-07-15 13:15:58 +0200277 rpc_status = fwu_deserialize_accept_req(req_buf, &image_type_uuid);
Julian Hall32798ff2022-12-19 13:33:42 +0000278
Imre Kise584a982023-07-04 17:59:18 +0200279 if (rpc_status == RPC_SUCCESS)
Imre Kisefadd3a2024-06-28 14:15:57 +0200280 req->service_status = update_agent_accept_image(this_instance->update_agent,
281 &image_type_uuid);
Julian Hall32798ff2022-12-19 13:33:42 +0000282
283 return rpc_status;
284}
285
Imre Kise584a982023-07-04 17:59:18 +0200286static rpc_status_t select_previous_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000287{
288 struct fwu_provider *this_instance = (struct fwu_provider *)context;
289
Imre Kise584a982023-07-04 17:59:18 +0200290 req->service_status = update_agent_select_previous(this_instance->update_agent);
Julian Hall32798ff2022-12-19 13:33:42 +0000291
Imre Kise584a982023-07-04 17:59:18 +0200292 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +0000293}