2 * Device tree enumeration DXE driver for ARM Virtual Machines
4 * Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
6 * This program and the accompanying materials are
7 * licensed and made available under the terms and conditions of the BSD License
8 * which accompanies this distribution. The full text of the license may be found at
9 * http://opensource.org/licenses/bsd-license.php
11 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/BaseLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/UefiLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/UefiDriverEntryPoint.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/VirtioMmioDeviceLib.h>
24 #include <Library/DevicePathLib.h>
25 #include <Library/PcdLib.h>
26 #include <Library/DxeServicesLib.h>
27 #include <Library/HobLib.h>
29 #include <Library/XenIoMmioLib.h>
32 #include <Guid/VirtioMmioTransport.h>
33 #include <Guid/FdtHob.h>
37 VENDOR_DEVICE_PATH Vendor
;
39 EFI_DEVICE_PATH_PROTOCOL End
;
40 } VIRTIO_TRANSPORT_DEVICE_PATH
;
62 STATIC CONST PROPERTY CompatibleProperties
[] = {
63 { PropertyTypeGic
, "arm,cortex-a15-gic" },
64 { PropertyTypeRtc
, "arm,pl031" },
65 { PropertyTypeVirtio
, "virtio,mmio" },
66 { PropertyTypeUart
, "arm,pl011" },
67 { PropertyTypeTimer
, "arm,armv7-timer" },
68 { PropertyTypeTimer
, "arm,armv8-timer" },
69 { PropertyTypePsci
, "arm,psci-0.2" },
70 { PropertyTypeFwCfg
, "qemu,fw-cfg-mmio" },
71 { PropertyTypePciHost
, "pci-host-ecam-generic" },
72 { PropertyTypeGicV3
, "arm,gic-v3" },
73 { PropertyTypeXen
, "xen,xen" },
74 { PropertyTypeUnknown
, "" }
86 IN CONST CHAR8
*NodeType
,
90 CONST CHAR8
*Compatible
;
91 CONST PROPERTY
*CompatibleProperty
;
94 // A 'compatible' node may contain a sequence of NULL terminated
95 // compatible strings so check each one
97 for (Compatible
= NodeType
; Compatible
< NodeType
+ Size
&& *Compatible
;
98 Compatible
+= 1 + AsciiStrLen (Compatible
)) {
99 for (CompatibleProperty
= CompatibleProperties
; CompatibleProperty
->Compatible
[0]; CompatibleProperty
++) {
100 if (AsciiStrCmp (CompatibleProperty
->Compatible
, Compatible
) == 0) {
101 return CompatibleProperty
->Type
;
105 return PropertyTypeUnknown
;
109 // We expect the "ranges" property of "pci-host-ecam-generic" to consist of
110 // records like this.
118 } DTB_PCI_HOST_RANGE_RECORD
;
121 #define DTB_PCI_HOST_RANGE_RELOCATABLE BIT31
122 #define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30
123 #define DTB_PCI_HOST_RANGE_ALIASED BIT29
124 #define DTB_PCI_HOST_RANGE_MMIO32 BIT25
125 #define DTB_PCI_HOST_RANGE_MMIO64 (BIT25 | BIT24)
126 #define DTB_PCI_HOST_RANGE_IO BIT24
127 #define DTB_PCI_HOST_RANGE_TYPEMASK (BIT31 | BIT30 | BIT29 | BIT25 | BIT24)
130 Process the device tree node describing the generic PCI host controller.
132 param[in] DeviceTreeBase Pointer to the device tree.
134 param[in] Node Offset of the device tree node whose "compatible"
135 property is "pci-host-ecam-generic".
137 param[in] RegProp Pointer to the "reg" property of Node. The caller
138 is responsible for ensuring that the size of the
139 property is 4 UINT32 cells.
141 @retval EFI_SUCCESS Parsing successful, properties parsed from Node
142 have been stored in dynamic PCDs.
144 @retval EFI_PROTOCOL_ERROR Parsing failed. PCDs are left unchanged.
150 IN CONST VOID
*DeviceTreeBase
,
152 IN CONST VOID
*RegProp
155 UINT64 ConfigBase
, ConfigSize
;
158 UINT32 BusMin
, BusMax
;
160 UINT64 IoBase
, IoSize
, IoTranslation
;
161 UINT64 MmioBase
, MmioSize
, MmioTranslation
;
164 // Fetch the ECAM window.
166 ConfigBase
= fdt64_to_cpu (((CONST UINT64
*)RegProp
)[0]);
167 ConfigSize
= fdt64_to_cpu (((CONST UINT64
*)RegProp
)[1]);
170 // Fetch the bus range (note: inclusive).
172 Prop
= fdt_getprop (DeviceTreeBase
, Node
, "bus-range", &Len
);
173 if (Prop
== NULL
|| Len
!= 2 * sizeof(UINT32
)) {
174 DEBUG ((EFI_D_ERROR
, "%a: 'bus-range' not found or invalid\n",
176 return EFI_PROTOCOL_ERROR
;
178 BusMin
= fdt32_to_cpu (((CONST UINT32
*)Prop
)[0]);
179 BusMax
= fdt32_to_cpu (((CONST UINT32
*)Prop
)[1]);
182 // Sanity check: the config space must accommodate all 4K register bytes of
183 // all 8 functions of all 32 devices of all buses.
185 if (BusMax
< BusMin
|| BusMax
- BusMin
== MAX_UINT32
||
186 DivU64x32 (ConfigSize
, SIZE_4KB
* 8 * 32) < BusMax
- BusMin
+ 1) {
187 DEBUG ((EFI_D_ERROR
, "%a: invalid 'bus-range' and/or 'reg'\n",
189 return EFI_PROTOCOL_ERROR
;
193 // Iterate over "ranges".
195 Prop
= fdt_getprop (DeviceTreeBase
, Node
, "ranges", &Len
);
196 if (Prop
== NULL
|| Len
== 0 ||
197 Len
% sizeof (DTB_PCI_HOST_RANGE_RECORD
) != 0) {
198 DEBUG ((EFI_D_ERROR
, "%a: 'ranges' not found or invalid\n", __FUNCTION__
));
199 return EFI_PROTOCOL_ERROR
;
203 // IoBase, IoTranslation, MmioBase and MmioTranslation are initialized only
204 // in order to suppress '-Werror=maybe-uninitialized' warnings *incorrectly*
205 // emitted by some gcc versions.
213 // IoSize and MmioSize are initialized to zero because the logic below
218 for (RecordIdx
= 0; RecordIdx
< Len
/ sizeof (DTB_PCI_HOST_RANGE_RECORD
);
220 CONST DTB_PCI_HOST_RANGE_RECORD
*Record
;
222 Record
= (CONST DTB_PCI_HOST_RANGE_RECORD
*)Prop
+ RecordIdx
;
223 switch (fdt32_to_cpu (Record
->Type
) & DTB_PCI_HOST_RANGE_TYPEMASK
) {
224 case DTB_PCI_HOST_RANGE_IO
:
225 IoBase
= fdt64_to_cpu (Record
->ChildBase
);
226 IoSize
= fdt64_to_cpu (Record
->Size
);
227 IoTranslation
= fdt64_to_cpu (Record
->CpuBase
) - IoBase
;
230 case DTB_PCI_HOST_RANGE_MMIO32
:
231 MmioBase
= fdt64_to_cpu (Record
->ChildBase
);
232 MmioSize
= fdt64_to_cpu (Record
->Size
);
233 MmioTranslation
= fdt64_to_cpu (Record
->CpuBase
) - MmioBase
;
235 if (MmioBase
> MAX_UINT32
|| MmioSize
> MAX_UINT32
||
236 MmioBase
+ MmioSize
> SIZE_4GB
) {
237 DEBUG ((EFI_D_ERROR
, "%a: MMIO32 space invalid\n", __FUNCTION__
));
238 return EFI_PROTOCOL_ERROR
;
241 if (MmioTranslation
!= 0) {
242 DEBUG ((EFI_D_ERROR
, "%a: unsupported nonzero MMIO32 translation "
243 "0x%Lx\n", __FUNCTION__
, MmioTranslation
));
244 return EFI_UNSUPPORTED
;
250 if (IoSize
== 0 || MmioSize
== 0) {
251 DEBUG ((EFI_D_ERROR
, "%a: %a space empty\n", __FUNCTION__
,
252 (IoSize
== 0) ? "IO" : "MMIO32"));
253 return EFI_PROTOCOL_ERROR
;
256 PcdSet64 (PcdPciExpressBaseAddress
, ConfigBase
);
258 PcdSet32 (PcdPciBusMin
, BusMin
);
259 PcdSet32 (PcdPciBusMax
, BusMax
);
261 PcdSet64 (PcdPciIoBase
, IoBase
);
262 PcdSet64 (PcdPciIoSize
, IoSize
);
263 PcdSet64 (PcdPciIoTranslation
, IoTranslation
);
265 PcdSet32 (PcdPciMmio32Base
, (UINT32
)MmioBase
);
266 PcdSet32 (PcdPciMmio32Size
, (UINT32
)MmioSize
);
268 PcdSetBool (PcdPciDisableBusEnumeration
, FALSE
);
270 DEBUG ((EFI_D_INFO
, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] "
271 "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__
, ConfigBase
,
272 ConfigSize
, BusMin
, BusMax
, IoBase
, IoSize
, IoTranslation
, MmioBase
,
273 MmioSize
, MmioTranslation
));
280 InitializeVirtFdtDxe (
281 IN EFI_HANDLE ImageHandle
,
282 IN EFI_SYSTEM_TABLE
*SystemTable
286 VOID
*DeviceTreeBase
;
292 PROPERTY_TYPE PropType
;
294 VIRTIO_TRANSPORT_DEVICE_PATH
*DevicePath
;
297 UINT64 DistBase
, CpuBase
, RedistBase
;
298 CONST INTERRUPT_PROPERTY
*InterruptProp
;
299 INT32 SecIntrNum
, IntrNum
, VirtIntrNum
, HypIntrNum
;
300 CONST CHAR8
*PsciMethod
;
301 UINT64 FwCfgSelectorAddress
;
302 UINT64 FwCfgSelectorSize
;
303 UINT64 FwCfgDataAddress
;
304 UINT64 FwCfgDataSize
;
306 Hob
= GetFirstGuidHob(&gFdtHobGuid
);
307 if (Hob
== NULL
|| GET_GUID_HOB_DATA_SIZE (Hob
) != sizeof (UINT64
)) {
308 return EFI_NOT_FOUND
;
310 DeviceTreeBase
= (VOID
*)(UINTN
)*(UINT64
*)GET_GUID_HOB_DATA (Hob
);
312 if (fdt_check_header (DeviceTreeBase
) != 0) {
313 DEBUG ((EFI_D_ERROR
, "%a: No DTB found @ 0x%p\n", __FUNCTION__
, DeviceTreeBase
));
314 return EFI_NOT_FOUND
;
317 Status
= gBS
->InstallConfigurationTable (&gFdtTableGuid
, DeviceTreeBase
);
318 ASSERT_EFI_ERROR (Status
);
320 DEBUG ((EFI_D_INFO
, "%a: DTB @ 0x%p\n", __FUNCTION__
, DeviceTreeBase
));
324 // Now enumerate the nodes and install peripherals that we are interested in,
325 // i.e., GIC, RTC and virtio MMIO nodes
327 for (Prev
= 0;; Prev
= Node
) {
328 Node
= fdt_next_node (DeviceTreeBase
, Prev
, NULL
);
333 Type
= fdt_getprop (DeviceTreeBase
, Node
, "compatible", &Len
);
338 PropType
= GetTypeFromNode (Type
, Len
);
339 if (PropType
== PropertyTypeUnknown
) {
344 // Get the 'reg' property of this node. For now, we will assume
345 // 8 byte quantities for base and size, respectively.
346 // TODO use #cells root properties instead
348 RegProp
= fdt_getprop (DeviceTreeBase
, Node
, "reg", &Len
);
349 ASSERT ((RegProp
!= NULL
) || (PropType
== PropertyTypeTimer
) ||
350 (PropType
== PropertyTypePsci
));
353 case PropertyTypePciHost
:
354 ASSERT (Len
== 2 * sizeof (UINT64
));
355 Status
= ProcessPciHost (DeviceTreeBase
, Node
, RegProp
);
356 ASSERT_EFI_ERROR (Status
);
359 case PropertyTypeFwCfg
:
360 ASSERT (Len
== 2 * sizeof (UINT64
));
362 FwCfgDataAddress
= fdt64_to_cpu (((UINT64
*)RegProp
)[0]);
364 FwCfgSelectorAddress
= FwCfgDataAddress
+ FwCfgDataSize
;
365 FwCfgSelectorSize
= 2;
368 // The following ASSERT()s express
370 // Address + Size - 1 <= MAX_UINTN
372 // for both registers, that is, that the last byte in each MMIO range is
373 // expressible as a MAX_UINTN. The form below is mathematically
374 // equivalent, and it also prevents any unsigned overflow before the
377 ASSERT (FwCfgSelectorAddress
<= MAX_UINTN
- FwCfgSelectorSize
+ 1);
378 ASSERT (FwCfgDataAddress
<= MAX_UINTN
- FwCfgDataSize
+ 1);
380 PcdSet64 (PcdFwCfgSelectorAddress
, FwCfgSelectorAddress
);
381 PcdSet64 (PcdFwCfgDataAddress
, FwCfgDataAddress
);
383 DEBUG ((EFI_D_INFO
, "Found FwCfg @ 0x%Lx/0x%Lx\n", FwCfgSelectorAddress
,
387 case PropertyTypeVirtio
:
390 // Create a unique device path for this transport on the fly
392 RegBase
= fdt64_to_cpu (((UINT64
*)RegProp
)[0]);
393 DevicePath
= (VIRTIO_TRANSPORT_DEVICE_PATH
*)CreateDeviceNode (
394 HARDWARE_DEVICE_PATH
,
396 sizeof (VIRTIO_TRANSPORT_DEVICE_PATH
));
397 if (DevicePath
== NULL
) {
398 DEBUG ((EFI_D_ERROR
, "%a: Out of memory\n", __FUNCTION__
));
402 CopyMem (&DevicePath
->Vendor
.Guid
, &gVirtioMmioTransportGuid
,
404 DevicePath
->PhysBase
= RegBase
;
405 SetDevicePathNodeLength (&DevicePath
->Vendor
,
406 sizeof (*DevicePath
) - sizeof (DevicePath
->End
));
407 SetDevicePathEndNode (&DevicePath
->End
);
410 Status
= gBS
->InstallProtocolInterface (&Handle
,
411 &gEfiDevicePathProtocolGuid
, EFI_NATIVE_INTERFACE
,
413 if (EFI_ERROR (Status
)) {
414 DEBUG ((EFI_D_ERROR
, "%a: Failed to install the EFI_DEVICE_PATH "
415 "protocol on a new handle (Status == %r)\n",
416 __FUNCTION__
, Status
));
417 FreePool (DevicePath
);
421 Status
= VirtioMmioInstallDevice (RegBase
, Handle
);
422 if (EFI_ERROR (Status
)) {
423 DEBUG ((EFI_D_ERROR
, "%a: Failed to install VirtIO transport @ 0x%Lx "
424 "on handle %p (Status == %r)\n", __FUNCTION__
, RegBase
,
427 Status
= gBS
->UninstallProtocolInterface (Handle
,
428 &gEfiDevicePathProtocolGuid
, DevicePath
);
429 ASSERT_EFI_ERROR (Status
);
430 FreePool (DevicePath
);
434 case PropertyTypeGic
:
437 DistBase
= fdt64_to_cpu (((UINT64
*)RegProp
)[0]);
438 CpuBase
= fdt64_to_cpu (((UINT64
*)RegProp
)[2]);
439 ASSERT (DistBase
< MAX_UINT32
);
440 ASSERT (CpuBase
< MAX_UINT32
);
442 PcdSet32 (PcdGicDistributorBase
, (UINT32
)DistBase
);
443 PcdSet32 (PcdGicInterruptInterfaceBase
, (UINT32
)CpuBase
);
445 DEBUG ((EFI_D_INFO
, "Found GIC @ 0x%Lx/0x%Lx\n", DistBase
, CpuBase
));
448 case PropertyTypeGicV3
:
450 // The GIC v3 DT binding describes a series of at least 3 physical (base
451 // addresses, size) pairs: the distributor interface (GICD), at least one
452 // redistributor region (GICR) containing dedicated redistributor
453 // interfaces for all individual CPUs, and the CPU interface (GICC).
454 // Under virtualization, we assume that the first redistributor region
455 // listed covers the boot CPU. Also, our GICv3 driver only supports the
456 // system register CPU interface, so we can safely ignore the MMIO version
457 // which is listed after the sequence of redistributor interfaces.
458 // This means we are only interested in the first two memory regions
459 // supplied, and ignore everything else.
463 // RegProp[0..1] == { GICD base, GICD size }
464 DistBase
= fdt64_to_cpu (((UINT64
*)RegProp
)[0]);
465 ASSERT (DistBase
< MAX_UINT32
);
467 // RegProp[2..3] == { GICR base, GICR size }
468 RedistBase
= fdt64_to_cpu (((UINT64
*)RegProp
)[2]);
469 ASSERT (RedistBase
< MAX_UINT32
);
471 PcdSet32 (PcdGicDistributorBase
, (UINT32
)DistBase
);
472 PcdSet32 (PcdGicRedistributorsBase
, (UINT32
)RedistBase
);
474 DEBUG ((EFI_D_INFO
, "Found GIC v3 (re)distributor @ 0x%Lx (0x%Lx)\n",
475 DistBase
, RedistBase
));
478 case PropertyTypeRtc
:
481 RegBase
= fdt64_to_cpu (((UINT64
*)RegProp
)[0]);
482 ASSERT (RegBase
< MAX_UINT32
);
484 PcdSet32 (PcdPL031RtcBase
, (UINT32
)RegBase
);
486 DEBUG ((EFI_D_INFO
, "Found PL031 RTC @ 0x%Lx\n", RegBase
));
490 case PropertyTypeTimer
:
492 // - interrupts : Interrupt list for secure, non-secure, virtual and
493 // hypervisor timers, in that order.
495 InterruptProp
= fdt_getprop (DeviceTreeBase
, Node
, "interrupts", &Len
);
496 ASSERT (Len
== 36 || Len
== 48);
498 SecIntrNum
= fdt32_to_cpu (InterruptProp
[0].Number
)
499 + (InterruptProp
[0].Type
? 16 : 0);
500 IntrNum
= fdt32_to_cpu (InterruptProp
[1].Number
)
501 + (InterruptProp
[1].Type
? 16 : 0);
502 VirtIntrNum
= fdt32_to_cpu (InterruptProp
[2].Number
)
503 + (InterruptProp
[2].Type
? 16 : 0);
504 HypIntrNum
= Len
< 48 ? 0 : fdt32_to_cpu (InterruptProp
[3].Number
)
505 + (InterruptProp
[3].Type
? 16 : 0);
507 DEBUG ((EFI_D_INFO
, "Found Timer interrupts %d, %d, %d, %d\n",
508 SecIntrNum
, IntrNum
, VirtIntrNum
, HypIntrNum
));
510 PcdSet32 (PcdArmArchTimerSecIntrNum
, SecIntrNum
);
511 PcdSet32 (PcdArmArchTimerIntrNum
, IntrNum
);
512 PcdSet32 (PcdArmArchTimerVirtIntrNum
, VirtIntrNum
);
513 PcdSet32 (PcdArmArchTimerHypIntrNum
, HypIntrNum
);
516 case PropertyTypePsci
:
517 PsciMethod
= fdt_getprop (DeviceTreeBase
, Node
, "method", &Len
);
519 if (PsciMethod
&& AsciiStrnCmp (PsciMethod
, "hvc", 3) == 0) {
520 PcdSet32 (PcdArmPsciMethod
, 1);
521 } else if (PsciMethod
&& AsciiStrnCmp (PsciMethod
, "smc", 3) == 0) {
522 PcdSet32 (PcdArmPsciMethod
, 2);
524 DEBUG ((EFI_D_ERROR
, "%a: Unknown PSCI method \"%a\"\n", __FUNCTION__
,
529 case PropertyTypeXen
:
533 // Retrieve the reg base from this node and wire it up to the
534 // MMIO flavor of the XenBus root device I/O protocol
536 RegBase
= fdt64_to_cpu (((UINT64
*)RegProp
)[0]);
538 Status
= XenIoMmioInstall (&Handle
, RegBase
);
539 if (EFI_ERROR (Status
)) {
540 DEBUG ((EFI_D_ERROR
, "%a: XenIoMmioInstall () failed on a new handle "
541 "(Status == %r)\n", __FUNCTION__
, Status
));
545 DEBUG ((EFI_D_INFO
, "Found Xen node with Grant table @ 0x%Lx\n", RegBase
));
555 // UEFI takes ownership of the RTC hardware, and exposes its functionality
556 // through the UEFI Runtime Services GetTime, SetTime, etc. This means we
557 // need to disable it in the device tree to prevent the OS from attaching its
558 // device driver as well.
560 if ((RtcNode
!= -1) &&
561 fdt_setprop_string (DeviceTreeBase
, RtcNode
, "status",
563 DEBUG ((EFI_D_WARN
, "Failed to set PL031 status to 'disabled'\n"));