1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * EFI application runtime services 4 * 5 * Copyright (c) 2016 Alexander Graf 6 */ 7 8 #include <common.h> 9 #include <command.h> 10 #include <dm.h> 11 #include <efi_loader.h> 12 #include <rtc.h> 13 14 /* For manual relocation support */ 15 DECLARE_GLOBAL_DATA_PTR; 16 17 struct efi_runtime_mmio_list { 18 struct list_head link; 19 void **ptr; 20 u64 paddr; 21 u64 len; 22 }; 23 24 /* This list contains all runtime available mmio regions */ 25 LIST_HEAD(efi_runtime_mmio); 26 27 static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void); 28 static efi_status_t __efi_runtime EFIAPI efi_device_error(void); 29 static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void); 30 31 #if defined(CONFIG_ARM64) 32 #define R_RELATIVE 1027 33 #define R_MASK 0xffffffffULL 34 #define IS_RELA 1 35 #elif defined(CONFIG_ARM) 36 #define R_RELATIVE 23 37 #define R_MASK 0xffULL 38 #elif defined(CONFIG_X86) 39 #include <asm/elf.h> 40 #define R_RELATIVE R_386_RELATIVE 41 #define R_MASK 0xffULL 42 #elif defined(CONFIG_RISCV) 43 #include <elf.h> 44 #define R_RELATIVE R_RISCV_RELATIVE 45 #define R_MASK 0xffULL 46 #define IS_RELA 1 47 48 struct dyn_sym { 49 ulong foo1; 50 ulong addr; 51 u32 foo2; 52 u32 foo3; 53 }; 54 #ifdef CONFIG_CPU_RISCV_32 55 #define R_ABSOLUTE R_RISCV_32 56 #define SYM_INDEX 8 57 #else 58 #define R_ABSOLUTE R_RISCV_64 59 #define SYM_INDEX 32 60 #endif 61 #else 62 #error Need to add relocation awareness 63 #endif 64 65 struct elf_rel { 66 ulong *offset; 67 ulong info; 68 }; 69 70 struct elf_rela { 71 ulong *offset; 72 ulong info; 73 long addend; 74 }; 75 76 /* 77 * EFI Runtime code lives in 2 stages. In the first stage, U-Boot and an EFI 78 * payload are running concurrently at the same time. In this mode, we can 79 * handle a good number of runtime callbacks 80 */ 81 82 static void EFIAPI efi_reset_system_boottime( 83 enum efi_reset_type reset_type, 84 efi_status_t reset_status, 85 unsigned long data_size, void *reset_data) 86 { 87 struct efi_event *evt; 88 89 EFI_ENTRY("%d %lx %lx %p", reset_type, reset_status, data_size, 90 reset_data); 91 92 /* Notify reset */ 93 list_for_each_entry(evt, &efi_events, link) { 94 if (evt->group && 95 !guidcmp(evt->group, 96 &efi_guid_event_group_reset_system)) { 97 efi_signal_event(evt, false); 98 break; 99 } 100 } 101 switch (reset_type) { 102 case EFI_RESET_COLD: 103 case EFI_RESET_WARM: 104 case EFI_RESET_PLATFORM_SPECIFIC: 105 do_reset(NULL, 0, 0, NULL); 106 break; 107 case EFI_RESET_SHUTDOWN: 108 /* We don't have anything to map this to */ 109 break; 110 } 111 112 while (1) { } 113 } 114 115 static efi_status_t EFIAPI efi_get_time_boottime( 116 struct efi_time *time, 117 struct efi_time_cap *capabilities) 118 { 119 #if defined(CONFIG_CMD_DATE) && defined(CONFIG_DM_RTC) 120 struct rtc_time tm; 121 int r; 122 struct udevice *dev; 123 124 EFI_ENTRY("%p %p", time, capabilities); 125 126 r = uclass_get_device(UCLASS_RTC, 0, &dev); 127 if (r) 128 return EFI_EXIT(EFI_DEVICE_ERROR); 129 130 r = dm_rtc_get(dev, &tm); 131 if (r) 132 return EFI_EXIT(EFI_DEVICE_ERROR); 133 134 memset(time, 0, sizeof(*time)); 135 time->year = tm.tm_year; 136 time->month = tm.tm_mon; 137 time->day = tm.tm_mday; 138 time->hour = tm.tm_hour; 139 time->minute = tm.tm_min; 140 time->daylight = tm.tm_isdst; 141 142 return EFI_EXIT(EFI_SUCCESS); 143 #else 144 return EFI_DEVICE_ERROR; 145 #endif 146 } 147 148 /* Boards may override the helpers below to implement RTS functionality */ 149 150 void __weak __efi_runtime EFIAPI efi_reset_system( 151 enum efi_reset_type reset_type, 152 efi_status_t reset_status, 153 unsigned long data_size, void *reset_data) 154 { 155 /* Nothing we can do */ 156 while (1) { } 157 } 158 159 efi_status_t __weak efi_reset_system_init(void) 160 { 161 return EFI_SUCCESS; 162 } 163 164 efi_status_t __weak __efi_runtime EFIAPI efi_get_time( 165 struct efi_time *time, 166 struct efi_time_cap *capabilities) 167 { 168 /* Nothing we can do */ 169 return EFI_DEVICE_ERROR; 170 } 171 172 efi_status_t __weak efi_get_time_init(void) 173 { 174 return EFI_SUCCESS; 175 } 176 177 struct efi_runtime_detach_list_struct { 178 void *ptr; 179 void *patchto; 180 }; 181 182 static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = { 183 { 184 /* do_reset is gone */ 185 .ptr = &efi_runtime_services.reset_system, 186 .patchto = efi_reset_system, 187 }, { 188 /* invalidate_*cache_all are gone */ 189 .ptr = &efi_runtime_services.set_virtual_address_map, 190 .patchto = &efi_invalid_parameter, 191 }, { 192 /* RTC accessors are gone */ 193 .ptr = &efi_runtime_services.get_time, 194 .patchto = &efi_get_time, 195 }, { 196 /* Clean up system table */ 197 .ptr = &systab.con_in, 198 .patchto = NULL, 199 }, { 200 /* Clean up system table */ 201 .ptr = &systab.con_out, 202 .patchto = NULL, 203 }, { 204 /* Clean up system table */ 205 .ptr = &systab.std_err, 206 .patchto = NULL, 207 }, { 208 /* Clean up system table */ 209 .ptr = &systab.boottime, 210 .patchto = NULL, 211 }, { 212 .ptr = &efi_runtime_services.get_variable, 213 .patchto = &efi_device_error, 214 }, { 215 .ptr = &efi_runtime_services.get_next_variable_name, 216 .patchto = &efi_device_error, 217 }, { 218 .ptr = &efi_runtime_services.set_variable, 219 .patchto = &efi_device_error, 220 } 221 }; 222 223 static bool efi_runtime_tobedetached(void *p) 224 { 225 int i; 226 227 for (i = 0; i < ARRAY_SIZE(efi_runtime_detach_list); i++) 228 if (efi_runtime_detach_list[i].ptr == p) 229 return true; 230 231 return false; 232 } 233 234 static void efi_runtime_detach(ulong offset) 235 { 236 int i; 237 ulong patchoff = offset - (ulong)gd->relocaddr; 238 239 for (i = 0; i < ARRAY_SIZE(efi_runtime_detach_list); i++) { 240 ulong patchto = (ulong)efi_runtime_detach_list[i].patchto; 241 ulong *p = efi_runtime_detach_list[i].ptr; 242 ulong newaddr = patchto ? (patchto + patchoff) : 0; 243 244 debug("%s: Setting %p to %lx\n", __func__, p, newaddr); 245 *p = newaddr; 246 } 247 } 248 249 /* Relocate EFI runtime to uboot_reloc_base = offset */ 250 void efi_runtime_relocate(ulong offset, struct efi_mem_desc *map) 251 { 252 #ifdef IS_RELA 253 struct elf_rela *rel = (void*)&__efi_runtime_rel_start; 254 #else 255 struct elf_rel *rel = (void*)&__efi_runtime_rel_start; 256 static ulong lastoff = CONFIG_SYS_TEXT_BASE; 257 #endif 258 259 debug("%s: Relocating to offset=%lx\n", __func__, offset); 260 for (; (ulong)rel < (ulong)&__efi_runtime_rel_stop; rel++) { 261 ulong base = CONFIG_SYS_TEXT_BASE; 262 ulong *p; 263 ulong newaddr; 264 265 p = (void*)((ulong)rel->offset - base) + gd->relocaddr; 266 267 debug("%s: rel->info=%#lx *p=%#lx rel->offset=%p\n", __func__, rel->info, *p, rel->offset); 268 269 switch (rel->info & R_MASK) { 270 case R_RELATIVE: 271 #ifdef IS_RELA 272 newaddr = rel->addend + offset - CONFIG_SYS_TEXT_BASE; 273 #else 274 newaddr = *p - lastoff + offset; 275 #endif 276 break; 277 #ifdef R_ABSOLUTE 278 case R_ABSOLUTE: { 279 ulong symidx = rel->info >> SYM_INDEX; 280 extern struct dyn_sym __dyn_sym_start[]; 281 newaddr = __dyn_sym_start[symidx].addr + offset; 282 break; 283 } 284 #endif 285 default: 286 continue; 287 } 288 289 /* Check if the relocation is inside bounds */ 290 if (map && ((newaddr < map->virtual_start) || 291 newaddr > (map->virtual_start + 292 (map->num_pages << EFI_PAGE_SHIFT)))) { 293 if (!efi_runtime_tobedetached(p)) 294 printf("U-Boot EFI: Relocation at %p is out of " 295 "range (%lx)\n", p, newaddr); 296 continue; 297 } 298 299 debug("%s: Setting %p to %lx\n", __func__, p, newaddr); 300 *p = newaddr; 301 flush_dcache_range((ulong)p & ~(EFI_CACHELINE_SIZE - 1), 302 ALIGN((ulong)&p[1], EFI_CACHELINE_SIZE)); 303 } 304 305 #ifndef IS_RELA 306 lastoff = offset; 307 #endif 308 309 invalidate_icache_all(); 310 } 311 312 static efi_status_t EFIAPI efi_set_virtual_address_map( 313 unsigned long memory_map_size, 314 unsigned long descriptor_size, 315 uint32_t descriptor_version, 316 struct efi_mem_desc *virtmap) 317 { 318 ulong runtime_start = (ulong)&__efi_runtime_start & 319 ~(ulong)EFI_PAGE_MASK; 320 int n = memory_map_size / descriptor_size; 321 int i; 322 323 EFI_ENTRY("%lx %lx %x %p", memory_map_size, descriptor_size, 324 descriptor_version, virtmap); 325 326 /* Rebind mmio pointers */ 327 for (i = 0; i < n; i++) { 328 struct efi_mem_desc *map = (void*)virtmap + 329 (descriptor_size * i); 330 struct list_head *lhandle; 331 efi_physical_addr_t map_start = map->physical_start; 332 efi_physical_addr_t map_len = map->num_pages << EFI_PAGE_SHIFT; 333 efi_physical_addr_t map_end = map_start + map_len; 334 335 /* Adjust all mmio pointers in this region */ 336 list_for_each(lhandle, &efi_runtime_mmio) { 337 struct efi_runtime_mmio_list *lmmio; 338 339 lmmio = list_entry(lhandle, 340 struct efi_runtime_mmio_list, 341 link); 342 if ((map_start <= lmmio->paddr) && 343 (map_end >= lmmio->paddr)) { 344 u64 off = map->virtual_start - map_start; 345 uintptr_t new_addr = lmmio->paddr + off; 346 *lmmio->ptr = (void *)new_addr; 347 } 348 } 349 } 350 351 /* Move the actual runtime code over */ 352 for (i = 0; i < n; i++) { 353 struct efi_mem_desc *map; 354 355 map = (void*)virtmap + (descriptor_size * i); 356 if (map->type == EFI_RUNTIME_SERVICES_CODE) { 357 ulong new_offset = map->virtual_start - 358 (runtime_start - gd->relocaddr); 359 360 efi_runtime_relocate(new_offset, map); 361 /* Once we're virtual, we can no longer handle 362 complex callbacks */ 363 efi_runtime_detach(new_offset); 364 return EFI_EXIT(EFI_SUCCESS); 365 } 366 } 367 368 return EFI_EXIT(EFI_INVALID_PARAMETER); 369 } 370 371 efi_status_t efi_add_runtime_mmio(void *mmio_ptr, u64 len) 372 { 373 struct efi_runtime_mmio_list *newmmio; 374 u64 pages = (len + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT; 375 uint64_t addr = *(uintptr_t *)mmio_ptr; 376 uint64_t retaddr; 377 378 retaddr = efi_add_memory_map(addr, pages, EFI_MMAP_IO, false); 379 if (retaddr != addr) 380 return EFI_OUT_OF_RESOURCES; 381 382 newmmio = calloc(1, sizeof(*newmmio)); 383 if (!newmmio) 384 return EFI_OUT_OF_RESOURCES; 385 newmmio->ptr = mmio_ptr; 386 newmmio->paddr = *(uintptr_t *)mmio_ptr; 387 newmmio->len = len; 388 list_add_tail(&newmmio->link, &efi_runtime_mmio); 389 390 return EFI_SUCCESS; 391 } 392 393 /* 394 * In the second stage, U-Boot has disappeared. To isolate our runtime code 395 * that at this point still exists from the rest, we put it into a special 396 * section. 397 * 398 * !!WARNING!! 399 * 400 * This means that we can not rely on any code outside of this file in any 401 * function or variable below this line. 402 * 403 * Please keep everything fully self-contained and annotated with 404 * __efi_runtime and __efi_runtime_data markers. 405 */ 406 407 /* 408 * Relocate the EFI runtime stub to a different place. We need to call this 409 * the first time we expose the runtime interface to a user and on set virtual 410 * address map calls. 411 */ 412 413 static efi_status_t __efi_runtime EFIAPI efi_unimplemented(void) 414 { 415 return EFI_UNSUPPORTED; 416 } 417 418 static efi_status_t __efi_runtime EFIAPI efi_device_error(void) 419 { 420 return EFI_DEVICE_ERROR; 421 } 422 423 static efi_status_t __efi_runtime EFIAPI efi_invalid_parameter(void) 424 { 425 return EFI_INVALID_PARAMETER; 426 } 427 428 efi_status_t __efi_runtime EFIAPI efi_update_capsule( 429 struct efi_capsule_header **capsule_header_array, 430 efi_uintn_t capsule_count, 431 u64 scatter_gather_list) 432 { 433 return EFI_UNSUPPORTED; 434 } 435 436 efi_status_t __efi_runtime EFIAPI efi_query_capsule_caps( 437 struct efi_capsule_header **capsule_header_array, 438 efi_uintn_t capsule_count, 439 u64 maximum_capsule_size, 440 u32 reset_type) 441 { 442 return EFI_UNSUPPORTED; 443 } 444 445 efi_status_t __efi_runtime EFIAPI efi_query_variable_info( 446 u32 attributes, 447 u64 *maximum_variable_storage_size, 448 u64 *remaining_variable_storage_size, 449 u64 *maximum_variable_size) 450 { 451 return EFI_UNSUPPORTED; 452 } 453 454 struct efi_runtime_services __efi_runtime_data efi_runtime_services = { 455 .hdr = { 456 .signature = EFI_RUNTIME_SERVICES_SIGNATURE, 457 .revision = EFI_RUNTIME_SERVICES_REVISION, 458 .headersize = sizeof(struct efi_table_hdr), 459 }, 460 .get_time = &efi_get_time_boottime, 461 .set_time = (void *)&efi_device_error, 462 .get_wakeup_time = (void *)&efi_unimplemented, 463 .set_wakeup_time = (void *)&efi_unimplemented, 464 .set_virtual_address_map = &efi_set_virtual_address_map, 465 .convert_pointer = (void *)&efi_invalid_parameter, 466 .get_variable = efi_get_variable, 467 .get_next_variable_name = efi_get_next_variable_name, 468 .set_variable = efi_set_variable, 469 .get_next_high_mono_count = (void *)&efi_device_error, 470 .reset_system = &efi_reset_system_boottime, 471 .update_capsule = efi_update_capsule, 472 .query_capsule_caps = efi_query_capsule_caps, 473 .query_variable_info = efi_query_variable_info, 474 }; 475