]> git.proxmox.com Git - mirror_edk2.git/blob - UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / UefiPayloadPkg / 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 if (FrameBufferBase == 0) {
434 FrameBufferBase = Resources->AddrRangeMin;
435 }
436
437 if (DeviceInfo->BarIndex == MAX_UINT8) {
438 if (Resources->AddrRangeMin == GraphicsInfo->FrameBufferBase) {
439 FrameBufferBase = Resources->AddrRangeMin;
440 break;
441 }
442 } else {
443 break;
444 }
445 }
446 }
447 }
448
449 if (Index == MAX_PCI_BAR) {
450 Status = EFI_UNSUPPORTED;
451 } else {
452 DEBUG ((DEBUG_INFO, "[%a]: ... matched!\n", gEfiCallerBaseName));
453 }
454 }
455 }
456
457 if (EFI_ERROR (Status)) {
458 goto CloseProtocols;
459 }
460
461 if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {
462 return EFI_SUCCESS;
463 }
464
465 Private = AllocateCopyPool (sizeof (mGraphicsOutputInstanceTemplate), &mGraphicsOutputInstanceTemplate);
466 if (Private == NULL) {
467 Status = EFI_OUT_OF_RESOURCES;
468 goto CloseProtocols;
469 }
470
471 Private->GraphicsOutputMode.FrameBufferBase = FrameBufferBase;
472 Private->GraphicsOutputMode.FrameBufferSize = GraphicsInfo->FrameBufferSize;
473 Private->GraphicsOutputMode.Info = &GraphicsInfo->GraphicsMode;
474
475 //
476 // Fix up Mode pointer in GraphicsOutput
477 //
478 Private->GraphicsOutput.Mode = &Private->GraphicsOutputMode;
479
480 //
481 // Set attributes
482 //
483 Status = PciIo->Attributes (
484 PciIo,
485 EfiPciIoAttributeOperationGet,
486 0,
487 &Private->PciAttributes
488 );
489 if (!EFI_ERROR (Status)) {
490 Status = PciIo->Attributes (
491 PciIo,
492 EfiPciIoAttributeOperationEnable,
493 EFI_PCI_DEVICE_ENABLE,
494 NULL
495 );
496 }
497
498 if (EFI_ERROR (Status)) {
499 goto FreeMemory;
500 }
501
502 //
503 // Create the FrameBufferBltLib configuration.
504 //
505 ReturnStatus = FrameBufferBltConfigure (
506 (VOID *)(UINTN)Private->GraphicsOutput.Mode->FrameBufferBase,
507 Private->GraphicsOutput.Mode->Info,
508 Private->FrameBufferBltLibConfigure,
509 &Private->FrameBufferBltLibConfigureSize
510 );
511 if (ReturnStatus == RETURN_BUFFER_TOO_SMALL) {
512 Private->FrameBufferBltLibConfigure = AllocatePool (Private->FrameBufferBltLibConfigureSize);
513 if (Private->FrameBufferBltLibConfigure != NULL) {
514 ReturnStatus = FrameBufferBltConfigure (
515 (VOID *)(UINTN)Private->GraphicsOutput.Mode->FrameBufferBase,
516 Private->GraphicsOutput.Mode->Info,
517 Private->FrameBufferBltLibConfigure,
518 &Private->FrameBufferBltLibConfigureSize
519 );
520 }
521 }
522
523 if (RETURN_ERROR (ReturnStatus)) {
524 Status = EFI_OUT_OF_RESOURCES;
525 goto RestorePciAttributes;
526 }
527
528 Private->DevicePath = AppendDevicePathNode (PciDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&mGraphicsOutputAdrNode);
529 if (Private->DevicePath == NULL) {
530 Status = EFI_OUT_OF_RESOURCES;
531 goto RestorePciAttributes;
532 }
533
534 Status = gBS->InstallMultipleProtocolInterfaces (
535 &Private->GraphicsOutputHandle,
536 &gEfiGraphicsOutputProtocolGuid,
537 &Private->GraphicsOutput,
538 &gEfiDevicePathProtocolGuid,
539 Private->DevicePath,
540 NULL
541 );
542
543 if (!EFI_ERROR (Status)) {
544 Status = gBS->OpenProtocol (
545 Controller,
546 &gEfiPciIoProtocolGuid,
547 (VOID **)&Private->PciIo,
548 This->DriverBindingHandle,
549 Private->GraphicsOutputHandle,
550 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
551 );
552 if (!EFI_ERROR (Status)) {
553 mDriverStarted = TRUE;
554 } else {
555 gBS->UninstallMultipleProtocolInterfaces (
556 Private->GraphicsOutputHandle,
557 &gEfiGraphicsOutputProtocolGuid,
558 &Private->GraphicsOutput,
559 &gEfiDevicePathProtocolGuid,
560 Private->DevicePath,
561 NULL
562 );
563 }
564 }
565
566 RestorePciAttributes:
567 if (EFI_ERROR (Status)) {
568 //
569 // Restore original PCI attributes
570 //
571 PciIo->Attributes (
572 PciIo,
573 EfiPciIoAttributeOperationSet,
574 Private->PciAttributes,
575 NULL
576 );
577 }
578
579 FreeMemory:
580 if (EFI_ERROR (Status)) {
581 if (Private != NULL) {
582 if (Private->DevicePath != NULL) {
583 FreePool (Private->DevicePath);
584 }
585
586 if (Private->FrameBufferBltLibConfigure != NULL) {
587 FreePool (Private->FrameBufferBltLibConfigure);
588 }
589
590 FreePool (Private);
591 }
592 }
593
594 CloseProtocols:
595 if (EFI_ERROR (Status)) {
596 //
597 // Close the PCI I/O Protocol
598 //
599 gBS->CloseProtocol (
600 Controller,
601 &gEfiDevicePathProtocolGuid,
602 This->DriverBindingHandle,
603 Controller
604 );
605
606 //
607 // Close the PCI I/O Protocol
608 //
609 gBS->CloseProtocol (
610 Controller,
611 &gEfiPciIoProtocolGuid,
612 This->DriverBindingHandle,
613 Controller
614 );
615 }
616
617 return Status;
618 }
619
620 /**
621 Stop the video controller.
622
623 @param This Driver Binding protocol instance pointer.
624 @param Controller The PCI controller.
625 @param NumberOfChildren The number of child device handles in ChildHandleBuffer.
626 @param ChildHandleBuffer An array of child handles to be freed. May be NULL
627 if NumberOfChildren is 0.
628
629 @retval EFI_SUCCESS The device was stopped.
630 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
631 **/
632 EFI_STATUS
633 EFIAPI
634 GraphicsOutputDriverBindingStop (
635 IN EFI_DRIVER_BINDING_PROTOCOL *This,
636 IN EFI_HANDLE Controller,
637 IN UINTN NumberOfChildren,
638 IN EFI_HANDLE *ChildHandleBuffer
639 )
640 {
641 EFI_STATUS Status;
642 EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
643 GRAPHICS_OUTPUT_PRIVATE_DATA *Private;
644
645 if (NumberOfChildren == 0) {
646 //
647 // Close the PCI I/O Protocol
648 //
649 Status = gBS->CloseProtocol (
650 Controller,
651 &gEfiPciIoProtocolGuid,
652 This->DriverBindingHandle,
653 Controller
654 );
655 ASSERT_EFI_ERROR (Status);
656
657 Status = gBS->CloseProtocol (
658 Controller,
659 &gEfiDevicePathProtocolGuid,
660 This->DriverBindingHandle,
661 Controller
662 );
663 ASSERT_EFI_ERROR (Status);
664 return EFI_SUCCESS;
665 }
666
667 ASSERT (NumberOfChildren == 1);
668 Status = gBS->OpenProtocol (
669 ChildHandleBuffer[0],
670 &gEfiGraphicsOutputProtocolGuid,
671 (VOID **)&Gop,
672 This->DriverBindingHandle,
673 ChildHandleBuffer[0],
674 EFI_OPEN_PROTOCOL_GET_PROTOCOL
675 );
676 if (EFI_ERROR (Status)) {
677 return Status;
678 }
679
680 Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (Gop);
681
682 Status = gBS->CloseProtocol (
683 Controller,
684 &gEfiPciIoProtocolGuid,
685 This->DriverBindingHandle,
686 Private->GraphicsOutputHandle
687 );
688 ASSERT_EFI_ERROR (Status);
689 //
690 // Remove the GOP protocol interface from the system
691 //
692 Status = gBS->UninstallMultipleProtocolInterfaces (
693 Private->GraphicsOutputHandle,
694 &gEfiGraphicsOutputProtocolGuid,
695 &Private->GraphicsOutput,
696 &gEfiDevicePathProtocolGuid,
697 Private->DevicePath,
698 NULL
699 );
700 if (!EFI_ERROR (Status)) {
701 //
702 // Restore original PCI attributes
703 //
704 Status = Private->PciIo->Attributes (
705 Private->PciIo,
706 EfiPciIoAttributeOperationSet,
707 Private->PciAttributes,
708 NULL
709 );
710 ASSERT_EFI_ERROR (Status);
711
712 FreePool (Private->DevicePath);
713 FreePool (Private->FrameBufferBltLibConfigure);
714 mDriverStarted = FALSE;
715 } else {
716 Status = gBS->OpenProtocol (
717 Controller,
718 &gEfiPciIoProtocolGuid,
719 (VOID **)&Private->PciIo,
720 This->DriverBindingHandle,
721 Private->GraphicsOutputHandle,
722 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
723 );
724 ASSERT_EFI_ERROR (Status);
725 }
726
727 return Status;
728 }
729
730 EFI_DRIVER_BINDING_PROTOCOL mGraphicsOutputDriverBinding = {
731 GraphicsOutputDriverBindingSupported,
732 GraphicsOutputDriverBindingStart,
733 GraphicsOutputDriverBindingStop,
734 0x10,
735 NULL,
736 NULL
737 };
738
739 /**
740 The Entry Point for GraphicsOutput driver.
741
742 It installs DriverBinding, ComponentName and ComponentName2 protocol if there is
743 GraphicsInfo HOB passed from Graphics PEIM.
744
745 @param[in] ImageHandle The firmware allocated handle for the EFI image.
746 @param[in] SystemTable A pointer to the EFI System Table.
747
748 @retval EFI_SUCCESS The entry point is executed successfully.
749 @retval other Some error occurs when executing this entry point.
750
751 **/
752 EFI_STATUS
753 EFIAPI
754 InitializeGraphicsOutput (
755 IN EFI_HANDLE ImageHandle,
756 IN EFI_SYSTEM_TABLE *SystemTable
757 )
758 {
759 EFI_STATUS Status;
760 VOID *HobStart;
761
762 HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid);
763
764 if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (EFI_PEI_GRAPHICS_INFO_HOB))) {
765 return EFI_NOT_FOUND;
766 }
767
768 Status = EfiLibInstallDriverBindingComponentName2 (
769 ImageHandle,
770 SystemTable,
771 &mGraphicsOutputDriverBinding,
772 ImageHandle,
773 &mGraphicsOutputComponentName,
774 &mGraphicsOutputComponentName2
775 );
776 ASSERT_EFI_ERROR (Status);
777
778 return Status;
779 }