RETURN_STATUS EFIAPI ArmVirtTimerFdtClientLibConstructor ( VOID ) { EFI_STATUS Status; FDT_CLIENT_PROTOCOL *FdtClient; CONST INTERRUPT_PROPERTY *InterruptProp; UINT32 PropSize; INT32 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum; RETURN_STATUS PcdStatus; Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL, (VOID **)&FdtClient); ASSERT_EFI_ERROR (Status); Status = FdtClient->FindCompatibleNodeProperty (FdtClient, "arm,armv7-timer", "interrupts", (CONST VOID **)&InterruptProp, &PropSize); if (Status == EFI_NOT_FOUND) { Status = FdtClient->FindCompatibleNodeProperty (FdtClient, "arm,armv8-timer", "interrupts", (CONST VOID **)&InterruptProp, &PropSize); } if (EFI_ERROR (Status)) { return Status; } // // - interrupts : Interrupt list for secure, non-secure, virtual and // hypervisor timers, in that order. // ASSERT (PropSize == 36 || PropSize == 48); SecIntrNum = SwapBytes32 (InterruptProp[0].Number) + (InterruptProp[0].Type ? 16 : 0); IntrNum = SwapBytes32 (InterruptProp[1].Number) + (InterruptProp[1].Type ? 16 : 0); VirtIntrNum = SwapBytes32 (InterruptProp[2].Number) + (InterruptProp[2].Type ? 16 : 0); HypIntrNum = PropSize < 48 ? 0 : SwapBytes32 (InterruptProp[3].Number) + (InterruptProp[3].Type ? 16 : 0); DEBUG ((EFI_D_INFO, "Found Timer interrupts %d, %d, %d, %d\n", SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum)); PcdStatus = PcdSet32S (PcdArmArchTimerSecIntrNum, SecIntrNum); ASSERT_RETURN_ERROR (PcdStatus); PcdStatus = PcdSet32S (PcdArmArchTimerIntrNum, IntrNum); ASSERT_RETURN_ERROR (PcdStatus); PcdStatus = PcdSet32S (PcdArmArchTimerVirtIntrNum, VirtIntrNum); ASSERT_RETURN_ERROR (PcdStatus); PcdStatus = PcdSet32S (PcdArmArchTimerHypIntrNum, HypIntrNum); ASSERT_RETURN_ERROR (PcdStatus); return EFI_SUCCESS; }
RETURN_STATUS EFIAPI ArmVirtPL031FdtClientLibConstructor ( VOID ) { EFI_STATUS Status; FDT_CLIENT_PROTOCOL *FdtClient; INT32 Node; CONST UINT64 *Reg; UINT32 RegSize; UINT64 RegBase; RETURN_STATUS PcdStatus; Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL, (VOID **)&FdtClient); ASSERT_EFI_ERROR (Status); Status = FdtClient->FindCompatibleNode (FdtClient, "arm,pl031", &Node); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_WARN, "%a: No 'arm,pl031' compatible DT node found\n", __FUNCTION__)); return EFI_SUCCESS; } Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg", (CONST VOID **)&Reg, &RegSize); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_WARN, "%a: No 'reg' property found in 'arm,pl031' compatible DT node\n", __FUNCTION__)); return EFI_SUCCESS; } ASSERT (RegSize == 16); RegBase = SwapBytes64 (Reg[0]); ASSERT (RegBase < MAX_UINT32); PcdStatus = PcdSet32S (PcdPL031RtcBase, (UINT32)RegBase); ASSERT_RETURN_ERROR (PcdStatus); DEBUG ((EFI_D_INFO, "Found PL031 RTC @ 0x%Lx\n", RegBase)); if (!FeaturePcdGet (PcdPureAcpiBoot)) { // // UEFI takes ownership of the RTC hardware, and exposes its functionality // through the UEFI Runtime Services GetTime, SetTime, etc. This means we // need to disable it in the device tree to prevent the OS from attaching // its device driver as well. // Status = FdtClient->SetNodeProperty (FdtClient, Node, "status", "disabled", sizeof ("disabled")); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_WARN, "Failed to set PL031 status to 'disabled'\n")); } } return EFI_SUCCESS; }
/** Get the address of Xen ACPI Root System Description Pointer (RSDP) structure. @param RsdpStructurePtr Return pointer to RSDP structure @return EFI_SUCCESS Find Xen RSDP structure successfully. @return EFI_NOT_FOUND Don't find Xen RSDP structure. @return EFI_ABORTED Find Xen RSDP structure, but it's not integrated. **/ STATIC EFI_STATUS EFIAPI GetXenArmAcpiRsdp ( OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr ) { EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpStructurePtr; EFI_STATUS Status; FDT_CLIENT_PROTOCOL *FdtClient; CONST UINT64 *Reg; UINT32 RegSize; UINTN AddressCells, SizeCells; UINT64 RegBase; UINT8 Sum; RsdpStructurePtr = NULL; FdtClient = NULL; // // Get the RSDP structure address from DeviceTree // Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL, (VOID **)&FdtClient); ASSERT_EFI_ERROR (Status); Status = FdtClient->FindCompatibleNodeReg (FdtClient, "xen,guest-acpi", (CONST VOID **)&Reg, &AddressCells, &SizeCells, &RegSize); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_WARN, "%a: No 'xen,guest-acpi' compatible DT node found\n", __FUNCTION__)); return EFI_NOT_FOUND; } ASSERT (AddressCells == 2); ASSERT (SizeCells == 2); ASSERT (RegSize == 2 * sizeof (UINT64)); RegBase = SwapBytes64(Reg[0]); RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)RegBase; if (RsdpStructurePtr && RsdpStructurePtr->Revision >= 2) { Sum = CalculateSum8 ((CONST UINT8 *)RsdpStructurePtr, sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)); if (Sum != 0) { return EFI_ABORTED; } } *RsdpPtr = RsdpStructurePtr; return EFI_SUCCESS; }
RETURN_STATUS EFIAPI QemuFwCfgInitialize ( VOID ) { EFI_STATUS Status; FDT_CLIENT_PROTOCOL *FdtClient; CONST UINT64 *Reg; UINT32 RegSize; UINTN AddressCells, SizeCells; UINT64 FwCfgSelectorAddress; UINT64 FwCfgSelectorSize; UINT64 FwCfgDataAddress; UINT64 FwCfgDataSize; UINT64 FwCfgDmaAddress; UINT64 FwCfgDmaSize; Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL, (VOID **)&FdtClient); ASSERT_EFI_ERROR (Status); Status = FdtClient->FindCompatibleNodeReg (FdtClient, "qemu,fw-cfg-mmio", (CONST VOID **)&Reg, &AddressCells, &SizeCells, &RegSize); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_WARN, "%a: No 'qemu,fw-cfg-mmio' compatible DT node found (Status == %r)\n", __FUNCTION__, Status)); return EFI_SUCCESS; } ASSERT (AddressCells == 2); ASSERT (SizeCells == 2); ASSERT (RegSize == 2 * sizeof (UINT64)); FwCfgDataAddress = SwapBytes64 (Reg[0]); FwCfgDataSize = 8; FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize; FwCfgSelectorSize = 2; // // The following ASSERT()s express // // Address + Size - 1 <= MAX_UINTN // // for both registers, that is, that the last byte in each MMIO range is // expressible as a MAX_UINTN. The form below is mathematically // equivalent, and it also prevents any unsigned overflow before the // comparison. // ASSERT (FwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1); ASSERT (FwCfgDataAddress <= MAX_UINTN - FwCfgDataSize + 1); mFwCfgSelectorAddress = FwCfgSelectorAddress; mFwCfgDataAddress = FwCfgDataAddress; DEBUG ((EFI_D_INFO, "Found FwCfg @ 0x%Lx/0x%Lx\n", FwCfgSelectorAddress, FwCfgDataAddress)); if (SwapBytes64 (Reg[1]) >= 0x18) { FwCfgDmaAddress = FwCfgDataAddress + 0x10; FwCfgDmaSize = 0x08; // // See explanation above. // ASSERT (FwCfgDmaAddress <= MAX_UINTN - FwCfgDmaSize + 1); DEBUG ((EFI_D_INFO, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress)); } else { FwCfgDmaAddress = 0; } if (InternalQemuFwCfgIsAvailable ()) { UINT32 Signature; QemuFwCfgSelectItem (QemuFwCfgItemSignature); Signature = QemuFwCfgRead32 (); if (Signature == SIGNATURE_32 ('Q', 'E', 'M', 'U')) { // // For DMA support, we require the DTB to advertise the register, and the // feature bitmap (which we read without DMA) to confirm the feature. // if (FwCfgDmaAddress != 0) { UINT32 Features; QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion); Features = QemuFwCfgRead32 (); if ((Features & BIT1) != 0) { mFwCfgDmaAddress = FwCfgDmaAddress; InternalQemuFwCfgReadBytes = DmaReadBytes; } } } else { mFwCfgSelectorAddress = 0; mFwCfgDataAddress = 0; } } return RETURN_SUCCESS; }
EFI_STATUS NorFlashPlatformGetDevices ( OUT NOR_FLASH_DESCRIPTION **NorFlashDescriptions, OUT UINT32 *Count ) { FDT_CLIENT_PROTOCOL *FdtClient; INT32 Node; EFI_STATUS Status; EFI_STATUS FindNodeStatus; CONST UINT32 *Reg; UINT32 PropSize; UINT32 Num; UINT64 Base; UINT64 Size; Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL, (VOID **)&FdtClient); ASSERT_EFI_ERROR (Status); Num = 0; for (FindNodeStatus = FdtClient->FindCompatibleNode (FdtClient, "cfi-flash", &Node); !EFI_ERROR (FindNodeStatus) && Num < MAX_FLASH_BANKS; FindNodeStatus = FdtClient->FindNextCompatibleNode (FdtClient, "cfi-flash", Node, &Node)) { Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg", (CONST VOID **)&Reg, &PropSize); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a: GetNodeProperty () failed (Status == %r)\n", __FUNCTION__, Status)); continue; } ASSERT ((PropSize % (4 * sizeof (UINT32))) == 0); while (PropSize >= (4 * sizeof (UINT32)) && Num < MAX_FLASH_BANKS) { Base = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[0])); Size = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[2])); Reg += 4; PropSize -= 4 * sizeof (UINT32); // // Disregard any flash devices that overlap with the primary FV. // The firmware is not updatable from inside the guest anyway. // if ((PcdGet64 (PcdFvBaseAddress) + PcdGet32 (PcdFvSize) > Base) && (Base + Size) > PcdGet64 (PcdFvBaseAddress)) { continue; } mNorFlashDevices[Num].DeviceBaseAddress = (UINTN)Base; mNorFlashDevices[Num].RegionBaseAddress = (UINTN)Base; mNorFlashDevices[Num].Size = (UINTN)Size; mNorFlashDevices[Num].BlockSize = QEMU_NOR_BLOCK_SIZE; Num++; } } *NorFlashDescriptions = mNorFlashDevices; *Count = Num; return EFI_SUCCESS; }