Releasing debian version 6.03~pre1+dfsg-3.
[syslinux-debian/hramrach.git] / efi / console.c
bloba01e14e89a9eba1fe71ec818c5ab22c9f2f45956
1 #include <syslinux/linux.h>
2 #include "efi.h"
3 #include <string.h>
5 extern EFI_GUID GraphicsOutputProtocol;
7 static uint32_t console_default_attribute;
8 static bool console_default_cursor;
11 * We want to restore the console state when we boot a kernel or return
12 * to the firmware.
14 void efi_console_save(void)
16 SIMPLE_TEXT_OUTPUT_INTERFACE *out = ST->ConOut;
17 SIMPLE_TEXT_OUTPUT_MODE *mode = out->Mode;
19 console_default_attribute = mode->Attribute;
20 console_default_cursor = mode->CursorVisible;
23 void efi_console_restore(void)
25 SIMPLE_TEXT_OUTPUT_INTERFACE *out = ST->ConOut;
27 uefi_call_wrapper(out->SetAttribute, 2, out, console_default_attribute);
28 uefi_call_wrapper(out->EnableCursor, 2, out, console_default_cursor);
31 __export void writechr(char data)
33 efi_write_char(data, 0);
36 static inline EFI_STATUS open_protocol(EFI_HANDLE handle, EFI_GUID *protocol,
37 void **interface, EFI_HANDLE agent,
38 EFI_HANDLE controller, UINT32 attributes)
40 return uefi_call_wrapper(BS->OpenProtocol, 6, handle, protocol,
41 interface, agent, controller, attributes);
44 static inline EFI_STATUS
45 gop_query_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN *size,
46 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **info)
48 return uefi_call_wrapper(gop->QueryMode, 4, gop,
49 gop->Mode->Mode, size, info);
52 static inline void bit_mask(uint32_t mask, uint8_t *pos, uint8_t *size)
54 *pos = 0;
55 *size = 0;
57 if (mask) {
58 while (!(mask & 0x1)) {
59 mask >>= 1;
60 (*pos)++;
63 while (mask & 0x1) {
64 mask >>= 1;
65 (*size)++;
70 static int setup_gop(struct screen_info *si)
72 EFI_HANDLE *handles = NULL;
73 EFI_STATUS status;
74 EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, *found;
75 EFI_GRAPHICS_PIXEL_FORMAT pixel_fmt;
76 EFI_PIXEL_BITMASK pixel_info;
77 uint32_t pixel_scanline;
78 UINTN i, nr_handles;
79 UINTN size;
80 uint16_t lfb_width, lfb_height;
81 uint32_t lfb_base, lfb_size;
82 int err = 0;
83 void **gop_handle = NULL;
85 size = 0;
86 status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &GraphicsOutputProtocol,
87 NULL, &size, gop_handle);
88 /* LibLocateHandle handle already returns the number of handles.
89 * There is no need to divide by sizeof(EFI_HANDLE)
91 status = LibLocateHandle(ByProtocol, &GraphicsOutputProtocol,
92 NULL, &nr_handles, &handles);
93 if (status == EFI_BUFFER_TOO_SMALL) {
95 handles = AllocatePool(nr_handles);
96 if (!handles)
97 return 0;
99 status = LibLocateHandle(ByProtocol, &GraphicsOutputProtocol,
100 NULL, &nr_handles, &handles);
102 if (status != EFI_SUCCESS)
103 goto out;
105 found = NULL;
106 for (i = 0; i < nr_handles; i++) {
107 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
108 EFI_PCI_IO *pciio = NULL;
109 EFI_HANDLE *h = handles[i];
111 status = uefi_call_wrapper(BS->HandleProtocol, 3, h,
112 &GraphicsOutputProtocol, (void **)&gop);
113 if (status != EFI_SUCCESS)
114 continue;
115 uefi_call_wrapper(BS->HandleProtocol, 3, h,
116 &PciIoProtocol, (void **)&pciio);
117 status = gop_query_mode(gop, &size, &info);
118 if (status == EFI_SUCCESS && (!found || pciio)) {
119 lfb_width = info->HorizontalResolution;
120 lfb_height = info->VerticalResolution;
121 lfb_base = gop->Mode->FrameBufferBase;
122 lfb_size = gop->Mode->FrameBufferSize;
123 pixel_fmt = info->PixelFormat;
124 pixel_info = info->PixelInformation;
125 pixel_scanline = info->PixelsPerScanLine;
126 if (pciio)
127 break;
128 found = gop;
132 if (!found)
133 goto out;
135 err = 1;
137 dprintf("setup_screen: set up screen parameters for EFI GOP\n");
138 si->orig_video_isVGA = 0x70; /* EFI framebuffer */
140 si->lfb_base = lfb_base;
141 si->lfb_size = lfb_size;
142 si->lfb_width = lfb_width;
143 si->lfb_height = lfb_height;
144 si->pages = 1;
146 dprintf("setup_screen: lfb_base 0x%x lfb_size %d lfb_width %d lfb_height %d\n", lfb_base, lfb_size, lfb_width, lfb_height);
147 switch (pixel_fmt) {
148 case PixelRedGreenBlueReserved8BitPerColor:
149 si->lfb_depth = 32;
150 si->lfb_linelength = pixel_scanline * 4;
151 si->red_size = 8;
152 si->red_pos = 0;
153 si->green_size = 8;
154 si->green_pos = 8;
155 si->blue_size = 8;
156 si->blue_pos = 16;
157 si->rsvd_size = 8;
158 si->rsvd_pos = 24;
159 break;
160 case PixelBlueGreenRedReserved8BitPerColor:
161 si->lfb_depth = 32;
162 si->lfb_linelength = pixel_scanline * 4;
163 si->red_size = 8;
164 si->red_pos = 16;
165 si->green_size = 8;
166 si->green_pos = 8;
167 si->blue_size = 8;
168 si->blue_pos = 0;
169 si->rsvd_size = 8;
170 si->rsvd_pos = 24;
171 break;
172 case PixelBitMask:
173 bit_mask(pixel_info.RedMask, &si->red_pos,
174 &si->red_size);
175 bit_mask(pixel_info.GreenMask, &si->green_pos,
176 &si->green_size);
177 bit_mask(pixel_info.BlueMask, &si->blue_pos,
178 &si->blue_size);
179 bit_mask(pixel_info.ReservedMask, &si->rsvd_pos,
180 &si->rsvd_size);
181 si->lfb_depth = si->red_size + si->green_size +
182 si->blue_size + si->rsvd_size;
183 si->lfb_linelength = (pixel_scanline * si->lfb_depth) / 8;
184 break;
185 default:
186 si->lfb_depth = 4;;
187 si->lfb_linelength = si->lfb_width / 2;
188 si->red_size = 0;
189 si->red_pos = 0;
190 si->green_size = 0;
191 si->green_pos = 0;
192 si->blue_size = 0;
193 si->blue_pos = 0;
194 si->rsvd_size = 0;
195 si->rsvd_pos = 0;
196 break;
198 dprintf("setup_screen: depth %d line %d rpos %d rsize %d gpos %d gsize %d bpos %d bsize %d rsvpos %d rsvsize %d\n",
199 si->lfb_depth, si->lfb_linelength,
200 si->red_pos, si->red_size,
201 si->green_pos, si->green_size,
202 si->blue_pos, si->blue_size,
203 si->blue_pos, si->blue_size,
204 si->rsvd_pos, si->rsvd_size);
206 out:
207 if (handles) FreePool(handles);
209 return err;
212 #define EFI_UGA_PROTOCOL_GUID \
214 0x982c298b, 0xf4fa, 0x41cb, {0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 } \
217 typedef struct _EFI_UGA_DRAW_PROTOCOL EFI_UGA_DRAW_PROTOCOL;
219 typedef
220 EFI_STATUS
221 (EFIAPI *EFI_UGA_DRAW_PROTOCOL_GET_MODE) (
222 IN EFI_UGA_DRAW_PROTOCOL *This,
223 OUT UINT32 *Width,
224 OUT UINT32 *Height,
225 OUT UINT32 *Depth,
226 OUT UINT32 *Refresh
230 struct _EFI_UGA_DRAW_PROTOCOL {
231 EFI_UGA_DRAW_PROTOCOL_GET_MODE GetMode;
232 void *SetMode;
233 void *Blt;
236 static int setup_uga(struct screen_info *si)
238 EFI_UGA_DRAW_PROTOCOL *uga, *first;
239 EFI_GUID UgaProtocol = EFI_UGA_PROTOCOL_GUID;
240 UINT32 width, height;
241 EFI_STATUS status;
242 EFI_HANDLE *handles;
243 UINTN i, nr_handles;
244 int rv = 0;
246 status = LibLocateHandle(ByProtocol, &UgaProtocol,
247 NULL, &nr_handles, &handles);
248 if (status != EFI_SUCCESS)
249 return rv;
251 for (i = 0; i < nr_handles; i++) {
252 EFI_PCI_IO *pciio = NULL;
253 EFI_HANDLE *handle = handles[i];
254 UINT32 w, h, depth, refresh;
256 status = uefi_call_wrapper(BS->HandleProtocol, 3, handle,
257 &UgaProtocol, (void **)&uga);
258 if (status != EFI_SUCCESS)
259 continue;
261 uefi_call_wrapper(BS->HandleProtocol, 3, handle,
262 &PciIoProtocol, (void **)&pciio);
264 status = uefi_call_wrapper(uga->GetMode, 5, uga, &w, &h,
265 &depth, &refresh);
267 if (status == EFI_SUCCESS && (!first || pciio)) {
268 width = w;
269 height = h;
271 if (pciio)
272 break;
274 first = uga;
278 if (!first)
279 goto out;
280 rv = 1;
282 si->orig_video_isVGA = 0x70; /* EFI framebuffer */
284 si->lfb_depth = 32;
285 si->lfb_width = width;
286 si->lfb_height = height;
288 si->red_size = 8;
289 si->red_pos = 16;
290 si->green_size = 8;
291 si->green_pos = 8;
292 si->blue_size = 8;
293 si->blue_pos = 0;
294 si->rsvd_size = 8;
295 si->rsvd_pos = 24;
297 out:
298 FreePool(handles);
299 return rv;
302 void setup_screen(struct screen_info *si)
304 memset(si, 0, sizeof(*si));
306 if (!setup_gop(si))
307 setup_uga(si);