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