mirror of
git://git.9front.org/plan9front/plan9front
synced 2025-01-12 11:10:06 +00:00
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:
parent
728cb9011f
commit
2531938269
4 changed files with 24 additions and 198 deletions
|
@ -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
5
rc/bin/scram
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/rc
|
||||||
|
if(test -e /dev/pmctl)
|
||||||
|
echo power off >>/dev/pmctl
|
||||||
|
|
||||||
|
aux/acpi -H
|
|
@ -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).
|
||||||
|
|
|
@ -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");
|
|
||||||
}
|
|
Loading…
Reference in a new issue