aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchandramouli narayanan <mouli@linux.intel.com>2012-07-13 10:43:32 -0700
committerchandramouli narayanan <mouli@linux.intel.com>2012-07-13 10:43:32 -0700
commitb21b8a48807b13eb1cefd94b4d7eea740c430801 (patch)
tree5a096a5ad33f5be2e660b79e16b529c5651450be
parent16aba524b339a2b0c5f0514827a8329fd120be03 (diff)
downloadsyslinux-b21b8a48807b13eb1cefd94b4d7eea740c430801.tar.gz
syslinux-b21b8a48807b13eb1cefd94b4d7eea740c430801.tar.xz
syslinux-b21b8a48807b13eb1cefd94b4d7eea740c430801.zip
This is the first cut checkin for GOP supporting the menu subsystem.
For the initial cut, all of vesa code is dropped into vesa/efi with code buildable for EFI with a build option. There is VESA only code that is in the efi subdirectory as well that should go away eventually. Other files not dependent on EFI or not relevant to EFI need to be removed as well (e.g. i915resolution.c). The crux of the code is in initvesa.c and screencpy.c. The GOP initialization code sets up a matching graphics mode for the caller's resolution needs. The VESA data structure is populated and mapped to the EFI implementation as much as possible with some EFI extensions. Since there is no way to query EFI for font, raw font data for cp865_8x16 is added. The code should build. Initial issues with testing the code are: GOP mode on qemu-x86_64 does not match 640x480 and secondly querying for the mode info on qemu fails. However, a simple program querying GOP modes on efi64 platform works ok though. Testing the resulting syslinux.efi on an efi64 platform does not seem to print output other than in efi_main() routine . I suspect that it may be due to loading failure or file system initialization. The issue does not show up on qemu. In summary, there are issues on qemu and an efi64 platform that need to be resolved.
-rw-r--r--com32/lib/Makefile13
-rw-r--r--com32/lib/sys/vesa/efi/background.c456
-rw-r--r--com32/lib/sys/vesa/efi/cp865_8x16.h262
-rw-r--r--com32/lib/sys/vesa/efi/debug.h36
-rw-r--r--com32/lib/sys/vesa/efi/drawtxt.c317
-rw-r--r--com32/lib/sys/vesa/efi/fill.h63
-rw-r--r--com32/lib/sys/vesa/efi/fmtpixel.c101
-rw-r--r--com32/lib/sys/vesa/efi/i915resolution.c795
-rw-r--r--com32/lib/sys/vesa/efi/initvesa.c617
-rw-r--r--com32/lib/sys/vesa/efi/screencpy.c169
-rw-r--r--com32/lib/sys/vesa/efi/vesa.h129
-rw-r--r--com32/lib/sys/vesa/efi/video.h97
-rw-r--r--com32/lib/sys/vesacon_write.c4
-rw-r--r--com32/menu/Makefile6
14 files changed, 3065 insertions, 0 deletions
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 7823fad9..616a5506 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -23,11 +23,19 @@ LIBJPG_OBJS = \
jpeg/rgb24.o jpeg/bgr24.o jpeg/yuv420p.o jpeg/grey.o \
jpeg/rgba32.o jpeg/bgra32.o
+ifndef EFI_BUILD
LIBVESA_OBJS = \
sys/vesacon_write.o sys/vesaserial_write.o \
sys/vesa/initvesa.o sys/vesa/drawtxt.o sys/vesa/background.o \
sys/vesa/alphatbl.o sys/vesa/screencpy.o sys/vesa/fmtpixel.o \
sys/vesa/i915resolution.o
+else
+LIBVESA_OBJS = \
+ sys/vesacon_write.o sys/vesaserial_write.o \
+ sys/vesa/efi/initvesa.o sys/vesa/efi/drawtxt.o sys/vesa/efi/background.o \
+ sys/vesa/alphatbl.o sys/vesa/efi/screencpy.o sys/vesa/efi/fmtpixel.o \
+ sys/vesa/efi/i915resolution.o
+endif
LIBMISC_OBJS = \
sys/libansi.o sys/gpxe.o
@@ -98,7 +106,12 @@ install: all
cp -r ../include $(INSTALLROOT)$(COM32DIR)
# These files are performance critical, and doesn't compile well with -Os
+#FIXME: determine if drawtxt.c is really EFI-dependent
+#ifndef EFI_BUILD
sys/vesa/drawtxt.o: sys/vesa/drawtxt.c
+#else
+sys/vesa/efi/drawtxt.o: sys/vesa/efi/drawtxt.c
+#endif
$(CC) $(MAKEDEPS) $(CFLAGS) -O3 -c -o $@ $<
sys/vesa/alphatbl.c: sys/vesa/alphatbl.pl
diff --git a/com32/lib/sys/vesa/efi/background.c b/com32/lib/sys/vesa/efi/background.c
new file mode 100644
index 00000000..93577461
--- /dev/null
+++ b/com32/lib/sys/vesa/efi/background.c
@@ -0,0 +1,456 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2006-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdio.h>
+#include <png.h>
+#include <tinyjpeg.h>
+#include <com32.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <minmax.h>
+#include <stdbool.h>
+#include <ilog2.h>
+#include <syslinux/loadfile.h>
+#include "vesa.h"
+#include "video.h"
+
+/*** FIX: This really should be alpha-blended with color index 0 ***/
+
+/* For best performance, "start" should be a multiple of 4, to assure
+ aligned dwords. */
+static void draw_background_line(int line, int start, int npixels)
+{
+ uint32_t *bgptr = &__vesacon_background[line*__vesa_info.mi.h_res+start];
+ unsigned int bytes_per_pixel = __vesacon_bytes_per_pixel;
+ size_t fbptr = line * __vesa_info.mi.logical_scan + start*bytes_per_pixel;
+
+ __vesacon_copy_to_screen(fbptr, bgptr, npixels);
+}
+
+/* This draws the border, then redraws the text area */
+static void draw_background(void)
+{
+ int i;
+ const int bottom_border = VIDEO_BORDER +
+ (TEXT_PIXEL_ROWS % __vesacon_font_height);
+ const int right_border = VIDEO_BORDER + (TEXT_PIXEL_COLS % FONT_WIDTH);
+
+ for (i = 0; i < VIDEO_BORDER; i++)
+ draw_background_line(i, 0, __vesa_info.mi.h_res);
+
+ for (i = VIDEO_BORDER; i < __vesa_info.mi.v_res - bottom_border; i++) {
+ draw_background_line(i, 0, VIDEO_BORDER);
+ draw_background_line(i, __vesa_info.mi.h_res - right_border,
+ right_border);
+ }
+
+ for (i = __vesa_info.mi.v_res - bottom_border;
+ i < __vesa_info.mi.v_res; i++)
+ draw_background_line(i, 0, __vesa_info.mi.h_res);
+
+ __vesacon_redraw_text();
+}
+
+/*
+ * Tile an image in the UL corner across the entire screen
+ */
+static void tile_image(int width, int height)
+{
+ int xsize = __vesa_info.mi.h_res;
+ int ysize = __vesa_info.mi.v_res;
+ int x, y, yr;
+ int xl, yl;
+ uint32_t *sp, *dp, *drp, *dtp;
+
+ drp = __vesacon_background;
+ for (y = 0 ; y < ysize ; y += height) {
+ yl = min(height, ysize-y);
+ dtp = drp;
+ for (x = 0 ; x < xsize ; x += width) {
+ xl = min(width, xsize-x);
+ if (x || y) {
+ sp = __vesacon_background;
+ dp = dtp;
+ for (yr = 0 ; yr < yl ; yr++) {
+ memcpy(dp, sp, xl*sizeof(uint32_t));
+ dp += xsize;
+ sp += xsize;
+ }
+ }
+ dtp += xl;
+ }
+ drp += xsize*height;
+ }
+}
+
+static int read_png_file(FILE * fp)
+{
+ png_structp png_ptr = NULL;
+ png_infop info_ptr = NULL;
+#if 0
+ png_color_16p image_background;
+ static const png_color_16 my_background = { 0, 0, 0, 0, 0 };
+#endif
+ png_bytep row_pointers[__vesa_info.mi.v_res], rp;
+ int i;
+ int rv = -1;
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ info_ptr = png_create_info_struct(png_ptr);
+
+ if (!png_ptr || !info_ptr || setjmp(png_jmpbuf(png_ptr)))
+ goto err;
+
+ png_init_io(png_ptr, fp);
+ png_set_sig_bytes(png_ptr, 8);
+
+ png_set_user_limits(png_ptr, __vesa_info.mi.h_res, __vesa_info.mi.v_res);
+
+ png_read_info(png_ptr, info_ptr);
+
+ /* Set the appropriate set of transformations. We need to end up
+ with 32-bit BGRA format, no more, no less. */
+
+ /* Expand to RGB first... */
+ if (info_ptr->color_type & PNG_COLOR_MASK_PALETTE)
+ png_set_palette_to_rgb(png_ptr);
+ else if (!(info_ptr->color_type & PNG_COLOR_MASK_COLOR))
+ png_set_gray_to_rgb(png_ptr);
+
+ /* Add alpha channel, if need be */
+ if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA)) {
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(png_ptr);
+ else
+ png_set_add_alpha(png_ptr, ~0, PNG_FILLER_AFTER);
+ }
+
+ /* Adjust the byte order, if necessary */
+ png_set_bgr(png_ptr);
+
+ /* Make sure we end up with 8-bit data */
+ if (info_ptr->bit_depth == 16)
+ png_set_strip_16(png_ptr);
+ else if (info_ptr->bit_depth < 8)
+ png_set_packing(png_ptr);
+
+#if 0
+ if (png_get_bKGD(png_ptr, info_ptr, &image_background))
+ png_set_background(png_ptr, image_background,
+ PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+ else
+ png_set_background(png_ptr, &my_background,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+#endif
+
+ /* Whew! Now we should get the stuff we want... */
+ rp = (png_bytep)__vesacon_background;
+ for (i = 0; i < (int)info_ptr->height; i++) {
+ row_pointers[i] = rp;
+ rp += __vesa_info.mi.h_res << 2;
+ }
+
+ png_read_image(png_ptr, row_pointers);
+
+ tile_image(info_ptr->width, info_ptr->height);
+
+ rv = 0;
+
+err:
+ if (png_ptr)
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
+ return rv;
+}
+
+static int jpeg_sig_cmp(uint8_t * bytes, int len)
+{
+ (void)len;
+
+ return (bytes[0] == 0xff && bytes[1] == 0xd8) ? 0 : -1;
+}
+
+static int read_jpeg_file(FILE * fp, uint8_t * header, int len)
+{
+ struct jdec_private *jdec = NULL;
+ void *jpeg_file = NULL;
+ size_t length_of_file;
+ unsigned int width, height;
+ int rv = -1;
+ unsigned char *components[1];
+ unsigned int bytes_per_row[1];
+
+ rv = floadfile(fp, &jpeg_file, &length_of_file, header, len);
+ fclose(fp);
+ if (rv)
+ goto err;
+
+ jdec = tinyjpeg_init();
+ if (!jdec)
+ goto err;
+
+ if (tinyjpeg_parse_header(jdec, jpeg_file, length_of_file) < 0)
+ goto err;
+
+ tinyjpeg_get_size(jdec, &width, &height);
+ if (width > __vesa_info.mi.h_res || height > __vesa_info.mi.v_res)
+ goto err;
+
+ components[0] = (void *)__vesacon_background;
+ tinyjpeg_set_components(jdec, components, 1);
+ bytes_per_row[0] = __vesa_info.mi.h_res << 2;
+ tinyjpeg_set_bytes_per_row(jdec, bytes_per_row, 1);
+
+ tinyjpeg_decode(jdec, TINYJPEG_FMT_BGRA32);
+ tile_image(width, height);
+
+ rv = 0;
+
+err:
+ /* Don't use tinyjpeg_free() here, since we didn't allow tinyjpeg
+ to allocate the frame buffer */
+ if (jdec)
+ free(jdec);
+
+ if (jpeg_file)
+ free(jpeg_file);
+
+ return rv;
+}
+
+/* Simple grey Gaussian hole, enough to look interesting */
+int vesacon_default_background(void)
+{
+ int x, y, dx, dy, dy2;
+ int z;
+ unsigned int shft;
+ uint8_t *bgptr = (uint8_t *)__vesacon_background;
+ uint8_t k;
+
+ if (__vesacon_pixel_format == PXF_NONE)
+ return 0; /* Not in graphics mode */
+
+ z = max(__vesa_info.mi.v_res, __vesa_info.mi.h_res) >> 1;
+ z = ((z*z) >> 11) - 1;
+ shft = ilog2(z) + 1;
+
+ for (y = 0, dy = -(__vesa_info.mi.v_res >> 1);
+ y < __vesa_info.mi.v_res; y++, dy++) {
+ dy2 = dy * dy;
+ for (x = 0, dx = -(__vesa_info.mi.h_res >> 1);
+ x < __vesa_info.mi.h_res; x++, dx++) {
+ k = __vesacon_linear_to_srgb[500 + ((dx*dx + dy2) >> shft)];
+ bgptr[0] = k; /* Blue */
+ bgptr[1] = k; /* Green */
+ bgptr[2] = k; /* Red */
+ bgptr += 4; /* Dummy alpha */
+ }
+ }
+
+ draw_background();
+ return 0;
+}
+
+/* Set the background to a single flat color */
+int vesacon_set_background(unsigned int rgb)
+{
+ void *bgptr = __vesacon_background;
+ unsigned int count = __vesa_info.mi.h_res * __vesa_info.mi.v_res;
+
+ if (__vesacon_pixel_format == PXF_NONE)
+ return 0; /* Not in graphics mode */
+
+ asm volatile ("rep; stosl":"+D" (bgptr), "+c"(count)
+ :"a"(rgb)
+ :"memory");
+
+ draw_background();
+ return 0;
+}
+
+struct lss16_header {
+ uint32_t magic;
+ uint16_t xsize;
+ uint16_t ysize;
+};
+
+#define LSS16_MAGIC 0x1413f33d
+
+static inline int lss16_sig_cmp(const void *header, int len)
+{
+ const struct lss16_header *h = header;
+
+ if (len != 8)
+ return 1;
+
+ return !(h->magic == LSS16_MAGIC &&
+ h->xsize <= __vesa_info.mi.h_res &&
+ h->ysize <= __vesa_info.mi.v_res);
+}
+
+static int read_lss16_file(FILE * fp, const void *header, int header_len)
+{
+ const struct lss16_header *h = header;
+ uint32_t colors[16], color;
+ bool has_nybble;
+ uint8_t byte;
+ int count;
+ int nybble, prev;
+ enum state {
+ st_start,
+ st_c0,
+ st_c1,
+ st_c2,
+ } state;
+ int i, x, y;
+ uint32_t *bgptr = __vesacon_background;
+
+ /* Assume the header, 8 bytes, has already been loaded. */
+ if (header_len != 8)
+ return -1;
+
+ for (i = 0; i < 16; i++) {
+ uint8_t rgb[3];
+ if (fread(rgb, 1, 3, fp) != 3)
+ return -1;
+
+ colors[i] = (((rgb[0] & 63) * 255 / 63) << 16) +
+ (((rgb[1] & 63) * 255 / 63) << 8) +
+ ((rgb[2] & 63) * 255 / 63);
+ }
+
+ /* By spec, the state machine is per row */
+ for (y = 0; y < h->ysize; y++) {
+ state = st_start;
+ has_nybble = false;
+ color = colors[prev = 0]; /* By specification */
+ count = 0;
+
+ x = 0;
+ while (x < h->xsize) {
+ if (!has_nybble) {
+ if (fread(&byte, 1, 1, fp) != 1)
+ return -1;
+ nybble = byte & 0xf;
+ has_nybble = true;
+ } else {
+ nybble = byte >> 4;
+ has_nybble = false;
+ }
+
+ switch (state) {
+ case st_start:
+ if (nybble != prev) {
+ *bgptr++ = color = colors[prev = nybble];
+ x++;
+ } else {
+ state = st_c0;
+ }
+ break;
+
+ case st_c0:
+ if (nybble == 0) {
+ state = st_c1;
+ } else {
+ count = nybble;
+ goto do_run;
+ }
+ break;
+
+ case st_c1:
+ count = nybble + 16;
+ state = st_c2;
+ break;
+
+ case st_c2:
+ count += nybble << 4;
+ goto do_run;
+
+do_run:
+ count = min(count, h->xsize - x);
+ x += count;
+ asm volatile ("rep; stosl":"+D" (bgptr),
+ "+c"(count):"a"(color));
+ state = st_start;
+ break;
+ }
+ }
+
+ /* Zero-fill rest of row */
+ i = __vesa_info.mi.h_res - x;
+ asm volatile ("rep; stosl":"+D" (bgptr), "+c"(i):"a"(0):"memory");
+ }
+
+ /* Zero-fill rest of screen */
+ i = (__vesa_info.mi.v_res - y) * __vesa_info.mi.h_res;
+ asm volatile ("rep; stosl":"+D" (bgptr), "+c"(i):"a"(0):"memory");
+
+ return 0;
+}
+
+int vesacon_load_background(const char *filename)
+{
+ FILE *fp = NULL;
+ uint8_t header[8];
+ int rv = 1;
+
+ if (__vesacon_pixel_format == PXF_NONE)
+ return 0; /* Not in graphics mode */
+
+ fp = fopen(filename, "r");
+
+ if (!fp)
+ goto err;
+
+ if (fread(header, 1, 8, fp) != 8)
+ goto err;
+
+ if (!png_sig_cmp(header, 0, 8)) {
+ rv = read_png_file(fp);
+ } else if (!jpeg_sig_cmp(header, 8)) {
+ rv = read_jpeg_file(fp, header, 8);
+ } else if (!lss16_sig_cmp(header, 8)) {
+ rv = read_lss16_file(fp, header, 8);
+ }
+
+ /* This actually displays the stuff */
+ draw_background();
+
+err:
+ if (fp)
+ fclose(fp);
+
+ return rv;
+}
+
+int __vesacon_init_background(void)
+{
+ /* __vesacon_background was cleared by calloc() */
+
+ /* The VESA BIOS has already cleared the screen */
+ return 0;
+}
diff --git a/com32/lib/sys/vesa/efi/cp865_8x16.h b/com32/lib/sys/vesa/efi/cp865_8x16.h
new file mode 100644
index 00000000..9c8a2678
--- /dev/null
+++ b/com32/lib/sys/vesa/efi/cp865_8x16.h
@@ -0,0 +1,262 @@
+static const short cp865_8x16_font_magic = 0x436;
+static const unsigned cp865_8x16_font_mode = 0x0;
+static const int cp865_8x16_font_height = 0x10;
+static const uint8_t cp865_8x16_font_data[] = {
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00,
+ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+ 0x00, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1c, 0x36, 0x32, 0x30, 0x78, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
+ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00,
+ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x18, 0x70, 0x00, 0x00,
+ 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x70, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x38, 0x6c, 0x38, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x0c, 0x18, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x36, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
+ 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xce, 0xd6, 0xe6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x7c, 0xce, 0xce, 0xd6, 0xd6, 0xd6, 0xd6, 0xe6, 0xe6, 0x7c, 0x40, 0x00, 0x00, 0x00,
+ 0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+ 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x60, 0xe0, 0x62, 0x66, 0x6c, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00,
+ 0x00, 0x60, 0xe0, 0x62, 0x66, 0x6c, 0x18, 0x30, 0x66, 0xce, 0x9a, 0x3f, 0x06, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
+ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+ 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x6c, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3c, 0x66, 0x0c, 0x18, 0x32, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
diff --git a/com32/lib/sys/vesa/efi/debug.h b/com32/lib/sys/vesa/efi/debug.h
new file mode 100644
index 00000000..86d085f1
--- /dev/null
+++ b/com32/lib/sys/vesa/efi/debug.h
@@ -0,0 +1,36 @@
+#ifndef LIB_SYS_VESA_DEBUG_H
+#define LIB_SYS_VESA_DEBUG_H
+
+#if 0
+
+#include <stdio.h>
+#include <unistd.h>
+
+ssize_t __serial_write(void *fp, const void *buf, size_t count);
+
+static void debug(const char *str, ...)
+{
+ va_list va;
+ char buf[65536];
+ size_t len;
+
+ va_start(va, str);
+ len = vsnprintf(buf, sizeof buf, str, va);
+ va_end(va);
+
+ if (len >= sizeof buf)
+ len = sizeof buf - 1;
+
+ __serial_write(NULL, buf, len);
+}
+
+#else
+
+static inline void debug(const char *str, ...)
+{
+ (void)str;
+}
+
+#endif
+
+#endif /* LIB_SYS_VESA_DEBUG_H */
diff --git a/com32/lib/sys/vesa/efi/drawtxt.c b/com32/lib/sys/vesa/efi/drawtxt.c
new file mode 100644
index 00000000..85a9e974
--- /dev/null
+++ b/com32/lib/sys/vesa/efi/drawtxt.c
@@ -0,0 +1,317 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2006-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <inttypes.h>
+#include <colortbl.h>
+#include <string.h>
+#include "vesa.h"
+#include "video.h"
+#include "fill.h"
+
+/*
+ * Visible cursor information
+ */
+static uint8_t cursor_pattern[FONT_MAX_HEIGHT];
+static struct vesa_char *cursor_pointer = NULL;
+static int cursor_x, cursor_y;
+
+static inline void *copy_dword(void *dst, void *src, size_t dword_count)
+{
+ asm volatile ("rep; movsl":"+D" (dst), "+S"(src), "+c"(dword_count));
+ return dst; /* Updated destination pointer */
+}
+
+static inline __attribute__ ((always_inline))
+uint8_t alpha_val(uint8_t fg, uint8_t bg, uint8_t alpha)
+{
+ unsigned int tmp;
+
+ tmp = __vesacon_srgb_to_linear[fg] * alpha;
+ tmp += __vesacon_srgb_to_linear[bg] * (255 - alpha);
+
+ return __vesacon_linear_to_srgb[tmp >> 12];
+}
+
+static uint32_t alpha_pixel(uint32_t fg, uint32_t bg)
+{
+ uint8_t alpha = fg >> 24;
+ uint8_t fg_r = fg >> 16;
+ uint8_t fg_g = fg >> 8;
+ uint8_t fg_b = fg;
+ uint8_t bg_r = bg >> 16;
+ uint8_t bg_g = bg >> 8;
+ uint8_t bg_b = bg;
+
+ return
+ (alpha_val(fg_r, bg_r, alpha) << 16) |
+ (alpha_val(fg_g, bg_g, alpha) << 8) | (alpha_val(fg_b, bg_b, alpha));
+}
+
+static void vesacon_update_characters(int row, int col, int nrows, int ncols)
+{
+ const int height = __vesacon_font_height;
+ const int width = FONT_WIDTH;
+ uint32_t *bgrowptr, *bgptr, bgval, fgval;
+ uint32_t fgcolor = 0, bgcolor = 0, color;
+ uint8_t chbits = 0, chxbits = 0, chsbits = 0;
+ int i, j, jx, pixrow, pixsrow;
+ struct vesa_char *rowptr, *rowsptr, *cptr, *csptr;
+ unsigned int bytes_per_pixel = __vesacon_bytes_per_pixel;
+ unsigned long pixel_offset;
+ uint32_t row_buffer[__vesa_info.mi.h_res], *rowbufptr;
+ size_t fbrowptr;
+ uint8_t sha;
+
+ pixel_offset = ((row * height + VIDEO_BORDER) * __vesa_info.mi.h_res) +
+ (col * width + VIDEO_BORDER);
+
+ bgrowptr = &__vesacon_background[pixel_offset];
+ fbrowptr = (row * height + VIDEO_BORDER) * __vesa_info.mi.logical_scan +
+ (col * width + VIDEO_BORDER) * bytes_per_pixel;
+
+ /* Note that we keep a 1-character guard area around the real text area... */
+ rowptr = &__vesacon_text_display[(row+1)*(__vesacon_text_cols+2)+(col+1)];
+ rowsptr = rowptr - ((__vesacon_text_cols+2)+1);
+ pixrow = 0;
+ pixsrow = height - 1;
+
+ for (i = height * nrows; i >= 0; i--) {
+ bgptr = bgrowptr;
+ rowbufptr = row_buffer;
+
+ cptr = rowptr;
+ csptr = rowsptr;
+
+ chsbits = __vesacon_graphics_font[csptr->ch][pixsrow];
+ if (__unlikely(csptr == cursor_pointer))
+ chsbits |= cursor_pattern[pixsrow];
+ sha = console_color_table[csptr->attr].shadow;
+ chsbits &= (sha & 0x02) ? 0xff : 0x00;
+ chsbits ^= (sha & 0x01) ? 0xff : 0x00;
+ chsbits <<= (width - 2);
+ csptr++;
+
+ /* Draw two pixels beyond the end of the line. One for the shadow,
+ and one to make sure we have a whole dword of data for the copy
+ operation at the end. Note that this code depends on the fact that
+ all characters begin on dword boundaries in the frame buffer. */
+
+ for (jx = 1, j = width * ncols + 1; j >= 0; j--) {
+ chbits <<= 1;
+ chsbits <<= 1;
+ chxbits <<= 1;
+
+ switch (jx) {
+ case 1:
+ chbits = __vesacon_graphics_font[cptr->ch][pixrow];
+ if (__unlikely(cptr == cursor_pointer))
+ chbits |= cursor_pattern[pixrow];
+ sha = console_color_table[cptr->attr].shadow;
+ chxbits = chbits;
+ chxbits &= (sha & 0x02) ? 0xff : 0x00;
+ chxbits ^= (sha & 0x01) ? 0xff : 0x00;
+ fgcolor = console_color_table[cptr->attr].argb_fg;
+ bgcolor = console_color_table[cptr->attr].argb_bg;
+ cptr++;
+ jx--;
+ break;
+ case 0:
+ chsbits = __vesacon_graphics_font[csptr->ch][pixsrow];
+ if (__unlikely(csptr == cursor_pointer))
+ chsbits |= cursor_pattern[pixsrow];
+ sha = console_color_table[csptr->attr].shadow;
+ chsbits &= (sha & 0x02) ? 0xff : 0x00;
+ chsbits ^= (sha & 0x01) ? 0xff : 0x00;
+ csptr++;
+ jx = width - 1;
+ break;
+ default:
+ jx--;
+ break;
+ }
+
+ /* If this pixel is raised, use the offsetted value */
+ bgval = (chxbits & 0x80)
+ ? bgptr[__vesa_info.mi.h_res + 1] : *bgptr;
+ bgptr++;
+
+ /* If this pixel is set, use the fg color, else the bg color */
+ fgval = (chbits & 0x80) ? fgcolor : bgcolor;
+
+ /* Produce the combined color pixel value */
+ color = alpha_pixel(fgval, bgval);
+
+ /* Apply the shadow (75% shadow) */
+ if ((chsbits & ~chxbits) & 0x80) {
+ color >>= 2;
+ color &= 0x3f3f3f;
+ }
+
+ *rowbufptr++ = color;
+ }
+
+ /* Copy to frame buffer */
+ __vesacon_copy_to_screen(fbrowptr, row_buffer, rowbufptr - row_buffer);
+
+ bgrowptr += __vesa_info.mi.h_res;
+ fbrowptr += __vesa_info.mi.logical_scan;
+
+ if (++pixrow == height) {
+ rowptr += __vesacon_text_cols + 2;
+ pixrow = 0;
+ }
+ if (++pixsrow == height) {
+ rowsptr += __vesacon_text_cols + 2;
+ pixsrow = 0;
+ }
+ }
+}
+
+/* Bounding box for changed text. The (x1, y1) coordinates are +1! */
+static unsigned int upd_x0 = -1U, upd_x1, upd_y0 = -1U, upd_y1;
+
+/* Update the range already touched by various variables */
+void __vesacon_doit(void)
+{
+ if (upd_x1 > upd_x0 && upd_y1 > upd_y0) {
+ vesacon_update_characters(upd_y0, upd_x0, upd_y1 - upd_y0,
+ upd_x1 - upd_x0);
+ upd_x0 = upd_y0 = -1U;
+ upd_x1 = upd_y1 = 0;
+ }
+}
+
+/* Mark a range for update; note argument sequence is the same as
+ vesacon_update_characters() */
+static inline void vesacon_touch(int row, int col, int rows, int cols)
+{
+ unsigned int y0 = row;
+ unsigned int x0 = col;
+ unsigned int y1 = y0 + rows;
+ unsigned int x1 = x0 + cols;
+
+ if (y0 < upd_y0)
+ upd_y0 = y0;
+ if (y1 > upd_y1)
+ upd_y1 = y1;
+ if (x0 < upd_x0)
+ upd_x0 = x0;
+ if (x1 > upd_x1)
+ upd_x1 = x1;
+}
+
+/* Erase a region of the screen */
+void __vesacon_erase(int x0, int y0, int x1, int y1, attr_t attr)
+{
+ int y;
+ struct vesa_char *ptr = &__vesacon_text_display
+ [(y0 + 1) * (__vesacon_text_cols + 2) + (x0 + 1)];
+ struct vesa_char fill = {
+ .ch = ' ',
+ .attr = attr,
+ };
+ int ncols = x1 - x0 + 1;
+
+ for (y = y0; y <= y1; y++) {
+ vesacon_fill(ptr, fill, ncols);
+ ptr += __vesacon_text_cols + 2;
+ }
+
+ vesacon_touch(y0, x0, y1 - y0 + 1, ncols);
+}
+
+/* Scroll the screen up */
+void __vesacon_scroll_up(int nrows, attr_t attr)
+{
+ struct vesa_char *fromptr = &__vesacon_text_display
+ [(nrows + 1) * (__vesacon_text_cols + 2)];
+ struct vesa_char *toptr = &__vesacon_text_display
+ [(__vesacon_text_cols + 2)];
+ int dword_count =
+ (__vesacon_text_rows - nrows) * (__vesacon_text_cols + 2);
+ struct vesa_char fill = {
+ .ch = ' ',
+ .attr = attr,
+ };
+
+ toptr = copy_dword(toptr, fromptr, dword_count);
+
+ dword_count = nrows * (__vesacon_text_cols + 2);
+
+ vesacon_fill(toptr, fill, dword_count);
+
+ vesacon_touch(0, 0, __vesacon_text_rows, __vesacon_text_cols);
+}
+
+/* Draw one character text at a specific area of the screen */
+void __vesacon_write_char(int x, int y, uint8_t ch, attr_t attr)
+{
+ struct vesa_char *ptr = &__vesacon_text_display
+ [(y + 1) * (__vesacon_text_cols + 2) + (x + 1)];
+
+ ptr->ch = ch;
+ ptr->attr = attr;
+
+ vesacon_touch(y, x, 1, 1);
+}
+
+void __vesacon_set_cursor(int x, int y, bool visible)
+{
+ struct vesa_char *ptr = &__vesacon_text_display
+ [(y + 1) * (__vesacon_text_cols + 2) + (x + 1)];
+
+ if (cursor_pointer)
+ vesacon_touch(cursor_y, cursor_x, 1, 1);
+
+ if (!visible) {
+ /* Invisible cursor */
+ cursor_pointer = NULL;
+ } else {
+ cursor_pointer = ptr;
+ vesacon_touch(y, x, 1, 1);
+ }
+
+ cursor_x = x;
+ cursor_y = y;
+}
+
+void __vesacon_init_cursor(int font_height)
+{
+ int r0 = font_height - (font_height < 10 ? 2 : 3);
+
+ if (r0 < 0)
+ r0 = 0;
+
+ memset(cursor_pattern, 0, font_height);
+ cursor_pattern[r0] = 0xff;
+ cursor_pattern[r0 + 1] = 0xff;
+}
+
+void __vesacon_redraw_text(void)
+{
+ vesacon_update_characters(0, 0, __vesacon_text_rows, __vesacon_text_cols);
+}
diff --git a/com32/lib/sys/vesa/efi/fill.h b/com32/lib/sys/vesa/efi/fill.h
new file mode 100644
index 00000000..5a43c728
--- /dev/null
+++ b/com32/lib/sys/vesa/efi/fill.h
@@ -0,0 +1,63 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2006-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef LIB_SYS_VESA_FILL_H
+#define LIB_SYS_VESA_FILL_H
+
+#include "video.h"
+
+/* Fill a number of characters. */
+static inline struct vesa_char *vesacon_fill(struct vesa_char *ptr,
+ struct vesa_char fill,
+ unsigned int count)
+{
+ switch (sizeof(struct vesa_char)) {
+ case 1:
+ asm volatile ("rep; stosb":"+D" (ptr), "+c"(count)
+ :"a"(fill)
+ :"memory");
+ break;
+ case 2:
+ asm volatile ("rep; stosw":"+D" (ptr), "+c"(count)
+ :"a"(fill)
+ :"memory");
+ break;
+ case 4:
+ asm volatile ("rep; stosl":"+D" (ptr), "+c"(count)
+ :"a"(fill)
+ :"memory");
+ break;
+ default:
+ while (count--)
+ *ptr++ = fill;
+ break;
+ }
+
+ return ptr;
+}
+
+#endif /* LIB_SYS_VESA_FILL_H */
diff --git a/com32/lib/sys/vesa/efi/fmtpixel.c b/com32/lib/sys/vesa/efi/fmtpixel.c
new file mode 100644
index 00000000..381fc216
--- /dev/null
+++ b/com32/lib/sys/vesa/efi/fmtpixel.c
@@ -0,0 +1,101 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2006-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * fmtpixel.c
+ *
+ * Functions to format a single pixel
+ */
+
+#include <inttypes.h>
+#include "video.h"
+
+/*
+ * Format a sequence of pixels. The first argument is the line buffer;
+ * we can use it to write up to 4 bytes past the end of the last pixel.
+ * Return the place we should be copying from, this is usually the
+ * buffer address, but doesn't *have* to be.
+ */
+
+static const void *format_pxf_bgra32(void *ptr, const uint32_t * p, size_t n)
+{
+ (void)ptr;
+ (void)n;
+ return p; /* No conversion needed! */
+}
+
+static const void *format_pxf_bgr24(void *ptr, const uint32_t * p, size_t n)
+{
+ char *q = ptr;
+
+ while (n--) {
+ *(uint32_t *) q = *p++;
+ q += 3;
+ }
+ return ptr;
+}
+
+static const void *format_pxf_le_rgb16_565(void *ptr, const uint32_t * p,
+ size_t n)
+{
+ uint32_t bgra;
+ uint16_t *q = ptr;
+
+ while (n--) {
+ bgra = *p++;
+ *q++ =
+ ((bgra >> 3) & 0x1f) +
+ ((bgra >> (2 + 8 - 5)) & (0x3f << 5)) +
+ ((bgra >> (3 + 16 - 11)) & (0x1f << 11));
+ }
+ return ptr;
+}
+
+static const void *format_pxf_le_rgb15_555(void *ptr, const uint32_t * p,
+ size_t n)
+{
+ uint32_t bgra;
+ uint16_t *q = ptr;
+
+ while (n--) {
+ bgra = *p++;
+ *q++ =
+ ((bgra >> 3) & 0x1f) +
+ ((bgra >> (2 + 8 - 5)) & (0x1f << 5)) +
+ ((bgra >> (3 + 16 - 10)) & (0x1f << 10));
+ }
+ return ptr;
+}
+
+__vesacon_format_pixels_t __vesacon_format_pixels;
+
+const __vesacon_format_pixels_t __vesacon_format_pixels_list[PXF_NONE] = {
+ [PXF_BGRA32] = format_pxf_bgra32,
+ [PXF_BGR24] = format_pxf_bgr24,
+ [PXF_LE_RGB16_565] = format_pxf_le_rgb16_565,
+ [PXF_LE_RGB15_555] = format_pxf_le_rgb15_555,
+};
diff --git a/com32/lib/sys/vesa/efi/i915resolution.c b/com32/lib/sys/vesa/efi/i915resolution.c
new file mode 100644
index 00000000..6ebb04d3
--- /dev/null
+++ b/com32/lib/sys/vesa/efi/i915resolution.c
@@ -0,0 +1,795 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2010 Intel Corporation; author: H. Peter Anvin
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Based on:
+ *
+ * 915 resolution by steve tomljenovic
+ *
+ * This was tested only on Sony VGN-FS550. Use at your own risk
+ *
+ * This code is based on the techniques used in :
+ *
+ * - 855patch. Many thanks to Christian Zietz (czietz gmx net)
+ * for demonstrating how to shadow the VBIOS into system RAM
+ * and then modify it.
+ *
+ * - 1280patch by Andrew Tipton (andrewtipton null li).
+ *
+ * - 855resolution by Alain Poirier
+ *
+ * This source code is into the public domain.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#define __USE_GNU
+#include <string.h>
+#include <sys/io.h>
+#include <sys/cpu.h>
+#include <sys/pci.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdbool.h>
+#include "video.h"
+#include "debug.h"
+
+#define VBIOS_START 0xc0000
+#define VBIOS_SIZE 0x10000
+
+#define MODE_TABLE_OFFSET_845G 617
+
+#define VERSION "0.5.3"
+
+#define ATI_SIGNATURE1 "ATI MOBILITY RADEON"
+#define ATI_SIGNATURE2 "ATI Technologies Inc"
+#define NVIDIA_SIGNATURE "NVIDIA Corp"
+#define INTEL_SIGNATURE "Intel Corp"
+
+typedef unsigned char * address;
+
+typedef enum {
+ CT_UNKWN, CT_830, CT_845G, CT_855GM, CT_865G, CT_915G, CT_915GM,
+ CT_945G, CT_945GM, CT_946GZ, CT_G965, CT_Q965, CT_945GME,
+ CHIPSET_TYPES
+} chipset_type;
+
+typedef enum {
+ BT_UNKWN, BT_1, BT_2, BT_3
+} bios_type;
+
+static int freqs[] = { 60, 75, 85 };
+
+typedef struct {
+ uint8_t mode;
+ uint8_t bits_per_pixel;
+ uint16_t resolution;
+ uint8_t unknown;
+} __attribute__((packed)) vbios_mode;
+
+typedef struct {
+ uint16_t clock; /* Clock frequency in 10 kHz */
+ uint8_t x1;
+ uint8_t x_total;
+ uint8_t x2;
+ uint8_t y1;
+ uint8_t y_total;
+ uint8_t y2;
+} __attribute__((packed)) vbios_resolution_type1;
+
+typedef struct {
+ uint32_t clock;
+
+ uint16_t x1;
+ uint16_t htotal;
+ uint16_t x2;
+ uint16_t hblank;
+ uint16_t hsyncstart;
+ uint16_t hsyncend;
+
+ uint16_t y1;
+ uint16_t vtotal;
+ uint16_t y2;
+ uint16_t vblank;
+ uint16_t vsyncstart;
+ uint16_t vsyncend;
+} __attribute__((packed)) vbios_modeline_type2;
+
+typedef struct {
+ uint8_t xchars;
+ uint8_t ychars;
+ uint8_t unknown[4];
+
+ vbios_modeline_type2 modelines[];
+} __attribute__((packed)) vbios_resolution_type2;
+
+typedef struct {
+ uint32_t clock;
+
+ uint16_t x1;
+ uint16_t htotal;
+ uint16_t x2;
+ uint16_t hblank;
+ uint16_t hsyncstart;
+ uint16_t hsyncend;
+
+ uint16_t y1;
+ uint16_t vtotal;
+ uint16_t y2;
+ uint16_t vblank;
+ uint16_t vsyncstart;
+ uint16_t vsyncend;
+
+ uint16_t timing_h;
+ uint16_t timing_v;
+
+ uint8_t unknown[6];
+} __attribute__((packed)) vbios_modeline_type3;
+
+typedef struct {
+ unsigned char unknown[6];
+
+ vbios_modeline_type3 modelines[];
+} __attribute__((packed)) vbios_resolution_type3;
+
+
+typedef struct {
+ unsigned int chipset_id;
+ chipset_type chipset;
+ bios_type bios;
+
+ address bios_ptr;
+
+ vbios_mode * mode_table;
+ unsigned int mode_table_size;
+
+ uint8_t b1, b2;
+
+ bool unlocked;
+} vbios_map;
+
+#if 0 /* Debugging hacks */
+static void good_marker(int x)
+{
+ ((uint16_t *)0xb8000)[x] = 0x2f30 - ((x & 0xf0) << 4) + (x & 0x0f);
+}
+
+static void bad_marker(int x)
+{
+ ((uint16_t *)0xb8000)[x] = 0x4f30 - ((x & 0xf0) << 4) + (x & 0x0f);
+}
+
+static void status(const char *fmt, ...)
+{
+ va_list ap;
+ char msg[81], *p;
+ int i;
+ uint16_t *q;
+
+ memset(msg, 0, sizeof msg);
+ va_start(ap, fmt);
+ vsnprintf(msg, sizeof msg, fmt, ap);
+ va_end(ap);
+ p = msg;
+ q = (uint16_t *)0xb8000 + 80;
+ for (i = 0; i < 80; i++)
+ *q++ = *p++ + 0x1f00;
+}
+#else
+static inline void good_marker(int x) { (void)x; }
+static inline void bad_marker(int x) { (void)x; }
+static inline void status(const char *fmt, ...) { (void)fmt; }
+#endif
+
+static unsigned int get_chipset_id(void) {
+ return pci_readl(0x80000000);
+}
+
+static chipset_type get_chipset(unsigned int id) {
+ chipset_type type;
+
+ switch (id) {
+ case 0x35758086:
+ type = CT_830;
+ break;
+
+ case 0x25608086:
+ type = CT_845G;
+ break;
+
+ case 0x35808086:
+ type = CT_855GM;
+ break;
+
+ case 0x25708086:
+ type = CT_865G;
+ break;
+
+ case 0x25808086:
+ type = CT_915G;
+ break;
+
+ case 0x25908086:
+ type = CT_915GM;
+ break;
+
+ case 0x27708086:
+ type = CT_945G;
+ break;
+
+ case 0x27a08086:
+ type = CT_945GM;
+ break;
+
+ case 0x29708086:
+ type = CT_946GZ;
+ break;
+
+ case 0x29a08086:
+ type = CT_G965;
+ break;
+
+ case 0x29908086:
+ type = CT_Q965;
+ break;
+
+ case 0x27ac8086:
+ type = CT_945GME;
+ break;
+
+ default:
+ type = CT_UNKWN;
+ break;
+ }
+
+ return type;
+}
+
+
+static vbios_resolution_type1 * map_type1_resolution(vbios_map * map,
+ uint16_t res)
+{
+ vbios_resolution_type1 * ptr = ((vbios_resolution_type1*)(map->bios_ptr + res));
+ return ptr;
+}
+
+static vbios_resolution_type2 * map_type2_resolution(vbios_map * map,
+ uint16_t res)
+{
+ vbios_resolution_type2 * ptr = ((vbios_resolution_type2*)(map->bios_ptr + res));
+ return ptr;
+}
+
+static vbios_resolution_type3 * map_type3_resolution(vbios_map * map,
+ uint16_t res)
+{
+ vbios_resolution_type3 * ptr = ((vbios_resolution_type3*)(map->bios_ptr + res));
+ return ptr;
+}
+
+
+static bool detect_bios_type(vbios_map * map, int entry_size)
+{
+ unsigned int i;
+ uint16_t r1, r2;
+
+ r1 = r2 = 32000;
+
+ for (i = 0; i < map->mode_table_size; i++) {
+ if (map->mode_table[i].resolution <= r1) {
+ r1 = map->mode_table[i].resolution;
+ } else if (map->mode_table[i].resolution <= r2) {
+ r2 = map->mode_table[i].resolution;
+ }
+ }
+
+ return ((r2-r1-6) % entry_size) == 0;
+}
+
+static inline void close_vbios(vbios_map *map)
+{
+ (void)map;
+}
+
+static vbios_map * open_vbios(void)
+{
+ static vbios_map _map;
+ vbios_map * const map = &_map;
+
+ memset(&_map, 0, sizeof _map);
+
+ /*
+ * Determine chipset
+ */
+ map->chipset_id = get_chipset_id();
+ good_marker(0x10);
+ map->chipset = get_chipset(map->chipset_id);
+ good_marker(0x11);
+
+ /*
+ * Map the video bios to memory
+ */
+ map->bios_ptr = (void *)VBIOS_START;
+
+ /*
+ * check if we have ATI Radeon
+ */
+
+ if (memmem(map->bios_ptr, VBIOS_SIZE, ATI_SIGNATURE1, strlen(ATI_SIGNATURE1)) ||
+ memmem(map->bios_ptr, VBIOS_SIZE, ATI_SIGNATURE2, strlen(ATI_SIGNATURE2)) ) {
+ debug("ATI chipset detected. 915resolution only works with Intel 800/900 series graphic chipsets.\r\n");
+ return NULL;
+ }
+
+ /*
+ * check if we have NVIDIA
+ */
+
+ if (memmem(map->bios_ptr, VBIOS_SIZE, NVIDIA_SIGNATURE, strlen(NVIDIA_SIGNATURE))) {
+ debug("NVIDIA chipset detected. 915resolution only works with Intel 800/900 series graphic chipsets.\r\n");
+ return NULL;
+ }
+
+ /*
+ * check if we have Intel
+ */
+
+ if (map->chipset == CT_UNKWN && memmem(map->bios_ptr, VBIOS_SIZE, INTEL_SIGNATURE, strlen(INTEL_SIGNATURE))) {
+ debug("Intel chipset detected. However, 915resolution was unable to determine the chipset type.\r\n");
+
+ debug("Chipset Id: %x\r\n", map->chipset_id);
+
+ debug("Please report this problem to stomljen@yahoo.com\r\n");
+
+ close_vbios(map);
+ return NULL;
+ }
+
+ /*
+ * check for others
+ */
+
+ if (map->chipset == CT_UNKWN) {
+ debug("Unknown chipset type and unrecognized bios.\r\n");
+ debug("915resolution only works with Intel 800/900 series graphic chipsets.\r\n");
+
+ debug("Chipset Id: %x\r\n", map->chipset_id);
+ close_vbios(map);
+ return NULL;
+ }
+
+ /*
+ * Figure out where the mode table is
+ */
+ good_marker(0x12);
+
+ {
+ address p = map->bios_ptr + 16;
+ address limit = map->bios_ptr + VBIOS_SIZE - (3 * sizeof(vbios_mode));
+
+ while (p < limit && map->mode_table == 0) {
+ vbios_mode * mode_ptr = (vbios_mode *) p;
+
+ if (((mode_ptr[0].mode & 0xf0) == 0x30) && ((mode_ptr[1].mode & 0xf0) == 0x30) &&
+ ((mode_ptr[2].mode & 0xf0) == 0x30) && ((mode_ptr[3].mode & 0xf0) == 0x30)) {
+
+ map->mode_table = mode_ptr;
+ }
+
+ p++;
+ }
+
+ if (map->mode_table == 0) {
+ debug("Unable to locate the mode table.\r\n");
+ close_vbios(map);
+ return NULL;
+ }
+ }
+ good_marker(0x13);
+
+ /*
+ * Determine size of mode table
+ */
+
+ {
+ vbios_mode * mode_ptr = map->mode_table;
+
+ while (mode_ptr->mode != 0xff) {
+ map->mode_table_size++;
+ mode_ptr++;
+ }
+ }
+ good_marker(0x14);
+ status("mode_table_size = %d", map->mode_table_size);
+
+ /*
+ * Figure out what type of bios we have
+ * order of detection is important
+ */
+
+ if (detect_bios_type(map, sizeof(vbios_modeline_type3))) {
+ map->bios = BT_3;
+ }
+ else if (detect_bios_type(map, sizeof(vbios_modeline_type2))) {
+ map->bios = BT_2;
+ }
+ else if (detect_bios_type(map, sizeof(vbios_resolution_type1))) {
+ map->bios = BT_1;
+ }
+ else {
+ debug("Unable to determine bios type.\r\n");
+ debug("Mode Table Offset: $C0000 + $%x\r\n", ((unsigned int)map->mode_table) - ((unsigned int)map->bios_ptr));
+ debug("Mode Table Entries: %u\r\n", map->mode_table_size);
+ bad_marker(0x15);
+ return NULL;
+ }
+ good_marker(0x15);
+
+ return map;
+}
+
+static void unlock_vbios(vbios_map * map)
+{
+ assert(!map->unlocked);
+
+ map->unlocked = true;
+
+ switch (map->chipset) {
+ case CT_UNKWN:
+ case CHIPSET_TYPES: /* Shut up gcc */
+ break;
+ case CT_830:
+ case CT_855GM:
+ map->b1 = pci_readb(0x8000005a);
+ pci_writeb(0x33, 0x8000005a);
+ break;
+ case CT_845G:
+ case CT_865G:
+ case CT_915G:
+ case CT_915GM:
+ case CT_945G:
+ case CT_945GM:
+ case CT_945GME:
+ case CT_946GZ:
+ case CT_G965:
+ case CT_Q965:
+ map->b1 = pci_readb(0x80000091);
+ map->b2 = pci_readb(0x80000092);
+ pci_writeb(0x33, 0x80000091);
+ pci_writeb(0x33, 0x80000092);
+ break;
+ }
+
+#if DEBUG
+ {
+ unsigned int t = inl(0xcfc);
+ debug("unlock PAM: (0x%08x)\r\n", t);
+ }
+#endif
+}
+
+static void relock_vbios(vbios_map * map)
+{
+ assert(map->unlocked);
+ map->unlocked = false;
+
+ switch (map->chipset) {
+ case CT_UNKWN:
+ case CHIPSET_TYPES: /* Shut up gcc */
+ break;
+ case CT_830:
+ case CT_855GM:
+ pci_writeb(map->b1, 0x8000005a);
+ break;
+ case CT_845G:
+ case CT_865G:
+ case CT_915G:
+ case CT_915GM:
+ case CT_945G:
+ case CT_945GM:
+ case CT_945GME:
+ case CT_946GZ:
+ case CT_G965:
+ case CT_Q965:
+ pci_writeb(map->b1, 0x80000091);
+ pci_writeb(map->b2, 0x80000092);
+ break;
+ }
+
+#if DEBUG
+ {
+ unsigned int t = inl(0xcfc);
+ debug("relock PAM: (0x%08x)\r\n", t);
+ }
+#endif
+}
+
+#if 0
+static void list_modes(vbios_map *map, unsigned int raw)
+{
+ unsigned int i, x, y;
+
+ for (i=0; i < map->mode_table_size; i++) {
+ switch(map->bios) {
+ case BT_1:
+ {
+ vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);
+
+ x = ((((unsigned int) res->x2) & 0xf0) << 4) | res->x1;
+ y = ((((unsigned int) res->y2) & 0xf0) << 4) | res->y1;
+
+ if (x != 0 && y != 0) {
+ debug("Mode %02x : %dx%d, %d bits/pixel\r\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
+ }
+
+ if (raw)
+ {
+ debug("Mode %02x (raw) :\r\n\t%02x %02x\r\n\t%02x\r\n\t%02x\r\n\t%02x\r\n\t%02x\r\n\t%02x\r\n\t%02x\r\n", map->mode_table[i].mode, res->unknow1[0],res->unknow1[1], res->x1,res->x_total,res->x2,res->y1,res->y_total,res->y2);
+ }
+
+ }
+ break;
+ case BT_2:
+ {
+ vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);
+
+ x = res->modelines[0].x1+1;
+ y = res->modelines[0].y1+1;
+
+ if (x != 0 && y != 0) {
+ debug("Mode %02x : %dx%d, %d bits/pixel\r\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
+ }
+ }
+ break;
+ case BT_3:
+ {
+ vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);
+
+ x = res->modelines[0].x1+1;
+ y = res->modelines[0].y1+1;
+
+ if (x != 0 && y != 0) {
+ debug("Mode %02x : %dx%d, %d bits/pixel\r\n", map->mode_table[i].mode, x, y, map->mode_table[i].bits_per_pixel);
+ }
+ }
+ break;
+ case BT_UNKWN:
+ break;
+ }
+ }
+}
+#endif
+
+static void gtf_timings(int x, int y, int freq, uint32_t *clock,
+ uint16_t *hsyncstart, uint16_t *hsyncend, uint16_t *hblank,
+ uint16_t *vsyncstart, uint16_t *vsyncend, uint16_t *vblank)
+{
+ int hbl, vbl, vfreq;
+
+ vbl = y + (y+1)/(20000.0/(11*freq) - 1) + 1.5;
+ vfreq = vbl * freq;
+ hbl = 16 * (int)(x * (30.0 - 300000.0 / vfreq) /
+ (70.0 + 300000.0 / vfreq) / 16.0 + 0.5);
+
+ *vsyncstart = y;
+ *vsyncend = y + 3;
+ *vblank = vbl - 1;
+ *hsyncstart = x + hbl / 2 - (x + hbl + 50) / 100 * 8 - 1;
+ *hsyncend = x + hbl / 2 - 1;
+ *hblank = x + hbl - 1;
+ *clock = (x + hbl) * vfreq / 1000;
+}
+
+static int set_mode(vbios_map * map, unsigned int mode,
+ unsigned int x, unsigned int y, unsigned int bp,
+ unsigned int htotal, unsigned int vtotal)
+{
+ int xprev, yprev;
+ unsigned int i, j;
+ int rv = -1;
+
+ for (i=0; i < map->mode_table_size; i++) {
+ if (map->mode_table[i].mode == mode) {
+ switch(map->bios) {
+ case BT_1:
+ {
+ vbios_resolution_type1 * res = map_type1_resolution(map, map->mode_table[i].resolution);
+ uint32_t clock;
+ uint16_t hsyncstart, hsyncend, hblank;
+ uint16_t vsyncstart, vsyncend, vblank;
+
+ if (bp) {
+ map->mode_table[i].bits_per_pixel = bp;
+ }
+
+ gtf_timings(x, y, freqs[0], &clock,
+ &hsyncstart, &hsyncend, &hblank,
+ &vsyncstart, &vsyncend, &vblank);
+
+ status("x = %d, y = %d, clock = %lu, h = %d %d %d, v = %d %d %d\n",
+ x, y, clock,
+ hsyncstart, hsyncend, hblank,
+ vsyncstart, vsyncend, vblank);
+
+ htotal = htotal ? htotal : (unsigned int)hblank+1;
+ vtotal = vtotal ? vtotal : (unsigned int)vblank+1;
+
+ res->clock = clock/10; /* Units appear to be 10 kHz */
+ res->x2 = (((htotal-x) >> 8) & 0x0f) | ((x >> 4) & 0xf0);
+ res->x1 = (x & 0xff);
+
+ res->y2 = (((vtotal-y) >> 8) & 0x0f) | ((y >> 4) & 0xf0);
+ res->y1 = (y & 0xff);
+ if (htotal)
+ res->x_total = ((htotal-x) & 0xff);
+
+ if (vtotal)
+ res->y_total = ((vtotal-y) & 0xff);
+
+ rv = 0;
+ }
+ break;
+ case BT_2:
+ {
+ vbios_resolution_type2 * res = map_type2_resolution(map, map->mode_table[i].resolution);
+
+ res->xchars = x / 8;
+ res->ychars = y / 16 - 1;
+ xprev = res->modelines[0].x1;
+ yprev = res->modelines[0].y1;
+
+ for(j=0; j < 3; j++) {
+ vbios_modeline_type2 * modeline = &res->modelines[j];
+
+ if (modeline->x1 == xprev && modeline->y1 == yprev) {
+ modeline->x1 = modeline->x2 = x-1;
+ modeline->y1 = modeline->y2 = y-1;
+
+ gtf_timings(x, y, freqs[j], &modeline->clock,
+ &modeline->hsyncstart, &modeline->hsyncend,
+ &modeline->hblank, &modeline->vsyncstart,
+ &modeline->vsyncend, &modeline->vblank);
+
+ if (htotal)
+ modeline->htotal = htotal;
+ else
+ modeline->htotal = modeline->hblank;
+
+ if (vtotal)
+ modeline->vtotal = vtotal;
+ else
+ modeline->vtotal = modeline->vblank;
+ }
+ }
+
+ rv = 0;
+ }
+ break;
+ case BT_3:
+ {
+ vbios_resolution_type3 * res = map_type3_resolution(map, map->mode_table[i].resolution);
+
+ xprev = res->modelines[0].x1;
+ yprev = res->modelines[0].y1;
+
+ for (j=0; j < 3; j++) {
+ vbios_modeline_type3 * modeline = &res->modelines[j];
+
+ if (modeline->x1 == xprev && modeline->y1 == yprev) {
+ modeline->x1 = modeline->x2 = x-1;
+ modeline->y1 = modeline->y2 = y-1;
+
+ gtf_timings(x, y, freqs[j], &modeline->clock,
+ &modeline->hsyncstart, &modeline->hsyncend,
+ &modeline->hblank, &modeline->vsyncstart,
+ &modeline->vsyncend, &modeline->vblank);
+ if (htotal)
+ modeline->htotal = htotal;
+ else
+ modeline->htotal = modeline->hblank;
+ if (vtotal)
+ modeline->vtotal = vtotal;
+ else
+ modeline->vtotal = modeline->vblank;
+
+ modeline->timing_h = y-1;
+ modeline->timing_v = x-1;
+ }
+ }
+
+ rv = 0;
+ }
+ break;
+ case BT_UNKWN:
+ break;
+ }
+ }
+ }
+
+ return rv;
+}
+
+static inline void display_map_info(vbios_map * map) {
+#ifdef DEBUG
+ static const char * bios_type_names[] =
+ {"UNKNOWN", "TYPE 1", "TYPE 2", "TYPE 3"};
+ static const char * chipset_type_names[] = {
+ "UNKNOWN", "830", "845G", "855GM", "865G", "915G", "915GM", "945G",
+ "945GM", "946GZ", "G965", "Q965", "945GME"
+ };
+
+ debug("Chipset: %s\r\n", chipset_type_names[map->chipset]);
+ debug("BIOS: %s\r\n", bios_type_names[map->bios]);
+
+ debug("Mode Table Offset: $C0000 + $%x\r\n",
+ ((unsigned int)map->mode_table) - ((unsigned int)map->bios_ptr));
+ debug("Mode Table Entries: %u\r\n", map->mode_table_size);
+#endif
+ (void)map;
+}
+
+int __vesacon_i915resolution(int x, int y)
+{
+ vbios_map * map;
+ unsigned int mode = 0x52; /* 800x600x32 mode in known BIOSes */
+ unsigned int bp = 32; /* 32 bits per pixel */
+ int rv = 0;
+
+ good_marker(0);
+
+ map = open_vbios();
+ if (!map)
+ return -1;
+
+ good_marker(1);
+
+ display_map_info(map);
+
+ debug("\r\n");
+
+ if (mode && x && y) {
+ good_marker(2);
+ cli();
+ good_marker(3);
+ unlock_vbios(map);
+ good_marker(4);
+ rv = set_mode(map, mode, x, y, bp, 0, 0);
+ if (rv)
+ bad_marker(5);
+ else
+ good_marker(5);
+ relock_vbios(map);
+ good_marker(6);
+ sti();
+
+ debug("Patch mode %02x to resolution %dx%d complete\r\n", mode, x, y);
+ }
+ close_vbios(map);
+
+ return rv;
+}
diff --git a/com32/lib/sys/vesa/efi/initvesa.c b/com32/lib/sys/vesa/efi/initvesa.c
new file mode 100644
index 00000000..9bb1f28d
--- /dev/null
+++ b/com32/lib/sys/vesa/efi/initvesa.c
@@ -0,0 +1,617 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1999-2012 H. Peter Anvin - All Rights Reserved
+ * Chandramouli Narayanan - extended for EFI support
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * initvesa.c
+ *
+ * Query the VESA BIOS and select a 640x480x32 mode with local mapping
+ * support, if one exists.
+ */
+
+#include <inttypes.h>
+#include <com32.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/fpu.h>
+#include <syslinux/video.h>
+#ifdef SYSLINUX_EFI
+#include <efi.h>
+#include <efilib.h>
+#include <efistdarg.h>
+/* We use cp865_8x16.psf as the standard font for EFI implementation
+ * the header file below contains raw data parsed from cp865_8x16.psf
+ */
+#include "cp865_8x16.h"
+#endif
+#include "vesa.h"
+#include "video.h"
+#include "fill.h"
+#include "debug.h"
+
+struct vesa_info __vesa_info;
+
+struct vesa_char *__vesacon_text_display;
+
+int __vesacon_font_height;
+int __vesacon_text_rows;
+int __vesacon_text_cols;
+enum vesa_pixel_format __vesacon_pixel_format = PXF_NONE;
+unsigned int __vesacon_bytes_per_pixel;
+uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT];
+
+uint32_t *__vesacon_background, *__vesacon_shadowfb;
+
+static void unpack_font(uint8_t * dst, uint8_t * src, int height)
+{
+ int i;
+
+ for (i = 0; i < FONT_MAX_CHARS; i++) {
+ memcpy(dst, src, height);
+ memset(dst + height, 0, FONT_MAX_HEIGHT - height);
+
+ dst += FONT_MAX_HEIGHT;
+ src += height;
+ }
+}
+
+static int __constfunc is_power_of_2(unsigned int x)
+{
+ return x && !(x & (x - 1));
+}
+
+static int vesacon_paged_mode_ok(const struct vesa_mode_info *mi)
+{
+ int i;
+
+ if (!is_power_of_2(mi->win_size) ||
+ !is_power_of_2(mi->win_grain) || mi->win_grain > mi->win_size)
+ return 0; /* Impossible... */
+
+ for (i = 0; i < 2; i++) {
+ if ((mi->win_attr[i] & 0x05) == 0x05 && mi->win_seg[i])
+ return 1; /* Usable window */
+ }
+
+ return 0; /* Nope... */
+}
+
+#ifndef SYSLINUX_EFI
+static int vesacon_set_mode(int x, int y)
+{
+ com32sys_t rm;
+ uint8_t *rom_font;
+ uint16_t mode, bestmode, *mode_ptr;
+ struct vesa_info *vi;
+ struct vesa_general_info *gi;
+ struct vesa_mode_info *mi;
+ enum vesa_pixel_format pxf, bestpxf;
+ int err = 0;
+
+ debug("Hello, World!\r\n");
+
+ /* Free any existing data structures */
+ if (__vesacon_background) {
+ free(__vesacon_background);
+ __vesacon_background = NULL;
+ }
+ if (__vesacon_shadowfb) {
+ free(__vesacon_shadowfb);
+ __vesacon_shadowfb = NULL;
+ }
+
+ /* Allocate space in the bounce buffer for these structures */
+ vi = lzalloc(sizeof *vi);
+ if (!vi) {
+ err = 10; /* Out of memory */
+ goto exit;
+ }
+ gi = &vi->gi;
+ mi = &vi->mi;
+
+ memset(&rm, 0, sizeof rm);
+
+ gi->signature = VBE2_MAGIC; /* Get VBE2 extended data */
+ rm.eax.w[0] = 0x4F00; /* Get SVGA general information */
+ rm.edi.w[0] = OFFS(gi);
+ rm.es = SEG(gi);
+ __intcall(0x10, &rm, &rm);
+
+ if (rm.eax.w[0] != 0x004F) {
+ err = 1; /* Function call failed */
+ goto exit;
+ }
+ if (gi->signature != VESA_MAGIC) {
+ err = 2; /* No magic */
+ goto exit;
+ }
+ if (gi->version < 0x0102) {
+ err = 3; /* VESA 1.2+ required */
+ goto exit;
+ }
+
+ /* Copy general info */
+ memcpy(&__vesa_info.gi, gi, sizeof *gi);
+
+ /* Search for the proper mode with a suitable color and memory model... */
+
+ mode_ptr = GET_PTR(gi->video_mode_ptr);
+ bestmode = 0;
+ bestpxf = PXF_NONE;
+
+ while ((mode = *mode_ptr++) != 0xFFFF) {
+ mode &= 0x1FF; /* The rest are attributes of sorts */
+
+ debug("Found mode: 0x%04x\r\n", mode);
+
+ memset(mi, 0, sizeof *mi);
+ rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */
+ rm.ecx.w[0] = mode;
+ rm.edi.w[0] = OFFS(mi);
+ rm.es = SEG(mi);
+ __intcall(0x10, &rm, &rm);
+
+ /* Must be a supported mode */
+ if (rm.eax.w[0] != 0x004f)
+ continue;
+
+ debug
+ ("mode_attr 0x%04x, h_res = %4d, v_res = %4d, bpp = %2d, layout = %d (%d,%d,%d)\r\n",
+ mi->mode_attr, mi->h_res, mi->v_res, mi->bpp, mi->memory_layout,
+ mi->rpos, mi->gpos, mi->bpos);
+
+ /* Must be an LFB color graphics mode supported by the hardware.
+
+ The bits tested are:
+ 4 - graphics mode
+ 3 - color mode
+ 1 - mode information available (mandatory in VBE 1.2+)
+ 0 - mode supported by hardware
+ */
+ if ((mi->mode_attr & 0x001b) != 0x001b)
+ continue;
+
+ /* Must be the chosen size */
+ if (mi->h_res != x || mi->v_res != y)
+ continue;
+
+ /* We don't support multibank (interlaced memory) modes */
+ /*
+ * Note: The Bochs VESA BIOS (vbe.c 1.58 2006/08/19) violates the
+ * specification which states that banks == 1 for unbanked modes;
+ * fortunately it does report bank_size == 0 for those.
+ */
+ if (mi->banks > 1 && mi->bank_size) {
+ debug("bad: banks = %d, banksize = %d, pages = %d\r\n",
+ mi->banks, mi->bank_size, mi->image_pages);
+ continue;
+ }
+
+ /* Must be either a flat-framebuffer mode, or be an acceptable
+ paged mode */
+ if (!(mi->mode_attr & 0x0080) && !vesacon_paged_mode_ok(mi)) {
+ debug("bad: invalid paged mode\r\n");
+ continue;
+ }
+
+ /* Must either be a packed-pixel mode or a direct color mode
+ (depending on VESA version ); must be a supported pixel format */
+ pxf = PXF_NONE; /* Not usable */
+
+ if (mi->bpp == 32 &&
+ (mi->memory_layout == 4 ||
+ (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 &&
+ mi->bpos == 0)))
+ pxf = PXF_BGRA32;
+ else if (mi->bpp == 24 &&
+ (mi->memory_layout == 4 ||
+ (mi->memory_layout == 6 && mi->rpos == 16 && mi->gpos == 8 &&
+ mi->bpos == 0)))
+ pxf = PXF_BGR24;
+ else if (mi->bpp == 16 &&
+ (mi->memory_layout == 4 ||
+ (mi->memory_layout == 6 && mi->rpos == 11 && mi->gpos == 5 &&
+ mi->bpos == 0)))
+ pxf = PXF_LE_RGB16_565;
+ else if (mi->bpp == 15 &&
+ (mi->memory_layout == 4 ||
+ (mi->memory_layout == 6 && mi->rpos == 10 && mi->gpos == 5 &&
+ mi->bpos == 0)))
+ pxf = PXF_LE_RGB15_555;
+
+ if (pxf < bestpxf) {
+ debug("Best mode so far, pxf = %d\r\n", pxf);
+
+ /* Best mode so far... */
+ bestmode = mode;
+ bestpxf = pxf;
+
+ /* Copy mode info */
+ memcpy(&__vesa_info.mi, mi, sizeof *mi);
+ }
+ }
+
+ if (bestpxf == PXF_NONE) {
+ err = 4; /* No mode found */
+ goto exit;
+ }
+
+ mi = &__vesa_info.mi;
+ mode = bestmode;
+ __vesacon_bytes_per_pixel = (mi->bpp + 7) >> 3;
+ __vesacon_format_pixels = __vesacon_format_pixels_list[bestpxf];
+
+ /* Download the SYSLINUX- or BIOS-provided font */
+ __vesacon_font_height = syslinux_font_query(&rom_font);
+ if (!__vesacon_font_height) {
+ /* Get BIOS 8x16 font */
+
+ rm.eax.w[0] = 0x1130; /* Get Font Information */
+ rm.ebx.w[0] = 0x0600; /* Get 8x16 ROM font */
+ __intcall(0x10, &rm, &rm);
+ rom_font = MK_PTR(rm.es, rm.ebp.w[0]);
+ __vesacon_font_height = 16;
+ }
+ unpack_font((uint8_t *) __vesacon_graphics_font, rom_font,
+ __vesacon_font_height);
+
+ /* Now set video mode */
+ rm.eax.w[0] = 0x4F02; /* Set SVGA video mode */
+ if (mi->mode_attr & 0x0080)
+ mode |= 0x4000; /* Request linear framebuffer if supported */
+ rm.ebx.w[0] = mode;
+ __intcall(0x10, &rm, &rm);
+ if (rm.eax.w[0] != 0x004F) {
+ err = 9; /* Failed to set mode */
+ goto exit;
+ }
+
+ __vesacon_background = calloc(mi->h_res*mi->v_res, 4);
+ __vesacon_shadowfb = calloc(mi->h_res*mi->v_res, 4);
+
+ __vesacon_init_copy_to_screen();
+
+ /* Tell syslinux we changed video mode */
+ /* In theory this should be:
+
+ flags = (mi->mode_attr & 4) ? 0x0007 : 0x000f;
+
+ However, that would assume all systems that claim to handle text
+ output in VESA modes actually do that... */
+ syslinux_report_video_mode(0x000f, mi->h_res, mi->v_res);
+
+ __vesacon_pixel_format = bestpxf;
+
+exit:
+ if (vi)
+ lfree(vi);
+
+ return err;
+}
+
+#else
+/* EFI GOP support
+ * Note GOP support uses the VESA info structure as much as possible and
+ * extends it as needed for EFI support. Not all of the vesa info structure
+ * is populated. Care must be taken in the routines that rely the vesa
+ * informataion structure
+ */
+static void find_pixmask_bits(uint32_t mask, uint8_t *first_bit, uint8_t *len) {
+ uint8_t bit_pos = 0, bit_len = 0;
+
+ *first_bit = 0;
+ *len = 0;
+ if (mask == 0)
+ return;
+ while (!(mask & 0x1)) {
+ mask = mask >> 1;
+ bit_pos++;
+ }
+ while (mask & 0x1) {
+ mask = mask >> 1;
+ bit_len++;
+ }
+ *first_bit = bit_pos;
+ *len = bit_len;
+}
+static int vesacon_set_mode(int x, int y)
+{
+ EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput = NULL;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *gop_mode;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info;
+ EFI_STATUS st;
+ UINT32 mode_num = 0, bestmode;
+ BOOLEAN mode_match = FALSE;
+ UINTN sz_info;
+ struct vesa_info *vi;
+ struct vesa_general_info *gi;
+ struct vesa_mode_info *mi;
+ enum vesa_pixel_format pxf, bestpxf = PXF_NONE;
+ int err = 0;
+
+ //debug("Hello, World!\r\n");
+ printf("Hello, world, entering EFI graphics mode set operation (x=%d, y=%d)\n", x,y);//debug
+ /* At this point, we assume that gnu-efi library is initialized */
+ st = LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
+ if (EFI_ERROR(st)) {
+ debug("LiblocateProtocol for GOP failed %d\n", st);
+ return 1; /* function call failed */
+ }
+
+ /* We use the VESA info structure to store relevant GOP info as much as possible */
+ gop_mode = GraphicsOutput->Mode;
+
+ /* simply pick the best mode that suits the caller's resolution */
+ for (mode_num = 0; mode_num < gop_mode->MaxMode; mode_num++) {
+ st = uefi_call_wrapper(GraphicsOutput->QueryMode, 4, GraphicsOutput, mode_num, &sz_info, &mode_info);
+ debug("mode_num = %d query_status %d\n", mode_num, st);
+ if (st == EFI_SUCCESS && sz_info >= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)) {
+ /*
+ Print(L"mode %d ver %d (Hres=%d, Vres=%d) PixlFmt %d ",
+ mode_num,
+ info->Version, info->HorizontalResolution,
+ info->VerticalResolution,
+ info->PixelFormat);
+ if (info->PixelFormat == PixelBitMask)
+ Print(L"PixelBitMask RMask 0x%x GMask 0x%x BMask 0x%x ",
+ info->PixelInformation.RedMask,
+ info->PixelInformation.GreenMask,
+ info->PixelInformation.BlueMask);
+ Print(L"ScanPerLine %d\n", info->PixelsPerScanLine);
+ */
+
+ /* For now, simply pick the best mode that suits caller's resolution (x,y)
+ * FIXME: Consider any additional criteria for matching mode
+ */
+ mode_match = ((uint32_t)x == mode_info->HorizontalResolution && (uint32_t)y == mode_info->VerticalResolution);
+ debug("mode %d hres=%d vres=%d\n", mode_num, mode_info->HorizontalResolution, mode_info->VerticalResolution);
+ if (mode_match) {
+ bestmode = mode_num;
+ break;
+ }
+ }
+ }
+
+ if (!mode_match) {
+ debug("No matching mode available for resolution (x=%d, y=%d)\n", x, y);
+ return 4; /* no mode found */
+ }
+
+ /* Allocate space in the bounce buffer for these structures */
+ vi = lzalloc(sizeof *vi);
+ if (!vi) {
+ err = 10; /* Out of memory */
+ goto exit;
+ }
+ /* Note that the generic info is untouched as we don't find any relevance to EFI */
+ gi = &vi->gi;
+ mi = &vi->mi;
+ /* Set up mode-specific information */
+ mi->h_res = x;
+ mi->v_res = y;
+ mi->lfb_ptr = (uint8_t *)(VOID *)(UINTN)gop_mode->FrameBufferBase;
+ mi->lfb_size = gop_mode->FrameBufferSize;
+
+ /* FIXME:
+ * The code below treats bpp == lfb_depth ; verify
+ */
+
+ switch (mode_info->PixelFormat) {
+ case PixelRedGreenBlueReserved8BitPerColor:
+ mi->mode_attr = 0x0080; /* supports physical frame buffer */
+ mi->bpp = sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * 8;
+ mi->rpos = 0;
+ mi->gpos = 8;
+ mi->bpos = 16;
+ mi->resv_pos = 24;
+ mi->resv_size = 8;
+ mi->logical_scan = mi->lfb_line_size = (mode_info->PixelsPerScanLine * mi->bpp) / 8;
+ bestpxf = PXF_BGRA32;
+ break;
+ case PixelBlueGreenRedReserved8BitPerColor:
+ mi->mode_attr = 0x0080; /* supports physical frame buffer */
+ mi->bpp = sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * 8;
+ mi->bpos = 0;
+ mi->gpos = 8;
+ mi->rpos = 16;
+ mi->resv_pos = 24;
+ mi->resv_size = 8;
+ mi->logical_scan = mi->lfb_line_size = (mode_info->PixelsPerScanLine * mi->bpp) / 8;
+ bestpxf = PXF_BGRA32;
+ break;
+ case PixelBitMask:
+ mi->mode_attr = 0x0080; /* supports physical frame buffer */
+ find_pixmask_bits(mode_info->PixelInformation.RedMask,
+ &mi->rpos, &mi->lfb_rsize);
+ find_pixmask_bits(mode_info->PixelInformation.GreenMask,
+ &mi->gpos, &mi->lfb_gsize);
+ find_pixmask_bits(mode_info->PixelInformation.BlueMask,
+ &mi->bpos, &mi->lfb_bsize);
+ find_pixmask_bits(mode_info->PixelInformation.ReservedMask,
+ &mi->resv_pos, &mi->resv_size);
+ mi->bpp = mi->lfb_rsize + mi->lfb_gsize +
+ mi->lfb_bsize + mi->lfb_resv_size;
+ mi->logical_scan = mi->lfb_line_size = (mode_info->PixelsPerScanLine * mi->bpp) / 8;
+ bestpxf = PXF_BGRA32; /* FIXME: correct? */
+ break;
+ case PixelBltOnly:
+ /* FIXME: unsupported */
+ mi->mode_attr = 0x0000; /* no support for physical frame buffer */
+ err = 4; /* no mode found */
+ goto exit;
+ break;
+ default:
+ /* should not get here, but let's error out */
+ err = 4; /* no mode found */
+ goto exit;
+ break;
+ }
+
+ memcpy(&__vesa_info.mi, mi, sizeof *mi);
+ mi = &__vesa_info.mi;
+ /* set up font info
+ * For now, font info is stored as raw data and used
+ * as such. Altenatively, the font data stored in a file
+ * could be read and parsed. (note: for this, EFI
+ * file support should be exposed via firmware structure)
+ */
+ __vesacon_font_height = cp865_8x16_font_height;
+ unpack_font((uint8_t *) __vesacon_graphics_font, cp865_8x16_font_data,
+ __vesacon_font_height);
+
+ /* Free any existing data structures */
+ if (__vesacon_background) {
+ free(__vesacon_background);
+ __vesacon_background = NULL;
+ }
+ if (__vesacon_shadowfb) {
+ free(__vesacon_shadowfb);
+ __vesacon_shadowfb = NULL;
+ }
+
+ __vesacon_bytes_per_pixel = (mi->bpp + 7) >> 3;
+ __vesacon_format_pixels = __vesacon_format_pixels_list[bestpxf];
+
+ /* Now set video mode */
+ st = uefi_call_wrapper(GraphicsOutput->SetMode, 2, GraphicsOutput, bestmode);
+ if (EFI_ERROR(st)) {
+ err = 9; /* Failed to set mode */
+ goto exit;
+ }
+
+ /* TODO: Follow the code usage of vesacon_background & vesacon_shadowfb */
+ /*
+ __vesacon_background = calloc(mi->h_res*mi->v_res, 4);
+ __vesacon_shadowfb = calloc(mi->h_res*mi->v_res, 4);
+ */
+ /* FIXME: the allocation takes the possible padding into account
+ * whereas BIOS code simply allocates hres * vres bytes.
+ * Which is correct?
+ */
+ /*
+ * For performance reasons, or due to hardware restrictions, scan lines
+ * may be padded to an amount of memory alignment. These padding pixel elements
+ * are outside the area covered by HorizontalResolution and are not visible.
+ * For direct frame buffer access, this number is used as a span between starts
+ * of pixel lines in video memory. Based on the size of an individual pixel element
+ * and PixelsPerScanline, the offset in video memory from pixel element (x, y)
+ * to pixel element (x, y+1) has to be calculated as
+ * "sizeof( PixelElement ) * PixelsPerScanLine", and not
+ * "sizeof( PixelElement ) * HorizontalResolution", though in many cases
+ * those values can coincide.
+ */
+
+ __vesacon_background = calloc(mi->lfb_line_size*mi->v_res, 4);
+ __vesacon_shadowfb = calloc(mi->lfb_line_size*mi->v_res, 4);
+
+ __vesacon_init_copy_to_screen();
+
+ /* Tell syslinux we changed video mode
+ * FIXME: The following call is BIOS-centric. I don't see an EFI-equivalent
+ * syslinux_report_video_mode(0x000f, mi->h_res, mi->v_res);
+ */
+
+ __vesacon_pixel_format = bestpxf;
+
+exit:
+ if (vi)
+ lfree(vi);
+
+ return err;
+}
+#endif /* SYSLINUX_EFI */
+
+/* FIXME:
+ * Does init_text_display need an EFI counterpart?
+ * e.g. vesa_char may need to setup UNICODE char for EFI
+ * and the number of screen chars may need to be sized up
+ * accordingly. This may also require turning byte strings
+ * into unicode strings in the framebuffer
+ * Possibly, revisit vesacon_fill() for EFI.
+ */
+
+static int init_text_display(void)
+{
+ size_t nchars;
+ struct vesa_char *ptr;
+ struct vesa_char def_char = {
+ .ch = ' ',
+ .attr = 0,
+ };
+
+ if (__vesacon_text_display)
+ free(__vesacon_text_display);
+
+ __vesacon_text_cols = TEXT_PIXEL_COLS / FONT_WIDTH;
+ __vesacon_text_rows = TEXT_PIXEL_ROWS / __vesacon_font_height;
+ nchars = (__vesacon_text_cols+2) * (__vesacon_text_rows+2);
+
+ __vesacon_text_display = ptr = malloc(nchars * sizeof(struct vesa_char));
+
+ if (!ptr)
+ return -1;
+
+ vesacon_fill(ptr, def_char, nchars);
+ __vesacon_init_cursor(__vesacon_font_height);
+
+ return 0;
+}
+
+int __vesacon_init(int x, int y)
+{
+ int rv;
+
+ /* We need the FPU for graphics, at least libpng et al will need it... */
+printf("vesacon_init: enter\n");
+ if (x86_init_fpu())
+ return 10;
+
+printf("vesacon_init: set mode\n");
+ rv = vesacon_set_mode(x, y);
+ /* FIXME: Accessing Video BIOS from EFI will probably not work */
+#ifndef SYSLINUX_EFI
+ if (rv) {
+ /* Try to see if we can just patch the BIOS... */
+ if (__vesacon_i915resolution(x, y))
+ return rv;
+ if (vesacon_set_mode(x, y))
+ return rv;
+ }
+#else
+ /* FIXME: Accessing Video BIOS from EFI will probably not work, skip it for now */
+#endif
+
+ init_text_display();
+
+ debug("Mode set, now drawing at %#p\r\n", __vesa_info.mi.lfb_ptr);
+
+ __vesacon_init_background();
+
+ debug("Ready!\r\n");
+ return 0;
+}
diff --git a/com32/lib/sys/vesa/efi/screencpy.c b/com32/lib/sys/vesa/efi/screencpy.c
new file mode 100644
index 00000000..345cdf44
--- /dev/null
+++ b/com32/lib/sys/vesa/efi/screencpy.c
@@ -0,0 +1,169 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <inttypes.h>
+#include <minmax.h>
+#include <klibc/compiler.h>
+#include <string.h>
+#include <com32.h>
+#include <ilog2.h>
+#include "vesa.h"
+#include "video.h"
+
+static struct win_info {
+ char *win_base;
+ size_t win_pos;
+ size_t win_size;
+ int win_gshift;
+ int win_num;
+} wi;
+
+#ifndef SYSLINUX_EFI
+void __vesacon_init_copy_to_screen(void)
+{
+ struct vesa_mode_info *const mi = &__vesa_info.mi;
+ int winn;
+
+ if (mi->mode_attr & 0x0080) {
+ /* Linear frame buffer */
+
+ wi.win_base = (char *)mi->lfb_ptr;
+ wi.win_size = 1 << 31; /* 2 GB, i.e. one huge window */
+ wi.win_pos = 0; /* Already positioned (only one position...) */
+ wi.win_num = -1; /* Not a window */
+ } else {
+ /* Paged frame buffer */
+
+ /* We have already tested that *one* of these is usable */
+ if ((mi->win_attr[0] & 0x05) == 0x05 && mi->win_seg[0])
+ winn = 0;
+ else
+ winn = 1;
+
+ wi.win_num = winn;
+ wi.win_base = (char *)(mi->win_seg[winn] << 4);
+ wi.win_size = mi->win_size << 10;
+ wi.win_gshift = ilog2(mi->win_grain) + 10;
+ wi.win_pos = -1; /* Undefined position */
+ }
+}
+
+static void set_window_pos(size_t win_pos)
+{
+ static com32sys_t ireg;
+
+ wi.win_pos = win_pos;
+
+ if (wi.win_num < 0)
+ return; /* This should never happen... */
+
+ ireg.eax.w[0] = 0x4F05;
+ ireg.ebx.b[0] = wi.win_num;
+ ireg.edx.w[0] = win_pos >> wi.win_gshift;
+
+ __intcall(0x10, &ireg, NULL);
+}
+
+void __vesacon_copy_to_screen(size_t dst, const uint32_t * src, size_t npixels)
+{
+ size_t win_pos, win_off;
+ size_t win_size = wi.win_size;
+ size_t omask = win_size - 1;
+ char *win_base = wi.win_base;
+ size_t l;
+ size_t bytes = npixels * __vesacon_bytes_per_pixel;
+ char rowbuf[bytes + 4] __aligned(4);
+ const char *s;
+
+ s = (const char *)__vesacon_format_pixels(rowbuf, src, npixels);
+
+ while (bytes) {
+ win_off = dst & omask;
+ win_pos = dst & ~omask;
+
+ if (__unlikely(win_pos != wi.win_pos))
+ set_window_pos(win_pos);
+
+ l = min(bytes, win_size - win_off);
+ memcpy(win_base + win_off, s, l);
+
+ bytes -= l;
+ s += l;
+ dst += l;
+ }
+}
+#else
+void __vesacon_init_copy_to_screen(void)
+{
+ struct vesa_mode_info *const mi = &__vesa_info.mi;
+ int winn;
+
+ if (mi->mode_attr & 0x0080) {
+ /* Linear frame buffer */
+
+ wi.win_base = (char *)mi->lfb_ptr;
+ wi.win_size = mi->lfb_line_size*mi->v_res; /* one giant window */
+ wi.win_pos = 0; /* Already positioned (only one position...) */
+ wi.win_num = -1; /* Not a window */
+ }
+ /* FIXME: PixelBltOnly mode is unsupported */
+}
+
+/* FIXME: Nothing to do for EFI */
+static void set_window_pos(size_t win_pos)
+{
+}
+
+void __vesacon_copy_to_screen(size_t dst, const uint32_t * src, size_t npixels)
+{
+ size_t win_pos, win_off;
+ size_t win_size = wi.win_size;
+ size_t omask = win_size - 1;
+ char *win_base = wi.win_base;
+ size_t l;
+ size_t bytes = npixels * __vesacon_bytes_per_pixel;
+ char rowbuf[bytes + 4] __aligned(4);
+ const char *s;
+
+ s = (const char *)__vesacon_format_pixels(rowbuf, src, npixels);
+
+ while (bytes) {
+ win_off = dst & omask;
+ win_pos = dst & ~omask;
+
+ if (__unlikely(win_pos != wi.win_pos))
+ set_window_pos(win_pos);
+
+ l = min(bytes, win_size - win_off);
+ memcpy(win_base + win_off, s, l);
+
+ bytes -= l;
+ s += l;
+ dst += l;
+ }
+}
+#endif /* SYSLINUX_EFI */
diff --git a/com32/lib/sys/vesa/efi/vesa.h b/com32/lib/sys/vesa/efi/vesa.h
new file mode 100644
index 00000000..81583c6b
--- /dev/null
+++ b/com32/lib/sys/vesa/efi/vesa.h
@@ -0,0 +1,129 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1999-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef LIB_SYS_VESA_H
+#define LIB_SYS_VESA_H
+
+#include <inttypes.h>
+#include <com32.h>
+
+/* VESA General Information table */
+struct vesa_general_info {
+ uint32_t signature; /* Magic number = "VESA" */
+ uint16_t version;
+ far_ptr_t vendor_string;
+ uint8_t capabilities[4];
+ far_ptr_t video_mode_ptr;
+ uint16_t total_memory;
+
+ uint16_t oem_software_rev;
+ far_ptr_t oem_vendor_name_ptr;
+ far_ptr_t oem_product_name_ptr;
+ far_ptr_t oem_product_rev_ptr;
+
+ uint8_t reserved[222];
+ uint8_t oem_data[256];
+} __attribute__ ((packed));
+
+#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24))
+#define VBE2_MAGIC ('V' + ('B' << 8) + ('E' << 16) + ('2' << 24))
+
+struct vesa_mode_info {
+ uint16_t mode_attr;
+ uint8_t win_attr[2];
+ uint16_t win_grain;
+ uint16_t win_size;
+ uint16_t win_seg[2];
+ far_ptr_t win_scheme;
+ uint16_t logical_scan;
+
+ uint16_t h_res;
+ uint16_t v_res;
+ uint8_t char_width;
+ uint8_t char_height;
+ uint8_t memory_planes;
+ uint8_t bpp;
+ uint8_t banks;
+ uint8_t memory_layout;
+ uint8_t bank_size;
+ uint8_t image_pages;
+ uint8_t page_function;
+
+ uint8_t rmask;
+ uint8_t rpos;
+ uint8_t gmask;
+ uint8_t gpos;
+ uint8_t bmask;
+ uint8_t bpos;
+ uint8_t resv_mask;
+ uint8_t resv_pos;
+ uint8_t dcm_info;
+
+ uint8_t *lfb_ptr; /* Linear frame buffer address */
+#ifdef SYSLINUX_EFI
+ /* GOP provides info about FrameBufferBase and Size
+ * Are these types consistent with EFI definition?
+ */
+ uint32_t lfb_size; /* frame buffer size */
+ uint16_t lfb_line_size; /* length of a line in bytes in frame buffer */
+ /* the following pixel sizes are relevant only if the
+ * pixel format for the GOP mode is PixelBitMask
+ */
+ uint8_t resv_size;
+ uint8_t lfb_rsize;
+ uint8_t lfb_gsize;
+ uint8_t lfb_bsize;
+ uint8_t lfb_resv_size;
+#endif
+ uint8_t *offscreen_ptr; /* Offscreen memory address */
+ uint16_t offscreen_size;
+
+ uint8_t reserved[206];
+} __attribute__ ((packed));
+
+struct vesa_info {
+ struct vesa_general_info gi;
+ struct vesa_mode_info mi;
+};
+
+extern struct vesa_info __vesa_info;
+
+#if 0
+static inline void vesa_debug(uint32_t color, int pos)
+{
+ uint32_t *stp = (uint32_t *) __vesa_info.mi.lfb_ptr;
+ stp[pos * 3] = color;
+}
+#else
+static inline void vesa_debug(uint32_t color, int pos)
+{
+ (void)color;
+ (void)pos;
+}
+#endif
+
+#endif /* LIB_SYS_VESA_H */
diff --git a/com32/lib/sys/vesa/efi/video.h b/com32/lib/sys/vesa/efi/video.h
new file mode 100644
index 00000000..d14494b1
--- /dev/null
+++ b/com32/lib/sys/vesa/efi/video.h
@@ -0,0 +1,97 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2006-2008 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef LIB_SYS_VESA_VIDEO_H
+#define LIB_SYS_VESA_VIDEO_H
+
+#include <stdbool.h>
+#include <colortbl.h>
+#include "vesa.h"
+
+#define FONT_MAX_CHARS 256
+#define FONT_MAX_HEIGHT 32
+#define FONT_WIDTH 8
+
+#define DEFAULT_VESA_X_SIZE 640
+#define DEFAULT_VESA_Y_SIZE 480
+
+#define VIDEO_BORDER 8
+#define TEXT_PIXEL_ROWS (__vesa_info.mi.v_res - 2*VIDEO_BORDER)
+#define TEXT_PIXEL_COLS (__vesa_info.mi.h_res - 2*VIDEO_BORDER)
+
+typedef uint16_t attr_t;
+
+struct vesa_char {
+ uint8_t ch; /* Character */
+ uint8_t _filler; /* Currently unused */
+ attr_t attr; /* Color table index */
+};
+
+/* Pixel formats in order of decreasing preference; PXF_NONE should be last */
+/* BGR24 is preferred over BGRA32 since the I/O overhead is smaller. */
+enum vesa_pixel_format {
+ PXF_BGR24, /* 24-bit BGR */
+ PXF_BGRA32, /* 32-bit BGRA */
+ PXF_LE_RGB16_565, /* 16-bit littleendian 5:6:5 RGB */
+ PXF_LE_RGB15_555, /* 15-bit littleendian 5:5:5 RGB */
+ PXF_NONE
+};
+extern enum vesa_pixel_format __vesacon_pixel_format;
+extern unsigned int __vesacon_bytes_per_pixel;
+typedef const void *(*__vesacon_format_pixels_t)
+ (void *, const uint32_t *, size_t);
+extern __vesacon_format_pixels_t __vesacon_format_pixels;
+extern const __vesacon_format_pixels_t __vesacon_format_pixels_list[PXF_NONE];
+
+extern struct vesa_char *__vesacon_text_display;
+
+extern int __vesacon_font_height;
+extern int __vesacon_text_rows;
+extern int __vesacon_text_cols;
+extern uint8_t __vesacon_graphics_font[FONT_MAX_CHARS][FONT_MAX_HEIGHT];
+extern uint32_t *__vesacon_background;
+extern uint32_t *__vesacon_shadowfb;
+
+extern const uint16_t __vesacon_srgb_to_linear[256];
+extern const uint8_t __vesacon_linear_to_srgb[4080];
+
+int __vesacon_init_background(void);
+int vesacon_load_background(const char *);
+int __vesacon_init(int, int);
+void __vesacon_init_cursor(int);
+void __vesacon_erase(int, int, int, int, attr_t);
+void __vesacon_scroll_up(int, attr_t);
+void __vesacon_write_char(int, int, uint8_t, attr_t);
+void __vesacon_redraw_text(void);
+void __vesacon_doit(void);
+void __vesacon_set_cursor(int, int, bool);
+void __vesacon_copy_to_screen(size_t, const uint32_t *, size_t);
+void __vesacon_init_copy_to_screen(void);
+
+int __vesacon_i915resolution(int x, int y);
+
+#endif /* LIB_SYS_VESA_VIDEO_H */
diff --git a/com32/lib/sys/vesacon_write.c b/com32/lib/sys/vesacon_write.c
index 37693177..c683c60a 100644
--- a/com32/lib/sys/vesacon_write.c
+++ b/com32/lib/sys/vesacon_write.c
@@ -43,7 +43,11 @@
#include <syslinux/config.h>
#include "ansi.h"
#include "file.h"
+#ifndef SYSLINUX_EFI
#include "vesa/video.h"
+#else
+#include "vesa/efi/video.h" /* FIXME: move to video.h */
+#endif
static void vesacon_erase(const struct term_state *, int, int, int, int);
static void vesacon_write_char(int, int, uint8_t, const struct term_state *);
diff --git a/com32/menu/Makefile b/com32/menu/Makefile
index 5a9b3c6a..d1e85ad0 100644
--- a/com32/menu/Makefile
+++ b/com32/menu/Makefile
@@ -34,6 +34,12 @@ menu.elf : menu.o $(COMMONOBJS) $(C_LIBS)
vesamenu.elf : vesamenu.o $(COMMONOBJS) $(C_LIBS)
$(LD) $(LDFLAGS) -o $@ $^
+vesamenu.c32: vesamenu.o $(COMMONOBJS) $(C_LIBS)
+ $(LD) $(LDFLAGS) -o $@ $^
+
+menu.c32: menu.o $(COMMONOBJS) $(C_LIBS)
+ $(LD) $(LDFLAGS) -o $@ $^
+
tidy dist:
rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp