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