1 /****************************************************************************** 2 * 3 * Module Name: dtfield.c - Code generation for individual source fields 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 AcpiUtConvertStringToUuid (InString, 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 /* 315 * Ensure that reserved fields are set properly. Note: uses 316 * the DT_NON_ZERO flag to indicate that the reserved value 317 * must be exactly one. Otherwise, the value must be zero. 318 * This is sufficient for now. 319 */ 320 321 /* TBD: Should use a flag rather than compare "Reserved" */ 322 323 if (!ACPI_STRCMP (Field->Name, "Reserved")) 324 { 325 if (Flags & DT_NON_ZERO) 326 { 327 if (Value != 1) 328 { 329 DtError (ASL_WARNING, ASL_MSG_RESERVED_VALUE, Field, 330 "Must be one, setting to one"); 331 Value = 1; 332 } 333 } 334 else if (Value != 0) 335 { 336 DtError (ASL_WARNING, ASL_MSG_RESERVED_VALUE, Field, 337 "Must be zero, setting to zero"); 338 Value = 0; 339 } 340 } 341 342 /* Check if the value must be non-zero */ 343 344 else if ((Flags & DT_NON_ZERO) && (Value == 0)) 345 { 346 DtError (ASL_ERROR, ASL_MSG_ZERO_VALUE, Field, NULL); 347 } 348 349 /* 350 * Generate the maximum value for the data type (ByteLength) 351 * Note: construct chosen for maximum portability 352 */ 353 MaxValue = ((UINT64) (-1)) >> (64 - (ByteLength * 8)); 354 355 /* Validate that the input value is within range of the target */ 356 357 if (Value > MaxValue) 358 { 359 sprintf (MsgBuffer, "%8.8X%8.8X - max %u bytes", 360 ACPI_FORMAT_UINT64 (Value), ByteLength); 361 DtError (ASL_ERROR, ASL_MSG_INTEGER_SIZE, Field, MsgBuffer); 362 } 363 364 ACPI_MEMCPY (Buffer, &Value, ByteLength); 365 return; 366 } 367 368 369 /****************************************************************************** 370 * 371 * FUNCTION: DtNormalizeBuffer 372 * 373 * PARAMETERS: Buffer - Input buffer 374 * Count - Output the count of hex number in 375 * the Buffer 376 * 377 * RETURN: The normalized buffer, freed by caller 378 * 379 * DESCRIPTION: [1A,2B,3C,4D] or 1A, 2B, 3C, 4D will be normalized 380 * to 1A 2B 3C 4D 381 * 382 *****************************************************************************/ 383 384 static char * 385 DtNormalizeBuffer ( 386 char *Buffer, 387 UINT32 *Count) 388 { 389 char *NewBuffer; 390 char *TmpBuffer; 391 UINT32 BufferCount = 0; 392 BOOLEAN Separator = TRUE; 393 char c; 394 395 396 NewBuffer = UtLocalCalloc (ACPI_STRLEN (Buffer) + 1); 397 TmpBuffer = NewBuffer; 398 399 while ((c = *Buffer++)) 400 { 401 switch (c) 402 { 403 /* Valid separators */ 404 405 case '[': 406 case ']': 407 case ' ': 408 case ',': 409 410 Separator = TRUE; 411 break; 412 413 default: 414 415 if (Separator) 416 { 417 /* Insert blank as the standard separator */ 418 419 if (NewBuffer[0]) 420 { 421 *TmpBuffer++ = ' '; 422 BufferCount++; 423 } 424 425 Separator = FALSE; 426 } 427 428 *TmpBuffer++ = c; 429 break; 430 } 431 } 432 433 *Count = BufferCount + 1; 434 return (NewBuffer); 435 } 436 437 438 /****************************************************************************** 439 * 440 * FUNCTION: DtCompileBuffer 441 * 442 * PARAMETERS: Buffer - Output buffer 443 * StringValue - Integer list to be compiled 444 * Field - Current field object 445 * ByteLength - Byte length of the integer list 446 * 447 * RETURN: Count of remaining data in the input list 448 * 449 * DESCRIPTION: Compile and pack an integer list, for example 450 * "AA 1F 20 3B" ==> Buffer[] = {0xAA,0x1F,0x20,0x3B} 451 * 452 *****************************************************************************/ 453 454 UINT32 455 DtCompileBuffer ( 456 UINT8 *Buffer, 457 char *StringValue, 458 DT_FIELD *Field, 459 UINT32 ByteLength) 460 { 461 ACPI_STATUS Status; 462 char Hex[3]; 463 UINT64 Value; 464 UINT32 i; 465 UINT32 Count; 466 467 468 /* Allow several different types of value separators */ 469 470 StringValue = DtNormalizeBuffer (StringValue, &Count); 471 472 Hex[2] = 0; 473 for (i = 0; i < Count; i++) 474 { 475 /* Each element of StringValue is three chars */ 476 477 Hex[0] = StringValue[(3 * i)]; 478 Hex[1] = StringValue[(3 * i) + 1]; 479 480 /* Convert one hex byte */ 481 482 Value = 0; 483 Status = DtStrtoul64 (Hex, &Value); 484 if (ACPI_FAILURE (Status)) 485 { 486 DtError (ASL_ERROR, ASL_MSG_BUFFER_ELEMENT, Field, MsgBuffer); 487 goto Exit; 488 } 489 490 Buffer[i] = (UINT8) Value; 491 } 492 493 Exit: 494 ACPI_FREE (StringValue); 495 return (ByteLength - Count); 496 } 497 498 499 /****************************************************************************** 500 * 501 * FUNCTION: DtCompileFlag 502 * 503 * PARAMETERS: Buffer - Output buffer 504 * Field - Field to be compiled 505 * Info - Flag info 506 * 507 * RETURN: 508 * 509 * DESCRIPTION: Compile a flag 510 * 511 *****************************************************************************/ 512 513 void 514 DtCompileFlag ( 515 UINT8 *Buffer, 516 DT_FIELD *Field, 517 ACPI_DMTABLE_INFO *Info) 518 { 519 UINT64 Value = 0; 520 UINT32 BitLength = 1; 521 UINT8 BitPosition = 0; 522 ACPI_STATUS Status; 523 524 525 Status = DtStrtoul64 (Field->Value, &Value); 526 if (ACPI_FAILURE (Status)) 527 { 528 DtError (ASL_ERROR, ASL_MSG_INVALID_HEX_INTEGER, Field, NULL); 529 } 530 531 switch (Info->Opcode) 532 { 533 case ACPI_DMT_FLAG0: 534 case ACPI_DMT_FLAG1: 535 case ACPI_DMT_FLAG2: 536 case ACPI_DMT_FLAG3: 537 case ACPI_DMT_FLAG4: 538 case ACPI_DMT_FLAG5: 539 case ACPI_DMT_FLAG6: 540 case ACPI_DMT_FLAG7: 541 542 BitPosition = Info->Opcode; 543 BitLength = 1; 544 break; 545 546 case ACPI_DMT_FLAGS0: 547 548 BitPosition = 0; 549 BitLength = 2; 550 break; 551 552 553 case ACPI_DMT_FLAGS1: 554 555 BitPosition = 1; 556 BitLength = 2; 557 break; 558 559 560 case ACPI_DMT_FLAGS2: 561 562 BitPosition = 2; 563 BitLength = 2; 564 break; 565 566 case ACPI_DMT_FLAGS4: 567 568 BitPosition = 4; 569 BitLength = 2; 570 break; 571 572 default: 573 574 DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid flag opcode"); 575 break; 576 } 577 578 /* Check range of the input flag value */ 579 580 if (Value >= ((UINT64) 1 << BitLength)) 581 { 582 sprintf (MsgBuffer, "Maximum %u bit", BitLength); 583 DtError (ASL_ERROR, ASL_MSG_FLAG_VALUE, Field, MsgBuffer); 584 Value = 0; 585 } 586 587 *Buffer |= (UINT8) (Value << BitPosition); 588 } 589