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