/* * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2026 Abdelkader Boudih * * Apple EFI Firmware Properties driver for DragonFly BSD. * * Discovers Apple-specific ACPI structures on Macs: * - Enumerates Apple SSDTs (SmcDppt, PcieTbt, Sdxc, etc.) * - Evaluates OSDW (macOS detection flag) * - Walks namespace for _DSM methods using Apple's DTGP UUID * - Extracts device properties and exposes via sysctl */ #include "apple_fw.h" #include #define _COMPONENT ACPI_OEM ACPI_MODULE_NAME("APPLE_FW") static int apple_fw_identify(driver_t *, device_t); static int apple_fw_probe(device_t); static int apple_fw_attach(device_t); static int apple_fw_detach(device_t); static void apple_fw_enumerate_ssdts(device_t); static void apple_fw_eval_osdw(device_t); static void apple_fw_fixup_osys(device_t); static device_method_t apple_fw_methods[] = { DEVMETHOD(device_identify, apple_fw_identify), DEVMETHOD(device_probe, apple_fw_probe), DEVMETHOD(device_attach, apple_fw_attach), DEVMETHOD(device_detach, apple_fw_detach), DEVMETHOD_END }; static driver_t apple_fw_driver = { "apple_fw", apple_fw_methods, sizeof(struct apple_fw_softc), .gpri = KOBJ_GPRI_ACPI }; static devclass_t apple_fw_devclass; DRIVER_MODULE(apple_fw, acpi, apple_fw_driver, apple_fw_devclass, NULL, NULL); MODULE_DEPEND(apple_fw, acpi, 1, 1, 1); MODULE_VERSION(apple_fw, 1); /* * Check if running on Apple EFI firmware by examining the FADT OEM ID. */ static int apple_fw_is_apple(void) { ACPI_TABLE_HEADER hdr; ACPI_STATUS status; status = AcpiGetTableHeader(ACPI_SIG_FADT, 0, &hdr); if (ACPI_FAILURE(status)) return (0); return (strncmp(hdr.OemId, "APPLE ", ACPI_OEM_ID_SIZE) == 0); } /* * Tag value for our synthetic child -- used by probe to distinguish * the device we create from real ACPI-enumerated devices. */ #define DEV_APPLE_FW(x) \ (acpi_get_magic(x) == (uintptr_t)&apple_fw_devclass) static int apple_fw_identify(driver_t *driver, device_t parent) { device_t child; /* Don't re-add on bus rescan */ if (device_find_child(parent, "apple_fw", -1) != NULL) return (0); if (!apple_fw_is_apple()) return (ENXIO); child = BUS_ADD_CHILD(parent, parent, 0, "apple_fw", -1); if (child != NULL) acpi_set_magic(child, (uintptr_t)&apple_fw_devclass); return (0); } static int apple_fw_probe(device_t dev) { char *product, *biosver; char desc[128]; if (acpi_disabled("apple_fw")) return (ENXIO); /* Only match the synthetic child we tagged in identify */ if (!DEV_APPLE_FW(dev)) return (ENXIO); product = kgetenv("smbios.system.product"); biosver = kgetenv("smbios.bios.version"); ksnprintf(desc, sizeof(desc), "Apple %s EFI Firmware %s", product, biosver); device_set_desc_copy(dev, desc); kfreeenv(product); kfreeenv(biosver); return (0); } static int apple_fw_attach(device_t dev) { struct apple_fw_softc *sc = device_get_softc(dev); int darwin_osi = 1; sc->sc_dev = dev; lockinit(&sc->sc_lock, "apple_fw", 0, LK_CANRECURSE); /* Enumerate Apple-specific SSDTs */ apple_fw_enumerate_ssdts(dev); /* * If the Darwin OSI tunable is enabled but the early path * didn't run (module loaded late), fix up OSYS ourselves. * If the tunable is disabled, the user opted out -- skip. */ TUNABLE_INT_FETCH("hw.acpi.apple_darwin_osi", &darwin_osi); apple_fw_eval_osdw(dev); if (darwin_osi && sc->sc_osdw == 0) apple_fw_fixup_osys(dev); /* Discover _DSM device properties via DTGP */ apple_fw_discover_dsm_devices(dev); /* Register sysctl tree */ apple_fw_sysctl_init(dev); return (0); } static int apple_fw_detach(device_t dev) { struct apple_fw_softc *sc = device_get_softc(dev); lockuninit(&sc->sc_lock); return (0); } /* * Fix up OSYS when Darwin OSI was not installed before AcpiLoadTables. * * Install the Darwin interface (affects future _OSI queries), then * re-evaluate PINI which re-checks _OSI and sets OSYS=0x2710. * If PINI is not present, write OSYS directly via the namespace. */ #define APPLE_OSYS_DARWIN 0x2710 static void apple_fw_fixup_osys(device_t dev) { struct apple_fw_softc *sc = device_get_softc(dev); ACPI_STATUS status; /* Install Darwin so future _OSI("Darwin") calls return true */ AcpiInstallInterface("Darwin"); /* Try re-evaluating PINI (Apple's _OSI->OSYS dispatcher) */ status = AcpiEvaluateObject(NULL, "\\PINI", NULL, NULL); if (ACPI_SUCCESS(status)) { apple_fw_eval_osdw(dev); if (sc->sc_osdw != 0) { device_printf(dev, "Darwin OSI fixup via PINI\n"); return; } } /* PINI missing or didn't help -- write OSYS directly */ { ACPI_HANDLE handle; ACPI_NAMESPACE_NODE *node; ACPI_OPERAND_OBJECT *obj; status = AcpiGetHandle(NULL, "\\OSYS", &handle); if (ACPI_FAILURE(status)) { device_printf(dev, "Darwin OSI fixup failed: no \\OSYS\n"); return; } node = AcpiNsValidateHandle(handle); if (node == NULL) return; obj = AcpiNsGetAttachedObject(node); if (obj != NULL && obj->Common.Type == ACPI_TYPE_INTEGER) { obj->Integer.Value = APPLE_OSYS_DARWIN; apple_fw_eval_osdw(dev); device_printf(dev, "Darwin OSI fixup via OSYS poke\n"); } } } /* * Enumerate all SSDT tables with OEM ID "APPLE". */ static void apple_fw_enumerate_ssdts(device_t dev) { struct apple_fw_softc *sc = device_get_softc(dev); ACPI_TABLE_HEADER *table; ACPI_STATUS status; uint32_t instance; int n; sc->sc_ssdt_count = 0; for (instance = 1; instance <= 128; instance++) { status = AcpiGetTable(ACPI_SIG_SSDT, instance, &table); if (ACPI_FAILURE(status)) break; /* Only catalog Apple SSDTs */ if (strncmp(table->OemId, "APPLE ", ACPI_OEM_ID_SIZE) != 0) continue; n = sc->sc_ssdt_count; if (n >= APPLE_FW_MAX_SSDTS) break; memcpy(sc->sc_ssdts[n].oem_table_id, table->OemTableId, ACPI_OEM_TABLE_ID_SIZE); sc->sc_ssdts[n].oem_table_id[ACPI_OEM_TABLE_ID_SIZE] = '\0'; sc->sc_ssdt_count++; } } /* * Evaluate the OSDW method. Returns 1 if the firmware thinks macOS is * running (OSYS == 0x2710), 0 otherwise. */ static void apple_fw_eval_osdw(device_t dev) { struct apple_fw_softc *sc = device_get_softc(dev); UINT32 val; sc->sc_osdw = 0; if (ACPI_SUCCESS(acpi_GetInteger(NULL, "OSDW", &val))) sc->sc_osdw = (int)val; }