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 }
int32_t strncmp(const char *s1, const char *s2, size_t num)
Сравнение строк с ограничением количества сравниваемых символов
Definition: string.c:394
int32_t memcmp(const char *s1, const char *s2, size_t n)
Сравнение массивов
Definition: string.c:305
Definition: apic_table.h:76
Definition: fadt.h:3