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