]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Console/GraphicsOutputDxe/GraphicsOutput.c
MdeModulePkg: Change OPTIONAL keyword usage style
[mirror_edk2.git] / MdeModulePkg / Universal / Console / GraphicsOutputDxe / GraphicsOutput.c
1 /** @file
2 Implementation for a generic GOP driver.
3
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7
8 **/
9
10 #include "GraphicsOutput.h"
11 CONST ACPI_ADR_DEVICE_PATH mGraphicsOutputAdrNode = {
12 {
13 ACPI_DEVICE_PATH,
14 ACPI_ADR_DP,
15 { sizeof (ACPI_ADR_DEVICE_PATH), 0 },
16 },
17 ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0)
18 };
19
20 EFI_PEI_GRAPHICS_DEVICE_INFO_HOB mDefaultGraphicsDeviceInfo = {
21 MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT8, MAX_UINT8
22 };
23
24 //
25 // The driver should only start on one graphics controller.
26 // So a global flag is used to remember that the driver is already started.
27 //
28 BOOLEAN mDriverStarted = FALSE;
29
30 /**
31 Returns information for an available graphics mode that the graphics device
32 and the set of active video output devices supports.
33
34 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
35 @param ModeNumber The mode number to return information on.
36 @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer.
37 @param Info A pointer to callee allocated buffer that returns information about ModeNumber.
38
39 @retval EFI_SUCCESS Valid mode information was returned.
40 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode.
41 @retval EFI_INVALID_PARAMETER ModeNumber is not valid.
42
43 **/
44 EFI_STATUS
45 EFIAPI
46 GraphicsOutputQueryMode (
47 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
48 IN UINT32 ModeNumber,
49 OUT UINTN *SizeOfInfo,
50 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
51 )
52 {
53 if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
54 return EFI_INVALID_PARAMETER;
55 }
56
57 *SizeOfInfo = This->Mode->SizeOfInfo;
58 *Info = AllocateCopyPool (*SizeOfInfo, This->Mode->Info);
59 return EFI_SUCCESS;
60 }
61
62 /**
63 Set the video device into the specified mode and clears the visible portions of
64 the output display to black.
65
66 @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
67 @param ModeNumber Abstraction that defines the current video mode.
68
69 @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected.
70 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
71 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
72
73 **/
74 EFI_STATUS
75 EFIAPI
76 GraphicsOutputSetMode (
77 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
78 IN UINT32 ModeNumber
79 )
80 {
81 RETURN_STATUS Status;
82 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black;
83 GRAPHICS_OUTPUT_PRIVATE_DATA *Private;
84
85 if (ModeNumber >= This->Mode->MaxMode) {
86 return EFI_UNSUPPORTED;
87 }
88
89 Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This);
90
91 Black.Blue = 0;
92 Black.Green = 0;
93 Black.Red = 0;
94 Black.Reserved = 0;
95
96 Status = FrameBufferBlt (
97 Private->FrameBufferBltLibConfigure,
98 &Black,
99 EfiBltVideoFill,
100 0, 0,
101 0, 0,
102 This->Mode->Info->HorizontalResolution,
103 This->Mode->Info->VerticalResolution,
104 0
105 );
106 return RETURN_ERROR (Status) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
107 }
108
109 /**
110 Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer.
111
112 @param This Protocol instance pointer.
113 @param BltBuffer The data to transfer to the graphics screen.
114 Size is at least Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL).
115 @param BltOperation The operation to perform when copying BltBuffer on to the graphics screen.
116 @param SourceX The X coordinate of source for the BltOperation.
117 @param SourceY The Y coordinate of source for the BltOperation.
118 @param DestinationX The X coordinate of destination for the BltOperation.
119 @param DestinationY The Y coordinate of destination for the BltOperation.
120 @param Width The width of a rectangle in the blt rectangle in pixels.
121 @param Height The height of a rectangle in the blt rectangle in pixels.
122 @param Delta Not used for EfiBltVideoFill or the EfiBltVideoToVideo operation.
123 If a Delta of zero is used, the entire BltBuffer is being operated on.
124 If a subrectangle of the BltBuffer is being used then Delta
125 represents the number of bytes in a row of the BltBuffer.
126
127 @retval EFI_SUCCESS BltBuffer was drawn to the graphics screen.
128 @retval EFI_INVALID_PARAMETER BltOperation is not valid.
129 @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
130
131 **/
132 EFI_STATUS
133 EFIAPI
134 GraphicsOutputBlt (
135 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
136 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,
137 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
138 IN UINTN SourceX,
139 IN UINTN SourceY,
140 IN UINTN DestinationX,
141 IN UINTN DestinationY,
142 IN UINTN Width,
143 IN UINTN Height,
144 IN UINTN Delta OPTIONAL
145 )
146 {
147 RETURN_STATUS Status;
148 EFI_TPL Tpl;
149 GRAPHICS_OUTPUT_PRIVATE_DATA *Private;
150
151 Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This);
152 //
153 // We have to raise to TPL_NOTIFY, so we make an atomic write to the frame buffer.
154 // We would not want a timer based event (Cursor, ...) to come in while we are
155 // doing this operation.
156 //
157 Tpl = gBS->RaiseTPL (TPL_NOTIFY);
158 Status = FrameBufferBlt (
159 Private->FrameBufferBltLibConfigure,
160 BltBuffer,
161 BltOperation,
162 SourceX, SourceY,
163 DestinationX, DestinationY, Width, Height,
164 Delta
165 );
166 gBS->RestoreTPL (Tpl);
167
168 return RETURN_ERROR (Status) ? EFI_INVALID_PARAMETER : EFI_SUCCESS;
169 }
170
171 CONST GRAPHICS_OUTPUT_PRIVATE_DATA mGraphicsOutputInstanceTemplate = {
172 GRAPHICS_OUTPUT_PRIVATE_DATA_SIGNATURE, // Signature
173 NULL, // GraphicsOutputHandle
174 {
175 GraphicsOutputQueryMode,
176 GraphicsOutputSetMode,
177 GraphicsOutputBlt,
178 NULL // Mode
179 },
180 {
181 1, // MaxMode
182 0, // Mode
183 NULL, // Info
184 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), // SizeOfInfo
185 0, // FrameBufferBase
186 0 // FrameBufferSize
187 },
188 NULL, // DevicePath
189 NULL, // PciIo
190 0, // PciAttributes
191 NULL, // FrameBufferBltLibConfigure
192 0 // FrameBufferBltLibConfigureSize
193 };
194
195 /**
196 Test whether the Controller can be managed by the driver.
197
198 @param This Driver Binding protocol instance pointer.
199 @param Controller The PCI controller.
200 @param RemainingDevicePath Optional parameter use to pick a specific child
201 device to start.
202
203 @retval EFI_SUCCESS The driver can manage the video device.
204 @retval other The driver cannot manage the video device.
205 **/
206 EFI_STATUS
207 EFIAPI
208 GraphicsOutputDriverBindingSupported (
209 IN EFI_DRIVER_BINDING_PROTOCOL *This,
210 IN EFI_HANDLE Controller,
211 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
212 )
213 {
214 EFI_STATUS Status;
215 EFI_PCI_IO_PROTOCOL *PciIo;
216 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
217
218 //
219 // Since there is only one GraphicsInfo HOB, the driver only manages one video device.
220 //
221 if (mDriverStarted) {
222 return EFI_ALREADY_STARTED;
223 }
224
225 //
226 // Test the PCI I/O Protocol
227 //
228 Status = gBS->OpenProtocol (
229 Controller,
230 &gEfiPciIoProtocolGuid,
231 (VOID **) &PciIo,
232 This->DriverBindingHandle,
233 Controller,
234 EFI_OPEN_PROTOCOL_BY_DRIVER
235 );
236 if (Status == EFI_ALREADY_STARTED) {
237 Status = EFI_SUCCESS;
238 }
239 if (EFI_ERROR (Status)) {
240 return Status;
241 }
242 gBS->CloseProtocol (
243 Controller,
244 &gEfiPciIoProtocolGuid,
245 This->DriverBindingHandle,
246 Controller
247 );
248
249 //
250 // Test the DevicePath protocol
251 //
252 Status = gBS->OpenProtocol (
253 Controller,
254 &gEfiDevicePathProtocolGuid,
255 (VOID **) &DevicePath,
256 This->DriverBindingHandle,
257 Controller,
258 EFI_OPEN_PROTOCOL_BY_DRIVER
259 );
260 if (Status == EFI_ALREADY_STARTED) {
261 Status = EFI_SUCCESS;
262 }
263 if (EFI_ERROR (Status)) {
264 return Status;
265 }
266 gBS->CloseProtocol (
267 Controller,
268 &gEfiDevicePathProtocolGuid,
269 This->DriverBindingHandle,
270 Controller
271 );
272
273 if ((RemainingDevicePath == NULL) ||
274 IsDevicePathEnd (RemainingDevicePath) ||
275 CompareMem (RemainingDevicePath, &mGraphicsOutputAdrNode, sizeof (mGraphicsOutputAdrNode)) == 0) {
276 return EFI_SUCCESS;
277 } else {
278 return EFI_INVALID_PARAMETER;
279 }
280 }
281
282 /**
283 Start the video controller.
284
285 @param This Driver Binding protocol instance pointer.
286 @param ControllerHandle The PCI controller.
287 @param RemainingDevicePath Optional parameter use to pick a specific child
288 device to start.
289
290 @retval EFI_SUCCESS The driver starts to manage the video device.
291 @retval other The driver cannot manage the video device.
292 **/
293 EFI_STATUS
294 EFIAPI
295 GraphicsOutputDriverBindingStart (
296 IN EFI_DRIVER_BINDING_PROTOCOL *This,
297 IN EFI_HANDLE Controller,
298 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
299 )
300 {
301 EFI_STATUS Status;
302 RETURN_STATUS ReturnStatus;
303 GRAPHICS_OUTPUT_PRIVATE_DATA *Private;
304 EFI_PCI_IO_PROTOCOL *PciIo;
305 EFI_DEVICE_PATH *PciDevicePath;
306 PCI_TYPE00 Pci;
307 UINT8 Index;
308 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;
309 VOID *HobStart;
310 EFI_PEI_GRAPHICS_INFO_HOB *GraphicsInfo;
311 EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *DeviceInfo;
312 EFI_PHYSICAL_ADDRESS FrameBufferBase;
313
314 FrameBufferBase = 0;
315
316 HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid);
317 ASSERT ((HobStart != NULL) && (GET_GUID_HOB_DATA_SIZE (HobStart) == sizeof (EFI_PEI_GRAPHICS_INFO_HOB)));
318 GraphicsInfo = (EFI_PEI_GRAPHICS_INFO_HOB *) (GET_GUID_HOB_DATA (HobStart));
319
320 HobStart = GetFirstGuidHob (&gEfiGraphicsDeviceInfoHobGuid);
321 if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (*DeviceInfo))) {
322 //
323 // Use default device infomation when the device info HOB doesn't exist
324 //
325 DeviceInfo = &mDefaultGraphicsDeviceInfo;
326 DEBUG ((DEBUG_INFO, "[%a]: GraphicsDeviceInfo HOB doesn't exist!\n", gEfiCallerBaseName));
327 } else {
328 DeviceInfo = (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *) (GET_GUID_HOB_DATA (HobStart));
329 DEBUG ((DEBUG_INFO, "[%a]: GraphicsDeviceInfo HOB:\n"
330 " VendorId = %04x, DeviceId = %04x,\n"
331 " RevisionId = %02x, BarIndex = %x,\n"
332 " SubsystemVendorId = %04x, SubsystemId = %04x\n",
333 gEfiCallerBaseName,
334 DeviceInfo->VendorId, DeviceInfo->DeviceId,
335 DeviceInfo->RevisionId, DeviceInfo->BarIndex,
336 DeviceInfo->SubsystemVendorId, DeviceInfo->SubsystemId));
337 }
338
339 //
340 // Open the PCI I/O Protocol
341 //
342 Status = gBS->OpenProtocol (
343 Controller,
344 &gEfiPciIoProtocolGuid,
345 (VOID **) &PciIo,
346 This->DriverBindingHandle,
347 Controller,
348 EFI_OPEN_PROTOCOL_BY_DRIVER
349 );
350 if (Status == EFI_ALREADY_STARTED) {
351 Status = EFI_SUCCESS;
352 }
353 ASSERT_EFI_ERROR (Status);
354
355 Status = gBS->OpenProtocol (
356 Controller,
357 &gEfiDevicePathProtocolGuid,
358 (VOID **) &PciDevicePath,
359 This->DriverBindingHandle,
360 Controller,
361 EFI_OPEN_PROTOCOL_BY_DRIVER
362 );
363 if (Status == EFI_ALREADY_STARTED) {
364 Status = EFI_SUCCESS;
365 }
366 ASSERT_EFI_ERROR (Status);
367
368 //
369 // Read the PCI Class Code from the PCI Device
370 //
371 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci);
372 if (!EFI_ERROR (Status)) {
373 if (!IS_PCI_DISPLAY (&Pci) || (
374 ((DeviceInfo->VendorId != MAX_UINT16) && (DeviceInfo->VendorId != Pci.Hdr.VendorId)) ||
375 ((DeviceInfo->DeviceId != MAX_UINT16) && (DeviceInfo->DeviceId != Pci.Hdr.DeviceId)) ||
376 ((DeviceInfo->RevisionId != MAX_UINT8) && (DeviceInfo->RevisionId != Pci.Hdr.RevisionID)) ||
377 ((DeviceInfo->SubsystemVendorId != MAX_UINT16) && (DeviceInfo->SubsystemVendorId != Pci.Device.SubsystemVendorID)) ||
378 ((DeviceInfo->SubsystemId != MAX_UINT16) && (DeviceInfo->SubsystemId != Pci.Device.SubsystemID))
379 )
380 ) {
381 //
382 // It's not a video device, or device infomation doesn't match.
383 //
384 Status = EFI_UNSUPPORTED;
385 } else {
386 //
387 // If it's a video device and device information matches, use the BarIndex
388 // from device information, or any BAR if BarIndex is not specified
389 // whose size >= the frame buffer size from GraphicsInfo HOB.
390 // Store the new frame buffer base.
391 //
392 for (Index = 0; Index < MAX_PCI_BAR; Index++) {
393 if ((DeviceInfo->BarIndex != MAX_UINT8) && (DeviceInfo->BarIndex != Index)) {
394 continue;
395 }
396 Status = PciIo->GetBarAttributes (PciIo, Index, NULL, (VOID**) &Resources);
397 if (!EFI_ERROR (Status)) {
398 DEBUG ((DEBUG_INFO, "[%a]: BAR[%d]: Base = %lx, Length = %lx\n",
399 gEfiCallerBaseName, Index, Resources->AddrRangeMin, Resources->AddrLen));
400 if ((Resources->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) &&
401 (Resources->Len == (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3)) &&
402 (Resources->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) &&
403 (Resources->AddrLen >= GraphicsInfo->FrameBufferSize)
404 ) {
405 FrameBufferBase = Resources->AddrRangeMin;
406 DEBUG ((DEBUG_INFO, "[%a]: ... matched!\n", gEfiCallerBaseName));
407 break;
408 }
409 }
410 }
411 if (Index == MAX_PCI_BAR) {
412 Status = EFI_UNSUPPORTED;
413 }
414 }
415 }
416
417 if (EFI_ERROR (Status)) {
418 goto CloseProtocols;
419 }
420
421 if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {
422 return EFI_SUCCESS;
423 }
424
425 Private = AllocateCopyPool (sizeof (mGraphicsOutputInstanceTemplate), &mGraphicsOutputInstanceTemplate);
426 if (Private == NULL) {
427 Status = EFI_OUT_OF_RESOURCES;
428 goto CloseProtocols;
429 }
430
431 Private->GraphicsOutputMode.FrameBufferBase = FrameBufferBase;
432 Private->GraphicsOutputMode.FrameBufferSize = GraphicsInfo->FrameBufferSize;
433 Private->GraphicsOutputMode.Info = &GraphicsInfo->GraphicsMode;
434
435 //
436 // Fix up Mode pointer in GraphicsOutput
437 //
438 Private->GraphicsOutput.Mode = &Private->GraphicsOutputMode;
439
440 //
441 // Set attributes
442 //
443 Status = PciIo->Attributes (
444 PciIo,
445 EfiPciIoAttributeOperationGet,
446 0,
447 &Private->PciAttributes
448 );
449 if (!EFI_ERROR (Status)) {
450 Status = PciIo->Attributes (
451 PciIo,
452 EfiPciIoAttributeOperationEnable,
453 EFI_PCI_DEVICE_ENABLE,
454 NULL
455 );
456 }
457
458 if (EFI_ERROR (Status)) {
459 goto FreeMemory;
460 }
461
462 //
463 // Create the FrameBufferBltLib configuration.
464 //
465 ReturnStatus = FrameBufferBltConfigure (
466 (VOID *) (UINTN) Private->GraphicsOutput.Mode->FrameBufferBase,
467 Private->GraphicsOutput.Mode->Info,
468 Private->FrameBufferBltLibConfigure,
469 &Private->FrameBufferBltLibConfigureSize
470 );
471 if (ReturnStatus == RETURN_BUFFER_TOO_SMALL) {
472 Private->FrameBufferBltLibConfigure = AllocatePool (Private->FrameBufferBltLibConfigureSize);
473 if (Private->FrameBufferBltLibConfigure != NULL) {
474 ReturnStatus = FrameBufferBltConfigure (
475 (VOID *) (UINTN) Private->GraphicsOutput.Mode->FrameBufferBase,
476 Private->GraphicsOutput.Mode->Info,
477 Private->FrameBufferBltLibConfigure,
478 &Private->FrameBufferBltLibConfigureSize
479 );
480 }
481 }
482 if (RETURN_ERROR (ReturnStatus)) {
483 Status = EFI_OUT_OF_RESOURCES;
484 goto RestorePciAttributes;
485 }
486
487 Private->DevicePath = AppendDevicePathNode (PciDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &mGraphicsOutputAdrNode);
488 if (Private->DevicePath == NULL) {
489 Status = EFI_OUT_OF_RESOURCES;
490 goto RestorePciAttributes;
491 }
492
493 Status = gBS->InstallMultipleProtocolInterfaces (
494 &Private->GraphicsOutputHandle,
495 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput,
496 &gEfiDevicePathProtocolGuid, Private->DevicePath,
497 NULL
498 );
499
500 if (!EFI_ERROR (Status)) {
501 Status = gBS->OpenProtocol (
502 Controller,
503 &gEfiPciIoProtocolGuid,
504 (VOID **) &Private->PciIo,
505 This->DriverBindingHandle,
506 Private->GraphicsOutputHandle,
507 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
508 );
509 if (!EFI_ERROR (Status)) {
510 mDriverStarted = TRUE;
511 } else {
512 gBS->UninstallMultipleProtocolInterfaces (
513 Private->GraphicsOutputHandle,
514 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput,
515 &gEfiDevicePathProtocolGuid, Private->DevicePath,
516 NULL
517 );
518 }
519 }
520
521 RestorePciAttributes:
522 if (EFI_ERROR (Status)) {
523 //
524 // Restore original PCI attributes
525 //
526 PciIo->Attributes (
527 PciIo,
528 EfiPciIoAttributeOperationSet,
529 Private->PciAttributes,
530 NULL
531 );
532 }
533
534 FreeMemory:
535 if (EFI_ERROR (Status)) {
536 if (Private != NULL) {
537 if (Private->DevicePath != NULL) {
538 FreePool (Private->DevicePath);
539 }
540 if (Private->FrameBufferBltLibConfigure != NULL) {
541 FreePool (Private->FrameBufferBltLibConfigure);
542 }
543 FreePool (Private);
544 }
545 }
546
547 CloseProtocols:
548 if (EFI_ERROR (Status)) {
549 //
550 // Close the PCI I/O Protocol
551 //
552 gBS->CloseProtocol (
553 Controller,
554 &gEfiDevicePathProtocolGuid,
555 This->DriverBindingHandle,
556 Controller
557 );
558
559 //
560 // Close the PCI I/O Protocol
561 //
562 gBS->CloseProtocol (
563 Controller,
564 &gEfiPciIoProtocolGuid,
565 This->DriverBindingHandle,
566 Controller
567 );
568 }
569 return Status;
570 }
571
572 /**
573 Stop the video controller.
574
575 @param This Driver Binding protocol instance pointer.
576 @param Controller The PCI controller.
577 @param NumberOfChildren The number of child device handles in ChildHandleBuffer.
578 @param ChildHandleBuffer An array of child handles to be freed. May be NULL
579 if NumberOfChildren is 0.
580
581 @retval EFI_SUCCESS The device was stopped.
582 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
583 **/
584 EFI_STATUS
585 EFIAPI
586 GraphicsOutputDriverBindingStop (
587 IN EFI_DRIVER_BINDING_PROTOCOL *This,
588 IN EFI_HANDLE Controller,
589 IN UINTN NumberOfChildren,
590 IN EFI_HANDLE *ChildHandleBuffer
591 )
592 {
593 EFI_STATUS Status;
594 EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
595 GRAPHICS_OUTPUT_PRIVATE_DATA *Private;
596
597 if (NumberOfChildren == 0) {
598
599 //
600 // Close the PCI I/O Protocol
601 //
602 Status = gBS->CloseProtocol (
603 Controller,
604 &gEfiPciIoProtocolGuid,
605 This->DriverBindingHandle,
606 Controller
607 );
608 ASSERT_EFI_ERROR (Status);
609
610 Status = gBS->CloseProtocol (
611 Controller,
612 &gEfiDevicePathProtocolGuid,
613 This->DriverBindingHandle,
614 Controller
615 );
616 ASSERT_EFI_ERROR (Status);
617 return EFI_SUCCESS;
618 }
619
620 ASSERT (NumberOfChildren == 1);
621 Status = gBS->OpenProtocol (
622 ChildHandleBuffer[0],
623 &gEfiGraphicsOutputProtocolGuid,
624 (VOID **) &Gop,
625 This->DriverBindingHandle,
626 ChildHandleBuffer[0],
627 EFI_OPEN_PROTOCOL_GET_PROTOCOL
628 );
629 if (EFI_ERROR (Status)) {
630 return Status;
631 }
632
633 Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (Gop);
634
635 Status = gBS->CloseProtocol (
636 Controller,
637 &gEfiPciIoProtocolGuid,
638 This->DriverBindingHandle,
639 Private->GraphicsOutputHandle
640 );
641 ASSERT_EFI_ERROR (Status);
642 //
643 // Remove the GOP protocol interface from the system
644 //
645 Status = gBS->UninstallMultipleProtocolInterfaces (
646 Private->GraphicsOutputHandle,
647 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput,
648 &gEfiDevicePathProtocolGuid, Private->DevicePath,
649 NULL
650 );
651 if (!EFI_ERROR (Status)) {
652 //
653 // Restore original PCI attributes
654 //
655 Status = Private->PciIo->Attributes (
656 Private->PciIo,
657 EfiPciIoAttributeOperationSet,
658 Private->PciAttributes,
659 NULL
660 );
661 ASSERT_EFI_ERROR (Status);
662
663 FreePool (Private->DevicePath);
664 FreePool (Private->FrameBufferBltLibConfigure);
665 mDriverStarted = FALSE;
666 } else {
667 Status = gBS->OpenProtocol (
668 Controller,
669 &gEfiPciIoProtocolGuid,
670 (VOID **) &Private->PciIo,
671 This->DriverBindingHandle,
672 Private->GraphicsOutputHandle,
673 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
674 );
675 ASSERT_EFI_ERROR (Status);
676 }
677 return Status;
678 }
679
680 EFI_DRIVER_BINDING_PROTOCOL mGraphicsOutputDriverBinding = {
681 GraphicsOutputDriverBindingSupported,
682 GraphicsOutputDriverBindingStart,
683 GraphicsOutputDriverBindingStop,
684 0x10,
685 NULL,
686 NULL
687 };
688
689 /**
690 The Entry Point for GraphicsOutput driver.
691
692 It installs DriverBinding, ComponentName and ComponentName2 protocol if there is
693 GraphicsInfo HOB passed from Graphics PEIM.
694
695 @param[in] ImageHandle The firmware allocated handle for the EFI image.
696 @param[in] SystemTable A pointer to the EFI System Table.
697
698 @retval EFI_SUCCESS The entry point is executed successfully.
699 @retval other Some error occurs when executing this entry point.
700
701 **/
702 EFI_STATUS
703 EFIAPI
704 InitializeGraphicsOutput (
705 IN EFI_HANDLE ImageHandle,
706 IN EFI_SYSTEM_TABLE *SystemTable
707 )
708 {
709 EFI_STATUS Status;
710 VOID *HobStart;
711
712 HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid);
713
714 if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (EFI_PEI_GRAPHICS_INFO_HOB))) {
715 return EFI_NOT_FOUND;
716 }
717
718 Status = EfiLibInstallDriverBindingComponentName2 (
719 ImageHandle,
720 SystemTable,
721 &mGraphicsOutputDriverBinding,
722 ImageHandle,
723 &mGraphicsOutputComponentName,
724 &mGraphicsOutputComponentName2
725 );
726 ASSERT_EFI_ERROR (Status);
727
728 return Status;
729 }