Exemplo n.º 1
0
/**
  Initialize the state information for the Timer Architectural Protocol and
  the Timer Debug support protocol that allows the debugger to break into a
  running program.

  @param  ImageHandle   of the loaded driver
  @param  SystemTable   Pointer to the System Table

  @retval EFI_SUCCESS           Protocol registered
  @retval EFI_OUT_OF_RESOURCES  Cannot allocate protocol data structure
  @retval EFI_DEVICE_ERROR      Hardware problems

**/
EFI_STATUS
EFIAPI
TimerInitialize (
  IN EFI_HANDLE         ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  )
{
  EFI_HANDLE  Handle = NULL;
  EFI_STATUS  Status;
  UINTN TimerCtrlReg;

  if (ArmIsArchTimerImplemented () == 0) {
    DEBUG ((EFI_D_ERROR, "ARM Architectural Timer is not available in the CPU, hence cann't use this Driver \n"));
    ASSERT (0);
  }

  // Find the interrupt controller protocol.  ASSERT if not found.
  Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt);
  ASSERT_EFI_ERROR (Status);

  // Disable the timer
  TimerCtrlReg = ArmArchTimerGetTimerCtrlReg ();
  TimerCtrlReg |= ARM_ARCH_TIMER_IMASK;
  TimerCtrlReg &= ~ARM_ARCH_TIMER_ENABLE;
  ArmArchTimerSetTimerCtrlReg (TimerCtrlReg);
  Status = TimerDriverSetTimerPeriod (&gTimer, 0);
  ASSERT_EFI_ERROR (Status);

  // Install secure and Non-secure interrupt handlers
  // Note: Because it is not possible to determine the security state of the
  // CPU dynamically, we just install interrupt handler for both sec and non-sec
  // timer PPI
  Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerSecIntrNum), TimerInterruptHandler);
  ASSERT_EFI_ERROR (Status);

  Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerIntrNum), TimerInterruptHandler);
  ASSERT_EFI_ERROR (Status);

  // Set up default timer
  Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32(PcdTimerPeriod)); // TIMER_DEFAULT_PERIOD
  ASSERT_EFI_ERROR (Status);

  // Install the Timer Architectural Protocol onto a new handle
  Status = gBS->InstallMultipleProtocolInterfaces(
                  &Handle,
                  &gEfiTimerArchProtocolGuid,      &gTimer,
                  NULL
                  );
  ASSERT_EFI_ERROR(Status);

  // Everything is ready, unmask and enable timer interrupts
  TimerCtrlReg = ARM_ARCH_TIMER_ENABLE;
  ArmArchTimerSetTimerCtrlReg (TimerCtrlReg);

  // Register for an ExitBootServicesEvent
  Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
  ASSERT_EFI_ERROR (Status);

  return Status;
}
Exemplo n.º 2
0
RETURN_STATUS
EFIAPI
TimerConstructor (
  VOID
  )
{
  // Check if the ARM Generic Timer Extension is implemented
  if (ArmIsArchTimerImplemented ()) {

    UINTN TimerFreq;

    // Check if Architectural Timer frequency is valid number (should not be 0)
    ASSERT (PcdGet32 (PcdArmArchTimerFreqInHz));

    // Check if ticks/uS is not 0. The Architectural timer runs at constant
    // frequency irrespective of CPU frequency. According to General Timer Ref
    // manual lower bound of the frequency is in the range of 1-10MHz
    ASSERT (TICKS_PER_MICRO_SEC);

#ifdef MDE_CPU_ARM
    // Only set the frequency for ARMv7. We expect the secure firmware to have already do it
    // If the security extensions are not implemented set Timer Frequency
    if ((ArmReadIdPfr1 () & ARM_PFR1_SEC) == 0x0) {
      ArmArchTimerSetTimerFreq (PcdGet32 (PcdArmArchTimerFreqInHz));
    }
#endif

    // Architectural Timer Frequency must be set in the Secure privileged(if secure extensions are supported) mode.
    // If the reset value (0) is returned just ASSERT.
    TimerFreq = ArmArchTimerGetTimerFreq ();
    ASSERT (TimerFreq != 0);

  } else {
    DEBUG ((EFI_D_ERROR, "ARM Architectural Timer is not available in the CPU, hence this library can not be used.\n"));
    ASSERT (0);
  }

  return RETURN_SUCCESS;
}
Exemplo n.º 3
0
VOID
EFIAPI
ArmArchTimerWriteReg (
    IN   ARM_ARCH_TIMER_REGS   Reg,
    IN   VOID                  *SrcBuf
    )
{
  // Check if the Generic/Architecture timer is implemented
  if (ArmIsArchTimerImplemented ()) {

    switch (Reg) {

    case CntFrq:
      ArmWriteCntFrq (*((UINTN *)SrcBuf));
      break;

    case CntPct:
      DEBUG ((EFI_D_ERROR, "Can't write to Read Only Register: CNTPCT \n"));
      break;

    case CntkCtl:
      ArmWriteCntkCtl (*((UINTN *)SrcBuf));
      break;

    case CntpTval:
      ArmWriteCntpTval (*((UINTN *)SrcBuf));
      break;

    case CntpCtl:
      ArmWriteCntpCtl (*((UINTN *)SrcBuf));
      break;

    case CntvTval:
      ArmWriteCntvTval (*((UINTN *)SrcBuf));
      break;

    case CntvCtl:
      ArmWriteCntvCtl (*((UINTN *)SrcBuf));
      break;

    case CntvCt:
      DEBUG ((EFI_D_ERROR, "Can't write to Read Only Register: CNTVCT \n"));
      break;

    case CntpCval:
      ArmWriteCntpCval (*((UINT64 *)SrcBuf) );
      break;

    case CntvCval:
      ArmWriteCntvCval (*((UINT64 *)SrcBuf) );
      break;

    case CntvOff:
      ArmWriteCntvOff (*((UINT64 *)SrcBuf));
      break;

    case CnthCtl:
    case CnthpTval:
    case CnthpCtl:
    case CnthpCval:
      DEBUG ((EFI_D_ERROR, "The register is related to Hypervisor Mode. Can't perform requested operation\n "));
      break;

    default:
      DEBUG ((EFI_D_ERROR, "Unknown ARM Generic Timer register %x. \n ", Reg));
    }
  } else {
    DEBUG ((EFI_D_ERROR, "Attempt to write to ARM Generic Timer registers. But ARM Generic Timer extension is not implemented \n "));
    ASSERT (0);
  }
}
Exemplo n.º 4
0
VOID
EFIAPI
ArmArchTimerReadReg (
    IN   ARM_ARCH_TIMER_REGS   Reg,
    OUT  VOID                  *DstBuf
    )
{
  // Check if the Generic/Architecture timer is implemented
  if (ArmIsArchTimerImplemented ()) {
    switch (Reg) {
    case CntFrq:
      *((UINTN *)DstBuf) = ArmReadCntFrq ();
      return;

    case CntPct:
      *((UINT64 *)DstBuf) = ArmReadCntPct ();
      return;

    case CntkCtl:
      *((UINTN *)DstBuf) = ArmReadCntkCtl();
      return;

    case CntpTval:
      *((UINTN *)DstBuf) = ArmReadCntpTval ();
      return;

    case CntpCtl:
      *((UINTN *)DstBuf) = ArmReadCntpCtl ();
      return;

    case CntvTval:
      *((UINTN *)DstBuf) = ArmReadCntvTval ();
      return;

    case CntvCtl:
      *((UINTN *)DstBuf) = ArmReadCntvCtl ();
      return;

    case CntvCt:
      *((UINT64 *)DstBuf) = ArmReadCntvCt ();
      return;

    case CntpCval:
      *((UINT64 *)DstBuf) = ArmReadCntpCval ();
      return;

    case CntvCval:
      *((UINT64 *)DstBuf) = ArmReadCntvCval ();
      return;

    case CntvOff:
      *((UINT64 *)DstBuf) = ArmReadCntvOff ();
      return;

    case CnthCtl:
    case CnthpTval:
    case CnthpCtl:
    case CnthpCval:
      DEBUG ((EFI_D_ERROR, "The register is related to Hypervisor Mode. Can't perform requested operation\n "));
      break;

    default:
      DEBUG ((EFI_D_ERROR, "Unknown ARM Generic Timer register %x. \n ", Reg));
    }
  } else {
    DEBUG ((EFI_D_ERROR, "Attempt to read ARM Generic Timer registers. But ARM Generic Timer extension is not implemented \n "));
    ASSERT (0);
  }

  *((UINT64 *)DstBuf) = 0;
}