efivar.c (3360B)
1// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause 2/* 3 * Copyright(c) 2015, 2016 Intel Corporation. 4 */ 5 6#include <linux/string.h> 7#include <linux/string_helpers.h> 8 9#include "efivar.h" 10 11/* GUID for HFI1 variables in EFI */ 12#define HFI1_EFIVAR_GUID EFI_GUID(0xc50a953e, 0xa8b2, 0x42a6, \ 13 0xbf, 0x89, 0xd3, 0x33, 0xa6, 0xe9, 0xe6, 0xd4) 14/* largest EFI data size we expect */ 15#define EFI_DATA_SIZE 4096 16 17/* 18 * Read the named EFI variable. Return the size of the actual data in *size 19 * and a kmalloc'ed buffer in *return_data. The caller must free the 20 * data. It is guaranteed that *return_data will be NULL and *size = 0 21 * if this routine fails. 22 * 23 * Return 0 on success, -errno on failure. 24 */ 25static int read_efi_var(const char *name, unsigned long *size, 26 void **return_data) 27{ 28 efi_status_t status; 29 efi_char16_t *uni_name; 30 efi_guid_t guid; 31 unsigned long temp_size; 32 void *temp_buffer; 33 void *data; 34 int i; 35 int ret; 36 37 /* set failure return values */ 38 *size = 0; 39 *return_data = NULL; 40 41 if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) 42 return -EOPNOTSUPP; 43 44 uni_name = kcalloc(strlen(name) + 1, sizeof(efi_char16_t), GFP_KERNEL); 45 temp_buffer = kzalloc(EFI_DATA_SIZE, GFP_KERNEL); 46 47 if (!uni_name || !temp_buffer) { 48 ret = -ENOMEM; 49 goto fail; 50 } 51 52 /* input: the size of the buffer */ 53 temp_size = EFI_DATA_SIZE; 54 55 /* convert ASCII to unicode - it is a 1:1 mapping */ 56 for (i = 0; name[i]; i++) 57 uni_name[i] = name[i]; 58 59 /* need a variable for our GUID */ 60 guid = HFI1_EFIVAR_GUID; 61 62 /* call into EFI runtime services */ 63 status = efi.get_variable( 64 uni_name, 65 &guid, 66 NULL, 67 &temp_size, 68 temp_buffer); 69 70 /* 71 * It would be nice to call efi_status_to_err() here, but that 72 * is in the EFIVAR_FS code and may not be compiled in. 73 * However, even that is insufficient since it does not cover 74 * EFI_BUFFER_TOO_SMALL which could be an important return. 75 * For now, just split out success or not found. 76 */ 77 ret = status == EFI_SUCCESS ? 0 : 78 status == EFI_NOT_FOUND ? -ENOENT : 79 -EINVAL; 80 if (ret) 81 goto fail; 82 83 /* 84 * We have successfully read the EFI variable into our 85 * temporary buffer. Now allocate a correctly sized 86 * buffer. 87 */ 88 data = kmemdup(temp_buffer, temp_size, GFP_KERNEL); 89 if (!data) { 90 ret = -ENOMEM; 91 goto fail; 92 } 93 94 *size = temp_size; 95 *return_data = data; 96 97fail: 98 kfree(uni_name); 99 kfree(temp_buffer); 100 101 return ret; 102} 103 104/* 105 * Read an HFI1 EFI variable of the form: 106 * <PCIe address>-<kind> 107 * Return an kalloc'ed array and size of the data. 108 * 109 * Returns 0 on success, -errno on failure. 110 */ 111int read_hfi1_efi_var(struct hfi1_devdata *dd, const char *kind, 112 unsigned long *size, void **return_data) 113{ 114 char prefix_name[64]; 115 char name[64]; 116 int result; 117 118 /* create a common prefix */ 119 snprintf(prefix_name, sizeof(prefix_name), "%04x:%02x:%02x.%x", 120 pci_domain_nr(dd->pcidev->bus), 121 dd->pcidev->bus->number, 122 PCI_SLOT(dd->pcidev->devfn), 123 PCI_FUNC(dd->pcidev->devfn)); 124 snprintf(name, sizeof(name), "%s-%s", prefix_name, kind); 125 result = read_efi_var(name, size, return_data); 126 127 /* 128 * If reading the lowercase EFI variable fail, read the uppercase 129 * variable. 130 */ 131 if (result) { 132 string_upper(prefix_name, prefix_name); 133 snprintf(name, sizeof(name), "%s-%s", prefix_name, kind); 134 result = read_efi_var(name, size, return_data); 135 } 136 137 return result; 138}