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