18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* -*- linux-c -*- ------------------------------------------------------- * 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 58c2ecf20Sopenharmony_ci * Copyright 2007 rPath, Inc. - All Rights Reserved 68c2ecf20Sopenharmony_ci * Copyright 2009 Intel Corporation; author H. Peter Anvin 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Original APM BIOS checking by Stephen Rothwell, May 1994 98c2ecf20Sopenharmony_ci * (sfr@canb.auug.org.au) 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * ----------------------------------------------------------------------- */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci * Get APM BIOS information 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "boot.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ciint query_apm_bios(void) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci struct biosregs ireg, oreg; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci /* APM BIOS installation check */ 248c2ecf20Sopenharmony_ci initregs(&ireg); 258c2ecf20Sopenharmony_ci ireg.ah = 0x53; 268c2ecf20Sopenharmony_ci intcall(0x15, &ireg, &oreg); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci if (oreg.flags & X86_EFLAGS_CF) 298c2ecf20Sopenharmony_ci return -1; /* No APM BIOS */ 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci if (oreg.bx != 0x504d) /* "PM" signature */ 328c2ecf20Sopenharmony_ci return -1; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci if (!(oreg.cx & 0x02)) /* 32 bits supported? */ 358c2ecf20Sopenharmony_ci return -1; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci /* Disconnect first, just in case */ 388c2ecf20Sopenharmony_ci ireg.al = 0x04; 398c2ecf20Sopenharmony_ci intcall(0x15, &ireg, NULL); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci /* 32-bit connect */ 428c2ecf20Sopenharmony_ci ireg.al = 0x03; 438c2ecf20Sopenharmony_ci intcall(0x15, &ireg, &oreg); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci boot_params.apm_bios_info.cseg = oreg.ax; 468c2ecf20Sopenharmony_ci boot_params.apm_bios_info.offset = oreg.ebx; 478c2ecf20Sopenharmony_ci boot_params.apm_bios_info.cseg_16 = oreg.cx; 488c2ecf20Sopenharmony_ci boot_params.apm_bios_info.dseg = oreg.dx; 498c2ecf20Sopenharmony_ci boot_params.apm_bios_info.cseg_len = oreg.si; 508c2ecf20Sopenharmony_ci boot_params.apm_bios_info.cseg_16_len = oreg.hsi; 518c2ecf20Sopenharmony_ci boot_params.apm_bios_info.dseg_len = oreg.di; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci if (oreg.flags & X86_EFLAGS_CF) 548c2ecf20Sopenharmony_ci return -1; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci /* Redo the installation check as the 32-bit connect; 578c2ecf20Sopenharmony_ci some BIOSes return different flags this way... */ 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci ireg.al = 0x00; 608c2ecf20Sopenharmony_ci intcall(0x15, &ireg, &oreg); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci if ((oreg.eflags & X86_EFLAGS_CF) || oreg.bx != 0x504d) { 638c2ecf20Sopenharmony_ci /* Failure with 32-bit connect, try to disconnect and ignore */ 648c2ecf20Sopenharmony_ci ireg.al = 0x04; 658c2ecf20Sopenharmony_ci intcall(0x15, &ireg, NULL); 668c2ecf20Sopenharmony_ci return -1; 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci boot_params.apm_bios_info.version = oreg.ax; 708c2ecf20Sopenharmony_ci boot_params.apm_bios_info.flags = oreg.cx; 718c2ecf20Sopenharmony_ci return 0; 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 74