From d5c70033d951782fde4a7df57a47c6eeca818a61 Mon Sep 17 00:00:00 2001
From: Ed Coyne <edcoyne@google.com>
Date: Tue, 23 Apr 2019 17:44:29 +0000
Subject: [PATCH] [system_updater] switch to using devmgr service to reboot.

devmgr is moving from a virtual device (/dev/misc/dmctl) to services,
one of these fuchsia.device.manager.Administrator provides the ability
to reboot now. Switch the updater to using this.

Issue: ZX-3403 # convert system_updater
Test: "fx ota" to astro.
Change-Id: I35032d046129dc3af5b84d36b2f0776df263a4cc
---
 garnet/go/src/amber/system_updater/BUILD.gn   |  1 +
 garnet/go/src/amber/system_updater/main.go    | 33 +++++++++++++++----
 .../system_updater/meta/system_updater.cmx    |  1 +
 .../devmgr/devcoordinator/coordinator.cpp     |  3 ++
 .../fuchsia-device-manager/administrator.fidl |  4 +++
 5 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/garnet/go/src/amber/system_updater/BUILD.gn b/garnet/go/src/amber/system_updater/BUILD.gn
index f32a68ac384..7c8bc0a85f8 100644
--- a/garnet/go/src/amber/system_updater/BUILD.gn
+++ b/garnet/go/src/amber/system_updater/BUILD.gn
@@ -18,6 +18,7 @@ go_library("lib") {
     "//sdk/fidl/fuchsia.amber($go_toolchain)",
     "//sdk/fidl/fuchsia.pkg($go_toolchain)",
     "//sdk/fidl/fuchsia.sys($go_toolchain)",
+    "//zircon/public/fidl/fuchsia-device-manager($go_toolchain)",
     "//zircon/public/fidl/fuchsia-io($go_toolchain)",
   ]
 }
diff --git a/garnet/go/src/amber/system_updater/main.go b/garnet/go/src/amber/system_updater/main.go
index 777e191aa50..f281652b437 100644
--- a/garnet/go/src/amber/system_updater/main.go
+++ b/garnet/go/src/amber/system_updater/main.go
@@ -10,8 +10,12 @@ import (
 	"os"
 	"path/filepath"
 	"time"
+	"syscall/zx"
+	"syscall/zx/fdio"
+	"syscall/zx/fidl"
 
 	"app/context"
+	devmgr "fidl/fuchsia/device/manager"
 	"syslog/logger"
 
 	"metrics"
@@ -136,17 +140,32 @@ func run() (err error) {
 
 	logger.Infof("system update complete, rebooting...")
 
-	dmctl, err := os.OpenFile("/dev/misc/dmctl", os.O_RDWR, os.ModePerm)
+	SendReboot()
+
+	return nil
+}
+
+func SendReboot() {
+	channel_local, channel_remote, err := zx.NewChannel(0)
 	if err != nil {
-		logger.Errorf("error forcing restart: %s", err)
+		logger.Errorf("error creating channel: %s", err)
+		return
 	}
-	defer dmctl.Close()
-	cmd := []byte("reboot")
-	if _, err := dmctl.Write(cmd); err != nil {
-		logger.Errorf("error writing to control socket: %s", err)
+
+	err = fdio.ServiceConnect(
+		"/svc/fuchsia.device.manager.Administrator", zx.Handle(channel_remote))
+	if err != nil {
+		logger.Errorf("error connecting to devmgr service: %s", err)
+		return
 	}
 
-	return nil
+	var administrator = devmgr.AdministratorInterface(
+		fidl.ChannelProxy{Channel: zx.Channel(channel_local)})
+	var status int32
+	status, err = administrator.Suspend(devmgr.SuspendFlagReboot)
+	if err != nil || status != 0 {
+		logger.Errorf("error sending restart to Administrator: %s status: %d", err, status)
+	}
 }
 
 type InitiatorValue struct {
diff --git a/garnet/go/src/amber/system_updater/meta/system_updater.cmx b/garnet/go/src/amber/system_updater/meta/system_updater.cmx
index 4bf13785a5b..c5468d61cf9 100644
--- a/garnet/go/src/amber/system_updater/meta/system_updater.cmx
+++ b/garnet/go/src/amber/system_updater/meta/system_updater.cmx
@@ -15,6 +15,7 @@
         "services": [
             "fuchsia.pkg.PackageResolver",
             "fuchsia.cobalt.LoggerFactory",
+            "fuchsia.device.manager.Administrator",
             "fuchsia.logger.LogSink",
             "fuchsia.process.Launcher"
         ]
diff --git a/zircon/system/core/devmgr/devcoordinator/coordinator.cpp b/zircon/system/core/devmgr/devcoordinator/coordinator.cpp
index 9072e297a19..3c604115a19 100644
--- a/zircon/system/core/devmgr/devcoordinator/coordinator.cpp
+++ b/zircon/system/core/devmgr/devcoordinator/coordinator.cpp
@@ -1649,6 +1649,9 @@ void Coordinator::InitOutgoingServices() {
     const auto& public_dir = outgoing_services_.public_dir();
 
     const auto admin = [this](zx::channel request) {
+        static_assert(fuchsia_device_manager_SUSPEND_FLAG_REBOOT == DEVICE_SUSPEND_FLAG_REBOOT);
+        static_assert(fuchsia_device_manager_SUSPEND_FLAG_POWEROFF == DEVICE_SUSPEND_FLAG_POWEROFF);
+
         static constexpr fuchsia_device_manager_Administrator_ops_t kOps = {
             .Suspend = [](void* ctx, uint32_t flags, fidl_txn_t* txn) {
                 static_cast<Coordinator*>(ctx)->Suspend(flags);
diff --git a/zircon/system/fidl/fuchsia-device-manager/administrator.fidl b/zircon/system/fidl/fuchsia-device-manager/administrator.fidl
index 272f22e6718..e9c926d2239 100644
--- a/zircon/system/fidl/fuchsia-device-manager/administrator.fidl
+++ b/zircon/system/fidl/fuchsia-device-manager/administrator.fidl
@@ -6,6 +6,10 @@ library fuchsia.device.manager;
 
 using zx;
 
+/// Check the DDK for all available flags.
+const uint32 SUSPEND_FLAG_REBOOT = 0xdcdc0100;
+const uint32 SUSPEND_FLAG_POWEROFF = 0xdcdc0200;
+
 /// Provides administration services for the device manager service and the device tree it controls.
 [Discoverable, Layout = "Simple"]
 protocol Administrator {
-- 
GitLab