ref: 25319382697878e01b9949afb33fcc6f4c4e6e1d
parent: 728cb9011f9612e969ec8747aa1de2a30959c38a
author: mia soweli <inbox@tachibana-labs.org>
date: Sun Jun 4 09:52:05 EDT 2023
scram: → /rc/bin/scram no need for scram to be a c program and duplicate the acpi shutdown code. try writing power off to /dev/pmctl or fall back to the new -H flag for aux/acpi.
--- a/rc/bin/fshalt
+++ b/rc/bin/fshalt
@@ -3,7 +3,6 @@
# and optionally reboot
rfork en
reboot=no
-scram=no
bootf=()
if(~ $1 -r){
reboot=yes
@@ -35,12 +34,6 @@
# for scram, don't scram other systems
bind -b '#P' /dev >[2]/dev/null
-if(! ~ $reboot yes){
- if(test -e '#P'/apm)
- scram=yes
- if(test -e '#P'/acpitbls -a -e '#P'/iow)
- scram=yes
-}
# halting (binaries we run can't be on the fs we're halting)
ramfs
@@ -52,7 +45,6 @@
cp /bin/rc /tmp
cp /bin/sed /tmp
cp /bin/sleep /tmp
-cp /bin/scram /tmp
cp /bin/test /tmp
if(~ $#bootf 1){
if(! cp $bootf /tmp/bootf)
@@ -59,6 +51,12 @@
exit 'failed to copy kernel'
bootf=/bin/bootf
}
+if not {
+ mkdir /tmp/aux
+ cp /bin/aux/acpi /tmp/aux
+ cp /bin/scram /tmp
+}
+
bind /tmp /rc
bind /tmp /bin
@@ -86,10 +84,7 @@
echo reboot $bootf >'#c/reboot'
}
if not {
- if (test -e /dev/pmctl)
- echo power off >>/dev/pmctl
- if (~ $scram yes)
- scram
+ scram
echo 'It''s now safe to turn off your computer'
}
}
--- /dev/null
+++ b/rc/bin/scram
@@ -1,0 +1,5 @@
+#!/bin/rc
+if(test -e /dev/pmctl)
+ echo power off >>/dev/pmctl
+
+aux/acpi -H
--- a/sys/man/8/fshalt
+++ b/sys/man/8/fshalt
@@ -49,14 +49,18 @@
.IR cons (3)).
.PP
.I Scram
-shuts down the machine it is invoked on.
+shuts down the machine it is invoked on by writing
+.I power off
+to
+.BR /dev/pmctl .
.SH SOURCE
.B /rc/bin/fshalt
.br
.B /rc/bin/reboot
.br
-.B /sys/src/cmd/scram.c
+.B /rc/bin/scram
.SH SEE ALSO
+.IR acpi (8),
.IR cons (3),
.IR reboot (8)
.SH BUGS
@@ -65,7 +69,12 @@
.IR fshalt .
.I Scram
-is limited to the PC and requires APM or ACPI.
+falls back to trying
+.I aux/acpi
+if writing to
+.B /dev/pmctl
+fails.
+
.SH HISTORY
.I Scram
first appeared in 9front (May, 2011).
--- a/sys/src/cmd/scram.c
+++ /dev/null
@@ -1,183 +1,0 @@
-#include <u.h>
-#include </386/include/ureg.h>
-#include <libc.h>
-#include <aml.h>
-
-int fd, iofd;
-struct Ureg u;
-ulong PM1a_CNT_BLK, PM1b_CNT_BLK, SLP_TYPa, SLP_TYPb;
-ulong GPE0_BLK, GPE1_BLK, GPE0_BLK_LEN, GPE1_BLK_LEN;
-enum {
- SLP_EN = 0x2000,
- SLP_TM = 0x1c00,
-};
-
-typedef struct Tbl Tbl;
-struct Tbl {
- uchar sig[4];
- uchar len[4];
- uchar rev;
- uchar csum;
- uchar oemid[6];
- uchar oemtid[8];
- uchar oemrev[4];
- uchar cid[4];
- uchar crev[4];
- uchar data[];
-};
-
-enum {
- Tblsz = 4+4+1+1+6+8+4+4+4,
-};
-
-static ulong
-get32(uchar *p){
- return p[3]<<24 | p[2]<<16 | p[1]<<8 | p[0];
-}
-
-void
-apm(void)
-{
- seek(fd, 0, 0);
- if(write(fd, &u, sizeof u) < 0)
- sysfatal("write: %r");
- seek(fd, 0, 0);
- if(read(fd, &u, sizeof u) < 0)
- sysfatal("read: %r");
- if(u.flags & 1)
- sysfatal("apm: %lux", (u.ax>>8) & 0xFF);
-}
-
-int
-loadacpi(void)
-{
- void *r, **rr;
- ulong l;
- Tbl *t;
- int n;
-
- amlinit();
- for(;;){
- t = malloc(sizeof(*t));
- if((n = readn(fd, t, Tblsz)) <= 0)
- break;
- if(n != Tblsz)
- return -1;
- l = get32(t->len);
- if(l < Tblsz)
- return -1;
- l -= Tblsz;
- t = realloc(t, sizeof(*t) + l);
- if(readn(fd, t->data, l) != l)
- return -1;
- if(memcmp("DSDT", t->sig, 4) == 0){
- amlintmask = (~0ULL) >> (t->rev <= 1)*32;
- amlload(t->data, l);
- }
- else if(memcmp("SSDT", t->sig, 4) == 0)
- amlload(t->data, l);
- else if(memcmp("FACP", t->sig, 4) == 0){
- PM1a_CNT_BLK = get32(((uchar*)t) + 64);
- PM1b_CNT_BLK = get32(((uchar*)t) + 68);
- GPE0_BLK = get32(((uchar*)t) + 80);
- GPE1_BLK = get32(((uchar*)t) + 84);
- GPE0_BLK_LEN = *(((uchar*)t) + 92);
- GPE1_BLK_LEN = *(((uchar*)t) + 93);
- }
- }
- if(amleval(amlwalk(amlroot, "_S5"), "", &r) < 0)
- return -1;
- if(amltag(r) != 'p' || amllen(r) < 2)
- return -1;
- rr = amlval(r);
- SLP_TYPa = amlint(rr[0]);
- SLP_TYPb = amlint(rr[1]);
- return 0;
-}
-
-void
-outw(long addr, ushort val)
-{
- uchar buf[2];
-
- if(addr == 0)
- return;
- buf[0] = val;
- buf[1] = val >> 8;
- pwrite(iofd, buf, 2, addr);
-}
-
-void
-wirecpu0(void)
-{
- char buf[128];
- int ctl;
-
- snprint(buf, sizeof(buf), "/proc/%d/ctl", getpid());
- if((ctl = open(buf, OWRITE)) < 0)
- return;
- write(ctl, "wired 0", 7);
- close(ctl);
-}
-
-void
-main(void)
-{
- int n;
-
- wirecpu0();
-
- if((fd = open("/dev/apm", ORDWR)) < 0)
- if((fd = open("#P/apm", ORDWR)) < 0)
- goto tryacpi;
-
- u.ax = 0x530E;
- u.bx = 0x0000;
- u.cx = 0x0102;
- apm();
- u.ax = 0x5307;
- u.bx = 0x0001;
- u.cx = 0x0003;
- apm();
-
-tryacpi:
- if((fd = open("/dev/acpitbls", OREAD)) < 0)
- if((fd = open("#P/acpitbls", OREAD)) < 0)
- goto fail;
- if((iofd = open("/dev/iow", OWRITE)) < 0)
- if((iofd = open("#P/iow", OWRITE)) < 0)
- goto fail;
- if(loadacpi() < 0)
- goto fail;
-
- /* disable GPEs */
- for(n = 0; GPE0_BLK > 0 && n < GPE0_BLK_LEN/2; n += 2){
- outw(GPE0_BLK + GPE0_BLK_LEN/2 + n, 0); /* EN */
- outw(GPE0_BLK + n, 0xffff); /* STS */
- }
- for(n = 0; GPE1_BLK > 0 && n < GPE1_BLK_LEN/2; n += 2){
- outw(GPE1_BLK + GPE1_BLK_LEN/2 + n, 0); /* EN */
- outw(GPE1_BLK + n, 0xffff); /* STS */
- }
-
- outw(PM1a_CNT_BLK, ((SLP_TYPa << 10) & SLP_TM) | SLP_EN);
- outw(PM1b_CNT_BLK, ((SLP_TYPb << 10) & SLP_TM) | SLP_EN);
- sleep(100);
-
- /*
- * The SetSystemSleeping() example from the ACPI spec
- * writes the same value in both registers. But Linux/BSD
- * write distinct values from the _Sx package (like the
- * code above). The _S5 package on a HP DC5700 is
- * Package(0x2){0x0, 0x7} and writing SLP_TYPa of 0 to
- * PM1a_CNT_BLK seems to have no effect but 0x7 seems
- * to work fine. So trying the following as a last effort.
- */
- SLP_TYPa |= SLP_TYPb;
- outw(PM1a_CNT_BLK, ((SLP_TYPa << 10) & SLP_TM) | SLP_EN);
- outw(PM1b_CNT_BLK, ((SLP_TYPa << 10) & SLP_TM) | SLP_EN);
- sleep(100);
-
-fail:
- exits("scram");
-}