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