Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/ACPIPatcher/aml_generator.c

1/*
2 * aml_generator.c
3 * Chameleon
4 *
5 * Created by Mozodojo on 20/07/10.
6 * Copyright 2010 mozo. All rights reserved.
7 *
8 */
9
10#include "aml_generator.h"
11
12bool aml_add_to_parent(struct aml_chunk* parent, struct aml_chunk* node)
13{
14if (parent && node)
15{
16switch (parent->Type)
17{
18case AML_CHUNK_NONE:
19case AML_CHUNK_BYTE:
20case AML_CHUNK_WORD:
21case AML_CHUNK_DWORD:
22case AML_CHUNK_QWORD:
23case AML_CHUNK_ALIAS:
24verbose("aml_add_to_parent: Node isn't supports child nodes!");
25return false;
26case AML_CHUNK_NAME:
27if (parent->First)
28{
29verbose("aml_add_to_parent: Name node could have only one child node!");
30return false;
31}
32break;
33
34default:
35break;
36}
37
38if (!parent->First)
39parent->First = node;
40
41if (parent->Last)
42parent->Last->Next = node;
43
44parent->Last = node;
45
46return true;
47}
48
49return false;
50}
51
52struct aml_chunk* aml_create_node(struct aml_chunk* parent)
53{
54struct aml_chunk* node = (struct aml_chunk*)malloc(sizeof(struct aml_chunk));
55
56aml_add_to_parent(parent, node);
57
58return node;
59}
60
61void aml_destroy_node(struct aml_chunk* node)
62{
63// Delete child nodes
64struct aml_chunk* child = node->First;
65
66while (child)
67{
68struct aml_chunk* next = child->Next;
69
70if (child->Buffer)
71free(child->Buffer);
72
73free(child);
74
75child = next;
76}
77
78// Free node
79if (node->Buffer)
80free(node->Buffer);
81
82free(node);
83}
84
85struct aml_chunk* aml_add_buffer(struct aml_chunk* parent, const char* buffer, unsigned int size)
86{
87struct aml_chunk* node = aml_create_node(parent);
88
89if (node)
90{
91node->Type = AML_CHUNK_NONE;
92node->Length = size;
93node->Buffer = malloc(node->Length);
94memcpy(node->Buffer, buffer, node->Length);
95}
96
97return node;
98}
99
100struct aml_chunk* aml_add_byte(struct aml_chunk* parent, unsigned char value)
101{
102struct aml_chunk* node = aml_create_node(parent);
103
104if (node)
105{
106node->Type = AML_CHUNK_BYTE;
107
108node->Length = 1;
109node->Buffer = malloc(node->Length);
110node->Buffer[0] = value;
111}
112
113return node;
114}
115
116struct aml_chunk* aml_add_word(struct aml_chunk* parent, unsigned int value)
117{
118struct aml_chunk* node = aml_create_node(parent);
119
120if (node)
121{
122node->Type = AML_CHUNK_WORD;
123node->Length = 2;
124node->Buffer = malloc(node->Length);
125node->Buffer[0] = value & 0xff;
126node->Buffer[1] = value >> 8;
127}
128
129return node;
130}
131
132struct aml_chunk* aml_add_dword(struct aml_chunk* parent, unsigned long value)
133{
134struct aml_chunk* node = aml_create_node(parent);
135
136if (node)
137{
138node->Type = AML_CHUNK_DWORD;
139node->Length = 4;
140node->Buffer = malloc(node->Length);
141node->Buffer[0] = value & 0xff;
142node->Buffer[1] = (value >> 8) & 0xff;
143node->Buffer[2] = (value >> 16) & 0xff;
144node->Buffer[3] = (value >> 24) & 0xff;
145}
146
147return node;
148}
149
150struct aml_chunk* aml_add_qword(struct aml_chunk* parent, unsigned long long value)
151{
152struct aml_chunk* node = aml_create_node(parent);
153
154if (node)
155{
156node->Type = AML_CHUNK_QWORD;
157node->Length = 8;
158node->Buffer = malloc(node->Length);
159node->Buffer[0] = value & 0xff;
160node->Buffer[1] = (value >> 8) & 0xff;
161node->Buffer[2] = (value >> 16) & 0xff;
162node->Buffer[3] = (value >> 24) & 0xff;
163node->Buffer[4] = (value >> 32) & 0xff;
164node->Buffer[5] = (value >> 40) & 0xff;
165node->Buffer[6] = (value >> 48) & 0xff;
166node->Buffer[7] = (value >> 56) & 0xff;
167}
168
169return node;
170}
171
172unsigned int aml_fill_simple_name(char* buffer, const char* name)
173{
174if (strlen(name) < 4)
175{
176verbose("aml_fill_simple_name: simple name %s has incorrect lengh! Must be 4", name);
177return 0;
178}
179
180memcpy(buffer, name, 4);
181return 4;
182}
183
184unsigned int aml_fill_name(struct aml_chunk* node, const char* name)
185{
186if (!node)
187return 0;
188
189int len = strlen(name), offset = 0, count = len / 4;
190
191if ((len % 4) > 1 || count == 0)
192{
193verbose("aml_fill_name: pathname %s has incorrect length! Must be 4, 8, 12, 16 etc.", name);
194return 0;
195}
196
197unsigned int root = 0;
198
199if ((len % 4) == 1 && name[0] == '\\')
200root++;
201
202if (count == 1)
203{
204node->Length = 4 + root;
205node->Buffer = malloc(node->Length);
206memcpy(node->Buffer, name, 4 + root);
207return node->Length;
208}
209
210if (count == 2)
211{
212node->Length = 2 + 8;
213node->Buffer = malloc(node->Length);
214node->Buffer[offset++] = 0x5c; // Root Char
215node->Buffer[offset++] = 0x2e; // Double name
216memcpy(node->Buffer+offset, name + root, 8);
217return node->Length;
218}
219
220node->Length = 3 + count*4;
221node->Buffer = malloc(node->Length);
222node->Buffer[offset++] = 0x5c; // Root Char
223node->Buffer[offset++] = 0x2f; // Multi name
224node->Buffer[offset++] = count; // Names count
225memcpy(node->Buffer+offset, name + root, count*4);
226
227return node->Length;
228}
229
230struct aml_chunk* aml_add_scope(struct aml_chunk* parent, const char* name)
231{
232struct aml_chunk* node = aml_create_node(parent);
233
234if (node)
235{
236node->Type = AML_CHUNK_SCOPE;
237
238aml_fill_name(node, name);
239}
240
241return node;
242}
243
244struct aml_chunk* aml_add_name(struct aml_chunk* parent, const char* name)
245{
246struct aml_chunk* node = aml_create_node(parent);
247
248if (node)
249{
250node->Type = AML_CHUNK_NAME;
251
252aml_fill_name(node, name);
253}
254
255return node;
256}
257
258struct aml_chunk* aml_add_package(struct aml_chunk* parent)
259{
260struct aml_chunk* node = aml_create_node(parent);
261
262if (node)
263{
264node->Type = AML_CHUNK_PACKAGE;
265
266node->Length = 1;
267node->Buffer = malloc(node->Length);
268}
269
270return node;
271}
272
273struct aml_chunk* aml_add_package_with_value(struct aml_chunk* parent, uint64_t *lst, int num)
274{
275struct aml_chunk* node = aml_create_node(parent);
276
277if (node)
278{
279node->Type = AML_CHUNK_PACKAGE;
280node->Length = 1;
281node->Buffer = malloc(node->Length);
282aml_add_multiple_value(node,lst,num);
283
284}
285
286return node;
287}
288
289void aml_add_value(struct aml_chunk* parent, uint64_t val)
290{
291if (parent)
292{
293if (val > 0xffffffff)
294aml_add_qword(parent,val);
295else if (val > 0xffff)
296aml_add_dword(parent,val);
297else if (val > 0xff)
298aml_add_word(parent,val);
299else if (val >= 0)
300aml_add_byte(parent, val);
301}
302
303}
304
305void aml_add_multiple_value(struct aml_chunk* parent, uint64_t *lst, int num)
306{
307if (parent)
308{
309int i;
310for (i=0; i<(num / 8); i++) {
311
312aml_add_value(parent, lst[i]);
313}
314}
315
316}
317
318struct aml_chunk* aml_add_alias(struct aml_chunk* parent, const char* name1, const char* name2)
319{
320struct aml_chunk* node = aml_create_node(parent);
321
322if (node)
323{
324node->Type = AML_CHUNK_ALIAS;
325
326node->Length = 8;
327node->Buffer = malloc(node->Length);
328aml_fill_simple_name(node->Buffer, name1);
329aml_fill_simple_name(node->Buffer+4, name2);
330}
331
332return node;
333}
334
335unsigned char aml_get_size_length(unsigned int size)
336{
337if (size + 1 <= 0x3f)
338return 1;
339else if (size + 2 <= 0x3fff)
340return 2;
341else if (size + 3 <= 0x3fffff)
342return 3;
343
344return 4;
345}
346
347unsigned int aml_calculate_size(struct aml_chunk* node)
348{
349if (node)
350{
351node->Size = 0;
352
353// Calculate child nodes size
354struct aml_chunk* child = node->First;
355unsigned char child_count = 0;
356
357while (child)
358{
359child_count++;
360
361node->Size += aml_calculate_size(child);
362
363child = child->Next;
364}
365
366switch (node->Type)
367{
368case AML_CHUNK_NONE:
369node->Size += node->Length;
370break;
371case AML_CHUNK_SCOPE:
372node->Size += 1 + node->Length;
373node->Size += aml_get_size_length(node->Size);
374break;
375case AML_CHUNK_PACKAGE:
376node->Buffer[0] = child_count;
377node->Size += 1 + node->Length;
378node->Size += aml_get_size_length(node->Size);
379break;
380
381case AML_CHUNK_BYTE:
382if (node->Buffer[0] == 0x0 || node->Buffer[0] == 0x1)
383{
384node->Size += node->Length;
385}
386else
387{
388node->Size += 1 + node->Length;
389}
390
391break;
392
393case AML_CHUNK_WORD:
394case AML_CHUNK_DWORD:
395case AML_CHUNK_QWORD:
396case AML_CHUNK_ALIAS:
397case AML_CHUNK_NAME:
398node->Size += 1 + node->Length;
399break;
400}
401
402return node->Size;
403}
404
405return 0;
406}
407
408unsigned int aml_write_byte(unsigned char value, char* buffer, unsigned int offset)
409{
410buffer[offset++] = value;
411
412return offset;
413}
414
415unsigned int aml_write_word(unsigned int value, char* buffer, unsigned int offset)
416{
417buffer[offset++] = value & 0xff;
418buffer[offset++] = value >> 8;
419
420return offset;
421}
422
423unsigned int aml_write_dword(unsigned long value, char* buffer, unsigned int offset)
424{
425buffer[offset++] = value & 0xff;
426buffer[offset++] = (value >> 8) & 0xff;
427buffer[offset++] = (value >> 16) & 0xff;
428buffer[offset++] = (value >> 24) & 0xff;
429
430return offset;
431}
432
433unsigned int aml_write_qword(unsigned long long value, char* buffer, unsigned int offset)
434{
435buffer[offset++] = value & 0xff;
436buffer[offset++] = (value >> 8) & 0xff;
437buffer[offset++] = (value >> 16) & 0xff;
438buffer[offset++] = (value >> 24) & 0xff;
439buffer[offset++] = (value >> 32) & 0xff;
440buffer[offset++] = (value >> 40) & 0xff;
441buffer[offset++] = (value >> 48) & 0xff;
442buffer[offset++] = (value >> 56) & 0xff;
443
444return offset;
445}
446
447unsigned int aml_write_buffer(const char* value, unsigned int size, char* buffer, unsigned int offset)
448{
449if (size > 0)
450{
451memcpy(buffer + offset, value, size);
452}
453
454return offset + size;
455}
456
457void aml_add_ressource_t_fxhw(struct aml_chunk* parent, uint64_t *lst)
458{
459if (parent) {
460char resource_template[] =
461{
4620x11, 0x14, 0x0A, 0x11, 0x82, 0x0C, 0x00, 0x7F,
4630x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
4640x00, 0x00, 0x00, 0x79, 0x00
465};
466
467char *buffer = resource_template;
468unsigned int offset = aml_write_byte(lst[0], buffer, 8);
469offset = aml_write_byte(lst[1], buffer, offset);
470offset = aml_write_byte(lst[2], buffer, offset);
471aml_write_qword(lst[3], buffer, offset);
472aml_add_buffer(parent, buffer, sizeof(resource_template));
473}
474}
475
476unsigned int aml_write_size(unsigned int size, char* buffer, unsigned int offset)
477{
478if (size <= 0x3f)
479{
480buffer[offset++] = size;
481}
482else if (size <= 0x3fff)
483{
484buffer[offset++] = 0x40 | (size & 0xf);
485buffer[offset++] = (size >> 4) & 0xff;
486}
487else if (size <= 0x3fffff)
488{
489buffer[offset++] = 0x80 | (size & 0xf);
490buffer[offset++] = (size >> 4) & 0xff;
491buffer[offset++] = (size >> 12) & 0xff;
492}
493 else
494{
495buffer[offset++] = 0xc0 | (size & 0xf);
496buffer[offset++] = (size >> 4) & 0xff;
497buffer[offset++] = (size >> 12) & 0xff;
498buffer[offset++] = (size >> 20) & 0xff;
499}
500
501return offset;
502}
503
504unsigned int aml_write_node(struct aml_chunk* node, char* buffer, unsigned int offset)
505{
506if (node && buffer)
507{
508unsigned int old = offset;
509
510switch (node->Type)
511{
512case AML_CHUNK_NONE:
513offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
514break;
515
516case AML_CHUNK_SCOPE:
517case AML_CHUNK_PACKAGE:
518offset = aml_write_byte(node->Type, buffer, offset);
519offset = aml_write_size(node->Size-1, buffer, offset);
520offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
521break;
522
523case AML_CHUNK_BYTE:
524if (node->Buffer[0] == 0x0 || node->Buffer[0] == 0x1)
525{
526offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
527}
528else
529{
530offset = aml_write_byte(node->Type, buffer, offset);
531offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
532}
533break;
534
535case AML_CHUNK_WORD:
536case AML_CHUNK_DWORD:
537case AML_CHUNK_QWORD:
538case AML_CHUNK_ALIAS:
539case AML_CHUNK_NAME:
540offset = aml_write_byte(node->Type, buffer, offset);
541offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
542break;
543
544default:
545break;
546}
547
548struct aml_chunk* child = node->First;
549
550while (child)
551{
552offset = aml_write_node(child, buffer, offset);
553
554child = child->Next;
555}
556
557if (offset - old != node->Size)
558verbose("Node size incorrect: 0x%x\n", node->Type);
559}
560
561return offset;
562}

Archive Download this file

Revision: 789