git: 40ce54ccd953 - main - apm(8): Remove support for APM BIOS

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Wed, 30 Sep 2026 16:27:40 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=40ce54ccd953840c6d1f83aff41dac5f0481299f

commit 40ce54ccd953840c6d1f83aff41dac5f0481299f
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2026-09-30 16:21:45 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2026-09-30 16:21:45 +0000

    apm(8): Remove support for APM BIOS
    
    Drop support for queries and commands that are not supported by ACPI's
    /dev/apm interface.  This includes dropping support for
    enabling/disabling APM BIOS used by /etc/rc.d/apm.
    
    Reviewed by:    ziaee, imp
    Differential Revision:  https://reviews.freebsd.org/D59941
---
 ObsoleteFiles.inc                        |   3 +
 libexec/rc/rc.d/Makefile                 |   6 -
 libexec/rc/rc.d/apm                      |  50 ------
 share/man/man5/rc.conf.5                 |   9 --
 tools/build/mk/OptionalObsoleteFiles.inc |   4 +-
 usr.sbin/apm/apm.8                       |  84 ++--------
 usr.sbin/apm/apm.c                       | 264 ++-----------------------------
 7 files changed, 26 insertions(+), 394 deletions(-)

diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index 9aa4ac8ac829..344173ab74bc 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -51,6 +51,9 @@
 #   xargs -n1 | sort | uniq -d;
 # done
 
+# 20260930: apm(8) only displays ACPI status
+OLD_FILES+=etc/rc.d/apm
+
 # 20260930: apm(4) not i386-specific
 OLD_FILES+=usr/share/man/man4/i386/apm.4.gz
 
diff --git a/libexec/rc/rc.d/Makefile b/libexec/rc/rc.d/Makefile
index 406b1b41d902..5db7feb831a6 100644
--- a/libexec/rc/rc.d/Makefile
+++ b/libexec/rc/rc.d/Makefile
@@ -97,12 +97,6 @@ ACPIPACKAGE=			acpi
 ACPI=		power_profile
 .endif
 
-.if ${MACHINE} == "i386"
-CONFGROUPS.${MK_APM}+=		APM
-APMPACKAGE=			apm
-APM=		apm
-.endif
-
 CONFGROUPS.${MK_AUDIT}+=	AUDIT
 AUDITPACKAGE=			audit
 AUDIT=		auditd \
diff --git a/libexec/rc/rc.d/apm b/libexec/rc/rc.d/apm
deleted file mode 100755
index 3187f41c3a50..000000000000
--- a/libexec/rc/rc.d/apm
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/sh
-#
-#
-
-# PROVIDE: apm
-# REQUIRE: DAEMON
-# BEFORE:  LOGIN
-# KEYWORD: nojail
-
-. /etc/rc.subr
-
-name="apm"
-desc="Advanced power management"
-rcvar="apm_enable"
-start_precmd="apm_precmd"
-command="/usr/sbin/${name}"
-start_cmd="${command} -e enable"
-stop_cmd="${command} -e disable"
-status_cmd="apm_status"
-
-apm_precmd()
-{
-	case `${SYSCTL_N} hw.machine_arch` in
-	i386)
-		return 0
-		;;
-	esac
-	return 1
-}
-
-apm_status()
-{
-	case `${command} -s` in
-	1)
-		echo "APM is enabled."
-		return 0
-		;;
-	0)
-		echo "APM is disabled"
-		;;
-	esac
-	return 1
-}
-
-load_rc_config $name
-
-# doesn't make sense to run in a svcj: nojail keyword
-apm_svcj="NO"
-
-run_rc_command "$1"
diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5
index 02f75d775cee..558529a4c259 100644
--- a/share/man/man5/rc.conf.5
+++ b/share/man/man5/rc.conf.5
@@ -293,14 +293,6 @@ A list of jail properties for the service.
 See
 .Sx SERVICE JAILS
 for a list of valid properties.
-.It Va apm_enable
-.Pq Vt bool
-If set to
-.Dq Li YES ,
-enable support for Automatic Power Management with
-the
-.Xr apm 8
-command.
 .It Va devd_enable
 .Pq Vt bool
 Run
@@ -5170,7 +5162,6 @@ to
 .Xr security 7 ,
 .Xr tuning 7 ,
 .Xr accton 8 ,
-.Xr apm 8 ,
 .Xr bsdinstall 8 ,
 .Xr bthidd 8 ,
 .Xr chkprintcap 8 ,
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index 821761ddd15f..a0bf0defb19f 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -60,10 +60,8 @@ OLD_FILES+=etc/devd/power_profile.conf
 .endif
 
 .if ${MK_APM} == no
-OLD_FILES+=etc/rc.d/apm
 OLD_FILES+=usr/sbin/apm
-.elif ${TARGET_ARCH} != "i386"
-OLD_FILES+=etc/rc.d/apm
+OLD_FILES+=usr/share/man/man8/apm.8.gz
 .endif
 
 .if ${MK_AT} == no
diff --git a/usr.sbin/apm/apm.8 b/usr.sbin/apm/apm.8
index b9cb51c200dd..2a6740a38243 100644
--- a/usr.sbin/apm/apm.8
+++ b/usr.sbin/apm/apm.8
@@ -9,25 +9,19 @@
 .\" the author assume any responsibility for damages incurred with its
 .\" use.
 .\"
-.Dd September 23, 2026
+.Dd September 30, 2026
 .Dt APM 8 i386
 .Os
 .Sh NAME
 .Nm apm
-.Nd control the APM BIOS and display its information
+.Nd display power management status
 .Sh SYNOPSIS
 .Nm
-.Op Fl ablstzZ
-.Op Fl d Ar enable
-.Op Fl e Ar enable
-.Op Fl h Ar enable
-.Op Fl r Ar delta
+.Op Fl abltzZ
 .Sh DESCRIPTION
 The
 .Nm
-utility
-controls the Intel / Microsoft APM (Advanced Power Management) BIOS and
-displays the current status of APM on laptop PCs.
+utility reports power management status.
 .Pp
 The options are as follows:
 .Bl -tag -width indent
@@ -52,49 +46,10 @@ status,
 status,
 .Dq charging
 status respectively.
-.It Fl d Ar enable
-Disable/enable suspending of the display separately from a normal suspend
-using the boolean value for
-.Ar enable .
-This feature seems to not work on many different laptops,
-including the Libretto 30CT and 50CT.
-.It Fl e Ar enable
-Enable or disable APM functions of the computer,
-depending on the boolean
-.Ar enable
-argument.
-.It Fl h Ar enable
-Depending on the boolean value of
-.Ar enable ,
-enable or disable the HLT instruction in the kernel context switch routine.
-These options are not necessary for almost all APM implementations,
-but for some implementations whose
-.Dq Pa Idle CPU
-call executes both CPU clock slowdown and HLT instruction,
-.Fl h Cm false
-is necessary to prevent the system from reducing its peak performance.
-See
-.Xr apm 4
-for details.
 .It Fl l
 Display the remaining battery percentage.
 If your laptop does not
 support this function, 255 is displayed.
-.It Fl r Ar delta
-Enable the resume wakeup timer, if the laptop supports it.
-This
-does not actually suspend the laptop, but if the laptop is suspended,
-and it supports resume from suspend, then it will be resumed after
-.Ar delta
-seconds (from when you run this command, not from when you suspend).
-.It Fl s
-Display the status of the APM support as an integer value.
-The values
-0 and 1 correspond to the
-.Dq disabled
-state or
-.Dq enabled
-state respectively.
 .It Fl t
 Display the estimated remaining battery lifetime in seconds.
 If
@@ -103,12 +58,6 @@ it is unknown, -1 is displayed.
 Transition the system into standby mode.
 This mode uses less power than
 full power mode, but more than suspend mode.
-Some laptops support
-resuming from this state on timer or Ring Indicator events.
-The
-output of
-.Nm
-tells what your laptop claims to support.
 .It Fl z
 Suspend the system.
 .El
@@ -119,24 +68,15 @@ displays information and current status of APM in verbose mode.
 If multiple display options are given, the values are displayed one
 per line in the order given here.
 .Sh SEE ALSO
+.Xr acpiconf 8 ,
+.Xr acpi 4 ,
 .Xr apm 4 ,
 .Xr zzz 8
+.Sh HISTORY
+The
+.Nm
+utility originally controlled the Advanced Power Management (APM) BIOS
+extension on i386,
+now it interfaces with ACPI.
 .Sh AUTHORS
 .An Tatsumi Hosokawa Aq Mt hosokawa@jp.FreeBSD.org
-.Sh BUGS
-Some APM implementations do not support parameters needed by
-.Nm .
-On such systems,
-.Nm
-displays them as unknown.
-.Pp
-Some APM implementations cannot handle events such as pushing the
-power button or closing the cover.
-On such implementations, the system
-.Ar must
-be suspended
-.Ar only
-by using
-.Nm
-or
-.Nm zzz .
diff --git a/usr.sbin/apm/apm.c b/usr.sbin/apm/apm.c
index 01e75eb1f8b1..efb322987a2e 100644
--- a/usr.sbin/apm/apm.c
+++ b/usr.sbin/apm/apm.c
@@ -13,103 +13,29 @@
  * Sep., 1994	Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
  */
 
-#include <sys/cdefs.h>
-#include <sys/file.h>
 #include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
 
 #include <machine/apm_bios.h>
 
 #include <err.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <time.h>
 #include <unistd.h>
 
 #define APMDEV	"/dev/apm"
 
 #define APM_UNKNOWN	255
 
-#define xh(a)	(((a) & 0xff00) >> 8)
-#define xl(a)	((a) & 0xff)
-#define APMERR(a) xh(a)
-
-static int cmos_wall = 0; /* True when wall time is in cmos clock, else UTC */
-
 static void
 usage(void)
 {
 	fprintf(stderr,
-		"usage: apm [-ablstzZ] [-d enable ] [ -e enable ] "
-		"[ -h enable ] [-r delta]\n");
+		"usage: apm [-abltzZ]\n");
 	exit(1);
 }
 
-/*
- * Return 1 for boolean true, and 0 for false, according to the
- * interpretation of the string argument given.
- */
-static int
-is_true(const char *boolean)
-{
-	char *endp;
-	long val;
-
-	val = strtoul(boolean, &endp, 0);
-	if (*endp == '\0')
-		return (val != 0 ? 1 : 0);
-	if (strcasecmp(boolean, "true") == 0 ||
-	    strcasecmp(boolean, "yes") == 0 ||
-	    strcasecmp(boolean, "enable") == 0)
-		return (1);
-	if (strcasecmp(boolean, "false") == 0 ||
-	    strcasecmp(boolean, "no") == 0 ||
-	    strcasecmp(boolean, "disable") == 0)
-		return (0);
-	/* Well, I have no idea what the user wants, so... */
-	warnx("invalid boolean argument \"%s\"", boolean);
-	usage();
-	/* NOTREACHED */
-
-	return (0);
-}
-
-static int
-int2bcd(int i)
-{
-	int retval = 0;
-	int base = 0;
-
-	if (i >= 10000)
-		return -1;
-    
-	while (i) {
-		retval |= (i % 10) << base;
-		i /= 10;
-		base += 4;
-	}
-	return retval;
-}
-
-static int
-bcd2int(int bcd)
-{
-	int retval = 0;
-	int place = 1;
-
-	if (bcd > 0x9999)
-		return -1;
-
-	while (bcd) {
-		retval += (bcd & 0xf) * place;
-		bcd >>= 4;
-		place *= 10;
-	}
-	return retval;
-}
-
 static void 
 apm_suspend(int fd)
 {
@@ -131,18 +57,6 @@ apm_getinfo(int fd, apm_info_t aip)
 		err(1, "ioctl(APMIO_GETINFO)");
 }
 
-static void 
-apm_enable(int fd, int enable) 
-{
-	if (enable) {
-		if (ioctl(fd, APMIO_ENABLE) == -1)
-			err(1, "ioctl(APMIO_ENABLE)");
-	} else {
-		if (ioctl(fd, APMIO_DISABLE) == -1)
-			err(1, "ioctl(APMIO_DISABLE)");
-	}
-}
-
 static void
 print_batt_time(int batt_time)
 {
@@ -188,10 +102,8 @@ print_batt_stat(u_int batt_stat)
 }
 
 static void 
-print_all_info(int fd, apm_info_t aip, int bioscall_available)
+print_all_info(int fd, apm_info_t aip)
 {
-	struct apm_bios_arg args;
-	int apmerr;
 	const char *line_msg[] = { "off-line", "on-line" , "backup power"};
 
 	printf("APM version: %d.%d\n", aip->ai_major, aip->ai_minor);
@@ -237,69 +149,6 @@ print_all_info(int fd, apm_info_t aip, int bioscall_available)
 		}
 	}
 
-	if (bioscall_available) {
-		/*
-		 * try to get the suspend timer
-		 */
-		bzero(&args, sizeof(args));
-		args.eax = (APM_BIOS) << 8 | APM_RESUMETIMER;
-		args.ebx = PMDV_APMBIOS;
-		args.ecx = 0x0001;
-		if (ioctl(fd, APMIO_BIOS, &args)) {
-			printf("Resume timer: unknown\n");
-		} else {
-			apmerr = APMERR(args.eax);
-			if (apmerr == 0x0d || apmerr == 0x86)
-				printf("Resume timer: disabled\n");
-			else if (apmerr)
-				warnx(
-		"failed to get the resume timer: APM error0x%x", apmerr);
-			else {
-				/*
-				 * OK.  We have the time (all bcd).
-				 * CH - seconds
-				 * DH - hours
-				 * DL - minutes
-				 * xh(SI) - month (1-12)
-				 * xl(SI) - day of month (1-31)
-				 * DI - year
-				 */
-				struct tm tm;
-				char buf[1024];
-				time_t t;
-
-				tm.tm_sec = bcd2int(xh(args.ecx));
-				tm.tm_min = bcd2int(xl(args.edx));
-				tm.tm_hour = bcd2int(xh(args.edx));
-				tm.tm_mday = bcd2int(xl(args.esi));
-				tm.tm_mon = bcd2int(xh(args.esi)) - 1;
-				tm.tm_year = bcd2int(args.edi) - 1900;
-				if (cmos_wall)
-					t = mktime(&tm);
-				else
-					t = timegm(&tm);
-				if (t != -1) {
-					tm = *localtime(&t);
-					strftime(buf, sizeof(buf), "%c", &tm);
-					printf("Resume timer: %s\n", buf);
-				} else
-					printf("Resume timer: unknown\n");
-			}
-		}
-
-		/*
-		 * Get the ring indicator resume state
-		 */
-		bzero(&args, sizeof(args));
-		args.eax  = (APM_BIOS) << 8 | APM_RESUMEONRING;
-		args.ebx = PMDV_APMBIOS;
-		args.ecx = 0x0002;
-		if (ioctl(fd, APMIO_BIOS, &args) == 0) {
-			printf("Resume on ring indicator: %sabled\n",
-			    args.ecx ? "en" : "dis");
-		}
-	}
-
 	if (aip->ai_infoversion >= 1) {
 		if (aip->ai_capabilities == 0xff00)
 		    return;
@@ -324,72 +173,15 @@ print_all_info(int fd, apm_info_t aip, int bioscall_available)
 
 }
 
-/*
- * currently, it can turn off the display, but the display never comes
- * back until the machine suspend/resumes :-).
- */
-static void 
-apm_display(int fd, int newstate)
-{
-	if (ioctl(fd, APMIO_DISPLAY, &newstate) == -1)
-		err(1, "ioctl(APMIO_DISPLAY)");
-}
-
-static void
-apm_haltcpu(int fd, int enable)
-{
-	if (enable) {
-		if (ioctl(fd, APMIO_HALTCPU, NULL) == -1)
-			err(1, "ioctl(APMIO_HALTCPU)");
-	} else {
-		if (ioctl(fd, APMIO_NOTHALTCPU, NULL) == -1)
-			err(1, "ioctl(APMIO_NOTHALTCPU)");
-	}
-}
-
-static void
-apm_set_timer(int fd, int delta)
-{
-	time_t tmr;
-	struct tm *tm;
-	struct apm_bios_arg args;
-
-	tmr = time(NULL) + delta;
-	if (cmos_wall)
-		tm = localtime(&tmr);
-	else
-		tm = gmtime(&tmr);
-	bzero(&args, sizeof(args));
-	args.eax = (APM_BIOS) << 8 | APM_RESUMETIMER;
-	args.ebx = PMDV_APMBIOS;
-	if (delta > 0) {
-		args.ecx = (int2bcd(tm->tm_sec) << 8) | 0x02;
-		args.edx = (int2bcd(tm->tm_hour) << 8) | int2bcd(tm->tm_min);
-		args.esi = (int2bcd(tm->tm_mon + 1) << 8) | int2bcd(tm->tm_mday);
-		args.edi = int2bcd(tm->tm_year + 1900);
-	} else {
-		args.ecx = 0x0000;
-	}
-	if (ioctl(fd, APMIO_BIOS, &args)) {
-		err(1,"set resume timer");
-	}
-}
-
 int 
 main(int argc, char *argv[])
 {
 	int	c, fd;
-	int     dosleep = 0, all_info = 1, apm_status = 0, batt_status = 0;
-	int     display = -1, batt_life = 0, ac_status = 0, standby = 0;
-	int	batt_time = 0, delta = 0, enable = -1, haltcpu = -1;
-	int	bioscall_available = 0;
-	size_t	cmos_wall_len = sizeof(cmos_wall);
-
-	if (sysctlbyname("machdep.wall_cmos_clock", &cmos_wall, &cmos_wall_len,
-	    NULL, 0) == -1)
-		err(1, "sysctlbyname(machdep.wall_cmos_clock)");
+	int     dosleep = 0, all_info = 1, batt_status = 0;
+	int     batt_life = 0, ac_status = 0, standby = 0;
+	int	batt_time = 0;
 
-	while ((c = getopt(argc, argv, "abe:h:lRr:stzd:Z")) != -1) {
+	while ((c = getopt(argc, argv, "abltzZ")) != -1) {
 		switch (c) {
 		case 'a':
 			ac_status = 1;
@@ -399,32 +191,10 @@ main(int argc, char *argv[])
 			batt_status = 1;
 			all_info = 0;
 			break;
-		case 'd':
-			display = is_true(optarg);
-			all_info = 0;
-			break;
 		case 'l':
 			batt_life = 1;
 			all_info = 0;
 			break;
-		case 'R':
-			delta = -1;
-			break;
-		case 'r':
-			delta = atoi(optarg);
-			break;
-		case 's':
-			apm_status = 1;
-			all_info = 0;
-			break;
-		case 'e':
-			enable = is_true(optarg);
-			all_info = 0;
-			break;
-		case 'h':
-			haltcpu = is_true(optarg);
-			all_info = 0;
-			break;
 		case 't':
 			batt_time = 1;
 			all_info = 0;
@@ -444,44 +214,30 @@ main(int argc, char *argv[])
 		argc -= optind;
 		argv += optind;
 	}
-	if (haltcpu != -1 || enable != -1 || display != -1 || delta || dosleep
-	    || standby) {
+	if (dosleep || standby)
 		fd = open(APMDEV, O_RDWR);
-		bioscall_available = 1;
-	} else if ((fd = open(APMDEV, O_RDWR)) >= 0)
-		bioscall_available = 1;
 	else
 		fd = open(APMDEV, O_RDONLY);
 	if (fd == -1)
 		err(1, "can't open %s", APMDEV);
-	if (enable != -1)
-		apm_enable(fd, enable);
-	if (haltcpu != -1)
-		apm_haltcpu(fd, haltcpu);
-	if (delta)
-		apm_set_timer(fd, delta);
 	if (dosleep)
 		apm_suspend(fd);
 	else if (standby)
 		apm_standby(fd);
-	else if (delta == 0) {
+	else {
 		struct apm_info info;
 
 		apm_getinfo(fd, &info);
 		if (all_info)
-			print_all_info(fd, &info, bioscall_available);
+			print_all_info(fd, &info);
 		if (ac_status)
 			printf("%d\n", info.ai_acline);
 		if (batt_status)
 			printf("%d\n", info.ai_batt_stat);
 		if (batt_life)
 			printf("%d\n", info.ai_batt_life);
-		if (apm_status)
-			printf("%d\n", info.ai_status);
 		if (batt_time)
 			printf("%d\n", info.ai_batt_time);
-		if (display != -1)
-			apm_display(fd, display);
 	}
 	close(fd);
 	exit(0);