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 
efi_pci_disable_bridge_busmaster(void)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