Fixed compatibility of output.
[AROS.git] / arch / all-pc / acpica / source / compiler / dtfield.c
bloba5642a114890ed5206dfa00cc9da2323083cb1c6
1 /******************************************************************************
3 * Module Name: dtfield.c - Code generation for individual source fields
5 *****************************************************************************/
7 /*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
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.
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.
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.
44 #define __DTFIELD_C__
46 #include "aslcompiler.h"
47 #include "dtcompiler.h"
49 #define _COMPONENT DT_COMPILER
50 ACPI_MODULE_NAME ("dtfield")
53 /* Local prototypes */
55 static void
56 DtCompileString (
57 UINT8 *Buffer,
58 DT_FIELD *Field,
59 UINT32 ByteLength);
61 static void
62 DtCompileUnicode (
63 UINT8 *Buffer,
64 DT_FIELD *Field,
65 UINT32 ByteLength);
67 static ACPI_STATUS
68 DtCompileUuid (
69 UINT8 *Buffer,
70 DT_FIELD *Field,
71 UINT32 ByteLength);
73 static char *
74 DtNormalizeBuffer (
75 char *Buffer,
76 UINT32 *Count);
79 /******************************************************************************
81 * FUNCTION: DtCompileOneField
83 * PARAMETERS: Buffer - Output buffer
84 * Field - Field to be compiled
85 * ByteLength - Byte length of the field
86 * Type - Field type
88 * RETURN: None
90 * DESCRIPTION: Compile a field value to binary
92 *****************************************************************************/
94 void
95 DtCompileOneField (
96 UINT8 *Buffer,
97 DT_FIELD *Field,
98 UINT32 ByteLength,
99 UINT8 Type,
100 UINT8 Flags)
102 ACPI_STATUS Status;
104 switch (Type)
106 case DT_FIELD_TYPE_INTEGER:
108 DtCompileInteger (Buffer, Field, ByteLength, Flags);
109 break;
111 case DT_FIELD_TYPE_STRING:
113 DtCompileString (Buffer, Field, ByteLength);
114 break;
116 case DT_FIELD_TYPE_UUID:
118 Status = DtCompileUuid (Buffer, Field, ByteLength);
119 if (ACPI_SUCCESS (Status))
121 break;
124 /* Fall through. */
126 case DT_FIELD_TYPE_BUFFER:
128 DtCompileBuffer (Buffer, Field->Value, Field, ByteLength);
129 break;
131 case DT_FIELD_TYPE_UNICODE:
133 DtCompileUnicode (Buffer, Field, ByteLength);
134 break;
136 case DT_FIELD_TYPE_DEVICE_PATH:
138 break;
140 default:
142 DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid field type");
143 break;
148 /******************************************************************************
150 * FUNCTION: DtCompileString
152 * PARAMETERS: Buffer - Output buffer
153 * Field - String to be copied to buffer
154 * ByteLength - Maximum length of string
156 * RETURN: None
158 * DESCRIPTION: Copy string to the buffer
160 *****************************************************************************/
162 static void
163 DtCompileString (
164 UINT8 *Buffer,
165 DT_FIELD *Field,
166 UINT32 ByteLength)
168 UINT32 Length;
171 Length = ACPI_STRLEN (Field->Value);
173 /* Check if the string is too long for the field */
175 if (Length > ByteLength)
177 sprintf (MsgBuffer, "Maximum %u characters", ByteLength);
178 DtError (ASL_ERROR, ASL_MSG_STRING_LENGTH, Field, MsgBuffer);
179 Length = ByteLength;
182 ACPI_MEMCPY (Buffer, Field->Value, Length);
186 /******************************************************************************
188 * FUNCTION: DtCompileUnicode
190 * PARAMETERS: Buffer - Output buffer
191 * Field - String to be copied to buffer
192 * ByteLength - Maximum length of string
194 * RETURN: None
196 * DESCRIPTION: Convert ASCII string to Unicode string
198 * Note: The Unicode string is 16 bits per character, no leading signature,
199 * with a 16-bit terminating NULL.
201 *****************************************************************************/
203 static void
204 DtCompileUnicode (
205 UINT8 *Buffer,
206 DT_FIELD *Field,
207 UINT32 ByteLength)
209 UINT32 Count;
210 UINT32 i;
211 char *AsciiString;
212 UINT16 *UnicodeString;
215 AsciiString = Field->Value;
216 UnicodeString = (UINT16 *) Buffer;
217 Count = ACPI_STRLEN (AsciiString) + 1;
219 /* Convert to Unicode string (including null terminator) */
221 for (i = 0; i < Count; i++)
223 UnicodeString[i] = (UINT16) AsciiString[i];
228 /*******************************************************************************
230 * FUNCTION: DtCompileUuid
232 * PARAMETERS: Buffer - Output buffer
233 * Field - String to be copied to buffer
234 * ByteLength - Maximum length of string
236 * RETURN: None
238 * DESCRIPTION: Convert UUID string to 16-byte buffer
240 ******************************************************************************/
242 static ACPI_STATUS
243 DtCompileUuid (
244 UINT8 *Buffer,
245 DT_FIELD *Field,
246 UINT32 ByteLength)
248 char *InString;
249 ACPI_STATUS Status;
252 InString = Field->Value;
254 Status = AuValidateUuid (InString);
255 if (ACPI_FAILURE (Status))
257 sprintf (MsgBuffer, "%s", Field->Value);
258 DtNameError (ASL_ERROR, ASL_MSG_INVALID_UUID, Field, MsgBuffer);
260 else
262 Status = AuConvertStringToUuid (InString, (char *) Buffer);
265 return (Status);
269 /******************************************************************************
271 * FUNCTION: DtCompileInteger
273 * PARAMETERS: Buffer - Output buffer
274 * Field - Field obj with Integer to be compiled
275 * ByteLength - Byte length of the integer
276 * Flags - Additional compile info
278 * RETURN: None
280 * DESCRIPTION: Compile an integer. Supports integer expressions with C-style
281 * operators.
283 *****************************************************************************/
285 void
286 DtCompileInteger (
287 UINT8 *Buffer,
288 DT_FIELD *Field,
289 UINT32 ByteLength,
290 UINT8 Flags)
292 UINT64 Value;
293 UINT64 MaxValue;
294 ACPI_STATUS Status;
297 /* Output buffer byte length must be in range 1-8 */
299 if ((ByteLength > 8) || (ByteLength == 0))
301 DtFatal (ASL_MSG_COMPILER_INTERNAL, Field,
302 "Invalid internal Byte length");
303 return;
306 /* Resolve integer expression to a single integer value */
308 Status = DtResolveIntegerExpression (Field, &Value);
309 if (ACPI_FAILURE (Status))
311 return;
314 /* Ensure that reserved fields are set to zero */
315 /* TBD: should we set to zero, or just make this an ERROR? */
316 /* TBD: Probably better to use a flag */
318 if (!ACPI_STRCMP (Field->Name, "Reserved") &&
319 (Value != 0))
321 DtError (ASL_WARNING, ASL_MSG_RESERVED_VALUE, Field,
322 "Setting to zero");
323 Value = 0;
326 /* Check if the value must be non-zero */
328 if ((Value == 0) && (Flags & DT_NON_ZERO))
330 DtError (ASL_ERROR, ASL_MSG_ZERO_VALUE, Field, NULL);
334 * Generate the maximum value for the data type (ByteLength)
335 * Note: construct chosen for maximum portability
337 MaxValue = ((UINT64) (-1)) >> (64 - (ByteLength * 8));
339 /* Validate that the input value is within range of the target */
341 if (Value > MaxValue)
343 sprintf (MsgBuffer, "%8.8X%8.8X", ACPI_FORMAT_UINT64 (Value));
344 DtError (ASL_ERROR, ASL_MSG_INTEGER_SIZE, Field, MsgBuffer);
347 ACPI_MEMCPY (Buffer, &Value, ByteLength);
348 return;
352 /******************************************************************************
354 * FUNCTION: DtNormalizeBuffer
356 * PARAMETERS: Buffer - Input buffer
357 * Count - Output the count of hex number in
358 * the Buffer
360 * RETURN: The normalized buffer, freed by caller
362 * DESCRIPTION: [1A,2B,3C,4D] or 1A, 2B, 3C, 4D will be normalized
363 * to 1A 2B 3C 4D
365 *****************************************************************************/
367 static char *
368 DtNormalizeBuffer (
369 char *Buffer,
370 UINT32 *Count)
372 char *NewBuffer;
373 char *TmpBuffer;
374 UINT32 BufferCount = 0;
375 BOOLEAN Separator = TRUE;
376 char c;
379 NewBuffer = UtLocalCalloc (ACPI_STRLEN (Buffer) + 1);
380 TmpBuffer = NewBuffer;
382 while ((c = *Buffer++))
384 switch (c)
386 /* Valid separators */
388 case '[':
389 case ']':
390 case ' ':
391 case ',':
393 Separator = TRUE;
394 break;
396 default:
398 if (Separator)
400 /* Insert blank as the standard separator */
402 if (NewBuffer[0])
404 *TmpBuffer++ = ' ';
405 BufferCount++;
408 Separator = FALSE;
411 *TmpBuffer++ = c;
412 break;
416 *Count = BufferCount + 1;
417 return (NewBuffer);
421 /******************************************************************************
423 * FUNCTION: DtCompileBuffer
425 * PARAMETERS: Buffer - Output buffer
426 * StringValue - Integer list to be compiled
427 * Field - Current field object
428 * ByteLength - Byte length of the integer list
430 * RETURN: Count of remaining data in the input list
432 * DESCRIPTION: Compile and pack an integer list, for example
433 * "AA 1F 20 3B" ==> Buffer[] = {0xAA,0x1F,0x20,0x3B}
435 *****************************************************************************/
437 UINT32
438 DtCompileBuffer (
439 UINT8 *Buffer,
440 char *StringValue,
441 DT_FIELD *Field,
442 UINT32 ByteLength)
444 ACPI_STATUS Status;
445 char Hex[3];
446 UINT64 Value;
447 UINT32 i;
448 UINT32 Count;
451 /* Allow several different types of value separators */
453 StringValue = DtNormalizeBuffer (StringValue, &Count);
455 Hex[2] = 0;
456 for (i = 0; i < Count; i++)
458 /* Each element of StringValue is three chars */
460 Hex[0] = StringValue[(3 * i)];
461 Hex[1] = StringValue[(3 * i) + 1];
463 /* Convert one hex byte */
465 Value = 0;
466 Status = DtStrtoul64 (Hex, &Value);
467 if (ACPI_FAILURE (Status))
469 DtError (ASL_ERROR, ASL_MSG_BUFFER_ELEMENT, Field, MsgBuffer);
470 goto Exit;
473 Buffer[i] = (UINT8) Value;
476 Exit:
477 ACPI_FREE (StringValue);
478 return (ByteLength - Count);
482 /******************************************************************************
484 * FUNCTION: DtCompileFlag
486 * PARAMETERS: Buffer - Output buffer
487 * Field - Field to be compiled
488 * Info - Flag info
490 * RETURN:
492 * DESCRIPTION: Compile a flag
494 *****************************************************************************/
496 void
497 DtCompileFlag (
498 UINT8 *Buffer,
499 DT_FIELD *Field,
500 ACPI_DMTABLE_INFO *Info)
502 UINT64 Value = 0;
503 UINT32 BitLength = 1;
504 UINT8 BitPosition = 0;
505 ACPI_STATUS Status;
508 Status = DtStrtoul64 (Field->Value, &Value);
509 if (ACPI_FAILURE (Status))
511 DtError (ASL_ERROR, ASL_MSG_INVALID_HEX_INTEGER, Field, NULL);
514 switch (Info->Opcode)
516 case ACPI_DMT_FLAG0:
517 case ACPI_DMT_FLAG1:
518 case ACPI_DMT_FLAG2:
519 case ACPI_DMT_FLAG3:
520 case ACPI_DMT_FLAG4:
521 case ACPI_DMT_FLAG5:
522 case ACPI_DMT_FLAG6:
523 case ACPI_DMT_FLAG7:
525 BitPosition = Info->Opcode;
526 BitLength = 1;
527 break;
529 case ACPI_DMT_FLAGS0:
531 BitPosition = 0;
532 BitLength = 2;
533 break;
536 case ACPI_DMT_FLAGS1:
538 BitPosition = 1;
539 BitLength = 2;
540 break;
543 case ACPI_DMT_FLAGS2:
545 BitPosition = 2;
546 BitLength = 2;
547 break;
549 case ACPI_DMT_FLAGS4:
551 BitPosition = 4;
552 BitLength = 2;
553 break;
555 default:
557 DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid flag opcode");
558 break;
561 /* Check range of the input flag value */
563 if (Value >= ((UINT64) 1 << BitLength))
565 sprintf (MsgBuffer, "Maximum %u bit", BitLength);
566 DtError (ASL_ERROR, ASL_MSG_FLAG_VALUE, Field, MsgBuffer);
567 Value = 0;
570 *Buffer |= (UINT8) (Value << BitPosition);