blob: e94f653799cd799f47b2c42d0ebda252f8ce00a8 [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"
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 Kise584a982023-07-04 17:59:18 +020087 req->service_status = update_agent_begin_staging(this_instance->update_agent);
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 =
Gyorgy Szing3c446242023-03-31 01:53:15 +0200124 update_agent_open(this_instance->update_agent, &image_type_uuid, &handle);
Julian Hall32798ff2022-12-19 13:33:42 +0000125
Imre Kise584a982023-07-04 17:59:18 +0200126 if (!req->service_status) {
127 struct rpc_buffer *resp_buf = &req->response;
Julian Hall32798ff2022-12-19 13:33:42 +0000128 rpc_status = serializer->serialize_open_resp(resp_buf, handle);
129 }
Julian Hall32798ff2022-12-19 13:33:42 +0000130 }
131
132 return rpc_status;
133}
134
Imre Kise584a982023-07-04 17:59:18 +0200135static rpc_status_t write_stream_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000136{
Imre Kise584a982023-07-04 17:59:18 +0200137 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
138 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000139 struct fwu_provider *this_instance = (struct fwu_provider *)context;
140 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
141 uint32_t handle = 0;
142 size_t data_len = 0;
143 const uint8_t *data = NULL;
144
145 if (serializer)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200146 rpc_status = serializer->deserialize_write_stream_req(req_buf, &handle, &data_len,
147 &data);
Julian Hall32798ff2022-12-19 13:33:42 +0000148
Imre Kise584a982023-07-04 17:59:18 +0200149 if (rpc_status == RPC_SUCCESS) {
150 req->service_status = update_agent_write_stream(this_instance->update_agent, handle,
151 data, data_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000152 }
153
154 return rpc_status;
155}
156
Imre Kise584a982023-07-04 17:59:18 +0200157static rpc_status_t read_stream_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000158{
Imre Kise584a982023-07-04 17:59:18 +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;
162 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
163 uint32_t handle = 0;
164
165 if (serializer)
166 rpc_status = serializer->deserialize_read_stream_req(req_buf, &handle);
167
Imre Kise584a982023-07-04 17:59:18 +0200168 if (rpc_status == RPC_SUCCESS) {
169 struct rpc_buffer *resp_buf = &req->response;
Julian Hall32798ff2022-12-19 13:33:42 +0000170 uint8_t *payload_buf;
171 size_t max_payload;
172 size_t read_len = 0;
173 size_t total_len = 0;
174
175 serializer->read_stream_resp_payload(resp_buf, &payload_buf, &max_payload);
176
Imre Kise584a982023-07-04 17:59:18 +0200177 req->service_status = update_agent_read_stream(this_instance->update_agent, handle,
Gyorgy Szing3c446242023-03-31 01:53:15 +0200178 payload_buf, max_payload, &read_len,
179 &total_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000180
Imre Kise584a982023-07-04 17:59:18 +0200181 if (!req->service_status)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200182 rpc_status = serializer->serialize_read_stream_resp(resp_buf, read_len,
183 total_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000184
Julian Hall32798ff2022-12-19 13:33:42 +0000185 }
186
187 return rpc_status;
188}
189
Imre Kise584a982023-07-04 17:59:18 +0200190static rpc_status_t commit_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000191{
Imre Kise584a982023-07-04 17:59:18 +0200192 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
193 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000194 struct fwu_provider *this_instance = (struct fwu_provider *)context;
195 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
196 uint32_t handle = 0;
197 bool accepted = false;
198 size_t max_atomic_len = 0;
199
200 if (serializer)
Gyorgy Szing3c446242023-03-31 01:53:15 +0200201 rpc_status = serializer->deserialize_commit_req(req_buf, &handle, &accepted,
202 &max_atomic_len);
Julian Hall32798ff2022-12-19 13:33:42 +0000203
Imre Kise584a982023-07-04 17:59:18 +0200204 if (rpc_status == RPC_SUCCESS) {
205 req->service_status = update_agent_commit(this_instance->update_agent, handle,
206 accepted);
Julian Hall32798ff2022-12-19 13:33:42 +0000207
Imre Kise584a982023-07-04 17:59:18 +0200208 if (!req->service_status) {
209 struct rpc_buffer *resp_buf = &req->response;
Julian Hall32798ff2022-12-19 13:33:42 +0000210 rpc_status = serializer->serialize_commit_resp(resp_buf, 0, 0);
211 }
Julian Hall32798ff2022-12-19 13:33:42 +0000212 }
213
214 return rpc_status;
215}
216
Imre Kise584a982023-07-04 17:59:18 +0200217static rpc_status_t accept_image_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000218{
Imre Kise584a982023-07-04 17:59:18 +0200219 rpc_status_t rpc_status = RPC_ERROR_INTERNAL;
220 struct rpc_buffer *req_buf = &req->request;
Julian Hall32798ff2022-12-19 13:33:42 +0000221 struct fwu_provider *this_instance = (struct fwu_provider *)context;
222 const struct fwu_provider_serializer *serializer = get_fwu_serializer(this_instance, req);
223 struct uuid_octets image_type_uuid;
224
225 if (serializer)
226 rpc_status = serializer->deserialize_accept_req(req_buf, &image_type_uuid);
227
Imre Kise584a982023-07-04 17:59:18 +0200228 if (rpc_status == RPC_SUCCESS)
229 req->service_status = update_agent_accept(this_instance->update_agent,
230 &image_type_uuid);
Julian Hall32798ff2022-12-19 13:33:42 +0000231
232 return rpc_status;
233}
234
Imre Kise584a982023-07-04 17:59:18 +0200235static rpc_status_t select_previous_handler(void *context, struct rpc_request *req)
Julian Hall32798ff2022-12-19 13:33:42 +0000236{
237 struct fwu_provider *this_instance = (struct fwu_provider *)context;
238
Imre Kise584a982023-07-04 17:59:18 +0200239 req->service_status = update_agent_select_previous(this_instance->update_agent);
Julian Hall32798ff2022-12-19 13:33:42 +0000240
Imre Kise584a982023-07-04 17:59:18 +0200241 return RPC_SUCCESS;
Julian Hall32798ff2022-12-19 13:33:42 +0000242}