3 Copyright (c) 2013-2017, ARM Ltd. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
14 IN EFI_EXCEPTION_TYPE InterruptType
,
15 IN EFI_SYSTEM_CONTEXT SystemContext
20 ExitBootServicesEvent (
25 // Making this global saves a few bytes in image size
26 EFI_HANDLE gHardwareInterruptHandle
= NULL
;
29 EFI_EVENT EfiExitBootServicesEvent
= (EFI_EVENT
)NULL
;
31 // Maximum Number of Interrupts
32 UINTN mGicNumInterrupts
= 0;
34 HARDWARE_INTERRUPT_HANDLER
*gRegisteredInterruptHandlers
= NULL
;
38 Calculate GICD_ICFGRn base address and corresponding bit
39 field Int_config[1] of the GIC distributor register.
41 @param Source Hardware source of the interrupt.
42 @param RegAddress Corresponding GICD_ICFGRn base address.
43 @param Config1Bit Bit number of F Int_config[1] bit in the register.
45 @retval EFI_SUCCESS Source interrupt supported.
46 @retval EFI_UNSUPPORTED Source interrupt is not supported.
49 GicGetDistributorIcfgBaseAndBit (
50 IN HARDWARE_INTERRUPT_SOURCE Source
,
51 OUT UINTN
*RegAddress
,
58 if (Source
>= mGicNumInterrupts
) {
59 ASSERT(Source
< mGicNumInterrupts
);
60 return EFI_UNSUPPORTED
;
63 RegIndex
= Source
/ ARM_GIC_ICDICFR_F_STRIDE
; // NOTE: truncation is significant
64 Field
= Source
% ARM_GIC_ICDICFR_F_STRIDE
;
65 *RegAddress
= PcdGet64 (PcdGicDistributorBase
)
67 + (ARM_GIC_ICDICFR_BYTES
* RegIndex
);
68 *Config1Bit
= ((Field
* ARM_GIC_ICDICFR_F_WIDTH
)
69 + ARM_GIC_ICDICFR_F_CONFIG1_BIT
);
77 Register Handler for the specified interrupt source.
79 @param This Instance pointer for this protocol
80 @param Source Hardware source of the interrupt
81 @param Handler Callback for interrupt. NULL to unregister
83 @retval EFI_SUCCESS Source was updated to support Handler.
84 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
89 RegisterInterruptSource (
90 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*This
,
91 IN HARDWARE_INTERRUPT_SOURCE Source
,
92 IN HARDWARE_INTERRUPT_HANDLER Handler
95 if (Source
>= mGicNumInterrupts
) {
97 return EFI_UNSUPPORTED
;
100 if ((Handler
== NULL
) && (gRegisteredInterruptHandlers
[Source
] == NULL
)) {
101 return EFI_INVALID_PARAMETER
;
104 if ((Handler
!= NULL
) && (gRegisteredInterruptHandlers
[Source
] != NULL
)) {
105 return EFI_ALREADY_STARTED
;
108 gRegisteredInterruptHandlers
[Source
] = Handler
;
110 // If the interrupt handler is unregistered then disable the interrupt
111 if (NULL
== Handler
){
112 return This
->DisableInterruptSource (This
, Source
);
114 return This
->EnableInterruptSource (This
, Source
);
118 STATIC VOID
*mCpuArchProtocolNotifyEventRegistration
;
123 CpuArchEventProtocolNotify (
128 EFI_CPU_ARCH_PROTOCOL
*Cpu
;
131 // Get the CPU protocol that this driver requires.
132 Status
= gBS
->LocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
, (VOID
**)&Cpu
);
133 if (EFI_ERROR (Status
)) {
137 // Unregister the default exception handler.
138 Status
= Cpu
->RegisterInterruptHandler (Cpu
, ARM_ARCH_EXCEPTION_IRQ
, NULL
);
139 if (EFI_ERROR (Status
)) {
140 DEBUG ((DEBUG_ERROR
, "%a: Cpu->RegisterInterruptHandler() - %r\n",
141 __FUNCTION__
, Status
));
145 // Register to receive interrupts
146 Status
= Cpu
->RegisterInterruptHandler (Cpu
, ARM_ARCH_EXCEPTION_IRQ
,
148 if (EFI_ERROR (Status
)) {
149 DEBUG ((DEBUG_ERROR
, "%a: Cpu->RegisterInterruptHandler() - %r\n",
150 __FUNCTION__
, Status
));
153 gBS
->CloseEvent (Event
);
157 InstallAndRegisterInterruptService (
158 IN EFI_HARDWARE_INTERRUPT_PROTOCOL
*InterruptProtocol
,
159 IN EFI_HARDWARE_INTERRUPT2_PROTOCOL
*Interrupt2Protocol
,
160 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
,
161 IN EFI_EVENT_NOTIFY ExitBootServicesEvent
165 CONST UINTN RihArraySize
=
166 (sizeof(HARDWARE_INTERRUPT_HANDLER
) * mGicNumInterrupts
);
168 // Initialize the array for the Interrupt Handlers
169 gRegisteredInterruptHandlers
= AllocateZeroPool (RihArraySize
);
170 if (gRegisteredInterruptHandlers
== NULL
) {
171 return EFI_OUT_OF_RESOURCES
;
174 Status
= gBS
->InstallMultipleProtocolInterfaces (
175 &gHardwareInterruptHandle
,
176 &gHardwareInterruptProtocolGuid
,
178 &gHardwareInterrupt2ProtocolGuid
,
182 if (EFI_ERROR (Status
)) {
187 // Install the interrupt handler as soon as the CPU arch protocol appears.
189 EfiCreateProtocolNotifyEvent (
190 &gEfiCpuArchProtocolGuid
,
192 CpuArchEventProtocolNotify
,
194 &mCpuArchProtocolNotifyEventRegistration
);
196 // Register for an ExitBootServicesEvent
197 Status
= gBS
->CreateEvent (
198 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
200 ExitBootServicesEvent
,
202 &EfiExitBootServicesEvent