diff options
author | H. Peter Anvin <hpa@zytor.com> | 2007-09-13 17:16:37 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2007-09-20 14:06:58 -0400 |
commit | 91c4b8cb5ab8cc3e8352739e35699c0487a6b6f3 (patch) | |
tree | d0a73e97ddb5c4ab8de7d5cb89517ff7f29f467f /arch | |
parent | 3f662b3f6e422a15fefcbaf4bdd21f97e6bcf32d (diff) |
[acpi] Correct the decoding of video mode numbers in wakeup.S
wakeup.S looks at the video mode number from the setup header and
looks to see if it is a VESA mode. Unfortunately, the decoding is
done incorrectly and it will attempt to frob the VESA BIOS for any
mode number 0x0200 or larger. Correct this, and remove a bunch of #if
0'd code.
Massive thanks to Jeff Chua for reporting the bug, and suffering
though a large number of experiments in order to track this problem
down.
Cc: Pavel Machek <pavel@ucw.cz>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/kernel/acpi/wakeup.S | 41 | ||||
-rw-r--r-- | arch/x86_64/kernel/acpi/wakeup.S | 47 |
2 files changed, 23 insertions, 65 deletions
diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S index ed0a0f2c1597..f22ba8534d26 100644 --- a/arch/i386/kernel/acpi/wakeup.S +++ b/arch/i386/kernel/acpi/wakeup.S | |||
@@ -151,51 +151,30 @@ bogus_real_magic: | |||
151 | #define VIDEO_FIRST_V7 0x0900 | 151 | #define VIDEO_FIRST_V7 0x0900 |
152 | 152 | ||
153 | # Setting of user mode (AX=mode ID) => CF=success | 153 | # Setting of user mode (AX=mode ID) => CF=success |
154 | |||
155 | # For now, we only handle VESA modes (0x0200..0x03ff). To handle other | ||
156 | # modes, we should probably compile in the video code from the boot | ||
157 | # directory. | ||
154 | mode_set: | 158 | mode_set: |
155 | movw %ax, %bx | 159 | movw %ax, %bx |
156 | #if 0 | 160 | subb $VIDEO_FIRST_VESA>>8, %bh |
157 | cmpb $0xff, %ah | 161 | cmpb $2, %bh |
158 | jz setalias | 162 | jb check_vesa |
159 | |||
160 | testb $VIDEO_RECALC>>8, %ah | ||
161 | jnz _setrec | ||
162 | |||
163 | cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah | ||
164 | jnc setres | ||
165 | |||
166 | cmpb $VIDEO_FIRST_SPECIAL>>8, %ah | ||
167 | jz setspc | ||
168 | |||
169 | cmpb $VIDEO_FIRST_V7>>8, %ah | ||
170 | jz setv7 | ||
171 | #endif | ||
172 | |||
173 | cmpb $VIDEO_FIRST_VESA>>8, %ah | ||
174 | jnc check_vesa | ||
175 | #if 0 | ||
176 | orb %ah, %ah | ||
177 | jz setmenu | ||
178 | #endif | ||
179 | |||
180 | decb %ah | ||
181 | # jz setbios Add bios modes later | ||
182 | 163 | ||
183 | setbad: clc | 164 | setbad: |
165 | clc | ||
184 | ret | 166 | ret |
185 | 167 | ||
186 | check_vesa: | 168 | check_vesa: |
187 | subb $VIDEO_FIRST_VESA>>8, %bh | ||
188 | orw $0x4000, %bx # Use linear frame buffer | 169 | orw $0x4000, %bx # Use linear frame buffer |
189 | movw $0x4f02, %ax # VESA BIOS mode set call | 170 | movw $0x4f02, %ax # VESA BIOS mode set call |
190 | int $0x10 | 171 | int $0x10 |
191 | cmpw $0x004f, %ax # AL=4f if implemented | 172 | cmpw $0x004f, %ax # AL=4f if implemented |
192 | jnz _setbad # AH=0 if OK | 173 | jnz setbad # AH=0 if OK |
193 | 174 | ||
194 | stc | 175 | stc |
195 | ret | 176 | ret |
196 | 177 | ||
197 | _setbad: jmp setbad | ||
198 | |||
199 | .code32 | 178 | .code32 |
200 | ALIGN | 179 | ALIGN |
201 | 180 | ||
diff --git a/arch/x86_64/kernel/acpi/wakeup.S b/arch/x86_64/kernel/acpi/wakeup.S index 13f1480cbec9..a06f2bcabef9 100644 --- a/arch/x86_64/kernel/acpi/wakeup.S +++ b/arch/x86_64/kernel/acpi/wakeup.S | |||
@@ -81,7 +81,7 @@ wakeup_code: | |||
81 | testl $2, realmode_flags - wakeup_code | 81 | testl $2, realmode_flags - wakeup_code |
82 | jz 1f | 82 | jz 1f |
83 | mov video_mode - wakeup_code, %ax | 83 | mov video_mode - wakeup_code, %ax |
84 | call mode_seta | 84 | call mode_set |
85 | 1: | 85 | 1: |
86 | 86 | ||
87 | movw $0xb800, %ax | 87 | movw $0xb800, %ax |
@@ -291,52 +291,31 @@ no_longmode: | |||
291 | #define VIDEO_FIRST_V7 0x0900 | 291 | #define VIDEO_FIRST_V7 0x0900 |
292 | 292 | ||
293 | # Setting of user mode (AX=mode ID) => CF=success | 293 | # Setting of user mode (AX=mode ID) => CF=success |
294 | |||
295 | # For now, we only handle VESA modes (0x0200..0x03ff). To handle other | ||
296 | # modes, we should probably compile in the video code from the boot | ||
297 | # directory. | ||
294 | .code16 | 298 | .code16 |
295 | mode_seta: | 299 | mode_set: |
296 | movw %ax, %bx | 300 | movw %ax, %bx |
297 | #if 0 | 301 | subb $VIDEO_FIRST_VESA>>8, %bh |
298 | cmpb $0xff, %ah | 302 | cmpb $2, %bh |
299 | jz setalias | 303 | jb check_vesa |
300 | |||
301 | testb $VIDEO_RECALC>>8, %ah | ||
302 | jnz _setrec | ||
303 | |||
304 | cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah | ||
305 | jnc setres | ||
306 | |||
307 | cmpb $VIDEO_FIRST_SPECIAL>>8, %ah | ||
308 | jz setspc | ||
309 | |||
310 | cmpb $VIDEO_FIRST_V7>>8, %ah | ||
311 | jz setv7 | ||
312 | #endif | ||
313 | |||
314 | cmpb $VIDEO_FIRST_VESA>>8, %ah | ||
315 | jnc check_vesaa | ||
316 | #if 0 | ||
317 | orb %ah, %ah | ||
318 | jz setmenu | ||
319 | #endif | ||
320 | |||
321 | decb %ah | ||
322 | # jz setbios Add bios modes later | ||
323 | 304 | ||
324 | setbada: clc | 305 | setbad: |
306 | clc | ||
325 | ret | 307 | ret |
326 | 308 | ||
327 | check_vesaa: | 309 | check_vesa: |
328 | subb $VIDEO_FIRST_VESA>>8, %bh | ||
329 | orw $0x4000, %bx # Use linear frame buffer | 310 | orw $0x4000, %bx # Use linear frame buffer |
330 | movw $0x4f02, %ax # VESA BIOS mode set call | 311 | movw $0x4f02, %ax # VESA BIOS mode set call |
331 | int $0x10 | 312 | int $0x10 |
332 | cmpw $0x004f, %ax # AL=4f if implemented | 313 | cmpw $0x004f, %ax # AL=4f if implemented |
333 | jnz _setbada # AH=0 if OK | 314 | jnz setbad # AH=0 if OK |
334 | 315 | ||
335 | stc | 316 | stc |
336 | ret | 317 | ret |
337 | 318 | ||
338 | _setbada: jmp setbada | ||
339 | |||
340 | wakeup_stack_begin: # Stack grows down | 319 | wakeup_stack_begin: # Stack grows down |
341 | 320 | ||
342 | .org 0xff0 | 321 | .org 0xff0 |