[FREELDR] Retrieve the correct ACPI RSDP table address. (#1951)
[reactos.git] / boot / freeldr / freeldr / arch / i386 / hwacpi.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 2004 Eric Kohl
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include <freeldr.h>
22
23 #include <debug.h>
24 DBG_DEFAULT_CHANNEL(HWDETECT);
25
26 BOOLEAN AcpiPresent = FALSE;
27
28 static PRSDP_DESCRIPTOR
29 FindAcpiBios(VOID)
30 {
31 PUCHAR Ptr;
32
33 /* Find the 'Root System Descriptor Table Pointer' */
34 Ptr = (PUCHAR)0xE0000;
35 while ((ULONG_PTR)Ptr < 0x100000)
36 {
37 if (!memcmp(Ptr, "RSD PTR ", 8))
38 {
39 TRACE("ACPI supported\n");
40
41 return (PRSDP_DESCRIPTOR)Ptr;
42 }
43
44 Ptr = (PUCHAR)((ULONG_PTR)Ptr + 0x10);
45 }
46
47 TRACE("ACPI not supported\n");
48
49 return NULL;
50 }
51
52
53 VOID
54 DetectAcpiBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
55 {
56 PCONFIGURATION_COMPONENT_DATA BiosKey;
57 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
58 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
59 PRSDP_DESCRIPTOR Rsdp;
60 PACPI_BIOS_DATA AcpiBiosData;
61 ULONG TableSize;
62
63 Rsdp = FindAcpiBios();
64
65 if (Rsdp)
66 {
67 /* Set up the flag in the loader block */
68 AcpiPresent = TRUE;
69
70 /* Calculate the table size */
71 TableSize = PcBiosMapCount * sizeof(BIOS_MEMORY_MAP) +
72 sizeof(ACPI_BIOS_DATA) - sizeof(BIOS_MEMORY_MAP);
73
74 /* Set 'Configuration Data' value */
75 PartialResourceList =
76 FrLdrHeapAlloc(sizeof(CM_PARTIAL_RESOURCE_LIST) + TableSize,
77 TAG_HW_RESOURCE_LIST);
78
79 if (PartialResourceList == NULL)
80 {
81 ERR("Failed to allocate resource descriptor\n");
82 return;
83 }
84
85 memset(PartialResourceList, 0, sizeof(CM_PARTIAL_RESOURCE_LIST) + TableSize);
86 PartialResourceList->Version = 0;
87 PartialResourceList->Revision = 0;
88 PartialResourceList->Count = 1;
89
90 PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
91 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
92 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
93 PartialDescriptor->u.DeviceSpecificData.DataSize = TableSize;
94
95 /* Fill the table */
96 AcpiBiosData = (PACPI_BIOS_DATA)&PartialResourceList->PartialDescriptors[1];
97
98 if (Rsdp->revision > 0)
99 {
100 TRACE("ACPI >1.0, using XSDT address\n");
101 AcpiBiosData->RSDTAddress.QuadPart = Rsdp->xsdt_physical_address;
102 }
103 else
104 {
105 TRACE("ACPI 1.0, using RSDT address\n");
106 AcpiBiosData->RSDTAddress.LowPart = Rsdp->rsdt_physical_address;
107 }
108
109 AcpiBiosData->Count = PcBiosMapCount;
110 memcpy(AcpiBiosData->MemoryMap, PcBiosMemoryMap,
111 PcBiosMapCount * sizeof(BIOS_MEMORY_MAP));
112
113 TRACE("RSDT %p, data size %x\n", Rsdp->rsdt_physical_address,
114 TableSize);
115
116 /* Create new bus key */
117 FldrCreateComponentKey(SystemKey,
118 AdapterClass,
119 MultiFunctionAdapter,
120 0x0,
121 0x0,
122 0xFFFFFFFF,
123 "ACPI BIOS",
124 PartialResourceList,
125 sizeof(CM_PARTIAL_RESOURCE_LIST) + TableSize,
126 &BiosKey);
127
128 /* Increment bus number */
129 (*BusNumber)++;
130 }
131 }
132
133 /* EOF */