Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2425