Home | History | Annotate | Download | only in core
      1 /* ----------------------------------------------------------------------- *
      2  *
      3  *   Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
      4  *   Copyright 2013 Intel Corporation
      5  *
      6  *   This program is free software; you can redistribute it and/or modify
      7  *   it under the terms of the GNU General Public License as published by
      8  *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
      9  *   Boston MA 02111-1307, USA; either version 2 of the License, or
     10  *   (at your option) any later version; incorporated herein by reference.
     11  *
     12  * ----------------------------------------------------------------------- */
     13 
     14 /*
     15  *
     16  * font.c
     17  *
     18  * VGA font handling code
     19  *
     20  */
     21 
     22 #include <syslinux/firmware.h>
     23 #include <syslinux/video.h>
     24 #include <sys/io.h>
     25 #include <stdio.h>
     26 #include <fs.h>
     27 
     28 #include "bios.h"
     29 #include "graphics.h"
     30 #include "core.h"
     31 
     32 __export uint8_t UserFont = 0;		/* Using a user-specified font */
     33 
     34 __export __lowmem char fontbuf[8192];
     35 
     36 uint16_t GXPixCols = 1;		/* Graphics mode pixel columns */
     37 uint16_t GXPixRows = 1;		/* Graphics mode pixel rows */
     38 
     39 /*
     40  * loadfont:	Load a .psf font file and install it onto the VGA console
     41  *		(if we're not on a VGA screen then ignore.)
     42  */
     43 __export void loadfont(const char *filename)
     44 {
     45 	struct psfheader {
     46 		uint16_t magic;
     47 		uint8_t mode;
     48 		uint8_t height;
     49 	} hdr;
     50 	FILE *f;
     51 
     52 	f = fopen(filename, "r");
     53 	if (!f)
     54 		return;
     55 
     56 	/* Read header */
     57 	if (_fread(&hdr, sizeof hdr, f) != sizeof hdr)
     58 		goto fail;
     59 
     60 	/* Magic number */
     61 	if (hdr.magic != 0x0436)
     62 		goto fail;
     63 
     64 	/* File mode: font modes 0-5 supported */
     65 	if (hdr.mode > 5)
     66 		goto fail;
     67 
     68 	/* VGA minimum/maximum */
     69 	if (hdr.height < 2 || hdr.height > 32)
     70 		goto fail;
     71 
     72 	/* Load the actual font into the font buffer. */
     73 	memset(fontbuf, 0, 256*32);
     74 	if (_fread(fontbuf, 256*hdr.height, f) != 256*hdr.height)
     75 	    goto fail;
     76 
     77 	/* Loaded OK */
     78 	VGAFontSize = hdr.height;
     79 	UserFont = 1;		/* Set font flag */
     80 	use_font();
     81 
     82 fail:
     83 	fclose(f);
     84 }
     85 
     86 /*
     87  * use_font:
     88  *	This routine activates whatever font happens to be in the
     89  *	vgafontbuf, and updates the bios_adjust_screen data.
     90  *      Must be called with CS = DS
     91  */
     92 void use_font(void)
     93 {
     94 	com32sys_t ireg, oreg;
     95 	uint8_t bytes = VGAFontSize;
     96 
     97 	/* Nonstandard mode? */
     98 	if (UsingVGA & ~0x3)
     99 		syslinux_force_text_mode();
    100 
    101 	memset(&ireg, 0, sizeof(ireg));
    102 
    103 	ireg.es = SEG(fontbuf);
    104 	ireg.ebp.w[0] = OFFS(fontbuf); /* ES:BP -> font */
    105 
    106 	/* Are we using a user-specified font? */
    107 	if (UserFont & 0x1) {
    108 		/* Are we in graphics mode? */
    109 		if (UsingVGA & 0x1) {
    110 			uint8_t rows;
    111 
    112 			rows = GXPixRows / bytes;
    113 			VidRows = rows - 1;
    114 
    115 			/* Set user character table */
    116 			ireg.eax.w[0] = 0x1121;
    117 			ireg.ebx.b[0] = 0;
    118 			ireg.ecx.b[0] = bytes; /* bytes/character */
    119 			ireg.edx.b[0] = rows;
    120 
    121 			__intcall(0x10, &ireg, &oreg);
    122 
    123 			/* 8 pixels/character */
    124 			VidCols = ((GXPixCols >> 3) - 1);
    125 
    126 			/* No need to call bios_adjust_screen */
    127 			return;
    128 		} else {
    129 			ireg.eax.w[0] = 0x1110;	/* Load into VGA RAM */
    130 			ireg.ebx.b[0] = 0;
    131 			ireg.ebx.b[1] = bytes; /* bytes/character */
    132 			ireg.ecx.w[0] = 256;
    133 			ireg.edx.w[0] = 0;
    134 
    135 			__intcall(0x10, &ireg, &oreg);
    136 
    137                         memset(&ireg, 0, sizeof(ireg));
    138 			ireg.ebx.b[0] = 0;
    139 			ireg.eax.w[0] = 0x1103; /* Select page 0 */
    140 			__intcall(0x10, &ireg, NULL);
    141 		}
    142 
    143 	}
    144 
    145 	bios_adjust_screen();
    146 }
    147 
    148 /*
    149  * bios_adjust_screen: Set the internal variables associated with the screen size.
    150  *		This is a subroutine in case we're loading a custom font.
    151  */
    152 void bios_adjust_screen(void)
    153 {
    154 	com32sys_t ireg, oreg;
    155 	volatile uint8_t *vidrows = (volatile uint8_t *)BIOS_vidrows;
    156 	uint8_t rows, cols;
    157 
    158 	memset(&ireg, 0, sizeof(ireg));
    159 
    160 	rows = *vidrows;
    161 	if (!rows) {
    162 		/*
    163 		 * No vidrows in BIOS, assume 25.
    164 		 * (Remember: vidrows == rows-1)
    165 		 */
    166 		rows = 24;
    167 	}
    168 
    169 	VidRows = rows;
    170 
    171 	ireg.eax.b[1] = 0x0f;	/* Read video state */
    172 	__intcall(0x10, &ireg, &oreg);
    173 	cols = oreg.eax.b[1];
    174 
    175 	VidCols = --cols;	/* Store count-1 (same as rows) */
    176 }
    177 
    178 void adjust_screen(void)
    179 {
    180 	if (firmware->adjust_screen)
    181 		firmware->adjust_screen();
    182 }
    183 
    184 void pm_adjust_screen(com32sys_t *regs __unused)
    185 {
    186 	adjust_screen();
    187 }
    188 
    189 void pm_userfont(com32sys_t *regs)
    190 {
    191 	regs->es = SEG(fontbuf);
    192 	regs->ebx.w[0] = OFFS(fontbuf);
    193 }
    194