]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/sleep/sleep.c
sleep: drop unneeded includes
[thirdparty/systemd.git] / src / sleep / sleep.c
index de1f6c7ec1f7893084655f4bd858649e06eb47b3..05d6e38ae1ff3914a0498bdc62f17f1a5137cddd 100644 (file)
@@ -7,11 +7,9 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
-#include <linux/fiemap.h>
 #include <poll.h>
-#include <sys/stat.h>
-#include <sys/types.h>
 #include <sys/timerfd.h>
+#include <sys/types.h>
 #include <sys/utsname.h>
 #include <unistd.h>
 
@@ -20,8 +18,8 @@
 #include "sd-id128.h"
 #include "sd-messages.h"
 
+#include "battery-capacity.h"
 #include "battery-util.h"
-#include "btrfs-util.h"
 #include "build.h"
 #include "bus-error.h"
 #include "bus-locator.h"
@@ -33,6 +31,7 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "format-util.h"
+#include "hibernate-util.h"
 #include "id128-util.h"
 #include "io-util.h"
 #include "json.h"
@@ -41,7 +40,7 @@
 #include "os-util.h"
 #include "parse-util.h"
 #include "pretty-print.h"
-#include "sleep-util.h"
+#include "sleep-config.h"
 #include "special.h"
 #include "stdio-util.h"
 #include "string-util.h"
@@ -52,7 +51,7 @@
 
 static SleepOperation arg_operation = _SLEEP_OPERATION_INVALID;
 
-static int write_efi_hibernate_location(const HibernateLocation *hibernate_location, bool required) {
+static int write_efi_hibernate_location(const HibernationDevice *hibernation_device, bool required) {
         int log_level = required ? LOG_ERR : LOG_DEBUG;
 
 #if ENABLE_EFI
@@ -65,27 +64,26 @@ static int write_efi_hibernate_location(const HibernateLocation *hibernate_locat
         struct utsname uts = {};
         int r, log_level_ignore = required ? LOG_WARNING : LOG_DEBUG;
 
-        assert(hibernate_location);
-        assert(hibernate_location->swap);
+        assert(hibernation_device);
 
         if (!is_efi_boot())
                 return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
                                       "Not an EFI boot, passing HibernateLocation via EFI variable is not possible.");
 
-        r = sd_device_new_from_devnum(&device, 'b', hibernate_location->devno);
+        r = sd_device_new_from_devnum(&device, 'b', hibernation_device->devno);
         if (r < 0)
                 return log_full_errno(log_level, r, "Failed to create sd-device object for '%s': %m",
-                                      hibernate_location->swap->path);
+                                      hibernation_device->path);
 
         r = sd_device_get_property_value(device, "ID_FS_UUID", &uuid_str);
         if (r < 0)
                 return log_full_errno(log_level, r, "Failed to get filesystem UUID for device '%s': %m",
-                                      hibernate_location->swap->path);
+                                      hibernation_device->path);
 
         r = sd_id128_from_string(uuid_str, &uuid);
         if (r < 0)
                 return log_full_errno(log_level, r, "Failed to parse ID_FS_UUID '%s' for device '%s': %m",
-                                      uuid_str, hibernate_location->swap->path);
+                                      uuid_str, hibernation_device->path);
 
         if (uname(&uts) < 0)
                 log_full_errno(log_level_ignore, errno, "Failed to get kernel info, ignoring: %m");
@@ -100,7 +98,7 @@ static int write_efi_hibernate_location(const HibernateLocation *hibernate_locat
 
         r = json_build(&v, JSON_BUILD_OBJECT(
                                JSON_BUILD_PAIR_UUID("uuid", uuid),
-                               JSON_BUILD_PAIR_UNSIGNED("offset", hibernate_location->offset),
+                               JSON_BUILD_PAIR_UNSIGNED("offset", hibernation_device->offset),
                                JSON_BUILD_PAIR_CONDITION(!isempty(uts.release), "kernelVersion", JSON_BUILD_STRING(uts.release)),
                                JSON_BUILD_PAIR_CONDITION(id, "osReleaseId", JSON_BUILD_STRING(id)),
                                JSON_BUILD_PAIR_CONDITION(image_id, "osReleaseImageId", JSON_BUILD_STRING(image_id)),
@@ -125,14 +123,6 @@ static int write_efi_hibernate_location(const HibernateLocation *hibernate_locat
 #endif
 }
 
-static int write_kernel_hibernate_location(const HibernateLocation *hibernate_location) {
-        assert(hibernate_location);
-        assert(hibernate_location->swap);
-        assert(IN_SET(hibernate_location->swap->type, SWAP_BLOCK, SWAP_FILE));
-
-        return write_resume_config(hibernate_location->devno, hibernate_location->offset, hibernate_location->swap->path);
-}
-
 static int write_mode(char **modes) {
         int r = 0;
 
@@ -176,6 +166,43 @@ static int write_state(FILE **f, char **states) {
         return r;
 }
 
+/* Return true if wakeup type is APM timer */
+static int check_wakeup_type(void) {
+        static const char dmi_object_path[] = "/sys/firmware/dmi/entries/1-0/raw";
+        uint8_t wakeup_type_byte, tablesize;
+        _cleanup_free_ char *buf = NULL;
+        size_t bufsize;
+        int r;
+
+        /* implementation via dmi/entries */
+        r = read_full_virtual_file(dmi_object_path, &buf, &bufsize);
+        if (r < 0)
+                return log_debug_errno(r, "Unable to read %s: %m", dmi_object_path);
+        if (bufsize < 25)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "Only read %zu bytes from %s (expected 25)",
+                                       bufsize, dmi_object_path);
+
+        /* index 1 stores the size of table */
+        tablesize = (uint8_t) buf[1];
+        if (tablesize < 25)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
+                                       "Table size less than the index[0x18] where waketype byte is available.");
+
+        wakeup_type_byte = (uint8_t) buf[24];
+        /* 0 is Reserved and 8 is AC Power Restored. As per table 12 in
+         * https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.4.0.pdf */
+        if (wakeup_type_byte >= 128)
+                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Expected value in range 0-127");
+
+        if (wakeup_type_byte == 3) {
+                log_debug("DMI BIOS System Information indicates wakeup type is APM Timer");
+                return true;
+        }
+
+        return false;
+}
+
 static int lock_all_homes(void) {
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
@@ -227,7 +254,7 @@ static int execute(
                 NULL
         };
 
-        _cleanup_(hibernate_location_freep) HibernateLocation *hibernate_location = NULL;
+        _cleanup_(hibernation_device_done) HibernationDevice hibernation_device = {};
         _cleanup_fclose_ FILE *f = NULL;
         char **modes, **states;
         int r;
@@ -254,24 +281,28 @@ static int execute(
         setvbuf(f, NULL, _IONBF, 0);
 
         /* Configure hibernation settings if we are supposed to hibernate */
-        if (!strv_isempty(modes)) {
+        if (sleep_operation_is_hibernation(operation)) {
                 bool resume_set;
 
-                r = find_hibernate_location(&hibernate_location);
+                r = find_suitable_hibernation_device(&hibernation_device);
                 if (r < 0)
                         return log_error_errno(r, "Failed to find location to hibernate to: %m");
                 resume_set = r > 0;
 
-                r = write_efi_hibernate_location(hibernate_location, !resume_set);
+                r = write_efi_hibernate_location(&hibernation_device, !resume_set);
                 if (!resume_set) {
                         if (r == -EOPNOTSUPP)
                                 return log_error_errno(r, "No valid 'resume=' option found, refusing to hibernate.");
                         if (r < 0)
                                 return r;
 
-                        r = write_kernel_hibernate_location(hibernate_location);
-                        if (r < 0)
+                        r = write_resume_config(hibernation_device.devno, hibernation_device.offset, hibernation_device.path);
+                        if (r < 0) {
+                                if (is_efi_boot())
+                                        (void) efi_set_variable(EFI_SYSTEMD_VARIABLE(HibernateLocation), NULL, 0);
+
                                 return log_error_errno(r, "Failed to prepare for hibernation: %m");
+                        }
                 }
 
                 r = write_mode(modes);
@@ -526,6 +557,7 @@ static int help(void) {
 }
 
 static int parse_argv(int argc, char *argv[]) {
+
         enum {
                 ARG_VERSION = 0x100,
         };
@@ -543,6 +575,7 @@ static int parse_argv(int argc, char *argv[]) {
 
         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
                 switch (c) {
+
                 case 'h':
                         return help();
 
@@ -554,6 +587,7 @@ static int parse_argv(int argc, char *argv[]) {
 
                 default:
                         assert_not_reached();
+
                 }
 
         if (argc - optind != 1)
@@ -569,7 +603,7 @@ static int parse_argv(int argc, char *argv[]) {
 }
 
 static int run(int argc, char *argv[]) {
-        _cleanup_(free_sleep_configp) SleepConfig *sleep_config = NULL;
+        _cleanup_(sleep_config_freep) SleepConfig *sleep_config = NULL;
         int r;
 
         log_setup();
@@ -610,6 +644,7 @@ static int run(int argc, char *argv[]) {
         default:
                 r = execute(sleep_config, arg_operation, NULL);
                 break;
+
         }
 
         return r;