Home | History | Annotate | Download | only in vesa
      1 /* ----------------------------------------------------------------------- *
      2  *
      3  *   Copyright 1999-2008 H. Peter Anvin - All Rights Reserved
      4  *
      5  *   Permission is hereby granted, free of charge, to any person
      6  *   obtaining a copy of this software and associated documentation
      7  *   files (the "Software"), to deal in the Software without
      8  *   restriction, including without limitation the rights to use,
      9  *   copy, modify, merge, publish, distribute, sublicense, and/or
     10  *   sell copies of the Software, and to permit persons to whom
     11  *   the Software is furnished to do so, subject to the following
     12  *   conditions:
     13  *
     14  *   The above copyright notice and this permission notice shall
     15  *   be included in all copies or substantial portions of the Software.
     16  *
     17  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     18  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
     19  *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     20  *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     21  *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     22  *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     23  *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     24  *   OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  * ----------------------------------------------------------------------- */
     27 
     28 /*
     29  * initvesa.c
     30  *
     31  * Query the VESA BIOS and select a 640x480x32 mode with local mapping
     32  * support, if one exists.
     33  */
     34 
     35 #include <inttypes.h>
     36 #include <com32.h>
     37 #include <stdlib.h>
     38 #include <string.h>
     39 #include <sys/fpu.h>
     40 #include <syslinux/video.h>
     41 #include "vesa.h"
     42 #include "video.h"
     43 #include "fill.h"
     44 #include "debug.h"
     45 
     46 struct vesa_info __vesa_info;
     47 
     48 struct vesa_char *__vesacon_text_display;
     49 
     50 int __vesacon_font_height;
     51 int __vesacon_text_rows;
     52 int __vesacon_text_cols;
     53 enum vesa_pixel_format __vesacon_pixel_format = PXF_NONE;
     54 unsigned int __vesacon_bytes_per_pixel;
     55 uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT];
     56 
     57 uint32_t *__vesacon_background, *__vesacon_shadowfb;
     58 
     59 static void unpack_font(uint8_t * dst, uint8_t * src, int height)
     60 {
     61     int i;
     62 
     63     for (i = 0; i < FONT_MAX_CHARS; i++) {
     64 	memcpy(dst, src, height);
     65 	memset(dst + height, 0, FONT_MAX_HEIGHT - height);
     66 
     67 	dst += FONT_MAX_HEIGHT;
     68 	src += height;
     69     }
     70 }
     71 
     72 static int vesacon_set_mode(int *x, int *y)
     73 {
     74     uint8_t *rom_font;
     75     struct vesa_mode_info *mi;
     76     enum vesa_pixel_format bestpxf;
     77     int rv;
     78 
     79     debug("Hello, World!\r\n");
     80 
     81     /* Free any existing data structures */
     82     if (__vesacon_background) {
     83 	free(__vesacon_background);
     84 	__vesacon_background = NULL;
     85     }
     86     if (__vesacon_shadowfb) {
     87 	free(__vesacon_shadowfb);
     88 	__vesacon_shadowfb = NULL;
     89     }
     90 
     91     rv = firmware->vesa->set_mode(&__vesa_info, x, y, &bestpxf);
     92     if (rv)
     93 	return rv;
     94 
     95     mi = &__vesa_info.mi;
     96     __vesacon_bytes_per_pixel = (mi->bpp + 7) >> 3;
     97     __vesacon_format_pixels = __vesacon_format_pixels_list[bestpxf];
     98 
     99     /* Download the SYSLINUX- or firmware-provided font */
    100     __vesacon_font_height = syslinux_font_query(&rom_font);
    101     if (!__vesacon_font_height)
    102 	__vesacon_font_height = firmware->vesa->font_query(&rom_font);
    103 
    104     unpack_font((uint8_t *) __vesacon_graphics_font, rom_font,
    105 		__vesacon_font_height);
    106 
    107     __vesacon_background = calloc(mi->h_res*mi->v_res, 4);
    108     __vesacon_shadowfb = calloc(mi->h_res*mi->v_res, 4);
    109 
    110     __vesacon_init_copy_to_screen();
    111 
    112     /* Tell syslinux we changed video mode */
    113     /* In theory this should be:
    114 
    115        flags = (mi->mode_attr & 4) ? 0x0007 : 0x000f;
    116 
    117        However, that would assume all systems that claim to handle text
    118        output in VESA modes actually do that... */
    119     syslinux_report_video_mode(0x000f, mi->h_res, mi->v_res);
    120 
    121     __vesacon_pixel_format = bestpxf;
    122 
    123     return 0;
    124 }
    125 
    126 /* FIXME:
    127  * Does init_text_display need an EFI counterpart?
    128  * e.g. vesa_char may need to setup UNICODE char for EFI
    129  * and the number of screen chars may need to be sized up
    130  * accordingly. This may also require turning byte strings
    131  * into unicode strings in the framebuffer
    132  * Possibly, revisit vesacon_fill() for EFI.
    133  */
    134 static int init_text_display(void)
    135 {
    136     size_t nchars;
    137     struct vesa_char *ptr;
    138     struct vesa_char def_char = {
    139 	.ch = ' ',
    140 	.attr = 0,
    141     };
    142 
    143     if (__vesacon_text_display)
    144 	free(__vesacon_text_display);
    145 
    146     __vesacon_text_cols = TEXT_PIXEL_COLS / FONT_WIDTH;
    147     __vesacon_text_rows = TEXT_PIXEL_ROWS / __vesacon_font_height;
    148     nchars = (__vesacon_text_cols+2) * (__vesacon_text_rows+2);
    149 
    150     __vesacon_text_display = ptr = malloc(nchars * sizeof(struct vesa_char));
    151 
    152     if (!ptr)
    153 	return -1;
    154 
    155     vesacon_fill(ptr, def_char, nchars);
    156     __vesacon_init_cursor(__vesacon_font_height);
    157 
    158     return 0;
    159 }
    160 
    161 /*
    162  * On input, VESA initialization is passed a desirable resolution. On
    163  * return, either the requested resolution is set or the system
    164  * supported default resolution is set and returned to the caller.
    165  */
    166 int __vesacon_init(int *x, int *y)
    167 {
    168     int rv;
    169 
    170     /* We need the FPU for graphics, at least libpng et al will need it... */
    171     if (x86_init_fpu())
    172 	return 10;
    173 
    174     rv = vesacon_set_mode(x, y);
    175     if (rv) {
    176 	/* Try to see if we can just patch the BIOS... */
    177 	if (__vesacon_i915resolution(*x, *y))
    178 	    return rv;
    179 	if (vesacon_set_mode(x, y))
    180 	    return rv;
    181     }
    182 
    183     init_text_display();
    184 
    185     debug("Mode set, now drawing at %#p\r\n", __vesa_info.mi.lfb_ptr);
    186 
    187     __vesacon_init_background();
    188 
    189     debug("Ready!\r\n");
    190     return 0;
    191 }
    192