8 enum Type { System_mem = 0, System_io = 1, Pci_cfg_mem = 2 };
12 Unsigned8 access_size;
14 } __attribute__((packed));
28 Unsigned32 creator_id;
29 Unsigned32 creator_rev;
31 bool checksum_ok() const;
32 } __attribute__((packed));
39 Acpi_table_head const **_tables;
45 static Acpi_sdt const *sdt() { return &_sdt; }
49 static bool _init_done;
52 class Acpi_madt : public Acpi_table_head
56 { LAPIC, IOAPIC, Irq_src_ovr, NMI, LAPIC_NMI, LAPIC_adr_ovr, IOSAPIC,
63 } __attribute__((packed));
65 struct Io_apic : public Apic_head
72 } __attribute__((packed));
74 struct Irq_source : public Apic_head
76 enum { ID = Irq_src_ovr };
81 } __attribute__((packed));
84 Unsigned32 local_apic;
85 Unsigned32 apic_flags;
89 } __attribute__((packed));
92 struct Acpi_helper_get_msb
93 { template<typename P> static Address msb(P) { return 0; } };
96 struct Acpi_helper_get_msb<true>
97 { template<typename P> static Address msb(P p) { return p >> (sizeof(Address) * 8); } };
102 #include "boot_alloc.h"
108 bool Acpi::_init_done;
110 template< typename T >
111 class Acpi_sdt_p : public Acpi_table_head
116 } __attribute__((packed));
118 typedef Acpi_sdt_p<Unsigned32> Acpi_rsdt_p;
119 typedef Acpi_sdt_p<Unsigned64> Acpi_xsdt_p;
128 Unsigned32 rsdt_phys;
130 Unsigned64 xsdt_phys;
131 Unsigned8 ext_chk_sum;
134 Acpi_rsdt_p const *rsdt() const;
135 Acpi_xsdt_p const *xsdt() const;
137 bool checksum_ok() const;
139 static Acpi_rsdp const *locate();
140 } __attribute__((packed));
144 print_acpi_id(char const *id, int len)
147 for (int i = 0; i < len; ++i)
148 ID[i] = isalnum(id[i]) ? id[i] : '.';
149 printf("%.*s", len, ID);
153 Acpi_rsdp::print_info() const
155 printf("ACPI: RSDP[%p]\tr%02x OEM:", this, (unsigned)rev);
156 print_acpi_id(oem, 6);
161 Acpi_table_head::print_info() const
164 print_acpi_id(signature, 4);
165 printf("[%p]\tr%02x OEM:", this, (unsigned)rev);
166 print_acpi_id(oem_id, 6);
168 print_acpi_id(oem_tid, 8);
174 Acpi_sdt::print_summary() const
176 for (unsigned i = 0; i < _num_tables; ++i)
178 _tables[i]->print_info();
181 PUBLIC template< typename T >
183 Acpi_sdt_p<T>::entries() const
184 { return (len - sizeof(Acpi_table_head)) / sizeof(ptrs[0]); }
186 PUBLIC template< typename SDT >
188 Acpi_sdt::init(SDT *sdt)
190 unsigned entries = sdt->entries();
191 _tables = (Acpi_table_head const **)Boot_alloced::alloc(sizeof(*_tables) * entries);
194 _num_tables = entries;
195 for (unsigned i = 0; i < entries; ++i)
197 _tables[i] = this->map_entry(i, sdt->ptrs[i]);
205 Acpi::_map_table_head(Unsigned64 phys)
207 // is the acpi address bigger that our handled physical addresses
208 if (Acpi_helper_get_msb<(sizeof(phys) > sizeof(Address))>::msb(phys))
210 printf("ACPI: cannot map phys address %llx, out of range (%ubit)\n",
211 (unsigned long long)phys, (unsigned)sizeof(Address) * 8);
215 void *t = Kmem::dev_map.map((void*)phys);
216 if (t == (void *)~0UL)
218 printf("ACPI: cannot map phys address %llx, map failed\n",
219 (unsigned long long)phys);
228 Acpi::check_signature(char const *sig, char const *reference)
230 for (; *reference; ++sig, ++reference)
231 if (*reference != *sig)
237 PUBLIC static template<typename TAB>
239 Acpi::map_table_head(Unsigned64 phys)
240 { return reinterpret_cast<TAB *>(_map_table_head(phys)); }
243 PRIVATE template< typename T >
244 Acpi_table_head const *
245 Acpi_sdt::map_entry(unsigned idx, T phys)
247 if (idx >= _num_tables)
249 printf("ACPI: table index out of range (%u >= %u)\n", idx, _num_tables);
253 return Acpi::map_table_head<Acpi_table_head>((Unsigned64)phys);
262 enum { Print_info = 0 };
269 printf("ACPI-Init\n");
271 Acpi_rsdp const *rsdp = Acpi_rsdp::locate();
274 WARN("ACPI: Could not find RSDP, skip init\n");
280 if (rsdp->rev && rsdp->xsdt_phys)
282 Acpi_xsdt_p const *x = Kmem::dev_map.map((const Acpi_xsdt_p *)rsdp->xsdt_phys);
283 if (x == (Acpi_xsdt_p const *)~0UL)
284 WARN("ACPI: Could not map XSDT\n");
285 else if (!x->checksum_ok())
286 WARN("ACPI: Checksum mismatch in XSDT\n");
293 _sdt.print_summary();
301 Acpi_rsdt_p const *r = Kmem::dev_map.map((const Acpi_rsdt_p *)(unsigned long)rsdp->rsdt_phys);
302 if (r == (Acpi_rsdt_p const *)~0UL)
303 WARN("ACPI: Could not map RSDT\n");
304 else if (!r->checksum_ok())
305 WARN("ACPI: Checksum mismatch in RSDT\n");
312 _sdt.print_summary();
320 template< typename T >
322 Acpi::find(const char *s)
325 return static_cast<T>(sdt()->find(s));
330 Acpi_rsdp::rsdt() const
332 return (Acpi_rsdt_p const*)(unsigned long)rsdt_phys;
337 Acpi_rsdp::xsdt() const
341 return (Acpi_xsdt_p const*)xsdt_phys;
346 Acpi_rsdp::checksum_ok() const
350 for (unsigned i = 0; i < 20; i++)
351 sum += *((Unsigned8 *)this + i);
360 for (unsigned i = 0; i < len && i < 4096; ++i)
361 sum += *((Unsigned8 *)this + i);
368 Acpi_table_head::checksum_ok() const
371 for (unsigned i = 0; i < len && i < 4096; ++i)
372 sum += *((Unsigned8 *)this + i);
378 Acpi_table_head const *
379 Acpi_sdt::find(char const *sig) const
381 for (unsigned i = 0; i < _num_tables; ++i)
383 Acpi_table_head const *t = _tables[i];
387 if (Acpi::check_signature(t->signature, sig)
396 template< typename T >
397 Acpi_table_head const *
398 Acpi_sdt_p<T>::find(char const *sig) const
400 for (unsigned i = 0; i < ((len-sizeof(Acpi_table_head))/sizeof(ptrs[0])); ++i)
402 Acpi_table_head const *t = Kmem::dev_map.map((Acpi_table_head const*)ptrs[i]);
403 if (t == (Acpi_table_head const *)~0UL)
406 if (Acpi::check_signature(t->signature, sig)
415 Acpi_madt::Apic_head const *
416 Acpi_madt::find(Unsigned8 type, int idx) const
418 for (unsigned i = 0; i < len-sizeof(Acpi_madt);)
420 Apic_head const *a = (Apic_head const *)(data + i);
421 //printf("a=%p, a->type=%u, a->len=%u\n", a, a->type, a->len);
434 PUBLIC template<typename T> inline
436 Acpi_madt::find(int idx) const
438 return static_cast<T const *>(find(T::ID, idx));
442 // ------------------------------------------------------------------------
443 IMPLEMENTATION [ia32,amd64]:
447 Acpi_rsdp::locate_in_region(Address start, Address end)
449 for (Address p = start; p < end; p += 16)
451 Acpi_rsdp const* r = (Acpi_rsdp const *)p;
452 if (Acpi::check_signature(r->signature, "RSD PTR ")
466 ACPI20_PC99_RSDP_START = 0x0e0000,
467 ACPI20_PC99_RSDP_END = 0x100000,
469 BDA_EBDA_SEGMENT = 0x00040E,
472 // If we are booted from UEFI, bootstrap reads the RDSP pointer from
473 // UEFI and creates a memory descriptor with sub type 5 for it
474 for (auto const &md: Kip::k()->mem_descs_a())
475 if ( md.type() == Mem_desc::Info
476 && md.ext_type() == Mem_desc::Info_acpi_rsdp)
478 Acpi_rsdp const *r = Acpi::map_table_head<Acpi_rsdp>(md.start());
479 if ( Acpi::check_signature(r->signature, "RSD PTR ")
483 panic("RSDP memory descriptor from bootstrap invalid");
486 if (Acpi_rsdp const *r = locate_in_region(ACPI20_PC99_RSDP_START,
487 ACPI20_PC99_RSDP_END))
490 Address ebda = *(Unsigned16 *)BDA_EBDA_SEGMENT << 4;
491 if (Acpi_rsdp const *r = locate_in_region(ebda, ebda + 1024))