162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* -*- linux-c -*- ------------------------------------------------------- * 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 562306a36Sopenharmony_ci * Copyright 2007 rPath, Inc. - All Rights Reserved 662306a36Sopenharmony_ci * Copyright 2009 Intel Corporation; author H. Peter Anvin 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Original APM BIOS checking by Stephen Rothwell, May 1994 962306a36Sopenharmony_ci * (sfr@canb.auug.org.au) 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * ----------------------------------------------------------------------- */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* 1462306a36Sopenharmony_ci * Get APM BIOS information 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "boot.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ciint query_apm_bios(void) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci struct biosregs ireg, oreg; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci /* APM BIOS installation check */ 2462306a36Sopenharmony_ci initregs(&ireg); 2562306a36Sopenharmony_ci ireg.ah = 0x53; 2662306a36Sopenharmony_ci intcall(0x15, &ireg, &oreg); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci if (oreg.flags & X86_EFLAGS_CF) 2962306a36Sopenharmony_ci return -1; /* No APM BIOS */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci if (oreg.bx != 0x504d) /* "PM" signature */ 3262306a36Sopenharmony_ci return -1; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci if (!(oreg.cx & 0x02)) /* 32 bits supported? */ 3562306a36Sopenharmony_ci return -1; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci /* Disconnect first, just in case */ 3862306a36Sopenharmony_ci ireg.al = 0x04; 3962306a36Sopenharmony_ci intcall(0x15, &ireg, NULL); 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci /* 32-bit connect */ 4262306a36Sopenharmony_ci ireg.al = 0x03; 4362306a36Sopenharmony_ci intcall(0x15, &ireg, &oreg); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci boot_params.apm_bios_info.cseg = oreg.ax; 4662306a36Sopenharmony_ci boot_params.apm_bios_info.offset = oreg.ebx; 4762306a36Sopenharmony_ci boot_params.apm_bios_info.cseg_16 = oreg.cx; 4862306a36Sopenharmony_ci boot_params.apm_bios_info.dseg = oreg.dx; 4962306a36Sopenharmony_ci boot_params.apm_bios_info.cseg_len = oreg.si; 5062306a36Sopenharmony_ci boot_params.apm_bios_info.cseg_16_len = oreg.hsi; 5162306a36Sopenharmony_ci boot_params.apm_bios_info.dseg_len = oreg.di; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci if (oreg.flags & X86_EFLAGS_CF) 5462306a36Sopenharmony_ci return -1; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci /* Redo the installation check as the 32-bit connect; 5762306a36Sopenharmony_ci some BIOSes return different flags this way... */ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci ireg.al = 0x00; 6062306a36Sopenharmony_ci intcall(0x15, &ireg, &oreg); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci if ((oreg.eflags & X86_EFLAGS_CF) || oreg.bx != 0x504d) { 6362306a36Sopenharmony_ci /* Failure with 32-bit connect, try to disconnect and ignore */ 6462306a36Sopenharmony_ci ireg.al = 0x04; 6562306a36Sopenharmony_ci intcall(0x15, &ireg, NULL); 6662306a36Sopenharmony_ci return -1; 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci boot_params.apm_bios_info.version = oreg.ax; 7062306a36Sopenharmony_ci boot_params.apm_bios_info.flags = oreg.cx; 7162306a36Sopenharmony_ci return 0; 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 74