Chameleon

Chameleon Svn Source Tree

Root/branches/chucko/i386/libsaio/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 * additions and corrections by Slice and pcj, 2012.
9 */
10
11#include "aml_generator.h"
12
13bool aml_add_to_parent(AML_CHUNK* parent, AML_CHUNK* node)
14{
15if (parent && node)
16{
17switch (parent->Type)
18{
19case AML_CHUNK_NONE:
20case AML_CHUNK_BYTE:
21case AML_CHUNK_WORD:
22case AML_CHUNK_DWORD:
23case AML_CHUNK_QWORD:
24case AML_CHUNK_ALIAS:
25verbose("aml_add_to_parent: Node doesn't support child nodes!\n");
26return false;
27case AML_CHUNK_NAME:
28if (parent->First) {
29verbose("aml_add_to_parent: Name node supports only one child node!\n");
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
52AML_CHUNK* aml_create_node(AML_CHUNK* parent)
53{
54AML_CHUNK* node = (AML_CHUNK*)malloc(sizeof(AML_CHUNK));
55
56aml_add_to_parent(parent, node);
57
58return node;
59}
60
61void aml_destroy_node(AML_CHUNK* node)
62{
63// Delete child nodes
64AML_CHUNK* child = node->First;
65
66while (child)
67{
68AML_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}
82
83free(node);
84}
85
86AML_CHUNK* aml_add_buffer(AML_CHUNK* parent, char* buffer, uint32_t size)
87{
88AML_CHUNK* node = aml_create_node(parent);
89
90if (node) {
91node->Type = AML_CHUNK_NONE;
92node->Length = (uint16_t)size;
93node->Buffer = malloc(node->Length);
94memcpy(node->Buffer, buffer, node->Length);
95}
96
97return node;
98}
99
100AML_CHUNK* aml_add_byte(AML_CHUNK* parent, uint8_t value)
101{
102AML_CHUNK* node = aml_create_node(parent);
103
104if (node) {
105node->Type = AML_CHUNK_BYTE;
106node->Length = 1;
107node->Buffer = malloc(node->Length);
108node->Buffer[0] = value;
109}
110return node;
111}
112
113AML_CHUNK* aml_add_word(AML_CHUNK* parent, uint16_t value)
114{
115AML_CHUNK* node = aml_create_node(parent);
116
117if (node) {
118node->Type = AML_CHUNK_WORD;
119node->Length = 2;
120node->Buffer = malloc(node->Length);
121node->Buffer[0] = value & 0xff;
122node->Buffer[1] = value >> 8;
123}
124return node;
125}
126
127AML_CHUNK* aml_add_dword(AML_CHUNK* parent, uint32_t value)
128{
129AML_CHUNK* node = aml_create_node(parent);
130
131if (node) {
132node->Type = AML_CHUNK_DWORD;
133node->Length = 4;
134node->Buffer = malloc(node->Length);
135node->Buffer[0] = value & 0xff;
136node->Buffer[1] = (value >> 8) & 0xff;
137node->Buffer[2] = (value >> 16) & 0xff;
138node->Buffer[3] = (value >> 24) & 0xff;
139}
140return node;
141}
142
143AML_CHUNK* aml_add_qword(AML_CHUNK* parent, uint64_t value)
144{
145AML_CHUNK* node = aml_create_node(parent);
146
147if (node) {
148node->Type = AML_CHUNK_QWORD;
149node->Length = 8;
150node->Buffer = malloc(node->Length);
151node->Buffer[0] = value & 0xff;
152node->Buffer[1] = (value >> 8) & 0xff;
153node->Buffer[2] = (value >> 16) & 0xff;
154node->Buffer[3] = (value >> 24) & 0xff;
155node->Buffer[4] = (value >> 32) & 0xff;
156node->Buffer[5] = (value >> 40) & 0xff;
157node->Buffer[6] = (value >> 48) & 0xff;
158node->Buffer[7] = (value >> 56) & 0xff;
159}
160return node;
161}
162
163uint32_t aml_fill_simple_name(char* buffer, char* name)
164{
165if (strlen(name) < 4) {
166verbose("aml_fill_simple_name: simple name %s has incorrect lengh! Must be 4.\n", name);
167return 0;
168}
169memcpy(buffer, name, 4);
170return 4;
171}
172
173uint32_t aml_fill_name(AML_CHUNK* node, char* name)
174{
175int len, offset, count;
176uint32_t root = 0;
177
178if (!node) {
179return 0;
180}
181
182len = strlen(name);
183offset = 0;
184count = len >> 2;
185
186if ((len % 4) > 1 || count == 0) {
187verbose("aml_fill_name: pathname %s has incorrect length! Must be 4, 8, 12, 16, etc...\n", name);
188return 0;
189}
190
191if (((len % 4) == 1) && (name[0] == '\\')) {
192root++;
193}
194
195if (count == 1) {
196node->Length = (uint16_t)(4 + root);
197node->Buffer = malloc(node->Length+4);
198memcpy(node->Buffer, name, 4 + root);
199offset += 4 + root;
200return (uint32_t)offset;
201}
202
203if (count == 2) {
204node->Length = 2 + 8;
205node->Buffer = malloc(node->Length+4);
206node->Buffer[offset++] = 0x5c; // Root Char
207node->Buffer[offset++] = 0x2e; // Double name
208memcpy(node->Buffer+offset, name + root, 8);
209offset += 8;
210return (uint32_t)offset;
211}
212
213node->Length = (uint16_t)(3 + (count << 2));
214node->Buffer = malloc(node->Length+4);
215node->Buffer[offset++] = 0x5c; // Root Char
216node->Buffer[offset++] = 0x2f; // Multi name
217node->Buffer[offset++] = (char)count; // Names count
218memcpy(node->Buffer+offset, name + root, count*4);
219offset += count*4;
220return (uint32_t)offset;
221}
222
223AML_CHUNK* aml_add_scope(AML_CHUNK* parent, char* name)
224{
225AML_CHUNK* node = aml_create_node(parent);
226
227if (node) {
228node->Type = AML_CHUNK_SCOPE;
229
230aml_fill_name(node, name);
231}
232return node;
233}
234
235AML_CHUNK* aml_add_name(AML_CHUNK* parent, char* name)
236{
237AML_CHUNK* node = aml_create_node(parent);
238
239if (node) {
240node->Type = AML_CHUNK_NAME;
241
242aml_fill_name(node, name);
243}
244return node;
245}
246
247AML_CHUNK* aml_add_method(AML_CHUNK* parent, char* name, uint8_t args)
248{
249AML_CHUNK* node = aml_create_node(parent);
250
251if (node) {
252unsigned int offset = aml_fill_name(node, name);
253node->Type = AML_CHUNK_METHOD;
254
255node->Length++;
256node->Buffer[offset] = args;
257
258}
259return node;
260}
261
262AML_CHUNK* aml_add_package(AML_CHUNK* parent)
263{
264AML_CHUNK* node = aml_create_node(parent);
265
266if (node) {
267node->Type = AML_CHUNK_PACKAGE;
268
269node->Length = 1;
270node->Buffer = malloc(node->Length);
271}
272return node;
273}
274
275AML_CHUNK* aml_add_alias(AML_CHUNK* parent, char* name1, char* name2)
276{
277AML_CHUNK* node = aml_create_node(parent);
278
279if (node) {
280node->Type = AML_CHUNK_ALIAS;
281
282node->Length = 8;
283node->Buffer = malloc(node->Length);
284aml_fill_simple_name(node->Buffer, name1);
285aml_fill_simple_name(node->Buffer+4, name2);
286}
287
288return node;
289}
290
291AML_CHUNK* aml_add_return_name(AML_CHUNK* parent, char* name)
292{
293AML_CHUNK* node = aml_create_node(parent);
294
295if (node) {
296node->Type = AML_CHUNK_RETURN;
297aml_fill_name(node, name);
298}
299
300return node;
301}
302
303AML_CHUNK* aml_add_return_byte(AML_CHUNK* parent, uint8_t value)
304{
305AML_CHUNK* node = aml_create_node(parent);
306
307if (node) {
308node->Type = AML_CHUNK_RETURN;
309aml_add_byte(node, value);
310}
311
312return node;
313}
314
315AML_CHUNK* aml_add_device(AML_CHUNK* parent, char* name)
316{
317AML_CHUNK* node = aml_create_node(parent);
318
319if (node) {
320node->Type = AML_CHUNK_DEVICE;
321aml_fill_name(node, name);
322}
323
324return node;
325}
326
327AML_CHUNK* aml_add_local0(AML_CHUNK* parent)
328{
329AML_CHUNK* node = aml_create_node(parent);
330
331if (node) {
332node->Type = AML_CHUNK_LOCAL0;
333node->Length = 1;
334}
335
336return node;
337}
338
339AML_CHUNK* aml_add_store(AML_CHUNK* parent)
340{
341AML_CHUNK* node = aml_create_node(parent);
342
343if (node) {
344node->Type = AML_STORE_OP;
345node->Length = 1;
346}
347
348return node;
349}
350
351AML_CHUNK* aml_add_byte_buffer(AML_CHUNK* parent, char* data, uint32_t size)
352{
353AML_CHUNK* node = aml_create_node(parent);
354
355if (node) {
356int offset = 0;
357node->Type = AML_CHUNK_BUFFER;
358node->Length = (uint8_t)(size + 2);
359node->Buffer = malloc (node->Length);
360node->Buffer[offset++] = AML_CHUNK_BYTE; //0x0A
361node->Buffer[offset++] = (char)size;
362memcpy(node->Buffer+offset,data, node->Length);
363}
364
365return node;
366}
367
368AML_CHUNK* aml_add_string_buffer(AML_CHUNK* parent, char* StringBuf)
369{
370AML_CHUNK* node = aml_create_node(parent);
371
372if (node) {
373unsigned int offset = 0;
374unsigned int len = strlen(StringBuf)+1;
375node->Type = AML_CHUNK_BUFFER;
376node->Length = (uint8_t)(len + 3);
377node->Buffer = malloc (node->Length);
378node->Buffer[offset++] = AML_CHUNK_BYTE;
379node->Buffer[offset++] = (char)len;
380memcpy(node->Buffer+offset, StringBuf, len);
381node->Buffer[offset+len] = '\0';
382}
383
384return node;
385}
386
387AML_CHUNK* aml_add_string(AML_CHUNK* parent, char* StringBuf)
388{
389AML_CHUNK* node = aml_create_node(parent);
390
391if (node) {
392int len = strlen(StringBuf);
393node->Type = AML_CHUNK_STRING;
394node->Length = (uint8_t)(len + 1);
395node->Buffer = malloc (len);
396memcpy(node->Buffer, StringBuf, len);
397node->Buffer[len] = '\0';
398}
399
400return node;
401}
402
403AML_CHUNK* aml_add_return(AML_CHUNK* parent)
404{
405AML_CHUNK* node = aml_create_node(parent);
406
407if (node) {
408node->Type = AML_CHUNK_RETURN;
409//aml_add_byte(node, value);
410}
411
412return node;
413}
414
415uint8_t aml_get_size_length(uint32_t size)
416{
417if (size + 1 <= 0x3f)
418return 1;
419else if (size + 2 <= 0xfff) /* Encode in 4 bits and 1 byte */
420return 2;
421else if (size + 3 <= 0xfffff) /* Encode in 4 bits and 2 bytes */
422return 3;
423
424return 4; /* Encode 0xfffffff in 4 bits and 2 bytes */
425}
426
427uint32_t aml_calculate_size(AML_CHUNK* node)
428{
429if (node) {
430// Calculate child nodes size
431AML_CHUNK* child = node->First;
432uint8_t child_count = 0;
433
434node->Size = 0;
435while (child) {
436child_count++;
437
438node->Size += (uint16_t)aml_calculate_size(child);
439
440child = child->Next;
441}
442
443switch (node->Type) {
444case AML_CHUNK_NONE:
445case AML_STORE_OP:
446case AML_CHUNK_LOCAL0:
447node->Size += node->Length;
448break;
449
450case AML_CHUNK_METHOD:
451case AML_CHUNK_SCOPE:
452case AML_CHUNK_BUFFER:
453node->Size += 1 + node->Length;
454node->Size += aml_get_size_length(node->Size);
455break;
456
457case AML_CHUNK_DEVICE:
458node->Size += 2 + node->Length;
459node->Size += aml_get_size_length(node->Size);
460break;
461
462case AML_CHUNK_PACKAGE:
463node->Buffer[0] = child_count;
464node->Size += 1 + node->Length;
465node->Size += aml_get_size_length(node->Size);
466break;
467
468case AML_CHUNK_BYTE:
469if (node->Buffer[0] == 0x0 || node->Buffer[0] == 0x1) {
470node->Size += node->Length;
471} else {
472node->Size += 1 + node->Length;
473}
474break;
475
476case AML_CHUNK_WORD:
477case AML_CHUNK_DWORD:
478case AML_CHUNK_QWORD:
479case AML_CHUNK_ALIAS:
480case AML_CHUNK_NAME:
481case AML_CHUNK_RETURN:
482case AML_CHUNK_STRING:
483node->Size += 1 + node->Length;
484break;
485}
486return node->Size;
487}
488return 0;
489}
490
491uint32_t aml_write_byte(uint8_t value, char* buffer, uint32_t offset)
492{
493buffer[offset++] = value;
494
495return offset;
496}
497
498uint32_t aml_write_word(uint16_t value, char* buffer, uint32_t offset)
499{
500buffer[offset++] = value & 0xff;
501buffer[offset++] = value >> 8;
502
503return offset;
504}
505
506uint32_t aml_write_dword(uint32_t value, char* buffer, uint32_t offset)
507{
508buffer[offset++] = value & 0xff;
509buffer[offset++] = (value >> 8) & 0xff;
510buffer[offset++] = (value >> 16) & 0xff;
511buffer[offset++] = (value >> 24) & 0xff;
512
513return offset;
514}
515
516uint32_t aml_write_qword(uint64_t value, char* buffer, uint32_t offset)
517{
518buffer[offset++] = value & 0xff;
519buffer[offset++] = (value >> 8) & 0xff;
520buffer[offset++] = (value >> 16) & 0xff;
521buffer[offset++] = (value >> 24) & 0xff;
522buffer[offset++] = (value >> 32) & 0xff;
523buffer[offset++] = (value >> 40) & 0xff;
524buffer[offset++] = (value >> 48) & 0xff;
525buffer[offset++] = (value >> 56) & 0xff;
526
527return offset;
528}
529
530uint32_t aml_write_buffer(const char* value, uint32_t size, char* buffer, uint32_t offset)
531{
532if (size > 0) {
533memcpy(buffer + offset, value, size);
534}
535
536return offset + size;
537}
538
539uint32_t aml_write_size(uint32_t size, char* buffer, uint32_t offset)
540{
541if (size <= 0x3f) { /* simple 1 byte length in 6 bits */
542buffer[offset++] = (char)size;
543} else if (size <= 0xfff) {
544buffer[offset++] = 0x40 | (size & 0xf); /* 0x40 is type, 0x0X is first nibble of length */
545buffer[offset++] = (size >> 4) & 0xff; /* +1 bytes for rest length */
546} else if (size <= 0xfffff) {
547buffer[offset++] = 0x80 | (size & 0xf); /* 0x80 is type, 0x0X is first nibble of length */
548buffer[offset++] = (size >> 4) & 0xff; /* +2 bytes for rest length */
549buffer[offset++] = (size >> 12) & 0xff;
550} else {
551buffer[offset++] = 0xc0 | (size & 0xf); /* 0xC0 is type, 0x0X is first nibble of length */
552buffer[offset++] = (size >> 4) & 0xff; /* +3 bytes for rest length */
553buffer[offset++] = (size >> 12) & 0xff;
554buffer[offset++] = (size >> 20) & 0xff;
555}
556
557return offset;
558}
559
560uint32_t aml_write_node(AML_CHUNK* node, char* buffer, uint32_t offset)
561{
562if (node && buffer) {
563uint32_t old = offset;
564AML_CHUNK* child = node->First;
565
566switch (node->Type) {
567case AML_CHUNK_NONE:
568offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
569break;
570
571case AML_CHUNK_LOCAL0:
572case AML_STORE_OP:
573offset = aml_write_byte(node->Type, buffer, offset);
574break;
575
576case AML_CHUNK_DEVICE:
577offset = aml_write_byte(AML_CHUNK_OP, buffer, offset);
578offset = aml_write_byte(node->Type, buffer, offset);
579offset = aml_write_size(node->Size-3, buffer, offset);
580offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
581break;
582
583case AML_CHUNK_SCOPE:
584case AML_CHUNK_METHOD:
585case AML_CHUNK_PACKAGE:
586case AML_CHUNK_BUFFER:
587offset = aml_write_byte(node->Type, buffer, offset);
588offset = aml_write_size(node->Size-1, buffer, offset);
589offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
590break;
591
592case AML_CHUNK_BYTE:
593if (node->Buffer[0] == 0x0 || node->Buffer[0] == 0x1) {
594offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
595} else {
596offset = aml_write_byte(node->Type, buffer, offset);
597offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
598}
599break;
600
601case AML_CHUNK_WORD:
602case AML_CHUNK_DWORD:
603case AML_CHUNK_QWORD:
604case AML_CHUNK_ALIAS:
605case AML_CHUNK_NAME:
606case AML_CHUNK_RETURN:
607case AML_CHUNK_STRING:
608offset = aml_write_byte(node->Type, buffer, offset);
609offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
610break;
611
612default:
613break;
614}
615
616while (child) {
617offset = aml_write_node(child, buffer, offset);
618
619child = child->Next;
620}
621
622if (offset - old != node->Size) {
623verbose("Node size incorrect: type=0x%x size=%x offset=%x\n",
624node->Type, node->Size, (offset - old));
625}
626}
627
628return offset;
629}
630
631//the procedure can find array char sizeof N inside part of large array "dsdt" size of len
632int32_t FindBin (uint8_t *dsdt, uint32_t len, uint8_t *bin, unsigned int N)
633{
634uint32_t i, j;
635bool eq;
636
637for (i=0; i<len-N; i++) {
638eq = true;
639for (j=0; j<N; j++) {
640if (dsdt[i+j] != bin[j]) {
641eq = false;
642break;
643}
644}
645if (eq) {
646return i;
647}
648}
649return 0;
650}
651
652uint32_t get_size(uint8_t* Buffer, uint32_t adr)
653{
654uint32_t temp;
655
656temp = Buffer[adr] & 0xF0; //keep bits 0x30 to check if this is valid size field
657
658if(temp <= 0x30) { // 0
659temp = Buffer[adr];
660} else if(temp == 0x40){// 4
661temp = (Buffer[adr] - 0x40) << 0|
662Buffer[adr+1] << 4;
663} else if(temp == 0x80){// 8
664temp = (Buffer[adr] - 0x80) << 0|
665Buffer[adr+1] << 4|
666Buffer[adr+2] << 12;
667} else if(temp == 0xC0){// C
668temp = (Buffer[adr] - 0xC0) << 0|
669Buffer[adr+1] << 4|
670Buffer[adr+2] << 12|
671Buffer[adr+3] << 20;
672} else {
673verbose("wrong pointer to size field at %x\n", adr);
674return 0; //this means wrong pointer to size field
675}
676return temp;
677}
678

Archive Download this file

Revision: 2337