1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * PCI-related functions used by the EFI stub on multiple 4 * architectures. 5 * 6 * Copyright 2019 Google, LLC 7 */ 8 9 #include <linux/efi.h> 10 #include <linux/pci.h> 11 12 #include <asm/efi.h> 13 14 #include "efistub.h" 15 16 void efi_pci_disable_bridge_busmaster(void) 17 { 18 efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; 19 efi_handle_t *pci_handle __free(efi_pool) = NULL; 20 unsigned long pci_handle_num; 21 efi_handle_t handle; 22 efi_status_t status; 23 u16 class, command; 24 25 status = efi_bs_call(locate_handle_buffer, EFI_LOCATE_BY_PROTOCOL, 26 &pci_proto, NULL, &pci_handle_num, &pci_handle); 27 if (status != EFI_SUCCESS) { 28 efi_err("Failed to locate PCI I/O handles\n"); 29 return; 30 } 31 32 for_each_efi_handle(handle, pci_handle, pci_handle_num) { 33 efi_pci_io_protocol_t *pci; 34 unsigned long segment_nr, bus_nr, device_nr, func_nr; 35 36 status = efi_bs_call(handle_protocol, handle, &pci_proto, 37 (void **)&pci); 38 if (status != EFI_SUCCESS) 39 continue; 40 41 /* 42 * Disregard devices living on bus 0 - these are not behind a 43 * bridge so no point in disconnecting them from their drivers. 44 */ 45 status = efi_call_proto(pci, get_location, &segment_nr, &bus_nr, 46 &device_nr, &func_nr); 47 if (status != EFI_SUCCESS || bus_nr == 0) 48 continue; 49 50 /* 51 * Don't disconnect VGA controllers so we don't risk losing 52 * access to the framebuffer. Drivers for true PCIe graphics 53 * controllers that are behind a PCIe root port do not use 54 * DMA to implement the GOP framebuffer anyway [although they 55 * may use it in their implementation of Gop->Blt()], and so 56 * disabling DMA in the PCI bridge should not interfere with 57 * normal operation of the device. 58 */ 59 status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16, 60 PCI_CLASS_DEVICE, 1, &class); 61 if (status != EFI_SUCCESS || class == PCI_CLASS_DISPLAY_VGA) 62 continue; 63 64 /* Disconnect this handle from all its drivers */ 65 efi_bs_call(disconnect_controller, handle, NULL, NULL); 66 } 67 68 for_each_efi_handle(handle, pci_handle, pci_handle_num) { 69 efi_pci_io_protocol_t *pci; 70 71 status = efi_bs_call(handle_protocol, handle, &pci_proto, 72 (void **)&pci); 73 if (status != EFI_SUCCESS || !pci) 74 continue; 75 76 status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16, 77 PCI_CLASS_DEVICE, 1, &class); 78 79 if (status != EFI_SUCCESS || class != PCI_CLASS_BRIDGE_PCI) 80 continue; 81 82 /* Disable busmastering */ 83 status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16, 84 PCI_COMMAND, 1, &command); 85 if (status != EFI_SUCCESS || !(command & PCI_COMMAND_MASTER)) 86 continue; 87 88 command &= ~PCI_COMMAND_MASTER; 89 status = efi_call_proto(pci, pci.write, EfiPciIoWidthUint16, 90 PCI_COMMAND, 1, &command); 91 if (status != EFI_SUCCESS) 92 efi_err("Failed to disable PCI busmastering\n"); 93 } 94 } 95