Example #1
0
/**
  Returns a boolean indicating if the firmware configuration interface
  is available or not.

  This function may change fw_cfg state.

  @retval    TRUE   The interface is available
  @retval    FALSE  The interface is not available

**/
BOOLEAN
EFIAPI
QemuFwCfgIsAvailable (
  VOID
  )
{
  return InternalQemuFwCfgIsAvailable ();
}
Example #2
0
/**
  Selects a firmware configuration item for reading.

  Following this call, any data read from this item will start from the
  beginning of the configuration item's data.

  @param[in] QemuFwCfgItem  Firmware Configuration item to read

**/
VOID
EFIAPI
QemuFwCfgSelectItem (
  IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem
  )
{
  if (InternalQemuFwCfgIsAvailable ()) {
    MmioWrite16 (mFwCfgSelectorAddress, SwapBytes16 ((UINT16)QemuFwCfgItem));
  }
}
Example #3
0
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;
}