• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
loadfont(const char * filename)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  */
use_font(void)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  */
bios_adjust_screen(void)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 
adjust_screen(void)178 void adjust_screen(void)
179 {
180 	if (firmware->adjust_screen)
181 		firmware->adjust_screen();
182 }
183 
pm_adjust_screen(com32sys_t * regs __unused)184 void pm_adjust_screen(com32sys_t *regs __unused)
185 {
186 	adjust_screen();
187 }
188 
pm_userfont(com32sys_t * regs)189 void pm_userfont(com32sys_t *regs)
190 {
191 	regs->es = SEG(fontbuf);
192 	regs->ebx.w[0] = OFFS(fontbuf);
193 }
194