video.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. video.c
  9. Abstract:
  10. This module implements support for VESA BIOS video services via int 0x10.
  11. Author:
  12. Evan Green 25-Mar-2014
  13. Environment:
  14. Firmware
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <uefifw.h>
  20. #include <minoca/uefi/protocol/graphout.h>
  21. #include "biosfw.h"
  22. //
  23. // --------------------------------------------------------------------- Macros
  24. //
  25. //
  26. // This macro converts the segmented addresses given in the VESA information
  27. // structure into linear addresses that can be dereferenced in protected mode.
  28. //
  29. #define VESA_SEGMENTED_TO_LINEAR_ADDRESS(_Address) \
  30. (VOID *)((((_Address) & 0xFFFF0000) >> 12) + \
  31. ((_Address) & 0x0000FFFF))
  32. //
  33. // ---------------------------------------------------------------- Definitions
  34. //
  35. #define EFI_VESA_DEVICE_MAGIC 0x61736556 // 'aseV'
  36. #define EFI_VESA_DEVICE_GUID \
  37. { \
  38. 0x19EEE1EB, 0x8F2A, 0x4DFA, \
  39. {0xB0, 0xF9, 0xB1, 0x0B, 0xD5, 0xB8, 0x71, 0xB9} \
  40. }
  41. //
  42. // Define the maximum number of supported modes.
  43. //
  44. #define VESA_MAX_MODES 70
  45. //
  46. // Define the signature at the header of the VESA Information structure, for
  47. // versions 1 and 2.
  48. //
  49. #define VESA_1_SIGNATURE 0x41534556 // 'VESA'
  50. #define VESA_2_SIGNATURE 0x32454256 // 'VBE2'
  51. //
  52. // Define video mode attribute flags.
  53. //
  54. #define VESA_MODE_ATTRIBUTE_SUPPORTED 0x0001
  55. #define VESA_MODE_ATTRIBUTE_TTY_SUPPORTED 0x0004
  56. #define VESA_MODE_ATTRIBUTE_COLOR 0x0008
  57. #define VESA_MODE_ATTRIBUTE_GRAPHICS 0x0010
  58. #define VESA_MODE_ATTRIBUTE_NON_VGA 0x0020
  59. #define VESA_MODE_ATTRIBUTE_VGA_WINDOWED 0x0040
  60. #define VESA_MODE_ATTRIBUTE_LINEAR 0x0080
  61. //
  62. // Define the meaningful bits in the mode number.
  63. //
  64. #define VESA_MODE_NUMBER_USE_LINEAR_MODEL 0x4000
  65. #define VESA_MODE_NUMBER_DONT_CLEAR_DISPLAY 0x8000
  66. //
  67. // Define values for AX (the different VESA function calls).
  68. //
  69. #define VESA_FUNCTION_GET_VESA_INFORMATION 0x4F00
  70. #define VESA_FUNCTION_GET_MODE_INFORMATION 0x4F01
  71. #define VESA_FUNCTION_SET_MODE 0x4F02
  72. //
  73. // ------------------------------------------------------ Data Type Definitions
  74. //
  75. typedef enum _VESA_MEMORY_MODEL {
  76. VesaMemoryModelText = 0,
  77. VesaMemoryModelCga = 1,
  78. VesaMemoryModelHercules = 2,
  79. VesaMemoryModel4Plane = 3,
  80. VesaMemoryModelPackedPixel = 4,
  81. VesaMemoryModelNonChain4 = 5,
  82. VesaMemoryModelDirectColor = 6,
  83. VesaMemoryModelYuv = 7
  84. } VESA_MEMORY_MODEL, *PVESA_MEMORY_MODEL;
  85. /*++
  86. Structure Description:
  87. This structure stores information about BIOS compatibility with the VESA
  88. video standard.
  89. Members:
  90. Signature - Stores the signature indicating this is a valid structure. The
  91. magic constant for VESA v1 means the structure content is valid through
  92. the Total Memory field. In v2 all fields are valid.
  93. VesaVersion - Stores the major version in the high byte, and the minor
  94. version in the low byte.
  95. OemStringPointer - Supplies a pointer to a NULL terminated string describing
  96. the Original Equipment Manufacturer chip, board, configuration, or
  97. anything else.
  98. Capabilities - Stores a bitfield of capabilities. The only valid bit is bit
  99. 0, which defines whether or not the DAC is switchable (has multiple
  100. modes).
  101. VideoModePointer - Stores a pointer to a list of possibly supported mode
  102. numbers. Each mode number is 16 bits in length, and the list is
  103. terminated with a -1.
  104. TotalMemoryBlocks - Storse the number of 64kB blocks of video memory in the
  105. card.
  106. OemSoftwareRevision - Stores the OEM software revision number. This is the
  107. first field that is only filled out in VESA 2.0.
  108. OemVendorNamePointer - Stores a pointer to a NULL terminated string of the
  109. vendor name.
  110. OemProductNamePointer - Stores a pointer to a NULL terminated string of the
  111. product name.
  112. OemProductRevisionPointer - Stores a pointer to a NULL terminated string of
  113. the product revision.
  114. Reserved - Stores a bunch of bytes that shouldn't be touched.
  115. OemData - Stores a section of space reserved for OEM-specific information.
  116. --*/
  117. typedef struct _VESA_INFORMATION {
  118. UINT32 Signature;
  119. UINT16 VesaVersion;
  120. UINT32 OemStringPointer;
  121. UINT32 Capabilities;
  122. UINT32 VideoModePointer;
  123. UINT16 TotalMemoryBlocks;
  124. UINT16 OemSoftwareRevision;
  125. UINT32 OemVendorNamePointer;
  126. UINT32 OemProductNamePointer;
  127. UINT32 OemProductRevisionPointer;
  128. //UCHAR Reserved[222];
  129. //UCHAR OemData[256];
  130. } PACKED VESA_INFORMATION, *PVESA_INFORMATION;
  131. /*++
  132. Structure Description:
  133. This structure stores information about a particular video mode.
  134. Members:
  135. ModeAttributes - Stores a bitfield of attributes about the mode. Bit 0
  136. specifies if the mode can be initialized in the present video
  137. configuration. Bit 1 specifies if the optional fields are filled in.
  138. Bit 2 specifies if the BIOS supports output functions like TTY output,
  139. scrolling, pixel output, etc.
  140. WindowAAttributes - Stores a bitfield of attributes relating to the first
  141. window buffer. Bit 0 stores whether or not the window is supported, bit
  142. 1 stores whether or not the window is readable, and bit 2 stores
  143. whether or not the window is writeable.
  144. WindowBAttributes - Stores a bitfield of attributes relating to the second
  145. window. The meaning of the bits are the same as window A.
  146. WindowGranularity - Stores the smallest boundary, in kilobytes, on which the
  147. window can be placed in the video memory.
  148. WindowSize - Stores the size of each window, in kilobytes.
  149. WindowASegment - Stores the segment address of the window in CPU address
  150. space.
  151. WindowBSegment - Stores the segment address of the second window in CPU
  152. address space.
  153. WindowFunctionPointer - Stores the address of the CPU video memory windowing
  154. function. The windowing function can be invoked by VESA BIOS function
  155. 5, or by calling this address directly.
  156. BytesPerScanLine - Stores the number of bytes in one horizontal line of the
  157. video frame. This value must be at least as large as the visible bytes
  158. per line.
  159. XResolution - Stores the width of the video mode, in pixels (for text modes,
  160. the units here are characters).
  161. YResolution - Stores the height of the video mode, in pixels or characters.
  162. XCharacterSize - Stores the width of one text character, in pixels.
  163. YCharacterSize - Stores the height of one text character, in pixels.
  164. NumberOfPlanes - Stores the number of memory planes available to software in
  165. the mode. For standard 16-color VGA graphics, this would be set to 4.
  166. For standard packed pixel modes, the field would be set to 1.
  167. BitsPerPixel - Stores the number of bits in one pixel on the screen.
  168. NumberOfBanks - Stores the number of memory banks used to display a window
  169. of the mode.
  170. MemoryModel - Stores the memory model for this video mode. See the
  171. VESA_MEMORY_MODEL for possible values.
  172. BankSize - Stores the size of a bank in 1 kilobyte units.
  173. NumberOfImagePages - Stores the number of additional complete display images
  174. that will fit into the VGA's memory at one time in this mode.
  175. Reserved1 - Stores a field reserved for a future VESA feature, and will
  176. always be set to 1.
  177. RedMaskSize - Stores the number of bits in the red component of a direct
  178. color pixel.
  179. RedFieldPosition - Stores the bit position of the least significant bit of
  180. the red color component.
  181. GreenMaskSize - Stores the number of bits in the green component of a direct
  182. color pixel.
  183. GreenFieldPosition - Stores the bit position of the least significant bit of
  184. the green color component.
  185. BlueMaskSize - Stores the number of bits in the blue component of a direct
  186. color pixel.
  187. BlueFieldPosition - Stores the bit position of the least significant bit of
  188. the Blue color component.
  189. ReservedMaskSize - Stores the number of bits in the reserved component of a
  190. direct color pixel.
  191. ReservedFieldPosition - Stores the bit position of the least significant
  192. bit of the reserved component.
  193. DirectColorModeInformation - Stores a bitfield of flags relating to the
  194. direct color mode.
  195. PhysicalBasePointer - Stores the physical address of the linear frame
  196. buffer.
  197. OffScreenMemoryOffset - Stores a pointer to the start of the off screen
  198. memory.
  199. OffScreenMemorySize - Stores the size of the off screen memory, in 1
  200. kilobyte units.
  201. --*/
  202. typedef struct _VESA_MODE_INFORMATION {
  203. UINT16 ModeAttributes;
  204. UINT8 WindowAAttributes;
  205. UINT8 WindowBAttributes;
  206. UINT16 WindowGranularity;
  207. UINT16 WindowSize;
  208. UINT16 WindowASegment;
  209. UINT16 WindowBSegment;
  210. UINT32 WindowFunctionPointer;
  211. UINT16 BytesPerScanLine;
  212. UINT16 XResolution;
  213. UINT16 YResolution;
  214. UINT8 XCharacterSize;
  215. UINT8 YCharacterSize;
  216. UINT8 NumberOfPlanes;
  217. UINT8 BitsPerPixel;
  218. UINT8 NumberOfBanks;
  219. UINT8 MemoryModel;
  220. UINT8 BankSize;
  221. UINT8 NumberOfImagePages;
  222. UINT8 Reserved1;
  223. UINT8 RedMaskSize;
  224. UINT8 RedFieldPosition;
  225. UINT8 GreenMaskSize;
  226. UINT8 GreenFieldPosition;
  227. UINT8 BlueMaskSize;
  228. UINT8 BlueFieldPosition;
  229. UINT8 ReservedMaskSize;
  230. UINT8 ReservedFieldPosition;
  231. UINT8 DirectColorModeInformation;
  232. UINT32 PhysicalBasePointer;
  233. UINT32 OffScreenMemoryOffset;
  234. UINT16 OffScreenMemorySize;
  235. //UCHAR Reserved2[206];
  236. } PACKED VESA_MODE_INFORMATION, *PVESA_MODE_INFORMATION;
  237. /*++
  238. Structure Description:
  239. This structure stores the VESA graphics output mode information.
  240. Members:
  241. Information - Stores the information structure.
  242. VesaModeNumber - Stores the VESA mode number associated with this mode.
  243. BitsPerPixels - Stores the number of bits of data in a pixel.
  244. FrameBufferBase - Stores the frame buffer base address associated with this
  245. mode.
  246. Failed - Stores a boolean indicating if a failure occurred trying to set
  247. this mode.
  248. --*/
  249. typedef struct _EFI_VESA_MODE {
  250. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION Information;
  251. UINT16 VesaModeNumber;
  252. UINT16 BitsPerPixel;
  253. EFI_PHYSICAL_ADDRESS FrameBufferBase;
  254. BOOLEAN Failed;
  255. } EFI_VESA_MODE, *PEFI_VESA_MODE;
  256. /*++
  257. Structure Description:
  258. This structure stores the internal context for a VESA device.
  259. Members:
  260. Magic - Stores the constant magic value EFI_VESA_DEVICE_MAGIC.
  261. Handle - Stores the graphics out handle.
  262. GraphicsOut - Stores the graphics output protocol.
  263. GraphicsOutMode - Stores the graphics output protocol mode.
  264. --*/
  265. typedef struct _EFI_VESA_DEVICE {
  266. UINT32 Magic;
  267. EFI_HANDLE Handle;
  268. EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOut;
  269. EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE GraphicsOutMode;
  270. } EFI_VESA_DEVICE, *PEFI_VESA_DEVICE;
  271. /*++
  272. Structure Description:
  273. This structure stores the structure of a VESA device path.
  274. Members:
  275. VendorPath - Stores the vendor path portion of the device path.
  276. End - Stores the end device path node.
  277. --*/
  278. typedef struct _EFI_VESA_DEVICE_PATH {
  279. VENDOR_DEVICE_PATH VendorPath;
  280. EFI_DEVICE_PATH_PROTOCOL End;
  281. } EFI_VESA_DEVICE_PATH, *PEFI_VESA_DEVICE_PATH;
  282. //
  283. // ----------------------------------------------- Internal Function Prototypes
  284. //
  285. EFIAPI
  286. EFI_STATUS
  287. EfipPcatGraphicsQueryMode (
  288. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  289. UINT32 ModeNumber,
  290. UINTN *SizeOfInfo,
  291. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
  292. );
  293. EFIAPI
  294. EFI_STATUS
  295. EfipPcatGraphicsSetMode (
  296. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  297. UINT32 ModeNumber
  298. );
  299. EFIAPI
  300. EFI_STATUS
  301. EfipPcatGraphicsBlt (
  302. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  303. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
  304. EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
  305. UINTN SourceX,
  306. UINTN SourceY,
  307. UINTN DestinationX,
  308. UINTN DestinationY,
  309. UINTN Width,
  310. UINTN Height,
  311. UINTN Delta
  312. );
  313. EFI_STATUS
  314. EfipPcatEnumerateVesaModes (
  315. UINT16 *VesaModeList,
  316. UINTN VesaModeCount
  317. );
  318. UINTN
  319. EfipPcatSelectInitialVideoMode (
  320. VOID
  321. );
  322. EFI_STATUS
  323. EfipPcatGetVesaInformation (
  324. PVESA_INFORMATION Information
  325. );
  326. EFI_STATUS
  327. EfipPcatGetVesaModeInformation (
  328. UINT16 ModeNumber,
  329. PVESA_MODE_INFORMATION ModeInformation
  330. );
  331. EFI_STATUS
  332. EfipPcatSetVesaMode (
  333. UINT16 ModeNumber
  334. );
  335. //
  336. // -------------------------------------------------------------------- Globals
  337. //
  338. PEFI_VESA_MODE EfiVesaModes;
  339. UINTN EfiVesaModeCount;
  340. EFI_VESA_DEVICE_PATH EfiVesaDevicePathTemplate = {
  341. {
  342. {
  343. HARDWARE_DEVICE_PATH,
  344. HW_VENDOR_DP,
  345. sizeof(VENDOR_DEVICE_PATH)
  346. },
  347. EFI_VESA_DEVICE_GUID,
  348. },
  349. {
  350. END_DEVICE_PATH_TYPE,
  351. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  352. END_DEVICE_PATH_LENGTH
  353. }
  354. };
  355. //
  356. // ------------------------------------------------------------------ Functions
  357. //
  358. EFI_STATUS
  359. EfipPcatEnumerateVideo (
  360. VOID
  361. )
  362. /*++
  363. Routine Description:
  364. This routine enumerates the video display on a BIOS machine.
  365. Arguments:
  366. None.
  367. Return Value:
  368. EFI Status code.
  369. --*/
  370. {
  371. PEFI_VESA_DEVICE Device;
  372. VESA_INFORMATION Information;
  373. PEFI_VESA_MODE Mode;
  374. UINT16 ModeCount;
  375. UINTN ModeIndex;
  376. UINT16 *ModeList;
  377. UINTN SelectedMode;
  378. EFI_STATUS Status;
  379. UINT16 VesaModeList[VESA_MAX_MODES];
  380. //
  381. // Attempt to get the VESA information structure.
  382. //
  383. Information.VesaVersion = 0;
  384. Information.Signature = VESA_2_SIGNATURE;
  385. Status = EfipPcatGetVesaInformation(&Information);
  386. if (EFI_ERROR(Status)) {
  387. goto PcatEnumerateVideoEnd;
  388. }
  389. if ((Information.Signature != VESA_1_SIGNATURE) ||
  390. (Information.VesaVersion < 0x0200)) {
  391. Status = EFI_UNSUPPORTED;
  392. goto PcatEnumerateVideoEnd;
  393. }
  394. ModeList = VESA_SEGMENTED_TO_LINEAR_ADDRESS(Information.VideoModePointer);
  395. //
  396. // Copy the mode list to the global.
  397. //
  398. ModeCount = 0;
  399. while ((ModeList[ModeCount] != 0xFFFF) &&
  400. (ModeCount < VESA_MAX_MODES - 1)) {
  401. VesaModeList[ModeCount] = ModeList[ModeCount];
  402. ModeCount += 1;
  403. }
  404. Status = EfipPcatEnumerateVesaModes(VesaModeList, ModeCount);
  405. if (EFI_ERROR(Status)) {
  406. return Status;
  407. }
  408. //
  409. // Attempt to find and switch to the best video mode.
  410. //
  411. Mode = NULL;
  412. for (ModeIndex = 0; ModeIndex < EfiVesaModeCount; ModeIndex += 1) {
  413. SelectedMode = EfipPcatSelectInitialVideoMode();
  414. Mode = &(EfiVesaModes[SelectedMode]);
  415. //
  416. // All video modes have been tried.
  417. //
  418. if (Mode->Failed != FALSE) {
  419. Status = EFI_UNSUPPORTED;
  420. break;
  421. }
  422. Status = EfipPcatSetVesaMode(Mode->VesaModeNumber);
  423. if (!EFI_ERROR(Status)) {
  424. break;
  425. }
  426. Mode->Failed = TRUE;
  427. }
  428. if (EFI_ERROR(Status)) {
  429. goto PcatEnumerateVideoEnd;
  430. }
  431. //
  432. // Everything's all set up, create the graphics output protocol.
  433. //
  434. Status = EfiAllocatePool(EfiBootServicesData,
  435. sizeof(EFI_VESA_DEVICE),
  436. (VOID **)&Device);
  437. if (EFI_ERROR(Status)) {
  438. goto PcatEnumerateVideoEnd;
  439. }
  440. EfiSetMem(Device, sizeof(EFI_VESA_DEVICE), 0);
  441. Device->Magic = EFI_VESA_DEVICE_MAGIC;
  442. Device->GraphicsOut.QueryMode = EfipPcatGraphicsQueryMode;
  443. Device->GraphicsOut.SetMode = EfipPcatGraphicsSetMode;
  444. Device->GraphicsOut.Blt = EfipPcatGraphicsBlt;
  445. Device->GraphicsOut.Mode = &(Device->GraphicsOutMode);
  446. Device->GraphicsOutMode.MaxMode = EfiVesaModeCount;
  447. Device->GraphicsOutMode.Mode = ModeIndex;
  448. Device->GraphicsOutMode.Info = &(Mode->Information);
  449. Device->GraphicsOutMode.SizeOfInfo =
  450. sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  451. Device->GraphicsOutMode.FrameBufferBase = Mode->FrameBufferBase;
  452. Device->GraphicsOutMode.FrameBufferSize =
  453. Mode->Information.PixelsPerScanLine *
  454. (Mode->BitsPerPixel / 8) *
  455. Mode->Information.VerticalResolution;
  456. Status = EfiInstallMultipleProtocolInterfaces(
  457. &(Device->Handle),
  458. &EfiGraphicsOutputProtocolGuid,
  459. &(Device->GraphicsOut),
  460. &EfiDevicePathProtocolGuid,
  461. &EfiVesaDevicePathTemplate,
  462. NULL);
  463. if (EFI_ERROR(Status)) {
  464. EfiFreePool(Device);
  465. }
  466. PcatEnumerateVideoEnd:
  467. return Status;
  468. }
  469. //
  470. // --------------------------------------------------------- Internal Functions
  471. //
  472. EFIAPI
  473. EFI_STATUS
  474. EfipPcatGraphicsQueryMode (
  475. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  476. UINT32 ModeNumber,
  477. UINTN *SizeOfInfo,
  478. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
  479. )
  480. /*++
  481. Routine Description:
  482. This routine returns information about available graphics modes that the
  483. graphics device and set of active video output devices support.
  484. Arguments:
  485. This - Supplies a pointer to the protocol instance.
  486. ModeNumber - Supplies the mode number to return information about.
  487. SizeOfInfo - Supplies a pointer that on input contains the size in bytes of
  488. the information buffer.
  489. Info - Supplies a pointer where a callee-allocated buffer will be returned
  490. containing information about the mode. The caller is responsible for
  491. calling FreePool to free this data.
  492. Return Value:
  493. EFI_SUCCESS on success.
  494. EFI_DEVICE_ERROR if a hardware error occurred trying to retrieve the video
  495. mode.
  496. EFI_INVALID_PARAMETER if the mode number is not valid.
  497. --*/
  498. {
  499. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information;
  500. EFI_STATUS Status;
  501. if ((ModeNumber >= EfiVesaModeCount) || (SizeOfInfo == NULL)) {
  502. return EFI_INVALID_PARAMETER;
  503. }
  504. Status = EfiAllocatePool(EfiBootServicesData,
  505. sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
  506. (VOID **)&Information);
  507. if (EFI_ERROR(Status)) {
  508. return Status;
  509. }
  510. EfiCopyMem(Information,
  511. &(EfiVesaModes[ModeNumber].Information),
  512. sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
  513. *Info = Information;
  514. *SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  515. return EFI_SUCCESS;
  516. }
  517. EFIAPI
  518. EFI_STATUS
  519. EfipPcatGraphicsSetMode (
  520. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  521. UINT32 ModeNumber
  522. )
  523. /*++
  524. Routine Description:
  525. This routine sets the video device into the specified mode and clears the
  526. visible portions of the output display to black.
  527. Arguments:
  528. This - Supplies a pointer to the protocol instance.
  529. ModeNumber - Supplies the mode number to set.
  530. Return Value:
  531. EFI_SUCCESS on success.
  532. EFI_DEVICE_ERROR if a hardware error occurred trying to set the video mode.
  533. EFI_UNSUPPORTED if the mode number is not supported by this device.
  534. --*/
  535. {
  536. PEFI_VESA_MODE Mode;
  537. EFI_STATUS Status;
  538. if (ModeNumber >= EfiVesaModeCount) {
  539. return EFI_UNSUPPORTED;
  540. }
  541. Mode = &(EfiVesaModes[ModeNumber]);
  542. Status = EfipPcatSetVesaMode(Mode->VesaModeNumber);
  543. if (!EFI_ERROR(Status)) {
  544. This->Mode->Info = &(Mode->Information);
  545. This->Mode->Mode = ModeNumber;
  546. This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
  547. This->Mode->FrameBufferBase = Mode->FrameBufferBase;
  548. This->Mode->FrameBufferSize = Mode->Information.PixelsPerScanLine *
  549. (Mode->BitsPerPixel / 8) *
  550. Mode->Information.VerticalResolution;
  551. }
  552. return Status;
  553. }
  554. EFIAPI
  555. EFI_STATUS
  556. EfipPcatGraphicsBlt (
  557. EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
  558. EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer,
  559. EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
  560. UINTN SourceX,
  561. UINTN SourceY,
  562. UINTN DestinationX,
  563. UINTN DestinationY,
  564. UINTN Width,
  565. UINTN Height,
  566. UINTN Delta
  567. )
  568. /*++
  569. Routine Description:
  570. This routine performs a Blt (copy) operation of pixels on the graphics
  571. screen. Blt stands for Block Transfer for those not up on their video lingo.
  572. Arguments:
  573. This - Supplies a pointer to the protocol instance.
  574. BltBuffer - Supplies an optional pointer to the data to transfer to the
  575. graphics screen. The size must be at least width * height *
  576. sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL).
  577. BltOperation - Supplies the operation to perform when copying the buffer to
  578. the screen.
  579. SourceX - Supplies the X coordinate of the source of the operation.
  580. SourceY - Supplies the Y coordinate of the source of the operation.
  581. DestinationX - Supplies the X coordinate of the destination of the
  582. operation.
  583. DestinationY - Supplies the Y coordinate of the destination of the
  584. operation.
  585. Width - Supplies the width of the rectangle in pixels.
  586. Height - Supplies the height of the rectangle in pixels.
  587. Delta - Supplies an optional number of bytes in a row of the given buffer.
  588. If a delta of zero is used, the entire buffer is being operated on.
  589. This is not used for EfiBltVideoFill or EfiBltVideoToVideo operations.
  590. Return Value:
  591. EFI_SUCCESS on success.
  592. EFI_INVALID_PARAMETER if the operation was not valid.
  593. EFI_DEVICE_ERROR if a hardware error occurred and the request could not be
  594. completed.
  595. --*/
  596. {
  597. return EFI_UNSUPPORTED;
  598. }
  599. EFI_STATUS
  600. EfipPcatEnumerateVesaModes (
  601. UINT16 *VesaModeList,
  602. UINTN VesaModeCount
  603. )
  604. /*++
  605. Routine Description:
  606. This routine creates the mode information array from the VESA mode list.
  607. Arguments:
  608. VesaModeList - Supplies a pointer to the list of VESA modes.
  609. VesaModeCount - Supplies the number of valid mode elements in the supplied
  610. list.
  611. Return Value:
  612. EFI status.
  613. --*/
  614. {
  615. UINTN AllocationSize;
  616. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information;
  617. UINTN ModeCount;
  618. PEFI_VESA_MODE Modes;
  619. EFI_STATUS Status;
  620. VESA_MODE_INFORMATION VesaInformation;
  621. UINTN VesaModeIndex;
  622. Modes = NULL;
  623. if (VesaModeCount == 0) {
  624. return EFI_DEVICE_ERROR;
  625. }
  626. AllocationSize = sizeof(EFI_VESA_MODE) * VesaModeCount;
  627. Status = EfiAllocatePool(EfiBootServicesData,
  628. AllocationSize,
  629. (VOID **)&Modes);
  630. if (EFI_ERROR(Status)) {
  631. return Status;
  632. }
  633. EfiSetMem(Modes, AllocationSize, 0);
  634. ModeCount = 0;
  635. for (VesaModeIndex = 0; VesaModeIndex < VesaModeCount; VesaModeIndex += 1) {
  636. Status = EfipPcatGetVesaModeInformation(VesaModeList[VesaModeIndex],
  637. &VesaInformation);
  638. if (EFI_ERROR(Status)) {
  639. continue;
  640. }
  641. //
  642. // Skip non-graphical modes and modes without a linear frame buffer.
  643. //
  644. if (((VesaInformation.ModeAttributes &
  645. VESA_MODE_ATTRIBUTE_GRAPHICS) == 0) ||
  646. ((VesaInformation.ModeAttributes &
  647. VESA_MODE_ATTRIBUTE_LINEAR) == 0)) {
  648. continue;
  649. }
  650. //
  651. // Fill out the EFI mode information based on the VESA mode information.
  652. //
  653. Information = &(Modes[ModeCount].Information);
  654. Information->Version = 0;
  655. Information->HorizontalResolution = VesaInformation.XResolution;
  656. Information->VerticalResolution = VesaInformation.YResolution;
  657. Information->PixelFormat = PixelBitMask;
  658. Information->PixelInformation.RedMask =
  659. ((1 << VesaInformation.RedMaskSize) - 1) <<
  660. VesaInformation.RedFieldPosition;
  661. Information->PixelInformation.GreenMask =
  662. ((1 << VesaInformation.GreenMaskSize) - 1) <<
  663. VesaInformation.GreenFieldPosition;
  664. Information->PixelInformation.BlueMask =
  665. ((1 << VesaInformation.BlueMaskSize) - 1) <<
  666. VesaInformation.BlueFieldPosition;
  667. Information->PixelInformation.ReservedMask =
  668. ((1 << VesaInformation.ReservedMaskSize) - 1) <<
  669. VesaInformation.ReservedFieldPosition;
  670. Information->PixelsPerScanLine = VesaInformation.BytesPerScanLine /
  671. (VesaInformation.BitsPerPixel / 8);
  672. if ((Information->PixelInformation.RedMask |
  673. Information->PixelInformation.GreenMask |
  674. Information->PixelInformation.BlueMask |
  675. Information->PixelInformation.ReservedMask) == 0) {
  676. continue;
  677. }
  678. Modes[ModeCount].VesaModeNumber = VesaModeList[VesaModeIndex];
  679. Modes[ModeCount].BitsPerPixel = VesaInformation.BitsPerPixel;
  680. Modes[ModeCount].FrameBufferBase = VesaInformation.PhysicalBasePointer;
  681. ModeCount += 1;
  682. }
  683. if (EfiVesaModes != NULL) {
  684. EfiFreePool(EfiVesaModes);
  685. EfiVesaModes = NULL;
  686. }
  687. EfiVesaModeCount = 0;
  688. if (ModeCount == 0) {
  689. EfiFreePool(Modes);
  690. return EFI_UNSUPPORTED;
  691. }
  692. EfiVesaModes = Modes;
  693. EfiVesaModeCount = ModeCount;
  694. return EFI_SUCCESS;
  695. }
  696. UINTN
  697. EfipPcatSelectInitialVideoMode (
  698. VOID
  699. )
  700. /*++
  701. Routine Description:
  702. This routine attempts to select an initial VESA graphics mode.
  703. Arguments:
  704. None.
  705. Return Value:
  706. Returns the mode index of the best video mode.
  707. --*/
  708. {
  709. EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information;
  710. PEFI_VESA_MODE Mode;
  711. UINTN ModeIndex;
  712. BOOLEAN NewWinner;
  713. UINTN WinnerBitsPerPixel;
  714. UINTN WinnerIndex;
  715. UINTN WinnerX;
  716. UINTN WinnerY;
  717. //
  718. // Find the biggest supported video mode.
  719. //
  720. WinnerIndex = 0;
  721. WinnerBitsPerPixel = 0;
  722. WinnerX = 0;
  723. WinnerY = 0;
  724. for (ModeIndex = 0; ModeIndex < EfiVesaModeCount; ModeIndex += 1) {
  725. Mode = &(EfiVesaModes[ModeIndex]);
  726. Information = &(Mode->Information);
  727. if (Mode->Failed != FALSE) {
  728. continue;
  729. }
  730. NewWinner = FALSE;
  731. //
  732. // If the resolution is just better, take it.
  733. //
  734. if ((Information->HorizontalResolution > WinnerX) &&
  735. (Information->VerticalResolution > WinnerY)) {
  736. NewWinner = TRUE;
  737. //
  738. // If the resolution is at least the same but the bits per pixel is
  739. // better, take it.
  740. //
  741. } else if ((Information->HorizontalResolution >= WinnerX) &&
  742. (Information->VerticalResolution >= WinnerY) &&
  743. (Mode->BitsPerPixel > WinnerBitsPerPixel)) {
  744. NewWinner = TRUE;
  745. }
  746. if (NewWinner != FALSE) {
  747. WinnerX = Information->HorizontalResolution;
  748. WinnerY = Information->VerticalResolution;
  749. WinnerBitsPerPixel = Mode->BitsPerPixel;
  750. WinnerIndex = ModeIndex;
  751. }
  752. }
  753. return WinnerIndex;
  754. }
  755. EFI_STATUS
  756. EfipPcatGetVesaInformation (
  757. PVESA_INFORMATION Information
  758. )
  759. /*++
  760. Routine Description:
  761. This routine attempts to get the VESA information structure.
  762. Arguments:
  763. Information - Supplies a pointer where the VESA information will be
  764. returned.
  765. Return Value:
  766. EFI Status code.
  767. --*/
  768. {
  769. PVESA_INFORMATION InformationData;
  770. BIOS_CALL_CONTEXT RealModeContext;
  771. EFI_STATUS Status;
  772. //
  773. // Create a standard BIOS call context.
  774. //
  775. Status = EfipCreateBiosCallContext(&RealModeContext, 0x10);
  776. if (EFI_ERROR(Status)) {
  777. goto GetVesaInformationEnd;
  778. }
  779. //
  780. // Copy the signature into the data page.
  781. //
  782. InformationData = RealModeContext.DataPage;
  783. InformationData->Signature = Information->Signature;
  784. //
  785. // Set up the call to int 10, VESA function 0, get information.
  786. //
  787. RealModeContext.Eax = VESA_FUNCTION_GET_VESA_INFORMATION;
  788. RealModeContext.Es = ADDRESS_TO_SEGMENT((UINTN)RealModeContext.DataPage);
  789. RealModeContext.Edi = (UINTN)(RealModeContext.DataPage) & 0x0F;
  790. //
  791. // Execute the firmware call.
  792. //
  793. EfipExecuteBiosCall(&RealModeContext);
  794. //
  795. // Check for an error. The status code is in Ah.
  796. //
  797. if (((RealModeContext.Eax & 0xFF00) != 0) ||
  798. ((RealModeContext.Eax & 0x00FF) != 0x4F)) {
  799. Status = EFI_DEVICE_ERROR;
  800. goto GetVesaInformationEnd;
  801. }
  802. EfiCopyMem(Information, InformationData, sizeof(VESA_INFORMATION));
  803. Status = EFI_SUCCESS;
  804. GetVesaInformationEnd:
  805. EfipDestroyBiosCallContext(&RealModeContext);
  806. return Status;
  807. }
  808. EFI_STATUS
  809. EfipPcatGetVesaModeInformation (
  810. UINT16 ModeNumber,
  811. PVESA_MODE_INFORMATION ModeInformation
  812. )
  813. /*++
  814. Routine Description:
  815. This routine attempts to get detailed information for the given VESA mode
  816. number.
  817. Arguments:
  818. ModeNumber - Supplies the mode number to query.
  819. ModeInformation - Supplies a pointer where the detailed mode information
  820. will be returned.
  821. Return Value:
  822. EFI Status code.
  823. --*/
  824. {
  825. BIOS_CALL_CONTEXT RealModeContext;
  826. EFI_STATUS Status;
  827. //
  828. // Create a standard BIOS call context.
  829. //
  830. Status = EfipCreateBiosCallContext(&RealModeContext, 0x10);
  831. if (EFI_ERROR(Status)) {
  832. goto GetVesaModeInformationEnd;
  833. }
  834. //
  835. // Set up the call to int 10, VESA function 1, get mode information.
  836. //
  837. RealModeContext.Eax = VESA_FUNCTION_GET_MODE_INFORMATION;
  838. RealModeContext.Es = ADDRESS_TO_SEGMENT((UINTN)RealModeContext.DataPage);
  839. RealModeContext.Edi = (UINTN)RealModeContext.DataPage & 0x0F;
  840. RealModeContext.Ecx = ModeNumber;
  841. //
  842. // Execute the firmware call.
  843. //
  844. EfipExecuteBiosCall(&RealModeContext);
  845. //
  846. // Check for an error. The status code is in Ah.
  847. //
  848. if (((RealModeContext.Eax & 0xFF00) != 0) ||
  849. ((RealModeContext.Eax & 0x00FF) != 0x4F)) {
  850. Status = EFI_DEVICE_ERROR;
  851. goto GetVesaModeInformationEnd;
  852. }
  853. EfiCopyMem(ModeInformation,
  854. RealModeContext.DataPage,
  855. sizeof(VESA_MODE_INFORMATION));
  856. Status = EFI_SUCCESS;
  857. GetVesaModeInformationEnd:
  858. EfipDestroyBiosCallContext(&RealModeContext);
  859. return Status;
  860. }
  861. EFI_STATUS
  862. EfipPcatSetVesaMode (
  863. UINT16 ModeNumber
  864. )
  865. /*++
  866. Routine Description:
  867. This routine attempts to set the given VESA mode.
  868. Arguments:
  869. ModeNumber - Supplies the mode number to set.
  870. Return Value:
  871. EFI Status code.
  872. --*/
  873. {
  874. BIOS_CALL_CONTEXT RealModeContext;
  875. EFI_STATUS Status;
  876. //
  877. // Create a standard BIOS call context.
  878. //
  879. Status = EfipCreateBiosCallContext(&RealModeContext, 0x10);
  880. if (EFI_ERROR(Status)) {
  881. goto PcatSetVesaModeEnd;
  882. }
  883. //
  884. // Set up the call to int 10, VESA function 1, get mode information.
  885. //
  886. RealModeContext.Eax = VESA_FUNCTION_SET_MODE;
  887. RealModeContext.Ebx = ModeNumber |
  888. VESA_MODE_NUMBER_USE_LINEAR_MODEL |
  889. VESA_MODE_NUMBER_DONT_CLEAR_DISPLAY;
  890. //
  891. // Execute the firmware call.
  892. //
  893. EfipExecuteBiosCall(&RealModeContext);
  894. //
  895. // Check for an error. The status code is in Ah.
  896. //
  897. if (((RealModeContext.Eax & 0xFF00) != 0) ||
  898. ((RealModeContext.Eax & 0x00FF) != 0x4F)) {
  899. Status = EFI_DEVICE_ERROR;
  900. goto PcatSetVesaModeEnd;
  901. }
  902. Status = EFI_SUCCESS;
  903. PcatSetVesaModeEnd:
  904. EfipDestroyBiosCallContext(&RealModeContext);
  905. return Status;
  906. }