1901d209aSJuergen Gross // SPDX-License-Identifier: GPL-2.0 2c7341d6aSDaniel Kiper /* 3c7341d6aSDaniel Kiper * Copyright (c) 2014 Oracle Co., Daniel Kiper 4c7341d6aSDaniel Kiper */ 5c7341d6aSDaniel Kiper 6342cd340SDaniel Kiper #include <linux/bitops.h> 7c7341d6aSDaniel Kiper #include <linux/efi.h> 8c7341d6aSDaniel Kiper #include <linux/init.h> 9c7341d6aSDaniel Kiper #include <linux/string.h> 10c7341d6aSDaniel Kiper 11a62ed500SShannon Zhao #include <xen/xen.h> 12c7341d6aSDaniel Kiper #include <xen/xen-ops.h> 13a62ed500SShannon Zhao #include <xen/interface/platform.h> 14c7341d6aSDaniel Kiper 15342cd340SDaniel Kiper #include <asm/page.h> 16c7341d6aSDaniel Kiper #include <asm/setup.h> 17a62ed500SShannon Zhao #include <asm/xen/hypercall.h> 18a62ed500SShannon Zhao 19a62ed500SShannon Zhao static efi_char16_t vendor[100] __initdata; 20a62ed500SShannon Zhao 21a62ed500SShannon Zhao static efi_system_table_t efi_systab_xen __initdata = { 22a62ed500SShannon Zhao .hdr = { 23a62ed500SShannon Zhao .signature = EFI_SYSTEM_TABLE_SIGNATURE, 24a62ed500SShannon Zhao .revision = 0, /* Initialized later. */ 25a62ed500SShannon Zhao .headersize = 0, /* Ignored by Linux Kernel. */ 26a62ed500SShannon Zhao .crc32 = 0, /* Ignored by Linux Kernel. */ 27a62ed500SShannon Zhao .reserved = 0 28a62ed500SShannon Zhao }, 29a62ed500SShannon Zhao .fw_vendor = EFI_INVALID_TABLE_ADDR, /* Initialized later. */ 30a62ed500SShannon Zhao .fw_revision = 0, /* Initialized later. */ 31a62ed500SShannon Zhao .con_in_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ 329b47c527SArvind Sankar .con_in = NULL, /* Not used under Xen. */ 33a62ed500SShannon Zhao .con_out_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ 34960a8d01SArd Biesheuvel .con_out = NULL, /* Not used under Xen. */ 35a62ed500SShannon Zhao .stderr_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ 36a62ed500SShannon Zhao .stderr = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ 37a62ed500SShannon Zhao .runtime = (efi_runtime_services_t *)EFI_INVALID_TABLE_ADDR, 38a62ed500SShannon Zhao /* Not used under Xen. */ 39a62ed500SShannon Zhao .boottime = (efi_boot_services_t *)EFI_INVALID_TABLE_ADDR, 40a62ed500SShannon Zhao /* Not used under Xen. */ 41a62ed500SShannon Zhao .nr_tables = 0, /* Initialized later. */ 42a62ed500SShannon Zhao .tables = EFI_INVALID_TABLE_ADDR /* Initialized later. */ 43a62ed500SShannon Zhao }; 44a62ed500SShannon Zhao 45a62ed500SShannon Zhao static efi_system_table_t __init *xen_efi_probe(void) 46a62ed500SShannon Zhao { 47a62ed500SShannon Zhao struct xen_platform_op op = { 48a62ed500SShannon Zhao .cmd = XENPF_firmware_info, 49a62ed500SShannon Zhao .u.firmware_info = { 50a62ed500SShannon Zhao .type = XEN_FW_EFI_INFO, 51a62ed500SShannon Zhao .index = XEN_FW_EFI_CONFIG_TABLE 52a62ed500SShannon Zhao } 53a62ed500SShannon Zhao }; 54a62ed500SShannon Zhao union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info; 55a62ed500SShannon Zhao 56a62ed500SShannon Zhao if (!xen_initial_domain() || HYPERVISOR_platform_op(&op) < 0) 57a62ed500SShannon Zhao return NULL; 58a62ed500SShannon Zhao 59a62ed500SShannon Zhao /* Here we know that Xen runs on EFI platform. */ 6009515706SJuergen Gross xen_efi_runtime_setup(); 61a62ed500SShannon Zhao 62a62ed500SShannon Zhao efi_systab_xen.tables = info->cfg.addr; 63a62ed500SShannon Zhao efi_systab_xen.nr_tables = info->cfg.nent; 64a62ed500SShannon Zhao 65a62ed500SShannon Zhao op.cmd = XENPF_firmware_info; 66a62ed500SShannon Zhao op.u.firmware_info.type = XEN_FW_EFI_INFO; 67a62ed500SShannon Zhao op.u.firmware_info.index = XEN_FW_EFI_VENDOR; 68a62ed500SShannon Zhao info->vendor.bufsz = sizeof(vendor); 69a62ed500SShannon Zhao set_xen_guest_handle(info->vendor.name, vendor); 70a62ed500SShannon Zhao 71a62ed500SShannon Zhao if (HYPERVISOR_platform_op(&op) == 0) { 72a62ed500SShannon Zhao efi_systab_xen.fw_vendor = __pa_symbol(vendor); 73a62ed500SShannon Zhao efi_systab_xen.fw_revision = info->vendor.revision; 74a62ed500SShannon Zhao } else 75a62ed500SShannon Zhao efi_systab_xen.fw_vendor = __pa_symbol(L"UNKNOWN"); 76a62ed500SShannon Zhao 77a62ed500SShannon Zhao op.cmd = XENPF_firmware_info; 78a62ed500SShannon Zhao op.u.firmware_info.type = XEN_FW_EFI_INFO; 79a62ed500SShannon Zhao op.u.firmware_info.index = XEN_FW_EFI_VERSION; 80a62ed500SShannon Zhao 81a62ed500SShannon Zhao if (HYPERVISOR_platform_op(&op) == 0) 82a62ed500SShannon Zhao efi_systab_xen.hdr.revision = info->version; 83a62ed500SShannon Zhao 84a62ed500SShannon Zhao op.cmd = XENPF_firmware_info; 85a62ed500SShannon Zhao op.u.firmware_info.type = XEN_FW_EFI_INFO; 86a62ed500SShannon Zhao op.u.firmware_info.index = XEN_FW_EFI_RT_VERSION; 87a62ed500SShannon Zhao 88a62ed500SShannon Zhao if (HYPERVISOR_platform_op(&op) == 0) 89a62ed500SShannon Zhao efi.runtime_version = info->version; 90a62ed500SShannon Zhao 91a62ed500SShannon Zhao return &efi_systab_xen; 92a62ed500SShannon Zhao } 93c7341d6aSDaniel Kiper 94a7012bdbSDaniel Kiper /* 95a7012bdbSDaniel Kiper * Determine whether we're in secure boot mode. 96a7012bdbSDaniel Kiper */ 97a7012bdbSDaniel Kiper static enum efi_secureboot_mode xen_efi_get_secureboot(void) 98a7012bdbSDaniel Kiper { 99a7012bdbSDaniel Kiper static efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID; 100*b283477dSArd Biesheuvel enum efi_secureboot_mode mode; 101a7012bdbSDaniel Kiper efi_status_t status; 102*b283477dSArd Biesheuvel u8 moksbstate; 103a7012bdbSDaniel Kiper unsigned long size; 104a7012bdbSDaniel Kiper 105*b283477dSArd Biesheuvel mode = efi_get_secureboot_mode(efi.get_variable); 106*b283477dSArd Biesheuvel if (mode == efi_secureboot_mode_unknown) { 107*b283477dSArd Biesheuvel pr_err("Could not determine UEFI Secure Boot status.\n"); 108*b283477dSArd Biesheuvel return efi_secureboot_mode_unknown; 109*b283477dSArd Biesheuvel } 110*b283477dSArd Biesheuvel if (mode != efi_secureboot_mode_enabled) 111*b283477dSArd Biesheuvel return mode; 112a7012bdbSDaniel Kiper 113a7012bdbSDaniel Kiper /* See if a user has put the shim into insecure mode. */ 114a7012bdbSDaniel Kiper size = sizeof(moksbstate); 115a7012bdbSDaniel Kiper status = efi.get_variable(L"MokSBStateRT", &shim_guid, 116a7012bdbSDaniel Kiper NULL, &size, &moksbstate); 117a7012bdbSDaniel Kiper 118a7012bdbSDaniel Kiper /* If it fails, we don't care why. Default to secure. */ 119a7012bdbSDaniel Kiper if (status != EFI_SUCCESS) 120a7012bdbSDaniel Kiper goto secure_boot_enabled; 121a7012bdbSDaniel Kiper 122a7012bdbSDaniel Kiper if (moksbstate == 1) 123a7012bdbSDaniel Kiper return efi_secureboot_mode_disabled; 124a7012bdbSDaniel Kiper 125a7012bdbSDaniel Kiper secure_boot_enabled: 126a7012bdbSDaniel Kiper pr_info("UEFI Secure Boot is enabled.\n"); 127a7012bdbSDaniel Kiper return efi_secureboot_mode_enabled; 128a7012bdbSDaniel Kiper } 129a7012bdbSDaniel Kiper 13072813bfbSRoger Pau Monne void __init xen_efi_init(struct boot_params *boot_params) 131c7341d6aSDaniel Kiper { 132c7341d6aSDaniel Kiper efi_system_table_t *efi_systab_xen; 133c7341d6aSDaniel Kiper 134c7341d6aSDaniel Kiper efi_systab_xen = xen_efi_probe(); 135c7341d6aSDaniel Kiper 136c7341d6aSDaniel Kiper if (efi_systab_xen == NULL) 137c7341d6aSDaniel Kiper return; 138c7341d6aSDaniel Kiper 13972813bfbSRoger Pau Monne strncpy((char *)&boot_params->efi_info.efi_loader_signature, "Xen", 14072813bfbSRoger Pau Monne sizeof(boot_params->efi_info.efi_loader_signature)); 14172813bfbSRoger Pau Monne boot_params->efi_info.efi_systab = (__u32)__pa(efi_systab_xen); 14272813bfbSRoger Pau Monne boot_params->efi_info.efi_systab_hi = (__u32)(__pa(efi_systab_xen) >> 32); 143c7341d6aSDaniel Kiper 14472813bfbSRoger Pau Monne boot_params->secure_boot = xen_efi_get_secureboot(); 145a7012bdbSDaniel Kiper 146c7341d6aSDaniel Kiper set_bit(EFI_BOOT, &efi.flags); 147c7341d6aSDaniel Kiper set_bit(EFI_PARAVIRT, &efi.flags); 148c7341d6aSDaniel Kiper set_bit(EFI_64BIT, &efi.flags); 149c7341d6aSDaniel Kiper } 150