dtfield.c revision 1.1.1.6 1 /******************************************************************************
2 *
3 * Module Name: dtfield.c - Code generation for individual source fields
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2015, 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 #include "aslcompiler.h"
45 #include "dtcompiler.h"
46
47 #define _COMPONENT DT_COMPILER
48 ACPI_MODULE_NAME ("dtfield")
49
50
51 /* Local prototypes */
52
53 static void
54 DtCompileString (
55 UINT8 *Buffer,
56 DT_FIELD *Field,
57 UINT32 ByteLength);
58
59 static void
60 DtCompileUnicode (
61 UINT8 *Buffer,
62 DT_FIELD *Field,
63 UINT32 ByteLength);
64
65 static ACPI_STATUS
66 DtCompileUuid (
67 UINT8 *Buffer,
68 DT_FIELD *Field,
69 UINT32 ByteLength);
70
71 static char *
72 DtNormalizeBuffer (
73 char *Buffer,
74 UINT32 *Count);
75
76
77 /******************************************************************************
78 *
79 * FUNCTION: DtCompileOneField
80 *
81 * PARAMETERS: Buffer - Output buffer
82 * Field - Field to be compiled
83 * ByteLength - Byte length of the field
84 * Type - Field type
85 *
86 * RETURN: None
87 *
88 * DESCRIPTION: Compile a field value to binary
89 *
90 *****************************************************************************/
91
92 void
93 DtCompileOneField (
94 UINT8 *Buffer,
95 DT_FIELD *Field,
96 UINT32 ByteLength,
97 UINT8 Type,
98 UINT8 Flags)
99 {
100 ACPI_STATUS Status;
101
102 switch (Type)
103 {
104 case DT_FIELD_TYPE_INTEGER:
105
106 DtCompileInteger (Buffer, Field, ByteLength, Flags);
107 break;
108
109 case DT_FIELD_TYPE_STRING:
110
111 DtCompileString (Buffer, Field, ByteLength);
112 break;
113
114 case DT_FIELD_TYPE_UUID:
115
116 Status = DtCompileUuid (Buffer, Field, ByteLength);
117 if (ACPI_SUCCESS (Status))
118 {
119 break;
120 }
121
122 /* Fall through. */
123
124 case DT_FIELD_TYPE_BUFFER:
125
126 DtCompileBuffer (Buffer, Field->Value, Field, ByteLength);
127 break;
128
129 case DT_FIELD_TYPE_UNICODE:
130
131 DtCompileUnicode (Buffer, Field, ByteLength);
132 break;
133
134 case DT_FIELD_TYPE_DEVICE_PATH:
135
136 break;
137
138 default:
139
140 DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid field type");
141 break;
142 }
143 }
144
145
146 /******************************************************************************
147 *
148 * FUNCTION: DtCompileString
149 *
150 * PARAMETERS: Buffer - Output buffer
151 * Field - String to be copied to buffer
152 * ByteLength - Maximum length of string
153 *
154 * RETURN: None
155 *
156 * DESCRIPTION: Copy string to the buffer
157 *
158 *****************************************************************************/
159
160 static void
161 DtCompileString (
162 UINT8 *Buffer,
163 DT_FIELD *Field,
164 UINT32 ByteLength)
165 {
166 UINT32 Length;
167
168
169 Length = ACPI_STRLEN (Field->Value);
170
171 /* Check if the string is too long for the field */
172
173 if (Length > ByteLength)
174 {
175 sprintf (MsgBuffer, "Maximum %u characters", ByteLength);
176 DtError (ASL_ERROR, ASL_MSG_STRING_LENGTH, Field, MsgBuffer);
177 Length = ByteLength;
178 }
179
180 ACPI_MEMCPY (Buffer, Field->Value, Length);
181 }
182
183
184 /******************************************************************************
185 *
186 * FUNCTION: DtCompileUnicode
187 *
188 * PARAMETERS: Buffer - Output buffer
189 * Field - String to be copied to buffer
190 * ByteLength - Maximum length of string
191 *
192 * RETURN: None
193 *
194 * DESCRIPTION: Convert ASCII string to Unicode string
195 *
196 * Note: The Unicode string is 16 bits per character, no leading signature,
197 * with a 16-bit terminating NULL.
198 *
199 *****************************************************************************/
200
201 static void
202 DtCompileUnicode (
203 UINT8 *Buffer,
204 DT_FIELD *Field,
205 UINT32 ByteLength)
206 {
207 UINT32 Count;
208 UINT32 i;
209 char *AsciiString;
210 UINT16 *UnicodeString;
211
212
213 AsciiString = Field->Value;
214 UnicodeString = (UINT16 *) Buffer;
215 Count = ACPI_STRLEN (AsciiString) + 1;
216
217 /* Convert to Unicode string (including null terminator) */
218
219 for (i = 0; i < Count; i++)
220 {
221 UnicodeString[i] = (UINT16) AsciiString[i];
222 }
223 }
224
225
226 /*******************************************************************************
227 *
228 * FUNCTION: DtCompileUuid
229 *
230 * PARAMETERS: Buffer - Output buffer
231 * Field - String to be copied to buffer
232 * ByteLength - Maximum length of string
233 *
234 * RETURN: None
235 *
236 * DESCRIPTION: Convert UUID string to 16-byte buffer
237 *
238 ******************************************************************************/
239
240 static ACPI_STATUS
241 DtCompileUuid (
242 UINT8 *Buffer,
243 DT_FIELD *Field,
244 UINT32 ByteLength)
245 {
246 char *InString;
247 ACPI_STATUS Status;
248
249
250 InString = Field->Value;
251
252 Status = AuValidateUuid (InString);
253 if (ACPI_FAILURE (Status))
254 {
255 sprintf (MsgBuffer, "%s", Field->Value);
256 DtNameError (ASL_ERROR, ASL_MSG_INVALID_UUID, Field, MsgBuffer);
257 }
258 else
259 {
260 AcpiUtConvertStringToUuid (InString, Buffer);
261 }
262
263 return (Status);
264 }
265
266
267 /******************************************************************************
268 *
269 * FUNCTION: DtCompileInteger
270 *
271 * PARAMETERS: Buffer - Output buffer
272 * Field - Field obj with Integer to be compiled
273 * ByteLength - Byte length of the integer
274 * Flags - Additional compile info
275 *
276 * RETURN: None
277 *
278 * DESCRIPTION: Compile an integer. Supports integer expressions with C-style
279 * operators.
280 *
281 *****************************************************************************/
282
283 void
284 DtCompileInteger (
285 UINT8 *Buffer,
286 DT_FIELD *Field,
287 UINT32 ByteLength,
288 UINT8 Flags)
289 {
290 UINT64 Value;
291 UINT64 MaxValue;
292 ACPI_STATUS Status;
293
294
295 /* Output buffer byte length must be in range 1-8 */
296
297 if ((ByteLength > 8) || (ByteLength == 0))
298 {
299 DtFatal (ASL_MSG_COMPILER_INTERNAL, Field,
300 "Invalid internal Byte length");
301 return;
302 }
303
304 /* Resolve integer expression to a single integer value */
305
306 Status = DtResolveIntegerExpression (Field, &Value);
307 if (ACPI_FAILURE (Status))
308 {
309 return;
310 }
311
312 /*
313 * Ensure that reserved fields are set properly. Note: uses
314 * the DT_NON_ZERO flag to indicate that the reserved value
315 * must be exactly one. Otherwise, the value must be zero.
316 * This is sufficient for now.
317 */
318
319 /* TBD: Should use a flag rather than compare "Reserved" */
320
321 if (!ACPI_STRCMP (Field->Name, "Reserved"))
322 {
323 if (Flags & DT_NON_ZERO)
324 {
325 if (Value != 1)
326 {
327 DtError (ASL_WARNING, ASL_MSG_RESERVED_VALUE, Field,
328 "Must be one, setting to one");
329 Value = 1;
330 }
331 }
332 else if (Value != 0)
333 {
334 DtError (ASL_WARNING, ASL_MSG_RESERVED_VALUE, Field,
335 "Must be zero, setting to zero");
336 Value = 0;
337 }
338 }
339
340 /* Check if the value must be non-zero */
341
342 else if ((Flags & DT_NON_ZERO) && (Value == 0))
343 {
344 DtError (ASL_ERROR, ASL_MSG_ZERO_VALUE, Field, NULL);
345 }
346
347 /*
348 * Generate the maximum value for the data type (ByteLength)
349 * Note: construct chosen for maximum portability
350 */
351 MaxValue = ((UINT64) (-1)) >> (64 - (ByteLength * 8));
352
353 /* Validate that the input value is within range of the target */
354
355 if (Value > MaxValue)
356 {
357 sprintf (MsgBuffer, "%8.8X%8.8X - max %u bytes",
358 ACPI_FORMAT_UINT64 (Value), ByteLength);
359 DtError (ASL_ERROR, ASL_MSG_INTEGER_SIZE, Field, MsgBuffer);
360 }
361
362 ACPI_MEMCPY (Buffer, &Value, ByteLength);
363 return;
364 }
365
366
367 /******************************************************************************
368 *
369 * FUNCTION: DtNormalizeBuffer
370 *
371 * PARAMETERS: Buffer - Input buffer
372 * Count - Output the count of hex number in
373 * the Buffer
374 *
375 * RETURN: The normalized buffer, freed by caller
376 *
377 * DESCRIPTION: [1A,2B,3C,4D] or 1A, 2B, 3C, 4D will be normalized
378 * to 1A 2B 3C 4D
379 *
380 *****************************************************************************/
381
382 static char *
383 DtNormalizeBuffer (
384 char *Buffer,
385 UINT32 *Count)
386 {
387 char *NewBuffer;
388 char *TmpBuffer;
389 UINT32 BufferCount = 0;
390 BOOLEAN Separator = TRUE;
391 char c;
392
393
394 NewBuffer = UtLocalCalloc (ACPI_STRLEN (Buffer) + 1);
395 TmpBuffer = NewBuffer;
396
397 while ((c = *Buffer++))
398 {
399 switch (c)
400 {
401 /* Valid separators */
402
403 case '[':
404 case ']':
405 case ' ':
406 case ',':
407
408 Separator = TRUE;
409 break;
410
411 default:
412
413 if (Separator)
414 {
415 /* Insert blank as the standard separator */
416
417 if (NewBuffer[0])
418 {
419 *TmpBuffer++ = ' ';
420 BufferCount++;
421 }
422
423 Separator = FALSE;
424 }
425
426 *TmpBuffer++ = c;
427 break;
428 }
429 }
430
431 *Count = BufferCount + 1;
432 return (NewBuffer);
433 }
434
435
436 /******************************************************************************
437 *
438 * FUNCTION: DtCompileBuffer
439 *
440 * PARAMETERS: Buffer - Output buffer
441 * StringValue - Integer list to be compiled
442 * Field - Current field object
443 * ByteLength - Byte length of the integer list
444 *
445 * RETURN: Count of remaining data in the input list
446 *
447 * DESCRIPTION: Compile and pack an integer list, for example
448 * "AA 1F 20 3B" ==> Buffer[] = {0xAA,0x1F,0x20,0x3B}
449 *
450 *****************************************************************************/
451
452 UINT32
453 DtCompileBuffer (
454 UINT8 *Buffer,
455 char *StringValue,
456 DT_FIELD *Field,
457 UINT32 ByteLength)
458 {
459 ACPI_STATUS Status;
460 char Hex[3];
461 UINT64 Value;
462 UINT32 i;
463 UINT32 Count;
464
465
466 /* Allow several different types of value separators */
467
468 StringValue = DtNormalizeBuffer (StringValue, &Count);
469
470 Hex[2] = 0;
471 for (i = 0; i < Count; i++)
472 {
473 /* Each element of StringValue is three chars */
474
475 Hex[0] = StringValue[(3 * i)];
476 Hex[1] = StringValue[(3 * i) + 1];
477
478 /* Convert one hex byte */
479
480 Value = 0;
481 Status = DtStrtoul64 (Hex, &Value);
482 if (ACPI_FAILURE (Status))
483 {
484 DtError (ASL_ERROR, ASL_MSG_BUFFER_ELEMENT, Field, MsgBuffer);
485 goto Exit;
486 }
487
488 Buffer[i] = (UINT8) Value;
489 }
490
491 Exit:
492 ACPI_FREE (StringValue);
493 return (ByteLength - Count);
494 }
495
496
497 /******************************************************************************
498 *
499 * FUNCTION: DtCompileFlag
500 *
501 * PARAMETERS: Buffer - Output buffer
502 * Field - Field to be compiled
503 * Info - Flag info
504 *
505 * RETURN:
506 *
507 * DESCRIPTION: Compile a flag
508 *
509 *****************************************************************************/
510
511 void
512 DtCompileFlag (
513 UINT8 *Buffer,
514 DT_FIELD *Field,
515 ACPI_DMTABLE_INFO *Info)
516 {
517 UINT64 Value = 0;
518 UINT32 BitLength = 1;
519 UINT8 BitPosition = 0;
520 ACPI_STATUS Status;
521
522
523 Status = DtStrtoul64 (Field->Value, &Value);
524 if (ACPI_FAILURE (Status))
525 {
526 DtError (ASL_ERROR, ASL_MSG_INVALID_HEX_INTEGER, Field, NULL);
527 }
528
529 switch (Info->Opcode)
530 {
531 case ACPI_DMT_FLAG0:
532 case ACPI_DMT_FLAG1:
533 case ACPI_DMT_FLAG2:
534 case ACPI_DMT_FLAG3:
535 case ACPI_DMT_FLAG4:
536 case ACPI_DMT_FLAG5:
537 case ACPI_DMT_FLAG6:
538 case ACPI_DMT_FLAG7:
539
540 BitPosition = Info->Opcode;
541 BitLength = 1;
542 break;
543
544 case ACPI_DMT_FLAGS0:
545
546 BitPosition = 0;
547 BitLength = 2;
548 break;
549
550
551 case ACPI_DMT_FLAGS1:
552
553 BitPosition = 1;
554 BitLength = 2;
555 break;
556
557
558 case ACPI_DMT_FLAGS2:
559
560 BitPosition = 2;
561 BitLength = 2;
562 break;
563
564 case ACPI_DMT_FLAGS4:
565
566 BitPosition = 4;
567 BitLength = 2;
568 break;
569
570 default:
571
572 DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid flag opcode");
573 break;
574 }
575
576 /* Check range of the input flag value */
577
578 if (Value >= ((UINT64) 1 << BitLength))
579 {
580 sprintf (MsgBuffer, "Maximum %u bit", BitLength);
581 DtError (ASL_ERROR, ASL_MSG_FLAG_VALUE, Field, MsgBuffer);
582 Value = 0;
583 }
584
585 *Buffer |= (UINT8) (Value << BitPosition);
586 }
587