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