acpi-fpdt: Use kernel fpdt parsing

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>
This commit is contained in:
Jeremy Linton 2022-11-07 23:31:30 -06:00
parent 09cd639a59
commit bc09c2d865
2 changed files with 39 additions and 0 deletions

4
TODO
View File

@ -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

View 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;