blob: ba612e2e9333a08539bea99944bc91036e745212 [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
21#include <boot_api.h>
Yann Gautiereb16b472018-10-15 09:36:32 +020022
23static uintptr_t backend_dev_handle;
24static uintptr_t backend_image_spec;
25static uint32_t *stm32_img;
26static uint8_t first_lba_buffer[MAX_LBA_SIZE] __aligned(4);
27static struct stm32image_part_info *current_part;
28
29/* STM32 Image driver functions */
30static int stm32image_dev_open(const uintptr_t init_params,
31 io_dev_info_t **dev_info);
32static int stm32image_partition_open(io_dev_info_t *dev_info,
33 const uintptr_t spec, io_entity_t *entity);
34static int stm32image_partition_size(io_entity_t *entity, size_t *length);
35static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
36 size_t length, size_t *length_read);
37static int stm32image_partition_close(io_entity_t *entity);
38static int stm32image_dev_init(io_dev_info_t *dev_info,
39 const uintptr_t init_params);
40static int stm32image_dev_close(io_dev_info_t *dev_info);
41
42/* Identify the device type as a virtual driver */
43static io_type_t device_type_stm32image(void)
44{
45 return IO_TYPE_STM32IMAGE;
46}
47
48static const io_dev_connector_t stm32image_dev_connector = {
49 .dev_open = stm32image_dev_open
50};
51
52static const io_dev_funcs_t stm32image_dev_funcs = {
53 .type = device_type_stm32image,
54 .open = stm32image_partition_open,
55 .size = stm32image_partition_size,
56 .read = stm32image_partition_read,
57 .close = stm32image_partition_close,
58 .dev_init = stm32image_dev_init,
59 .dev_close = stm32image_dev_close,
60};
61
62static io_dev_info_t stm32image_dev_info = {
63 .funcs = &stm32image_dev_funcs,
64 .info = (uintptr_t)0,
65};
66
67static struct stm32image_device_info stm32image_dev;
68
69static int get_part_idx_by_binary_type(uint32_t binary_type)
70{
71 int i;
72
73 for (i = 0; i < STM32_PART_NUM; i++) {
74 if (stm32image_dev.part_info[i].binary_type == binary_type) {
75 return i;
76 }
77 }
78
79 return -EINVAL;
80}
81
82/* Open a connection to the STM32IMAGE device */
83static int stm32image_dev_open(const uintptr_t init_params,
84 io_dev_info_t **dev_info)
85{
86 int i;
87 struct stm32image_device_info *device_info =
88 (struct stm32image_device_info *)init_params;
89
90 assert(dev_info != NULL);
91 *dev_info = (io_dev_info_t *)&stm32image_dev_info;
92
93 stm32image_dev.device_size = device_info->device_size;
94 stm32image_dev.lba_size = device_info->lba_size;
95
96 for (i = 0; i < STM32_PART_NUM; i++) {
97 memcpy(stm32image_dev.part_info[i].name,
98 device_info->part_info[i].name, MAX_PART_NAME_SIZE);
99 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) {
198 ERROR("%s: io_read (%i)\n", __func__, result);
199 break;
200 }
201
202 if ((header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) ||
203 (header->binary_type != current_part->binary_type) ||
204 (header->image_length >= stm32image_dev.device_size)) {
205 WARN("%s: partition %s wrong header\n",
206 __func__, current_part->name);
207
208 /* Header not correct, check next offset for backup */
209 *stm32_img += current_part->bkp_offset;
210 if (*stm32_img > stm32image_dev.device_size) {
211 /* No backup found, end of device reached */
212 WARN("Out of memory\n");
213 result = -ENOMEM;
214 break;
215 }
216 header->magic = 0;
217 }
218 }
219
220 io_close(backend_handle);
221
222 if (result != 0) {
223 return result;
224 }
225
226 *length = header->image_length;
227
228 INFO("STM32 Image size : %i\n", *length);
229
230 return 0;
231}
232
233static int check_header(boot_api_image_header_t *header, uintptr_t buffer)
234{
235 uint32_t i;
236 uint32_t img_checksum = 0;
237
238 /*
239 * Check header/payload validity:
240 * - Header magic
241 * - Header version
242 * - Payload checksum
243 */
244 if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) {
245 ERROR("Header magic\n");
246 return -EINVAL;
247 }
248
249 if (header->header_version != BOOT_API_HEADER_VERSION) {
250 ERROR("Header version\n");
251 return -EINVAL;
252 }
253
254 for (i = 0; i < header->image_length; i++) {
255 img_checksum += *(uint8_t *)(buffer + i);
256 }
257
258 if (header->payload_checksum != img_checksum) {
259 ERROR("Checksum: 0x%x (awaited: 0x%x)\n", img_checksum,
260 header->payload_checksum);
261 return -EINVAL;
262 }
263
264 return 0;
265}
266
267/* Read data from a partition */
268static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
269 size_t length, size_t *length_read)
270{
271 int result = 0, offset, local_length = 0;
272 uint8_t *local_buffer = (uint8_t *)buffer;
273 boot_api_image_header_t *header =
274 (boot_api_image_header_t *)first_lba_buffer;
275 uintptr_t backend_handle;
276
277 assert(entity != NULL);
278 assert(buffer != 0U);
279 assert(length_read != NULL);
280
281 *length_read = 0U;
282
283 while (*length_read == 0U) {
284 if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) {
285 /* Check for backup as image is corrupted */
286 *stm32_img += current_part->bkp_offset;
287 if (*stm32_img >= stm32image_dev.device_size) {
288 /* End of device reached */
289 result = -ENOMEM;
290 break;
291 }
292
293 local_buffer = (uint8_t *)buffer;
294
295 result = stm32image_partition_size(entity, &length);
296 if (result != 0) {
297 break;
298 }
299 }
300
301 /* Part of image already loaded with the header */
302 memcpy(local_buffer, (uint8_t *)first_lba_buffer +
303 sizeof(boot_api_image_header_t),
304 MAX_LBA_SIZE - sizeof(boot_api_image_header_t));
305 local_buffer += MAX_LBA_SIZE - sizeof(boot_api_image_header_t);
306 offset = MAX_LBA_SIZE;
307
308 /* New image length to be read */
309 local_length = round_up(length -
310 ((MAX_LBA_SIZE) -
311 sizeof(boot_api_image_header_t)),
312 stm32image_dev.lba_size);
313
314 if ((header->load_address != 0U) &&
315 (header->load_address != buffer)) {
316 ERROR("Wrong load address\n");
317 panic();
318 }
319
320 result = io_open(backend_dev_handle, backend_image_spec,
321 &backend_handle);
322
323 if (result != 0) {
324 ERROR("%s: io_open (%i)\n", __func__, result);
325 break;
326 }
327
328 result = io_seek(backend_handle, IO_SEEK_SET,
329 *stm32_img + offset);
330
331 if (result != 0) {
332 ERROR("%s: io_seek (%i)\n", __func__, result);
333 *length_read = 0;
334 io_close(backend_handle);
335 break;
336 }
337
338 result = io_read(backend_handle, (uintptr_t)local_buffer,
339 local_length, length_read);
340
341 /* Adding part of size already read from header */
342 *length_read += MAX_LBA_SIZE - sizeof(boot_api_image_header_t);
343
344 if (result != 0) {
345 ERROR("%s: io_read (%i)\n", __func__, result);
346 *length_read = 0;
347 io_close(backend_handle);
348 break;
349 }
350
351 result = check_header(header, buffer);
352 if (result != 0) {
353 ERROR("Header check failed\n");
354 *length_read = 0;
355 header->magic = 0;
356 io_close(backend_handle);
357 break;
358 }
359
360 io_close(backend_handle);
361 }
362
363 return result;
364}
365
366/* Close a partition */
367static int stm32image_partition_close(io_entity_t *entity)
368{
369 current_part = NULL;
370
371 return 0;
372}
373
374/* Register the stm32image driver with the IO abstraction */
375int register_io_dev_stm32image(const io_dev_connector_t **dev_con)
376{
377 int result;
378
379 assert(dev_con != NULL);
380
381 result = io_register_device(&stm32image_dev_info);
382 if (result == 0) {
383 *dev_con = &stm32image_dev_connector;
384 }
385
386 return result;
387}