Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 1 | From 652259af2f795a5d69c628ae7b1e79d33c234abd Mon Sep 17 00:00:00 2001 |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 2 | From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> |
| 3 | Date: Thu, 11 Nov 2021 16:27:59 +0000 |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 4 | Subject: [PATCH 11/24] efi: corstone1000: introduce EFI capsule update |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 5 | |
| 6 | This commit provides capsule update feature for Corstone1000. |
| 7 | |
| 8 | This feature is available before and after ExitBootServices(). |
| 9 | |
| 10 | A platform specific capsule buffer is allocated. This buffer |
| 11 | is physically contiguous and allocated at the start of the DDR |
| 12 | memory after u-boot relocation to the end of DDR. |
| 13 | |
| 14 | The capsule buffer is shared between u-boot and the secure world. |
| 15 | On UpdateCapsule() , capsule data is copied to the buffer |
| 16 | and a buffer ready event is generated using FF-A transport. |
| 17 | |
| 18 | On ExitBootServices() a kernel started event is sent to the |
| 19 | SE Proxy FW update service. This event is generated on each boot. |
| 20 | |
| 21 | Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> |
| 22 | Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org> |
| 23 | --- |
| 24 | include/configs/corstone1000.h | 18 +++++ |
| 25 | include/efi_loader.h | 4 +- |
| 26 | lib/efi_loader/efi_boottime.c | 47 ++++++++++++ |
| 27 | lib/efi_loader/efi_capsule.c | 135 ++++++++++++++++++++++++++++++++- |
| 28 | lib/efi_loader/efi_setup.c | 15 ++++ |
| 29 | 5 files changed, 215 insertions(+), 4 deletions(-) |
| 30 | |
| 31 | diff --git a/include/configs/corstone1000.h b/include/configs/corstone1000.h |
| 32 | index afc9ccfc192b..a400cdef69d0 100644 |
| 33 | --- a/include/configs/corstone1000.h |
| 34 | +++ b/include/configs/corstone1000.h |
| 35 | @@ -14,6 +14,24 @@ |
| 36 | |
| 37 | #include <linux/sizes.h> |
| 38 | |
| 39 | +/* The SE Proxy partition ID*/ |
| 40 | +#define CORSTONE1000_SEPROXY_PART_ID (0x8002) |
| 41 | + |
| 42 | +/* Update service ID provided by the SE Proxy secure partition*/ |
| 43 | +#define CORSTONE1000_SEPROXY_UPDATE_SVC_ID (0x4) |
| 44 | + |
| 45 | +/* Notification events used with SE Proxy update service */ |
| 46 | +#define CORSTONE1000_BUFFER_READY_EVT (0x1) |
| 47 | +#define CORSTONE1000_KERNEL_STARTED_EVT (0x2) |
| 48 | + |
| 49 | +/* Size in 4KB pages of the EFI capsule buffer */ |
| 50 | +#define CORSTONE1000_CAPSULE_BUFFER_SIZE (8192) /* 32 MB */ |
| 51 | + |
| 52 | +/* Capsule GUID */ |
| 53 | +#define EFI_CORSTONE1000_CAPSULE_ID_GUID \ |
| 54 | + EFI_GUID(0x3a770ddc, 0x409b, 0x48b2, 0x81, 0x41, \ |
| 55 | + 0x93, 0xb7, 0xc6, 0x0b, 0x20, 0x9e) |
| 56 | + |
| 57 | /* MM SP UUID binary data (little-endian format) */ |
| 58 | #define MM_SP_UUID_DATA \ |
| 59 | 0xed, 0x32, 0xd5, 0x33, \ |
| 60 | diff --git a/include/efi_loader.h b/include/efi_loader.h |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 61 | index 5b41985244e2..796419b69b40 100644 |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 62 | --- a/include/efi_loader.h |
| 63 | +++ b/include/efi_loader.h |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 64 | @@ -984,11 +984,11 @@ extern const struct efi_firmware_management_protocol efi_fmp_fit; |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 65 | extern const struct efi_firmware_management_protocol efi_fmp_raw; |
| 66 | |
| 67 | /* Capsule update */ |
| 68 | -efi_status_t EFIAPI efi_update_capsule( |
| 69 | +efi_status_t __efi_runtime EFIAPI efi_update_capsule( |
| 70 | struct efi_capsule_header **capsule_header_array, |
| 71 | efi_uintn_t capsule_count, |
| 72 | u64 scatter_gather_list); |
| 73 | -efi_status_t EFIAPI efi_query_capsule_caps( |
| 74 | +efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps( |
| 75 | struct efi_capsule_header **capsule_header_array, |
| 76 | efi_uintn_t capsule_count, |
| 77 | u64 *maximum_capsule_size, |
| 78 | diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 79 | index c68d9ed4f0bd..f2b5c7834c01 100644 |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 80 | --- a/lib/efi_loader/efi_boottime.c |
| 81 | +++ b/lib/efi_loader/efi_boottime.c |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 82 | @@ -2095,6 +2095,44 @@ static void efi_exit_caches(void) |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 83 | #endif |
| 84 | } |
| 85 | |
| 86 | +#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) |
| 87 | +/** |
| 88 | + * efi_corstone1000_kernel_started_event - notifies SE Proxy FW update service |
| 89 | + * |
| 90 | + * This function notifies the SE Proxy update service that the kernel has already started |
| 91 | + * |
| 92 | + * Return: |
| 93 | + * |
| 94 | + * 0: on success, otherwise failure |
| 95 | + */ |
| 96 | +static int efi_corstone1000_kernel_started_event(void) |
| 97 | +{ |
| 98 | + struct ffa_interface_data func_data = {0}; |
| 99 | + struct ffa_send_direct_data msg = {0}; |
| 100 | + u16 part_id = CORSTONE1000_SEPROXY_PART_ID; |
| 101 | + |
| 102 | + log_debug("[%s]\n", __func__); |
| 103 | + |
| 104 | + /* |
| 105 | + * telling the driver which partition to use |
| 106 | + */ |
| 107 | + func_data.data0_size = sizeof(part_id); |
| 108 | + func_data.data0 = &part_id; |
| 109 | + |
| 110 | + /* |
| 111 | + * setting the kernel started event arguments |
| 112 | + */ |
| 113 | + msg.a3 = CORSTONE1000_SEPROXY_UPDATE_SVC_ID; |
| 114 | + msg.a5 = CORSTONE1000_KERNEL_STARTED_EVT; |
| 115 | + |
| 116 | + func_data.data1_size = sizeof(msg); |
| 117 | + func_data.data1 = &msg; |
| 118 | + |
| 119 | + return ffa_helper_msg_send_direct_req(&func_data); |
| 120 | +} |
| 121 | + |
| 122 | +#endif |
| 123 | + |
| 124 | /** |
| 125 | * efi_exit_boot_services() - stop all boot services |
| 126 | * @image_handle: handle of the loaded image |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 127 | @@ -2208,6 +2246,15 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 128 | /* Recalculate CRC32 */ |
| 129 | efi_update_table_header_crc32(&systab.hdr); |
| 130 | |
| 131 | +#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) |
| 132 | + /* Notifying SE Proxy FW update service */ |
| 133 | + ffa_ret = efi_corstone1000_kernel_started_event(); |
| 134 | + if (ffa_ret) |
| 135 | + debug("[efi_boottime][ERROR]: Failure to notify SE Proxy FW update service\n"); |
| 136 | + else |
| 137 | + debug("[efi_boottime][INFO]: SE Proxy FW update service notified\n"); |
| 138 | +#endif |
| 139 | + |
| 140 | /* Give the payload some time to boot */ |
| 141 | efi_set_watchdog(0); |
| 142 | WATCHDOG_RESET(); |
| 143 | diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 144 | index a6b98f066a0b..a0689ba912fc 100644 |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 145 | --- a/lib/efi_loader/efi_capsule.c |
| 146 | +++ b/lib/efi_loader/efi_capsule.c |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 147 | @@ -25,6 +25,14 @@ |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 148 | #include <crypto/pkcs7_parser.h> |
| 149 | #include <linux/err.h> |
| 150 | |
| 151 | +#ifdef CONFIG_TARGET_CORSTONE1000 |
| 152 | +#include <arm_ffa_helper.h> |
| 153 | +#include <cpu_func.h> |
| 154 | + |
| 155 | +void *__efi_runtime_data corstone1000_capsule_buf; /* capsule shared buffer virtual address */ |
| 156 | +efi_guid_t corstone1000_capsule_guid = EFI_CORSTONE1000_CAPSULE_ID_GUID; |
| 157 | +#endif |
| 158 | + |
| 159 | DECLARE_GLOBAL_DATA_PTR; |
| 160 | |
| 161 | const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID; |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 162 | @@ -512,6 +520,89 @@ static efi_status_t efi_capsule_update_firmware( |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 163 | } |
| 164 | #endif /* CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT */ |
| 165 | |
| 166 | +#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) |
| 167 | + |
| 168 | +/** |
| 169 | + * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer |
| 170 | + * @capsule_image_size: The capsule data (header + payload) |
| 171 | + * |
| 172 | + * This function allocates the physically contiguous buffer shared between u-boot |
| 173 | + * and the secure world. On UpdateCapsule() capsule data is copied to the buffer |
| 174 | + * and a door bell event is generated. |
| 175 | + * The buffer is allocated at the start of the DDR memory after u-boot has been relocated |
| 176 | + * to the end of DDR. |
| 177 | + * |
| 178 | + * Return: |
| 179 | + * |
| 180 | + * 0: on success, otherwise failure |
| 181 | + */ |
| 182 | +efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void) |
| 183 | +{ |
| 184 | + efi_status_t efi_ret; |
| 185 | + u64 ram_base = CONFIG_SYS_SDRAM_BASE; |
| 186 | + |
| 187 | + log_debug("[%s]\n", __func__); |
| 188 | + |
| 189 | + efi_ret = efi_allocate_pages(EFI_ALLOCATE_ADDRESS, |
| 190 | + EFI_RUNTIME_SERVICES_DATA, |
| 191 | + CORSTONE1000_CAPSULE_BUFFER_SIZE, |
| 192 | + &ram_base); |
| 193 | + |
| 194 | + if (efi_ret != EFI_SUCCESS) { |
| 195 | + corstone1000_capsule_buf = NULL; |
| 196 | + log_err("EFI: Corstone1000: Allocating capsule shared buffer error (%d)\n" |
| 197 | + , (int)efi_ret); |
| 198 | + return efi_ret; |
| 199 | + } |
| 200 | + |
| 201 | + log_info("EFI: Corstone1000: Capsule shared buffer at 0x%x , size %d pages\n" |
| 202 | + , (unsigned int)ram_base, |
| 203 | + CORSTONE1000_CAPSULE_BUFFER_SIZE); |
| 204 | + |
| 205 | + corstone1000_capsule_buf = (void *)map_sysmem((phys_addr_t)ram_base, 0); |
| 206 | + |
| 207 | + return EFI_SUCCESS; |
| 208 | +} |
| 209 | + |
| 210 | +/** |
| 211 | + * efi_corstone1000_buffer_ready_event - issue door bell event |
| 212 | + * @capsule_image_size: The capsule data (header + payload) |
| 213 | + * |
| 214 | + * This function notifies the SE Proxy update service that capsule data is available |
| 215 | + * in the capsule shared buffer. |
| 216 | + * |
| 217 | + * Return: |
| 218 | + * |
| 219 | + * 0: on success, otherwise failure |
| 220 | + */ |
| 221 | +static int __efi_runtime efi_corstone1000_buffer_ready_event(u32 capsule_image_size) |
| 222 | +{ |
| 223 | + struct ffa_interface_data func_data = {0}; |
| 224 | + struct ffa_send_direct_data msg = {0}; |
| 225 | + u16 part_id = CORSTONE1000_SEPROXY_PART_ID; |
| 226 | + |
| 227 | + log_debug("[%s]\n", __func__); |
| 228 | + |
| 229 | + /* |
| 230 | + * telling the driver which partition to use |
| 231 | + */ |
| 232 | + func_data.data0_size = sizeof(part_id); |
| 233 | + func_data.data0 = &part_id; |
| 234 | + |
| 235 | + /* |
| 236 | + * setting the buffer ready event arguments |
| 237 | + */ |
| 238 | + msg.a3 = CORSTONE1000_SEPROXY_UPDATE_SVC_ID; |
| 239 | + msg.a4 = capsule_image_size; |
| 240 | + msg.a5 = CORSTONE1000_BUFFER_READY_EVT; |
| 241 | + |
| 242 | + func_data.data1_size = sizeof(msg); |
| 243 | + func_data.data1 = &msg; |
| 244 | + |
| 245 | + return ffa_helper_msg_send_direct_req(&func_data); |
| 246 | +} |
| 247 | +#endif |
| 248 | + |
| 249 | /** |
| 250 | * efi_update_capsule() - process information from operating system |
| 251 | * @capsule_header_array: Array of virtual address pointers |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 252 | @@ -525,7 +616,7 @@ static efi_status_t efi_capsule_update_firmware( |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 253 | * |
| 254 | * Return: status code |
| 255 | */ |
| 256 | -efi_status_t EFIAPI efi_update_capsule( |
| 257 | +efi_status_t __efi_runtime EFIAPI efi_update_capsule( |
| 258 | struct efi_capsule_header **capsule_header_array, |
| 259 | efi_uintn_t capsule_count, |
| 260 | u64 scatter_gather_list) |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 261 | @@ -542,6 +633,13 @@ efi_status_t EFIAPI efi_update_capsule( |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 262 | goto out; |
| 263 | } |
| 264 | |
| 265 | +#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) |
| 266 | + if (capsule_count != 1 || !corstone1000_capsule_buf) { |
| 267 | + ret = EFI_INVALID_PARAMETER; |
| 268 | + goto out; |
| 269 | + } |
| 270 | +#endif |
| 271 | + |
| 272 | ret = EFI_SUCCESS; |
| 273 | for (i = 0, capsule = *capsule_header_array; i < capsule_count; |
| 274 | i++, capsule = *(++capsule_header_array)) { |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 275 | @@ -554,6 +652,39 @@ efi_status_t EFIAPI efi_update_capsule( |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 276 | |
| 277 | log_debug("Capsule[%d] (guid:%pUs)\n", |
| 278 | i, &capsule->capsule_guid); |
| 279 | + |
| 280 | +#if CONFIG_IS_ENABLED(TARGET_CORSTONE1000) |
| 281 | + if (guidcmp(&corstone1000_capsule_guid, &capsule->capsule_guid)) { |
| 282 | + ret = EFI_INVALID_PARAMETER; |
| 283 | + log_err("Corstone1000: Invalid capsule GUID\n"); |
| 284 | + goto out; |
| 285 | + } |
| 286 | + |
| 287 | + if (efi_size_in_pages(capsule->capsule_image_size) > |
| 288 | + CORSTONE1000_CAPSULE_BUFFER_SIZE) { |
| 289 | + log_err("Corstone1000: Capsule data size exceeds the shared buffer size\n"); |
| 290 | + ret = EFI_BUFFER_TOO_SMALL; |
| 291 | + goto out; |
| 292 | + } |
| 293 | + |
| 294 | + /* copy the data to the contiguous buffer */ |
| 295 | + efi_memcpy_runtime(corstone1000_capsule_buf, capsule, capsule->capsule_image_size); |
| 296 | + |
| 297 | + /* invalidate the data cache */ |
| 298 | + invalidate_dcache_all(); |
| 299 | + |
| 300 | + /* issue buffer ready event */ |
| 301 | + ret = efi_corstone1000_buffer_ready_event(capsule->capsule_image_size); |
| 302 | + if (ret) { |
| 303 | + log_err("EFI: Corstone1000: Buffer ready event error (%d)\n", (int)ret); |
| 304 | + ret = EFI_DEVICE_ERROR; |
| 305 | + } else { |
| 306 | + ret = EFI_SUCCESS; |
| 307 | + } |
| 308 | + |
| 309 | + goto out; |
| 310 | +#endif |
| 311 | + |
| 312 | if (!guidcmp(&capsule->capsule_guid, |
| 313 | &efi_guid_firmware_management_capsule_id)) { |
| 314 | ret = efi_capsule_update_firmware(capsule); |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 315 | @@ -592,7 +723,7 @@ out: |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 316 | * |
| 317 | * Return: status code |
| 318 | */ |
| 319 | -efi_status_t EFIAPI efi_query_capsule_caps( |
| 320 | +efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps( |
| 321 | struct efi_capsule_header **capsule_header_array, |
| 322 | efi_uintn_t capsule_count, |
| 323 | u64 *maximum_capsule_size, |
| 324 | diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 325 | index 492ecf4cb15c..bfd4687e10b5 100644 |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 326 | --- a/lib/efi_loader/efi_setup.c |
| 327 | +++ b/lib/efi_loader/efi_setup.c |
| 328 | @@ -16,6 +16,13 @@ |
| 329 | |
| 330 | efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; |
| 331 | |
| 332 | +#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) |
| 333 | +/** |
| 334 | + * efi_corstone1000_alloc_capsule_shared_buf - allocate capsule shared buffer |
| 335 | + */ |
| 336 | +extern efi_status_t efi_corstone1000_alloc_capsule_shared_buf(void); |
| 337 | +#endif |
| 338 | + |
| 339 | /* |
| 340 | * Allow unaligned memory access. |
| 341 | * |
| 342 | @@ -128,6 +135,14 @@ static efi_status_t efi_init_capsule(void) |
| 343 | { |
| 344 | efi_status_t ret = EFI_SUCCESS; |
| 345 | |
| 346 | +#if IS_ENABLED(CONFIG_TARGET_CORSTONE1000) |
| 347 | + ret = efi_corstone1000_alloc_capsule_shared_buf(); |
| 348 | + if (ret != EFI_SUCCESS) { |
| 349 | + printf("EFI: Corstone-1000: cannot allocate caspsule shared buffer\n"); |
| 350 | + return ret; |
| 351 | + } |
| 352 | +#endif |
| 353 | + |
| 354 | if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_UPDATE)) { |
| 355 | ret = efi_set_variable_int(u"CapsuleMax", |
| 356 | &efi_guid_capsule_report, |
| 357 | -- |
Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame^] | 358 | 2.37.1 |
Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 359 | |