1 /* 2 * Copyright(c) 2015, 2016 Intel Corporation. 3 * 4 * This file is provided under a dual BSD/GPLv2 license. When using or 5 * redistributing this file, you may do so under either license. 6 * 7 * GPL LICENSE SUMMARY 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of version 2 of the GNU General Public License as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * BSD LICENSE 19 * 20 * Redistribution and use in source and binary forms, with or without 21 * modification, are permitted provided that the following conditions 22 * are met: 23 * 24 * - Redistributions of source code must retain the above copyright 25 * notice, this list of conditions and the following disclaimer. 26 * - Redistributions in binary form must reproduce the above copyright 27 * notice, this list of conditions and the following disclaimer in 28 * the documentation and/or other materials provided with the 29 * distribution. 30 * - Neither the name of Intel Corporation nor the names of its 31 * contributors may be used to endorse or promote products derived 32 * from this software without specific prior written permission. 33 * 34 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 35 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 36 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 37 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 38 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 39 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 40 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 41 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 42 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 43 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 44 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 45 * 46 */ 47 48 #include <linux/ctype.h> 49 #include "efivar.h" 50 51 /* GUID for HFI1 variables in EFI */ 52 #define HFI1_EFIVAR_GUID EFI_GUID(0xc50a953e, 0xa8b2, 0x42a6, \ 53 0xbf, 0x89, 0xd3, 0x33, 0xa6, 0xe9, 0xe6, 0xd4) 54 /* largest EFI data size we expect */ 55 #define EFI_DATA_SIZE 4096 56 57 /* 58 * Read the named EFI variable. Return the size of the actual data in *size 59 * and a kmalloc'ed buffer in *return_data. The caller must free the 60 * data. It is guaranteed that *return_data will be NULL and *size = 0 61 * if this routine fails. 62 * 63 * Return 0 on success, -errno on failure. 64 */ 65 static int read_efi_var(const char *name, unsigned long *size, 66 void **return_data) 67 { 68 efi_status_t status; 69 efi_char16_t *uni_name; 70 efi_guid_t guid; 71 unsigned long temp_size; 72 void *temp_buffer; 73 void *data; 74 int i; 75 int ret; 76 77 /* set failure return values */ 78 *size = 0; 79 *return_data = NULL; 80 81 if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) 82 return -EOPNOTSUPP; 83 84 uni_name = kcalloc(strlen(name) + 1, sizeof(efi_char16_t), GFP_KERNEL); 85 temp_buffer = kzalloc(EFI_DATA_SIZE, GFP_KERNEL); 86 87 if (!uni_name || !temp_buffer) { 88 ret = -ENOMEM; 89 goto fail; 90 } 91 92 /* input: the size of the buffer */ 93 temp_size = EFI_DATA_SIZE; 94 95 /* convert ASCII to unicode - it is a 1:1 mapping */ 96 for (i = 0; name[i]; i++) 97 uni_name[i] = name[i]; 98 99 /* need a variable for our GUID */ 100 guid = HFI1_EFIVAR_GUID; 101 102 /* call into EFI runtime services */ 103 status = efi.get_variable( 104 uni_name, 105 &guid, 106 NULL, 107 &temp_size, 108 temp_buffer); 109 110 /* 111 * It would be nice to call efi_status_to_err() here, but that 112 * is in the EFIVAR_FS code and may not be compiled in. 113 * However, even that is insufficient since it does not cover 114 * EFI_BUFFER_TOO_SMALL which could be an important return. 115 * For now, just split out succces or not found. 116 */ 117 ret = status == EFI_SUCCESS ? 0 : 118 status == EFI_NOT_FOUND ? -ENOENT : 119 -EINVAL; 120 if (ret) 121 goto fail; 122 123 /* 124 * We have successfully read the EFI variable into our 125 * temporary buffer. Now allocate a correctly sized 126 * buffer. 127 */ 128 data = kmemdup(temp_buffer, temp_size, GFP_KERNEL); 129 if (!data) { 130 ret = -ENOMEM; 131 goto fail; 132 } 133 134 *size = temp_size; 135 *return_data = data; 136 137 fail: 138 kfree(uni_name); 139 kfree(temp_buffer); 140 141 return ret; 142 } 143 144 /* 145 * Read an HFI1 EFI variable of the form: 146 * <PCIe address>-<kind> 147 * Return an kalloc'ed array and size of the data. 148 * 149 * Returns 0 on success, -errno on failure. 150 */ 151 int read_hfi1_efi_var(struct hfi1_devdata *dd, const char *kind, 152 unsigned long *size, void **return_data) 153 { 154 char prefix_name[64]; 155 char name[64]; 156 int result; 157 int i; 158 159 /* create a common prefix */ 160 snprintf(prefix_name, sizeof(prefix_name), "%04x:%02x:%02x.%x", 161 pci_domain_nr(dd->pcidev->bus), 162 dd->pcidev->bus->number, 163 PCI_SLOT(dd->pcidev->devfn), 164 PCI_FUNC(dd->pcidev->devfn)); 165 snprintf(name, sizeof(name), "%s-%s", prefix_name, kind); 166 result = read_efi_var(name, size, return_data); 167 168 /* 169 * If reading the lowercase EFI variable fail, read the uppercase 170 * variable. 171 */ 172 if (result) { 173 /* Converting to uppercase */ 174 for (i = 0; prefix_name[i]; i++) 175 if (isalpha(prefix_name[i])) 176 prefix_name[i] = toupper(prefix_name[i]); 177 snprintf(name, sizeof(name), "%s-%s", prefix_name, kind); 178 result = read_efi_var(name, size, return_data); 179 } 180 181 return result; 182 } 183