176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* ----------------------------------------------------------------------- * 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright 2009 Intel Corporation; author: H. Peter Anvin 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is free software; you can redistribute it and/or modify 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * it under the terms of the GNU General Public License as published by 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Boston MA 02110-1301, USA; either version 2 of the License, or 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * (at your option) any later version; incorporated herein by reference. 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Based on code from the Linux kernel: 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright (C) 1991, 1992 Linus Torvalds 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright 2007 rPath, Inc. - All Rights Reserved 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Original APM BIOS checking by Stephen Rothwell, May 1994 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * (sfr@canb.auug.org.au) 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This file is part of the Linux kernel, and is made available under 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the terms of the GNU General Public License version 2. 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * ----------------------------------------------------------------------- */ 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * apm.c 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * APM information for Multiboot 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "mboot.h" 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <com32.h> 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid mboot_apm(void) 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman static struct apm_info apm; 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman com32sys_t ireg, oreg; 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&ireg, 0, sizeof ireg); 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ireg.eax.w[0] = 0x5300; 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman __intcall(0x15, &ireg, &oreg); 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (oreg.eflags.l & EFLAGS_CF) 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; /* No APM BIOS */ 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (oreg.ebx.w[0] != 0x504d) 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; /* No "PM" signature */ 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (!(oreg.ecx.w[0] & 0x02)) 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; /* 32 bits not supported */ 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Disconnect first, just in case */ 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&ireg, 0, sizeof ireg); 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ireg.eax.b[0] = 0x04; 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman __intcall(0x15, &ireg, &oreg); 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* 32-bit connect */ 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ireg.eax.b[0] = 0x03; 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman __intcall(0x15, &ireg, &oreg); 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman apm.cseg = oreg.eax.w[0]; 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman apm.offset = oreg.ebx.l; 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman apm.cseg_16 = oreg.ecx.w[0]; 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman apm.dseg_16 = oreg.edx.w[0]; 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman apm.cseg_len = oreg.esi.w[0]; 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman apm.cseg_16_len = oreg.esi.w[1]; 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman apm.dseg_16_len = oreg.edi.w[0]; 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Redo the installation check as the 32-bit connect; 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman some BIOSes return different flags this way... */ 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset(&ireg, 0, sizeof ireg); 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ireg.eax.b[0] = 0x00; 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman __intcall(0x15, &ireg, &oreg); 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ((oreg.eflags.l & EFLAGS_CF) || (oreg.ebx.w[0] != 0x504d)) { 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Failure with 32-bit connect, try to disconect and ignore */ 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ireg.eax.b[0] = 0x04; 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman __intcall(0x15, &ireg, NULL); 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman apm.version = oreg.eax.w[0]; 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mbinfo.apm_table = map_data(&apm, sizeof apm, 4, false); 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if (mbinfo.apm_table) 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman mbinfo.flags |= MB_INFO_APM_TABLE; 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 89