static vm_paddr_t sdt_search_rsdt(vm_paddr_t rsdt_paddr, const uint8_t *sig) { struct acpi_rsdt *rsdt; vm_paddr_t sdt_paddr = 0; int i, nent; if (rsdt_paddr == 0) { kprintf("sdt_search_rsdt: RSDT paddr == 0\n"); return 0; } rsdt = sdt_sdth_map(rsdt_paddr); if (rsdt == NULL) { kprintf("sdt_search_rsdt: can't map RSDT\n"); return 0; } if (memcmp(rsdt->rsdt_hdr.sdth_sig, ACPI_RSDT_SIG, ACPI_SDTH_SIGLEN) != 0) { kprintf("sdt_search_rsdt: not RSDT\n"); goto back; } if (rsdt->rsdt_hdr.sdth_rev != 1) { kprintf("sdt_search_rsdt: unknown RSDT revision %d\n", rsdt->rsdt_hdr.sdth_rev); } if (rsdt->rsdt_hdr.sdth_len < sizeof(rsdt->rsdt_hdr)) { kprintf("sdt_search_rsdt: invalid RSDT length %u\n", rsdt->rsdt_hdr.sdth_len); goto back; } nent = (rsdt->rsdt_hdr.sdth_len - sizeof(rsdt->rsdt_hdr)) / sizeof(rsdt->rsdt_ents[0]); for (i = 0; i < nent; ++i) { struct acpi_sdth *sdth; if (rsdt->rsdt_ents[i] == 0) continue; sdth = sdt_sdth_map(rsdt->rsdt_ents[i]); if (sdth != NULL) { int ret; ret = memcmp(sdth->sdth_sig, sig, ACPI_SDTH_SIGLEN); sdt_sdth_unmap(sdth); if (ret == 0) { sdt_paddr = rsdt->rsdt_ents[i]; break; } } } back: sdt_sdth_unmap(&rsdt->rsdt_hdr); return sdt_paddr; }
static vm_paddr_t sdt_search_rsdt(vm_paddr_t rsdt_paddr, const uint8_t *sig) { ACPI_TABLE_RSDT *rsdt; vm_paddr_t sdt_paddr = 0; int i, nent; if (rsdt_paddr == 0) { kprintf("sdt_search_rsdt: RSDT paddr == 0\n"); return 0; } rsdt = sdt_sdth_map(rsdt_paddr); if (rsdt == NULL) { kprintf("sdt_search_rsdt: can't map RSDT\n"); return 0; } if (memcmp(rsdt->Header.Signature, ACPI_SIG_RSDT, ACPI_NAME_SIZE) != 0) { kprintf("sdt_search_rsdt: not RSDT\n"); goto back; } if (rsdt->Header.Revision != 1) { kprintf("sdt_search_rsdt: unknown RSDT revision %d\n", rsdt->Header.Revision); } if (rsdt->Header.Length < sizeof(rsdt->Header)) { kprintf("sdt_search_rsdt: invalid RSDT length %u\n", rsdt->Header.Length); goto back; } nent = (rsdt->Header.Length - sizeof(rsdt->Header)) / sizeof(rsdt->TableOffsetEntry[0]); for (i = 0; i < nent; ++i) { ACPI_TABLE_HEADER *sdth; if (rsdt->TableOffsetEntry[i] == 0) continue; sdth = sdt_sdth_map(rsdt->TableOffsetEntry[i]); if (sdth != NULL) { int ret; ret = memcmp(sdth->Signature, sig, ACPI_NAME_SIZE); sdt_sdth_unmap(sdth); if (ret == 0) { sdt_paddr = rsdt->TableOffsetEntry[i]; break; } } } back: sdt_sdth_unmap(&rsdt->Header); return sdt_paddr; }
static vm_paddr_t sdt_search_xsdt(vm_paddr_t xsdt_paddr, const uint8_t *sig) { struct acpi_xsdt *xsdt; vm_paddr_t sdt_paddr = 0; int i, nent; if (xsdt_paddr == 0) { kprintf("sdt_search_xsdt: XSDT paddr == 0\n"); return 0; } xsdt = sdt_sdth_map(xsdt_paddr); if (xsdt == NULL) { kprintf("sdt_search_xsdt: can't map XSDT\n"); return 0; } if (memcmp(xsdt->xsdt_hdr.sdth_sig, ACPI_XSDT_SIG, ACPI_SDTH_SIGLEN) != 0) { kprintf("sdt_search_xsdt: not XSDT\n"); goto back; } if (xsdt->xsdt_hdr.sdth_rev != 1) { kprintf("sdt_search_xsdt: unsupported XSDT revision %d\n", xsdt->xsdt_hdr.sdth_rev); goto back; } nent = (xsdt->xsdt_hdr.sdth_len - sizeof(xsdt->xsdt_hdr)) / sizeof(xsdt->xsdt_ents[0]); for (i = 0; i < nent; ++i) { struct acpi_sdth *sdth; if (xsdt->xsdt_ents[i] == 0) continue; sdth = sdt_sdth_map(xsdt->xsdt_ents[i]); if (sdth != NULL) { int ret; ret = memcmp(sdth->sdth_sig, sig, ACPI_SDTH_SIGLEN); sdt_sdth_unmap(sdth); if (ret == 0) { sdt_paddr = xsdt->xsdt_ents[i]; break; } } } back: sdt_sdth_unmap(&xsdt->xsdt_hdr); return sdt_paddr; }
static int madt_lapic_probe(struct lapic_enumerator *e) { struct madt_lapic_probe_cbarg arg; struct acpi_madt *madt; int error; if (madt_phyaddr == 0) return ENXIO; madt = sdt_sdth_map(madt_phyaddr); KKASSERT(madt != NULL); bzero(&arg, sizeof(arg)); arg.lapic_addr = madt->madt_lapic_addr; error = madt_iterate_entries(madt, madt_lapic_probe_callback, &arg); if (!error) { if (arg.cpu_count == 0) { kprintf("madt_lapic_probe: no CPU is found\n"); error = EOPNOTSUPP; } if (arg.lapic_addr == 0) { kprintf("madt_lapic_probe: zero LAPIC address\n"); error = EOPNOTSUPP; } } sdt_sdth_unmap(&madt->madt_hdr); return error; }
static int madt_lapic_pass2(int bsp_apic_id) { struct acpi_madt *madt; struct madt_lapic_pass2_cbarg arg; int error; MADT_VPRINTF("BSP apic id %d\n", bsp_apic_id); KKASSERT(madt_phyaddr != 0); madt = sdt_sdth_map(madt_phyaddr); KKASSERT(madt != NULL); bzero(&arg, sizeof(arg)); arg.cpu = 1; arg.bsp_apic_id = bsp_apic_id; error = madt_iterate_entries(madt, madt_lapic_pass2_callback, &arg); if (error) panic("madt_iterate_entries(pass2) failed"); KKASSERT(arg.bsp_found); naps = arg.cpu - 1; /* exclude BSP */ sdt_sdth_unmap(&madt->madt_hdr); return 0; }
static vm_paddr_t madt_lapic_pass1(void) { struct acpi_madt *madt; vm_paddr_t lapic_addr; uint64_t lapic_addr64; int error; KKASSERT(madt_phyaddr != 0); madt = sdt_sdth_map(madt_phyaddr); KKASSERT(madt != NULL); MADT_VPRINTF("LAPIC address 0x%x, flags %#x\n", madt->madt_lapic_addr, madt->madt_flags); lapic_addr = madt->madt_lapic_addr; lapic_addr64 = 0; error = madt_iterate_entries(madt, madt_lapic_pass1_callback, &lapic_addr64); if (error) panic("madt_iterate_entries(pass1) failed"); if (lapic_addr64 != 0) { kprintf("ACPI MADT: 64bits lapic address 0x%lx\n", lapic_addr64); lapic_addr = lapic_addr64; } sdt_sdth_unmap(&madt->madt_hdr); return lapic_addr; }
static int madt_check(vm_paddr_t madt_paddr) { struct acpi_madt *madt; int error = 0; KKASSERT(madt_paddr != 0); madt = sdt_sdth_map(madt_paddr); KKASSERT(madt != NULL); /* * MADT in ACPI specification 1.0 - 4.0 */ if (madt->madt_hdr.sdth_rev < 1 || madt->madt_hdr.sdth_rev > 3) { kprintf("madt_check: unknown MADT revision %d\n", madt->madt_hdr.sdth_rev); } if (madt->madt_hdr.sdth_len < sizeof(*madt) - sizeof(madt->madt_ents)) { kprintf("madt_check: invalid MADT length %u\n", madt->madt_hdr.sdth_len); error = EINVAL; goto back; } back: sdt_sdth_unmap(&madt->madt_hdr); return error; }
static void fadt_probe(void) { struct acpi_fadt *fadt; vm_paddr_t fadt_paddr; enum intr_trigger trig; enum intr_polarity pola; int enabled = 1; char *env; fadt_paddr = sdt_search(ACPI_FADT_SIG); if (fadt_paddr == 0) { kprintf("fadt_probe: can't locate FADT\n"); return; } fadt = sdt_sdth_map(fadt_paddr); KKASSERT(fadt != NULL); /* * FADT in ACPI specification 1.0 - 4.0 */ if (fadt->fadt_hdr.sdth_rev < 1 || fadt->fadt_hdr.sdth_rev > 4) { kprintf("fadt_probe: unsupported FADT revision %d\n", fadt->fadt_hdr.sdth_rev); goto back; } if (fadt->fadt_hdr.sdth_len < sizeof(*fadt)) { kprintf("fadt_probe: invalid FADT length %u\n", fadt->fadt_hdr.sdth_len); goto back; } kgetenv_int("hw.acpi.sci.enabled", &enabled); if (!enabled) goto back; acpi_sci_irq = fadt->fadt_sci_int; env = kgetenv("hw.acpi.sci.trigger"); if (env == NULL) goto back; trig = INTR_TRIGGER_CONFORM; if (strcmp(env, "edge") == 0) trig = INTR_TRIGGER_EDGE; else if (strcmp(env, "level") == 0) trig = INTR_TRIGGER_LEVEL; kfreeenv(env); if (trig == INTR_TRIGGER_CONFORM) goto back; env = kgetenv("hw.acpi.sci.polarity"); if (env == NULL) goto back; pola = INTR_POLARITY_CONFORM; if (strcmp(env, "high") == 0) pola = INTR_POLARITY_HIGH; else if (strcmp(env, "low") == 0) pola = INTR_POLARITY_LOW; kfreeenv(env); if (pola == INTR_POLARITY_CONFORM) goto back; acpi_sci_trig = trig; acpi_sci_pola = pola; back: if (acpi_sci_irq >= 0) { FADT_VPRINTF("SCI irq %d, %s/%s\n", acpi_sci_irq, intr_str_trigger(acpi_sci_trig), intr_str_polarity(acpi_sci_pola)); } else { FADT_VPRINTF("SCI is disabled\n"); } sdt_sdth_unmap(&fadt->fadt_hdr); }
static void fadt_probe(void) { ACPI_TABLE_FADT *fadt; vm_paddr_t fadt_paddr; enum intr_trigger trig; enum intr_polarity pola; int enabled = 1; char *env; fadt_paddr = sdt_search(ACPI_SIG_FADT); if (fadt_paddr == 0) { kprintf("fadt_probe: can't locate FADT\n"); return; } fadt = sdt_sdth_map(fadt_paddr); KKASSERT(fadt != NULL); /* * FADT in ACPI specification 1.0 - 6.0 */ if (fadt->Header.Revision < 1 || fadt->Header.Revision > 6) { kprintf("fadt_probe: unknown FADT revision %d\n", fadt->Header.Revision); } if (fadt->Header.Length < ACPI_FADT_V1_SIZE) { kprintf("fadt_probe: invalid FADT length %u (< %u)\n", fadt->Header.Length, ACPI_FADT_V1_SIZE); goto back; } kgetenv_int("hw.acpi.sci.enabled", &enabled); if (!enabled) goto back; acpi_sci_irq = fadt->SciInterrupt; env = kgetenv("hw.acpi.sci.trigger"); if (env == NULL) goto back; trig = INTR_TRIGGER_CONFORM; if (strcmp(env, "edge") == 0) trig = INTR_TRIGGER_EDGE; else if (strcmp(env, "level") == 0) trig = INTR_TRIGGER_LEVEL; kfreeenv(env); if (trig == INTR_TRIGGER_CONFORM) goto back; env = kgetenv("hw.acpi.sci.polarity"); if (env == NULL) goto back; pola = INTR_POLARITY_CONFORM; if (strcmp(env, "high") == 0) pola = INTR_POLARITY_HIGH; else if (strcmp(env, "low") == 0) pola = INTR_POLARITY_LOW; kfreeenv(env); if (pola == INTR_POLARITY_CONFORM) goto back; acpi_sci_trig = trig; acpi_sci_pola = pola; back: if (acpi_sci_irq >= 0) { FADT_VPRINTF("SCI irq %d, %s/%s\n", acpi_sci_irq, intr_str_trigger(acpi_sci_trig), intr_str_polarity(acpi_sci_pola)); } else { FADT_VPRINTF("SCI is disabled\n"); } sdt_sdth_unmap(&fadt->Header); }