blob: 33b744f79048334810585fc307fca943eaf6ef1b [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
Julian Hall32798ff2022-12-19 13:33:42 +000018/* Service request handlers */
Imre Kise584a982023-07-04 17:59:18 +020019static rpc_status_t begin_staging_handler(void *context, struct rpc_request *req);
20static rpc_status_t end_staging_handler(void *context, struct rpc_request *req);
21static rpc_status_t cancel_staging_handler(void *context, struct rpc_request *req);
22static rpc_status_t open_handler(void *context, struct rpc_request *req);
23static rpc_status_t write_stream_handler(void *context, struct rpc_request *req);
24static rpc_status_t read_stream_handler(void *context, struct rpc_request *req);
25static rpc_status_t commit_handler(void *context, struct rpc_request *req);
26static rpc_status_t accept_image_handler(void *context, struct rpc_request *req);
27static rpc_status_t select_previous_handler(void *context, struct rpc_request *req);
Julian Hall32798ff2022-12-19 13:33:42 +000028
29/* Handler mapping table for service */
30static const struct service_handler handler_table[] = {
Gyorgy Szing3c446242023-03-31 01:53:15 +020031 { TS_FWU_OPCODE_BEGIN_STAGING, begin_staging_handler },
32 { TS_FWU_OPCODE_END_STAGING, end_staging_handler },
33 { TS_FWU_OPCODE_CANCEL_STAGING, cancel_staging_handler },
34 { TS_FWU_OPCODE_OPEN, open_handler },
35 { TS_FWU_OPCODE_WRITE_STREAM, write_stream_handler },
36 { TS_FWU_OPCODE_READ_STREAM, read_stream_handler },
37 { TS_FWU_OPCODE_COMMIT, commit_handler },
38 { TS_FWU_OPCODE_ACCEPT_IMAGE, accept_image_handler },
39 { TS_FWU_OPCODE_SELECT_PREVIOUS, select_previous_handler }
Julian Hall32798ff2022-12-19 13:33:42 +000040};
41
Imre Kise584a982023-07-04 17:59:18 +020042struct rpc_service_interface *fwu_provider_init(struct fwu_provider *context,
Gyorgy Szing3c446242023-03-31 01:53:15 +020043 struct update_agent *update_agent)
Julian Hall32798ff2022-12-19 13:33:42 +000044{
Imre Kise584a982023-07-04 17:59:18 +020045 const struct rpc_uuid service_uuid = { .uuid = TS_FWU_SERVICE_UUID };
Julian Hall32798ff2022-12-19 13:33:42 +000046 /* Initialise the fwu_provider */
47 context->update_agent = update_agent;
48
49 for (size_t encoding = 0; encoding < TS_RPC_ENCODING_LIMIT; ++encoding)
50 context->serializers[encoding] = NULL;
51
Imre Kise584a982023-07-04 17:59:18 +020052 service_provider_init(&context->base_provider, context, &service_uuid, handler_table,
Gyorgy Szing3c446242023-03-31 01:53:15 +020053 sizeof(handler_table) / sizeof(struct service_handler));
Julian Hall32798ff2022-12-19 13:33:42 +000054
Julian Hall32798ff2022-12-19 13:33:42 +000055 return service_provider_get_rpc_interface(&context->base_provider);
56}
57
Gyorgy Szing3c446242023-03-31 01:53:15 +020058void fwu_provider_deinit(struct fwu_provider *context)
Julian Hall32798ff2022-12-19 13:33:42 +000059{
Imre Kise584a982023-07-04 17:59:18 +020060 (void)context;
Julian Hall32798ff2022-12-19 13:33:42 +000061}
62
Gyorgy Szing3c446242023-03-31 01:53:15 +020063void fwu_provider_register_serializer(struct fwu_provider *context, unsigned int encoding,
64 const struct fwu_provider_serializer *serializer)
Julian Hall32798ff2022-12-19 13:33:42 +000065{
66 if (encoding < TS_RPC_ENCODING_LIMIT) {
Julian Hall32798ff2022-12-19 13:33:42 +000067 context->serializers[encoding] = serializer;
Julian Hall32798ff2022-12-19 13:33:42 +000068 }
69}
70
Gyorgy Szing3c446242023-03-31 01:53:15 +020071static const struct fwu_provider_serializer *get_fwu_serializer(struct fwu_provider *this_instance,
Imre Kise584a982023-07-04 17:59:18 +020072 const struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +000073{
Gyorgy Szing3c446242023-03-31 01:53:15 +020074 const struct fwu_provider_serializer *serializer = NULL;
Imre Kise584a982023-07-04 17:59:18 +020075 unsigned int encoding = 0;
Julian Hall32798ff2022-12-19 13:33:42 +000076
77 if (encoding < TS_RPC_ENCODING_LIMIT)
78 serializer = this_instance->serializers[encoding];
79
80 return serializer;
81}
82
Imre Kise584a982023-07-04 17:59:18 +020083static rpc_status_t begin_staging_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +000084{
85 struct fwu_provider *this_instance = (struct fwu_provider *)context;
86
Imre Kisefadd3a2024-06-28 14:15:57 +020087 req->service_status = update_agent_begin_staging(this_instance->update_agent, 0, 0, NULL);
Julian Hall32798ff2022-12-19 13:33:42 +000088
Imre Kise584a982023-07-04 17:59:18 +020089 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +000090}
91
Imre Kise584a982023-07-04 17:59:18 +020092static rpc_status_t end_staging_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +000093{
94 struct fwu_provider *this_instance = (struct fwu_provider *)context;
95
Imre Kise584a982023-07-04 17:59:18 +020096 req->service_status = update_agent_end_staging(this_instance->update_agent);
Julian Hall32798ff2022-12-19 13:33:42 +000097
Imre Kise584a982023-07-04 17:59:18 +020098 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +000099}
100
Imre Kise584a982023-07-04 17:59:18 +0200101static rpc_status_t cancel_staging_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000102{
103 struct fwu_provider *this_instance = (struct fwu_provider *)context;
104
Imre Kise584a982023-07-04 17:59:18 +0200105 req->service_status = update_agent_cancel_staging(this_instance->update_agent);
Julian Hall32798ff2022-12-19 13:33:42 +0000106
Imre Kise584a982023-07-04 17:59:18 +0200107 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +0000108}
109
Imre Kise584a982023-07-04 17:59:18 +0200110static rpc_status_t open_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000111{
Imre Kise584a982023-07-04 17:59:18 +0200112 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
113 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000114 struct fwu_provider *this_instance = (struct fwu_provider *)context;
115 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
116 struct uuid_octets image_type_uuid;
117
118 if (serializer)
119 rpc_status = serializer->deserialize_open_req(req_buf, &image_type_uuid);
120
Imre Kise584a982023-07-04 17:59:18 +0200121 if (rpc_status == RPC_SUCCESS) {
Julian Hall32798ff2022-12-19 13:33:42 +0000122 uint32_t handle = 0;
Imre Kise584a982023-07-04 17:59:18 +0200123 req->service_status =
Imre Kisefadd3a2024-06-28 14:15:57 +0200124 update_agent_open(this_instance->update_agent, &image_type_uuid, 0,
125 &handle);
Julian Hall32798ff2022-12-19 13:33:42 +0000126
Imre Kise584a982023-07-04 17:59:18 +0200127 if (!req->service_status) {
128 struct rpc_buffer *resp_buf = &req->response;
Julian Hall32798ff2022-12-19 13:33:42 +0000129 rpc_status = serializer->serialize_open_resp(resp_buf, handle);
130 }
Julian Hall32798ff2022-12-19 13:33:42 +0000131 }
132
133 return rpc_status;
134}
135
Imre Kise584a982023-07-04 17:59:18 +0200136static rpc_status_t write_stream_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000137{
Imre Kise584a982023-07-04 17:59:18 +0200138 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
139 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000140 struct fwu_provider *this_instance = (struct fwu_provider *)context;
141 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
142 uint32_t handle = 0;
143 size_t data_len = 0;
144 const uint8_t *data = NULL;
145
146 if (serializer)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200147 rpc_status = serializer->deserialize_write_stream_req(req_buf, &handle, &data_len,
148 &data);
Julian Hall32798ff2022-12-19 13:33:42 +0000149
Imre Kise584a982023-07-04 17:59:18 +0200150 if (rpc_status == RPC_SUCCESS) {
151 req->service_status = update_agent_write_stream(this_instance->update_agent, handle,
152 data, data_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000153 }
154
155 return rpc_status;
156}
157
Imre Kise584a982023-07-04 17:59:18 +0200158static rpc_status_t read_stream_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000159{
Imre Kise584a982023-07-04 17:59:18 +0200160 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
161 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000162 struct fwu_provider *this_instance = (struct fwu_provider *)context;
163 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
164 uint32_t handle = 0;
165
166 if (serializer)
167 rpc_status = serializer->deserialize_read_stream_req(req_buf, &handle);
168
Imre Kise584a982023-07-04 17:59:18 +0200169 if (rpc_status == RPC_SUCCESS) {
170 struct rpc_buffer *resp_buf = &req->response;
Julian Hall32798ff2022-12-19 13:33:42 +0000171 uint8_t *payload_buf;
172 size_t max_payload;
173 size_t read_len = 0;
174 size_t total_len = 0;
175
176 serializer->read_stream_resp_payload(resp_buf, &payload_buf, &max_payload);
177
Imre Kise584a982023-07-04 17:59:18 +0200178 req->service_status = update_agent_read_stream(this_instance->update_agent, handle,
Gyorgy Szing3c446242023-03-31 01:53:15 +0200179 payload_buf, max_payload, &read_len,
180 &total_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000181
Imre Kise584a982023-07-04 17:59:18 +0200182 if (!req->service_status)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200183 rpc_status = serializer->serialize_read_stream_resp(resp_buf, read_len,
184 total_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000185
Julian Hall32798ff2022-12-19 13:33:42 +0000186 }
187
188 return rpc_status;
189}
190
Imre Kise584a982023-07-04 17:59:18 +0200191static rpc_status_t commit_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000192{
Imre Kise584a982023-07-04 17:59:18 +0200193 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
194 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000195 struct fwu_provider *this_instance = (struct fwu_provider *)context;
196 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
197 uint32_t handle = 0;
198 bool accepted = false;
199 size_t max_atomic_len = 0;
200
201 if (serializer)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200202 rpc_status = serializer->deserialize_commit_req(req_buf, &handle, &accepted,
203 &max_atomic_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000204
Imre Kise584a982023-07-04 17:59:18 +0200205 if (rpc_status == RPC_SUCCESS) {
Imre Kisefadd3a2024-06-28 14:15:57 +0200206 uint32_t progress = 0;
207 uint32_t total_work = 0;
208
Imre Kise584a982023-07-04 17:59:18 +0200209 req->service_status = update_agent_commit(this_instance->update_agent, handle,
Imre Kisefadd3a2024-06-28 14:15:57 +0200210 accepted, 0, &progress, &total_work);
Julian Hall32798ff2022-12-19 13:33:42 +0000211
Imre Kise584a982023-07-04 17:59:18 +0200212 if (!req->service_status) {
213 struct rpc_buffer *resp_buf = &req->response;
Imre Kisefadd3a2024-06-28 14:15:57 +0200214 rpc_status = serializer->serialize_commit_resp(resp_buf, progress, total_work);
Julian Hall32798ff2022-12-19 13:33:42 +0000215 }
Julian Hall32798ff2022-12-19 13:33:42 +0000216 }
217
218 return rpc_status;
219}
220
Imre Kise584a982023-07-04 17:59:18 +0200221static rpc_status_t accept_image_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000222{
Imre Kise584a982023-07-04 17:59:18 +0200223 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
224 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000225 struct fwu_provider *this_instance = (struct fwu_provider *)context;
226 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
227 struct uuid_octets image_type_uuid;
228
229 if (serializer)
230 rpc_status = serializer->deserialize_accept_req(req_buf, &image_type_uuid);
231
Imre Kise584a982023-07-04 17:59:18 +0200232 if (rpc_status == RPC_SUCCESS)
Imre Kisefadd3a2024-06-28 14:15:57 +0200233 req->service_status = update_agent_accept_image(this_instance->update_agent,
234 &image_type_uuid);
Julian Hall32798ff2022-12-19 13:33:42 +0000235
236 return rpc_status;
237}
238
Imre Kise584a982023-07-04 17:59:18 +0200239static rpc_status_t select_previous_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000240{
241 struct fwu_provider *this_instance = (struct fwu_provider *)context;
242
Imre Kise584a982023-07-04 17:59:18 +0200243 req->service_status = update_agent_select_previous(this_instance->update_agent);
Julian Hall32798ff2022-12-19 13:33:42 +0000244
Imre Kise584a982023-07-04 17:59:18 +0200245 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +0000246}