1 /*
2  * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "direct_fwu_client.h"
8 
9 #include <cstring>
10 
11 #include "service/fwu/common/update_agent_interface.h"
12 #include "protocols/service/fwu/fwu_proto.h"
13 
direct_fwu_client(struct update_agent ** update_agent)14 direct_fwu_client::direct_fwu_client(struct update_agent **update_agent)
15 	: fwu_client()
16 	, m_update_agent(update_agent)
17 	, m_read_buf()
18 {
19 	/* The read buffer represents a communication buffer that will
20 	 * constrain the amount of data that may be read in a single read.
21 	 */
22 	memset(m_read_buf, 0, READ_BUF_SIZE);
23 }
24 
~direct_fwu_client()25 direct_fwu_client::~direct_fwu_client()
26 {
27 }
28 
discover(int16_t * service_status,uint8_t * version_major,uint8_t * version_minor,uint16_t * num_func,uint64_t * max_payload_size,uint32_t * flags,uint32_t * vendor_specific_flags,uint8_t * function_presence)29 int direct_fwu_client::discover(int16_t *service_status, uint8_t *version_major,
30 				uint8_t *version_minor, uint16_t *num_func,
31 				uint64_t *max_payload_size, uint32_t *flags,
32 				uint32_t *vendor_specific_flags, uint8_t *function_presence)
33 {
34 	struct fwu_discovery_result discovery_result = { 0 };
35 	int res = 0;
36 
37 	res = update_agent_discover(*m_update_agent, &discovery_result);
38 	if (res)
39 		return res;
40 
41 	*service_status = discovery_result.service_status;
42 	*version_major = discovery_result.version_major;
43 	*version_minor = discovery_result.version_minor;
44 	*max_payload_size = discovery_result.max_payload_size;
45 	*flags = discovery_result.flags;
46 	*vendor_specific_flags = discovery_result.vendor_specific_flags;
47 
48 	*num_func = 0;
49 
50 #define ADD_FUNC_IF_PRESENT(func, id) \
51 do { \
52 	if ((*m_update_agent)->interface->func != NULL) \
53 		function_presence[(*num_func)++] = (id); \
54 } while (0)
55 
56 	ADD_FUNC_IF_PRESENT(discover, FWU_FUNC_ID_DISCOVER);
57 	ADD_FUNC_IF_PRESENT(begin_staging, FWU_FUNC_ID_BEGIN_STAGING);
58 	ADD_FUNC_IF_PRESENT(end_staging, FWU_FUNC_ID_END_STAGING);
59 	ADD_FUNC_IF_PRESENT(cancel_staging, FWU_FUNC_ID_CANCEL_STAGING);
60 	ADD_FUNC_IF_PRESENT(open, FWU_FUNC_ID_OPEN);
61 	ADD_FUNC_IF_PRESENT(write_stream, FWU_FUNC_ID_WRITE_STREAM);
62 	ADD_FUNC_IF_PRESENT(read_stream, FWU_FUNC_ID_READ_STREAM);
63 	ADD_FUNC_IF_PRESENT(commit, FWU_FUNC_ID_COMMIT);
64 	ADD_FUNC_IF_PRESENT(accept_image, FWU_FUNC_ID_ACCEPT_IMAGE);
65 	ADD_FUNC_IF_PRESENT(select_previous, FWU_FUNC_ID_SELECT_PREVIOUS);
66 
67 #undef ADD_FUNC_IF_PRESENT
68 
69 	return res;
70 }
71 
begin_staging(uint32_t vendor_flags,uint32_t partial_update_count,struct uuid_octets update_guid[])72 int direct_fwu_client::begin_staging(uint32_t vendor_flags, uint32_t partial_update_count,
73 				     struct uuid_octets update_guid[])
74 {
75 	return update_agent_begin_staging(*m_update_agent, vendor_flags, partial_update_count,
76 					  update_guid);
77 }
78 
end_staging(void)79 int direct_fwu_client::end_staging(void)
80 {
81 	return update_agent_end_staging(*m_update_agent);
82 }
83 
cancel_staging(void)84 int direct_fwu_client::cancel_staging(void)
85 {
86 	return update_agent_cancel_staging(*m_update_agent);
87 }
88 
accept(const struct uuid_octets * image_type_uuid)89 int direct_fwu_client::accept(const struct uuid_octets *image_type_uuid)
90 {
91 	return update_agent_accept_image(*m_update_agent, image_type_uuid);
92 }
93 
select_previous(void)94 int direct_fwu_client::select_previous(void)
95 {
96 	return update_agent_select_previous(*m_update_agent);
97 }
98 
open(const struct uuid_octets * uuid,op_type op_type,uint32_t * handle)99 int direct_fwu_client::open(const struct uuid_octets *uuid, op_type op_type, uint32_t *handle)
100 {
101 	return update_agent_open(*m_update_agent, uuid, (uint8_t)op_type, handle);
102 }
103 
commit(uint32_t handle,bool accepted)104 int direct_fwu_client::commit(uint32_t handle, bool accepted)
105 {
106 	uint32_t progress = 0;
107 	uint32_t total_work = 0;
108 
109 	return update_agent_commit(*m_update_agent, handle, accepted, 0, &progress, &total_work);
110 }
111 
write_stream(uint32_t handle,const uint8_t * data,size_t data_len)112 int direct_fwu_client::write_stream(uint32_t handle, const uint8_t *data, size_t data_len)
113 {
114 	return update_agent_write_stream(*m_update_agent, handle, data, data_len);
115 }
116 
read_stream(uint32_t handle,uint8_t * buf,size_t buf_size,size_t * read_len,size_t * total_len)117 int direct_fwu_client::read_stream(uint32_t handle, uint8_t *buf, size_t buf_size, size_t *read_len,
118 				   size_t *total_len)
119 {
120 	int status = update_agent_read_stream(*m_update_agent, handle, m_read_buf, READ_BUF_SIZE,
121 					      read_len, total_len);
122 
123 	if (!status && buf && buf_size) {
124 		size_t copy_len = (*read_len <= buf_size) ? *read_len : buf_size;
125 
126 		memcpy(buf, m_read_buf, copy_len);
127 	}
128 
129 	return status;
130 }
131