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 "aslcompiler.h" 47 #include "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 - max %u bytes", 344 ACPI_FORMAT_UINT64 (Value), ByteLength); 345 DtError (ASL_ERROR, ASL_MSG_INTEGER_SIZE, Field, MsgBuffer); 346 } 347 348 ACPI_MEMCPY (Buffer, &Value, ByteLength); 349 return; 350 } 351 352 353 /****************************************************************************** 354 * 355 * FUNCTION: DtNormalizeBuffer 356 * 357 * PARAMETERS: Buffer - Input buffer 358 * Count - Output the count of hex number in 359 * the Buffer 360 * 361 * RETURN: The normalized buffer, freed by caller 362 * 363 * DESCRIPTION: [1A,2B,3C,4D] or 1A, 2B, 3C, 4D will be normalized 364 * to 1A 2B 3C 4D 365 * 366 *****************************************************************************/ 367 368 static char * 369 DtNormalizeBuffer ( 370 char *Buffer, 371 UINT32 *Count) 372 { 373 char *NewBuffer; 374 char *TmpBuffer; 375 UINT32 BufferCount = 0; 376 BOOLEAN Separator = TRUE; 377 char c; 378 379 380 NewBuffer = UtLocalCalloc (ACPI_STRLEN (Buffer) + 1); 381 TmpBuffer = NewBuffer; 382 383 while ((c = *Buffer++)) 384 { 385 switch (c) 386 { 387 /* Valid separators */ 388 389 case '[': 390 case ']': 391 case ' ': 392 case ',': 393 394 Separator = TRUE; 395 break; 396 397 default: 398 399 if (Separator) 400 { 401 /* Insert blank as the standard separator */ 402 403 if (NewBuffer[0]) 404 { 405 *TmpBuffer++ = ' '; 406 BufferCount++; 407 } 408 409 Separator = FALSE; 410 } 411 412 *TmpBuffer++ = c; 413 break; 414 } 415 } 416 417 *Count = BufferCount + 1; 418 return (NewBuffer); 419 } 420 421 422 /****************************************************************************** 423 * 424 * FUNCTION: DtCompileBuffer 425 * 426 * PARAMETERS: Buffer - Output buffer 427 * StringValue - Integer list to be compiled 428 * Field - Current field object 429 * ByteLength - Byte length of the integer list 430 * 431 * RETURN: Count of remaining data in the input list 432 * 433 * DESCRIPTION: Compile and pack an integer list, for example 434 * "AA 1F 20 3B" ==> Buffer[] = {0xAA,0x1F,0x20,0x3B} 435 * 436 *****************************************************************************/ 437 438 UINT32 439 DtCompileBuffer ( 440 UINT8 *Buffer, 441 char *StringValue, 442 DT_FIELD *Field, 443 UINT32 ByteLength) 444 { 445 ACPI_STATUS Status; 446 char Hex[3]; 447 UINT64 Value; 448 UINT32 i; 449 UINT32 Count; 450 451 452 /* Allow several different types of value separators */ 453 454 StringValue = DtNormalizeBuffer (StringValue, &Count); 455 456 Hex[2] = 0; 457 for (i = 0; i < Count; i++) 458 { 459 /* Each element of StringValue is three chars */ 460 461 Hex[0] = StringValue[(3 * i)]; 462 Hex[1] = StringValue[(3 * i) + 1]; 463 464 /* Convert one hex byte */ 465 466 Value = 0; 467 Status = DtStrtoul64 (Hex, &Value); 468 if (ACPI_FAILURE (Status)) 469 { 470 DtError (ASL_ERROR, ASL_MSG_BUFFER_ELEMENT, Field, MsgBuffer); 471 goto Exit; 472 } 473 474 Buffer[i] = (UINT8) Value; 475 } 476 477 Exit: 478 ACPI_FREE (StringValue); 479 return (ByteLength - Count); 480 } 481 482 483 /****************************************************************************** 484 * 485 * FUNCTION: DtCompileFlag 486 * 487 * PARAMETERS: Buffer - Output buffer 488 * Field - Field to be compiled 489 * Info - Flag info 490 * 491 * RETURN: 492 * 493 * DESCRIPTION: Compile a flag 494 * 495 *****************************************************************************/ 496 497 void 498 DtCompileFlag ( 499 UINT8 *Buffer, 500 DT_FIELD *Field, 501 ACPI_DMTABLE_INFO *Info) 502 { 503 UINT64 Value = 0; 504 UINT32 BitLength = 1; 505 UINT8 BitPosition = 0; 506 ACPI_STATUS Status; 507 508 509 Status = DtStrtoul64 (Field->Value, &Value); 510 if (ACPI_FAILURE (Status)) 511 { 512 DtError (ASL_ERROR, ASL_MSG_INVALID_HEX_INTEGER, Field, NULL); 513 } 514 515 switch (Info->Opcode) 516 { 517 case ACPI_DMT_FLAG0: 518 case ACPI_DMT_FLAG1: 519 case ACPI_DMT_FLAG2: 520 case ACPI_DMT_FLAG3: 521 case ACPI_DMT_FLAG4: 522 case ACPI_DMT_FLAG5: 523 case ACPI_DMT_FLAG6: 524 case ACPI_DMT_FLAG7: 525 526 BitPosition = Info->Opcode; 527 BitLength = 1; 528 break; 529 530 case ACPI_DMT_FLAGS0: 531 532 BitPosition = 0; 533 BitLength = 2; 534 break; 535 536 537 case ACPI_DMT_FLAGS1: 538 539 BitPosition = 1; 540 BitLength = 2; 541 break; 542 543 544 case ACPI_DMT_FLAGS2: 545 546 BitPosition = 2; 547 BitLength = 2; 548 break; 549 550 case ACPI_DMT_FLAGS4: 551 552 BitPosition = 4; 553 BitLength = 2; 554 break; 555 556 default: 557 558 DtFatal (ASL_MSG_COMPILER_INTERNAL, Field, "Invalid flag opcode"); 559 break; 560 } 561 562 /* Check range of the input flag value */ 563 564 if (Value >= ((UINT64) 1 << BitLength)) 565 { 566 sprintf (MsgBuffer, "Maximum %u bit", BitLength); 567 DtError (ASL_ERROR, ASL_MSG_FLAG_VALUE, Field, MsgBuffer); 568 Value = 0; 569 } 570 571 *Buffer |= (UINT8) (Value << BitPosition); 572 }