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