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