diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2009-04-01 21:17:17 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-04-09 19:08:11 -0400 |
commit | 3435d3476c5ed955d56a6216ed2d156847b3a575 (patch) | |
tree | 3d1f7e43cc1db567454e7b1368fd4dd0448f2a94 | |
parent | d54ea252e4c92357226992cf65d94616a96e6fce (diff) |
x86, setup: "glove box" BIOS interrupts in the EDD code
Impact: BIOS proofing
"Glove box" off BIOS interrupts in the EDD code.
LKML-Reference: <49DE7F79.4030106@zytor.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r-- | arch/x86/boot/edd.c | 71 |
1 files changed, 31 insertions, 40 deletions
diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c index 1aae8f3e5ca1..c501a5b466f8 100644 --- a/arch/x86/boot/edd.c +++ b/arch/x86/boot/edd.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 | * This file is part of the Linux kernel, and is made available under | 7 | * This file is part of the Linux kernel, and is made available under |
7 | * the terms of the GNU General Public License version 2. | 8 | * the terms of the GNU General Public License version 2. |
@@ -22,17 +23,17 @@ | |||
22 | */ | 23 | */ |
23 | static int read_mbr(u8 devno, void *buf) | 24 | static int read_mbr(u8 devno, void *buf) |
24 | { | 25 | { |
25 | u16 ax, bx, cx, dx; | 26 | struct biosregs ireg, oreg; |
26 | 27 | ||
27 | ax = 0x0201; /* Legacy Read, one sector */ | 28 | initregs(&ireg); |
28 | cx = 0x0001; /* Sector 0-0-1 */ | 29 | ireg.ax = 0x0201; /* Legacy Read, one sector */ |
29 | dx = devno; | 30 | ireg.cx = 0x0001; /* Sector 0-0-1 */ |
30 | bx = (size_t)buf; | 31 | ireg.dl = devno; |
31 | asm volatile("pushfl; stc; int $0x13; setc %%al; popfl" | 32 | ireg.bx = (size_t)buf; |
32 | : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx) | ||
33 | : : "esi", "edi", "memory"); | ||
34 | 33 | ||
35 | return -(u8)ax; /* 0 or -1 */ | 34 | intcall(0x13, &ireg, &oreg); |
35 | |||
36 | return -(oreg.eflags & X86_EFLAGS_CF); /* 0 or -1 */ | ||
36 | } | 37 | } |
37 | 38 | ||
38 | static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig) | 39 | static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig) |
@@ -72,56 +73,46 @@ static u32 read_mbr_sig(u8 devno, struct edd_info *ei, u32 *mbrsig) | |||
72 | 73 | ||
73 | static int get_edd_info(u8 devno, struct edd_info *ei) | 74 | static int get_edd_info(u8 devno, struct edd_info *ei) |
74 | { | 75 | { |
75 | u16 ax, bx, cx, dx, di; | 76 | struct biosregs ireg, oreg; |
76 | 77 | ||
77 | memset(ei, 0, sizeof *ei); | 78 | memset(ei, 0, sizeof *ei); |
78 | 79 | ||
79 | /* Check Extensions Present */ | 80 | /* Check Extensions Present */ |
80 | 81 | ||
81 | ax = 0x4100; | 82 | initregs(&ireg); |
82 | bx = EDDMAGIC1; | 83 | ireg.ah = 0x41; |
83 | dx = devno; | 84 | ireg.bx = EDDMAGIC1; |
84 | asm("pushfl; stc; int $0x13; setc %%al; popfl" | 85 | ireg.dl = devno; |
85 | : "+a" (ax), "+b" (bx), "=c" (cx), "+d" (dx) | 86 | intcall(0x13, &ireg, &oreg); |
86 | : : "esi", "edi"); | ||
87 | 87 | ||
88 | if ((u8)ax) | 88 | if (oreg.eflags & X86_EFLAGS_CF) |
89 | return -1; /* No extended information */ | 89 | return -1; /* No extended information */ |
90 | 90 | ||
91 | if (bx != EDDMAGIC2) | 91 | if (oreg.bx != EDDMAGIC2) |
92 | return -1; | 92 | return -1; |
93 | 93 | ||
94 | ei->device = devno; | 94 | ei->device = devno; |
95 | ei->version = ax >> 8; /* EDD version number */ | 95 | ei->version = oreg.ah; /* EDD version number */ |
96 | ei->interface_support = cx; /* EDD functionality subsets */ | 96 | ei->interface_support = oreg.cx; /* EDD functionality subsets */ |
97 | 97 | ||
98 | /* Extended Get Device Parameters */ | 98 | /* Extended Get Device Parameters */ |
99 | 99 | ||
100 | ei->params.length = sizeof(ei->params); | 100 | ei->params.length = sizeof(ei->params); |
101 | ax = 0x4800; | 101 | ireg.ah = 0x48; |
102 | dx = devno; | 102 | ireg.si = (size_t)&ei->params; |
103 | asm("pushfl; int $0x13; popfl" | 103 | intcall(0x13, &ireg, &oreg); |
104 | : "+a" (ax), "+d" (dx), "=m" (ei->params) | ||
105 | : "S" (&ei->params) | ||
106 | : "ebx", "ecx", "edi"); | ||
107 | 104 | ||
108 | /* Get legacy CHS parameters */ | 105 | /* Get legacy CHS parameters */ |
109 | 106 | ||
110 | /* Ralf Brown recommends setting ES:DI to 0:0 */ | 107 | /* Ralf Brown recommends setting ES:DI to 0:0 */ |
111 | ax = 0x0800; | 108 | ireg.ah = 0x08; |
112 | dx = devno; | 109 | ireg.es = 0; |
113 | di = 0; | 110 | intcall(0x13, &ireg, &oreg); |
114 | asm("pushw %%es; " | 111 | |
115 | "movw %%di,%%es; " | 112 | if (!(oreg.eflags & X86_EFLAGS_CF)) { |
116 | "pushfl; stc; int $0x13; setc %%al; popfl; " | 113 | ei->legacy_max_cylinder = oreg.ch + ((oreg.cl & 0xc0) << 2); |
117 | "popw %%es" | 114 | ei->legacy_max_head = oreg.dh; |
118 | : "+a" (ax), "=b" (bx), "=c" (cx), "+d" (dx), "+D" (di) | 115 | ei->legacy_sectors_per_track = oreg.cl & 0x3f; |
119 | : : "esi"); | ||
120 | |||
121 | if ((u8)ax == 0) { | ||
122 | ei->legacy_max_cylinder = (cx >> 8) + ((cx & 0xc0) << 2); | ||
123 | ei->legacy_max_head = dx >> 8; | ||
124 | ei->legacy_sectors_per_track = cx & 0x3f; | ||
125 | } | 116 | } |
126 | 117 | ||
127 | return 0; | 118 | return 0; |