Chameleon

Chameleon Svn Source Tree

Root/branches/rekursor/i386/libsaio/acpi.c

1#include "libsaio.h"
2#include "boot.h"
3#include "bootstruct.h"
4#include "acpi.h"
5
6#ifndef DEBUG_ACPI
7#define DEBUG_ACPI 1
8#endif
9
10#if DEBUG_ACPI!=0
11#define DBG(x...) printf(x)
12#else
13#define DBG(x...)
14#endif
15
16/** Search and try opening an acpi table matching a spec defined by key, should be reused anywhere needed:*/
17int acpiSearchAndGetFd(const char * key, const char ** outDirspec)
18{
19 int fd=0;
20 const char * overriden_pathname=NULL;
21 char filename[64];
22 static char dirspec[512]="";
23 int len=0,i=0;
24
25 sprintf(filename, "%s.aml", key);
26
27 /// Take in account user overriding for 'DSDT'.aml table
28 // and try to find <key>.aml at the same place
29 if (getValueForKey("DSDT", &overriden_pathname, &len,
30 &bootInfo->bootConfig) && len>0)
31 {
32 strcpy(dirspec, overriden_pathname);
33 for (i=len-1; i>=0; i--)
34 {
35 if (dirspec[i]=='/')
36 {
37 dirspec[i+1]='\0';
38 strcat(dirspec, filename);
39 break;
40 }
41 else if (i==0) // no '/' found copy filename and seek in current directory
42 {
43 strcpy(dirspec, filename);
44 break;
45 }
46 }
47 fd=open (dirspec,0);
48 if (fd>=0) goto success_fd;
49 }
50
51 // Start searching any potential location for ACPI Table
52 sprintf(dirspec, "/%s", filename); // start searching root
53 fd=open (dirspec,0);
54 if (fd>=0) goto success_fd;
55
56 sprintf(dirspec, "%s", filename); // start current dir
57 fd=open (dirspec,0);
58 if (fd>=0) goto success_fd;
59
60 sprintf(dirspec,"/Extra/%s",filename);
61 fd=open (dirspec,0);
62 if (fd>=0) goto success_fd;
63
64 sprintf(dirspec,"bt(0,0)/Extra/%s",filename);
65 fd=open (dirspec,0);
66 if (fd>=0) goto success_fd;
67
68 // NOT FOUND:
69 verbose("ACPI Table not found: %s\n", filename);
70 if (outDirspec) *outDirspec = "";
71 return -1;
72 // FOUND
73 success_fd:
74 if (outDirspec) *outDirspec = dirspec;
75 return fd;
76}
77
78/** Load a table in kernel memory and return a pointer to it if found, NULL otherwise */
79void *acpiLoadTable (const char * key)
80{
81 void *tableAddr;
82 const char * dirspec=NULL;
83
84 int fd = acpiSearchAndGetFd(key, &dirspec);
85
86 if (fd>=0)
87 {
88 tableAddr=(void*)AllocateKernelMemory(file_size (fd));
89 if (tableAddr)
90 {
91 if (read (fd, tableAddr, file_size (fd))!=file_size (fd))
92 {
93 printf("Couldn't read table %s\n",dirspec);
94 free (tableAddr);
95 close (fd);
96 return NULL;
97 }
98
99 DBG("Table %s read and stored at: %x\n", dirspec, tableAddr);
100 close (fd);
101 return tableAddr;
102 }
103 close (fd);
104 }
105 printf("Couldn't allocate memory for table %s\n", dirspec);
106 return NULL;
107}
108
109/** Load an SSDTx into memory, code could be factorized here using acpiSearchAndGetFd() */
110void * acpiLoadSSDTTable(int ssdt_number)
111{
112 char filename[64];
113
114 sprintf(filename, "SSDT-%d", ssdt_number);
115 return acpiLoadTable(filename);
116}
117
118/** Gets the ACPI 1.0 RSDP address */
119struct acpi_2_rsdp* acpiGetAddressOfTable10()
120{
121 /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
122
123 void *acpi_addr = (void*)ACPI_RANGE_START;
124 for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
125 {
126 if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
127 {
128 uint8_t csum = checksum8(acpi_addr, 20);
129 if(csum == 0)
130 {
131 // Only return the table if it is a true version 1.0 table (Revision 0)
132 if(((struct acpi_2_rsdp*)acpi_addr)->Revision == 0)
133 return acpi_addr;
134 }
135 }
136 }
137 return NULL;
138}
139
140/** Gets the ACPI 2.0 RSDP address */
141struct acpi_2_rsdp* acpiGetAddressOfTable20()
142{
143 /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */
144
145 void *acpi_addr = (void*)ACPI_RANGE_START;
146 for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16)
147 {
148 if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE)
149 {
150 uint8_t csum = checksum8(acpi_addr, 20);
151
152 /* Only assume this is a 2.0 or better table if the revision is greater than 0
153 * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1
154 * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0.
155 */
156
157 if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0))
158 {
159 uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp));
160 if(csum2 == 0)
161 return acpi_addr;
162 }
163 }
164 }
165 return NULL;
166}
167
168/** Fills an ACPI 2.0 GAS structure */
169struct acpi_2_gas acpiFillGASStruct(uint32_t Address, uint8_t Length)
170{
171 struct acpi_2_gas TmpGAS;
172
173 TmpGAS.Address_Space_ID = 1; /* I/O Address */
174
175 if (Address == 0)
176 {
177 TmpGAS.Register_Bit_Width = 0;
178 } else {
179 TmpGAS.Register_Bit_Width = Length * 8;
180 }
181
182 TmpGAS.Register_Bit_Offset = 0;
183 TmpGAS.Access_Size = 0; /* Not set for Legacy reasons... */
184 TmpGAS.Address = (uint64_t)Address;
185
186 return(TmpGAS);
187}
188
189/* Handling acpi dropped tables enumeration */
190
191static struct ACPIDropTableEntry sACPIKeyDropTable[16];
192const int sACPIKeyDropTableSize = sizeof(sACPIKeyDropTableSize) / sizeof(char);
193static int sACPIKeyCount = 0;
194static bool bACPIDropTableInitialized=false;
195
196/* initialize the the dropped table array from user specification, if not done already*/
197static void acpiInitializeDropTables()
198{
199 if (bACPIDropTableInitialized) return;
200 const char * dropTablesEnum = NULL;
201 int len = 0;
202 bool bOverride = getValueForKey(kDrop, &dropTablesEnum, &len, &bootInfo->bootConfig);
203 bACPIDropTableInitialized = true;
204 bzero(sACPIKeyDropTable, sACPIKeyDropTableSize);
205
206 if (!bOverride || !dropTablesEnum || len==0) return;
207
208 // Now transform the whitespace delimited enum into an array of keys:
209 char buffer[sACPIKeyDropTableSize*8];
210 int i,j;
211 // skip beginning whitespaces
212 for (i=0; i < len; i++)
213 if (dropTablesEnum[i]!=' ' && dropTablesEnum[i]!='\t')
214 break;
215 for (;i < len; i++)
216 {
217 j=0;
218 *buffer = '\0';
219 while(i<len && dropTablesEnum[i]!=' ' && dropTablesEnum[i]!='\t')
220 buffer[j++] = dropTablesEnum[i++];
221 buffer[j] = '\0';
222 if(j>0)
223 {
224 DBG("ACPI: Adding Key[%d]: %s\n", sACPIKeyCount, buffer);
225 strncpy(sACPIKeyDropTable[sACPIKeyCount++].key,buffer, ACPI_KEY_MAX_SIZE);
226 }
227 }
228}
229
230static int _current = 0;
231/** Get first acpi drop key*/
232struct ACPIDropTableEntry* acpiGetFirstDropTable()
233{
234 acpiInitializeDropTables();
235 _current = 0;
236 return sACPIKeyCount>0 ? &sACPIKeyDropTable[0] : NULL;
237}
238
239/** Get Next acpi drop key*/
240struct ACPIDropTableEntry* acpiGetNextDropTable()
241{
242 acpiInitializeDropTables();
243 return (_current<sACPIKeyCount) ? &sACPIKeyDropTable[_current++] : NULL;
244}
245
246/* Gets and aml table name and in input and return ture if it is in the DROP list*/
247bool acpiIsTableDropped(const char * key)
248{
249// Note: input key can be non zero terminated
250 struct ACPIDropTableEntry* p;
251 for (p = acpiGetFirstDropTable(); p; p = acpiGetNextDropTable())
252 {
253 if (p->key[0]==key[0] && p->key[1]==key[1] &&
254 p->key[2]==key[2] && p->key[3]==key[3])
255 {
256 DBG("ACPI: Key: %s found in the drop list\n", p);
257 return true;
258 }
259 }
260 DBG("ACPI: Key: %c%c%c%c NOT found in the drop list\n", p);
261 return false;
262}
263/* Return the content of user acpi table if it has been loaded sucessfully, NULL otherwise*/
264void * acpiTableUserContent(const char * key)
265{
266// Note: input key can be non zero terminated
267 struct ACPIDropTableEntry* p;
268 for (p = acpiGetFirstDropTable(); p; p = acpiGetNextDropTable())
269 {
270 if (p->key[0]==key[0] && p->key[1]==key[1] &&
271 p->key[2]==key[2] && p->key[3]==key[3])
272 {
273 return p->content;
274 }
275 }
276 return NULL;
277}
278
279/** For each table in the drop list, try to load an equivalent user table */
280void acpiLoadUserTables()
281{
282 struct ACPIDropTableEntry* p;
283 for (p = acpiGetFirstDropTable(); p; p = acpiGetNextDropTable())
284 {
285 p->content = acpiLoadTable(p->key);
286
287 if (p->content)
288 {
289 DBG("ACPI: User Table %s loaded in Memory\n", p->key);
290 }
291 }
292}
293

Archive Download this file

Revision: 63