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 <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 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 = 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 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 = 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 (!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 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 (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