1ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel/** @file 2ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel* Device tree enumeration DXE driver for ARM Virtual Machines 3ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel* 4ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel* Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR> 5ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel* 6ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel* This program and the accompanying materials are 7ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel* licensed and made available under the terms and conditions of the BSD License 8ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel* which accompanies this distribution. The full text of the license may be found at 9ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel* http://opensource.org/licenses/bsd-license.php 10ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel* 11ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel* 14ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel**/ 15ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 16ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#include <Library/BaseLib.h> 17ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#include <Library/DebugLib.h> 18ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#include <Library/UefiLib.h> 19ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#include <Library/BaseMemoryLib.h> 20ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#include <Library/UefiDriverEntryPoint.h> 21ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#include <Library/MemoryAllocationLib.h> 22ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#include <Library/UefiBootServicesTableLib.h> 23ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#include <Library/VirtioMmioDeviceLib.h> 24ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#include <Library/DevicePathLib.h> 25ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#include <Library/PcdLib.h> 26ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#include <Library/DxeServicesLib.h> 27cc667df08ae8208865744465eafa446b39b2805dArd Biesheuvel#include <Library/HobLib.h> 28ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#include <libfdt.h> 296abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel#include <Library/XenIoMmioLib.h> 30ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 31ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#include <Guid/Fdt.h> 3273bb8e6895080f07ece26b0db0f50048713c2b93Laszlo Ersek#include <Guid/VirtioMmioTransport.h> 33cc667df08ae8208865744465eafa446b39b2805dArd Biesheuvel#include <Guid/FdtHob.h> 34ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 35ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#pragma pack (1) 36ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuveltypedef struct { 37ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel VENDOR_DEVICE_PATH Vendor; 38ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel UINT64 PhysBase; 39ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel EFI_DEVICE_PATH_PROTOCOL End; 40ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel} VIRTIO_TRANSPORT_DEVICE_PATH; 41ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel#pragma pack () 42ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 43ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuveltypedef enum { 44ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PropertyTypeUnknown, 45ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PropertyTypeGic, 46ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PropertyTypeRtc, 47ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PropertyTypeVirtio, 48ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PropertyTypeUart, 49ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PropertyTypeTimer, 50ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PropertyTypePsci, 51ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek PropertyTypeFwCfg, 5265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek PropertyTypePciHost, 537b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel PropertyTypeGicV3, 546abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel PropertyTypeXen, 55ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel} PROPERTY_TYPE; 56ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 57ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuveltypedef struct { 58ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PROPERTY_TYPE Type; 5965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek CHAR8 Compatible[32]; 60ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel} PROPERTY; 61ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 62ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard BiesheuvelSTATIC CONST PROPERTY CompatibleProperties[] = { 6365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek { PropertyTypeGic, "arm,cortex-a15-gic" }, 6465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek { PropertyTypeRtc, "arm,pl031" }, 6565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek { PropertyTypeVirtio, "virtio,mmio" }, 6665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek { PropertyTypeUart, "arm,pl011" }, 6765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek { PropertyTypeTimer, "arm,armv7-timer" }, 6865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek { PropertyTypeTimer, "arm,armv8-timer" }, 6965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek { PropertyTypePsci, "arm,psci-0.2" }, 7065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek { PropertyTypeFwCfg, "qemu,fw-cfg-mmio" }, 7165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek { PropertyTypePciHost, "pci-host-ecam-generic" }, 727b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel { PropertyTypeGicV3, "arm,gic-v3" }, 736abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel { PropertyTypeXen, "xen,xen" }, 7465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek { PropertyTypeUnknown, "" } 75ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel}; 76ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 77ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuveltypedef struct { 78ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel UINT32 Type; 79ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel UINT32 Number; 80ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel UINT32 Flags; 81ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel} INTERRUPT_PROPERTY; 82ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 83ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard BiesheuvelSTATIC 84ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard BiesheuvelPROPERTY_TYPE 85ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard BiesheuvelGetTypeFromNode ( 86ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel IN CONST CHAR8 *NodeType, 87ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel IN UINTN Size 88ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel ) 89ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel{ 90ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel CONST CHAR8 *Compatible; 91ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel CONST PROPERTY *CompatibleProperty; 92ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 93ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // 94ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // A 'compatible' node may contain a sequence of NULL terminated 95ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // compatible strings so check each one 96ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // 97ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel for (Compatible = NodeType; Compatible < NodeType + Size && *Compatible; 98ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel Compatible += 1 + AsciiStrLen (Compatible)) { 99ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel for (CompatibleProperty = CompatibleProperties; CompatibleProperty->Compatible[0]; CompatibleProperty++) { 100ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel if (AsciiStrCmp (CompatibleProperty->Compatible, Compatible) == 0) { 101ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel return CompatibleProperty->Type; 102ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 103ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 104ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 105ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel return PropertyTypeUnknown; 106ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel} 107ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 10865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek// 10965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek// We expect the "ranges" property of "pci-host-ecam-generic" to consist of 11065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek// records like this. 11165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek// 11265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek#pragma pack (1) 11365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersektypedef struct { 11465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek UINT32 Type; 11565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek UINT64 ChildBase; 11665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek UINT64 CpuBase; 11765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek UINT64 Size; 11865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek} DTB_PCI_HOST_RANGE_RECORD; 11965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek#pragma pack () 12065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 12165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek#define DTB_PCI_HOST_RANGE_RELOCATABLE BIT31 12265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30 12365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek#define DTB_PCI_HOST_RANGE_ALIASED BIT29 12465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek#define DTB_PCI_HOST_RANGE_MMIO32 BIT25 12565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek#define DTB_PCI_HOST_RANGE_MMIO64 (BIT25 | BIT24) 12665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek#define DTB_PCI_HOST_RANGE_IO BIT24 12765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek#define DTB_PCI_HOST_RANGE_TYPEMASK (BIT31 | BIT30 | BIT29 | BIT25 | BIT24) 12865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 12965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek/** 13065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek Process the device tree node describing the generic PCI host controller. 13165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 13265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek param[in] DeviceTreeBase Pointer to the device tree. 13365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 13465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek param[in] Node Offset of the device tree node whose "compatible" 13565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek property is "pci-host-ecam-generic". 13665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 13765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek param[in] RegProp Pointer to the "reg" property of Node. The caller 13865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek is responsible for ensuring that the size of the 13965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek property is 4 UINT32 cells. 14065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 14165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek @retval EFI_SUCCESS Parsing successful, properties parsed from Node 14265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek have been stored in dynamic PCDs. 14365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 14465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek @retval EFI_PROTOCOL_ERROR Parsing failed. PCDs are left unchanged. 14565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek**/ 14665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo ErsekSTATIC 14765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo ErsekEFI_STATUS 14865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo ErsekEFIAPI 14965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo ErsekProcessPciHost ( 15065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek IN CONST VOID *DeviceTreeBase, 15165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek IN INT32 Node, 15265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek IN CONST VOID *RegProp 15365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek ) 15465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek{ 15565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek UINT64 ConfigBase, ConfigSize; 15665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek CONST VOID *Prop; 15765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek INT32 Len; 15865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek UINT32 BusMin, BusMax; 15965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek UINT32 RecordIdx; 16065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek UINT64 IoBase, IoSize, IoTranslation; 16165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek UINT64 MmioBase, MmioSize, MmioTranslation; 16265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 16365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // 16465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // Fetch the ECAM window. 16565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // 16665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek ConfigBase = fdt64_to_cpu (((CONST UINT64 *)RegProp)[0]); 16765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek ConfigSize = fdt64_to_cpu (((CONST UINT64 *)RegProp)[1]); 16865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 16965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // 17065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // Fetch the bus range (note: inclusive). 17165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // 17265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek Prop = fdt_getprop (DeviceTreeBase, Node, "bus-range", &Len); 17365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek if (Prop == NULL || Len != 2 * sizeof(UINT32)) { 17465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek DEBUG ((EFI_D_ERROR, "%a: 'bus-range' not found or invalid\n", 17565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek __FUNCTION__)); 17665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek return EFI_PROTOCOL_ERROR; 17765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek } 17865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek BusMin = fdt32_to_cpu (((CONST UINT32 *)Prop)[0]); 17965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek BusMax = fdt32_to_cpu (((CONST UINT32 *)Prop)[1]); 18065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 18165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // 18265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // Sanity check: the config space must accommodate all 4K register bytes of 18365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // all 8 functions of all 32 devices of all buses. 18465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // 18565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek if (BusMax < BusMin || BusMax - BusMin == MAX_UINT32 || 18665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek DivU64x32 (ConfigSize, SIZE_4KB * 8 * 32) < BusMax - BusMin + 1) { 18765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek DEBUG ((EFI_D_ERROR, "%a: invalid 'bus-range' and/or 'reg'\n", 18865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek __FUNCTION__)); 18965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek return EFI_PROTOCOL_ERROR; 19065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek } 19165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 19265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // 19365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // Iterate over "ranges". 19465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // 19565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek Prop = fdt_getprop (DeviceTreeBase, Node, "ranges", &Len); 19665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek if (Prop == NULL || Len == 0 || 19765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0) { 19865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek DEBUG ((EFI_D_ERROR, "%a: 'ranges' not found or invalid\n", __FUNCTION__)); 19965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek return EFI_PROTOCOL_ERROR; 20065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek } 20165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 20265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // 20365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // IoBase, IoTranslation, MmioBase and MmioTranslation are initialized only 20465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // in order to suppress '-Werror=maybe-uninitialized' warnings *incorrectly* 20565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // emitted by some gcc versions. 20665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // 20765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek IoBase = 0; 20865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek IoTranslation = 0; 20965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek MmioBase = 0; 21065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek MmioTranslation = 0; 21165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 21265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // 21365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // IoSize and MmioSize are initialized to zero because the logic below 21465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // requires it. 21565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek // 21665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek IoSize = 0; 21765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek MmioSize = 0; 21865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD); 21965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek ++RecordIdx) { 22065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek CONST DTB_PCI_HOST_RANGE_RECORD *Record; 22165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 22265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx; 22365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek switch (fdt32_to_cpu (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK) { 22465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek case DTB_PCI_HOST_RANGE_IO: 22565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek IoBase = fdt64_to_cpu (Record->ChildBase); 22665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek IoSize = fdt64_to_cpu (Record->Size); 22765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek IoTranslation = fdt64_to_cpu (Record->CpuBase) - IoBase; 22865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek break; 22965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 23065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek case DTB_PCI_HOST_RANGE_MMIO32: 23165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek MmioBase = fdt64_to_cpu (Record->ChildBase); 23265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek MmioSize = fdt64_to_cpu (Record->Size); 23365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek MmioTranslation = fdt64_to_cpu (Record->CpuBase) - MmioBase; 23465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 23565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek if (MmioBase > MAX_UINT32 || MmioSize > MAX_UINT32 || 23665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek MmioBase + MmioSize > SIZE_4GB) { 23765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek DEBUG ((EFI_D_ERROR, "%a: MMIO32 space invalid\n", __FUNCTION__)); 23865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek return EFI_PROTOCOL_ERROR; 23965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek } 24065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 24165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek if (MmioTranslation != 0) { 24265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO32 translation " 24365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek "0x%Lx\n", __FUNCTION__, MmioTranslation)); 24465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek return EFI_UNSUPPORTED; 24565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek } 24665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 24765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek break; 24865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek } 24965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek } 25065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek if (IoSize == 0 || MmioSize == 0) { 25165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek DEBUG ((EFI_D_ERROR, "%a: %a space empty\n", __FUNCTION__, 25265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek (IoSize == 0) ? "IO" : "MMIO32")); 25365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek return EFI_PROTOCOL_ERROR; 25465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek } 25565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 25665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek PcdSet64 (PcdPciExpressBaseAddress, ConfigBase); 25765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 25865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek PcdSet32 (PcdPciBusMin, BusMin); 25965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek PcdSet32 (PcdPciBusMax, BusMax); 26065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 26165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek PcdSet64 (PcdPciIoBase, IoBase); 26265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek PcdSet64 (PcdPciIoSize, IoSize); 26365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek PcdSet64 (PcdPciIoTranslation, IoTranslation); 26465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 26565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek PcdSet32 (PcdPciMmio32Base, (UINT32)MmioBase); 26665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek PcdSet32 (PcdPciMmio32Size, (UINT32)MmioSize); 26765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 26865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek PcdSetBool (PcdPciDisableBusEnumeration, FALSE); 26965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 27065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] " 27165bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__, ConfigBase, 27265bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek ConfigSize, BusMin, BusMax, IoBase, IoSize, IoTranslation, MmioBase, 27365bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek MmioSize, MmioTranslation)); 27465bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek return EFI_SUCCESS; 27565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek} 27665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 27765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 278ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard BiesheuvelEFI_STATUS 279ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard BiesheuvelEFIAPI 280ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard BiesheuvelInitializeVirtFdtDxe ( 281ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel IN EFI_HANDLE ImageHandle, 282ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel IN EFI_SYSTEM_TABLE *SystemTable 283ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel ) 284ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel{ 285cc667df08ae8208865744465eafa446b39b2805dArd Biesheuvel VOID *Hob; 286ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel VOID *DeviceTreeBase; 287ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel INT32 Node, Prev; 288ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel INT32 RtcNode; 289ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel EFI_STATUS Status; 290ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel CONST CHAR8 *Type; 291ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel INT32 Len; 292ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PROPERTY_TYPE PropType; 293ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel CONST VOID *RegProp; 294ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel VIRTIO_TRANSPORT_DEVICE_PATH *DevicePath; 295ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel EFI_HANDLE Handle; 296ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel UINT64 RegBase; 2977b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel UINT64 DistBase, CpuBase, RedistBase; 298ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel CONST INTERRUPT_PROPERTY *InterruptProp; 299ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel INT32 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum; 300ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel CONST CHAR8 *PsciMethod; 301ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek UINT64 FwCfgSelectorAddress; 302ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek UINT64 FwCfgSelectorSize; 303ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek UINT64 FwCfgDataAddress; 304ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek UINT64 FwCfgDataSize; 30550b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek UINT64 FwCfgDmaAddress; 30650b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek UINT64 FwCfgDmaSize; 307ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 308cc667df08ae8208865744465eafa446b39b2805dArd Biesheuvel Hob = GetFirstGuidHob(&gFdtHobGuid); 309cc667df08ae8208865744465eafa446b39b2805dArd Biesheuvel if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) { 310cc667df08ae8208865744465eafa446b39b2805dArd Biesheuvel return EFI_NOT_FOUND; 311cc667df08ae8208865744465eafa446b39b2805dArd Biesheuvel } 312cc667df08ae8208865744465eafa446b39b2805dArd Biesheuvel DeviceTreeBase = (VOID *)(UINTN)*(UINT64 *)GET_GUID_HOB_DATA (Hob); 313ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 314ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel if (fdt_check_header (DeviceTreeBase) != 0) { 315ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%p\n", __FUNCTION__, DeviceTreeBase)); 316ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel return EFI_NOT_FOUND; 317ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 318ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 319ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel Status = gBS->InstallConfigurationTable (&gFdtTableGuid, DeviceTreeBase); 320ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel ASSERT_EFI_ERROR (Status); 321ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 322ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, DeviceTreeBase)); 323ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 324ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel RtcNode = -1; 325ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // 326ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // Now enumerate the nodes and install peripherals that we are interested in, 327ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // i.e., GIC, RTC and virtio MMIO nodes 328ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // 329ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel for (Prev = 0;; Prev = Node) { 330ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel Node = fdt_next_node (DeviceTreeBase, Prev, NULL); 331ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel if (Node < 0) { 332ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel break; 333ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 334ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 335ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len); 336ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel if (Type == NULL) { 337ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel continue; 338ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 339ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 340ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PropType = GetTypeFromNode (Type, Len); 341ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel if (PropType == PropertyTypeUnknown) { 342ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel continue; 343ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 344ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 345ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // 346ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // Get the 'reg' property of this node. For now, we will assume 347ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // 8 byte quantities for base and size, respectively. 348ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // TODO use #cells root properties instead 349ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // 350ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); 351ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel ASSERT ((RegProp != NULL) || (PropType == PropertyTypeTimer) || 352ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel (PropType == PropertyTypePsci)); 353ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 354ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel switch (PropType) { 35565bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek case PropertyTypePciHost: 35665bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek ASSERT (Len == 2 * sizeof (UINT64)); 35765bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek Status = ProcessPciHost (DeviceTreeBase, Node, RegProp); 35865bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek ASSERT_EFI_ERROR (Status); 35965bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek break; 36065bb13b0fd7feed90ca45ea5333490a3f35e24abLaszlo Ersek 361ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek case PropertyTypeFwCfg: 362ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek ASSERT (Len == 2 * sizeof (UINT64)); 363ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek 364ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek FwCfgDataAddress = fdt64_to_cpu (((UINT64 *)RegProp)[0]); 365ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek FwCfgDataSize = 8; 366ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize; 367ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek FwCfgSelectorSize = 2; 368ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek 369ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek // 370ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek // The following ASSERT()s express 371ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek // 372ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek // Address + Size - 1 <= MAX_UINTN 373ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek // 374ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek // for both registers, that is, that the last byte in each MMIO range is 375ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek // expressible as a MAX_UINTN. The form below is mathematically 376ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek // equivalent, and it also prevents any unsigned overflow before the 377ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek // comparison. 378ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek // 379ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek ASSERT (FwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1); 380ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek ASSERT (FwCfgDataAddress <= MAX_UINTN - FwCfgDataSize + 1); 381ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek 382ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek PcdSet64 (PcdFwCfgSelectorAddress, FwCfgSelectorAddress); 383ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek PcdSet64 (PcdFwCfgDataAddress, FwCfgDataAddress); 384ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek 385ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek DEBUG ((EFI_D_INFO, "Found FwCfg @ 0x%Lx/0x%Lx\n", FwCfgSelectorAddress, 386ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek FwCfgDataAddress)); 38750b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek 38850b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek if (fdt64_to_cpu (((UINT64 *)RegProp)[1]) >= 0x18) { 38950b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek FwCfgDmaAddress = FwCfgDataAddress + 0x10; 39050b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek FwCfgDmaSize = 0x08; 39150b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek 39250b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek // 39350b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek // See explanation above. 39450b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek // 39550b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek ASSERT (FwCfgDmaAddress <= MAX_UINTN - FwCfgDmaSize + 1); 39650b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek 39750b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek PcdSet64 (PcdFwCfgDmaAddress, FwCfgDmaAddress); 39850b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek DEBUG ((EFI_D_INFO, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress)); 39950b91449a3a073af3a7c87af83002016e7e34cc4Laszlo Ersek } 400ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek break; 401ad652d46941c6a1e0f828cb084fb6829c3abb68dLaszlo Ersek 402ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel case PropertyTypeVirtio: 403ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel ASSERT (Len == 16); 404ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // 405ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // Create a unique device path for this transport on the fly 406ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // 407ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]); 408ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DevicePath = (VIRTIO_TRANSPORT_DEVICE_PATH *)CreateDeviceNode ( 409ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel HARDWARE_DEVICE_PATH, 410ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel HW_VENDOR_DP, 411ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel sizeof (VIRTIO_TRANSPORT_DEVICE_PATH)); 412ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel if (DevicePath == NULL) { 413ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DEBUG ((EFI_D_ERROR, "%a: Out of memory\n", __FUNCTION__)); 414ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel break; 415ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 416ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 41773bb8e6895080f07ece26b0db0f50048713c2b93Laszlo Ersek CopyMem (&DevicePath->Vendor.Guid, &gVirtioMmioTransportGuid, 41873bb8e6895080f07ece26b0db0f50048713c2b93Laszlo Ersek sizeof (EFI_GUID)); 419ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DevicePath->PhysBase = RegBase; 420ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel SetDevicePathNodeLength (&DevicePath->Vendor, 421ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel sizeof (*DevicePath) - sizeof (DevicePath->End)); 422ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel SetDevicePathEndNode (&DevicePath->End); 423ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 424ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel Handle = NULL; 425ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel Status = gBS->InstallProtocolInterface (&Handle, 426ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE, 427ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DevicePath); 428ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel if (EFI_ERROR (Status)) { 429ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DEBUG ((EFI_D_ERROR, "%a: Failed to install the EFI_DEVICE_PATH " 430ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel "protocol on a new handle (Status == %r)\n", 431ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel __FUNCTION__, Status)); 432ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel FreePool (DevicePath); 433ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel break; 434ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 435ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 436ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel Status = VirtioMmioInstallDevice (RegBase, Handle); 437ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel if (EFI_ERROR (Status)) { 438ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DEBUG ((EFI_D_ERROR, "%a: Failed to install VirtIO transport @ 0x%Lx " 439ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel "on handle %p (Status == %r)\n", __FUNCTION__, RegBase, 440ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel Handle, Status)); 441ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 442ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel Status = gBS->UninstallProtocolInterface (Handle, 443ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel &gEfiDevicePathProtocolGuid, DevicePath); 444ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel ASSERT_EFI_ERROR (Status); 445ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel FreePool (DevicePath); 446ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 447ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel break; 448ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 449ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel case PropertyTypeGic: 450ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel ASSERT (Len == 32); 451ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 452ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DistBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]); 453ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel CpuBase = fdt64_to_cpu (((UINT64 *)RegProp)[2]); 454ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel ASSERT (DistBase < MAX_UINT32); 455ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel ASSERT (CpuBase < MAX_UINT32); 456ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 457ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PcdSet32 (PcdGicDistributorBase, (UINT32)DistBase); 458ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PcdSet32 (PcdGicInterruptInterfaceBase, (UINT32)CpuBase); 459ae26410e285bf0320252f99fe25055d467f86824Ard Biesheuvel PcdSet32 (PcdArmGicRevision, 2); 460ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 461ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DEBUG ((EFI_D_INFO, "Found GIC @ 0x%Lx/0x%Lx\n", DistBase, CpuBase)); 462ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel break; 463ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 4647b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel case PropertyTypeGicV3: 4657b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // 4667b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // The GIC v3 DT binding describes a series of at least 3 physical (base 4677b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // addresses, size) pairs: the distributor interface (GICD), at least one 4687b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // redistributor region (GICR) containing dedicated redistributor 4697b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // interfaces for all individual CPUs, and the CPU interface (GICC). 4707b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // Under virtualization, we assume that the first redistributor region 4717b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // listed covers the boot CPU. Also, our GICv3 driver only supports the 4727b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // system register CPU interface, so we can safely ignore the MMIO version 4737b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // which is listed after the sequence of redistributor interfaces. 4747b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // This means we are only interested in the first two memory regions 4757b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // supplied, and ignore everything else. 4767b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // 4777b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel ASSERT (Len >= 32); 4787b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel 4797b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // RegProp[0..1] == { GICD base, GICD size } 4807b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel DistBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]); 4817b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel ASSERT (DistBase < MAX_UINT32); 4827b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel 4837b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel // RegProp[2..3] == { GICR base, GICR size } 4847b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel RedistBase = fdt64_to_cpu (((UINT64 *)RegProp)[2]); 4857b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel ASSERT (RedistBase < MAX_UINT32); 4867b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel 4877b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel PcdSet32 (PcdGicDistributorBase, (UINT32)DistBase); 4887b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel PcdSet32 (PcdGicRedistributorsBase, (UINT32)RedistBase); 489ae26410e285bf0320252f99fe25055d467f86824Ard Biesheuvel PcdSet32 (PcdArmGicRevision, 3); 4907b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel 4917b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel DEBUG ((EFI_D_INFO, "Found GIC v3 (re)distributor @ 0x%Lx (0x%Lx)\n", 4927b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel DistBase, RedistBase)); 4937b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel break; 4947b70dabbb2d8dd22afbb14defbb9ce5b9cb8b4c7Ard Biesheuvel 495ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel case PropertyTypeRtc: 496ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel ASSERT (Len == 16); 497ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 498ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]); 499ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel ASSERT (RegBase < MAX_UINT32); 500ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 501ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PcdSet32 (PcdPL031RtcBase, (UINT32)RegBase); 502ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 503ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DEBUG ((EFI_D_INFO, "Found PL031 RTC @ 0x%Lx\n", RegBase)); 504ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel RtcNode = Node; 505ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel break; 506ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 507ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel case PropertyTypeTimer: 508ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // 509ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // - interrupts : Interrupt list for secure, non-secure, virtual and 510ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // hypervisor timers, in that order. 511ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // 512ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel InterruptProp = fdt_getprop (DeviceTreeBase, Node, "interrupts", &Len); 513967efdcdc3a3a22550563acb9ec77f565b3dbee0Ard Biesheuvel ASSERT (Len == 36 || Len == 48); 514ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 515ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel SecIntrNum = fdt32_to_cpu (InterruptProp[0].Number) 516ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel + (InterruptProp[0].Type ? 16 : 0); 517ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel IntrNum = fdt32_to_cpu (InterruptProp[1].Number) 518ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel + (InterruptProp[1].Type ? 16 : 0); 519ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel VirtIntrNum = fdt32_to_cpu (InterruptProp[2].Number) 520ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel + (InterruptProp[2].Type ? 16 : 0); 521967efdcdc3a3a22550563acb9ec77f565b3dbee0Ard Biesheuvel HypIntrNum = Len < 48 ? 0 : fdt32_to_cpu (InterruptProp[3].Number) 522967efdcdc3a3a22550563acb9ec77f565b3dbee0Ard Biesheuvel + (InterruptProp[3].Type ? 16 : 0); 523ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 524ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DEBUG ((EFI_D_INFO, "Found Timer interrupts %d, %d, %d, %d\n", 525ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum)); 526ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 527ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PcdSet32 (PcdArmArchTimerSecIntrNum, SecIntrNum); 528ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PcdSet32 (PcdArmArchTimerIntrNum, IntrNum); 529ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PcdSet32 (PcdArmArchTimerVirtIntrNum, VirtIntrNum); 530ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PcdSet32 (PcdArmArchTimerHypIntrNum, HypIntrNum); 531ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel break; 532ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 533ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel case PropertyTypePsci: 534ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PsciMethod = fdt_getprop (DeviceTreeBase, Node, "method", &Len); 535ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 536ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel if (PsciMethod && AsciiStrnCmp (PsciMethod, "hvc", 3) == 0) { 537ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PcdSet32 (PcdArmPsciMethod, 1); 538ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } else if (PsciMethod && AsciiStrnCmp (PsciMethod, "smc", 3) == 0) { 539ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PcdSet32 (PcdArmPsciMethod, 2); 540ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } else { 541ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DEBUG ((EFI_D_ERROR, "%a: Unknown PSCI method \"%a\"\n", __FUNCTION__, 542ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel PsciMethod)); 543ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 544ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel break; 545ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 5466abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel case PropertyTypeXen: 5476abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel ASSERT (Len == 16); 5486abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel 5496abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel // 5506abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel // Retrieve the reg base from this node and wire it up to the 5516abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel // MMIO flavor of the XenBus root device I/O protocol 5526abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel // 5536abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel RegBase = fdt64_to_cpu (((UINT64 *)RegProp)[0]); 5546abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel Handle = NULL; 5556abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel Status = XenIoMmioInstall (&Handle, RegBase); 5566abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel if (EFI_ERROR (Status)) { 5576abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel DEBUG ((EFI_D_ERROR, "%a: XenIoMmioInstall () failed on a new handle " 5586abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel "(Status == %r)\n", __FUNCTION__, Status)); 5596abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel break; 5606abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel } 5616abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel 5626abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel DEBUG ((EFI_D_INFO, "Found Xen node with Grant table @ 0x%Lx\n", RegBase)); 5636abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel 5646abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel break; 5656abe83c3c884f86bd423d6155eb1b7f6d2833fd9Ard Biesheuvel 566ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel default: 567ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel break; 568ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 569ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 570ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel 571ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // 572ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // UEFI takes ownership of the RTC hardware, and exposes its functionality 573ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // through the UEFI Runtime Services GetTime, SetTime, etc. This means we 574ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // need to disable it in the device tree to prevent the OS from attaching its 575ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // device driver as well. 576ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel // 577ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel if ((RtcNode != -1) && 578ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel fdt_setprop_string (DeviceTreeBase, RtcNode, "status", 579ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel "disabled") != 0) { 580ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel DEBUG ((EFI_D_WARN, "Failed to set PL031 status to 'disabled'\n")); 581ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel } 582ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel return EFI_SUCCESS; 583ad10693231b9bc5ba7bab0f20ce1bf8d8f868c52Ard Biesheuvel} 584