]> git.proxmox.com Git - mirror_edk2.git/blame - ArmVirtPkg/VirtFdtDxe/VirtFdtDxe.c
ArmVirtPkg/VirtFdtDxe: remove timer DT node handling
[mirror_edk2.git] / ArmVirtPkg / VirtFdtDxe / VirtFdtDxe.c
CommitLineData
ad106932
AB
1/** @file\r
2* Device tree enumeration DXE driver for ARM Virtual Machines\r
3*\r
4* Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>\r
5*\r
6* This program and the accompanying materials are\r
7* licensed and made available under the terms and conditions of the BSD License\r
8* which accompanies this distribution. The full text of the license may be found at\r
9* http://opensource.org/licenses/bsd-license.php\r
10*\r
11* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13*\r
14**/\r
15\r
16#include <Library/BaseLib.h>\r
17#include <Library/DebugLib.h>\r
18#include <Library/UefiLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20#include <Library/UefiDriverEntryPoint.h>\r
21#include <Library/MemoryAllocationLib.h>\r
22#include <Library/UefiBootServicesTableLib.h>\r
23#include <Library/VirtioMmioDeviceLib.h>\r
24#include <Library/DevicePathLib.h>\r
25#include <Library/PcdLib.h>\r
26#include <Library/DxeServicesLib.h>\r
cc667df0 27#include <Library/HobLib.h>\r
ad106932 28#include <libfdt.h>\r
6abe83c3 29#include <Library/XenIoMmioLib.h>\r
ad106932
AB
30\r
31#include <Guid/Fdt.h>\r
73bb8e68 32#include <Guid/VirtioMmioTransport.h>\r
cc667df0 33#include <Guid/FdtHob.h>\r
ad106932
AB
34\r
35#pragma pack (1)\r
36typedef struct {\r
37 VENDOR_DEVICE_PATH Vendor;\r
38 UINT64 PhysBase;\r
39 EFI_DEVICE_PATH_PROTOCOL End;\r
40} VIRTIO_TRANSPORT_DEVICE_PATH;\r
41#pragma pack ()\r
42\r
43typedef enum {\r
44 PropertyTypeUnknown,\r
ad106932
AB
45 PropertyTypeRtc,\r
46 PropertyTypeVirtio,\r
47 PropertyTypeUart,\r
ad652d46 48 PropertyTypeFwCfg,\r
65bb13b0 49 PropertyTypePciHost,\r
6abe83c3 50 PropertyTypeXen,\r
ad106932
AB
51} PROPERTY_TYPE;\r
52\r
53typedef struct {\r
54 PROPERTY_TYPE Type;\r
65bb13b0 55 CHAR8 Compatible[32];\r
ad106932
AB
56} PROPERTY;\r
57\r
58STATIC CONST PROPERTY CompatibleProperties[] = {\r
65bb13b0
LE
59 { PropertyTypeRtc, "arm,pl031" },\r
60 { PropertyTypeVirtio, "virtio,mmio" },\r
61 { PropertyTypeUart, "arm,pl011" },\r
65bb13b0
LE
62 { PropertyTypeFwCfg, "qemu,fw-cfg-mmio" },\r
63 { PropertyTypePciHost, "pci-host-ecam-generic" },\r
6abe83c3 64 { PropertyTypeXen, "xen,xen" },\r
65bb13b0 65 { PropertyTypeUnknown, "" }\r
ad106932
AB
66};\r
67\r
ad106932
AB
68STATIC\r
69PROPERTY_TYPE\r
70GetTypeFromNode (\r
71 IN CONST CHAR8 *NodeType,\r
72 IN UINTN Size\r
73 )\r
74{\r
75 CONST CHAR8 *Compatible;\r
76 CONST PROPERTY *CompatibleProperty;\r
77\r
78 //\r
79 // A 'compatible' node may contain a sequence of NULL terminated\r
80 // compatible strings so check each one\r
81 //\r
82 for (Compatible = NodeType; Compatible < NodeType + Size && *Compatible;\r
83 Compatible += 1 + AsciiStrLen (Compatible)) {\r
84 for (CompatibleProperty = CompatibleProperties; CompatibleProperty->Compatible[0]; CompatibleProperty++) {\r
85 if (AsciiStrCmp (CompatibleProperty->Compatible, Compatible) == 0) {\r
86 return CompatibleProperty->Type;\r
87 }\r
88 }\r
89 }\r
90 return PropertyTypeUnknown;\r
91}\r
92\r
65bb13b0
LE
93//\r
94// We expect the "ranges" property of "pci-host-ecam-generic" to consist of\r
95// records like this.\r
96//\r
97#pragma pack (1)\r
98typedef struct {\r
99 UINT32 Type;\r
100 UINT64 ChildBase;\r
101 UINT64 CpuBase;\r
102 UINT64 Size;\r
103} DTB_PCI_HOST_RANGE_RECORD;\r
104#pragma pack ()\r
105\r
106#define DTB_PCI_HOST_RANGE_RELOCATABLE BIT31\r
107#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30\r
108#define DTB_PCI_HOST_RANGE_ALIASED BIT29\r
109#define DTB_PCI_HOST_RANGE_MMIO32 BIT25\r
110#define DTB_PCI_HOST_RANGE_MMIO64 (BIT25 | BIT24)\r
111#define DTB_PCI_HOST_RANGE_IO BIT24\r
112#define DTB_PCI_HOST_RANGE_TYPEMASK (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)\r
113\r
114/**\r
115 Process the device tree node describing the generic PCI host controller.\r
116\r
117 param[in] DeviceTreeBase Pointer to the device tree.\r
118\r
119 param[in] Node Offset of the device tree node whose "compatible"\r
120 property is "pci-host-ecam-generic".\r
121\r
122 param[in] RegProp Pointer to the "reg" property of Node. The caller\r
123 is responsible for ensuring that the size of the\r
124 property is 4 UINT32 cells.\r
125\r
126 @retval EFI_SUCCESS Parsing successful, properties parsed from Node\r
127 have been stored in dynamic PCDs.\r
128\r
129 @retval EFI_PROTOCOL_ERROR Parsing failed. PCDs are left unchanged.\r
130**/\r
131STATIC\r
132EFI_STATUS\r
133EFIAPI\r
134ProcessPciHost (\r
135 IN CONST VOID *DeviceTreeBase,\r
136 IN INT32 Node,\r
137 IN CONST VOID *RegProp\r
138 )\r
139{\r
140 UINT64 ConfigBase, ConfigSize;\r
141 CONST VOID *Prop;\r
142 INT32 Len;\r
143 UINT32 BusMin, BusMax;\r
144 UINT32 RecordIdx;\r
145 UINT64 IoBase, IoSize, IoTranslation;\r
146 UINT64 MmioBase, MmioSize, MmioTranslation;\r
147\r
148 //\r
149 // Fetch the ECAM window.\r
150 //\r
151 ConfigBase = fdt64_to_cpu (((CONST UINT64 *)RegProp)[0]);\r
152 ConfigSize = fdt64_to_cpu (((CONST UINT64 *)RegProp)[1]);\r
153\r
154 //\r
155 // Fetch the bus range (note: inclusive).\r
156 //\r
157 Prop = fdt_getprop (DeviceTreeBase, Node, "bus-range", &Len);\r
158 if (Prop == NULL || Len != 2 * sizeof(UINT32)) {\r
159 DEBUG ((EFI_D_ERROR, "%a: 'bus-range' not found or invalid\n",\r
160 __FUNCTION__));\r
161 return EFI_PROTOCOL_ERROR;\r
162 }\r
163 BusMin = fdt32_to_cpu (((CONST UINT32 *)Prop)[0]);\r
164 BusMax = fdt32_to_cpu (((CONST UINT32 *)Prop)[1]);\r
165\r
166 //\r
167 // Sanity check: the config space must accommodate all 4K register bytes of\r
168 // all 8 functions of all 32 devices of all buses.\r
169 //\r
170 if (BusMax < BusMin || BusMax - BusMin == MAX_UINT32 ||\r
171 DivU64x32 (ConfigSize, SIZE_4KB * 8 * 32) < BusMax - BusMin + 1) {\r
172 DEBUG ((EFI_D_ERROR, "%a: invalid 'bus-range' and/or 'reg'\n",\r
173 __FUNCTION__));\r
174 return EFI_PROTOCOL_ERROR;\r
175 }\r
176\r
177 //\r
178 // Iterate over "ranges".\r
179 //\r
180 Prop = fdt_getprop (DeviceTreeBase, Node, "ranges", &Len);\r
181 if (Prop == NULL || Len == 0 ||\r
182 Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0) {\r
183 DEBUG ((EFI_D_ERROR, "%a: 'ranges' not found or invalid\n", __FUNCTION__));\r
184 return EFI_PROTOCOL_ERROR;\r
185 }\r
186\r
187 //\r
188 // IoBase, IoTranslation, MmioBase and MmioTranslation are initialized only\r
189 // in order to suppress '-Werror=maybe-uninitialized' warnings *incorrectly*\r
190 // emitted by some gcc versions.\r
191 //\r
192 IoBase = 0;\r
193 IoTranslation = 0;\r
194 MmioBase = 0;\r
195 MmioTranslation = 0;\r
196\r
197 //\r
198 // IoSize and MmioSize are initialized to zero because the logic below\r
199 // requires it.\r
200 //\r
201 IoSize = 0;\r
202 MmioSize = 0;\r
203 for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD);\r
204 ++RecordIdx) {\r
205 CONST DTB_PCI_HOST_RANGE_RECORD *Record;\r
206\r
207 Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx;\r
208 switch (fdt32_to_cpu (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK) {\r
209 case DTB_PCI_HOST_RANGE_IO:\r
210 IoBase = fdt64_to_cpu (Record->ChildBase);\r
211 IoSize = fdt64_to_cpu (Record->Size);\r
212 IoTranslation = fdt64_to_cpu (Record->CpuBase) - IoBase;\r
213 break;\r
214\r
215 case DTB_PCI_HOST_RANGE_MMIO32:\r
216 MmioBase = fdt64_to_cpu (Record->ChildBase);\r
217 MmioSize = fdt64_to_cpu (Record->Size);\r
218 MmioTranslation = fdt64_to_cpu (Record->CpuBase) - MmioBase;\r
219\r
220 if (MmioBase > MAX_UINT32 || MmioSize > MAX_UINT32 ||\r
221 MmioBase + MmioSize > SIZE_4GB) {\r
222 DEBUG ((EFI_D_ERROR, "%a: MMIO32 space invalid\n", __FUNCTION__));\r
223 return EFI_PROTOCOL_ERROR;\r
224 }\r
225\r
226 if (MmioTranslation != 0) {\r
227 DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO32 translation "\r
228 "0x%Lx\n", __FUNCTION__, MmioTranslation));\r
229 return EFI_UNSUPPORTED;\r
230 }\r
231\r
232 break;\r
233 }\r
234 }\r
235 if (IoSize == 0 || MmioSize == 0) {\r
236 DEBUG ((EFI_D_ERROR, "%a: %a space empty\n", __FUNCTION__,\r
237 (IoSize == 0) ? "IO" : "MMIO32"));\r
238 return EFI_PROTOCOL_ERROR;\r
239 }\r
240\r
241 PcdSet64 (PcdPciExpressBaseAddress, ConfigBase);\r
242\r
243 PcdSet32 (PcdPciBusMin, BusMin);\r
244 PcdSet32 (PcdPciBusMax, BusMax);\r
245\r
246 PcdSet64 (PcdPciIoBase, IoBase);\r
247 PcdSet64 (PcdPciIoSize, IoSize);\r
248 PcdSet64 (PcdPciIoTranslation, IoTranslation);\r
249\r
250 PcdSet32 (PcdPciMmio32Base, (UINT32)MmioBase);\r
251 PcdSet32 (PcdPciMmio32Size, (UINT32)MmioSize);\r
252\r
253 PcdSetBool (PcdPciDisableBusEnumeration, FALSE);\r
254\r
255 DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "\r
256 "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__, ConfigBase,\r
257 ConfigSize, BusMin, BusMax, IoBase, IoSize, IoTranslation, MmioBase,\r
258 MmioSize, MmioTranslation));\r
259 return EFI_SUCCESS;\r
260}\r
261\r
262\r
ad106932
AB
263EFI_STATUS\r
264EFIAPI\r
265InitializeVirtFdtDxe (\r
266 IN EFI_HANDLE ImageHandle,\r
267 IN EFI_SYSTEM_TABLE *SystemTable\r
268 )\r
269{\r
cc667df0 270 VOID *Hob;\r
ad106932
AB
271 VOID *DeviceTreeBase;\r
272 INT32 Node, Prev;\r
273 INT32 RtcNode;\r
274 EFI_STATUS Status;\r
275 CONST CHAR8 *Type;\r
276 INT32 Len;\r
277 PROPERTY_TYPE PropType;\r
278 CONST VOID *RegProp;\r
279 VIRTIO_TRANSPORT_DEVICE_PATH *DevicePath;\r
280 EFI_HANDLE Handle;\r
281 UINT64 RegBase;\r
ad652d46
LE
282 UINT64 FwCfgSelectorAddress;\r
283 UINT64 FwCfgSelectorSize;\r
284 UINT64 FwCfgDataAddress;\r
285 UINT64 FwCfgDataSize;\r
50b91449
LE
286 UINT64 FwCfgDmaAddress;\r
287 UINT64 FwCfgDmaSize;\r
8b816c62 288 BOOLEAN HavePci;\r
ad106932 289\r
cc667df0
AB
290 Hob = GetFirstGuidHob(&gFdtHobGuid);\r
291 if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) {\r
292 return EFI_NOT_FOUND;\r
293 }\r
294 DeviceTreeBase = (VOID *)(UINTN)*(UINT64 *)GET_GUID_HOB_DATA (Hob);\r
ad106932
AB
295\r
296 if (fdt_check_header (DeviceTreeBase) != 0) {\r
297 DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%p\n", __FUNCTION__, DeviceTreeBase));\r
298 return EFI_NOT_FOUND;\r
299 }\r
300\r
ad106932
AB
301 DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, DeviceTreeBase));\r
302\r
303 RtcNode = -1;\r
8b816c62 304 HavePci = FALSE;\r
ad106932
AB
305 //\r
306 // Now enumerate the nodes and install peripherals that we are interested in,\r
307 // i.e., GIC, RTC and virtio MMIO nodes\r
308 //\r
309 for (Prev = 0;; Prev = Node) {\r
310 Node = fdt_next_node (DeviceTreeBase, Prev, NULL);\r
311 if (Node < 0) {\r
312 break;\r
313 }\r
314\r
315 Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);\r
316 if (Type == NULL) {\r
317 continue;\r
318 }\r
319\r
320 PropType = GetTypeFromNode (Type, Len);\r
321 if (PropType == PropertyTypeUnknown) {\r
322 continue;\r
323 }\r
324\r
325 //\r
326 // Get the 'reg' property of this node. For now, we will assume\r
327 // 8 byte quantities for base and size, respectively.\r
328 // TODO use #cells root properties instead\r
329 //\r
330 RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);\r
479d5c41 331 ASSERT (RegProp != NULL);\r
ad106932
AB
332\r
333 switch (PropType) {\r
65bb13b0
LE
334 case PropertyTypePciHost:\r
335 ASSERT (Len == 2 * sizeof (UINT64));\r
336 Status = ProcessPciHost (DeviceTreeBase, Node, RegProp);\r
337 ASSERT_EFI_ERROR (Status);\r
8b816c62 338 HavePci = TRUE;\r
65bb13b0
LE
339 break;\r
340\r
ad652d46
LE
341 case PropertyTypeFwCfg:\r
342 ASSERT (Len == 2 * sizeof (UINT64));\r
343\r
344 FwCfgDataAddress = fdt64_to_cpu (((UINT64 *)RegProp)[0]);\r
345 FwCfgDataSize = 8;\r
346 FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize;\r
347 FwCfgSelectorSize = 2;\r
348\r
349 //\r
350 // The following ASSERT()s express\r
351 //\r
352 // Address + Size - 1 <= MAX_UINTN\r
353 //\r
354 // for both registers, that is, that the last byte in each MMIO range is\r
355 // expressible as a MAX_UINTN. The form below is mathematically\r
356 // equivalent, and it also prevents any unsigned overflow before the\r
357 // comparison.\r
358 //\r
359 ASSERT (FwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1);\r
360 ASSERT (FwCfgDataAddress <= MAX_UINTN - FwCfgDataSize + 1);\r
361\r
362 PcdSet64 (PcdFwCfgSelectorAddress, FwCfgSelectorAddress);\r
363 PcdSet64 (PcdFwCfgDataAddress, FwCfgDataAddress);\r
364\r
365 DEBUG ((EFI_D_INFO, "Found FwCfg @ 0x%Lx/0x%Lx\n", FwCfgSelectorAddress,\r
366 FwCfgDataAddress));\r
50b91449
LE
367\r
368 if (fdt64_to_cpu (((UINT64 *)RegProp)[1]) >= 0x18) {\r
369 FwCfgDmaAddress = FwCfgDataAddress + 0x10;\r
370 FwCfgDmaSize = 0x08;\r
371\r
372 //\r
373 // See explanation above.\r
374 //\r
375 ASSERT (FwCfgDmaAddress <= MAX_UINTN - FwCfgDmaSize + 1);\r
376\r
377 PcdSet64 (PcdFwCfgDmaAddress, FwCfgDmaAddress);\r
378 DEBUG ((EFI_D_INFO, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress));\r
379 }\r
ad652d46
LE
380 break;\r
381\r
ad106932
AB
382 case PropertyTypeVirtio:\r
383 ASSERT (Len == 16);\r
384 //\r
385 // Create a unique device path for this transport on the fly\r
386 //\r
387 RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);\r
388 DevicePath = (VIRTIO_TRANSPORT_DEVICE_PATH *)CreateDeviceNode (\r
389 HARDWARE_DEVICE_PATH,\r
390 HW_VENDOR_DP,\r
391 sizeof (VIRTIO_TRANSPORT_DEVICE_PATH));\r
392 if (DevicePath == NULL) {\r
393 DEBUG ((EFI_D_ERROR, "%a: Out of memory\n", __FUNCTION__));\r
394 break;\r
395 }\r
396\r
73bb8e68
LE
397 CopyMem (&DevicePath->Vendor.Guid, &gVirtioMmioTransportGuid,\r
398 sizeof (EFI_GUID));\r
ad106932
AB
399 DevicePath->PhysBase = RegBase;\r
400 SetDevicePathNodeLength (&DevicePath->Vendor,\r
401 sizeof (*DevicePath) - sizeof (DevicePath->End));\r
402 SetDevicePathEndNode (&DevicePath->End);\r
403\r
404 Handle = NULL;\r
405 Status = gBS->InstallProtocolInterface (&Handle,\r
406 &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,\r
407 DevicePath);\r
408 if (EFI_ERROR (Status)) {\r
409 DEBUG ((EFI_D_ERROR, "%a: Failed to install the EFI_DEVICE_PATH "\r
410 "protocol on a new handle (Status == %r)\n",\r
411 __FUNCTION__, Status));\r
412 FreePool (DevicePath);\r
413 break;\r
414 }\r
415\r
416 Status = VirtioMmioInstallDevice (RegBase, Handle);\r
417 if (EFI_ERROR (Status)) {\r
418 DEBUG ((EFI_D_ERROR, "%a: Failed to install VirtIO transport @ 0x%Lx "\r
419 "on handle %p (Status == %r)\n", __FUNCTION__, RegBase,\r
420 Handle, Status));\r
421\r
422 Status = gBS->UninstallProtocolInterface (Handle,\r
423 &gEfiDevicePathProtocolGuid, DevicePath);\r
424 ASSERT_EFI_ERROR (Status);\r
425 FreePool (DevicePath);\r
426 }\r
427 break;\r
428\r
ad106932
AB
429 case PropertyTypeRtc:\r
430 ASSERT (Len == 16);\r
431\r
432 RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);\r
433 ASSERT (RegBase < MAX_UINT32);\r
434\r
435 PcdSet32 (PcdPL031RtcBase, (UINT32)RegBase);\r
436\r
437 DEBUG ((EFI_D_INFO, "Found PL031 RTC @ 0x%Lx\n", RegBase));\r
438 RtcNode = Node;\r
439 break;\r
440\r
6abe83c3
AB
441 case PropertyTypeXen:\r
442 ASSERT (Len == 16);\r
443\r
444 //\r
445 // Retrieve the reg base from this node and wire it up to the\r
446 // MMIO flavor of the XenBus root device I/O protocol\r
447 //\r
448 RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]);\r
449 Handle = NULL;\r
450 Status = XenIoMmioInstall (&Handle, RegBase);\r
451 if (EFI_ERROR (Status)) {\r
452 DEBUG ((EFI_D_ERROR, "%a: XenIoMmioInstall () failed on a new handle "\r
453 "(Status == %r)\n", __FUNCTION__, Status));\r
454 break;\r
455 }\r
456\r
457 DEBUG ((EFI_D_INFO, "Found Xen node with Grant table @ 0x%Lx\n", RegBase));\r
458\r
459 break;\r
460\r
ad106932
AB
461 default:\r
462 break;\r
463 }\r
464 }\r
465\r
7a63d291
AB
466 if (!FeaturePcdGet (PcdPureAcpiBoot)) {\r
467 //\r
468 // Only install the FDT as a configuration table if we want to leave it up\r
469 // to the OS to decide whether it prefers ACPI over DT.\r
8b816c62 470 //\r
7a63d291
AB
471 Status = gBS->InstallConfigurationTable (&gFdtTableGuid, DeviceTreeBase);\r
472 ASSERT_EFI_ERROR (Status);\r
473\r
8b816c62 474 //\r
7a63d291
AB
475 // UEFI takes ownership of the RTC hardware, and exposes its functionality\r
476 // through the UEFI Runtime Services GetTime, SetTime, etc. This means we\r
477 // need to disable it in the device tree to prevent the OS from attaching its\r
478 // device driver as well.\r
8b816c62 479 //\r
7a63d291
AB
480 if ((RtcNode != -1) &&\r
481 fdt_setprop_string (DeviceTreeBase, RtcNode, "status",\r
482 "disabled") != 0) {\r
483 DEBUG ((EFI_D_WARN, "Failed to set PL031 status to 'disabled'\n"));\r
8b816c62 484 }\r
7a63d291
AB
485\r
486 if (HavePci) {\r
487 //\r
488 // Set the /chosen/linux,pci-probe-only property to 1, so that the PCI\r
489 // setup we will perform in the firmware is honored by the Linux OS,\r
490 // rather than torn down and done from scratch. This is generally a more\r
491 // sensible approach, and aligns with what ACPI based OSes do in general.\r
492 //\r
493 // In case we are exposing an emulated VGA PCI device to the guest, which\r
494 // may subsequently get exposed via the Graphics Output protocol and\r
495 // driven as an efifb by Linux, we need this setting to prevent the\r
496 // framebuffer from becoming unresponsive.\r
497 //\r
498 Node = fdt_path_offset (DeviceTreeBase, "/chosen");\r
499 if (Node < 0) {\r
500 Node = fdt_add_subnode (DeviceTreeBase, 0, "/chosen");\r
501 }\r
502 if (Node < 0 ||\r
503 fdt_setprop_u32 (DeviceTreeBase, Node, "linux,pci-probe-only", 1) < 0) {\r
504 DEBUG ((EFI_D_WARN, "Failed to set /chosen/linux,pci-probe-only property\n"));\r
505 }\r
8b816c62
AB
506 }\r
507 }\r
ad106932
AB
508 return EFI_SUCCESS;\r
509}\r