1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
// Advanced Configuration and Power Interface
// http://wiki.xomb.org/index.php?title=ACPI_Tables
#define FOOLOS_MODULE_NAME "acpi"
#include "lib/logger/log.h"
#include "lib/int/stdint.h"
#include "lib/bool/bool.h"
#include "smp.h"
typedef struct acpi_rsdt_struct
{
char sig[4];
uint32_t length;
uint8_t revision;
uint8_t checksum;
char oemid[6];
char oemtabid[8];
uint32_t oemrevision;
uint32_t vendor;
uint32_t rev;
}acpi_rsdt;
typedef struct aspi_rsdp_struct
{
char sig[8]; //signature
uint8_t checksum;
char oem[6];
uint8_t revision;
uint32_t ptr_rsdt;
uint32_t length;
uint64_t ptr_xsdt; //same info but with 64bit pointers (preferred)
uint8_t checksum_ext;
uint8_t reserved[3];
}acpi_rsdp;
typedef struct
{
char sig[4];
uint32_t length;
uint8_t rev;
uint8_t checksum;
char oemid[6];
char oemtableid[8];
char oemrev[4];
char creatorid[4];
char creatorrev[4];
uint32_t apic_local;
uint32_t flags;
}acpi_madt;
uint8_t *apci_get_next_entry(uint8_t *addr,smp_processors *procdata)
{
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"Examining MADT Entry at 0x%08X",addr);
if(*addr==0)
{
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"MADT Entry: LocalAPIC");
// usable
if(addr[4]&1)
{
if(procdata->processors>=SMP_MAX_PROC){
panic(FOOLOS_MODULE_NAME,"we do not support that many processors. recompile with higher SMP_MAX_PROC.");
}
procdata->local_apic_id[procdata->processors]=addr[3];
procdata->processors++;
}
}
else if(*addr==1)
{
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"MADT Entry: IO APIC");
}
else if(*addr==2)log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"MADT Entry: Interrupt Source Override");
else log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"MADT Entry: type:0x%X",*addr);
return addr+addr[1];
}
void acpi_check_madt(uint32_t *madt,smp_processors *procdata)
{
acpi_madt *table=(acpi_madt *)*madt;
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"Looking for MADT Table at %08X.",table);
if(strcmp("APIC",table->sig,4))
{
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Found MADT Table at 0x%08X",table);
uint8_t *end=(uint8_t *)table;
end+=table->length;
uint8_t *entry=(uint8_t *)table;
entry+=sizeof(acpi_madt);
procdata->local_apic_address=table->apic_local;
while(entry<end)
{
entry=apci_get_next_entry(entry,procdata);
}
}
}
void acpi_read_rsdt(acpi_rsdt *rsdt,smp_processors *procdata)
{
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Reading RSDT Table at 0x%08X",rsdt);
if(!strcmp("RSDT",rsdt->sig,4))
panic(FOOLOS_MODULE_NAME,"Signature MISMATCH!");
int entries=(rsdt->length-sizeof(acpi_rsdt))/4;
uint32_t *first=(uint32_t *)rsdt;
first+=sizeof(acpi_rsdt)/4;
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Entries: %d",entries);
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Looking for MADT Table");
for(int i=0;i<entries;i++)
{
acpi_check_madt(first,procdata);
first++;
}
}
// search for the RSDB table in
// 0x7ffff - 0x9ffff (max)
// 0xe0000 - 0xfffff
bool acpi_find(smp_processors *procdata)
{
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Looking for RSDP Table");
char *search=(char *)0x9f000; //will be 16 bit aligned;
procdata->processors=0;
procdata->boot=0;
while(search<=(char *)0xfffff)
{
if(strcmp("RSD PTR ",search,8)) // notice trailing space in "RSD PTR "
{
uint8_t checksum=0;
for(int i=0;i<20;i++)
checksum+=search[i];
if(checksum==0)
{
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"RSDP Table found at 0x%08X",search);
acpi_rsdp *rsdp=(acpi_rsdp *)search;
acpi_read_rsdt(rsdp->ptr_rsdt,procdata);
return true;
}
}
search++;
if(search==0xa0000)search=0xe0000;
}
return false;
}
|