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.
This commit is contained in:
mia soweli 2023-06-04 13:52:05 +00:00
parent 728cb9011f
commit 2531938269
4 changed files with 24 additions and 198 deletions

View file

@ -3,7 +3,6 @@
# and optionally reboot # and optionally reboot
rfork en rfork en
reboot=no reboot=no
scram=no
bootf=() bootf=()
if(~ $1 -r){ if(~ $1 -r){
reboot=yes reboot=yes
@ -35,12 +34,6 @@ s=`{awk '/^sd./ && /nvme/ {print substr($1,3,1)}' <'#S/sdctl' >[2]/dev/null}
# for scram, don't scram other systems # for scram, don't scram other systems
bind -b '#P' /dev >[2]/dev/null 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) # halting (binaries we run can't be on the fs we're halting)
ramfs ramfs
@ -52,13 +45,18 @@ cp /bin/ns /tmp
cp /bin/rc /tmp cp /bin/rc /tmp
cp /bin/sed /tmp cp /bin/sed /tmp
cp /bin/sleep /tmp cp /bin/sleep /tmp
cp /bin/scram /tmp
cp /bin/test /tmp cp /bin/test /tmp
if(~ $#bootf 1){ if(~ $#bootf 1){
if(! cp $bootf /tmp/bootf) if(! cp $bootf /tmp/bootf)
exit 'failed to copy kernel' exit 'failed to copy kernel'
bootf=/bin/bootf bootf=/bin/bootf
} }
if not {
mkdir /tmp/aux
cp /bin/aux/acpi /tmp/aux
cp /bin/scram /tmp
}
bind /tmp /rc bind /tmp /rc
bind /tmp /bin bind /tmp /bin
@ -86,10 +84,7 @@ fn x {
echo reboot $bootf >'#c/reboot' echo reboot $bootf >'#c/reboot'
} }
if not { if not {
if (test -e /dev/pmctl) scram
echo power off >>/dev/pmctl
if (~ $scram yes)
scram
echo 'It''s now safe to turn off your computer' echo 'It''s now safe to turn off your computer'
} }
} }

5
rc/bin/scram Executable file
View file

@ -0,0 +1,5 @@
#!/bin/rc
if(test -e /dev/pmctl)
echo power off >>/dev/pmctl
aux/acpi -H

View file

@ -49,14 +49,18 @@ kernel directly instead of returning to the system rom. (see
.IR cons (3)). .IR cons (3)).
.PP .PP
.I Scram .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 .SH SOURCE
.B /rc/bin/fshalt .B /rc/bin/fshalt
.br .br
.B /rc/bin/reboot .B /rc/bin/reboot
.br .br
.B /sys/src/cmd/scram.c .B /rc/bin/scram
.SH SEE ALSO .SH SEE ALSO
.IR acpi (8),
.IR cons (3), .IR cons (3),
.IR reboot (8) .IR reboot (8)
.SH BUGS .SH BUGS
@ -65,7 +69,12 @@ after invoking bare
.IR fshalt . .IR fshalt .
.I Scram .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 .SH HISTORY
.I Scram .I Scram
first appeared in 9front (May, 2011). first appeared in 9front (May, 2011).

View file

@ -1,183 +0,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");
}