diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2009-04-01 21:14:26 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-04-09 19:08:11 -0400 |
commit | d54ea252e4c92357226992cf65d94616a96e6fce (patch) | |
tree | 58299fc725d73e27b664e2f2a442297c89605a75 /arch/x86/boot | |
parent | df7699c56421c0476704f24a43409ac8c505f3d2 (diff) |
x86, setup: "glove box" BIOS interrupts in the APM code
Impact: BIOS proofing
"Glove box" off BIOS interrupts in the APM code.
LKML-Reference: <49DE7F79.4030106@zytor.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Diffstat (limited to 'arch/x86/boot')
-rw-r--r-- | arch/x86/boot/apm.c | 76 |
1 files changed, 29 insertions, 47 deletions
diff --git a/arch/x86/boot/apm.c b/arch/x86/boot/apm.c index 7aa6033001f9..ee274834ea8b 100644 --- a/arch/x86/boot/apm.c +++ b/arch/x86/boot/apm.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 1991, 1992 Linus Torvalds | 3 | * Copyright (C) 1991, 1992 Linus Torvalds |
4 | * Copyright 2007 rPath, Inc. - All Rights Reserved | 4 | * Copyright 2007 rPath, Inc. - All Rights Reserved |
5 | * Copyright 2009 Intel Corporation; author H. Peter Anvin | ||
5 | * | 6 | * |
6 | * Original APM BIOS checking by Stephen Rothwell, May 1994 | 7 | * Original APM BIOS checking by Stephen Rothwell, May 1994 |
7 | * (sfr@canb.auug.org.au) | 8 | * (sfr@canb.auug.org.au) |
@@ -19,75 +20,56 @@ | |||
19 | 20 | ||
20 | int query_apm_bios(void) | 21 | int query_apm_bios(void) |
21 | { | 22 | { |
22 | u16 ax, bx, cx, dx, di; | 23 | struct biosregs ireg, oreg; |
23 | u32 ebx, esi; | ||
24 | u8 err; | ||
25 | 24 | ||
26 | /* APM BIOS installation check */ | 25 | /* APM BIOS installation check */ |
27 | ax = 0x5300; | 26 | initregs(&ireg); |
28 | bx = cx = 0; | 27 | ireg.ah = 0x53; |
29 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" | 28 | intcall(0x15, &ireg, &oreg); |
30 | : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) | ||
31 | : : "esi", "edi"); | ||
32 | 29 | ||
33 | if (err) | 30 | if (oreg.flags & X86_EFLAGS_CF) |
34 | return -1; /* No APM BIOS */ | 31 | return -1; /* No APM BIOS */ |
35 | 32 | ||
36 | if (bx != 0x504d) /* "PM" signature */ | 33 | if (oreg.bx != 0x504d) /* "PM" signature */ |
37 | return -1; | 34 | return -1; |
38 | 35 | ||
39 | if (!(cx & 0x02)) /* 32 bits supported? */ | 36 | if (!(oreg.cx & 0x02)) /* 32 bits supported? */ |
40 | return -1; | 37 | return -1; |
41 | 38 | ||
42 | /* Disconnect first, just in case */ | 39 | /* Disconnect first, just in case */ |
43 | ax = 0x5304; | 40 | ireg.al = 0x04; |
44 | bx = 0; | 41 | intcall(0x15, &ireg, NULL); |
45 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" | ||
46 | : "+a" (ax), "+b" (bx) | ||
47 | : : "ecx", "edx", "esi", "edi"); | ||
48 | |||
49 | /* Paranoia */ | ||
50 | ebx = esi = 0; | ||
51 | cx = dx = di = 0; | ||
52 | 42 | ||
53 | /* 32-bit connect */ | 43 | /* 32-bit connect */ |
54 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6" | 44 | ireg.al = 0x03; |
55 | : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx), | 45 | intcall(0x15, &ireg, &oreg); |
56 | "+S" (esi), "+D" (di), "=m" (err) | 46 | |
57 | : "a" (0x5303)); | 47 | boot_params.apm_bios_info.cseg = oreg.ax; |
58 | 48 | boot_params.apm_bios_info.offset = oreg.ebx; | |
59 | boot_params.apm_bios_info.cseg = ax; | 49 | boot_params.apm_bios_info.cseg_16 = oreg.cx; |
60 | boot_params.apm_bios_info.offset = ebx; | 50 | boot_params.apm_bios_info.dseg = oreg.dx; |
61 | boot_params.apm_bios_info.cseg_16 = cx; | 51 | boot_params.apm_bios_info.cseg_len = oreg.si; |
62 | boot_params.apm_bios_info.dseg = dx; | 52 | boot_params.apm_bios_info.cseg_16_len = oreg.hsi; |
63 | boot_params.apm_bios_info.cseg_len = (u16)esi; | 53 | boot_params.apm_bios_info.dseg_len = oreg.di; |
64 | boot_params.apm_bios_info.cseg_16_len = esi >> 16; | 54 | |
65 | boot_params.apm_bios_info.dseg_len = di; | 55 | if (oreg.flags & X86_EFLAGS_CF) |
66 | |||
67 | if (err) | ||
68 | return -1; | 56 | return -1; |
69 | 57 | ||
70 | /* Redo the installation check as the 32-bit connect; | 58 | /* Redo the installation check as the 32-bit connect; |
71 | some BIOSes return different flags this way... */ | 59 | some BIOSes return different flags this way... */ |
72 | 60 | ||
73 | ax = 0x5300; | 61 | ireg.al = 0x00; |
74 | bx = cx = 0; | 62 | intcall(0x15, &ireg, &oreg); |
75 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" | ||
76 | : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) | ||
77 | : : "esi", "edi"); | ||
78 | 63 | ||
79 | if (err || bx != 0x504d) { | 64 | if ((oreg.eflags & X86_EFLAGS_CF) || oreg.bx != 0x504d) { |
80 | /* Failure with 32-bit connect, try to disconect and ignore */ | 65 | /* Failure with 32-bit connect, try to disconect and ignore */ |
81 | ax = 0x5304; | 66 | ireg.al = 0x04; |
82 | bx = 0; | 67 | intcall(0x15, &ireg, NULL); |
83 | asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" | ||
84 | : "+a" (ax), "+b" (bx) | ||
85 | : : "ecx", "edx", "esi", "edi"); | ||
86 | return -1; | 68 | return -1; |
87 | } | 69 | } |
88 | 70 | ||
89 | boot_params.apm_bios_info.version = ax; | 71 | boot_params.apm_bios_info.version = oreg.ax; |
90 | boot_params.apm_bios_info.flags = cx; | 72 | boot_params.apm_bios_info.flags = oreg.cx; |
91 | return 0; | 73 | return 0; |
92 | } | 74 | } |
93 | 75 | ||