From: H. Peter Anvin , Rafael J. Wysocki [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. 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 Signed-off-by: H. Peter Anvin --- arch/i386/kernel/acpi/wakeup.S | 21 ++++++++++----------- arch/x86_64/kernel/acpi/wakeup.S | 27 +++++++++++++-------------- 2 files changed, 23 insertions(+), 25 deletions(-) Index: linux-2.6.23-rc7/arch/i386/kernel/acpi/wakeup.S =================================================================== --- linux-2.6.23-rc7.orig/arch/i386/kernel/acpi/wakeup.S +++ linux-2.6.23-rc7/arch/i386/kernel/acpi/wakeup.S @@ -143,31 +143,30 @@ bogus_real_magic: #define VIDEO_FIRST_V7 0x0900 # Setting of user mode (AX=mode ID) => CF=success + +# For now, we only handle VESA modes (0x0200..0x03ff). To handle other +# modes, we should probably compile in the video code from the boot +# directory. mode_set: movw %ax, %bx - - cmpb $VIDEO_FIRST_VESA>>8, %ah - jnc check_vesa - - decb %ah -# jz setbios Add bios modes later + subb $VIDEO_FIRST_VESA>>8, %bh + cmpb $2, %bh + jb check_vesa -setbad: clc +setbad: + clc ret check_vesa: - subb $VIDEO_FIRST_VESA>>8, %bh orw $0x4000, %bx # Use linear frame buffer movw $0x4f02, %ax # VESA BIOS mode set call int $0x10 cmpw $0x004f, %ax # AL=4f if implemented - jnz _setbad # AH=0 if OK + jnz setbad # AH=0 if OK stc ret -_setbad: jmp setbad - .code32 ALIGN Index: linux-2.6.23-rc7/arch/x86_64/kernel/acpi/wakeup.S =================================================================== --- linux-2.6.23-rc7.orig/arch/x86_64/kernel/acpi/wakeup.S +++ linux-2.6.23-rc7/arch/x86_64/kernel/acpi/wakeup.S @@ -76,7 +76,7 @@ wakeup_code: testl $2, realmode_flags - wakeup_code jz 1f mov video_mode - wakeup_code, %ax - call mode_seta + call mode_set 1: mov %ds, %ax # Find 32bit wakeup_code addr @@ -261,32 +261,31 @@ bogus_64_magic: #define VIDEO_FIRST_V7 0x0900 # Setting of user mode (AX=mode ID) => CF=success + +# For now, we only handle VESA modes (0x0200..0x03ff). To handle other +# modes, we should probably compile in the video code from the boot +# directory. .code16 -mode_seta: +mode_set: movw %ax, %bx - - cmpb $VIDEO_FIRST_VESA>>8, %ah - jnc check_vesaa - - decb %ah -# jz setbios Add bios modes later + subb $VIDEO_FIRST_VESA>>8, %bh + cmpb $2, %bh + jb check_vesa -setbada: clc +setbad: + clc ret -check_vesaa: - subb $VIDEO_FIRST_VESA>>8, %bh +check_vesa: orw $0x4000, %bx # Use linear frame buffer movw $0x4f02, %ax # VESA BIOS mode set call int $0x10 cmpw $0x004f, %ax # AL=4f if implemented - jnz _setbada # AH=0 if OK + jnz setbad # AH=0 if OK stc ret -_setbada: jmp setbada - wakeup_stack_begin: # Stack grows down .org 0xff0