The Pedigree Project 0.1
mach_pc/Acpi.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <config.h>
21
22#if ACPI
23
24#include "pedigree/kernel/BootstrapInfo.h"
25#include "pedigree/kernel/Log.h"
26#include "pedigree/kernel/machine/Device.h"
27#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
28#include "pedigree/kernel/processor/VirtualAddressSpace.h"
29#include "pedigree/kernel/utilities/RangeList.h"
30#include "pedigree/kernel/utilities/utility.h"
31
32#include "../../core/processor/x86_common/PhysicalMemoryManager.h"
33#include "Acpi.h"
34
35Acpi Acpi::m_Instance;
36
37namespace {
38bool rangeContains(uint64_t rangeAddress, uint64_t rangeLength, uint64_t address, uint64_t length) {
39 const uint64_t rangeEnd = rangeAddress + rangeLength;
40 const uint64_t end = address + length;
41 return rangeEnd >= rangeAddress && end >= address && address >= rangeAddress && end <= rangeEnd;
42}
43
44bool mappedRangeContains(const MemoryRegion& region, uint64_t address, uint64_t length) {
45 return rangeContains(region.physicalAddress(), region.size(), address, length);
46}
47} // namespace
48
49void Acpi::initialise() {
50 // Search for the ACPI root system description pointer
51 if (find() == false) {
52 WARNING("Acpi: not compliant to the ACPI Specification");
53 return;
54 }
55
56 NOTICE("ACPI Specification");
57 NOTICE(" RSDT pointer at " << Hex << reinterpret_cast<uintptr_t>(m_pRsdtPointer));
58
59 // XSDT present?
60 if (m_pRsdtPointer->revision >= 2) {
61 if (m_pRsdtPointer->xsdtAddress != 0) {
62 NOTICE(" XSDT at " << Hex << m_pRsdtPointer->xsdtAddress);
63 }
64 }
65
66 NOTICE(" RSDT at " << Hex << m_pRsdtPointer->rsdtAddress);
67
68 // Get the ACPI memory ranges
69 X86CommonPhysicalMemoryManager& physicalMemoryManager =
71 const RangeList<uint64_t>& AcpiRanges = physicalMemoryManager.getAcpiRanges();
72 RangeList<uint64_t>::Range AcpiRange(0, 0);
73 bool foundAcpiRange = false;
74 for (size_t i = 0; i < AcpiRanges.size(); ++i) {
75 RangeList<uint64_t>::Range candidate(0, 0);
76 if (AcpiRanges.getRange(i, candidate) &&
77 rangeContains(candidate.address, candidate.length, m_pRsdtPointer->rsdtAddress,
78 sizeof(SystemDescriptionTableHeader))) {
79 AcpiRange = candidate;
80 foundAcpiRange = true;
81 break;
82 }
83 }
84
85 // Firmware may mark ACPI tables reserved instead of reclaimable.
86 if (!foundAcpiRange && g_pBootstrapInfo) {
87 void* memoryMap = g_pBootstrapInfo->getMemoryMap();
88 while (memoryMap) {
89 const uint64_t address = g_pBootstrapInfo->getMemoryMapEntryAddress(memoryMap);
90 const uint64_t length = g_pBootstrapInfo->getMemoryMapEntryLength(memoryMap);
91 if (rangeContains(address, length, m_pRsdtPointer->rsdtAddress,
92 sizeof(SystemDescriptionTableHeader))) {
93 AcpiRange.address = address;
94 AcpiRange.length = length;
95 foundAcpiRange = true;
96 NOTICE(" ACPI tables are in firmware memory-map type "
97 << Hex << g_pBootstrapInfo->getMemoryMapEntryType(memoryMap));
98 break;
99 }
100 memoryMap = g_pBootstrapInfo->nextMemoryMapEntry(memoryMap);
101 }
102 }
103
104 if (!foundAcpiRange) {
105 ERROR("Acpi: Could not locate the RSDT in the firmware memory map");
106 return;
107 }
108
109 // Allocate the ACPI memory as a MemoryRegion
110 physical_uintptr_t address = AcpiRange.address & (~(PhysicalMemoryManager::getPageSize() - 1));
111 size_t sAddress = AcpiRange.length + (AcpiRange.address - address);
112 size_t nPages = (sAddress + (PhysicalMemoryManager::getPageSize() - 1)) /
114 if (physicalMemoryManager.allocateRegion(
115 m_AcpiMemoryRegion, nPages,
119 ERROR("Acpi: Could not allocate the MemoryRegion");
120 return;
121 }
122
123 // Check the RSDT (Root System Description Table)
124 m_pRsdt = m_AcpiMemoryRegion.convertPhysicalPointer<SystemDescriptionTableHeader>(
125 m_pRsdtPointer->rsdtAddress);
126 if (m_pRsdt->signature != 0x54445352 || m_pRsdt->length < sizeof(SystemDescriptionTableHeader) ||
127 !mappedRangeContains(m_AcpiMemoryRegion, m_pRsdtPointer->rsdtAddress, m_pRsdt->length) ||
128 checksum(m_pRsdt) != true) {
129 ERROR("Acpi: RSDT invalid");
130 m_pRsdt = 0;
131 return;
132 }
133
134 // Go through the table's entries
135 size_t sEntries = (m_pRsdt->length - sizeof(SystemDescriptionTableHeader)) / 4;
136 for (size_t i = 0; i < sEntries; i++) {
137 uint32_t* pTable = adjust_pointer(reinterpret_cast<uint32_t*>(m_pRsdt),
138 sizeof(SystemDescriptionTableHeader) + 4 * i);
139
140 SystemDescriptionTableHeader* pSystemDescTable =
141 m_AcpiMemoryRegion.convertPhysicalPointer<SystemDescriptionTableHeader>(*pTable);
142
143 if (!mappedRangeContains(m_AcpiMemoryRegion, *pTable, sizeof(SystemDescriptionTableHeader))) {
144 ERROR(" ACPI table header is outside the mapped firmware range");
145 continue;
146 }
147
148 if (pSystemDescTable->length < sizeof(SystemDescriptionTableHeader) ||
149 !mappedRangeContains(m_AcpiMemoryRegion, *pTable, pSystemDescTable->length)) {
150 ERROR(" ACPI table is outside the mapped firmware range");
151 continue;
152 }
153
154 char Signature[5];
155 StringCopyN(Signature, reinterpret_cast<char*>(&pSystemDescTable->signature), 4);
156 Signature[4] = '\0';
157
158 NOTICE(" " << Signature << " at " << Hex << *pTable);
159
160 // Is the table valid?
161 if (checksum(pSystemDescTable) != true) {
162 ERROR(" invalid");
163 continue;
164 }
165
166 // Is Fixed ACPI Description Table?
167 if (pSystemDescTable->signature == 0x50434146) {
168 if (pSystemDescTable->length < sizeof(FixedACPIDescriptionTable)) {
169 ERROR("Acpi: truncated Fixed ACPI Description Table");
170 continue;
171 }
172 m_pFacp = reinterpret_cast<FixedACPIDescriptionTable*>(pSystemDescTable);
173 }
174// Is Multiple APIC Description Table?
175#if MULTIPROCESSOR
176 else if (pSystemDescTable->signature == 0x43495041)
177 m_pApic = pSystemDescTable;
178#endif
179 else if (pSystemDescTable->signature == 0x52414d44) {
180 if (m_DmarSeen) {
181 m_DmarPresent = false;
182 ERROR("Acpi: duplicate DMAR table");
183 continue;
184 }
185 m_DmarSeen = true;
186 AcpiDmar::Info info;
187 if (!AcpiDmar::parse(reinterpret_cast<const uint8_t*>(pSystemDescTable),
188 pSystemDescTable->length, info)) {
189 ERROR("Acpi: invalid DMAR table");
190 } else {
191 m_DmarInfo = info;
192 m_DmarPresent = true;
193 NOTICE(" ACPI DMAR: " << Dec << info.hardwareUnitCount << " DMA remapping units ("
194 << info.segmentZeroUnitCount << " on PCI segment 0), interrupt "
195 << (info.interruptRemapping ? "remapping advertised"
196 : "remapping absent"));
197 }
198 } else if (pSystemDescTable->signature == 0x4746434d) {
199 constexpr size_t entriesOffset = sizeof(SystemDescriptionTableHeader) + 8;
200 if (pSystemDescTable->length < entriesOffset ||
201 (pSystemDescTable->length - entriesOffset) % sizeof(PciConfigurationRange)) {
202 ERROR("Acpi: invalid MCFG length");
203 continue;
204 }
205 const size_t count =
206 (pSystemDescTable->length - entriesOffset) / sizeof(PciConfigurationRange);
207 for (size_t entryIndex = 0; entryIndex < count; ++entryIndex) {
208 const auto* entry =
209 adjust_pointer(reinterpret_cast<const PciConfigurationRange*>(pSystemDescTable),
210 entriesOffset + entryIndex * sizeof(PciConfigurationRange));
211 if (entry->segment || entry->firstBus > entry->lastBus ||
212 (entry->base & ((1ULL << 20) - 1))) {
213 continue;
214 }
215 const uint64_t bytes = uint64_t(entry->lastBus + 1) << 20;
216 if (!entry->base || entry->base + bytes < entry->base) {
217 continue;
218 }
219 bool overlap = false;
220 for (const auto& range : m_PciConfigurationRanges) {
221 if (entry->firstBus <= range.lastBus && entry->lastBus >= range.firstBus) {
222 overlap = true;
223 break;
224 }
225 }
226 if (!overlap) {
227 m_PciConfigurationRanges.pushBack(*entry);
228 NOTICE(" ACPI MCFG segment 0 buses " << Dec << entry->firstBus << ".." << entry->lastBus
229 << " at " << Hex << entry->base);
230 }
231 }
232 } else {
233 NOTICE(" unknown table");
234 }
235 }
236
237 // Do we have a Fixed ACPI Description Table?
238 if (m_pFacp == 0) {
239 ERROR("Acpi: no Fixed ACPI Description Table (FACP)");
240 return;
241 }
242
243 // Parse the FACP
244 parseFixedACPIDescriptionTable();
245 initialisePowerManagement();
246
247 if (m_pFacp->dsdt && mappedRangeContains(m_AcpiMemoryRegion, m_pFacp->dsdt,
248 sizeof(SystemDescriptionTableHeader))) {
249 const auto* dsdt =
250 m_AcpiMemoryRegion.convertPhysicalPointer<SystemDescriptionTableHeader>(m_pFacp->dsdt);
251 if (dsdt->signature == 0x54445344 && dsdt->length >= sizeof(SystemDescriptionTableHeader) &&
252 mappedRangeContains(m_AcpiMemoryRegion, m_pFacp->dsdt, dsdt->length) && checksum(dsdt)) {
253 m_PciInterruptRoutesPresent = AcpiPciRouting::parse(
254 reinterpret_cast<const uint8_t*>(dsdt) + sizeof(SystemDescriptionTableHeader),
255 dsdt->length - sizeof(SystemDescriptionTableHeader), m_PciInterruptRoutes);
256 if (m_PciInterruptRoutesPresent) {
257 NOTICE(" ACPI PCI IOAPIC routes available");
258 }
259 }
260 }
261
262#if MULTIPROCESSOR
263 // If we have an Multiple APIC Description Table parse it
264 if (m_pApic != 0)
265 parseMultipleApicDescriptionTable();
266#endif
267
268 m_bValid = true;
269}
270
271Acpi::Acpi()
272 : m_bValid(0),
273 m_pRsdtPointer(0),
274 m_AcpiMemoryRegion("ACPI"),
275 m_pRsdt(0),
276 m_pFacp(0),
277 m_PciConfigurationRanges(),
278 m_DmarInfo(),
279 m_DmarPresent(false),
280 m_DmarSeen(false)
281#if MULTIPROCESSOR
282 ,
283 m_pApic(0),
284 m_bValidApicInfo(false),
285 m_bHasPICs(false),
286 m_LocalApicAddress(0),
287 m_IoApics(),
288 m_bValidProcessorInfo(false),
289 m_Processors()
290#endif
291{
292 for (size_t irq = 0; irq < 16; ++irq) {
293 m_IsaGsis[irq] = irq;
294 }
295}
296
297bool Acpi::getPmTimerPort(uint16_t& port, uint32_t& mask) const {
298 if (!m_bValid || !m_pFacp || (m_pFacp->flags & (1U << 20)) || m_pFacp->pmTimerLength != 4) {
299 return false;
300 }
301
302 uint64_t address = m_pFacp->pmTimerBlock;
303 // X_PM_TMR_BLK takes precedence when the extended FADT provides it.
304 if (m_pFacp->header.length >= 220) {
305 const uint8_t* gas = reinterpret_cast<const uint8_t*>(m_pFacp) + 208;
306 uint64_t extendedAddress = 0;
307 MemoryCopy(&extendedAddress, gas + 4, sizeof(extendedAddress));
308 if (extendedAddress) {
309 if (gas[0] != 1 || (gas[1] != 24 && gas[1] != 32) || gas[2] || (gas[3] != 0 && gas[3] != 3)) {
310 return false;
311 }
312 address = extendedAddress;
313 }
314 }
315 if (!address || address > 0xfffc) {
316 return false;
317 }
318 port = static_cast<uint16_t>(address);
319 mask = (m_pFacp->flags & (1U << 8)) ? 0xffffffffU : 0x00ffffffU;
320 return true;
321}
322
323bool Acpi::pciConfigurationAddress(uint8_t bus, uint64_t& address) const {
324 if (!m_bValid) {
325 return false;
326 }
327 for (const auto& range : m_PciConfigurationRanges) {
328 if (bus >= range.firstBus && bus <= range.lastBus) {
329 address = range.base + (uint64_t(bus) << 20);
330 return true;
331 }
332 }
333 return false;
334}
335
336bool Acpi::pciBusRange(uint8_t& first, uint8_t& last) const {
337 if (!m_bValid || !m_PciConfigurationRanges.size()) {
338 return false;
339 }
340 first = 255;
341 last = 0;
342 for (const auto& range : m_PciConfigurationRanges) {
343 if (range.firstBus < first) {
344 first = range.firstBus;
345 }
346 if (range.lastBus > last) {
347 last = range.lastBus;
348 }
349 }
350 return true;
351}
352
353bool Acpi::pciInterruptRoute(uint8_t slot, uint8_t pin, AcpiPciRouting::Route& route) const {
354 if (!m_bValid || !m_PciInterruptRoutesPresent || slot >= 32 || pin < 1 || pin > 4) {
355 return false;
356 }
357 route = m_PciInterruptRoutes[slot][pin - 1];
358 return route.gsi >= 16;
359}
360
361void Acpi::setPciInterruptRouter(PciInterruptRouter router) {
362 __atomic_store_n(&m_PciInterruptRouter, router, __ATOMIC_RELEASE);
363}
364
365bool Acpi::hasPciInterruptRouter() const {
366 return __atomic_load_n(&m_PciInterruptRouter, __ATOMIC_ACQUIRE) != nullptr;
367}
368
369bool Acpi::pciInterruptRoute(Device* device, uint8_t pin, AcpiPciRouting::Route& route) const {
370 if (!device || pin < 1 || pin > 4) {
371 return false;
372 }
373 const auto router = __atomic_load_n(&m_PciInterruptRouter, __ATOMIC_ACQUIRE);
374 if (router) {
375 return router(device, pin, route);
376 }
377 Device* current = device;
378 for (size_t depth = 0; current->getPciBusPosition(); ++depth) {
379 if (depth == 8) {
380 return false;
381 }
382 Device* bus = current->getParent();
383 Device* bridge = bus ? bus->getParent() : nullptr;
384 if (!bridge || bridge->getPciClassCode() != 6 || bridge->getPciSubclassCode() != 4) {
385 return false;
386 }
387 pin = static_cast<uint8_t>(((pin - 1 + current->getPciDevicePosition()) & 3) + 1);
388 current = bridge;
389 }
390 return pciInterruptRoute(current->getPciDevicePosition(), pin, route);
391}
392
393bool Acpi::isaIrqsForGsi(uint32_t gsi, uint16_t& irqs) const {
394 irqs = 0;
395#if MULTIPROCESSOR
396 if (!m_bValidApicInfo) {
397 return false;
398 }
399#endif
400 if (!m_bValid || !m_IsaRoutingValid) {
401 return false;
402 }
403 for (uint32_t nmi : m_NmiGsis) {
404 if (nmi == gsi) {
405 return false;
406 }
407 }
408 for (size_t irq = 0; irq < 16; ++irq) {
409 if (m_IsaGsis[irq] == gsi) {
410 irqs |= uint16_t(1U << irq);
411 }
412 }
413 return true;
414}
415
416void Acpi::parseFixedACPIDescriptionTable() {
417 NOTICE("ACPI: Fixed Description Table (FACP)");
418
419 NOTICE(" Firmware ACPI Control Structure at " << Hex << m_pFacp->firmwareControl);
420 NOTICE(" Differentiated System Description Table at " << Hex << m_pFacp->dsdt);
421 NOTICE(" Interrupt Model: " << Dec
422 << ((m_pFacp->interruptModel == 0) ? "dual 8259 PICs"
423 : "multiple local APICs"));
424 NOTICE(" SCI Interrupt #" << Dec << m_pFacp->sciInterrupt);
425 NOTICE(" SMI Command Port at " << Hex << m_pFacp->smiCommandPort);
426 NOTICE(" enable " << Hex << m_pFacp->acpiEnableCommand);
427 NOTICE(" disable " << Hex << m_pFacp->acpiDisableCommand);
428 if (m_pFacp->s4BiosCommand != 0) {
429 NOTICE(" S4 BIOS " << Hex << m_pFacp->s4BiosCommand);
430 }
431 NOTICE(" Power-Management");
432 NOTICE(" Event 1A at " << Hex << m_pFacp->pm1aEventBlock << " - "
433 << (m_pFacp->pm1aEventBlock + m_pFacp->pm1EventLength));
434 if (m_pFacp->pm1bEventBlock != 0) {
435 NOTICE(" Event 1B at " << Hex << m_pFacp->pm1bEventBlock << " - "
436 << (m_pFacp->pm1bEventBlock + m_pFacp->pm1EventLength));
437 }
438 NOTICE(" Control 1A at " << Hex << m_pFacp->pm1aControlBlock << " - "
439 << (m_pFacp->pm1aControlBlock + m_pFacp->pm1ControlLength));
440 if (m_pFacp->pm1bControlBlock != 0) {
441 NOTICE(" Control 1B at " << Hex << m_pFacp->pm1bControlBlock << " - "
442 << (m_pFacp->pm1bControlBlock + m_pFacp->pm1ControlLength));
443 }
444 if (m_pFacp->pm2ControlBlock != 0) {
445 NOTICE(" Control 2 at " << Hex << m_pFacp->pm2ControlBlock << " - "
446 << (m_pFacp->pm2ControlBlock + m_pFacp->pm2ControlLength));
447 }
448 NOTICE(" Timer at " << Hex << m_pFacp->pmTimerBlock << " - "
449 << (m_pFacp->pmTimerBlock + m_pFacp->pmTimerLength));
450 if (m_pFacp->gpe0Block != 0) {
451 NOTICE(" General Purpose Event 0 at " << Hex << m_pFacp->gpe0Block << " - "
452 << (m_pFacp->gpe0Block + m_pFacp->gpe0BlockLength));
453 }
454 if (m_pFacp->gpe1Block != 0) {
455 NOTICE(" General Purpose Event 1 at " << Hex << m_pFacp->gpe1Block << " - "
456 << (m_pFacp->gpe1Block + m_pFacp->gpe1BlockLength));
457 }
458 if (m_pFacp->gpe1Base != 0) {
459 NOTICE(" General Purpose Event Base: " << Hex << m_pFacp->gpe1Base);
460 }
461 // TODO: Unimportant imho
462 NOTICE(" Flags " << Hex << m_pFacp->flags);
463}
464
465#if MULTIPROCESSOR
466void Acpi::parseMultipleApicDescriptionTable() {
467 NOTICE("ACPI: Multiple APIC Description Table (APIC)");
468
469 if (m_pApic->length < sizeof(SystemDescriptionTableHeader) + 8) {
470 ERROR("ACPI: truncated Multiple APIC Description Table");
471 return;
472 }
473
474 // Parse the Multiple APIC Description Table
475 uint32_t* pLocalApicAddress =
476 reinterpret_cast<uint32_t*>(adjust_pointer(m_pApic, sizeof(SystemDescriptionTableHeader)));
477 uint32_t* pFlags = adjust_pointer(pLocalApicAddress, 4);
478
479 m_LocalApicAddress = *pLocalApicAddress;
480 m_bHasPICs = (((*pFlags) & 0x01) == 0x01);
481
482 uint8_t* pType = reinterpret_cast<uint8_t*>(adjust_pointer(pFlags, 4));
483 uint8_t* const end = reinterpret_cast<uint8_t*>(adjust_pointer(m_pApic, m_pApic->length));
484 for (; end - pType >= 2;) {
485 const uint8_t entryLength = pType[1];
486 if (entryLength < 2 || entryLength > end - pType) {
487 ERROR("ACPI: invalid Multiple APIC Description Table entry");
488 return;
489 }
490 // Processor Local APIC
491 if (*pType == 0 && entryLength >= 8) {
492 ProcessorLocalApic* pLocalApic =
493 reinterpret_cast<ProcessorLocalApic*>(adjust_pointer(pType, 2));
494 bool bUsable = ((pLocalApic->flags & 0x01) == 0x01);
495 NOTICE(" Processor #" << Dec << pLocalApic->processorId
496 << (bUsable ? " usable" : " unusable"));
497
498 // Is the processor usable?
499 if (bUsable) {
500 // Add the processor to the list
502 new Multiprocessor::ProcessorInformation(pLocalApic->processorId, pLocalApic->apicId);
503 m_Processors.pushBack(pProcessorInfo);
504 }
505 }
506 // I/O APIC
507 else if (*pType == 1 && entryLength >= 12) {
508 IoApic* pIoApic = reinterpret_cast<IoApic*>(adjust_pointer(pType, 2));
509
510 NOTICE(" I/O APIC #" << Dec << pIoApic->apicId << " at " << Hex << pIoApic->address
511 << ", global system interrupt base "
512 << pIoApic->globalSystemInterruptBase);
513
514 // Add to the I/O APIC list
516 pIoApic->apicId, pIoApic->address, pIoApic->globalSystemInterruptBase);
517 m_IoApics.pushBack(pIoApicInfo);
518 }
519 // Interrupt Source override
520 else if (*pType == 2 && entryLength >= 10) {
521 InterruptSourceOverride* pInterruptSourceOverride =
522 reinterpret_cast<InterruptSourceOverride*>(adjust_pointer(pType, 2));
523
524 ERROR(" Interrupt override: " << ((pInterruptSourceOverride->bus == 0) ? "ISA" : "unknown")
525 << " bus, #" << Dec << pInterruptSourceOverride->source
526 << " -> #" << pInterruptSourceOverride->globalSystemInterrupt
527 << ", flags " << Hex << pInterruptSourceOverride->flags);
528
529 const auto& source = *pInterruptSourceOverride;
530 if (source.bus || source.source >= 16 || (m_IsaOverrides & (1U << source.source)) ||
531 (source.flags & ~0xfU) || (source.flags & 3) == 2 || ((source.flags >> 2) & 3) == 2) {
532 m_IsaRoutingValid = false;
533 } else {
534 m_IsaGsis[source.source] = source.globalSystemInterrupt;
535 m_IsaOverrides |= uint16_t(1U << source.source);
536 }
537 }
538 // Non-maskable Interrupt Source (NMI)
539 else if (*pType == 3) {
540 ERROR(" NMI source");
541 if (entryLength < 8) {
542 m_IsaRoutingValid = false;
543 } else {
544 m_NmiGsis.pushBack(uint32_t(pType[4]) | (uint32_t(pType[5]) << 8) |
545 (uint32_t(pType[6]) << 16) | (uint32_t(pType[7]) << 24));
546 }
547 }
548 // Local APIC NMI
549 else if (*pType == 4) {
550 ERROR(" Local APIC NMI");
551 }
552 // Local APIC Address Override
553 else if (*pType == 5) {
554 ERROR(" Local APIC address override");
555 }
556 // I/O SAPIC
557 else if (*pType == 6) {
558 ERROR(" I/O SAPIC");
559 }
560 // Local SAPIC
561 else if (*pType == 7) {
562 ERROR(" Local SAPIC");
563 }
564 // Platform Interrupt Source
565 else if (*pType == 8) {
566 ERROR(" Platform Interrupt Source");
567 } else {
568 NOTICE(" unknown entry #" << Dec << *pType);
569 }
570
571 // Go to the next entry;
572 pType += entryLength;
573 }
574
575 m_bValidApicInfo = true;
576 m_bValidProcessorInfo = true;
577}
578#endif
579
580bool Acpi::find() {
581 if (g_pBootstrapInfo && g_pBootstrapInfo->getAcpiRsdp()) {
582 m_pRsdtPointer = reinterpret_cast<RsdtPointer*>(g_pBootstrapInfo->getAcpiRsdp());
583 if (m_pRsdtPointer->signature == 0x2052545020445352ULL && checksum(m_pRsdtPointer)) {
584 return true;
585 }
586 }
587 m_pRsdtPointer = nullptr;
588 return false;
589}
590
591bool Acpi::checksum(const RsdtPointer* pRdstPointer) {
592 // ACPI 1.0 checksum
593 if (::checksum(reinterpret_cast<const uint8_t*>(pRdstPointer), 20) == false)
594 return false;
595
596 if (pRdstPointer->revision >= 2) {
597 // ACPI 2.0+ checksum
598 if (::checksum(reinterpret_cast<const uint8_t*>(pRdstPointer), pRdstPointer->length) == false)
599 return false;
600 }
601
602 return true;
603}
604
605bool Acpi::checksum(const SystemDescriptionTableHeader* pHeader) {
606 return ::checksum(reinterpret_cast<const uint8_t*>(pHeader), pHeader->length);
607}
608
609#endif
uint32_t getPciDevicePosition()
Definition Device.h:240
uint8_t getPciClassCode()
Definition Device.h:216
uint8_t getPciSubclassCode()
Definition Device.h:220
Device * getParent() const
Definition Device.h:166
uint32_t getPciBusPosition()
Definition Device.h:236
Special memory entity in the kernel's virtual address space.
physical_uintptr_t physicalAddress() const
size_t size() const
bool getRange(size_t index, Range &range) const
Definition RangeList.h:419
size_t size() const
Definition RangeList.h:104
Implementation of the PhysicalMemoryManager for common x86.
virtual bool allocateRegion(MemoryRegion &Region, size_t cPages, size_t pageConstraints, size_t Flags, physical_uintptr_t start=-1) override
@ Dec
Definition Log.h:126
@ Hex
Definition Log.h:124