video.c 31 KB

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