1241233Sbrooks// SPDX-License-Identifier: GPL-2.0-only 2241233Sbrooks/* -*- linux-c -*- ------------------------------------------------------- * 3241233Sbrooks * 4241233Sbrooks * Copyright (C) 1991, 1992 Linus Torvalds 5241233Sbrooks * Copyright 2007 rPath, Inc. - All Rights Reserved 6241233Sbrooks * Copyright 2009 Intel Corporation; author H. Peter Anvin 7241233Sbrooks * 8241233Sbrooks * Original APM BIOS checking by Stephen Rothwell, May 1994 9241233Sbrooks * (sfr@canb.auug.org.au) 10241233Sbrooks * 11241233Sbrooks * ----------------------------------------------------------------------- */ 12241233Sbrooks 13241233Sbrooks/* 14241233Sbrooks * Get APM BIOS information 15241233Sbrooks */ 16241233Sbrooks 17241233Sbrooks#include "boot.h" 18241233Sbrooks 19241233Sbrooksint query_apm_bios(void) 20241233Sbrooks{ 21241233Sbrooks struct biosregs ireg, oreg; 22241233Sbrooks 23241233Sbrooks /* APM BIOS installation check */ 24241233Sbrooks initregs(&ireg); 25241233Sbrooks ireg.ah = 0x53; 26241233Sbrooks intcall(0x15, &ireg, &oreg); 27241233Sbrooks 28241233Sbrooks if (oreg.flags & X86_EFLAGS_CF) 29241233Sbrooks return -1; /* No APM BIOS */ 30241233Sbrooks 31241233Sbrooks if (oreg.bx != 0x504d) /* "PM" signature */ 32241233Sbrooks return -1; 33241233Sbrooks 34241233Sbrooks if (!(oreg.cx & 0x02)) /* 32 bits supported? */ 35241233Sbrooks return -1; 36241233Sbrooks 37241233Sbrooks /* Disconnect first, just in case */ 38241233Sbrooks ireg.al = 0x04; 39241233Sbrooks intcall(0x15, &ireg, NULL); 40241233Sbrooks 41241233Sbrooks /* 32-bit connect */ 42241233Sbrooks ireg.al = 0x03; 43241233Sbrooks intcall(0x15, &ireg, &oreg); 44241233Sbrooks 45241233Sbrooks boot_params.apm_bios_info.cseg = oreg.ax; 46241233Sbrooks boot_params.apm_bios_info.offset = oreg.ebx; 47241233Sbrooks boot_params.apm_bios_info.cseg_16 = oreg.cx; 48241233Sbrooks boot_params.apm_bios_info.dseg = oreg.dx; 49241233Sbrooks boot_params.apm_bios_info.cseg_len = oreg.si; 50241233Sbrooks boot_params.apm_bios_info.cseg_16_len = oreg.hsi; 51241233Sbrooks boot_params.apm_bios_info.dseg_len = oreg.di; 52241233Sbrooks 53241233Sbrooks if (oreg.flags & X86_EFLAGS_CF) 54241233Sbrooks return -1; 55241233Sbrooks 56241233Sbrooks /* Redo the installation check as the 32-bit connect; 57241233Sbrooks some BIOSes return different flags this way... */ 58241233Sbrooks 59241233Sbrooks ireg.al = 0x00; 60241233Sbrooks intcall(0x15, &ireg, &oreg); 61241233Sbrooks 62241233Sbrooks if ((oreg.eflags & X86_EFLAGS_CF) || oreg.bx != 0x504d) { 63241233Sbrooks /* Failure with 32-bit connect, try to disconnect and ignore */ 64241233Sbrooks ireg.al = 0x04; 65241233Sbrooks intcall(0x15, &ireg, NULL); 66241233Sbrooks return -1; 67241233Sbrooks } 68241233Sbrooks 69241233Sbrooks boot_params.apm_bios_info.version = oreg.ax; 70241233Sbrooks boot_params.apm_bios_info.flags = oreg.cx; 71241233Sbrooks return 0; 72241233Sbrooks} 73241233Sbrooks 74241233Sbrooks