blob: 9fa0c50fd4b2e14f2faba2b0f3a57a520e2e3cec [file] [log] [blame]
Yann Gautiereb16b472018-10-15 09:36:32 +02001/*
Nicolas Le Bayonf3bc8a02019-11-18 17:15:22 +01002 * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved.
Yann Gautiereb16b472018-10-15 09:36:32 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
Yann Gautiereb16b472018-10-15 09:36:32 +02008#include <errno.h>
Yann Gautiereb16b472018-10-15 09:36:32 +02009#include <stdint.h>
10#include <string.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011
12#include <platform_def.h>
13
14#include <common/debug.h>
15#include <drivers/io/io_driver.h>
16#include <drivers/io/io_storage.h>
17#include <drivers/st/io_stm32image.h>
18#include <lib/utils.h>
19#include <plat/common/platform.h>
20
Yann Gautiereb16b472018-10-15 09:36:32 +020021static uintptr_t backend_dev_handle;
22static uintptr_t backend_image_spec;
23static uint32_t *stm32_img;
24static uint8_t first_lba_buffer[MAX_LBA_SIZE] __aligned(4);
25static struct stm32image_part_info *current_part;
26
27/* STM32 Image driver functions */
28static int stm32image_dev_open(const uintptr_t init_params,
29 io_dev_info_t **dev_info);
30static int stm32image_partition_open(io_dev_info_t *dev_info,
31 const uintptr_t spec, io_entity_t *entity);
32static int stm32image_partition_size(io_entity_t *entity, size_t *length);
33static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
34 size_t length, size_t *length_read);
35static int stm32image_partition_close(io_entity_t *entity);
36static int stm32image_dev_init(io_dev_info_t *dev_info,
37 const uintptr_t init_params);
38static int stm32image_dev_close(io_dev_info_t *dev_info);
39
40/* Identify the device type as a virtual driver */
41static io_type_t device_type_stm32image(void)
42{
43 return IO_TYPE_STM32IMAGE;
44}
45
46static const io_dev_connector_t stm32image_dev_connector = {
47 .dev_open = stm32image_dev_open
48};
49
50static const io_dev_funcs_t stm32image_dev_funcs = {
51 .type = device_type_stm32image,
52 .open = stm32image_partition_open,
53 .size = stm32image_partition_size,
54 .read = stm32image_partition_read,
55 .close = stm32image_partition_close,
56 .dev_init = stm32image_dev_init,
57 .dev_close = stm32image_dev_close,
58};
59
60static io_dev_info_t stm32image_dev_info = {
61 .funcs = &stm32image_dev_funcs,
62 .info = (uintptr_t)0,
63};
64
65static struct stm32image_device_info stm32image_dev;
66
67static int get_part_idx_by_binary_type(uint32_t binary_type)
68{
69 int i;
70
71 for (i = 0; i < STM32_PART_NUM; i++) {
72 if (stm32image_dev.part_info[i].binary_type == binary_type) {
73 return i;
74 }
75 }
76
77 return -EINVAL;
78}
79
80/* Open a connection to the STM32IMAGE device */
81static int stm32image_dev_open(const uintptr_t init_params,
82 io_dev_info_t **dev_info)
83{
84 int i;
85 struct stm32image_device_info *device_info =
86 (struct stm32image_device_info *)init_params;
87
88 assert(dev_info != NULL);
89 *dev_info = (io_dev_info_t *)&stm32image_dev_info;
90
91 stm32image_dev.device_size = device_info->device_size;
92 stm32image_dev.lba_size = device_info->lba_size;
93
94 for (i = 0; i < STM32_PART_NUM; i++) {
95 memcpy(stm32image_dev.part_info[i].name,
96 device_info->part_info[i].name, MAX_PART_NAME_SIZE);
Yann Gautier1a3fc9f2019-01-17 14:35:22 +010097 stm32image_dev.part_info[i].binary_type =
98 device_info->part_info[i].binary_type;
Yann Gautiereb16b472018-10-15 09:36:32 +020099 stm32image_dev.part_info[i].part_offset =
100 device_info->part_info[i].part_offset;
101 stm32image_dev.part_info[i].bkp_offset =
102 device_info->part_info[i].bkp_offset;
103 }
104
105 return 0;
106}
107
108/* Do some basic package checks */
109static int stm32image_dev_init(io_dev_info_t *dev_info,
110 const uintptr_t init_params)
111{
112 int result;
113
114 if ((backend_dev_handle != 0U) || (backend_image_spec != 0U)) {
115 ERROR("STM32 Image io supports only one session\n");
116 return -ENOMEM;
117 }
118
119 /* Obtain a reference to the image by querying the platform layer */
120 result = plat_get_image_source(STM32_IMAGE_ID, &backend_dev_handle,
121 &backend_image_spec);
122 if (result != 0) {
123 ERROR("STM32 image error (%i)\n", result);
124 return -EINVAL;
125 }
126
127 return result;
128}
129
130/* Close a connection to the STM32 Image device */
131static int stm32image_dev_close(io_dev_info_t *dev_info)
132{
133 backend_dev_handle = 0U;
134 backend_image_spec = 0U;
135 stm32_img = NULL;
136
137 return 0;
138}
139
140/* Open a partition */
141static int stm32image_partition_open(io_dev_info_t *dev_info,
142 const uintptr_t spec, io_entity_t *entity)
143{
144 const struct stm32image_part_info *partition_spec;
145 int idx;
146
147 assert(entity != NULL);
148
149 partition_spec = (struct stm32image_part_info *)spec;
150 assert(partition_spec != NULL);
151
152 idx = get_part_idx_by_binary_type(partition_spec->binary_type);
153 if ((idx < 0) || (idx > STM32_PART_NUM)) {
154 ERROR("Wrong partition index (%d)\n", idx);
155 return -EINVAL;
156 }
157
158 current_part = &stm32image_dev.part_info[idx];
159 stm32_img = (uint32_t *)&current_part->part_offset;
160
161 return 0;
162}
163
164/* Return the size of a partition */
165static int stm32image_partition_size(io_entity_t *entity, size_t *length)
166{
167 int result;
168 uintptr_t backend_handle;
169 size_t bytes_read;
170 boot_api_image_header_t *header =
171 (boot_api_image_header_t *)first_lba_buffer;
172
173 assert(entity != NULL);
174 assert(length != NULL);
175
176 /* Attempt to access the image */
177 result = io_open(backend_dev_handle, backend_image_spec,
178 &backend_handle);
179
180 if (result < 0) {
181 ERROR("%s: io_open (%i)\n", __func__, result);
182 return result;
183 }
184
185 /* Reset magic header value */
186 header->magic = 0;
187
188 while (header->magic == 0U) {
189 result = io_seek(backend_handle, IO_SEEK_SET, *stm32_img);
190 if (result != 0) {
191 ERROR("%s: io_seek (%i)\n", __func__, result);
192 break;
193 }
194
195 result = io_read(backend_handle, (uintptr_t)header,
196 MAX_LBA_SIZE, (size_t *)&bytes_read);
197 if (result != 0) {
Yann Gautier1a3fc9f2019-01-17 14:35:22 +0100198 if (current_part->bkp_offset == 0U) {
199 ERROR("%s: io_read (%i)\n", __func__, result);
200 }
201 header->magic = 0;
Yann Gautiereb16b472018-10-15 09:36:32 +0200202 }
203
204 if ((header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) ||
205 (header->binary_type != current_part->binary_type) ||
206 (header->image_length >= stm32image_dev.device_size)) {
Yann Gautier1a3fc9f2019-01-17 14:35:22 +0100207 VERBOSE("%s: partition %s not found at %x\n",
208 __func__, current_part->name, *stm32_img);
209
210 if (current_part->bkp_offset == 0U) {
211 result = -ENOMEM;
212 break;
213 }
Yann Gautiereb16b472018-10-15 09:36:32 +0200214
215 /* Header not correct, check next offset for backup */
216 *stm32_img += current_part->bkp_offset;
217 if (*stm32_img > stm32image_dev.device_size) {
218 /* No backup found, end of device reached */
Yann Gautier1a3fc9f2019-01-17 14:35:22 +0100219 WARN("%s : partition %s not found\n",
220 __func__, current_part->name);
Yann Gautiereb16b472018-10-15 09:36:32 +0200221 result = -ENOMEM;
222 break;
223 }
224 header->magic = 0;
225 }
226 }
227
228 io_close(backend_handle);
229
230 if (result != 0) {
231 return result;
232 }
233
Yann Gautier1a3fc9f2019-01-17 14:35:22 +0100234 if (header->image_length < stm32image_dev.lba_size) {
235 *length = stm32image_dev.lba_size;
236 } else {
237 *length = header->image_length;
238 }
Yann Gautiereb16b472018-10-15 09:36:32 +0200239
Yann Gautier1a3fc9f2019-01-17 14:35:22 +0100240 INFO("STM32 Image size : %lu\n", (unsigned long)*length);
Yann Gautiereb16b472018-10-15 09:36:32 +0200241
242 return 0;
243}
244
Yann Gautiereb16b472018-10-15 09:36:32 +0200245/* Read data from a partition */
246static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
247 size_t length, size_t *length_read)
248{
Nicolas Le Bayonf3bc8a02019-11-18 17:15:22 +0100249 int result = -EINVAL;
Yann Gautier3dcc5f12020-03-18 14:50:50 +0100250 uint8_t *local_buffer;
Yann Gautiereb16b472018-10-15 09:36:32 +0200251 boot_api_image_header_t *header =
252 (boot_api_image_header_t *)first_lba_buffer;
Yann Gautierf3633d52020-06-19 11:38:24 +0200253 size_t hdr_sz = sizeof(boot_api_image_header_t);
Yann Gautiereb16b472018-10-15 09:36:32 +0200254
255 assert(entity != NULL);
256 assert(buffer != 0U);
257 assert(length_read != NULL);
258
Yann Gautier3dcc5f12020-03-18 14:50:50 +0100259 local_buffer = (uint8_t *)buffer;
Yann Gautiereb16b472018-10-15 09:36:32 +0200260 *length_read = 0U;
261
262 while (*length_read == 0U) {
Yann Gautier1a3fc9f2019-01-17 14:35:22 +0100263 int offset;
264 int local_length;
265 uintptr_t backend_handle;
266
Yann Gautiereb16b472018-10-15 09:36:32 +0200267 if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) {
268 /* Check for backup as image is corrupted */
Yann Gautier1a3fc9f2019-01-17 14:35:22 +0100269 if (current_part->bkp_offset == 0U) {
270 result = -ENOMEM;
271 break;
272 }
273
Yann Gautiereb16b472018-10-15 09:36:32 +0200274 *stm32_img += current_part->bkp_offset;
275 if (*stm32_img >= stm32image_dev.device_size) {
276 /* End of device reached */
277 result = -ENOMEM;
278 break;
279 }
280
281 local_buffer = (uint8_t *)buffer;
282
283 result = stm32image_partition_size(entity, &length);
284 if (result != 0) {
285 break;
286 }
287 }
288
289 /* Part of image already loaded with the header */
Yann Gautierf3633d52020-06-19 11:38:24 +0200290 memcpy(local_buffer, (uint8_t *)first_lba_buffer + hdr_sz,
291 MAX_LBA_SIZE - hdr_sz);
292 local_buffer += MAX_LBA_SIZE - hdr_sz;
Yann Gautiereb16b472018-10-15 09:36:32 +0200293 offset = MAX_LBA_SIZE;
294
295 /* New image length to be read */
Yann Gautierf3633d52020-06-19 11:38:24 +0200296 local_length = round_up(length - ((MAX_LBA_SIZE) - hdr_sz),
Yann Gautiereb16b472018-10-15 09:36:32 +0200297 stm32image_dev.lba_size);
298
299 if ((header->load_address != 0U) &&
300 (header->load_address != buffer)) {
301 ERROR("Wrong load address\n");
302 panic();
303 }
304
305 result = io_open(backend_dev_handle, backend_image_spec,
306 &backend_handle);
307
308 if (result != 0) {
309 ERROR("%s: io_open (%i)\n", __func__, result);
310 break;
311 }
312
313 result = io_seek(backend_handle, IO_SEEK_SET,
314 *stm32_img + offset);
315
316 if (result != 0) {
317 ERROR("%s: io_seek (%i)\n", __func__, result);
318 *length_read = 0;
319 io_close(backend_handle);
320 break;
321 }
322
323 result = io_read(backend_handle, (uintptr_t)local_buffer,
324 local_length, length_read);
325
326 /* Adding part of size already read from header */
Yann Gautierf3633d52020-06-19 11:38:24 +0200327 *length_read += MAX_LBA_SIZE - hdr_sz;
Yann Gautiereb16b472018-10-15 09:36:32 +0200328
329 if (result != 0) {
330 ERROR("%s: io_read (%i)\n", __func__, result);
331 *length_read = 0;
Yann Gautier1a3fc9f2019-01-17 14:35:22 +0100332 header->magic = 0;
333 continue;
Yann Gautiereb16b472018-10-15 09:36:32 +0200334 }
335
Yann Gautiere97b6632019-04-19 10:48:36 +0200336 result = stm32mp_check_header(header, buffer);
Yann Gautiereb16b472018-10-15 09:36:32 +0200337 if (result != 0) {
338 ERROR("Header check failed\n");
339 *length_read = 0;
340 header->magic = 0;
Yann Gautiereb16b472018-10-15 09:36:32 +0200341 }
342
Lionel Debieve7bd96f42019-09-03 12:22:23 +0200343 result = stm32mp_auth_image(header, buffer);
344 if (result != 0) {
345 ERROR("Authentication Failed (%i)\n", result);
346 return result;
347 }
348
Yann Gautierc1f667c2020-11-09 13:28:47 +0100349 inv_dcache_range(round_up((uintptr_t)(local_buffer + length - hdr_sz),
350 CACHE_WRITEBACK_GRANULE), *length_read - length + hdr_sz);
351
Yann Gautiereb16b472018-10-15 09:36:32 +0200352 io_close(backend_handle);
353 }
354
355 return result;
356}
357
358/* Close a partition */
359static int stm32image_partition_close(io_entity_t *entity)
360{
361 current_part = NULL;
362
363 return 0;
364}
365
366/* Register the stm32image driver with the IO abstraction */
367int register_io_dev_stm32image(const io_dev_connector_t **dev_con)
368{
369 int result;
370
371 assert(dev_con != NULL);
372
373 result = io_register_device(&stm32image_dev_info);
374 if (result == 0) {
375 *dev_con = &stm32image_dev_connector;
376 }
377
378 return result;
379}