Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Modules/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 */
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 doesn't support child nodes!\n");
25return false;
26case AML_CHUNK_NAME:
27if (parent->First)
28{
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
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.\n", 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...\n", 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_alias(struct aml_chunk* parent, const char* name1, const char* name2)
274{
275struct aml_chunk* node = aml_create_node(parent);
276
277if (node)
278{
279node->Type = AML_CHUNK_ALIAS;
280
281node->Length = 8;
282node->Buffer = malloc(node->Length);
283aml_fill_simple_name(node->Buffer, name1);
284aml_fill_simple_name(node->Buffer+4, name2);
285}
286
287return node;
288}
289
290unsigned char aml_get_size_length(unsigned int size)
291{
292if (size + 1 <= 0x3f)
293return 1;
294else if (size + 2 <= 0x3fff)
295return 2;
296else if (size + 3 <= 0x3fffff)
297return 3;
298
299return 4;
300}
301
302unsigned int aml_calculate_size(struct aml_chunk* node)
303{
304if (node)
305{
306node->Size = 0;
307
308// Calculate child nodes size
309struct aml_chunk* child = node->First;
310unsigned char child_count = 0;
311
312while (child)
313{
314child_count++;
315
316node->Size += aml_calculate_size(child);
317
318child = child->Next;
319}
320
321switch (node->Type)
322{
323case AML_CHUNK_NONE:
324node->Size += node->Length;
325break;
326case AML_CHUNK_SCOPE:
327node->Size += 1 + node->Length;
328node->Size += aml_get_size_length(node->Size);
329break;
330case AML_CHUNK_PACKAGE:
331node->Buffer[0] = child_count;
332node->Size += 1 + node->Length;
333node->Size += aml_get_size_length(node->Size);
334break;
335
336case AML_CHUNK_BYTE:
337if (node->Buffer[0] == 0x0 || node->Buffer[0] == 0x1)
338{
339node->Size += node->Length;
340}
341else
342{
343node->Size += 1 + node->Length;
344}
345
346break;
347
348case AML_CHUNK_WORD:
349case AML_CHUNK_DWORD:
350case AML_CHUNK_QWORD:
351case AML_CHUNK_ALIAS:
352case AML_CHUNK_NAME:
353node->Size += 1 + node->Length;
354break;
355}
356
357return node->Size;
358}
359
360return 0;
361}
362
363unsigned int aml_write_byte(unsigned char value, char* buffer, unsigned int offset)
364{
365buffer[offset++] = value;
366
367return offset;
368}
369
370unsigned int aml_write_word(unsigned int value, char* buffer, unsigned int offset)
371{
372buffer[offset++] = value & 0xff;
373buffer[offset++] = value >> 8;
374
375return offset;
376}
377
378unsigned int aml_write_dword(unsigned long value, char* buffer, unsigned int offset)
379{
380buffer[offset++] = value & 0xff;
381buffer[offset++] = (value >> 8) & 0xff;
382buffer[offset++] = (value >> 16) & 0xff;
383buffer[offset++] = (value >> 24) & 0xff;
384
385return offset;
386}
387
388unsigned int aml_write_qword(unsigned long long value, char* buffer, unsigned int offset)
389{
390buffer[offset++] = value & 0xff;
391buffer[offset++] = (value >> 8) & 0xff;
392buffer[offset++] = (value >> 16) & 0xff;
393buffer[offset++] = (value >> 24) & 0xff;
394buffer[offset++] = (value >> 32) & 0xff;
395buffer[offset++] = (value >> 40) & 0xff;
396buffer[offset++] = (value >> 48) & 0xff;
397buffer[offset++] = (value >> 56) & 0xff;
398
399return offset;
400}
401
402unsigned int aml_write_buffer(const char* value, unsigned int size, char* buffer, unsigned int offset)
403{
404if (size > 0)
405{
406memcpy(buffer + offset, value, size);
407}
408
409return offset + size;
410}
411
412unsigned int aml_write_size(unsigned int size, char* buffer, unsigned int offset)
413{
414if (size <= 0x3f)
415{
416buffer[offset++] = size;
417}
418else if (size <= 0x3fff)
419{
420buffer[offset++] = 0x40 | (size & 0xf);
421buffer[offset++] = (size >> 4) & 0xff;
422}
423else if (size <= 0x3fffff)
424{
425buffer[offset++] = 0x80 | (size & 0xf);
426buffer[offset++] = (size >> 4) & 0xff;
427buffer[offset++] = (size >> 12) & 0xff;
428}
429 else
430{
431buffer[offset++] = 0xc0 | (size & 0xf);
432buffer[offset++] = (size >> 4) & 0xff;
433buffer[offset++] = (size >> 12) & 0xff;
434buffer[offset++] = (size >> 20) & 0xff;
435}
436
437return offset;
438}
439
440unsigned int aml_write_node(struct aml_chunk* node, char* buffer, unsigned int offset)
441{
442if (node && buffer)
443{
444unsigned int old = offset;
445
446switch (node->Type)
447{
448case AML_CHUNK_NONE:
449offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
450break;
451
452case AML_CHUNK_SCOPE:
453case AML_CHUNK_PACKAGE:
454offset = aml_write_byte(node->Type, buffer, offset);
455offset = aml_write_size(node->Size-1, buffer, offset);
456offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
457break;
458
459case AML_CHUNK_BYTE:
460if (node->Buffer[0] == 0x0 || node->Buffer[0] == 0x1)
461{
462offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
463}
464else
465{
466offset = aml_write_byte(node->Type, buffer, offset);
467offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
468}
469break;
470
471case AML_CHUNK_WORD:
472case AML_CHUNK_DWORD:
473case AML_CHUNK_QWORD:
474case AML_CHUNK_ALIAS:
475case AML_CHUNK_NAME:
476offset = aml_write_byte(node->Type, buffer, offset);
477offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
478break;
479
480default:
481break;
482}
483
484struct aml_chunk* child = node->First;
485
486while (child)
487{
488offset = aml_write_node(child, buffer, offset);
489
490child = child->Next;
491}
492
493if (offset - old != node->Size)
494verbose("Node size incorrect: 0x%x\n", node->Type);
495}
496
497return offset;
498}
499

Archive Download this file

Revision: 1621