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