• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
8  *   Boston MA 02110-1301, USA; either version 2 of the License, or
9  *   (at your option) any later version; incorporated herein by reference.
10  *
11  *   Based on code from the Linux kernel:
12  *
13  *   Copyright (C) 1991, 1992 Linus Torvalds
14  *   Copyright 2007 rPath, Inc. - All Rights Reserved
15  *
16  *   Original APM BIOS checking by Stephen Rothwell, May 1994
17  *   (sfr@canb.auug.org.au)
18  *
19  *   This file is part of the Linux kernel, and is made available under
20  *   the terms of the GNU General Public License version 2.
21  *
22  * ----------------------------------------------------------------------- */
23 
24 /*
25  * apm.c
26  *
27  * APM information for Multiboot
28  */
29 
30 #include "mboot.h"
31 #include <com32.h>
32 
mboot_apm(void)33 void mboot_apm(void)
34 {
35     static struct apm_info apm;
36     com32sys_t ireg, oreg;
37 
38     memset(&ireg, 0, sizeof ireg);
39 
40     ireg.eax.w[0] = 0x5300;
41     __intcall(0x15, &ireg, &oreg);
42 
43     if (oreg.eflags.l & EFLAGS_CF)
44 	return;			/* No APM BIOS */
45 
46     if (oreg.ebx.w[0] != 0x504d)
47 	return;			/* No "PM" signature */
48 
49     if (!(oreg.ecx.w[0] & 0x02))
50 	return;			/* 32 bits not supported */
51 
52     /* Disconnect first, just in case */
53     memset(&ireg, 0, sizeof ireg);
54     ireg.eax.b[0] = 0x04;
55     __intcall(0x15, &ireg, &oreg);
56 
57     /* 32-bit connect */
58     ireg.eax.b[0] = 0x03;
59     __intcall(0x15, &ireg, &oreg);
60 
61     apm.cseg = oreg.eax.w[0];
62     apm.offset = oreg.ebx.l;
63     apm.cseg_16 = oreg.ecx.w[0];
64     apm.dseg_16 = oreg.edx.w[0];
65     apm.cseg_len = oreg.esi.w[0];
66     apm.cseg_16_len = oreg.esi.w[1];
67     apm.dseg_16_len = oreg.edi.w[0];
68 
69     /* Redo the installation check as the 32-bit connect;
70        some BIOSes return different flags this way... */
71 
72     memset(&ireg, 0, sizeof ireg);
73     ireg.eax.b[0] = 0x00;
74     __intcall(0x15, &ireg, &oreg);
75 
76     if ((oreg.eflags.l & EFLAGS_CF) || (oreg.ebx.w[0] != 0x504d)) {
77 	/* Failure with 32-bit connect, try to disconect and ignore */
78 	ireg.eax.b[0] = 0x04;
79 	__intcall(0x15, &ireg, NULL);
80 	return;
81     }
82 
83     apm.version = oreg.eax.w[0];
84 
85     mbinfo.apm_table = map_data(&apm, sizeof apm, 4, false);
86     if (mbinfo.apm_table)
87 	mbinfo.flags |= MB_INFO_APM_TABLE;
88 }
89