VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/ArmPkg/Drivers/ArmGic/ArmGicCommonDxe.c@ 101291

Last change on this file since 101291 was 101291, checked in by vboxsync, 14 months ago

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

  • Property svn:eol-style set to native
File size: 5.3 KB
Line 
1/*++
2
3Copyright (c) 2013-2023, Arm Ltd. All rights reserved.<BR>
4
5SPDX-License-Identifier: BSD-2-Clause-Patent
6
7--*/
8
9#include "ArmGicDxe.h"
10
11// Making this global saves a few bytes in image size
12EFI_HANDLE gHardwareInterruptHandle = NULL;
13
14// Notifications
15EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
16
17// Maximum Number of Interrupts
18UINTN mGicNumInterrupts = 0;
19
20HARDWARE_INTERRUPT_HANDLER *gRegisteredInterruptHandlers = NULL;
21
22/**
23 Calculate GICD_ICFGRn base address and corresponding bit
24 field Int_config[1] of the GIC distributor register.
25
26 @param Source Hardware source of the interrupt.
27 @param RegAddress Corresponding GICD_ICFGRn base address.
28 @param Config1Bit Bit number of F Int_config[1] bit in the register.
29
30 @retval EFI_SUCCESS Source interrupt supported.
31 @retval EFI_UNSUPPORTED Source interrupt is not supported.
32**/
33EFI_STATUS
34GicGetDistributorIcfgBaseAndBit (
35 IN HARDWARE_INTERRUPT_SOURCE Source,
36 OUT UINTN *RegAddress,
37 OUT UINTN *Config1Bit
38 )
39{
40 UINTN RegIndex;
41 UINTN Field;
42
43 if (Source >= mGicNumInterrupts) {
44 ASSERT (Source < mGicNumInterrupts);
45 return EFI_UNSUPPORTED;
46 }
47
48 RegIndex = Source / ARM_GIC_ICDICFR_F_STRIDE; // NOTE: truncation is significant
49 Field = Source % ARM_GIC_ICDICFR_F_STRIDE;
50 *RegAddress = (UINTN)PcdGet64 (PcdGicDistributorBase)
51 + ARM_GIC_ICDICFR
52 + (ARM_GIC_ICDICFR_BYTES * RegIndex);
53 *Config1Bit = ((Field * ARM_GIC_ICDICFR_F_WIDTH)
54 + ARM_GIC_ICDICFR_F_CONFIG1_BIT);
55
56 return EFI_SUCCESS;
57}
58
59/**
60 Register Handler for the specified interrupt source.
61
62 @param This Instance pointer for this protocol
63 @param Source Hardware source of the interrupt
64 @param Handler Callback for interrupt. NULL to unregister
65
66 @retval EFI_SUCCESS Source was updated to support Handler.
67 @retval EFI_DEVICE_ERROR Hardware could not be programmed.
68
69**/
70EFI_STATUS
71EFIAPI
72RegisterInterruptSource (
73 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
74 IN HARDWARE_INTERRUPT_SOURCE Source,
75 IN HARDWARE_INTERRUPT_HANDLER Handler
76 )
77{
78 if (Source >= mGicNumInterrupts) {
79 ASSERT (FALSE);
80 return EFI_UNSUPPORTED;
81 }
82
83 if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {
84 return EFI_INVALID_PARAMETER;
85 }
86
87 if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {
88 return EFI_ALREADY_STARTED;
89 }
90
91 gRegisteredInterruptHandlers[Source] = Handler;
92
93 // If the interrupt handler is unregistered then disable the interrupt
94 if (NULL == Handler) {
95 return This->DisableInterruptSource (This, Source);
96 } else {
97 return This->EnableInterruptSource (This, Source);
98 }
99}
100
101STATIC VOID *mCpuArchProtocolNotifyEventRegistration;
102
103STATIC
104VOID
105EFIAPI
106CpuArchEventProtocolNotify (
107 IN EFI_EVENT Event,
108 IN VOID *Context
109 )
110{
111 EFI_CPU_ARCH_PROTOCOL *Cpu;
112 EFI_STATUS Status;
113
114 // Get the CPU protocol that this driver requires.
115 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
116 if (EFI_ERROR (Status)) {
117 return;
118 }
119
120 // Unregister the default exception handler.
121 Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ, NULL);
122 if (EFI_ERROR (Status)) {
123 DEBUG ((
124 DEBUG_ERROR,
125 "%a: Cpu->RegisterInterruptHandler() - %r\n",
126 __func__,
127 Status
128 ));
129 return;
130 }
131
132 // Register to receive interrupts
133 Status = Cpu->RegisterInterruptHandler (
134 Cpu,
135 ARM_ARCH_EXCEPTION_IRQ,
136 Context
137 );
138 if (EFI_ERROR (Status)) {
139 DEBUG ((
140 DEBUG_ERROR,
141 "%a: Cpu->RegisterInterruptHandler() - %r\n",
142 __func__,
143 Status
144 ));
145 }
146
147 gBS->CloseEvent (Event);
148}
149
150EFI_STATUS
151InstallAndRegisterInterruptService (
152 IN EFI_HARDWARE_INTERRUPT_PROTOCOL *InterruptProtocol,
153 IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *Interrupt2Protocol,
154 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler,
155 IN EFI_EVENT_NOTIFY ExitBootServicesEvent
156 )
157{
158 EFI_STATUS Status;
159 CONST UINTN RihArraySize =
160 (sizeof (HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
161
162 // Initialize the array for the Interrupt Handlers
163 gRegisteredInterruptHandlers = AllocateZeroPool (RihArraySize);
164 if (gRegisteredInterruptHandlers == NULL) {
165 return EFI_OUT_OF_RESOURCES;
166 }
167
168 Status = gBS->InstallMultipleProtocolInterfaces (
169 &gHardwareInterruptHandle,
170 &gHardwareInterruptProtocolGuid,
171 InterruptProtocol,
172 &gHardwareInterrupt2ProtocolGuid,
173 Interrupt2Protocol,
174 NULL
175 );
176 if (EFI_ERROR (Status)) {
177 return Status;
178 }
179
180 //
181 // Install the interrupt handler as soon as the CPU arch protocol appears.
182 //
183 EfiCreateProtocolNotifyEvent (
184 &gEfiCpuArchProtocolGuid,
185 TPL_CALLBACK,
186 CpuArchEventProtocolNotify,
187 InterruptHandler,
188 &mCpuArchProtocolNotifyEventRegistration
189 );
190
191 // Register for an ExitBootServicesEvent
192 Status = gBS->CreateEvent (
193 EVT_SIGNAL_EXIT_BOOT_SERVICES,
194 TPL_NOTIFY,
195 ExitBootServicesEvent,
196 NULL,
197 &EfiExitBootServicesEvent
198 );
199
200 return Status;
201}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette