]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
acpi-fpdt: Use kernel fpdt parsing 25310/head
authorJeremy Linton <jlinton@redhat.com>
Tue, 8 Nov 2022 05:31:30 +0000 (23:31 -0600)
committerJeremy Linton <jlinton@redhat.com>
Tue, 15 Nov 2022 02:07:57 +0000 (20:07 -0600)
On some kernels/distros (RHEL/aarch64) /dev/mem is
turned off. This means that the ACPI FPDT data is
missing from systemd-analyze output when /dev/mem
fails to provide the boot times.

Instead recent kernels can export that data from
/sys/firmware/acpi/fpdt/boot/ entries. Use that
information if available first.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
TODO
src/shared/acpi-fpdt.c

diff --git a/TODO b/TODO
index 0b9f4da7f0842bc49ba3ed9a957810c04feb000e..9c30bfb30d8f902823b7af06079451fab96e1552 100644 (file)
--- a/TODO
+++ b/TODO
@@ -115,6 +115,10 @@ Deprecations and removals:
 
 * H2 2023: remove support for unmerged-usr
 
+* Remove /dev/mem ACPI FPDT parsing when /sys/firmware/acpi/fpdt is ubiquitous.
+  That requires distros to enable CONFIG_ACPI_FPDT, and have kernels v5.12 for
+  x86 and v6.2 for arm.
+
 Features:
 
 * sd-boot: add a new PE section .bls or so that carries a cpio with additional
index 668f6c3eee9b80bfd8f83c93b3cf559d4136ddb4..9f77997d5a59843a2e87449a68cbb70b8654f9f9 100644 (file)
@@ -61,6 +61,37 @@ struct acpi_fpdt_boot {
         uint64_t exit_services_exit;
 } _packed;
 
+/* /dev/mem is deprecated on many systems, try using /sys/firmware/acpi/fpdt parsing instead.
+ * This code requires kernel version 5.12 on x86 based machines or 6.2 for arm64 */
+static int acpi_get_boot_usec_kernel_parsed(usec_t *ret_loader_start, usec_t *ret_loader_exit) {
+        usec_t start, end;
+        int r;
+
+        r = read_timestamp_file("/sys/firmware/acpi/fpdt/boot/exitbootservice_end_ns", &end);
+        if (r < 0)
+                return r;
+
+        if (end == 0)
+                /* Non-UEFI compatible boot. */
+                return -ENODATA;
+
+        r = read_timestamp_file("/sys/firmware/acpi/fpdt/boot/bootloader_launch_ns", &start);
+        if (r < 0)
+                return r;
+
+        if (start == 0 || end < start)
+                return -EINVAL;
+        if (end > NSEC_PER_HOUR)
+                return -EINVAL;
+
+        if (ret_loader_start)
+                *ret_loader_start = start / 1000;
+        if (ret_loader_exit)
+                *ret_loader_exit = end / 1000;
+
+        return 0;
+}
+
 int acpi_get_boot_usec(usec_t *ret_loader_start, usec_t *ret_loader_exit) {
         _cleanup_free_ char *buf = NULL;
         struct acpi_table_header *tbl;
@@ -73,6 +104,10 @@ int acpi_get_boot_usec(usec_t *ret_loader_start, usec_t *ret_loader_exit) {
         struct acpi_fpdt_boot_header hbrec;
         struct acpi_fpdt_boot brec;
 
+        r = acpi_get_boot_usec_kernel_parsed(ret_loader_start, ret_loader_exit);
+        if (r != -ENOENT) /* fallback to /dev/mem hack only if kernel doesn't support the new sysfs files */
+                return r;
+
         r = read_full_virtual_file("/sys/firmware/acpi/tables/FPDT", &buf, &l);
         if (r < 0)
                 return r;