FbGop.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527
  1. /** @file
  2. ConsoleOut Routines that speak VGA.
  3. Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
  4. This program and the accompanying materials
  5. are licensed and made available under the terms and conditions
  6. of the BSD License which accompanies this distribution. The
  7. full text of the license may be found at
  8. http://opensource.org/licenses/bsd-license.php
  9. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  11. **/
  12. #include "FbGop.h"
  13. EFI_PIXEL_BITMASK mPixelBitMask = {0x0000FF, 0x00FF00, 0xFF0000, 0x000000};
  14. //
  15. // Save controller attributes during first start
  16. //
  17. UINT64 mOriginalPciAttributes;
  18. BOOLEAN mPciAttributesSaved = FALSE;
  19. //
  20. // EFI Driver Binding Protocol Instance
  21. //
  22. EFI_DRIVER_BINDING_PROTOCOL gFbGopDriverBinding = {
  23. FbGopDriverBindingSupported,
  24. FbGopDriverBindingStart,
  25. FbGopDriverBindingStop,
  26. 0x3,
  27. NULL,
  28. NULL
  29. };
  30. //
  31. // Native resolution in EDID DetailedTiming[0]
  32. //
  33. UINT32 mNativeModeHorizontal;
  34. UINT32 mNativeModeVertical;
  35. /**
  36. Supported.
  37. @param This Pointer to driver binding protocol
  38. @param Controller Controller handle to connect
  39. @param RemainingDevicePath A pointer to the remaining portion of a device
  40. path
  41. @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this
  42. driver, Otherwise, this controller cannot be
  43. managed by this driver
  44. **/
  45. EFI_STATUS
  46. EFIAPI
  47. FbGopDriverBindingSupported (
  48. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  49. IN EFI_HANDLE Controller,
  50. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  51. )
  52. {
  53. EFI_STATUS Status;
  54. EFI_PCI_IO_PROTOCOL *PciIo;
  55. PCI_TYPE00 Pci;
  56. EFI_DEV_PATH *Node;
  57. //
  58. // Open the IO Abstraction(s) needed to perform the supported test
  59. //
  60. Status = gBS->OpenProtocol (
  61. Controller,
  62. &gEfiPciIoProtocolGuid,
  63. (VOID **) &PciIo,
  64. This->DriverBindingHandle,
  65. Controller,
  66. EFI_OPEN_PROTOCOL_BY_DRIVER
  67. );
  68. if (EFI_ERROR (Status)) {
  69. return Status;
  70. }
  71. //
  72. // See if this is a PCI Graphics Controller by looking at the Command register and
  73. // Class Code Register
  74. //
  75. Status = PciIo->Pci.Read (
  76. PciIo,
  77. EfiPciIoWidthUint32,
  78. 0,
  79. sizeof (Pci) / sizeof (UINT32),
  80. &Pci
  81. );
  82. if (EFI_ERROR (Status)) {
  83. Status = EFI_UNSUPPORTED;
  84. goto Done;
  85. }
  86. Status = EFI_UNSUPPORTED;
  87. if (Pci.Hdr.ClassCode[2] == 0x03 || (Pci.Hdr.ClassCode[2] == 0x00 && Pci.Hdr.ClassCode[1] == 0x01)) {
  88. Status = EFI_SUCCESS;
  89. //
  90. // If this is a graphics controller,
  91. // go further check RemainingDevicePath validation
  92. //
  93. if (RemainingDevicePath != NULL) {
  94. Node = (EFI_DEV_PATH *) RemainingDevicePath;
  95. //
  96. // Check if RemainingDevicePath is the End of Device Path Node,
  97. // if yes, return EFI_SUCCESS
  98. //
  99. if (!IsDevicePathEnd (Node)) {
  100. //
  101. // If RemainingDevicePath isn't the End of Device Path Node,
  102. // check its validation
  103. //
  104. if (Node->DevPath.Type != ACPI_DEVICE_PATH ||
  105. Node->DevPath.SubType != ACPI_ADR_DP ||
  106. DevicePathNodeLength(&Node->DevPath) < sizeof(ACPI_ADR_DEVICE_PATH)) {
  107. Status = EFI_UNSUPPORTED;
  108. }
  109. }
  110. }
  111. }
  112. Done:
  113. gBS->CloseProtocol (
  114. Controller,
  115. &gEfiPciIoProtocolGuid,
  116. This->DriverBindingHandle,
  117. Controller
  118. );
  119. return Status;
  120. }
  121. /**
  122. Install Graphics Output Protocol onto VGA device handles.
  123. @param This Pointer to driver binding protocol
  124. @param Controller Controller handle to connect
  125. @param RemainingDevicePath A pointer to the remaining portion of a device
  126. path
  127. @return EFI_STATUS
  128. **/
  129. EFI_STATUS
  130. EFIAPI
  131. FbGopDriverBindingStart (
  132. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  133. IN EFI_HANDLE Controller,
  134. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  135. )
  136. {
  137. EFI_STATUS Status;
  138. EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
  139. EFI_PCI_IO_PROTOCOL *PciIo;
  140. UINT64 Supports;
  141. DEBUG ((EFI_D_INFO, "GOP START\n"));
  142. //
  143. // Initialize local variables
  144. //
  145. PciIo = NULL;
  146. ParentDevicePath = NULL;
  147. //
  148. // Prepare for status code
  149. //
  150. Status = gBS->HandleProtocol (
  151. Controller,
  152. &gEfiDevicePathProtocolGuid,
  153. (VOID **) &ParentDevicePath
  154. );
  155. if (EFI_ERROR (Status)) {
  156. return Status;
  157. }
  158. //
  159. // Open the IO Abstraction(s) needed
  160. //
  161. Status = gBS->OpenProtocol (
  162. Controller,
  163. &gEfiPciIoProtocolGuid,
  164. (VOID **) &PciIo,
  165. This->DriverBindingHandle,
  166. Controller,
  167. EFI_OPEN_PROTOCOL_BY_DRIVER
  168. );
  169. if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
  170. return Status;
  171. }
  172. //
  173. // Save original PCI attributes
  174. //
  175. if (!mPciAttributesSaved) {
  176. Status = PciIo->Attributes (
  177. PciIo,
  178. EfiPciIoAttributeOperationGet,
  179. 0,
  180. &mOriginalPciAttributes
  181. );
  182. if (EFI_ERROR (Status)) {
  183. goto Done;
  184. }
  185. mPciAttributesSaved = TRUE;
  186. }
  187. //
  188. // Get supported PCI attributes
  189. //
  190. Status = PciIo->Attributes (
  191. PciIo,
  192. EfiPciIoAttributeOperationSupported,
  193. 0,
  194. &Supports
  195. );
  196. if (EFI_ERROR (Status)) {
  197. goto Done;
  198. }
  199. Supports &= (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
  200. if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) {
  201. Status = EFI_UNSUPPORTED;
  202. goto Done;
  203. }
  204. REPORT_STATUS_CODE_WITH_DEVICE_PATH (
  205. EFI_PROGRESS_CODE,
  206. EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_ENABLE,
  207. ParentDevicePath
  208. );
  209. //
  210. // Enable the device and make sure VGA cycles are being forwarded to this VGA device
  211. //
  212. Status = PciIo->Attributes (
  213. PciIo,
  214. EfiPciIoAttributeOperationEnable,
  215. EFI_PCI_DEVICE_ENABLE,
  216. NULL
  217. );
  218. if (EFI_ERROR (Status)) {
  219. REPORT_STATUS_CODE_WITH_DEVICE_PATH (
  220. EFI_ERROR_CODE | EFI_ERROR_MINOR,
  221. EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_RESOURCE_CONFLICT,
  222. ParentDevicePath
  223. );
  224. goto Done;
  225. }
  226. if (RemainingDevicePath != NULL) {
  227. if (IsDevicePathEnd (RemainingDevicePath)) {
  228. //
  229. // If RemainingDevicePath is the End of Device Path Node,
  230. // don't create any child device and return EFI_SUCCESS
  231. Status = EFI_SUCCESS;
  232. goto Done;
  233. }
  234. }
  235. //
  236. // Create child handle and install GraphicsOutputProtocol on it
  237. //
  238. Status = FbGopChildHandleInstall (
  239. This,
  240. Controller,
  241. PciIo,
  242. NULL,
  243. ParentDevicePath,
  244. RemainingDevicePath
  245. );
  246. Done:
  247. if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
  248. REPORT_STATUS_CODE_WITH_DEVICE_PATH (
  249. EFI_PROGRESS_CODE,
  250. EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_PC_DISABLE,
  251. ParentDevicePath
  252. );
  253. REPORT_STATUS_CODE_WITH_DEVICE_PATH (
  254. EFI_PROGRESS_CODE,
  255. EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_NOT_DETECTED,
  256. ParentDevicePath
  257. );
  258. if (!HasChildHandle (Controller)) {
  259. if (mPciAttributesSaved) {
  260. //
  261. // Restore original PCI attributes
  262. //
  263. PciIo->Attributes (
  264. PciIo,
  265. EfiPciIoAttributeOperationSet,
  266. mOriginalPciAttributes,
  267. NULL
  268. );
  269. }
  270. }
  271. //
  272. // Release PCI I/O Protocols on the controller handle.
  273. //
  274. gBS->CloseProtocol (
  275. Controller,
  276. &gEfiPciIoProtocolGuid,
  277. This->DriverBindingHandle,
  278. Controller
  279. );
  280. }
  281. return Status;
  282. }
  283. /**
  284. Stop.
  285. @param This Pointer to driver binding protocol
  286. @param Controller Controller handle to connect
  287. @param NumberOfChildren Number of children handle created by this driver
  288. @param ChildHandleBuffer Buffer containing child handle created
  289. @retval EFI_SUCCESS Driver disconnected successfully from controller
  290. @retval EFI_UNSUPPORTED Cannot find FB_VIDEO_DEV structure
  291. **/
  292. EFI_STATUS
  293. EFIAPI
  294. FbGopDriverBindingStop (
  295. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  296. IN EFI_HANDLE Controller,
  297. IN UINTN NumberOfChildren,
  298. IN EFI_HANDLE *ChildHandleBuffer
  299. )
  300. {
  301. EFI_STATUS Status;
  302. BOOLEAN AllChildrenStopped;
  303. UINTN Index;
  304. EFI_PCI_IO_PROTOCOL *PciIo;
  305. AllChildrenStopped = TRUE;
  306. if (NumberOfChildren == 0) {
  307. //
  308. // Close PCI I/O protocol on the controller handle
  309. //
  310. gBS->CloseProtocol (
  311. Controller,
  312. &gEfiPciIoProtocolGuid,
  313. This->DriverBindingHandle,
  314. Controller
  315. );
  316. return EFI_SUCCESS;
  317. }
  318. for (Index = 0; Index < NumberOfChildren; Index++) {
  319. Status = EFI_SUCCESS;
  320. FbGopChildHandleUninstall (This, Controller, ChildHandleBuffer[Index]);
  321. if (EFI_ERROR (Status)) {
  322. AllChildrenStopped = FALSE;
  323. }
  324. }
  325. if (!AllChildrenStopped) {
  326. return EFI_DEVICE_ERROR;
  327. }
  328. if (!HasChildHandle (Controller)) {
  329. if (mPciAttributesSaved) {
  330. Status = gBS->HandleProtocol (
  331. Controller,
  332. &gEfiPciIoProtocolGuid,
  333. (VOID **) &PciIo
  334. );
  335. ASSERT_EFI_ERROR (Status);
  336. //
  337. // Restore original PCI attributes
  338. //
  339. Status = PciIo->Attributes (
  340. PciIo,
  341. EfiPciIoAttributeOperationSet,
  342. mOriginalPciAttributes,
  343. NULL
  344. );
  345. ASSERT_EFI_ERROR (Status);
  346. }
  347. }
  348. return EFI_SUCCESS;
  349. }
  350. /**
  351. Install child handles if the Handle supports MBR format.
  352. @param This Calling context.
  353. @param ParentHandle Parent Handle
  354. @param ParentPciIo Parent PciIo interface
  355. @param ParentLegacyBios Parent LegacyBios interface
  356. @param ParentDevicePath Parent Device Path
  357. @param RemainingDevicePath Remaining Device Path
  358. @retval EFI_SUCCESS If a child handle was added
  359. @retval other A child handle was not added
  360. **/
  361. EFI_STATUS
  362. FbGopChildHandleInstall (
  363. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  364. IN EFI_HANDLE ParentHandle,
  365. IN EFI_PCI_IO_PROTOCOL *ParentPciIo,
  366. IN VOID *ParentLegacyBios,
  367. IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
  368. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  369. )
  370. {
  371. EFI_STATUS Status;
  372. FB_VIDEO_DEV *FbGopPrivate;
  373. PCI_TYPE00 Pci;
  374. ACPI_ADR_DEVICE_PATH AcpiDeviceNode;
  375. //
  376. // Allocate the private device structure for video device
  377. //
  378. FbGopPrivate = (FB_VIDEO_DEV *) AllocateZeroPool (
  379. sizeof (FB_VIDEO_DEV)
  380. );
  381. if (NULL == FbGopPrivate) {
  382. Status = EFI_OUT_OF_RESOURCES;
  383. goto Done;
  384. }
  385. //
  386. // See if this is a VGA compatible controller or not
  387. //
  388. Status = ParentPciIo->Pci.Read (
  389. ParentPciIo,
  390. EfiPciIoWidthUint32,
  391. 0,
  392. sizeof (Pci) / sizeof (UINT32),
  393. &Pci
  394. );
  395. if (EFI_ERROR (Status)) {
  396. REPORT_STATUS_CODE_WITH_DEVICE_PATH (
  397. EFI_ERROR_CODE | EFI_ERROR_MINOR,
  398. EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR,
  399. ParentDevicePath
  400. );
  401. goto Done;
  402. }
  403. //
  404. // Initialize the child private structure
  405. //
  406. FbGopPrivate->Signature = FB_VIDEO_DEV_SIGNATURE;
  407. //
  408. // Fill in Graphics Output specific mode structures
  409. //
  410. FbGopPrivate->ModeData = NULL;
  411. FbGopPrivate->VbeFrameBuffer = NULL;
  412. FbGopPrivate->EdidDiscovered.SizeOfEdid = 0;
  413. FbGopPrivate->EdidDiscovered.Edid = NULL;
  414. FbGopPrivate->EdidActive.SizeOfEdid = 0;
  415. FbGopPrivate->EdidActive.Edid = NULL;
  416. //
  417. // Fill in the Graphics Output Protocol
  418. //
  419. FbGopPrivate->GraphicsOutput.QueryMode = FbGopGraphicsOutputQueryMode;
  420. FbGopPrivate->GraphicsOutput.SetMode = FbGopGraphicsOutputSetMode;
  421. //
  422. // Allocate buffer for Graphics Output Protocol mode information
  423. //
  424. FbGopPrivate->GraphicsOutput.Mode = (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *) AllocatePool (
  425. sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE)
  426. );
  427. if (NULL == FbGopPrivate->GraphicsOutput.Mode) {
  428. Status = EFI_OUT_OF_RESOURCES;
  429. goto Done;
  430. }
  431. FbGopPrivate->GraphicsOutput.Mode->Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (
  432. sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
  433. );
  434. if (NULL == FbGopPrivate->GraphicsOutput.Mode->Info) {
  435. Status = EFI_OUT_OF_RESOURCES;
  436. goto Done;
  437. }
  438. //
  439. // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.
  440. //
  441. if ((RemainingDevicePath == NULL) || (!IsDevicePathEnd (RemainingDevicePath))) {
  442. if (RemainingDevicePath == NULL) {
  443. ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));
  444. AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
  445. AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
  446. AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);
  447. SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));
  448. FbGopPrivate->GopDevicePath = AppendDevicePathNode (
  449. ParentDevicePath,
  450. (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode
  451. );
  452. } else {
  453. FbGopPrivate->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);
  454. }
  455. //
  456. // Creat child handle and device path protocol firstly
  457. //
  458. FbGopPrivate->Handle = NULL;
  459. Status = gBS->InstallMultipleProtocolInterfaces (
  460. &FbGopPrivate->Handle,
  461. &gEfiDevicePathProtocolGuid,
  462. FbGopPrivate->GopDevicePath,
  463. NULL
  464. );
  465. if (EFI_ERROR (Status)) {
  466. goto Done;
  467. }
  468. }
  469. //
  470. // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
  471. //
  472. FbGopPrivate->PciIo = ParentPciIo;
  473. //
  474. // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
  475. //
  476. Status = FbGopCheckForVbe (FbGopPrivate);
  477. DEBUG ((EFI_D_INFO, "FbGopCheckForVbe - %r\n", Status));
  478. if (EFI_ERROR (Status)) {
  479. Status = EFI_UNSUPPORTED;
  480. //goto Done;
  481. }
  482. //
  483. // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
  484. //
  485. Status = gBS->InstallMultipleProtocolInterfaces (
  486. &FbGopPrivate->Handle,
  487. &gEfiGraphicsOutputProtocolGuid,
  488. &FbGopPrivate->GraphicsOutput,
  489. &gEfiEdidDiscoveredProtocolGuid,
  490. &FbGopPrivate->EdidDiscovered,
  491. &gEfiEdidActiveProtocolGuid,
  492. &FbGopPrivate->EdidActive,
  493. NULL
  494. );
  495. if (!EFI_ERROR (Status)) {
  496. //
  497. // Open the Parent Handle for the child
  498. //
  499. Status = gBS->OpenProtocol (
  500. ParentHandle,
  501. &gEfiPciIoProtocolGuid,
  502. (VOID **) &FbGopPrivate->PciIo,
  503. This->DriverBindingHandle,
  504. FbGopPrivate->Handle,
  505. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  506. );
  507. if (EFI_ERROR (Status)) {
  508. goto Done;
  509. }
  510. }
  511. Done:
  512. if (EFI_ERROR (Status)) {
  513. //
  514. // Free private data structure
  515. //
  516. FbGopDeviceReleaseResource (FbGopPrivate);
  517. }
  518. return Status;
  519. }
  520. /**
  521. Deregister an video child handle and free resources.
  522. @param This Protocol instance pointer.
  523. @param Controller Video controller handle
  524. @param Handle Video child handle
  525. @return EFI_STATUS
  526. **/
  527. EFI_STATUS
  528. FbGopChildHandleUninstall (
  529. EFI_DRIVER_BINDING_PROTOCOL *This,
  530. EFI_HANDLE Controller,
  531. EFI_HANDLE Handle
  532. )
  533. {
  534. EFI_STATUS Status;
  535. EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
  536. FB_VIDEO_DEV *FbGopPrivate;
  537. EFI_PCI_IO_PROTOCOL *PciIo;
  538. FbGopPrivate = NULL;
  539. GraphicsOutput = NULL;
  540. PciIo = NULL;
  541. Status = EFI_UNSUPPORTED;
  542. Status = gBS->OpenProtocol (
  543. Handle,
  544. &gEfiGraphicsOutputProtocolGuid,
  545. (VOID **) &GraphicsOutput,
  546. This->DriverBindingHandle,
  547. Handle,
  548. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  549. );
  550. if (!EFI_ERROR (Status)) {
  551. FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);
  552. }
  553. if (FbGopPrivate == NULL) {
  554. return EFI_UNSUPPORTED;
  555. }
  556. //
  557. // Close PCI I/O protocol that opened by child handle
  558. //
  559. Status = gBS->CloseProtocol (
  560. Controller,
  561. &gEfiPciIoProtocolGuid,
  562. This->DriverBindingHandle,
  563. Handle
  564. );
  565. //
  566. // Uninstall protocols on child handle
  567. //
  568. Status = gBS->UninstallMultipleProtocolInterfaces (
  569. FbGopPrivate->Handle,
  570. &gEfiDevicePathProtocolGuid,
  571. FbGopPrivate->GopDevicePath,
  572. &gEfiGraphicsOutputProtocolGuid,
  573. &FbGopPrivate->GraphicsOutput,
  574. NULL
  575. );
  576. if (EFI_ERROR (Status)) {
  577. gBS->OpenProtocol (
  578. Controller,
  579. &gEfiPciIoProtocolGuid,
  580. (VOID **) &PciIo,
  581. This->DriverBindingHandle,
  582. Handle,
  583. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  584. );
  585. return Status;
  586. }
  587. //
  588. // Release all allocated resources
  589. //
  590. FbGopDeviceReleaseResource (FbGopPrivate);
  591. return EFI_SUCCESS;
  592. }
  593. /**
  594. Release resource for bios video instance.
  595. @param FbGopPrivate Video child device private data structure
  596. **/
  597. VOID
  598. FbGopDeviceReleaseResource (
  599. FB_VIDEO_DEV *FbGopPrivate
  600. )
  601. {
  602. if (FbGopPrivate == NULL) {
  603. return ;
  604. }
  605. //
  606. // Release all the resources occupied by the FB_VIDEO_DEV
  607. //
  608. //
  609. // Free VBE Frame Buffer
  610. //
  611. if (FbGopPrivate->VbeFrameBuffer != NULL) {
  612. FreePool (FbGopPrivate->VbeFrameBuffer);
  613. }
  614. //
  615. // Free mode data
  616. //
  617. if (FbGopPrivate->ModeData != NULL) {
  618. FreePool (FbGopPrivate->ModeData);
  619. }
  620. //
  621. // Free graphics output protocol occupied resource
  622. //
  623. if (FbGopPrivate->GraphicsOutput.Mode != NULL) {
  624. if (FbGopPrivate->GraphicsOutput.Mode->Info != NULL) {
  625. FreePool (FbGopPrivate->GraphicsOutput.Mode->Info);
  626. FbGopPrivate->GraphicsOutput.Mode->Info = NULL;
  627. }
  628. FreePool (FbGopPrivate->GraphicsOutput.Mode);
  629. FbGopPrivate->GraphicsOutput.Mode = NULL;
  630. }
  631. if (FbGopPrivate->GopDevicePath!= NULL) {
  632. FreePool (FbGopPrivate->GopDevicePath);
  633. }
  634. FreePool (FbGopPrivate);
  635. return ;
  636. }
  637. /**
  638. Check if all video child handles have been uninstalled.
  639. @param Controller Video controller handle
  640. @return TRUE Child handles exist.
  641. @return FALSE All video child handles have been uninstalled.
  642. **/
  643. BOOLEAN
  644. HasChildHandle (
  645. IN EFI_HANDLE Controller
  646. )
  647. {
  648. UINTN Index;
  649. EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
  650. UINTN EntryCount;
  651. BOOLEAN HasChild;
  652. EntryCount = 0;
  653. HasChild = FALSE;
  654. gBS->OpenProtocolInformation (
  655. Controller,
  656. &gEfiPciIoProtocolGuid,
  657. &OpenInfoBuffer,
  658. &EntryCount
  659. );
  660. for (Index = 0; Index < EntryCount; Index++) {
  661. if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
  662. HasChild = TRUE;
  663. }
  664. }
  665. return HasChild;
  666. }
  667. /**
  668. Check for VBE device.
  669. @param FbGopPrivate Pointer to FB_VIDEO_DEV structure
  670. @retval EFI_SUCCESS VBE device found
  671. **/
  672. EFI_STATUS
  673. FbGopCheckForVbe (
  674. IN OUT FB_VIDEO_DEV *FbGopPrivate
  675. )
  676. {
  677. EFI_STATUS Status;
  678. FB_VIDEO_MODE_DATA *ModeBuffer;
  679. FB_VIDEO_MODE_DATA *CurrentModeData;
  680. UINTN ModeNumber;
  681. UINTN BitsPerPixel;
  682. UINTN BytesPerScanLine;
  683. UINT32 HorizontalResolution;
  684. UINT32 VerticalResolution;
  685. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;
  686. EFI_HOB_GUID_TYPE *GuidHob;
  687. FRAME_BUFFER_INFO *pFbInfo;
  688. Status = EFI_SUCCESS;
  689. //
  690. // Find the frame buffer information guid hob
  691. //
  692. GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid);
  693. ASSERT (GuidHob != NULL);
  694. pFbInfo = (FRAME_BUFFER_INFO *)GET_GUID_HOB_DATA (GuidHob);
  695. //
  696. // Add mode to the list of available modes
  697. //
  698. VbeFrameBuffer = NULL;
  699. ModeBuffer = NULL;
  700. ModeNumber = 1;
  701. BitsPerPixel = pFbInfo->BitsPerPixel;
  702. HorizontalResolution = pFbInfo->HorizontalResolution;
  703. VerticalResolution = pFbInfo->VerticalResolution;
  704. BytesPerScanLine = pFbInfo->BytesPerScanLine;
  705. ModeBuffer = (FB_VIDEO_MODE_DATA *) AllocatePool (
  706. ModeNumber * sizeof (FB_VIDEO_MODE_DATA)
  707. );
  708. if (NULL == ModeBuffer) {
  709. Status = EFI_OUT_OF_RESOURCES;
  710. goto Done;
  711. }
  712. VbeFrameBuffer =
  713. (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) AllocatePool (
  714. BytesPerScanLine * VerticalResolution
  715. );
  716. if (NULL == VbeFrameBuffer) {
  717. Status = EFI_OUT_OF_RESOURCES;
  718. goto Done;
  719. }
  720. if (FbGopPrivate->ModeData != NULL) {
  721. FreePool (FbGopPrivate->ModeData);
  722. }
  723. if (FbGopPrivate->VbeFrameBuffer != NULL) {
  724. FreePool (FbGopPrivate->VbeFrameBuffer);
  725. }
  726. CurrentModeData = &ModeBuffer[ModeNumber - 1];
  727. CurrentModeData->BytesPerScanLine = (UINT16)BytesPerScanLine;
  728. CurrentModeData->Red = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Red);
  729. CurrentModeData->Blue = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Blue);
  730. CurrentModeData->Green = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Green);
  731. CurrentModeData->Reserved = *(FB_VIDEO_COLOR_PLACEMENT *)&(pFbInfo->Reserved);
  732. CurrentModeData->BitsPerPixel = (UINT32)BitsPerPixel;
  733. CurrentModeData->HorizontalResolution = HorizontalResolution;
  734. CurrentModeData->VerticalResolution = VerticalResolution;
  735. CurrentModeData->FrameBufferSize = CurrentModeData->BytesPerScanLine * CurrentModeData->VerticalResolution;
  736. CurrentModeData->LinearFrameBuffer = (VOID *) (UINTN) pFbInfo->LinearFrameBuffer;
  737. CurrentModeData->VbeModeNumber = 0;
  738. CurrentModeData->ColorDepth = 32;
  739. CurrentModeData->RefreshRate = 60;
  740. CurrentModeData->PixelFormat = PixelBitMask;
  741. if ((CurrentModeData->BitsPerPixel == 32) &&
  742. (CurrentModeData->Red.Mask == 0xff) && (CurrentModeData->Green.Mask == 0xff) && (CurrentModeData->Blue.Mask == 0xff)) {
  743. if ((CurrentModeData->Red.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Blue.Position == 16)) {
  744. CurrentModeData->PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
  745. } else if ((CurrentModeData->Blue.Position == 0) && (CurrentModeData->Green.Position == 8) && (CurrentModeData->Red.Position == 16)) {
  746. CurrentModeData->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
  747. }
  748. }
  749. CopyMem (&(CurrentModeData->PixelBitMask), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK));
  750. FbGopPrivate->ModeData = ModeBuffer;
  751. FbGopPrivate->VbeFrameBuffer = VbeFrameBuffer;
  752. //
  753. // Assign Gop's Blt function
  754. //
  755. FbGopPrivate->GraphicsOutput.Blt = FbGopGraphicsOutputVbeBlt;
  756. FbGopPrivate->GraphicsOutput.Mode->MaxMode = 1;
  757. FbGopPrivate->GraphicsOutput.Mode->Mode = 0;
  758. FbGopPrivate->GraphicsOutput.Mode->Info->Version = 0;
  759. FbGopPrivate->GraphicsOutput.Mode->Info->HorizontalResolution = HorizontalResolution;
  760. FbGopPrivate->GraphicsOutput.Mode->Info->VerticalResolution = VerticalResolution;
  761. FbGopPrivate->GraphicsOutput.Mode->Info->PixelFormat = CurrentModeData->PixelFormat;
  762. CopyMem (&(FbGopPrivate->GraphicsOutput.Mode->Info->PixelInformation), &mPixelBitMask, sizeof (EFI_PIXEL_BITMASK));
  763. FbGopPrivate->GraphicsOutput.Mode->Info->PixelsPerScanLine = (UINT32)(BytesPerScanLine * 8 / BitsPerPixel);
  764. FbGopPrivate->GraphicsOutput.Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  765. FbGopPrivate->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) (UINTN) CurrentModeData->LinearFrameBuffer;
  766. FbGopPrivate->GraphicsOutput.Mode->FrameBufferSize = CurrentModeData->FrameBufferSize;
  767. //
  768. // Find the best mode to initialize
  769. //
  770. Done:
  771. //
  772. // If there was an error, then free the mode structure
  773. //
  774. if (EFI_ERROR (Status)) {
  775. if (VbeFrameBuffer != NULL) {
  776. FreePool (VbeFrameBuffer);
  777. }
  778. if (ModeBuffer != NULL) {
  779. FreePool (ModeBuffer);
  780. }
  781. }
  782. return Status;
  783. }
  784. //
  785. // Graphics Output Protocol Member Functions for VESA BIOS Extensions
  786. //
  787. /**
  788. Graphics Output protocol interface to get video mode.
  789. @param This Protocol instance pointer.
  790. @param ModeNumber The mode number to return information on.
  791. @param SizeOfInfo A pointer to the size, in bytes, of the Info
  792. buffer.
  793. @param Info Caller allocated buffer that returns information
  794. about ModeNumber.
  795. @retval EFI_SUCCESS Mode information returned.
  796. @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
  797. video mode.
  798. @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
  799. @retval EFI_INVALID_PARAMETER One of the input args was NULL.
  800. **/
  801. EFI_STATUS
  802. EFIAPI
  803. FbGopGraphicsOutputQueryMode (
  804. IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  805. IN UINT32 ModeNumber,
  806. OUT UINTN *SizeOfInfo,
  807. OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
  808. )
  809. {
  810. FB_VIDEO_DEV *FbGopPrivate;
  811. FB_VIDEO_MODE_DATA *ModeData;
  812. FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
  813. if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
  814. return EFI_INVALID_PARAMETER;
  815. }
  816. *Info = (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) AllocatePool (
  817. sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)
  818. );
  819. if (NULL == *Info) {
  820. return EFI_OUT_OF_RESOURCES;
  821. }
  822. *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  823. ModeData = &FbGopPrivate->ModeData[ModeNumber];
  824. (*Info)->Version = 0;
  825. (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
  826. (*Info)->VerticalResolution = ModeData->VerticalResolution;
  827. (*Info)->PixelFormat = ModeData->PixelFormat;
  828. CopyMem (&((*Info)->PixelInformation), &(ModeData->PixelBitMask), sizeof(ModeData->PixelBitMask));
  829. (*Info)->PixelsPerScanLine = (ModeData->BytesPerScanLine * 8) / ModeData->BitsPerPixel;
  830. return EFI_SUCCESS;
  831. }
  832. /**
  833. Graphics Output protocol interface to set video mode.
  834. @param This Protocol instance pointer.
  835. @param ModeNumber The mode number to be set.
  836. @retval EFI_SUCCESS Graphics mode was changed.
  837. @retval EFI_DEVICE_ERROR The device had an error and could not complete the
  838. request.
  839. @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
  840. **/
  841. EFI_STATUS
  842. EFIAPI
  843. FbGopGraphicsOutputSetMode (
  844. IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
  845. IN UINT32 ModeNumber
  846. )
  847. {
  848. FB_VIDEO_DEV *FbGopPrivate;
  849. FB_VIDEO_MODE_DATA *ModeData;
  850. EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
  851. if (This == NULL) {
  852. return EFI_INVALID_PARAMETER;
  853. }
  854. FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
  855. ModeData = &FbGopPrivate->ModeData[ModeNumber];
  856. if (ModeNumber >= This->Mode->MaxMode) {
  857. return EFI_UNSUPPORTED;
  858. }
  859. if (ModeNumber == This->Mode->Mode) {
  860. //
  861. // Clear screen to black
  862. //
  863. ZeroMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
  864. FbGopGraphicsOutputVbeBlt (
  865. This,
  866. &Background,
  867. EfiBltVideoFill,
  868. 0,
  869. 0,
  870. 0,
  871. 0,
  872. ModeData->HorizontalResolution,
  873. ModeData->VerticalResolution,
  874. 0
  875. );
  876. return EFI_SUCCESS;
  877. } else {
  878. return EFI_UNSUPPORTED;
  879. }
  880. }
  881. /**
  882. Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
  883. @param PciIo The pointer of EFI_PCI_IO_PROTOCOL
  884. @param VbeBuffer The data to transfer to screen
  885. @param MemAddress Physical frame buffer base address
  886. @param DestinationX The X coordinate of the destination for BltOperation
  887. @param DestinationY The Y coordinate of the destination for BltOperation
  888. @param TotalBytes The total bytes of copy
  889. @param VbePixelWidth Bytes per pixel
  890. @param BytesPerScanLine Bytes per scan line
  891. **/
  892. VOID
  893. CopyVideoBuffer (
  894. IN EFI_PCI_IO_PROTOCOL *PciIo,
  895. IN UINT8 *VbeBuffer,
  896. IN VOID *MemAddress,
  897. IN UINTN DestinationX,
  898. IN UINTN DestinationY,
  899. IN UINTN TotalBytes,
  900. IN UINT32 VbePixelWidth,
  901. IN UINTN BytesPerScanLine
  902. )
  903. {
  904. UINTN FrameBufferAddr;
  905. UINTN CopyBlockNum;
  906. UINTN RemainingBytes;
  907. UINTN UnalignedBytes;
  908. EFI_STATUS Status;
  909. FrameBufferAddr = (UINTN) MemAddress + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth;
  910. //
  911. // If TotalBytes is less than 4 bytes, only start byte copy.
  912. //
  913. if (TotalBytes < 4) {
  914. Status = PciIo->Mem.Write (
  915. PciIo,
  916. EfiPciIoWidthUint8,
  917. EFI_PCI_IO_PASS_THROUGH_BAR,
  918. (UINT64) FrameBufferAddr,
  919. TotalBytes,
  920. VbeBuffer
  921. );
  922. ASSERT_EFI_ERROR (Status);
  923. return;
  924. }
  925. //
  926. // If VbeBuffer is not 4-byte aligned, start byte copy.
  927. //
  928. UnalignedBytes = (4 - ((UINTN) VbeBuffer & 0x3)) & 0x3;
  929. if (UnalignedBytes != 0) {
  930. Status = PciIo->Mem.Write (
  931. PciIo,
  932. EfiPciIoWidthUint8,
  933. EFI_PCI_IO_PASS_THROUGH_BAR,
  934. (UINT64) FrameBufferAddr,
  935. UnalignedBytes,
  936. VbeBuffer
  937. );
  938. ASSERT_EFI_ERROR (Status);
  939. FrameBufferAddr += UnalignedBytes;
  940. VbeBuffer += UnalignedBytes;
  941. }
  942. //
  943. // Calculate 4-byte block count and remaining bytes.
  944. //
  945. CopyBlockNum = (TotalBytes - UnalignedBytes) >> 2;
  946. RemainingBytes = (TotalBytes - UnalignedBytes) & 3;
  947. //
  948. // Copy 4-byte block and remaining bytes to physical frame buffer.
  949. //
  950. if (CopyBlockNum != 0) {
  951. Status = PciIo->Mem.Write (
  952. PciIo,
  953. EfiPciIoWidthUint32,
  954. EFI_PCI_IO_PASS_THROUGH_BAR,
  955. (UINT64) FrameBufferAddr,
  956. CopyBlockNum,
  957. VbeBuffer
  958. );
  959. ASSERT_EFI_ERROR (Status);
  960. }
  961. if (RemainingBytes != 0) {
  962. FrameBufferAddr += (CopyBlockNum << 2);
  963. VbeBuffer += (CopyBlockNum << 2);
  964. Status = PciIo->Mem.Write (
  965. PciIo,
  966. EfiPciIoWidthUint8,
  967. EFI_PCI_IO_PASS_THROUGH_BAR,
  968. (UINT64) FrameBufferAddr,
  969. RemainingBytes,
  970. VbeBuffer
  971. );
  972. ASSERT_EFI_ERROR (Status);
  973. }
  974. }
  975. /**
  976. Worker function to block transfer for VBE device.
  977. @param FbGopPrivate Instance of FB_VIDEO_DEV
  978. @param BltBuffer The data to transfer to screen
  979. @param BltOperation The operation to perform
  980. @param SourceX The X coordinate of the source for BltOperation
  981. @param SourceY The Y coordinate of the source for BltOperation
  982. @param DestinationX The X coordinate of the destination for
  983. BltOperation
  984. @param DestinationY The Y coordinate of the destination for
  985. BltOperation
  986. @param Width The width of a rectangle in the blt rectangle in
  987. pixels
  988. @param Height The height of a rectangle in the blt rectangle in
  989. pixels
  990. @param Delta Not used for EfiBltVideoFill and
  991. EfiBltVideoToVideo operation. If a Delta of 0 is
  992. used, the entire BltBuffer will be operated on. If
  993. a subrectangle of the BltBuffer is used, then
  994. Delta represents the number of bytes in a row of
  995. the BltBuffer.
  996. @param Mode Mode data.
  997. @retval EFI_INVALID_PARAMETER Invalid parameter passed in
  998. @retval EFI_SUCCESS Blt operation success
  999. **/
  1000. EFI_STATUS
  1001. FbGopVbeBltWorker (
  1002. IN FB_VIDEO_DEV *FbGopPrivate,
  1003. IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
  1004. IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
  1005. IN UINTN SourceX,
  1006. IN UINTN SourceY,
  1007. IN UINTN DestinationX,
  1008. IN UINTN DestinationY,
  1009. IN UINTN Width,
  1010. IN UINTN Height,
  1011. IN UINTN Delta,
  1012. IN FB_VIDEO_MODE_DATA *Mode
  1013. )
  1014. {
  1015. EFI_PCI_IO_PROTOCOL *PciIo;
  1016. EFI_TPL OriginalTPL;
  1017. UINTN DstY;
  1018. UINTN SrcY;
  1019. UINTN DstX;
  1020. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
  1021. VOID *MemAddress;
  1022. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VbeFrameBuffer;
  1023. UINTN BytesPerScanLine;
  1024. UINTN Index;
  1025. UINT8 *VbeBuffer;
  1026. UINT8 *VbeBuffer1;
  1027. UINT8 *BltUint8;
  1028. UINT32 VbePixelWidth;
  1029. UINT32 Pixel;
  1030. UINTN TotalBytes;
  1031. PciIo = FbGopPrivate->PciIo;
  1032. VbeFrameBuffer = FbGopPrivate->VbeFrameBuffer;
  1033. MemAddress = Mode->LinearFrameBuffer;
  1034. BytesPerScanLine = Mode->BytesPerScanLine;
  1035. VbePixelWidth = Mode->BitsPerPixel / 8;
  1036. BltUint8 = (UINT8 *) BltBuffer;
  1037. TotalBytes = Width * VbePixelWidth;
  1038. if (((UINTN) BltOperation) >= EfiGraphicsOutputBltOperationMax) {
  1039. return EFI_INVALID_PARAMETER;
  1040. }
  1041. if (Width == 0 || Height == 0) {
  1042. return EFI_INVALID_PARAMETER;
  1043. }
  1044. //
  1045. // We need to fill the Virtual Screen buffer with the blt data.
  1046. // The virtual screen is upside down, as the first row is the bottom row of
  1047. // the image.
  1048. //
  1049. if (BltOperation == EfiBltVideoToBltBuffer) {
  1050. //
  1051. // Video to BltBuffer: Source is Video, destination is BltBuffer
  1052. //
  1053. if (SourceY + Height > Mode->VerticalResolution) {
  1054. return EFI_INVALID_PARAMETER;
  1055. }
  1056. if (SourceX + Width > Mode->HorizontalResolution) {
  1057. return EFI_INVALID_PARAMETER;
  1058. }
  1059. } else {
  1060. //
  1061. // BltBuffer to Video: Source is BltBuffer, destination is Video
  1062. //
  1063. if (DestinationY + Height > Mode->VerticalResolution) {
  1064. return EFI_INVALID_PARAMETER;
  1065. }
  1066. if (DestinationX + Width > Mode->HorizontalResolution) {
  1067. return EFI_INVALID_PARAMETER;
  1068. }
  1069. }
  1070. //
  1071. // If Delta is zero, then the entire BltBuffer is being used, so Delta
  1072. // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
  1073. // the number of bytes in each row can be computed.
  1074. //
  1075. if (Delta == 0) {
  1076. Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
  1077. }
  1078. //
  1079. // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
  1080. // We would not want a timer based event (Cursor, ...) to come in while we are
  1081. // doing this operation.
  1082. //
  1083. OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
  1084. switch (BltOperation) {
  1085. case EfiBltVideoToBltBuffer:
  1086. for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
  1087. Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + DstY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
  1088. //
  1089. // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
  1090. //
  1091. VbeBuffer = ((UINT8 *) VbeFrameBuffer + (SrcY * BytesPerScanLine + SourceX * VbePixelWidth));
  1092. for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
  1093. Pixel = VbeBuffer[0] | VbeBuffer[1] << 8 | VbeBuffer[2] << 16 | VbeBuffer[3] << 24;
  1094. Blt->Red = (UINT8) ((Pixel >> Mode->Red.Position) & Mode->Red.Mask);
  1095. Blt->Blue = (UINT8) ((Pixel >> Mode->Blue.Position) & Mode->Blue.Mask);
  1096. Blt->Green = (UINT8) ((Pixel >> Mode->Green.Position) & Mode->Green.Mask);
  1097. Blt->Reserved = 0;
  1098. Blt++;
  1099. VbeBuffer += VbePixelWidth;
  1100. }
  1101. }
  1102. break;
  1103. case EfiBltVideoToVideo:
  1104. for (Index = 0; Index < Height; Index++) {
  1105. if (DestinationY <= SourceY) {
  1106. SrcY = SourceY + Index;
  1107. DstY = DestinationY + Index;
  1108. } else {
  1109. SrcY = SourceY + Height - Index - 1;
  1110. DstY = DestinationY + Height - Index - 1;
  1111. }
  1112. VbeBuffer = ((UINT8 *) VbeFrameBuffer + DstY * BytesPerScanLine + DestinationX * VbePixelWidth);
  1113. VbeBuffer1 = ((UINT8 *) VbeFrameBuffer + SrcY * BytesPerScanLine + SourceX * VbePixelWidth);
  1114. gBS->CopyMem (
  1115. VbeBuffer,
  1116. VbeBuffer1,
  1117. TotalBytes
  1118. );
  1119. //
  1120. // Update physical frame buffer.
  1121. //
  1122. CopyVideoBuffer (
  1123. PciIo,
  1124. VbeBuffer,
  1125. MemAddress,
  1126. DestinationX,
  1127. DstY,
  1128. TotalBytes,
  1129. VbePixelWidth,
  1130. BytesPerScanLine
  1131. );
  1132. }
  1133. break;
  1134. case EfiBltVideoFill:
  1135. VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
  1136. Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltUint8;
  1137. //
  1138. // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
  1139. //
  1140. Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
  1141. (
  1142. (Blt->Green & Mode->Green.Mask) <<
  1143. Mode->Green.Position
  1144. ) |
  1145. ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
  1146. for (Index = 0; Index < Width; Index++) {
  1147. gBS->CopyMem (
  1148. VbeBuffer,
  1149. &Pixel,
  1150. VbePixelWidth
  1151. );
  1152. VbeBuffer += VbePixelWidth;
  1153. }
  1154. VbeBuffer = (UINT8 *) ((UINTN) VbeFrameBuffer + (DestinationY * BytesPerScanLine) + DestinationX * VbePixelWidth);
  1155. for (DstY = DestinationY + 1; DstY < (Height + DestinationY); DstY++) {
  1156. gBS->CopyMem (
  1157. (VOID *) ((UINTN) VbeFrameBuffer + (DstY * BytesPerScanLine) + DestinationX * VbePixelWidth),
  1158. VbeBuffer,
  1159. TotalBytes
  1160. );
  1161. }
  1162. for (DstY = DestinationY; DstY < (Height + DestinationY); DstY++) {
  1163. //
  1164. // Update physical frame buffer.
  1165. //
  1166. CopyVideoBuffer (
  1167. PciIo,
  1168. VbeBuffer,
  1169. MemAddress,
  1170. DestinationX,
  1171. DstY,
  1172. TotalBytes,
  1173. VbePixelWidth,
  1174. BytesPerScanLine
  1175. );
  1176. }
  1177. break;
  1178. case EfiBltBufferToVideo:
  1179. for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
  1180. Blt = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) (BltUint8 + (SrcY * Delta) + (SourceX) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
  1181. VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
  1182. for (DstX = DestinationX; DstX < (Width + DestinationX); DstX++) {
  1183. //
  1184. // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
  1185. //
  1186. Pixel = ((Blt->Red & Mode->Red.Mask) << Mode->Red.Position) |
  1187. ((Blt->Green & Mode->Green.Mask) << Mode->Green.Position) |
  1188. ((Blt->Blue & Mode->Blue.Mask) << Mode->Blue.Position);
  1189. gBS->CopyMem (
  1190. VbeBuffer,
  1191. &Pixel,
  1192. VbePixelWidth
  1193. );
  1194. Blt++;
  1195. VbeBuffer += VbePixelWidth;
  1196. }
  1197. VbeBuffer = ((UINT8 *) VbeFrameBuffer + (DstY * BytesPerScanLine + DestinationX * VbePixelWidth));
  1198. //
  1199. // Update physical frame buffer.
  1200. //
  1201. CopyVideoBuffer (
  1202. PciIo,
  1203. VbeBuffer,
  1204. MemAddress,
  1205. DestinationX,
  1206. DstY,
  1207. TotalBytes,
  1208. VbePixelWidth,
  1209. BytesPerScanLine
  1210. );
  1211. }
  1212. break;
  1213. default: ;
  1214. }
  1215. gBS->RestoreTPL (OriginalTPL);
  1216. return EFI_SUCCESS;
  1217. }
  1218. /**
  1219. Graphics Output protocol instance to block transfer for VBE device.
  1220. @param This Pointer to Graphics Output protocol instance
  1221. @param BltBuffer The data to transfer to screen
  1222. @param BltOperation The operation to perform
  1223. @param SourceX The X coordinate of the source for BltOperation
  1224. @param SourceY The Y coordinate of the source for BltOperation
  1225. @param DestinationX The X coordinate of the destination for
  1226. BltOperation
  1227. @param DestinationY The Y coordinate of the destination for
  1228. BltOperation
  1229. @param Width The width of a rectangle in the blt rectangle in
  1230. pixels
  1231. @param Height The height of a rectangle in the blt rectangle in
  1232. pixels
  1233. @param Delta Not used for EfiBltVideoFill and
  1234. EfiBltVideoToVideo operation. If a Delta of 0 is
  1235. used, the entire BltBuffer will be operated on. If
  1236. a subrectangle of the BltBuffer is used, then
  1237. Delta represents the number of bytes in a row of
  1238. the BltBuffer.
  1239. @retval EFI_INVALID_PARAMETER Invalid parameter passed in
  1240. @retval EFI_SUCCESS Blt operation success
  1241. **/
  1242. EFI_STATUS
  1243. EFIAPI
  1244. FbGopGraphicsOutputVbeBlt (
  1245. IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  1246. IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
  1247. IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
  1248. IN UINTN SourceX,
  1249. IN UINTN SourceY,
  1250. IN UINTN DestinationX,
  1251. IN UINTN DestinationY,
  1252. IN UINTN Width,
  1253. IN UINTN Height,
  1254. IN UINTN Delta
  1255. )
  1256. {
  1257. FB_VIDEO_DEV *FbGopPrivate;
  1258. FB_VIDEO_MODE_DATA *Mode;
  1259. if (This == NULL) {
  1260. return EFI_INVALID_PARAMETER;
  1261. }
  1262. FbGopPrivate = FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This);
  1263. Mode = &FbGopPrivate->ModeData[This->Mode->Mode];
  1264. return FbGopVbeBltWorker (
  1265. FbGopPrivate,
  1266. BltBuffer,
  1267. BltOperation,
  1268. SourceX,
  1269. SourceY,
  1270. DestinationX,
  1271. DestinationY,
  1272. Width,
  1273. Height,
  1274. Delta,
  1275. Mode
  1276. );
  1277. }
  1278. /**
  1279. The user Entry Point for module UefiFbGop. The user code starts with this function.
  1280. @param[in] ImageHandle The firmware allocated handle for the EFI image.
  1281. @param[in] SystemTable A pointer to the EFI System Table.
  1282. @retval EFI_SUCCESS The entry point is executed successfully.
  1283. @retval other Some error occurs when executing this entry point.
  1284. **/
  1285. EFI_STATUS
  1286. EFIAPI
  1287. FbGopEntryPoint(
  1288. IN EFI_HANDLE ImageHandle,
  1289. IN EFI_SYSTEM_TABLE *SystemTable
  1290. )
  1291. {
  1292. EFI_STATUS Status;
  1293. EFI_HOB_GUID_TYPE *GuidHob;
  1294. //
  1295. // Find the frame buffer information guid hob
  1296. //
  1297. GuidHob = GetFirstGuidHob (&gUefiFrameBufferInfoGuid);
  1298. if (GuidHob != NULL) {
  1299. //
  1300. // Install driver model protocol(s).
  1301. //
  1302. Status = EfiLibInstallDriverBindingComponentName2 (
  1303. ImageHandle,
  1304. SystemTable,
  1305. &gFbGopDriverBinding,
  1306. ImageHandle,
  1307. &gFbGopComponentName,
  1308. &gFbGopComponentName2
  1309. );
  1310. ASSERT_EFI_ERROR (Status);
  1311. } else {
  1312. DEBUG ((EFI_D_ERROR, "No FrameBuffer information from coreboot. NO GOP driver !!!\n"));
  1313. Status = EFI_ABORTED;
  1314. }
  1315. return Status;
  1316. }