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