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