blob: 0164a2d43da4688fe9d647aa88fdc32e7caedc59 [file] [log] [blame]
Yann Gautiereb16b472018-10-15 09:36:32 +02001/*
2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3 *
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);
97 stm32image_dev.part_info[i].part_offset =
98 device_info->part_info[i].part_offset;
99 stm32image_dev.part_info[i].bkp_offset =
100 device_info->part_info[i].bkp_offset;
101 }
102
103 return 0;
104}
105
106/* Do some basic package checks */
107static int stm32image_dev_init(io_dev_info_t *dev_info,
108 const uintptr_t init_params)
109{
110 int result;
111
112 if ((backend_dev_handle != 0U) || (backend_image_spec != 0U)) {
113 ERROR("STM32 Image io supports only one session\n");
114 return -ENOMEM;
115 }
116
117 /* Obtain a reference to the image by querying the platform layer */
118 result = plat_get_image_source(STM32_IMAGE_ID, &backend_dev_handle,
119 &backend_image_spec);
120 if (result != 0) {
121 ERROR("STM32 image error (%i)\n", result);
122 return -EINVAL;
123 }
124
125 return result;
126}
127
128/* Close a connection to the STM32 Image device */
129static int stm32image_dev_close(io_dev_info_t *dev_info)
130{
131 backend_dev_handle = 0U;
132 backend_image_spec = 0U;
133 stm32_img = NULL;
134
135 return 0;
136}
137
138/* Open a partition */
139static int stm32image_partition_open(io_dev_info_t *dev_info,
140 const uintptr_t spec, io_entity_t *entity)
141{
142 const struct stm32image_part_info *partition_spec;
143 int idx;
144
145 assert(entity != NULL);
146
147 partition_spec = (struct stm32image_part_info *)spec;
148 assert(partition_spec != NULL);
149
150 idx = get_part_idx_by_binary_type(partition_spec->binary_type);
151 if ((idx < 0) || (idx > STM32_PART_NUM)) {
152 ERROR("Wrong partition index (%d)\n", idx);
153 return -EINVAL;
154 }
155
156 current_part = &stm32image_dev.part_info[idx];
157 stm32_img = (uint32_t *)&current_part->part_offset;
158
159 return 0;
160}
161
162/* Return the size of a partition */
163static int stm32image_partition_size(io_entity_t *entity, size_t *length)
164{
165 int result;
166 uintptr_t backend_handle;
167 size_t bytes_read;
168 boot_api_image_header_t *header =
169 (boot_api_image_header_t *)first_lba_buffer;
170
171 assert(entity != NULL);
172 assert(length != NULL);
173
174 /* Attempt to access the image */
175 result = io_open(backend_dev_handle, backend_image_spec,
176 &backend_handle);
177
178 if (result < 0) {
179 ERROR("%s: io_open (%i)\n", __func__, result);
180 return result;
181 }
182
183 /* Reset magic header value */
184 header->magic = 0;
185
186 while (header->magic == 0U) {
187 result = io_seek(backend_handle, IO_SEEK_SET, *stm32_img);
188 if (result != 0) {
189 ERROR("%s: io_seek (%i)\n", __func__, result);
190 break;
191 }
192
193 result = io_read(backend_handle, (uintptr_t)header,
194 MAX_LBA_SIZE, (size_t *)&bytes_read);
195 if (result != 0) {
196 ERROR("%s: io_read (%i)\n", __func__, result);
197 break;
198 }
199
200 if ((header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) ||
201 (header->binary_type != current_part->binary_type) ||
202 (header->image_length >= stm32image_dev.device_size)) {
203 WARN("%s: partition %s wrong header\n",
204 __func__, current_part->name);
205
206 /* Header not correct, check next offset for backup */
207 *stm32_img += current_part->bkp_offset;
208 if (*stm32_img > stm32image_dev.device_size) {
209 /* No backup found, end of device reached */
210 WARN("Out of memory\n");
211 result = -ENOMEM;
212 break;
213 }
214 header->magic = 0;
215 }
216 }
217
218 io_close(backend_handle);
219
220 if (result != 0) {
221 return result;
222 }
223
224 *length = header->image_length;
225
226 INFO("STM32 Image size : %i\n", *length);
227
228 return 0;
229}
230
231static int check_header(boot_api_image_header_t *header, uintptr_t buffer)
232{
233 uint32_t i;
234 uint32_t img_checksum = 0;
235
236 /*
237 * Check header/payload validity:
238 * - Header magic
239 * - Header version
240 * - Payload checksum
241 */
242 if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) {
243 ERROR("Header magic\n");
244 return -EINVAL;
245 }
246
247 if (header->header_version != BOOT_API_HEADER_VERSION) {
248 ERROR("Header version\n");
249 return -EINVAL;
250 }
251
252 for (i = 0; i < header->image_length; i++) {
253 img_checksum += *(uint8_t *)(buffer + i);
254 }
255
256 if (header->payload_checksum != img_checksum) {
257 ERROR("Checksum: 0x%x (awaited: 0x%x)\n", img_checksum,
258 header->payload_checksum);
259 return -EINVAL;
260 }
261
262 return 0;
263}
264
265/* Read data from a partition */
266static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
267 size_t length, size_t *length_read)
268{
269 int result = 0, offset, local_length = 0;
270 uint8_t *local_buffer = (uint8_t *)buffer;
271 boot_api_image_header_t *header =
272 (boot_api_image_header_t *)first_lba_buffer;
273 uintptr_t backend_handle;
274
275 assert(entity != NULL);
276 assert(buffer != 0U);
277 assert(length_read != NULL);
278
279 *length_read = 0U;
280
281 while (*length_read == 0U) {
282 if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) {
283 /* Check for backup as image is corrupted */
284 *stm32_img += current_part->bkp_offset;
285 if (*stm32_img >= stm32image_dev.device_size) {
286 /* End of device reached */
287 result = -ENOMEM;
288 break;
289 }
290
291 local_buffer = (uint8_t *)buffer;
292
293 result = stm32image_partition_size(entity, &length);
294 if (result != 0) {
295 break;
296 }
297 }
298
299 /* Part of image already loaded with the header */
300 memcpy(local_buffer, (uint8_t *)first_lba_buffer +
301 sizeof(boot_api_image_header_t),
302 MAX_LBA_SIZE - sizeof(boot_api_image_header_t));
303 local_buffer += MAX_LBA_SIZE - sizeof(boot_api_image_header_t);
304 offset = MAX_LBA_SIZE;
305
306 /* New image length to be read */
307 local_length = round_up(length -
308 ((MAX_LBA_SIZE) -
309 sizeof(boot_api_image_header_t)),
310 stm32image_dev.lba_size);
311
312 if ((header->load_address != 0U) &&
313 (header->load_address != buffer)) {
314 ERROR("Wrong load address\n");
315 panic();
316 }
317
318 result = io_open(backend_dev_handle, backend_image_spec,
319 &backend_handle);
320
321 if (result != 0) {
322 ERROR("%s: io_open (%i)\n", __func__, result);
323 break;
324 }
325
326 result = io_seek(backend_handle, IO_SEEK_SET,
327 *stm32_img + offset);
328
329 if (result != 0) {
330 ERROR("%s: io_seek (%i)\n", __func__, result);
331 *length_read = 0;
332 io_close(backend_handle);
333 break;
334 }
335
336 result = io_read(backend_handle, (uintptr_t)local_buffer,
337 local_length, length_read);
338
339 /* Adding part of size already read from header */
340 *length_read += MAX_LBA_SIZE - sizeof(boot_api_image_header_t);
341
342 if (result != 0) {
343 ERROR("%s: io_read (%i)\n", __func__, result);
344 *length_read = 0;
345 io_close(backend_handle);
346 break;
347 }
348
349 result = check_header(header, buffer);
350 if (result != 0) {
351 ERROR("Header check failed\n");
352 *length_read = 0;
353 header->magic = 0;
354 io_close(backend_handle);
355 break;
356 }
357
358 io_close(backend_handle);
359 }
360
361 return result;
362}
363
364/* Close a partition */
365static int stm32image_partition_close(io_entity_t *entity)
366{
367 current_part = NULL;
368
369 return 0;
370}
371
372/* Register the stm32image driver with the IO abstraction */
373int register_io_dev_stm32image(const io_dev_connector_t **dev_con)
374{
375 int result;
376
377 assert(dev_con != NULL);
378
379 result = io_register_device(&stm32image_dev_info);
380 if (result == 0) {
381 *dev_con = &stm32image_dev_connector;
382 }
383
384 return result;
385}