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 "efivar.h" 49 50 /* GUID for HFI1 variables in EFI */ 51 #define HFI1_EFIVAR_GUID EFI_GUID(0xc50a953e, 0xa8b2, 0x42a6, \ 52 0xbf, 0x89, 0xd3, 0x33, 0xa6, 0xe9, 0xe6, 0xd4) 53 /* largest EFI data size we expect */ 54 #define EFI_DATA_SIZE 4096 55 56 /* 57 * Read the named EFI variable. Return the size of the actual data in *size 58 * and a kmalloc'ed buffer in *return_data. The caller must free the 59 * data. It is guaranteed that *return_data will be NULL and *size = 0 60 * if this routine fails. 61 * 62 * Return 0 on success, -errno on failure. 63 */ 64 static int read_efi_var(const char *name, unsigned long *size, 65 void **return_data) 66 { 67 efi_status_t status; 68 efi_char16_t *uni_name; 69 efi_guid_t guid; 70 unsigned long temp_size; 71 void *temp_buffer; 72 void *data; 73 int i; 74 int ret; 75 76 /* set failure return values */ 77 *size = 0; 78 *return_data = NULL; 79 80 if (!efi_enabled(EFI_RUNTIME_SERVICES)) 81 return -EOPNOTSUPP; 82 83 uni_name = kcalloc(strlen(name) + 1, sizeof(efi_char16_t), GFP_KERNEL); 84 temp_buffer = kzalloc(EFI_DATA_SIZE, GFP_KERNEL); 85 86 if (!uni_name || !temp_buffer) { 87 ret = -ENOMEM; 88 goto fail; 89 } 90 91 /* input: the size of the buffer */ 92 temp_size = EFI_DATA_SIZE; 93 94 /* convert ASCII to unicode - it is a 1:1 mapping */ 95 for (i = 0; name[i]; i++) 96 uni_name[i] = name[i]; 97 98 /* need a variable for our GUID */ 99 guid = HFI1_EFIVAR_GUID; 100 101 /* call into EFI runtime services */ 102 status = efi.get_variable( 103 uni_name, 104 &guid, 105 NULL, 106 &temp_size, 107 temp_buffer); 108 109 /* 110 * It would be nice to call efi_status_to_err() here, but that 111 * is in the EFIVAR_FS code and may not be compiled in. 112 * However, even that is insufficient since it does not cover 113 * EFI_BUFFER_TOO_SMALL which could be an important return. 114 * For now, just split out succces or not found. 115 */ 116 ret = status == EFI_SUCCESS ? 0 : 117 status == EFI_NOT_FOUND ? -ENOENT : 118 -EINVAL; 119 if (ret) 120 goto fail; 121 122 /* 123 * We have successfully read the EFI variable into our 124 * temporary buffer. Now allocate a correctly sized 125 * buffer. 126 */ 127 data = kmemdup(temp_buffer, temp_size, GFP_KERNEL); 128 if (!data) { 129 ret = -ENOMEM; 130 goto fail; 131 } 132 133 *size = temp_size; 134 *return_data = data; 135 136 fail: 137 kfree(uni_name); 138 kfree(temp_buffer); 139 140 return ret; 141 } 142 143 /* 144 * Read an HFI1 EFI variable of the form: 145 * <PCIe address>-<kind> 146 * Return an kalloc'ed array and size of the data. 147 * 148 * Returns 0 on success, -errno on failure. 149 */ 150 int read_hfi1_efi_var(struct hfi1_devdata *dd, const char *kind, 151 unsigned long *size, void **return_data) 152 { 153 char name[64]; 154 155 /* create a common prefix */ 156 snprintf(name, sizeof(name), "%04x:%02x:%02x.%x-%s", 157 pci_domain_nr(dd->pcidev->bus), 158 dd->pcidev->bus->number, 159 PCI_SLOT(dd->pcidev->devfn), 160 PCI_FUNC(dd->pcidev->devfn), 161 kind); 162 163 return read_efi_var(name, size, return_data); 164 } 165