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