source: bootcd/isolinux/syslinux-6.03/efi/console.c @ 26ffad7

Last change on this file since 26ffad7 was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * Copyright 2011-2014 Intel Corporation - All Rights Reserved
3 */
4
5#include <syslinux/linux.h>
6#include "efi.h"
7#include <string.h>
8
9extern EFI_GUID GraphicsOutputProtocol;
10
11static uint32_t console_default_attribute;
12static bool console_default_cursor;
13
14/*
15 * We want to restore the console state when we boot a kernel or return
16 * to the firmware.
17 */
18void efi_console_save(void)
19{
20    SIMPLE_TEXT_OUTPUT_INTERFACE *out = ST->ConOut;
21    SIMPLE_TEXT_OUTPUT_MODE *mode = out->Mode;
22
23    console_default_attribute = mode->Attribute;
24    console_default_cursor = mode->CursorVisible;
25}
26
27void efi_console_restore(void)
28{
29    SIMPLE_TEXT_OUTPUT_INTERFACE *out = ST->ConOut;
30
31    uefi_call_wrapper(out->SetAttribute, 2, out, console_default_attribute);
32    uefi_call_wrapper(out->EnableCursor, 2, out, console_default_cursor);
33}
34
35__export void writechr(char data)
36{
37        efi_write_char(data, 0);
38}
39
40static inline EFI_STATUS open_protocol(EFI_HANDLE handle, EFI_GUID *protocol,
41                                       void **interface, EFI_HANDLE agent,
42                                       EFI_HANDLE controller, UINT32 attributes)
43{
44        return uefi_call_wrapper(BS->OpenProtocol, 6, handle, protocol,
45                                 interface, agent, controller, attributes);
46}
47
48static inline EFI_STATUS
49gop_query_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN *size,
50               EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **info)
51{
52        return uefi_call_wrapper(gop->QueryMode, 4, gop,
53                                 gop->Mode->Mode, size, info);
54}
55
56static inline void bit_mask(uint32_t mask, uint8_t *pos, uint8_t *size)
57{
58        *pos = 0;
59        *size = 0;
60
61        if (mask) {
62                while (!(mask & 0x1)) {
63                        mask >>= 1;
64                        (*pos)++;
65                }
66
67                while (mask & 0x1) {
68                        mask >>= 1;
69                        (*size)++;
70                }
71        }
72}
73
74static int setup_gop(struct screen_info *si)
75{
76        EFI_HANDLE *handles = NULL;
77        EFI_STATUS status;
78        EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, *found;
79        EFI_GRAPHICS_PIXEL_FORMAT pixel_fmt;
80        EFI_PIXEL_BITMASK pixel_info;
81        uint32_t pixel_scanline;
82        UINTN i, nr_handles;
83        UINTN size;
84        uint16_t lfb_width, lfb_height;
85        uint32_t lfb_base, lfb_size;
86        int err = 0;
87        void **gop_handle = NULL;
88
89        size = 0;
90        status = uefi_call_wrapper(BS->LocateHandle, 5, ByProtocol, &GraphicsOutputProtocol,
91                                NULL, &size, gop_handle);
92        /* LibLocateHandle handle already returns the number of handles.
93         * There is no need to divide by sizeof(EFI_HANDLE)
94         */
95        status = LibLocateHandle(ByProtocol, &GraphicsOutputProtocol,
96                                 NULL, &nr_handles, &handles);
97        if (status == EFI_BUFFER_TOO_SMALL) {
98
99                handles = AllocatePool(nr_handles);
100                if (!handles)
101                        return 0;
102
103                status = LibLocateHandle(ByProtocol, &GraphicsOutputProtocol,
104                                         NULL, &nr_handles, &handles);
105        }
106        if (status != EFI_SUCCESS)
107                goto out;
108
109        found = NULL;
110        for (i = 0; i < nr_handles; i++) {
111                EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
112                EFI_PCI_IO *pciio = NULL;
113                EFI_HANDLE *h = handles[i];
114
115                status = uefi_call_wrapper(BS->HandleProtocol, 3, h,
116                                           &GraphicsOutputProtocol, (void **)&gop);
117                if (status != EFI_SUCCESS)
118                        continue;
119                uefi_call_wrapper(BS->HandleProtocol, 3, h,
120                                  &PciIoProtocol, (void **)&pciio);
121                status = gop_query_mode(gop, &size, &info);
122                if (status == EFI_SUCCESS && (!found || pciio)) {
123                        lfb_width = info->HorizontalResolution;
124                        lfb_height = info->VerticalResolution;
125                        lfb_base = gop->Mode->FrameBufferBase;
126                        lfb_size = gop->Mode->FrameBufferSize;
127                        pixel_fmt = info->PixelFormat;
128                        pixel_info = info->PixelInformation;
129                        pixel_scanline = info->PixelsPerScanLine;
130                        if (pciio)
131                                break;
132                        found = gop;
133                }
134        }
135
136        if (!found)
137                goto out;
138
139        err = 1;
140
141        dprintf("setup_screen: set up screen parameters for EFI GOP\n");
142        si->orig_video_isVGA = 0x70; /* EFI framebuffer */
143
144        si->lfb_base = lfb_base;
145        si->lfb_size = lfb_size;
146        si->lfb_width = lfb_width;
147        si->lfb_height = lfb_height;
148        si->pages = 1;
149
150        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);
151        switch (pixel_fmt) {
152        case PixelRedGreenBlueReserved8BitPerColor:
153                si->lfb_depth = 32;
154                si->lfb_linelength = pixel_scanline * 4;
155                si->red_size = 8;
156                si->red_pos = 0;
157                si->green_size = 8;
158                si->green_pos = 8;
159                si->blue_size = 8;
160                si->blue_pos = 16;
161                si->rsvd_size = 8;
162                si->rsvd_pos = 24;
163                break;
164        case PixelBlueGreenRedReserved8BitPerColor:
165                si->lfb_depth = 32;
166                si->lfb_linelength = pixel_scanline * 4;
167                si->red_size = 8;
168                si->red_pos = 16;
169                si->green_size = 8;
170                si->green_pos = 8;
171                si->blue_size = 8;
172                si->blue_pos = 0;
173                si->rsvd_size = 8;
174                si->rsvd_pos = 24;
175                break;
176        case PixelBitMask:
177                bit_mask(pixel_info.RedMask, &si->red_pos,
178                         &si->red_size);
179                bit_mask(pixel_info.GreenMask, &si->green_pos,
180                         &si->green_size);
181                bit_mask(pixel_info.BlueMask, &si->blue_pos,
182                         &si->blue_size);
183                bit_mask(pixel_info.ReservedMask, &si->rsvd_pos,
184                         &si->rsvd_size);
185                si->lfb_depth = si->red_size + si->green_size +
186                        si->blue_size + si->rsvd_size;
187                si->lfb_linelength = (pixel_scanline * si->lfb_depth) / 8;
188                break;
189        default:
190                si->lfb_depth = 4;;
191                si->lfb_linelength = si->lfb_width / 2;
192                si->red_size = 0;
193                si->red_pos = 0;
194                si->green_size = 0;
195                si->green_pos = 0;
196                si->blue_size = 0;
197                si->blue_pos = 0;
198                si->rsvd_size = 0;
199                si->rsvd_pos = 0;
200                break;
201        }
202        dprintf("setup_screen: depth %d line %d rpos %d rsize %d gpos %d gsize %d bpos %d bsize %d rsvpos %d rsvsize %d\n",
203                si->lfb_depth, si->lfb_linelength,
204                si->red_pos, si->red_size,
205                si->green_pos, si->green_size,
206                si->blue_pos, si->blue_size,
207                si->blue_pos, si->blue_size,
208                si->rsvd_pos, si->rsvd_size);
209       
210out:
211        if (handles) FreePool(handles);
212
213        return err;
214}
215
216#define EFI_UGA_PROTOCOL_GUID \
217  { \
218    0x982c298b, 0xf4fa, 0x41cb, {0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 } \
219  }
220
221typedef struct _EFI_UGA_DRAW_PROTOCOL EFI_UGA_DRAW_PROTOCOL;
222
223typedef
224EFI_STATUS
225(EFIAPI *EFI_UGA_DRAW_PROTOCOL_GET_MODE) (
226  IN  EFI_UGA_DRAW_PROTOCOL *This,
227  OUT UINT32 *Width,
228  OUT UINT32 *Height,
229  OUT UINT32 *Depth,
230  OUT UINT32 *Refresh
231  )
232;
233
234struct _EFI_UGA_DRAW_PROTOCOL {
235        EFI_UGA_DRAW_PROTOCOL_GET_MODE  GetMode;
236        void    *SetMode;
237        void    *Blt;
238};
239
240static int setup_uga(struct screen_info *si)
241{
242        EFI_UGA_DRAW_PROTOCOL *uga, *first;
243        EFI_GUID UgaProtocol = EFI_UGA_PROTOCOL_GUID;
244        UINT32 width, height;
245        EFI_STATUS status;
246        EFI_HANDLE *handles;
247        UINTN i, nr_handles;
248        int rv = 0;
249
250        status = LibLocateHandle(ByProtocol, &UgaProtocol,
251                                 NULL, &nr_handles, &handles);
252        if (status != EFI_SUCCESS)
253                return rv;
254
255        for (i = 0; i < nr_handles; i++) {
256                EFI_PCI_IO *pciio = NULL;
257                EFI_HANDLE *handle = handles[i];
258                UINT32 w, h, depth, refresh;
259
260                status = uefi_call_wrapper(BS->HandleProtocol, 3, handle,
261                                           &UgaProtocol, (void **)&uga);
262                if (status != EFI_SUCCESS)
263                        continue;
264
265                uefi_call_wrapper(BS->HandleProtocol, 3, handle,
266                                  &PciIoProtocol, (void **)&pciio);
267
268                status = uefi_call_wrapper(uga->GetMode, 5, uga, &w, &h,
269                                           &depth, &refresh);
270
271                if (status == EFI_SUCCESS && (!first || pciio)) {
272                        width = w;
273                        height = h;
274
275                        if (pciio)
276                                break;
277
278                        first = uga;
279                }
280        }
281
282        if (!first)
283                goto out;
284        rv = 1;
285
286        si->orig_video_isVGA = 0x70; /* EFI framebuffer */
287
288        si->lfb_depth = 32;
289        si->lfb_width = width;
290        si->lfb_height = height;
291
292        si->red_size = 8;
293        si->red_pos = 16;
294        si->green_size = 8;
295        si->green_pos = 8;
296        si->blue_size = 8;
297        si->blue_pos = 0;
298        si->rsvd_size = 8;
299        si->rsvd_pos = 24;
300
301out:
302        FreePool(handles);
303        return rv;
304}
305
306void setup_screen(struct screen_info *si)
307{
308        memset(si, 0, sizeof(*si));
309
310        if (!setup_gop(si))
311                setup_uga(si);
312}
Note: See TracBrowser for help on using the repository browser.