dtfield.c revision 1.1.1.2.4.2 1 /******************************************************************************
2 *
3 * Module Name: dtfield.c - Code generation for individual source fields
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2011, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44 #define __DTFIELD_C__
45
46 #include "aslcompiler.h"
47 #include "dtcompiler.h"
48
49 #define _COMPONENT DT_COMPILER
50 ACPI_MODULE_NAME ("dtfield")
51
52
53 /* Local prototypes */
54
55 static void
56 DtCompileString (
57 UINT8 *Buffer,
58 DT_FIELD *Field,
59 UINT32 ByteLength);
60
61 static void
62 DtCompileUnicode (
63 UINT8 *Buffer,
64 DT_FIELD *Field,
65 UINT32 ByteLength);
66
67 static ACPI_STATUS
68 DtCompileUuid (
69 UINT8 *Buffer,
70 DT_FIELD *Field,
71 UINT32 ByteLength);
72
73 static char *
74 DtNormalizeBuffer (
75 char *Buffer,
76 UINT32 *Count);
77
78
79 /******************************************************************************
80 *
81 * FUNCTION: DtCompileOneField
82 *
83 * PARAMETERS: Buffer - Output buffer
84 * Field - Field to be compiled
85 * ByteLength - Byte length of the field
86 * Type - Field type
87 *
88 * RETURN: None
89 *
90 * DESCRIPTION: Compile a field value to binary
91 *
92 *****************************************************************************/
93
94 void
95 DtCompileOneField (
96 UINT8 *Buffer,
97 DT_FIELD *Field,
98 UINT32 ByteLength,
99 UINT8 Type,
100 UINT8 Flags)
101 {
102 ACPI_STATUS Status;
103
104 switch (Type)
105 {
106 case DT_FIELD_TYPE_INTEGER:
107 DtCompileInteger (Buffer, Field, ByteLength, Flags);
108 break;
109
110 case DT_FIELD_TYPE_STRING:
111 DtCompileString (Buffer, Field, ByteLength);
112 break;
113
114 case DT_FIELD_TYPE_UUID:
115 Status = DtCompileUuid (Buffer, Field, ByteLength);
116 if (ACPI_SUCCESS (Status))
117 {
118 break;
119 }
120
121 /* Fall through. */
122
123 case DT_FIELD_TYPE_BUFFER:
124 DtCompileBuffer (Buffer, Field->Value, Field, ByteLength);
125 break;
126
127 case DT_FIELD_TYPE_UNICODE:
128 DtCompileUnicode (Buffer, Field, ByteLength);
129 break;
130
131 case DT_FIELD_TYPE_DEVICE_PATH:
132 break;
133
134 default:
135 DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid field type");
136 break;
137 }
138 }
139
140
141 /******************************************************************************
142 *
143 * FUNCTION: DtCompileString
144 *
145 * PARAMETERS: Buffer - Output buffer
146 * Field - String to be copied to buffer
147 * ByteLength - Maximum length of string
148 *
149 * RETURN: None
150 *
151 * DESCRIPTION: Copy string to the buffer
152 *
153 *****************************************************************************/
154
155 static void
156 DtCompileString (
157 UINT8 *Buffer,
158 DT_FIELD *Field,
159 UINT32 ByteLength)
160 {
161 UINT32 Length;
162
163
164 Length = ACPI_STRLEN (Field->Value);
165
166 /* Check if the string is too long for the field */
167
168 if (Length > ByteLength)
169 {
170 sprintf (MsgBuffer, "Maximum %u characters", ByteLength);
171 DtError (ASL_ERROR, ASL_MSG_STRING_LENGTH, Field, MsgBuffer);
172 Length = ByteLength;
173 }
174
175 ACPI_MEMCPY (Buffer, Field->Value, Length);
176 }
177
178
179 /******************************************************************************
180 *
181 * FUNCTION: DtCompileUnicode
182 *
183 * PARAMETERS: Buffer - Output buffer
184 * Field - String to be copied to buffer
185 * ByteLength - Maximum length of string
186 *
187 * RETURN: None
188 *
189 * DESCRIPTION: Convert ASCII string to Unicode string
190 *
191 * Note: The Unicode string is 16 bits per character, no leading signature,
192 * with a 16-bit terminating NULL.
193 *
194 *****************************************************************************/
195
196 static void
197 DtCompileUnicode (
198 UINT8 *Buffer,
199 DT_FIELD *Field,
200 UINT32 ByteLength)
201 {
202 UINT32 Count;
203 UINT32 i;
204 char *AsciiString;
205 UINT16 *UnicodeString;
206
207
208 AsciiString = Field->Value;
209 UnicodeString = (UINT16 *) Buffer;
210 Count = ACPI_STRLEN (AsciiString) + 1;
211
212 /* Convert to Unicode string (including null terminator) */
213
214 for (i = 0; i < Count; i++)
215 {
216 UnicodeString[i] = (UINT16) AsciiString[i];
217 }
218 }
219
220
221 /*******************************************************************************
222 *
223 * FUNCTION: DtCompileUuid
224 *
225 * PARAMETERS: Buffer - Output buffer
226 * Field - String to be copied to buffer
227 * ByteLength - Maximum length of string
228 *
229 * RETURN: None
230 *
231 * DESCRIPTION: Convert UUID string to 16-byte buffer
232 *
233 ******************************************************************************/
234
235 static ACPI_STATUS
236 DtCompileUuid (
237 UINT8 *Buffer,
238 DT_FIELD *Field,
239 UINT32 ByteLength)
240 {
241 char *InString;
242 ACPI_STATUS Status;
243
244
245 InString = Field->Value;
246
247 Status = AuValidateUuid (InString);
248 if (ACPI_FAILURE (Status))
249 {
250 sprintf (MsgBuffer, "%s", Field->Value);
251 DtNameError (ASL_ERROR, ASL_MSG_INVALID_UUID, Field, MsgBuffer);
252 }
253 else
254 {
255 Status = AuConvertStringToUuid (InString, (char *) Buffer);
256 }
257
258 return (Status);
259 }
260
261
262 /******************************************************************************
263 *
264 * FUNCTION: DtCompileInteger
265 *
266 * PARAMETERS: Buffer - Output buffer
267 * Field - Field obj with Integer to be compiled
268 * ByteLength - Byte length of the integer
269 * Flags - Additional compile info
270 *
271 * RETURN: None
272 *
273 * DESCRIPTION: Compile an integer. Supports integer expressions with C-style
274 * operators.
275 *
276 *****************************************************************************/
277
278 void
279 DtCompileInteger (
280 UINT8 *Buffer,
281 DT_FIELD *Field,
282 UINT32 ByteLength,
283 UINT8 Flags)
284 {
285 UINT64 Value;
286 UINT64 MaxValue;
287
288
289 /* Output buffer byte length must be in range 1-8 */
290
291 if ((ByteLength > 8) || (ByteLength == 0))
292 {
293 DtFatal (ASL_MSG_COMPILER_INTERNAL, Field,
294 "Invalid internal Byte length");
295 return;
296 }
297
298 /* Resolve integer expression to a single integer value */
299
300 Value = DtResolveIntegerExpression (Field);
301
302 /* Ensure that reserved fields are set to zero */
303 /* TBD: should we set to zero, or just make this an ERROR? */
304 /* TBD: Probably better to use a flag */
305
306 if (!ACPI_STRCMP (Field->Name, "Reserved") &&
307 (Value != 0))
308 {
309 DtError (ASL_WARNING, ASL_MSG_RESERVED_VALUE, Field,
310 "Setting to zero");
311 Value = 0;
312 }
313
314 /* Check if the value must be non-zero */
315
316 if ((Value == 0) && (Flags & DT_NON_ZERO))
317 {
318 DtError (ASL_ERROR, ASL_MSG_ZERO_VALUE, Field, NULL);
319 }
320
321 /*
322 * Generate the maximum value for the data type (ByteLength)
323 * Note: construct chosen for maximum portability
324 */
325 MaxValue = ((UINT64) (-1)) >> (64 - (ByteLength * 8));
326
327 /* Validate that the input value is within range of the target */
328
329 if (Value > MaxValue)
330 {
331 sprintf (MsgBuffer, "%8.8X%8.8X", ACPI_FORMAT_UINT64 (Value));
332 DtError (ASL_ERROR, ASL_MSG_INTEGER_SIZE, Field, MsgBuffer);
333 }
334
335 ACPI_MEMCPY (Buffer, &Value, ByteLength);
336 return;
337 }
338
339
340 /******************************************************************************
341 *
342 * FUNCTION: DtNormalizeBuffer
343 *
344 * PARAMETERS: Buffer - Input buffer
345 * Count - Output the count of hex number in
346 * the Buffer
347 *
348 * RETURN: The normalized buffer, freed by caller
349 *
350 * DESCRIPTION: [1A,2B,3C,4D] or 1A, 2B, 3C, 4D will be normalized
351 * to 1A 2B 3C 4D
352 *
353 *****************************************************************************/
354
355 static char *
356 DtNormalizeBuffer (
357 char *Buffer,
358 UINT32 *Count)
359 {
360 char *NewBuffer;
361 char *TmpBuffer;
362 UINT32 BufferCount = 0;
363 BOOLEAN Separator = TRUE;
364 char c;
365
366
367 NewBuffer = UtLocalCalloc (ACPI_STRLEN (Buffer) + 1);
368 TmpBuffer = NewBuffer;
369
370 while ((c = *Buffer++))
371 {
372 switch (c)
373 {
374 /* Valid separators */
375
376 case '[':
377 case ']':
378 case ' ':
379 case ',':
380 Separator = TRUE;
381 break;
382
383 default:
384 if (Separator)
385 {
386 /* Insert blank as the standard separator */
387
388 if (NewBuffer[0])
389 {
390 *TmpBuffer++ = ' ';
391 BufferCount++;
392 }
393
394 Separator = FALSE;
395 }
396
397 *TmpBuffer++ = c;
398 break;
399 }
400 }
401
402 *Count = BufferCount + 1;
403 return (NewBuffer);
404 }
405
406
407 /******************************************************************************
408 *
409 * FUNCTION: DtCompileBuffer
410 *
411 * PARAMETERS: Buffer - Output buffer
412 * StringValue - Integer list to be compiled
413 * Field - Current field object
414 * ByteLength - Byte length of the integer list
415 *
416 * RETURN: Count of remaining data in the input list
417 *
418 * DESCRIPTION: Compile and pack an integer list, for example
419 * "AA 1F 20 3B" ==> Buffer[] = {0xAA,0x1F,0x20,0x3B}
420 *
421 *****************************************************************************/
422
423 UINT32
424 DtCompileBuffer (
425 UINT8 *Buffer,
426 char *StringValue,
427 DT_FIELD *Field,
428 UINT32 ByteLength)
429 {
430 ACPI_STATUS Status;
431 char Hex[3];
432 UINT64 Value;
433 UINT32 i;
434 UINT32 Count;
435
436
437 /* Allow several different types of value separators */
438
439 StringValue = DtNormalizeBuffer (StringValue, &Count);
440
441 Hex[2] = 0;
442 for (i = 0; i < Count; i++)
443 {
444 /* Each element of StringValue is three chars */
445
446 Hex[0] = StringValue[(3 * i)];
447 Hex[1] = StringValue[(3 * i) + 1];
448
449 /* Convert one hex byte */
450
451 Value = 0;
452 Status = DtStrtoul64 (Hex, &Value);
453 if (ACPI_FAILURE (Status))
454 {
455 DtError (ASL_ERROR, ASL_MSG_BUFFER_ELEMENT, Field, MsgBuffer);
456 return (ByteLength - Count);
457 }
458
459 Buffer[i] = (UINT8) Value;
460 }
461
462 ACPI_FREE (StringValue);
463 return (ByteLength - Count);
464 }
465
466
467 /******************************************************************************
468 *
469 * FUNCTION: DtCompileFlag
470 *
471 * PARAMETERS: Buffer - Output buffer
472 * Field - Field to be compiled
473 * Info - Flag info
474 *
475 * RETURN:
476 *
477 * DESCRIPTION: Compile a flag
478 *
479 *****************************************************************************/
480
481 void
482 DtCompileFlag (
483 UINT8 *Buffer,
484 DT_FIELD *Field,
485 ACPI_DMTABLE_INFO *Info)
486 {
487 UINT64 Value = 0;
488 UINT32 BitLength = 1;
489 UINT8 BitPosition = 0;
490 ACPI_STATUS Status;
491
492
493 Status = DtStrtoul64 (Field->Value, &Value);
494 if (ACPI_FAILURE (Status))
495 {
496 DtError (ASL_ERROR, ASL_MSG_INVALID_HEX_INTEGER, Field, NULL);
497 }
498
499 switch (Info->Opcode)
500 {
501 case ACPI_DMT_FLAG0:
502 case ACPI_DMT_FLAG1:
503 case ACPI_DMT_FLAG2:
504 case ACPI_DMT_FLAG3:
505 case ACPI_DMT_FLAG4:
506 case ACPI_DMT_FLAG5:
507 case ACPI_DMT_FLAG6:
508 case ACPI_DMT_FLAG7:
509
510 BitPosition = Info->Opcode;
511 BitLength = 1;
512 break;
513
514 case ACPI_DMT_FLAGS0:
515
516 BitPosition = 0;
517 BitLength = 2;
518 break;
519
520
521 case ACPI_DMT_FLAGS2:
522
523 BitPosition = 2;
524 BitLength = 2;
525 break;
526
527 default:
528
529 DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid flag opcode");
530 break;
531 }
532
533 /* Check range of the input flag value */
534
535 if (Value >= ((UINT64) 1 << BitLength))
536 {
537 sprintf (MsgBuffer, "Maximum %u bit", BitLength);
538 DtError (ASL_ERROR, ASL_MSG_FLAG_VALUE, Field, MsgBuffer);
539 Value = 0;
540 }
541
542 *Buffer |= (UINT8) (Value << BitPosition);
543 }
544