Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/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 */
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);
207
208return node->Length;
209}
210
211if (count == 2)
212{
213node->Length = 2 + 8;
214node->Buffer = malloc(node->Length);
215node->Buffer[offset++] = 0x5c; // Root Char
216node->Buffer[offset++] = 0x2e; // Double name
217memcpy(node->Buffer+offset, name + root, 8);
218return node->Length;
219}
220
221node->Length = 3 + count*4;
222node->Buffer = malloc(node->Length);
223node->Buffer[offset++] = 0x5c; // Root Char
224node->Buffer[offset++] = 0x2f; // Multi name
225node->Buffer[offset++] = count; // Names count
226memcpy(node->Buffer+offset, name + root, count*4);
227
228return node->Length;
229}
230
231struct aml_chunk* aml_add_scope(struct aml_chunk* parent, const char* name)
232{
233struct aml_chunk* node = aml_create_node(parent);
234
235if (node)
236{
237node->Type = AML_CHUNK_SCOPE;
238
239aml_fill_name(node, name);
240}
241
242return node;
243}
244
245struct aml_chunk* aml_add_name(struct aml_chunk* parent, const char* name)
246{
247struct aml_chunk* node = aml_create_node(parent);
248
249if (node)
250{
251node->Type = AML_CHUNK_NAME;
252
253aml_fill_name(node, name);
254}
255
256return node;
257}
258
259struct aml_chunk* aml_add_package(struct aml_chunk* parent)
260{
261struct aml_chunk* node = aml_create_node(parent);
262
263if (node)
264{
265node->Type = AML_CHUNK_PACKAGE;
266
267node->Length = 1;
268node->Buffer = malloc(node->Length);
269}
270
271return node;
272}
273
274struct aml_chunk* aml_add_alias(struct aml_chunk* parent, const char* name1, const char* name2)
275{
276struct aml_chunk* node = aml_create_node(parent);
277
278if (node)
279{
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
291unsigned char aml_get_size_length(unsigned int size)
292{
293if (size + 1 <= 0x3f)
294return 1;
295else if (size + 2 <= 0xfff) /* Encode in 4 bits and 1 byte */
296return 2;
297else if (size + 3 <= 0xfffff) /* Encode in 4 bits and 2 bytes */
298return 3;
299
300return 4; /* Encode 0xfffffff in 4 bits and 2 bytes */
301}
302
303unsigned int aml_calculate_size(struct aml_chunk* node)
304{
305if (node)
306{
307node->Size = 0;
308
309// Calculate child nodes size
310struct aml_chunk* child = node->First;
311unsigned char child_count = 0;
312
313while (child)
314{
315child_count++;
316
317node->Size += aml_calculate_size(child);
318
319child = child->Next;
320}
321
322switch (node->Type)
323{
324case AML_CHUNK_NONE:
325node->Size += node->Length;
326break;
327case AML_CHUNK_SCOPE:
328node->Size += 1 + node->Length;
329node->Size += aml_get_size_length(node->Size);
330break;
331case AML_CHUNK_PACKAGE:
332node->Buffer[0] = child_count;
333node->Size += 1 + node->Length;
334node->Size += aml_get_size_length(node->Size);
335break;
336
337case AML_CHUNK_BYTE:
338if (node->Buffer[0] == 0x0 || node->Buffer[0] == 0x1)
339{
340node->Size += node->Length;
341}
342else
343{
344node->Size += 1 + node->Length;
345}
346
347break;
348
349case AML_CHUNK_WORD:
350case AML_CHUNK_DWORD:
351case AML_CHUNK_QWORD:
352case AML_CHUNK_ALIAS:
353case AML_CHUNK_NAME:
354node->Size += 1 + node->Length;
355break;
356}
357
358return node->Size;
359}
360
361return 0;
362}
363
364unsigned int aml_write_byte(unsigned char value, char* buffer, unsigned int offset)
365{
366buffer[offset++] = value;
367
368return offset;
369}
370
371unsigned int aml_write_word(unsigned int value, char* buffer, unsigned int offset)
372{
373buffer[offset++] = value & 0xff;
374buffer[offset++] = value >> 8;
375
376return offset;
377}
378
379unsigned int aml_write_dword(unsigned long value, char* buffer, unsigned int offset)
380{
381buffer[offset++] = value & 0xff;
382buffer[offset++] = (value >> 8) & 0xff;
383buffer[offset++] = (value >> 16) & 0xff;
384buffer[offset++] = (value >> 24) & 0xff;
385
386return offset;
387}
388
389unsigned int aml_write_qword(unsigned long long value, char* buffer, unsigned int offset)
390{
391buffer[offset++] = value & 0xff;
392buffer[offset++] = (value >> 8) & 0xff;
393buffer[offset++] = (value >> 16) & 0xff;
394buffer[offset++] = (value >> 24) & 0xff;
395buffer[offset++] = (value >> 32) & 0xff;
396buffer[offset++] = (value >> 40) & 0xff;
397buffer[offset++] = (value >> 48) & 0xff;
398buffer[offset++] = (value >> 56) & 0xff;
399
400return offset;
401}
402
403unsigned int aml_write_buffer(const char* value, unsigned int size, char* buffer, unsigned int offset)
404{
405if (size > 0)
406{
407memcpy(buffer + offset, value, size);
408}
409
410return offset + size;
411}
412
413unsigned int aml_write_size(unsigned int size, char* buffer, unsigned int offset)
414{
415if (size <= 0x3f) /* simple 1 byte length in 6 bits */
416{
417buffer[offset++] = size;
418}
419else if (size <= 0xfff)
420{
421buffer[offset++] = 0x40 | (size & 0xf); /* 0x40 is type, 0x0X is first nibble of length */
422buffer[offset++] = (size >> 4) & 0xff; /* +1 bytes for rest length */
423}
424else if (size <= 0xfffff)
425{
426buffer[offset++] = 0x80 | (size & 0xf); /* 0x80 is type, 0x0X is first nibble of length */
427buffer[offset++] = (size >> 4) & 0xff; /* +2 bytes for rest length */
428buffer[offset++] = (size >> 12) & 0xff;
429}
430 else
431{
432buffer[offset++] = 0xc0 | (size & 0xf); /* 0xC0 is type, 0x0X is first nibble of length */
433buffer[offset++] = (size >> 4) & 0xff; /* +3 bytes for rest length */
434buffer[offset++] = (size >> 12) & 0xff;
435buffer[offset++] = (size >> 20) & 0xff;
436}
437
438return offset;
439}
440
441unsigned int aml_write_node(struct aml_chunk* node, char* buffer, unsigned int offset)
442{
443if (node && buffer)
444{
445unsigned int old = offset;
446
447switch (node->Type)
448{
449case AML_CHUNK_NONE:
450offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
451break;
452
453case AML_CHUNK_SCOPE:
454case AML_CHUNK_PACKAGE:
455offset = aml_write_byte(node->Type, buffer, offset);
456offset = aml_write_size(node->Size-1, buffer, offset);
457offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
458break;
459
460case AML_CHUNK_BYTE:
461if (node->Buffer[0] == 0x0 || node->Buffer[0] == 0x1)
462{
463offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
464}
465else
466{
467offset = aml_write_byte(node->Type, buffer, offset);
468offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
469}
470break;
471
472case AML_CHUNK_WORD:
473case AML_CHUNK_DWORD:
474case AML_CHUNK_QWORD:
475case AML_CHUNK_ALIAS:
476case AML_CHUNK_NAME:
477offset = aml_write_byte(node->Type, buffer, offset);
478offset = aml_write_buffer(node->Buffer, node->Length, buffer, offset);
479break;
480
481default:
482break;
483}
484
485struct aml_chunk* child = node->First;
486
487while (child)
488{
489offset = aml_write_node(child, buffer, offset);
490
491child = child->Next;
492}
493
494if (offset - old != node->Size)
495verbose("Node size incorrect: type=0x%x size=%x offset=%x\n",
496node->Type, node->Size, (offset - old));
497}
498
499return offset;
500}
501

Archive Download this file

Revision: 2004