194 lines
4.1 KiB
C
194 lines
4.1 KiB
C
/* ----------------------------------------------------------------------- *
|
|
*
|
|
* Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
|
|
* Copyright 2013 Intel Corporation
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, Inc., 53 Temple Place Ste 330,
|
|
* Boston MA 02111-1307, USA; either version 2 of the License, or
|
|
* (at your option) any later version; incorporated herein by reference.
|
|
*
|
|
* ----------------------------------------------------------------------- */
|
|
|
|
/*
|
|
*
|
|
* font.c
|
|
*
|
|
* VGA font handling code
|
|
*
|
|
*/
|
|
|
|
#include <syslinux/firmware.h>
|
|
#include <syslinux/video.h>
|
|
#include <sys/io.h>
|
|
#include <stdio.h>
|
|
#include <fs.h>
|
|
|
|
#include "bios.h"
|
|
#include "graphics.h"
|
|
#include "core.h"
|
|
|
|
__export uint8_t UserFont = 0; /* Using a user-specified font */
|
|
|
|
__export __lowmem char fontbuf[8192];
|
|
|
|
uint16_t GXPixCols = 1; /* Graphics mode pixel columns */
|
|
uint16_t GXPixRows = 1; /* Graphics mode pixel rows */
|
|
|
|
/*
|
|
* loadfont: Load a .psf font file and install it onto the VGA console
|
|
* (if we're not on a VGA screen then ignore.)
|
|
*/
|
|
__export void loadfont(const char *filename)
|
|
{
|
|
struct psfheader {
|
|
uint16_t magic;
|
|
uint8_t mode;
|
|
uint8_t height;
|
|
} hdr;
|
|
FILE *f;
|
|
|
|
f = fopen(filename, "r");
|
|
if (!f)
|
|
return;
|
|
|
|
/* Read header */
|
|
if (_fread(&hdr, sizeof hdr, f) != sizeof hdr)
|
|
goto fail;
|
|
|
|
/* Magic number */
|
|
if (hdr.magic != 0x0436)
|
|
goto fail;
|
|
|
|
/* File mode: font modes 0-5 supported */
|
|
if (hdr.mode > 5)
|
|
goto fail;
|
|
|
|
/* VGA minimum/maximum */
|
|
if (hdr.height < 2 || hdr.height > 32)
|
|
goto fail;
|
|
|
|
/* Load the actual font into the font buffer. */
|
|
memset(fontbuf, 0, 256*32);
|
|
if (_fread(fontbuf, 256*hdr.height, f) != 256*hdr.height)
|
|
goto fail;
|
|
|
|
/* Loaded OK */
|
|
VGAFontSize = hdr.height;
|
|
UserFont = 1; /* Set font flag */
|
|
use_font();
|
|
|
|
fail:
|
|
fclose(f);
|
|
}
|
|
|
|
/*
|
|
* use_font:
|
|
* This routine activates whatever font happens to be in the
|
|
* vgafontbuf, and updates the bios_adjust_screen data.
|
|
* Must be called with CS = DS
|
|
*/
|
|
void use_font(void)
|
|
{
|
|
com32sys_t ireg, oreg;
|
|
uint8_t bytes = VGAFontSize;
|
|
|
|
/* Nonstandard mode? */
|
|
if (UsingVGA & ~0x3)
|
|
syslinux_force_text_mode();
|
|
|
|
memset(&ireg, 0, sizeof(ireg));
|
|
|
|
ireg.es = SEG(fontbuf);
|
|
ireg.ebp.w[0] = OFFS(fontbuf); /* ES:BP -> font */
|
|
|
|
/* Are we using a user-specified font? */
|
|
if (UserFont & 0x1) {
|
|
/* Are we in graphics mode? */
|
|
if (UsingVGA & 0x1) {
|
|
uint8_t rows;
|
|
|
|
rows = GXPixRows / bytes;
|
|
VidRows = rows - 1;
|
|
|
|
/* Set user character table */
|
|
ireg.eax.w[0] = 0x1121;
|
|
ireg.ebx.b[0] = 0;
|
|
ireg.ecx.b[0] = bytes; /* bytes/character */
|
|
ireg.edx.b[0] = rows;
|
|
|
|
__intcall(0x10, &ireg, &oreg);
|
|
|
|
/* 8 pixels/character */
|
|
VidCols = ((GXPixCols >> 3) - 1);
|
|
|
|
/* No need to call bios_adjust_screen */
|
|
return;
|
|
} else {
|
|
ireg.eax.w[0] = 0x1110; /* Load into VGA RAM */
|
|
ireg.ebx.b[0] = 0;
|
|
ireg.ebx.b[1] = bytes; /* bytes/character */
|
|
ireg.ecx.w[0] = 256;
|
|
ireg.edx.w[0] = 0;
|
|
|
|
__intcall(0x10, &ireg, &oreg);
|
|
|
|
memset(&ireg, 0, sizeof(ireg));
|
|
ireg.ebx.b[0] = 0;
|
|
ireg.eax.w[0] = 0x1103; /* Select page 0 */
|
|
__intcall(0x10, &ireg, NULL);
|
|
}
|
|
|
|
}
|
|
|
|
bios_adjust_screen();
|
|
}
|
|
|
|
/*
|
|
* bios_adjust_screen: Set the internal variables associated with the screen size.
|
|
* This is a subroutine in case we're loading a custom font.
|
|
*/
|
|
void bios_adjust_screen(void)
|
|
{
|
|
com32sys_t ireg, oreg;
|
|
volatile uint8_t *vidrows = (volatile uint8_t *)BIOS_vidrows;
|
|
uint8_t rows, cols;
|
|
|
|
memset(&ireg, 0, sizeof(ireg));
|
|
|
|
rows = *vidrows;
|
|
if (!rows) {
|
|
/*
|
|
* No vidrows in BIOS, assume 25.
|
|
* (Remember: vidrows == rows-1)
|
|
*/
|
|
rows = 24;
|
|
}
|
|
|
|
VidRows = rows;
|
|
|
|
ireg.eax.b[1] = 0x0f; /* Read video state */
|
|
__intcall(0x10, &ireg, &oreg);
|
|
cols = oreg.eax.b[1];
|
|
|
|
VidCols = --cols; /* Store count-1 (same as rows) */
|
|
}
|
|
|
|
void adjust_screen(void)
|
|
{
|
|
if (firmware->adjust_screen)
|
|
firmware->adjust_screen();
|
|
}
|
|
|
|
void pm_adjust_screen(com32sys_t *regs __unused)
|
|
{
|
|
adjust_screen();
|
|
}
|
|
|
|
void pm_userfont(com32sys_t *regs)
|
|
{
|
|
regs->es = SEG(fontbuf);
|
|
regs->ebx.w[0] = OFFS(fontbuf);
|
|
}
|