SayoriOS 0.3.3

acpi.c
1 #include "sys/acpi.h"
2 #include "sys/apic_table.h"
3 #include "sys/fadt.h"
4 #include "lib/string.h"
5 #include "io/ports.h"
6 #include "io/tty.h"
7 #include "mem/pmm.h"
8
9 #define ACPI_PAGE_COUNT 32
10
11 uint32_t system_processors_found = 0;
12
13 RSDPDescriptor* rsdp_find() {
14 size_t saddr = 0x000E0000;
15 char rsdp_ptr[8] = {'R','S','D',' ','P','T','R',' '};
16
17 for(; saddr < 0x000FFFFF; saddr++) {
18 if(memcmp((const char*)saddr, (const char*)rsdp_ptr, 8) == 0) {
19 qemu_log("Found! At: %x", saddr);
20 break;
21 }
22 }
23
24 RSDPDescriptor* rsdp = (RSDPDescriptor*)saddr;
25
26 // WORKS!
27 //
28 // char* a;
29 // asprintf(&a, "RSDP sig: %.8s", rsdp->signature);
30 // qemu_log("%s", a);
31 // kfree(a);
32 //
33 // RSD PTR
34
35 qemu_log("RSDP sig: %.8s", rsdp->signature);
36 qemu_log("RSDP checksum: %d", rsdp->checksum);
37 qemu_log("RSDP OEMID: %s", rsdp->OEMID);
38 qemu_log("RSDP revision: %d", rsdp->revision);
39 qemu_log("RSDT address: %x", rsdp->RSDTaddress);
40
41 if(rsdp->RSDTaddress == 0) {
42 return 0;
43 }
44
45 return rsdp;
46 }
47
48 bool acpi_checksum_sdt(ACPISDTHeader *tableHeader) {
49 unsigned char sum = 0;
50
51 for (int i = 0; i < tableHeader->Length; i++) {
52 sum += ((char*)tableHeader)[i];
53 }
54
55 return sum == 0;
56 }
57
58 ACPISDTHeader* find_table(uint32_t rsdt_addr, uint32_t sdt_count, char signature[4]) {
59 uint32_t* rsdt_end = (uint32_t*)(rsdt_addr + sizeof(ACPISDTHeader));
60
61 map_pages_overlapping(
62 get_kernel_page_directory(),
63 rsdt_addr,
64 rsdt_addr,
65 PAGE_SIZE * ACPI_PAGE_COUNT,
66 PAGE_PRESENT
67 );
68
69 qemu_log("RSDT start: %x", rsdt_addr);
70 qemu_log("RSDT end: %x", rsdt_end);
71 qemu_log("RSDT size: %d", sizeof(ACPISDTHeader));
72
73 for(uint32_t i = 0; i < sdt_count; i++) {
74 ACPISDTHeader* entry = (ACPISDTHeader*)(rsdt_end[i]);
75
76 if(strncmp(entry->Signature, signature, 4) == 0) {
77 return entry;
78 }
79 }
80
81 unmap_pages_overlapping(
82 get_kernel_page_directory(),
83 rsdt_addr,
84 PAGE_SIZE * ACPI_PAGE_COUNT
85 );
86
87 return 0;
88 }
89
90 void acpi_scan_all_tables(uint32_t rsdt_addr) {
91 ACPISDTHeader* rsdt = (ACPISDTHeader*)rsdt_addr;
92
93 map_pages_overlapping(
94 get_kernel_page_directory(),
95 rsdt_addr,
96 rsdt_addr,
97 PAGE_SIZE * ACPI_PAGE_COUNT,
98 PAGE_PRESENT
99 );
100
101 uint32_t sdt_count = (rsdt->Length - sizeof(ACPISDTHeader)) / sizeof(uint32_t);
102
103 qemu_log("LEN: %d (// %d)", rsdt->Length, sizeof(ACPISDTHeader));
104
105 uint32_t* rsdt_end = (uint32_t*)(rsdt_addr + sizeof(ACPISDTHeader));
106
107 qemu_log("RSDT start: %x", rsdt_addr);
108 qemu_log("RSDT end: %x", rsdt_end);
109 qemu_log("RSDT size: %d", sizeof(ACPISDTHeader));
110
111 tty_printf("RSDT start: %x\n", rsdt_addr);
112 tty_printf("RSDT end: %x\n", rsdt_end);
113 tty_printf("SDT COUNT: %u\n", sdt_count);
114
115 for(uint32_t i = 0; i < sdt_count; i++) {
116 ACPISDTHeader* entry = (ACPISDTHeader*)(rsdt_end[i]);
117
118 tty_printf("[%d/%d] [%x] Found table: %.4s\n", i, sdt_count, entry, entry->Signature);
119 qemu_log("[%x] Found table: %.4s", (size_t)entry, entry->Signature);
120 }
121
122 unmap_pages_overlapping(
123 get_kernel_page_directory(),
124 rsdt_addr,
125 PAGE_SIZE * ACPI_PAGE_COUNT
126 );
127 }
128
129
130 void find_facp(size_t rsdt_addr) {
131 qemu_log("FACP at P%x", rsdt_addr);
132
133 map_pages_overlapping(
134 get_kernel_page_directory(),
135 rsdt_addr,
136 rsdt_addr,
137 PAGE_SIZE * 2,
138 PAGE_PRESENT
139 );
140
141 ACPISDTHeader* rsdt = (ACPISDTHeader*)rsdt_addr;
142
143 // new_qemu_printf("OEM: %.11s\n", rsdt->OEMID);
144 // qemu_log("Length: %d", rsdt->Length);
145 // new_qemu_printf("OEMTableID: %.8s\n", rsdt->OEMTableID);
146
147 bool check = acpi_checksum_sdt(rsdt);
148
149 qemu_log("Checksum: %s", check ? "PASS" : "FAIL");
150
151 if(!check) {
152 qemu_log("INVALID RSDT TABLE!");
153 return;
154 }
155
156 qemu_log("OEMID: %s", rsdt->OEMID);
157 qemu_log("Length: %d entries", rsdt->Length);
158
159 uint32_t sdt_count = (rsdt->Length - sizeof(ACPISDTHeader)) / sizeof(uint32_t);
160
161 qemu_log("SDTs available: %d", sdt_count);
162
163 // Find FACP here
164
165 ACPISDTHeader* pre_fadt = find_table((uint32_t) rsdt_addr, sdt_count, "FACP");
166
167 if(!pre_fadt) {
168 qemu_log("FADT not found...");
169 return;
170 }
171
172 struct FADT* fadt = (struct FADT*)(pre_fadt + 1); // It skips SDT header
173
174 // map_single_page(get_kernel_page_directory(), (virtual_addr_t) fadt, (virtual_addr_t) fadt, PAGE_WRITEABLE);
175
176 qemu_log("Century: %d", fadt->Century);
177 qemu_log("SMI port: %x", fadt->SMI_CommandPort);
178 qemu_log("Enable Command: %x", fadt->AcpiEnable);
179 qemu_log("TODO: Write 'Enable Command' to 'SMI Port' using `outb()` func");
180
181 qemu_log("Found FADT!");
182
183 // unmap_single_page(get_kernel_page_directory(), (virtual_addr_t) fadt);
184 unmap_pages_overlapping(get_kernel_page_directory(), (virtual_addr_t) rsdt_addr, PAGE_SIZE * 2);
185 }
186
187 void find_apic(size_t rsdt_addr, size_t *lapic_addr) {
188 size_t start = rsdt_addr & ~0xfff;
189 size_t end = ALIGN(rsdt_addr + PAGE_SIZE, PAGE_SIZE);
190
191 map_pages(
192 get_kernel_page_directory(),
193 start,
194 start,
195 end - start,
196 PAGE_PRESENT
197 );
198
199 qemu_log("!!! Should be: %x - %x", start, end);
200 qemu_log("!!! Mapped memory range: %x - %x", rsdt_addr, rsdt_addr + (PAGE_SIZE));
201 ACPISDTHeader* rsdt = (ACPISDTHeader*)rsdt_addr;
202
203 bool check = acpi_checksum_sdt(rsdt);
204
205 qemu_log("Checksum: %s", check ? "PASS" : "FAIL");
206
207 if(!check) {
208 qemu_log("INVALID RSDT TABLE!");
209 return;
210 }
211
212 qemu_log("OEMID: %s", rsdt->OEMID);
213 qemu_log("Length: %d entries", rsdt->Length);
214
215 uint32_t sdt_count = (rsdt->Length - sizeof(ACPISDTHeader)) / sizeof(uint32_t);
216
217 qemu_log("SDTs available: %d", sdt_count);
218
219 // Find APIC here
220
221 ACPISDTHeader* apic = find_table(rsdt_addr, sdt_count, "APIC");
222
223 if(!apic) {
224 qemu_log("APIC not found...");
225 return;
226 }
227
228 qemu_log("Found APIC!");
229
230 size_t table_end = (size_t)apic + sizeof(ACPISDTHeader);
231
232 qemu_log("Table end at: %x", table_end);
233
234 struct APIC_Base_Table* apic_base = (struct APIC_Base_Table*)table_end;
235
236 qemu_log("LAPIC at: %x", apic_base->lapic_addr);
237 qemu_log("Flags: %x", apic_base->flags);
238
239 *lapic_addr = apic_base->lapic_addr;
240
241 size_t base_table_end = table_end + sizeof(struct APIC_Base_Table);
242
243 for(int i = 0; i < sdt_count; i++) {
244 struct APIC_Entry* entry = (struct APIC_Entry*)base_table_end;
245
246 qemu_log("[%x] Type: %d", entry, entry->type);
247
248 switch(entry->type) {
249 case APIC_PLAPIC: {
250 qemu_log("PLAPIC!");
251
252 qemu_log("- Processor ID: %d", entry->entry.plapic.processor_id);
253 qemu_log("- Flags: %x", entry->entry.plapic.flags);
254 qemu_log("- APIC ID: %x", entry->entry.plapic.apic_id);
255
256 system_processors_found++;
257
258 break;
259 }
260
261 case APIC_IOAPIC: {
262 qemu_log("IOAPIC!");
263
264 qemu_log("- ID: %d", entry->entry.ioapic.id);
265 qemu_log("- IO APIC Address: %x", entry->entry.ioapic.io_apic_address);
266 qemu_log("- Global System Interrupt Base: %x", entry->entry.ioapic.global_system_interrupt_base);
267
268 break;
269 }
270
271 case APIC_IOAPIC_ISO: {
272 qemu_log("IOAPIC Interrupt source override!");
273
274 qemu_log("- Bus Source: %d", entry->entry.ioapic_iso.bus_source);
275 qemu_log("- IRQ Source: %d", entry->entry.ioapic_iso.irq_source);
276 qemu_log("- Global System Interrupt: %x", entry->entry.ioapic_iso.global_system_interrupt);
277 qemu_log("- Flags: %x", entry->entry.ioapic_iso.flags);
278
279 break;
280 }
281
282 case APIC_IOAPIC_NMI: {
283 qemu_log("IOAPIC NMI!");
284
285 qemu_log("- Source: %x", entry->entry.ioapic_nmi.source);
286 qemu_log("- Global System Interrupt: %x", entry->entry.ioapic_nmi.global_system_interrupt);
287 qemu_log("- Flags: %x", entry->entry.ioapic_nmi.flags);
288
289 break;
290 }
291
292 case APIC_LAPIC_NMI: {
293 qemu_log("LAPIC NMI!");
294
295 qemu_log("- Processor ID: %d", entry->entry.lapic_nmi.processor_id);
296 qemu_log("- LINT: %d", entry->entry.lapic_nmi.lint);
297 qemu_log("- Flags: %x", entry->entry.lapic_nmi.flags);
298
299 break;
300 }
301
302 default: {
303 qemu_log("Unknown type! [%d]", entry->type);
304
305 goto apic_detect_end;
306 }
307 }
308
309 base_table_end += entry->record_length;
310 }
311
312 apic_detect_end:
313
314 unmap_single_page(get_kernel_page_directory(), rsdt_addr);
315 }
strncmp
int32_t strncmp(const char *s1, const char *s2, size_t num)
Сравнение строк с ограничением количества сравниваемых символов
Definition: string.c:394
memcmp
int32_t memcmp(const char *s1, const char *s2, size_t n)
Сравнение массивов
Definition: string.c:305
ACPISDTHeader
Definition: rsdt.h:5
APIC_Base_Table
Definition: apic_table.h:15
APIC_Entry
Definition: apic_table.h:76
APIC_IOAPIC_ISO
Definition: apic_table.h:36
APIC_IOAPIC_NMI
Definition: apic_table.h:44
APIC_IOAPIC
Definition: apic_table.h:28
APIC_LAPIC_NMI
Definition: apic_table.h:52
APIC_PLAPIC
Definition: apic_table.h:21
FADT
Definition: fadt.h:3
RSDPDescriptor
Definition: rsdp.h:5