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