/** Load an EFI executable. * @param _loader Pointer to loader data. */ static __noreturn void efi_loader_load(void *_loader) { efi_loader_t *loader = _loader; void *buf; efi_handle_t image_handle; efi_loaded_image_t *image; efi_char16_t *str; efi_uintn_t str_size; efi_status_t status; status_t ret; /* Allocate a buffer to read the image into. */ buf = malloc_large(loader->handle->size); /* Read it in. */ ret = fs_read(loader->handle, buf, loader->handle->size, 0); if (ret != STATUS_SUCCESS) boot_error("Error reading EFI image: %pS", ret); /* Ask the firmware to load the image. */ status = efi_call( efi_boot_services->load_image, false, efi_image_handle, NULL, buf, loader->handle->size, &image_handle); if (status != EFI_SUCCESS) boot_error("Error loading EFI image (0x%zx)", status); /* Get the loaded image protocol. */ status = efi_get_loaded_image(image_handle, &image); if (status != EFI_SUCCESS) boot_error("Error getting loaded image protocol (0x%zx)", status); /* Try to identify the handle of the device the image was on. */ image->device_handle = efi_device_get_handle(loader->handle->mount->device); image->file_path = loader->efi_path; fs_close(loader->handle); /* Convert the arguments to UTF-16. FIXME: UTF-8 internally? */ str_size = (strlen(loader->args.string) + 1) * sizeof(*str); str = malloc(str_size); for (size_t i = 0; i < str_size / sizeof(*str); i++) str[i] = loader->args.string[i]; image->load_options = str; image->load_options_size = str_size; loader_preboot(); /* Free up extra memory we've allocated. */ efi_memory_cleanup(); /* Start the image. */ status = efi_call(efi_boot_services->start_image, image_handle, &str_size, &str); if (status != EFI_SUCCESS) dprintf("efi: loaded image returned status 0x%zx\n", status); /* We can't do anything here - the loaded image may have done things making * our internal state invalid. Just pass through the error to whatever * loaded us. */ efi_exit(status, str, str_size); }
static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5) { struct uv_systab *tab = uv_systab; s64 ret; if (!tab || !tab->function) /* * BIOS does not support UV systab */ return BIOS_STATUS_UNIMPLEMENTED; /* * If EFI_OLD_MEMMAP is set, we need to fall back to using our old EFI * callback method, which uses efi_call() directly, with the kernel page tables: */ if (unlikely(test_bit(EFI_OLD_MEMMAP, &efi.flags))) ret = efi_call((void *)__va(tab->function), (u64)which, a1, a2, a3, a4, a5); else ret = efi_call_virt_pointer(tab, function, (u64)which, a1, a2, a3, a4, a5); return ret; }