[syslinux] com16/com32 module for APM powerdown

Luciano Miguel Ferreira Rocha strange at nsk.no-ip.org
Sat Sep 17 16:41:18 PDT 2005


Hello,

In case anyone is interested, here are the source code for comboot and
com32 modules for powering down a computer using APM.

I started work on the ACPI version of it, but it will take some time to
parse the spec.

Regards,
Luciano Rocha

-- 
lfr
0/0
-------------- next part --------------
; ****************************************************************************
;
;  apmoff.asm
;
;  A program to power down a machine, using APM.
;
;   Copyright (C) 1999,2005  Luciano Rocha
;
;  This program is free software; you can redistribute it and/or modify
;  it under the terms of the GNU General Public License as published by
;  the Free Software Foundation, Inc., 53 Temple Place Ste 330,
;  Boston MA 02111-1307, USA; either version 2 of the License, or
;  (at your option) any later version; incorporated herein by reference.
;
; ****************************************************************************

%macro print 1
		mov dx, %1
		mov ah, 0x9
		int 0x21
%endmacro

%macro apm 3
		mov ah, 0x53
		mov al, %1
		mov bx, %2
		mov cx, %3
		int 0x15
%endmacro

                section .text
                cpu 8086
                org 0100h

_start:
; echo (C)
		print msg_cpy

; check APM support
		apm 0, 0, 0
		jnc apm_checkver
; APM not found
noapm:
		print msg_noapm
		jmp exit

; check bx for PM
apm_checkver:
		cmp bx, 0x504d
		jne noapm

; save flags and version
		mov [apm_flags], cx
		mov [apm_version], ax

; show apm version
		add ax, 0x3030
		mov [apm_ver_maj], ah
		mov [apm_ver_min], al
		print msg_apmver

; connect to APM
		apm 1, 0, 0
		jnc apmc

; try to break any other connection
		apm 4, 0, 0

; try again
		apm 1, 0, 0
		jnc apmc

; connection error
		print msg_apm_error_connect
		jmp exit

; apm connected
apmc:
		print msg_apm_connected
		mov cx, [apm_version]
		cmp cx, 0x0101
		jl apm_enable

; report driver version
		apm 0xe, 0, cx
		jnc apm_enable
		print msg_apm_vreport_err

; must enable apm bios?
apm_enable:
		mov cx, [apm_flags]
		and cx, 0x4
		jz apm_off

; enable apm bios
		apm 8, 1, 1
		jc apm_off
		print msg_apm_enabled

; send shutdown command
apm_off:
		apm 7, 1, 3
		jnc apmerr
		print msg_apm_off_err

; apm failed, disconnect
apmerr:
		print msg_apm_disconnecting
		apm 4, 0, 0

exit:
		mov ax, 0x4c01
		int 0x21


apm_flags		dw 0
apm_version		dw 0

%define			endl	0x2e, 0x0a, 0x0d, 0x24

msg_cpy			db "APM/ACPI Off", 0x0a, 0x0d
			db "Copyright (C) 1999,2005  Luciano Rocha", endl
msg_noapm		db "APM not detected", endl
msg_apmver		db "APM BIOS Version "
apm_ver_maj		db 0, "."
apm_ver_min		db 0
			db " found", endl
msg_apm_error_connect	db "Error connecting to APM BIOS", endl
msg_apm_connected	db "Connected to APM BIOS", endl
msg_apm_enabled		db "APM enabled", endl
msg_apm_off_err		db "APM shutdown command failed", endl
msg_apm_disconnecting	db "APM disconnected", endl
msg_apm_vreport_err	db "Error reporting driver version", endl

-------------- next part --------------
/* ----------------------------------------------------------------------- *
 *
 *   Copyright 1999,2005 Luciano Rocha
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
 *   Boston MA 02111-1307, USA; either version 2 of the License, or
 *   (at your option) any later version; incorporated herein by reference.
 *
 * ----------------------------------------------------------------------- */

/*
 * apmoff.c
 *
 * Power down a computer, using APM.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <console.h>
#include <com32.h>

int main(void)
{
  com32sys_t in, out;
  int flags;
  int version;

  openconsole(&dev_null_r, &dev_stdcon_w);

  printf("APM/ACPI Off\nCopyright (C) 1999,2005  Luciano Rocha.\n");

  /* clear input registers */
  memset(&in, '\0', sizeof in);

  /* check APM support and version */
  in.eax.w[0] = 0x5300;
  __intcall(0x15, &in, &out);
  
  /* version in ax, bx must be equal to "PM" */
  if (out.eflags.l & EFLAGS_CF || out.ebx.w[0] != 0x504d) {
    printf("APM not detected.\n");
    return 1;
  }

  printf("APM BIOS Version %x.%x found.\n", out.eax.b[1], out.eax.b[0]);

  flags = out.ecx.w[0];
  version = out.eax.w[0];

  /* establish connection to APM */
  in.eax.b[0] = 1;
  __intcall(0x15, &in, &out);

  /* connection failed, break any existing connection and try again */
  if (out.eflags.l & EFLAGS_CF) {
    in.eax.b[0] = 4;
    __intcall(0x15, &in, &out);
    in.eax.b[0] = 1;
    __intcall(0x15, &in, &out);
  }
  if (out.eflags.l & EFLAGS_CF) {
    printf("Error connecting to APM BIOS.\n");
    return 1;
  }

  printf("Connected to APM BIOS.\n");

  /* register with APM BIOS, if version >= 1.1 */
  if (version > 0x100) {
    in.ecx.w[0] = version;
    in.eax.b[0] = 0xe;
    __intcall(0x15, &in, &out);
    if (out.eflags.l & EFLAGS_CF) {
      printf("Error reporting driver version.\n");
    }
  }

  /* if APM disabled, enable it */
  if (flags & 0x4) {
    in.ecx.w[0] = 1;
    in.ebx.w[0] = 1;
    in.eax.b[0] = 8;
    __intcall(0x15, &in, &out);
    if (!(out.eflags.l & EFLAGS_CF)) {
      printf("APM enabled.\n");
    }
  }

  /* send shutdown command */
  in.ecx.w[0] = 3;
  in.ebx.w[0] = 1;
  in.eax.b[0] = 7;
  __intcall(0x15, &in, &out);
  if (out.eflags.l & EFLAGS_CF) {
    printf("APM shutdown command failed.\n");
  }

  /* if we reach this point, shutdown failed. disconnect from BIOS */
  printf("APM disconnected\n");
  in.ecx.w[0] = 0;
  in.ebx.w[0] = 0;
  in.eax.b[0] = 4;
  __intcall(0x15, &in, &out);

  return 1;
}


More information about the Syslinux mailing list