VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.c@ 105668

最後變更 在這個檔案從105668是 101291,由 vboxsync 提交於 18 月 前

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

  • 屬性 svn:eol-style 設為 native
檔案大小: 21.2 KB
 
1/** @file
2 The UEFI driver model driver which is responsible for locating the
3 Redfish service through Redfish host interface and executing EDKII
4 Redfish feature drivers.
5
6 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
7 (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
8
9 SPDX-License-Identifier: BSD-2-Clause-Patent
10
11**/
12
13#include "RedfishConfigHandlerDriver.h"
14
15EFI_EVENT gEfiRedfishDiscoverProtocolEvent = NULL;
16
17//
18// Variables for using RFI Redfish Discover Protocol
19//
20VOID *gEfiRedfishDiscoverRegistration;
21EFI_HANDLE gEfiRedfishDiscoverControllerHandle = NULL;
22EFI_REDFISH_DISCOVER_PROTOCOL *gEfiRedfishDiscoverProtocol = NULL;
23BOOLEAN gRedfishDiscoverActivated = FALSE;
24BOOLEAN gRedfishServiceDiscovered = FALSE;
25
26///
27/// Driver Binding Protocol instance
28///
29EFI_DRIVER_BINDING_PROTOCOL gRedfishConfigDriverBinding = {
30 RedfishConfigDriverBindingSupported,
31 RedfishConfigDriverBindingStart,
32 RedfishConfigDriverBindingStop,
33 REDFISH_CONFIG_VERSION,
34 NULL,
35 NULL
36};
37
38/**
39 Stop acquiring Redfish service.
40
41**/
42VOID
43RedfishConfigStopRedfishDiscovery (
44 VOID
45 )
46{
47 if (gRedfishDiscoverActivated) {
48 //
49 // No more EFI Discover Protocol.
50 //
51 if (gEfiRedfishDiscoverProtocolEvent != NULL) {
52 gBS->CloseEvent (gEfiRedfishDiscoverProtocolEvent);
53 }
54
55 gEfiRedfishDiscoverControllerHandle = NULL;
56 gEfiRedfishDiscoverProtocol = NULL;
57 gRedfishDiscoverActivated = FALSE;
58 gRedfishServiceDiscovered = FALSE;
59 }
60}
61
62/**
63 Callback function executed when a Redfish Config Handler Protocol is installed.
64
65 @param[in] Event Event whose notification function is being invoked.
66 @param[in] Context Pointer to the REDFISH_CONFIG_DRIVER_DATA buffer.
67
68**/
69VOID
70EFIAPI
71RedfishConfigHandlerInstalledCallback (
72 IN EFI_EVENT Event,
73 IN VOID *Context
74 )
75{
76 if (!gRedfishDiscoverActivated) {
77 //
78 // No Redfish service is discovered yet.
79 //
80 return;
81 }
82
83 RedfishConfigHandlerInitialization ();
84}
85
86/**
87 Tests to see if this driver supports a given controller. If a child device is provided,
88 it further tests to see if this driver supports creating a handle for the specified child device.
89
90 This function checks to see if the driver specified by This supports the device specified by
91 ControllerHandle. Drivers will typically use the device path attached to
92 ControllerHandle and/or the services from the bus I/O abstraction attached to
93 ControllerHandle to determine if the driver supports ControllerHandle. This function
94 may be called many times during platform initialization. In order to reduce boot times, the tests
95 performed by this function must be very small, and take as little time as possible to execute. This
96 function must not change the state of any hardware devices, and this function must be aware that the
97 device specified by ControllerHandle may already be managed by the same driver or a
98 different driver. This function must match its calls to AllocatePages() with FreePages(),
99 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
100 Because ControllerHandle may have been previously started by the same driver, if a protocol is
101 already in the opened state, then it must not be closed with CloseProtocol(). This is required
102 to guarantee the state of ControllerHandle is not modified by this function.
103
104 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
105 @param[in] ControllerHandle The handle of the controller to test. This handle
106 must support a protocol interface that supplies
107 an I/O abstraction to the driver.
108 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
109 parameter is ignored by device drivers, and is optional for bus
110 drivers. For bus drivers, if this parameter is not NULL, then
111 the bus driver must determine if the bus controller specified
112 by ControllerHandle and the child controller specified
113 by RemainingDevicePath are both supported by this
114 bus driver.
115
116 @retval EFI_SUCCESS The device specified by ControllerHandle and
117 RemainingDevicePath is supported by the driver specified by This.
118 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
119 RemainingDevicePath is not supported by the driver specified by This.
120**/
121EFI_STATUS
122EFIAPI
123RedfishConfigDriverBindingSupported (
124 IN EFI_DRIVER_BINDING_PROTOCOL *This,
125 IN EFI_HANDLE ControllerHandle,
126 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
127 )
128{
129 EFI_REST_EX_PROTOCOL *RestEx;
130 EFI_STATUS Status;
131 EFI_HANDLE ChildHandle;
132
133 ChildHandle = NULL;
134
135 //
136 // Check if REST EX is ready. This just makes sure
137 // the network stack is brought up.
138 //
139 Status = NetLibCreateServiceChild (
140 ControllerHandle,
141 This->ImageHandle,
142 &gEfiRestExServiceBindingProtocolGuid,
143 &ChildHandle
144 );
145 if (EFI_ERROR (Status)) {
146 return EFI_UNSUPPORTED;
147 }
148
149 //
150 // Test if REST EX protocol is ready.
151 //
152 Status = gBS->OpenProtocol (
153 ChildHandle,
154 &gEfiRestExProtocolGuid,
155 (VOID **)&RestEx,
156 This->DriverBindingHandle,
157 ControllerHandle,
158 EFI_OPEN_PROTOCOL_GET_PROTOCOL
159 );
160 if (EFI_ERROR (Status)) {
161 Status = EFI_UNSUPPORTED;
162 }
163
164 NetLibDestroyServiceChild (
165 ControllerHandle,
166 This->ImageHandle,
167 &gEfiRestExServiceBindingProtocolGuid,
168 ChildHandle
169 );
170 return Status;
171}
172
173/**
174 Starts a device controller or a bus controller.
175
176 The Start() function is designed to be invoked from the EFI boot service ConnectController().
177 As a result, much of the error checking on the parameters to Start() has been moved into this
178 common boot service. It is legal to call Start() from other locations,
179 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
180 1. ControllerHandle must be a valid EFI_HANDLE.
181 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
182 EFI_DEVICE_PATH_PROTOCOL.
183 3. Prior to calling Start(), the Supported() function for the driver specified by This must
184 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
185
186 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
187 @param[in] ControllerHandle The handle of the controller to start. This handle
188 must support a protocol interface that supplies
189 an I/O abstraction to the driver.
190 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
191 parameter is ignored by device drivers, and is optional for bus
192 drivers. For a bus driver, if this parameter is NULL, then handles
193 for all the children of Controller are created by this driver.
194 If this parameter is not NULL and the first Device Path Node is
195 not the End of Device Path Node, then only the handle for the
196 child device specified by the first Device Path Node of
197 RemainingDevicePath is created by this driver.
198 If the first Device Path Node of RemainingDevicePath is
199 the End of Device Path Node, no child handle is created by this
200 driver.
201
202 @retval EFI_SUCCESS The driver is started.
203 @retval EFI_ALREADY_STARTED The driver was already started.
204
205**/
206EFI_STATUS
207EFIAPI
208RedfishConfigDriverBindingStart (
209 IN EFI_DRIVER_BINDING_PROTOCOL *This,
210 IN EFI_HANDLE ControllerHandle,
211 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
212 )
213{
214 VOID *ConfigHandlerRegistration;
215
216 if (gRedfishConfigData.Event != NULL) {
217 return EFI_ALREADY_STARTED;
218 }
219
220 gRedfishConfigData.Event = EfiCreateProtocolNotifyEvent (
221 &gEdkIIRedfishConfigHandlerProtocolGuid,
222 TPL_CALLBACK,
223 RedfishConfigHandlerInstalledCallback,
224 (VOID *)&gRedfishConfigData,
225 &ConfigHandlerRegistration
226 );
227 return EFI_SUCCESS;
228}
229
230/**
231 Stops a device controller or a bus controller.
232
233 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
234 As a result, much of the error checking on the parameters to Stop() has been moved
235 into this common boot service. It is legal to call Stop() from other locations,
236 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
237 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
238 same driver's Start() function.
239 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
240 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
241 Start() function, and the Start() function must have called OpenProtocol() on
242 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
243
244 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
245 @param[in] ControllerHandle A handle to the device being stopped. The handle must
246 support a bus specific I/O protocol for the driver
247 to use to stop the device.
248 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
249 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
250 if NumberOfChildren is 0.
251
252 @retval EFI_SUCCESS The device was stopped.
253 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
254
255**/
256EFI_STATUS
257EFIAPI
258RedfishConfigDriverBindingStop (
259 IN EFI_DRIVER_BINDING_PROTOCOL *This,
260 IN EFI_HANDLE ControllerHandle,
261 IN UINTN NumberOfChildren,
262 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
263 )
264{
265 EFI_STATUS Status;
266
267 if (ControllerHandle == gEfiRedfishDiscoverControllerHandle) {
268 RedfishConfigStopRedfishDiscovery ();
269 }
270
271 gBS->CloseProtocol (
272 ControllerHandle,
273 &gEfiRedfishDiscoverProtocolGuid,
274 gRedfishConfigData.Image,
275 gRedfishConfigData.Image
276 );
277
278 Status = RedfishConfigCommonStop ();
279 if (EFI_ERROR (Status)) {
280 return EFI_DEVICE_ERROR;
281 }
282
283 if (gRedfishConfigData.Event != NULL) {
284 gBS->CloseEvent (gRedfishConfigData.Event);
285 gRedfishConfigData.Event = NULL;
286 }
287
288 return EFI_SUCCESS;
289}
290
291/**
292 Callback function when Redfish service is discovered.
293
294 @param[in] Event Event whose notification function is being invoked.
295 @param[out] Context Pointer to the Context buffer
296
297**/
298VOID
299EFIAPI
300RedfishServiceDiscoveredCallback (
301 IN EFI_EVENT Event,
302 OUT VOID *Context
303 )
304{
305 EFI_REDFISH_DISCOVERED_TOKEN *RedfishDiscoveredToken;
306 EFI_REDFISH_DISCOVERED_INSTANCE *RedfishInstance;
307
308 RedfishDiscoveredToken = (EFI_REDFISH_DISCOVERED_TOKEN *)Context;
309 gBS->CloseEvent (RedfishDiscoveredToken->Event);
310
311 //
312 // Only support one Redfish service on platform.
313 //
314 if (!gRedfishServiceDiscovered) {
315 RedfishInstance = RedfishDiscoveredToken->DiscoverList.RedfishInstances;
316 //
317 // Only pick up the first found Redfish service.
318 //
319 if (RedfishInstance->Status == EFI_SUCCESS) {
320 gRedfishConfigData.RedfishServiceInfo.RedfishServiceRestExHandle = RedfishInstance->Information.RedfishRestExHandle;
321 gRedfishConfigData.RedfishServiceInfo.RedfishServiceVersion = RedfishInstance->Information.RedfishVersion;
322 gRedfishConfigData.RedfishServiceInfo.RedfishServiceLocation = RedfishInstance->Information.Location;
323 gRedfishConfigData.RedfishServiceInfo.RedfishServiceUuid = RedfishInstance->Information.Uuid;
324 gRedfishConfigData.RedfishServiceInfo.RedfishServiceOs = RedfishInstance->Information.Os;
325 gRedfishConfigData.RedfishServiceInfo.RedfishServiceOsVersion = RedfishInstance->Information.OsVersion;
326 gRedfishConfigData.RedfishServiceInfo.RedfishServiceProduct = RedfishInstance->Information.Product;
327 gRedfishConfigData.RedfishServiceInfo.RedfishServiceProductVer = RedfishInstance->Information.ProductVer;
328 gRedfishConfigData.RedfishServiceInfo.RedfishServiceUseHttps = RedfishInstance->Information.UseHttps;
329 gRedfishServiceDiscovered = TRUE;
330 }
331
332 //
333 // Invoke RedfishConfigHandlerInstalledCallback to execute
334 // the initialization of Redfish Configure Handler instance.
335 //
336 RedfishConfigHandlerInstalledCallback (gRedfishConfigData.Event, &gRedfishConfigData);
337 }
338
339 FreePool (RedfishDiscoveredToken);
340}
341
342/**
343 Callback function executed when the EFI_REDFISH_DISCOVER_PROTOCOL
344 protocol interface is installed.
345
346 @param[in] Event Event whose notification function is being invoked.
347 @param[out] Context Pointer to the Context buffer
348
349**/
350VOID
351EFIAPI
352RedfishDiscoverProtocolInstalled (
353 IN EFI_EVENT Event,
354 OUT VOID *Context
355 )
356{
357 EFI_STATUS Status;
358 UINTN BufferSize;
359 EFI_HANDLE HandleBuffer;
360 UINTN NetworkInterfaceIndex;
361 EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *ThisNetworkInterface;
362 EFI_REDFISH_DISCOVERED_TOKEN *ThisRedfishDiscoveredToken;
363 UINTN NumberOfNetworkInterfaces;
364
365 DEBUG ((DEBUG_MANAGEABILITY, "%a: New network interface is installed on system by EFI Redfish discover driver.\n", __func__));
366
367 BufferSize = sizeof (EFI_HANDLE);
368 Status = gBS->LocateHandle (
369 ByRegisterNotify,
370 NULL,
371 gEfiRedfishDiscoverRegistration,
372 &BufferSize,
373 &HandleBuffer
374 );
375 if (EFI_ERROR (Status)) {
376 DEBUG ((DEBUG_ERROR, "%a: Can't locate handle with EFI_REDFISH_DISCOVER_PROTOCOL installed.\n", __func__));
377 }
378
379 gRedfishDiscoverActivated = TRUE;
380 if (gEfiRedfishDiscoverProtocol == NULL) {
381 gEfiRedfishDiscoverControllerHandle = HandleBuffer;
382 //
383 // First time to open EFI_REDFISH_DISCOVER_PROTOCOL.
384 //
385 Status = gBS->OpenProtocol (
386 gEfiRedfishDiscoverControllerHandle,
387 &gEfiRedfishDiscoverProtocolGuid,
388 (VOID **)&gEfiRedfishDiscoverProtocol,
389 gRedfishConfigData.Image,
390 gRedfishConfigData.Image,
391 EFI_OPEN_PROTOCOL_BY_DRIVER
392 );
393 if (EFI_ERROR (Status)) {
394 gEfiRedfishDiscoverProtocol = NULL;
395 gRedfishDiscoverActivated = FALSE;
396 DEBUG ((DEBUG_ERROR, "%a: Can't locate EFI_REDFISH_DISCOVER_PROTOCOL.\n", __func__));
397 return;
398 }
399 }
400
401 Status = gEfiRedfishDiscoverProtocol->GetNetworkInterfaceList (
402 gEfiRedfishDiscoverProtocol,
403 gRedfishConfigData.Image,
404 &NumberOfNetworkInterfaces,
405 &ThisNetworkInterface
406 );
407 if (EFI_ERROR (Status) || (NumberOfNetworkInterfaces == 0)) {
408 DEBUG ((DEBUG_ERROR, "%a: No network interfaces found on the handle.\n", __func__));
409 return;
410 }
411
412 //
413 // Loop to discover Redfish service on each network interface.
414 //
415 for (NetworkInterfaceIndex = 0; NetworkInterfaceIndex < NumberOfNetworkInterfaces; NetworkInterfaceIndex++) {
416 ThisRedfishDiscoveredToken = (EFI_REDFISH_DISCOVERED_TOKEN *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVERED_TOKEN));
417 if (ThisRedfishDiscoveredToken == NULL) {
418 DEBUG ((DEBUG_ERROR, "%a: Not enough memory for EFI_REDFISH_DISCOVERED_TOKEN.\n", __func__));
419 return;
420 }
421
422 ThisRedfishDiscoveredToken->Signature = REDFISH_DISCOVER_TOKEN_SIGNATURE;
423
424 //
425 // Initial this Redfish Discovered Token
426 //
427 Status = gBS->CreateEvent (
428 EVT_NOTIFY_SIGNAL,
429 TPL_CALLBACK,
430 RedfishServiceDiscoveredCallback,
431 (VOID *)ThisRedfishDiscoveredToken,
432 &ThisRedfishDiscoveredToken->Event
433 );
434 if (EFI_ERROR (Status)) {
435 FreePool (ThisRedfishDiscoveredToken);
436 DEBUG ((DEBUG_ERROR, "%a: Failed to create event for Redfish discovered token.\n", __func__));
437 return;
438 }
439
440 //
441 // Acquire for Redfish service which is reported by
442 // Redfish Host Interface.
443 //
444 Status = gEfiRedfishDiscoverProtocol->AcquireRedfishService (
445 gEfiRedfishDiscoverProtocol,
446 gRedfishConfigData.Image,
447 ThisNetworkInterface,
448 EFI_REDFISH_DISCOVER_HOST_INTERFACE,
449 ThisRedfishDiscoveredToken
450 );
451
452 //
453 // Free Redfish Discovered Token if Discover Instance was not created and
454 // Redfish Service Discovered Callback event was not triggered.
455 //
456 if ((ThisRedfishDiscoveredToken->DiscoverList.NumberOfServiceFound == 0) ||
457 EFI_ERROR (ThisRedfishDiscoveredToken->DiscoverList.RedfishInstances->Status))
458 {
459 gBS->CloseEvent (ThisRedfishDiscoveredToken->Event);
460 DEBUG ((DEBUG_ERROR, "%a: Free Redfish discovered token - %x.\n", __func__, ThisRedfishDiscoveredToken));
461 FreePool (ThisRedfishDiscoveredToken);
462 }
463
464 ThisNetworkInterface++;
465 }
466
467 return;
468}
469
470/**
471 Unloads an image.
472
473 @param[in] ImageHandle Handle that identifies the image to be unloaded.
474
475 @retval EFI_SUCCESS The image has been unloaded.
476
477**/
478EFI_STATUS
479EFIAPI
480RedfishConfigHandlerDriverUnload (
481 IN EFI_HANDLE ImageHandle
482 )
483{
484 RedfishConfigDriverCommonUnload (ImageHandle);
485
486 RedfishConfigStopRedfishDiscovery ();
487
488 return EFI_SUCCESS;
489}
490
491/**
492 This is the declaration of an EFI image entry point. This entry point is
493 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
494 both device drivers and bus drivers.
495
496 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
497 @param[in] SystemTable A pointer to the EFI System Table.
498
499 @retval EFI_SUCCESS The operation completed successfully.
500 @retval Others An unexpected error occurred.
501**/
502EFI_STATUS
503EFIAPI
504RedfishConfigHandlerDriverEntryPoint (
505 IN EFI_HANDLE ImageHandle,
506 IN EFI_SYSTEM_TABLE *SystemTable
507 )
508{
509 EFI_STATUS Status;
510
511 ZeroMem ((VOID *)&gRedfishConfigData, sizeof (REDFISH_CONFIG_DRIVER_DATA));
512 gRedfishConfigData.Image = ImageHandle;
513 //
514 // Register event for EFI_REDFISH_DISCOVER_PROTOCOL protocol install
515 // notification.
516 //
517 Status = gBS->CreateEventEx (
518 EVT_NOTIFY_SIGNAL,
519 TPL_CALLBACK,
520 RedfishDiscoverProtocolInstalled,
521 NULL,
522 &gEfiRedfishDiscoverProtocolGuid,
523 &gEfiRedfishDiscoverProtocolEvent
524 );
525 if (EFI_ERROR (Status)) {
526 DEBUG ((DEBUG_ERROR, "%a: Fail to create event for the installation of EFI_REDFISH_DISCOVER_PROTOCOL.", __func__));
527 return Status;
528 }
529
530 Status = gBS->RegisterProtocolNotify (
531 &gEfiRedfishDiscoverProtocolGuid,
532 gEfiRedfishDiscoverProtocolEvent,
533 &gEfiRedfishDiscoverRegistration
534 );
535 if (EFI_ERROR (Status)) {
536 DEBUG ((DEBUG_ERROR, "%a: Fail to register event for the installation of EFI_REDFISH_DISCOVER_PROTOCOL.", __func__));
537 return Status;
538 }
539
540 Status = RedfishConfigCommonInit (ImageHandle, SystemTable);
541 if (EFI_ERROR (Status)) {
542 gBS->CloseEvent (gEfiRedfishDiscoverProtocolEvent);
543 gEfiRedfishDiscoverProtocolEvent = NULL;
544 return Status;
545 }
546
547 //
548 // Install UEFI Driver Model protocol(s).
549 //
550 Status = EfiLibInstallDriverBinding (
551 ImageHandle,
552 SystemTable,
553 &gRedfishConfigDriverBinding,
554 ImageHandle
555 );
556 if (EFI_ERROR (Status)) {
557 gBS->CloseEvent (gEndOfDxeEvent);
558 gEndOfDxeEvent = NULL;
559 gBS->CloseEvent (gExitBootServiceEvent);
560 gExitBootServiceEvent = NULL;
561 gBS->CloseEvent (gEfiRedfishDiscoverProtocolEvent);
562 gEfiRedfishDiscoverProtocolEvent = NULL;
563 DEBUG ((DEBUG_ERROR, "%a: Fail to install EFI Binding Protocol of EFI Redfish Config driver.", __func__));
564 return Status;
565 }
566
567 return Status;
568}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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