Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

H. Peter Anvin and committed by
H. Peter Anvin
d54ea252 df7699c5

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