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