1 /****************************************************************************** 2 * 3 * Module Name: aslpld - Implementation of ASL ToPLD macro 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 "aslcompiler.h" 45 #include "aslcompiler.y.h" 46 #include "amlcode.h" 47 48 #define _COMPONENT ACPI_COMPILER 49 ACPI_MODULE_NAME ("aslpld") 50 51 52 /* Local prototypes */ 53 54 static UINT8 * 55 OpcEncodePldBuffer ( 56 ACPI_PLD_INFO *PldInfo); 57 58 static BOOLEAN 59 OpcFindName ( 60 const char **List, 61 char *Name, 62 UINT32 *Index); 63 64 65 /******************************************************************************* 66 * 67 * FUNCTION: OpcDoPld 68 * 69 * PARAMETERS: Op - Current parse node 70 * 71 * RETURN: None 72 * 73 * DESCRIPTION: Convert ToPLD macro to 20-byte buffer 74 * 75 * The ToPLD parse tree looks like this: 76 * 77 * TOPLD 78 * PLD_REVISION 79 * INTEGER 80 * PLD_IGNORECOLOR 81 * INTEGER 82 * ... 83 * etc. 84 * 85 ******************************************************************************/ 86 87 void 88 OpcDoPld ( 89 ACPI_PARSE_OBJECT *Op) 90 { 91 ACPI_PLD_INFO PldInfo; 92 UINT8 *Buffer; 93 ACPI_PARSE_OBJECT *ThisOp; 94 ACPI_PARSE_OBJECT *NewOp; 95 UINT16 ParseOpcode; 96 UINT32 Value; 97 98 99 if (!Op) 100 { 101 AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op, NULL); 102 return; 103 } 104 105 if (Op->Asl.ParseOpcode != PARSEOP_TOPLD) 106 { 107 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, Op, NULL); 108 return; 109 } 110 111 memset (&PldInfo, 0, sizeof (ACPI_PLD_INFO)); 112 113 /* Traverse the list of PLD Ops (one per PLD field) */ 114 115 ThisOp = Op->Asl.Child; 116 while (ThisOp) 117 { 118 /* Get child values */ 119 120 ParseOpcode = ThisOp->Asl.Child->Asl.ParseOpcode; 121 Value = (UINT32) ThisOp->Asl.Child->Asl.Value.Integer; 122 123 switch (ThisOp->Asl.ParseOpcode) 124 { 125 case PARSEOP_PLD_REVISION: 126 127 if (ParseOpcode != PARSEOP_INTEGER) 128 { 129 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ThisOp, NULL); 130 break; 131 } 132 133 if (Value > 127) 134 { 135 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 136 break; 137 } 138 139 PldInfo.Revision = (UINT8) Value; 140 break; 141 142 case PARSEOP_PLD_IGNORECOLOR: 143 144 if (ParseOpcode != PARSEOP_INTEGER) 145 { 146 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ThisOp, NULL); 147 break; 148 } 149 150 if (Value > 1) 151 { 152 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 153 break; 154 } 155 156 PldInfo.IgnoreColor = (UINT8) Value; 157 break; 158 159 case PARSEOP_PLD_RED: 160 case PARSEOP_PLD_GREEN: 161 case PARSEOP_PLD_BLUE: 162 163 if (ParseOpcode != PARSEOP_INTEGER) 164 { 165 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 166 break; 167 } 168 169 if (Value > 255) 170 { 171 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 172 break; 173 } 174 175 if (ThisOp->Asl.ParseOpcode == PARSEOP_PLD_RED) 176 { 177 PldInfo.Red = (UINT8) Value; 178 } 179 else if (ThisOp->Asl.ParseOpcode == PARSEOP_PLD_GREEN) 180 { 181 PldInfo.Green = (UINT8) Value; 182 } 183 else /* PARSEOP_PLD_BLUE */ 184 { 185 PldInfo.Blue = (UINT8) Value; 186 } 187 break; 188 189 case PARSEOP_PLD_WIDTH: 190 case PARSEOP_PLD_HEIGHT: 191 192 if (ParseOpcode != PARSEOP_INTEGER) 193 { 194 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ThisOp, NULL); 195 break; 196 } 197 198 if (Value > 65535) 199 { 200 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 201 break; 202 } 203 204 if (ThisOp->Asl.ParseOpcode == PARSEOP_PLD_WIDTH) 205 { 206 PldInfo.Width = (UINT16) Value; 207 } 208 else /* PARSEOP_PLD_HEIGHT */ 209 { 210 PldInfo.Height = (UINT16) Value; 211 } 212 213 break; 214 215 case PARSEOP_PLD_USERVISIBLE: 216 case PARSEOP_PLD_DOCK: 217 case PARSEOP_PLD_LID: 218 219 if (ParseOpcode != PARSEOP_INTEGER) 220 { 221 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ThisOp, NULL); 222 break; 223 } 224 225 if (Value > 1) 226 { 227 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 228 break; 229 } 230 231 if (ThisOp->Asl.ParseOpcode == PARSEOP_PLD_USERVISIBLE) 232 { 233 PldInfo.UserVisible = (UINT8) Value; 234 } 235 else if (ThisOp->Asl.ParseOpcode == PARSEOP_PLD_DOCK) 236 { 237 PldInfo.Dock = (UINT8) Value; 238 } 239 else 240 { 241 PldInfo.Lid = (UINT8) Value; 242 } 243 244 break; 245 246 case PARSEOP_PLD_PANEL: 247 248 if (ParseOpcode == PARSEOP_INTEGER) 249 { 250 if (Value > 6) 251 { 252 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 253 break; 254 } 255 } 256 else /* PARSEOP_STRING */ 257 { 258 if (!OpcFindName (AcpiGbl_PldPanelList, 259 ThisOp->Asl.Child->Asl.Value.String, 260 &Value)) 261 { 262 AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, ThisOp, NULL); 263 break; 264 } 265 } 266 267 PldInfo.Panel = (UINT8) Value; 268 break; 269 270 case PARSEOP_PLD_VERTICALPOSITION: 271 272 if (ParseOpcode == PARSEOP_INTEGER) 273 { 274 if (Value > 2) 275 { 276 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 277 break; 278 } 279 } 280 else /* PARSEOP_STRING */ 281 { 282 if (!OpcFindName (AcpiGbl_PldVerticalPositionList, 283 ThisOp->Asl.Child->Asl.Value.String, 284 &Value)) 285 { 286 AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, ThisOp, NULL); 287 break; 288 } 289 } 290 291 PldInfo.VerticalPosition = (UINT8) Value; 292 break; 293 294 case PARSEOP_PLD_HORIZONTALPOSITION: 295 296 if (ParseOpcode == PARSEOP_INTEGER) 297 { 298 if (Value > 2) 299 { 300 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 301 break; 302 } 303 } 304 else /* PARSEOP_STRING */ 305 { 306 if (!OpcFindName (AcpiGbl_PldHorizontalPositionList, 307 ThisOp->Asl.Child->Asl.Value.String, 308 &Value)) 309 { 310 AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, ThisOp, NULL); 311 break; 312 } 313 } 314 315 PldInfo.HorizontalPosition = (UINT8) Value; 316 break; 317 318 case PARSEOP_PLD_SHAPE: 319 320 if (ParseOpcode == PARSEOP_INTEGER) 321 { 322 if (Value > 8) 323 { 324 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 325 break; 326 } 327 } 328 else /* PARSEOP_STRING */ 329 { 330 if (!OpcFindName (AcpiGbl_PldShapeList, 331 ThisOp->Asl.Child->Asl.Value.String, 332 &Value)) 333 { 334 AslError (ASL_ERROR, ASL_MSG_INVALID_OPERAND, ThisOp, NULL); 335 break; 336 } 337 } 338 339 PldInfo.Shape = (UINT8) Value; 340 break; 341 342 case PARSEOP_PLD_GROUPORIENTATION: 343 344 if (ParseOpcode != PARSEOP_INTEGER) 345 { 346 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ThisOp, NULL); 347 break; 348 } 349 350 if (Value > 1) 351 { 352 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 353 break; 354 } 355 356 PldInfo.GroupOrientation = (UINT8) Value; 357 break; 358 359 case PARSEOP_PLD_GROUPTOKEN: 360 case PARSEOP_PLD_GROUPPOSITION: 361 362 if (ParseOpcode != PARSEOP_INTEGER) 363 { 364 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ThisOp, NULL); 365 break; 366 } 367 368 if (Value > 255) 369 { 370 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 371 break; 372 } 373 374 if (ThisOp->Asl.ParseOpcode == PARSEOP_PLD_GROUPTOKEN) 375 { 376 PldInfo.GroupToken = (UINT8) Value; 377 } 378 else /* PARSEOP_PLD_GROUPPOSITION */ 379 { 380 PldInfo.GroupPosition = (UINT8) Value; 381 } 382 383 break; 384 385 case PARSEOP_PLD_BAY: 386 case PARSEOP_PLD_EJECTABLE: 387 case PARSEOP_PLD_EJECTREQUIRED: 388 389 if (ParseOpcode != PARSEOP_INTEGER) 390 { 391 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ThisOp, NULL); 392 break; 393 } 394 395 if (Value > 1) 396 { 397 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 398 break; 399 } 400 401 if (ThisOp->Asl.ParseOpcode == PARSEOP_PLD_BAY) 402 { 403 PldInfo.Bay = (UINT8) Value; 404 } 405 else if (ThisOp->Asl.ParseOpcode == PARSEOP_PLD_EJECTABLE) 406 { 407 PldInfo.Ejectable = (UINT8) Value; 408 } 409 else /* PARSEOP_PLD_EJECTREQUIRED */ 410 { 411 PldInfo.OspmEjectRequired = (UINT8) Value; 412 } 413 414 break; 415 416 case PARSEOP_PLD_CABINETNUMBER: 417 case PARSEOP_PLD_CARDCAGENUMBER: 418 419 if (ParseOpcode != PARSEOP_INTEGER) 420 { 421 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ThisOp, NULL); 422 break; 423 } 424 425 if (Value > 255) 426 { 427 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 428 break; 429 } 430 431 if (ThisOp->Asl.ParseOpcode == PARSEOP_PLD_CABINETNUMBER) 432 { 433 PldInfo.CabinetNumber = (UINT8) Value; 434 } 435 else /* PARSEOP_PLD_CARDCAGENUMBER */ 436 { 437 PldInfo.CardCageNumber = (UINT8) Value; 438 } 439 440 break; 441 442 case PARSEOP_PLD_REFERENCE: 443 444 if (ParseOpcode != PARSEOP_INTEGER) 445 { 446 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ThisOp, NULL); 447 break; 448 } 449 450 if (Value > 1) 451 { 452 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 453 break; 454 } 455 456 PldInfo.Reference = (UINT8) Value; 457 break; 458 459 case PARSEOP_PLD_ROTATION: 460 461 if (ParseOpcode != PARSEOP_INTEGER) 462 { 463 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ThisOp, NULL); 464 break; 465 } 466 467 if (Value > 7) 468 { 469 switch (Value) 470 { 471 case 45: 472 473 Value = 1; 474 break; 475 476 case 90: 477 478 Value = 2; 479 break; 480 481 case 135: 482 483 Value = 3; 484 break; 485 486 case 180: 487 488 Value = 4; 489 break; 490 491 case 225: 492 493 Value = 5; 494 break; 495 496 case 270: 497 498 Value = 6; 499 break; 500 501 case 315: 502 503 Value = 7; 504 break; 505 506 default: 507 508 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 509 break; 510 } 511 } 512 513 PldInfo.Rotation = (UINT8) Value; 514 break; 515 516 case PARSEOP_PLD_ORDER: 517 518 if (ParseOpcode != PARSEOP_INTEGER) 519 { 520 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ThisOp, NULL); 521 break; 522 } 523 524 if (Value > 31) 525 { 526 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 527 break; 528 } 529 530 PldInfo.Order = (UINT8) Value; 531 break; 532 533 case PARSEOP_PLD_VERTICALOFFSET: 534 case PARSEOP_PLD_HORIZONTALOFFSET: 535 536 if (ParseOpcode != PARSEOP_INTEGER) 537 { 538 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ThisOp, NULL); 539 break; 540 } 541 542 if (Value > 65535) 543 { 544 AslError (ASL_ERROR, ASL_MSG_RANGE, ThisOp, NULL); 545 break; 546 } 547 548 if (ThisOp->Asl.ParseOpcode == PARSEOP_PLD_VERTICALOFFSET) 549 { 550 PldInfo.VerticalOffset = (UINT16) Value; 551 } 552 else /* PARSEOP_PLD_HORIZONTALOFFSET */ 553 { 554 PldInfo.HorizontalOffset = (UINT16) Value; 555 } 556 557 break; 558 559 default: 560 561 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ThisOp, NULL); 562 break; 563 } 564 565 ThisOp = ThisOp->Asl.Next; 566 } 567 568 Buffer = OpcEncodePldBuffer (&PldInfo); 569 570 /* Change Op to a Buffer */ 571 572 Op->Asl.ParseOpcode = PARSEOP_BUFFER; 573 Op->Common.AmlOpcode = AML_BUFFER_OP; 574 575 /* Disable further optimization */ 576 577 Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST; 578 UtSetParseOpName (Op); 579 580 /* Child node is the buffer length */ 581 582 NewOp = TrAllocateNode (PARSEOP_INTEGER); 583 584 NewOp->Asl.AmlOpcode = AML_BYTE_OP; 585 NewOp->Asl.Value.Integer = 20; 586 NewOp->Asl.Parent = Op; 587 588 Op->Asl.Child = NewOp; 589 Op = NewOp; 590 591 /* Peer to the child is the raw buffer data */ 592 593 NewOp = TrAllocateNode (PARSEOP_RAW_DATA); 594 NewOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; 595 NewOp->Asl.AmlLength = 20; 596 NewOp->Asl.Value.String = ACPI_CAST_PTR (char, Buffer); 597 NewOp->Asl.Parent = Op->Asl.Parent; 598 599 Op->Asl.Next = NewOp; 600 } 601 602 603 /******************************************************************************* 604 * 605 * FUNCTION: OpcEncodePldBuffer 606 * 607 * PARAMETERS: PldInfo - _PLD buffer struct (Using local struct) 608 * 609 * RETURN: Encode _PLD buffer suitable for return value from _PLD 610 * 611 * DESCRIPTION: Bit-packs a _PLD buffer struct. 612 * 613 ******************************************************************************/ 614 615 static UINT8 * 616 OpcEncodePldBuffer ( 617 ACPI_PLD_INFO *PldInfo) 618 { 619 UINT32 *Buffer; 620 UINT32 Dword; 621 622 623 Buffer = ACPI_ALLOCATE_ZEROED (ACPI_PLD_BUFFER_SIZE); 624 if (!Buffer) 625 { 626 return (NULL); 627 } 628 629 /* First 32 bits */ 630 631 Dword = 0; 632 ACPI_PLD_SET_REVISION (&Dword, PldInfo->Revision); 633 ACPI_PLD_SET_IGNORE_COLOR (&Dword, PldInfo->IgnoreColor); 634 ACPI_PLD_SET_RED (&Dword, PldInfo->Red); 635 ACPI_PLD_SET_GREEN (&Dword, PldInfo->Green); 636 ACPI_PLD_SET_BLUE (&Dword, PldInfo->Blue); 637 ACPI_MOVE_32_TO_32 (&Buffer[0], &Dword); 638 639 /* Second 32 bits */ 640 641 Dword = 0; 642 ACPI_PLD_SET_WIDTH (&Dword, PldInfo->Width); 643 ACPI_PLD_SET_HEIGHT (&Dword, PldInfo->Height); 644 ACPI_MOVE_32_TO_32 (&Buffer[1], &Dword); 645 646 /* Third 32 bits */ 647 648 Dword = 0; 649 ACPI_PLD_SET_USER_VISIBLE (&Dword, PldInfo->UserVisible); 650 ACPI_PLD_SET_DOCK (&Dword, PldInfo->Dock); 651 ACPI_PLD_SET_LID (&Dword, PldInfo->Lid); 652 ACPI_PLD_SET_PANEL (&Dword, PldInfo->Panel); 653 ACPI_PLD_SET_VERTICAL (&Dword, PldInfo->VerticalPosition); 654 ACPI_PLD_SET_HORIZONTAL (&Dword, PldInfo->HorizontalPosition); 655 ACPI_PLD_SET_SHAPE (&Dword, PldInfo->Shape); 656 ACPI_PLD_SET_ORIENTATION (&Dword, PldInfo->GroupOrientation); 657 ACPI_PLD_SET_TOKEN (&Dword, PldInfo->GroupToken); 658 ACPI_PLD_SET_POSITION (&Dword, PldInfo->GroupPosition); 659 ACPI_PLD_SET_BAY (&Dword, PldInfo->Bay); 660 ACPI_MOVE_32_TO_32 (&Buffer[2], &Dword); 661 662 /* Fourth 32 bits */ 663 664 Dword = 0; 665 ACPI_PLD_SET_EJECTABLE (&Dword, PldInfo->Ejectable); 666 ACPI_PLD_SET_OSPM_EJECT (&Dword, PldInfo->OspmEjectRequired); 667 ACPI_PLD_SET_CABINET (&Dword, PldInfo->CabinetNumber); 668 ACPI_PLD_SET_CARD_CAGE (&Dword, PldInfo->CardCageNumber); 669 ACPI_PLD_SET_REFERENCE (&Dword, PldInfo->Reference); 670 ACPI_PLD_SET_ROTATION (&Dword, PldInfo->Rotation); 671 ACPI_PLD_SET_ORDER (&Dword, PldInfo->Order); 672 ACPI_MOVE_32_TO_32 (&Buffer[3], &Dword); 673 674 /* Revision 2 adds an additional DWORD */ 675 676 if (PldInfo->Revision >= 2) 677 { 678 /* Fifth 32 bits */ 679 680 Dword = 0; 681 ACPI_PLD_SET_VERT_OFFSET (&Dword, PldInfo->VerticalOffset); 682 ACPI_PLD_SET_HORIZ_OFFSET (&Dword, PldInfo->HorizontalOffset); 683 ACPI_MOVE_32_TO_32 (&Buffer[4], &Dword); 684 } 685 686 return (ACPI_CAST_PTR (UINT8, Buffer)); 687 } 688 689 690 /******************************************************************************* 691 * 692 * FUNCTION: OpcFindName 693 * 694 * PARAMETERS: List - Array of char strings to be searched 695 * Name - Char string to string for 696 * Index - Index value to set if found 697 * 698 * RETURN: TRUE if any names matched, FALSE otherwise 699 * 700 * DESCRIPTION: Match PLD name to value in lookup table. Sets Value to 701 * equivalent parameter value. 702 * 703 ******************************************************************************/ 704 705 static BOOLEAN 706 OpcFindName ( 707 const char **List, 708 char *Name, 709 UINT32 *Index) 710 { 711 const char *NameString; 712 UINT32 i; 713 714 715 AcpiUtStrupr (Name); 716 717 for (i = 0, NameString = List[0]; 718 NameString; 719 i++, NameString = List[i]) 720 { 721 if (!(strncmp (NameString, Name, strlen (Name)))) 722 { 723 *Index = i; 724 return (TRUE); 725 } 726 } 727 728 return (FALSE); 729 } 730