>From 2be6b5cab503e4358d60b4d97d1705cbf06bdf44 Mon Sep 17 00:00:00 2001 From: Damien Zammit Date: Wed, 21 Nov 2018 04:17:33 -0500 Subject: [PATCH 2/3] Add shutdown RPC && ACPI specific disappear routine --- Makefile | 3 +- hurd/hurd_types.defs | 18 +++++ hurd/hurd_types.h | 1 + hurd/shutdown.defs | 33 +++++++++ shutdown/Makefile | 28 +++++++ shutdown/acpi_shutdown.c | 62 ++++++++++++++++ shutdown/acpi_shutdown.h | 18 +++++ shutdown/mig-mutate.h | 8 ++ shutdown/shutdown.c | 153 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 323 insertions(+), 1 deletion(-) create mode 100644 hurd/shutdown.defs create mode 100644 shutdown/Makefile create mode 100644 shutdown/acpi_shutdown.c create mode 100644 shutdown/acpi_shutdown.h create mode 100644 shutdown/mig-mutate.h create mode 100644 shutdown/shutdown.c diff --git a/Makefile b/Makefile index aa4ddc5a..f1d10c35 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,8 @@ prog-subdirs = auth proc exec term \ devnode \ eth-multiplexer \ pci-arbiter \ - acpi + acpi \ + shutdown ifeq ($(HAVE_SUN_RPC),yes) prog-subdirs += nfs nfsd diff --git a/hurd/hurd_types.defs b/hurd/hurd_types.defs index 0e9b990e..f0d1a351 100644 --- a/hurd/hurd_types.defs +++ b/hurd/hurd_types.defs @@ -314,6 +314,24 @@ destructor: PCI_DESTRUCTOR #endif ; +/* Shutdown */ +type shutdown_t = mach_port_copy_send_t +#ifdef SHUTDOWN_INTRAN +intran: SHUTDOWN_INTRAN +intranpayload: SHUTDOWN_INTRAN_PAYLOAD +#else +#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT +intranpayload: shutdown_t HURD_DEFAULT_PAYLOAD_TO_PORT +#endif +#endif +#ifdef SHUTDOWN_OUTTRAN +outtran: SHUTDOWN_OUTTRAN +#endif +#ifdef SHUTDOWN_DESTRUCTOR +destructor: SHUTDOWN_DESTRUCTOR +#endif +; + type proccoll_t = mach_port_copy_send_t; type sreply_port_t = MACH_MSG_TYPE_MAKE_SEND_ONCE | polymorphic diff --git a/hurd/hurd_types.h b/hurd/hurd_types.h index a77a9e43..bc6b618b 100644 --- a/hurd/hurd_types.h +++ b/hurd/hurd_types.h @@ -52,6 +52,7 @@ typedef mach_port_t interrupt_t; typedef mach_port_t proccoll_t; typedef mach_port_t ctty_t; typedef mach_port_t pci_t; +typedef mach_port_t shutdown_t; #include /* Defines `error_t'. */ diff --git a/hurd/shutdown.defs b/hurd/shutdown.defs new file mode 100644 index 00000000..b2ceb751 --- /dev/null +++ b/hurd/shutdown.defs @@ -0,0 +1,33 @@ +/* Definitions for shutdown + Copyright (C) 2018 Free Software Foundation, Inc. + +This file is part of the GNU Hurd. + +The GNU Hurd 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; either version 2, or (at your option) +any later version. + +The GNU Hurd is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with the GNU Hurd; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +subsystem shutdown 40000; + +#include + +#ifdef SHUTDOWN_IMPORTS +SHUTDOWN_IMPORTS +#endif + +/* + * Shut down the computer + */ +routine shutdown ( + server : shutdown_t +); diff --git a/shutdown/Makefile b/shutdown/Makefile new file mode 100644 index 00000000..ced79702 --- /dev/null +++ b/shutdown/Makefile @@ -0,0 +1,28 @@ +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 2008 Free Software Foundation, Inc. +# This file is part of the GNU Hurd. +# +# The GNU Hurd 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; either version 2, or (at your option) +# any later version. +# +# The GNU Hurd is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the GNU Hurd; see the file COPYING. If not, write to +# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + +dir := shutdown +makemode := server + +SRCS = shutdown.c acpi_shutdown.c +HURDLIBS = ports shouldbeinlibc trivfs +target = shutdown +MIGSTUBS = shutdownServer.o +MIGSFLAGS = -imacros $(srcdir)/mig-mutate.h +OBJS = $(SRCS:.c=.o) $(MIGSTUBS) + +include ../Makeconf diff --git a/shutdown/acpi_shutdown.c b/shutdown/acpi_shutdown.c new file mode 100644 index 00000000..af9b15d4 --- /dev/null +++ b/shutdown/acpi_shutdown.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include +#include "acpi_shutdown.h" + +void disappear_via_acpi(void) +{ + uint16_t i, pm1a_ctl, smi_cmd; + uint8_t regbuf[2], acpi_en; + FILE *facp; + + /* Open the ACPI FADT table */ + facp = fopen(SERVERS_ACPI_FADT, "r"); + if (!facp) + exit(errno); + + /* Grab value to write to SMI_CMD to enable ACPI */ + fseek(facp, SMI_EN_OFFSET, SEEK_SET); + fread(&acpi_en, 1, 1, facp); + + /* Grab SMI_CMD I/O port */ + fseek(facp, SMI_CMD_OFFSET, SEEK_SET); + fread(regbuf, 2, 1, facp); + smi_cmd = (uint16_t)regbuf[0] | + ((uint16_t)regbuf[1] << 8); + + /* Grab PM1a Control I/O port */ + fseek(facp, PM1A_CTL_OFFSET, SEEK_SET); + fread(regbuf, 2, 1, facp); + pm1a_ctl = (uint16_t)regbuf[0] | + ((uint16_t)regbuf[1] << 8); + + /* Close the ACPI FADT table */ + fclose(facp); + + /* Get I/O permissions */ + if (ioperm(0, 0xffff, 1)) { + mach_print("EPERM on ioperm()\n"); + return; + } + + /* Enable ACPI */ + outb(acpi_en, smi_cmd); + for (i = 0; i < 300; i++) + { + if ( (inw(pm1a_ctl) & SCI_EN) == SCI_EN) + break; + } + + /* Kill machine */ + + /* try sleep state 5 first */ + outw(SLP_TYP5 | SLP_EN, pm1a_ctl); + + /* if we reach here then above did not work */ + outw(SLP_TYP0 | SLP_EN, pm1a_ctl); + + /* Never reached */ +} diff --git a/shutdown/acpi_shutdown.h b/shutdown/acpi_shutdown.h new file mode 100644 index 00000000..50b7f1f6 --- /dev/null +++ b/shutdown/acpi_shutdown.h @@ -0,0 +1,18 @@ +#ifndef _ACPI_SHUTDOWN_H_ +#define _ACPI_SHUTDOWN_H_ + +#include + +#define _SERVERS_ACPI _SERVERS "/acpi/tables" +#define SERVERS_ACPI_FADT _SERVERS_ACPI "/FACP" +#define SLP_TYP0 (0x0 << 10) +#define SLP_TYP5 (0x5 << 10) +#define SLP_EN (0x1 << 13) +#define SCI_EN 1 +#define SMI_CMD_OFFSET 12 +#define SMI_EN_OFFSET 16 +#define PM1A_CTL_OFFSET 28 + +void disappear_via_acpi(void); + +#endif diff --git a/shutdown/mig-mutate.h b/shutdown/mig-mutate.h new file mode 100644 index 00000000..9eaf3db0 --- /dev/null +++ b/shutdown/mig-mutate.h @@ -0,0 +1,8 @@ +#define SHUTDOWN_INTRAN \ + trivfs_protid_t trivfs_begin_using_protid (shutdown_t) +#define SHUTDOWN_INTRAN_PAYLOAD \ + trivfs_protid_t trivfs_begin_using_protid_payload +#define SHUTDOWN_DESTRUCTOR \ + trivfs_end_using_protid (trivfs_protid_t) +#define SHUTDOWN_IMPORTS \ + import "libtrivfs/mig-decls.h"; diff --git a/shutdown/shutdown.c b/shutdown/shutdown.c new file mode 100644 index 00000000..413b5148 --- /dev/null +++ b/shutdown/shutdown.c @@ -0,0 +1,153 @@ +/* + Copyright (C) 2018 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd 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; either version 2, or (at your option) + any later version. + + The GNU Hurd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + * This program is a translator that implements an RPC to halt the pc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acpi_shutdown.h" +#include "shutdown_S.h" + +/* Port bucket we service requests on. */ +struct port_bucket *port_bucket; + +/* Trivfs hooks. */ +int trivfs_fstype = FSTYPE_MISC; +int trivfs_fsid = 0; +int trivfs_support_read = 0; +int trivfs_support_write = 0; +int trivfs_support_exec = 0; +int trivfs_allow_open = O_READ | O_WRITE; + +/* Our port classes. */ +struct port_class *trivfs_protid_class; +struct port_class *trivfs_control_class; + +kern_return_t +S_shutdown(trivfs_protid_t server) +{ + mach_print ("YAY RPC\n"); + disappear_via_acpi(); + return 0; +} + +static int +shutdown_demuxer (mach_msg_header_t *inp, + mach_msg_header_t *outp) +{ + mig_routine_t routine; + if ((routine = shutdown_server_routine (inp)) || + (routine = NULL, trivfs_demuxer (inp, outp))) + { + if (routine) + (*routine) (inp, outp); + return TRUE; + } + else + return FALSE; +} + +void +trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st) +{ +} + +error_t +trivfs_goaway (struct trivfs_control *fsys, int flags) +{ + int count; + + /* Stop new requests. */ + ports_inhibit_class_rpcs (trivfs_control_class); + ports_inhibit_class_rpcs (trivfs_protid_class); + + /* Are there any extant user ports for the /servers/password file? */ + count = ports_count_class (trivfs_protid_class); + if (count > 0 && !(flags & FSYS_GOAWAY_FORCE)) + { + /* We won't go away, so start things going again... */ + ports_enable_class (trivfs_protid_class); + ports_resume_class_rpcs (trivfs_control_class); + ports_resume_class_rpcs (trivfs_protid_class); + + return EBUSY; + } + + exit (0); +} + + +int +main (int argc, char *argv[]) +{ + error_t err; + mach_port_t bootstrap; + struct trivfs_control *fsys; + + task_get_bootstrap_port (mach_task_self (), &bootstrap); + if (bootstrap == MACH_PORT_NULL) + error (1, 0, "must be started as a translator"); + + err = trivfs_add_port_bucket (&port_bucket); + if (err) + error (1, 0, "error creating port bucket"); + + err = trivfs_add_control_port_class (&trivfs_control_class); + if (err) + error (1, 0, "error creating control port class"); + + err = trivfs_add_protid_port_class (&trivfs_protid_class); + if (err) + error (1, 0, "error creating protid port class"); + + /* Reply to our parent. */ + err = trivfs_startup (bootstrap, 0, + trivfs_control_class, port_bucket, + trivfs_protid_class, port_bucket, + &fsys); + mach_port_deallocate (mach_task_self (), bootstrap); + if (err) + error (3, err, "Contacting parent"); + + mach_print("Hello shutdown before ports loop\n"); + + /* Launch. */ + do + ports_manage_port_operations_multithread (port_bucket, shutdown_demuxer, + 2 * 60 * 1000, + 10 * 60 * 1000, + 0); + while (1); + + return 0; +} -- 2.17.1