Impact: BIOS proofing "Glove box" off BIOS interrupts in the core boot code. LKML-Reference: <49DE7F79.4030106@zytor.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
		
			
				
	
	
		
			114 lines
		
	
	
	
		
			1.9 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
	
		
			1.9 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
/* -*- linux-c -*- ------------------------------------------------------- *
 | 
						|
 *
 | 
						|
 *   Copyright (C) 1991, 1992 Linus Torvalds
 | 
						|
 *   Copyright 2007 rPath, Inc. - All Rights Reserved
 | 
						|
 *   Copyright 2009 Intel Corporation; author H. Peter Anvin
 | 
						|
 *
 | 
						|
 *   This file is part of the Linux kernel, and is made available under
 | 
						|
 *   the terms of the GNU General Public License version 2.
 | 
						|
 *
 | 
						|
 * ----------------------------------------------------------------------- */
 | 
						|
 | 
						|
/*
 | 
						|
 * Very simple screen I/O
 | 
						|
 * XXX: Probably should add very simple serial I/O?
 | 
						|
 */
 | 
						|
 | 
						|
#include "boot.h"
 | 
						|
 | 
						|
/*
 | 
						|
 * These functions are in .inittext so they can be used to signal
 | 
						|
 * error during initialization.
 | 
						|
 */
 | 
						|
 | 
						|
void __attribute__((section(".inittext"))) putchar(int ch)
 | 
						|
{
 | 
						|
	struct biosregs ireg;
 | 
						|
 | 
						|
	if (ch == '\n')
 | 
						|
		putchar('\r');	/* \n -> \r\n */
 | 
						|
 | 
						|
	initregs(&ireg);
 | 
						|
	ireg.bx = 0x0007;
 | 
						|
	ireg.cx = 0x0001;
 | 
						|
	ireg.ah = 0x0e;
 | 
						|
	ireg.al = ch;
 | 
						|
	intcall(0x10, &ireg, NULL);
 | 
						|
}
 | 
						|
 | 
						|
void __attribute__((section(".inittext"))) puts(const char *str)
 | 
						|
{
 | 
						|
	while (*str)
 | 
						|
		putchar(*str++);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Read the CMOS clock through the BIOS, and return the
 | 
						|
 * seconds in BCD.
 | 
						|
 */
 | 
						|
 | 
						|
static u8 gettime(void)
 | 
						|
{
 | 
						|
	struct biosregs ireg, oreg;
 | 
						|
 | 
						|
	initregs(&ireg);
 | 
						|
	ireg.ah = 0x02;
 | 
						|
	intcall(0x1a, &ireg, &oreg);
 | 
						|
 | 
						|
	return oreg.dh;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Read from the keyboard
 | 
						|
 */
 | 
						|
int getchar(void)
 | 
						|
{
 | 
						|
	struct biosregs ireg, oreg;
 | 
						|
 | 
						|
	initregs(&ireg);
 | 
						|
	/* ireg.ah = 0x00; */
 | 
						|
	intcall(0x16, &ireg, &oreg);
 | 
						|
 | 
						|
	return oreg.al;
 | 
						|
}
 | 
						|
 | 
						|
static int kbd_pending(void)
 | 
						|
{
 | 
						|
	struct biosregs ireg, oreg;
 | 
						|
 | 
						|
	initregs(&ireg);
 | 
						|
	ireg.ah = 0x01;
 | 
						|
	intcall(0x16, &ireg, &oreg);
 | 
						|
 | 
						|
	return !(oreg.eflags & X86_EFLAGS_ZF);
 | 
						|
}
 | 
						|
 | 
						|
void kbd_flush(void)
 | 
						|
{
 | 
						|
	for (;;) {
 | 
						|
		if (!kbd_pending())
 | 
						|
			break;
 | 
						|
		getchar();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
int getchar_timeout(void)
 | 
						|
{
 | 
						|
	int cnt = 30;
 | 
						|
	int t0, t1;
 | 
						|
 | 
						|
	t0 = gettime();
 | 
						|
 | 
						|
	while (cnt) {
 | 
						|
		if (kbd_pending())
 | 
						|
			return getchar();
 | 
						|
 | 
						|
		t1 = gettime();
 | 
						|
		if (t0 != t1) {
 | 
						|
			cnt--;
 | 
						|
			t0 = t1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;		/* Timeout! */
 | 
						|
}
 |