1 /* ----------------------------------------------------------------------- *
3 * Copyright 2009 Intel Corporation; author: H. Peter Anvin
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.
11 * Based on code from the Linux kernel:
13 * Copyright (C) 1991, 1992 Linus Torvalds
14 * Copyright 2007 rPath, Inc. - All Rights Reserved
16 * Original APM BIOS checking by Stephen Rothwell, May 1994
17 * (sfr@canb.auug.org.au)
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.
22 * ----------------------------------------------------------------------- */
27 * APM information for Multiboot
35 static struct apm_info apm
;
36 com32sys_t ireg
, oreg
;
38 memset(&ireg
, 0, sizeof ireg
);
40 ireg
.eax
.w
[0] = 0x5300;
41 __intcall(0x15, &ireg
, &oreg
);
43 if (oreg
.eflags
.l
& EFLAGS_CF
)
44 return; /* No APM BIOS */
46 if (oreg
.ebx
.w
[0] != 0x504d)
47 return; /* No "PM" signature */
49 if (!(oreg
.ecx
.w
[0] & 0x02))
50 return; /* 32 bits not supported */
52 /* Disconnect first, just in case */
54 __intcall(0x15, &ireg
, &oreg
);
58 __intcall(0x15, &ireg
, &oreg
);
60 apm
.cseg
= oreg
.eax
.w
[0];
61 apm
.offset
= oreg
.ebx
.l
;
62 apm
.cseg_16
= oreg
.ecx
.w
[0];
63 apm
.dseg_16
= oreg
.edx
.w
[0];
64 apm
.cseg_len
= oreg
.esi
.w
[0];
65 apm
.cseg_16_len
= oreg
.esi
.w
[1];
66 apm
.dseg_16_len
= oreg
.edi
.w
[0];
68 /* Redo the installation check as the 32-bit connect;
69 some BIOSes return different flags this way... */
72 __intcall(0x15, &ireg
, &oreg
);
74 if ((oreg
.eflags
.l
& EFLAGS_CF
) || (oreg
.ebx
.w
[0] != 0x504d)) {
75 /* Failure with 32-bit connect, try to disconect and ignore */
77 __intcall(0x15, &ireg
, NULL
);
81 apm
.version
= oreg
.eax
.w
[0];
83 mbinfo
.apm_table
= map_data(&apm
, sizeof apm
, 4, false);
85 mbinfo
.flags
|= MB_INFO_APM_TABLE
;