blob: 70059d004261051c86631a4da999cc1caf3864cf [file] [log] [blame]
Julian Hall65bb4102023-01-19 12:09:02 +00001/*
2 * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <cassert>
8#include <cstddef>
9#include <cstring>
10#include <errno.h>
11#include <media/volume/factory/volume_factory.h>
12#include <service/block_storage/factory/file/block_store_factory.h>
13#include <service/fwu/installer/factory/installer_factory.h>
14#include <service/fwu/fw_store/banked/bank_scheme.h>
15#include <service/fwu/fw_store/banked/metadata_serializer/v1/metadata_serializer_v1.h>
16#include <service/fwu/fw_store/banked/metadata_serializer/v2/metadata_serializer_v2.h>
17#include <service/fwu/inspector/direct/direct_fw_inspector.h>
18#include <service/fwu/agent/update_agent.h>
19#include <service/fwu/fw_store/banked/banked_fw_store.h>
20#include <service/fwu/config/fwu_configure.h>
21#include "metadata_reader.h"
22#include "fwu_app.h"
23
24extern "C" {
25#include <trace.h>
26}
27
28fwu_app::fwu_app() :
29 m_update_agent(),
30 m_fw_store()
31{
32 memset(&m_update_agent, 0, sizeof(m_update_agent));
33 memset(&m_fw_store, 0, sizeof(m_fw_store));
34}
35
36fwu_app::~fwu_app()
37{
38 update_agent_deinit(&m_update_agent);
39 banked_fw_store_deinit(&m_fw_store);
40
41 fwu_deconfigure();
42 volume_factory_deinit();
43}
44
45int fwu_app::configure(
46 const char *disk_img_filename)
47{
48 if (disk_img_filename)
49 file_block_store_factory_set_filename(disk_img_filename);
50
51 struct uuid_octets device_uuids[MAX_STORAGE_DEVICES];
52 size_t num_storage_devices = 0;
53
54 int status = volume_factory_init(device_uuids,
55 MAX_STORAGE_DEVICES, &num_storage_devices);
56
57 if (status) {
58
59 EMSG("Failed to init volume factory: %d", status);
60 return -EIO;
61 }
62
63 status = fwu_configure(device_uuids, num_storage_devices);
64
65 if (status) {
66
67 EMSG("Failed to setup FWU configuration: %d", status);
68 return -EIO;
69 }
70
71 return 0;
72}
73
74int fwu_app::get_boot_info(
75 unsigned int &active_index,
76 unsigned int &metadata_version)
77{
78 return metadata_reader::instance()->get_boot_info(active_index, metadata_version);
79}
80
81int fwu_app::init_update_agent(
82 unsigned int boot_index,
83 unsigned int metadata_version)
84{
85 if (boot_index >= BANK_SCHEME_NUM_BANKS) {
86
87 IMSG("Invalid boot index");
88 return -1;
89 }
90
91 const struct metadata_serializer *serializer =
92 select_metadata_serializer(metadata_version);
93
94 if (!serializer) {
95
96 IMSG("Unsupported FWU metadata version");
97 return -1;
98 }
99
100 /* Initialise update_agent */
101 int status = banked_fw_store_init(&m_fw_store, serializer);
102
103 if (status) {
104
105 IMSG("fw store initialisation error %d", status);
106 return -1;
107 }
108
109 status = update_agent_init(&m_update_agent, boot_index,
110 direct_fw_inspector_inspect, &m_fw_store);
111
112 if (status) {
113
114 IMSG("update agent initialisation error %d", status);
115 return -1;
116 }
117
118 /* Success */
119 return 0;
120}
121
122int fwu_app::update_image(
123 const struct uuid_octets &img_type_uuid,
124 const uint8_t *img_data,
125 size_t img_size)
126{
127 int status = update_agent_begin_staging(&m_update_agent);
128
129 if (status)
130 return status;
131
132 uint32_t stream_handle = 0;
133
134 status = update_agent_open(&m_update_agent,
135 &img_type_uuid, &stream_handle);
136
137 if (!status) {
138
139 status = update_agent_write_stream(&m_update_agent,
140 stream_handle, img_data, img_size);
141
142 if (!status)
143 status = update_agent_commit(&m_update_agent,
144 stream_handle, false);
145 }
146
147 if (!status)
148 status = update_agent_end_staging(&m_update_agent);
149 else
150 update_agent_cancel_staging(&m_update_agent);
151
152 return status;
153}
154
155int fwu_app::read_object(
156 const struct uuid_octets &object_uuid,
157 std::vector<uint8_t> &data)
158{
159 uint32_t stream_handle = 0;
160 int status = update_agent_open(&m_update_agent, &object_uuid, &stream_handle);
161
162 if (status)
163 return status;
164
165 /* Don't yet know how big the object will be so allocate some space to get
166 * started with the initial read.
167 */
168 size_t reported_total_len = 0;
169 size_t read_so_far = 0;
170 size_t vector_capacity = 512;
171
172 data.resize(vector_capacity);
173
174 do {
175
176 size_t data_len_read = 0;
177 size_t requested_read_len = vector_capacity - read_so_far;
178
179 status = update_agent_read_stream(
180 &m_update_agent,
181 stream_handle,
182 &data[read_so_far],
183 requested_read_len,
184 &data_len_read,
185 &reported_total_len);
186
187 read_so_far += data_len_read;
188 data.resize(read_so_far);
189
190 if (reported_total_len > vector_capacity) {
191
192 vector_capacity = reported_total_len;
193 data.resize(vector_capacity);
194 }
195
196 assert(read_so_far <= reported_total_len);
197
198 if (read_so_far == reported_total_len) {
199
200 /* Read all the data */
201 if (vector_capacity > reported_total_len)
202 data.resize(reported_total_len);
203
204 break;
205 }
206
207 } while (!status);
208
209 status = update_agent_commit(&m_update_agent, stream_handle, false);
210
211 return status;
212}
213
214struct update_agent *fwu_app::update_agent()
215{
216 return &m_update_agent;
217}
218
219const struct metadata_serializer *fwu_app::select_metadata_serializer(
220 unsigned int version)
221{
222 if (version == 1)
223 return metadata_serializer_v1();
224
225 if (version == 2)
226 return metadata_serializer_v2();
227
228 return NULL;
229}