blob: ec8bb719648053c40e878105a0814b1f8712cbb8 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
2 * Copyright (c) 2018, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <debug.h>
Antonio Nino Diaz09a00ef2019-01-11 13:12:58 +00009#include <drivers/io/io_fip.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020010#include <firmware_image_package.h>
11#include <fwu_nvm.h>
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +020012#include <io_storage.h>
13#include <platform.h>
14#include <platform_def.h>
15#include <status.h>
16#include <string.h>
17#include <uuid_utils.h>
18
19
20STATUS fwu_nvm_write(unsigned long long offset, const void *buffer, size_t size)
21{
22 uintptr_t nvm_handle;
23 int ret;
24 size_t length_write;
25
26 if (offset + size > FLASH_SIZE)
27 return STATUS_OUT_OF_RESOURCES;
28
29 /* Obtain a handle to the NVM by querying the platfom layer */
30 plat_get_nvm_handle(&nvm_handle);
31
32 /* Seek to the given offset. */
33 ret = io_seek(nvm_handle, IO_SEEK_SET, offset);
34 if (ret != IO_SUCCESS)
35 return STATUS_FAIL;
36
37 /* Write to the given offset. */
38 ret = io_write(nvm_handle, (const uintptr_t)buffer,
39 size, &length_write);
40 if ((ret != IO_SUCCESS) || (size != length_write))
41 return STATUS_FAIL;
42
43 return STATUS_SUCCESS;
44}
45
46STATUS fwu_nvm_read(unsigned long long offset, void *buffer, size_t size)
47{
48 uintptr_t nvm_handle;
49 int ret;
50 size_t length_read;
51
52 if (offset + size > FLASH_SIZE)
53 return STATUS_OUT_OF_RESOURCES;
54
55 /* Obtain a handle to the NVM by querying the platform layer */
56 plat_get_nvm_handle(&nvm_handle);
57
58 /* Seek to the given offset. */
59 ret = io_seek(nvm_handle, IO_SEEK_SET, offset);
60 if (ret != IO_SUCCESS)
61 return STATUS_FAIL;
62
63 /* Read from the given offset. */
64 ret = io_read(nvm_handle, (const uintptr_t)buffer,
65 size, &length_read);
66 if ((ret != IO_SUCCESS) || (size != length_read))
67 return STATUS_FAIL;
68
69 return STATUS_SUCCESS;
70}
71
72
73STATUS fwu_update_fip(unsigned long fip_addr)
74{
75 uintptr_t nvm_handle;
76 int ret;
77 size_t bytes;
78 int fip_size;
79 unsigned int fip_read;
80 fip_toc_header_t *toc_header;
81 fip_toc_entry_t *toc_entry;
82
83 /* Obtain a handle to the NVM by querying the platform layer */
84 plat_get_nvm_handle(&nvm_handle);
85
86#if FWU_BL_TEST
87 /* Read the address of backup fip.bin for Firmware Update. */
88 ret = io_seek(nvm_handle, IO_SEEK_SET,
89 FWU_TFTF_TESTCASE_BUFFER_OFFSET);
90 if (ret != IO_SUCCESS)
91 return STATUS_FAIL;
92
93 ret = io_read(nvm_handle, (const uintptr_t)&fip_addr,
94 sizeof(bytes), &bytes);
95 if (ret != IO_SUCCESS)
96 return STATUS_FAIL;
97#endif /* FWU_BL_TEST */
98
99 /* If the new FIP address is 0 it means no update. */
100 if (fip_addr == 0)
101 return STATUS_SUCCESS;
102
103 /* Set the ToC Header at the base of the buffer */
104 toc_header = (fip_toc_header_t *)fip_addr;
105
106 /* Check if this FIP is Valid */
107 if ((toc_header->name != TOC_HEADER_NAME) ||
108 (toc_header->serial_number == 0))
109 return STATUS_LOAD_ERROR;
110
111 /* Get to the last NULL TOC entry */
112 toc_entry = (fip_toc_entry_t *)(toc_header + 1);
113 while (!is_uuid_null(&toc_entry->uuid))
114 toc_entry++;
115
116 /* get the total size of this FIP */
117 fip_size = (int)toc_entry->offset_address;
118
119 /* Copy the new FIP in DDR. */
120 memcpy((void *)FIP_IMAGE_TMP_DDR_ADDRESS, (void *)fip_addr, fip_size);
121
122 /* Update the FIP */
123 ret = io_seek(nvm_handle, IO_SEEK_SET, 0);
124 if (ret != IO_SUCCESS)
125 return STATUS_FAIL;
126
127 ret = io_write(nvm_handle, (const uintptr_t)FIP_IMAGE_TMP_DDR_ADDRESS,
128 fip_size, &bytes);
129 if ((ret != IO_SUCCESS) || fip_size != bytes)
130 return STATUS_LOAD_ERROR;
131
132 /* Read the TOC header after update. */
133 ret = io_seek(nvm_handle, IO_SEEK_SET, 0);
134 if (ret != IO_SUCCESS)
135 return STATUS_LOAD_ERROR;
136
137 ret = io_read(nvm_handle, (const uintptr_t)&fip_read,
138 sizeof(bytes), &bytes);
139 if (ret != IO_SUCCESS)
140 return STATUS_FAIL;
141
142 /* Check if this FIP is Valid */
143 if (fip_read != TOC_HEADER_NAME)
144 return STATUS_LOAD_ERROR;
145
146#if FWU_BL_TEST
147 unsigned int done_flag = FIP_IMAGE_UPDATE_DONE_FLAG;
148 /* Update the TFTF test case buffer with DONE flag */
149 ret = io_seek(nvm_handle, IO_SEEK_SET,
150 FWU_TFTF_TESTCASE_BUFFER_OFFSET);
151 if (ret != IO_SUCCESS)
152 return STATUS_FAIL;
153
154 ret = io_write(nvm_handle, (const uintptr_t)&done_flag,
155 4, &bytes);
156 if (ret != IO_SUCCESS)
157 return STATUS_FAIL;
158#endif /* FWU_BL_TEST */
159
160 INFO("FWU Image update success\n");
161
162 return STATUS_SUCCESS;
163}
164