rscalc.c revision 241973
1/******************************************************************************* 2 * 3 * Module Name: rscalc - Calculate stream and list lengths 4 * 5 ******************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2012, 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 __RSCALC_C__ 45 46#include <contrib/dev/acpica/include/acpi.h> 47#include <contrib/dev/acpica/include/accommon.h> 48#include <contrib/dev/acpica/include/acresrc.h> 49#include <contrib/dev/acpica/include/acnamesp.h> 50 51 52#define _COMPONENT ACPI_RESOURCES 53 ACPI_MODULE_NAME ("rscalc") 54 55 56/* Local prototypes */ 57 58static UINT8 59AcpiRsCountSetBits ( 60 UINT16 BitField); 61 62static ACPI_RS_LENGTH 63AcpiRsStructOptionLength ( 64 ACPI_RESOURCE_SOURCE *ResourceSource); 65 66static UINT32 67AcpiRsStreamOptionLength ( 68 UINT32 ResourceLength, 69 UINT32 MinimumTotalLength); 70 71 72/******************************************************************************* 73 * 74 * FUNCTION: AcpiRsCountSetBits 75 * 76 * PARAMETERS: BitField - Field in which to count bits 77 * 78 * RETURN: Number of bits set within the field 79 * 80 * DESCRIPTION: Count the number of bits set in a resource field. Used for 81 * (Short descriptor) interrupt and DMA lists. 82 * 83 ******************************************************************************/ 84 85static UINT8 86AcpiRsCountSetBits ( 87 UINT16 BitField) 88{ 89 UINT8 BitsSet; 90 91 92 ACPI_FUNCTION_ENTRY (); 93 94 95 for (BitsSet = 0; BitField; BitsSet++) 96 { 97 /* Zero the least significant bit that is set */ 98 99 BitField &= (UINT16) (BitField - 1); 100 } 101 102 return (BitsSet); 103} 104 105 106/******************************************************************************* 107 * 108 * FUNCTION: AcpiRsStructOptionLength 109 * 110 * PARAMETERS: ResourceSource - Pointer to optional descriptor field 111 * 112 * RETURN: Status 113 * 114 * DESCRIPTION: Common code to handle optional ResourceSourceIndex and 115 * ResourceSource fields in some Large descriptors. Used during 116 * list-to-stream conversion 117 * 118 ******************************************************************************/ 119 120static ACPI_RS_LENGTH 121AcpiRsStructOptionLength ( 122 ACPI_RESOURCE_SOURCE *ResourceSource) 123{ 124 ACPI_FUNCTION_ENTRY (); 125 126 127 /* 128 * If the ResourceSource string is valid, return the size of the string 129 * (StringLength includes the NULL terminator) plus the size of the 130 * ResourceSourceIndex (1). 131 */ 132 if (ResourceSource->StringPtr) 133 { 134 return ((ACPI_RS_LENGTH) (ResourceSource->StringLength + 1)); 135 } 136 137 return (0); 138} 139 140 141/******************************************************************************* 142 * 143 * FUNCTION: AcpiRsStreamOptionLength 144 * 145 * PARAMETERS: ResourceLength - Length from the resource header 146 * MinimumTotalLength - Minimum length of this resource, before 147 * any optional fields. Includes header size 148 * 149 * RETURN: Length of optional string (0 if no string present) 150 * 151 * DESCRIPTION: Common code to handle optional ResourceSourceIndex and 152 * ResourceSource fields in some Large descriptors. Used during 153 * stream-to-list conversion 154 * 155 ******************************************************************************/ 156 157static UINT32 158AcpiRsStreamOptionLength ( 159 UINT32 ResourceLength, 160 UINT32 MinimumAmlResourceLength) 161{ 162 UINT32 StringLength = 0; 163 164 165 ACPI_FUNCTION_ENTRY (); 166 167 168 /* 169 * The ResourceSourceIndex and ResourceSource are optional elements of some 170 * Large-type resource descriptors. 171 */ 172 173 /* 174 * If the length of the actual resource descriptor is greater than the ACPI 175 * spec-defined minimum length, it means that a ResourceSourceIndex exists 176 * and is followed by a (required) null terminated string. The string length 177 * (including the null terminator) is the resource length minus the minimum 178 * length, minus one byte for the ResourceSourceIndex itself. 179 */ 180 if (ResourceLength > MinimumAmlResourceLength) 181 { 182 /* Compute the length of the optional string */ 183 184 StringLength = ResourceLength - MinimumAmlResourceLength - 1; 185 } 186 187 /* 188 * Round the length up to a multiple of the native word in order to 189 * guarantee that the entire resource descriptor is native word aligned 190 */ 191 return ((UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (StringLength)); 192} 193 194 195/******************************************************************************* 196 * 197 * FUNCTION: AcpiRsGetAmlLength 198 * 199 * PARAMETERS: Resource - Pointer to the resource linked list 200 * SizeNeeded - Where the required size is returned 201 * 202 * RETURN: Status 203 * 204 * DESCRIPTION: Takes a linked list of internal resource descriptors and 205 * calculates the size buffer needed to hold the corresponding 206 * external resource byte stream. 207 * 208 ******************************************************************************/ 209 210ACPI_STATUS 211AcpiRsGetAmlLength ( 212 ACPI_RESOURCE *Resource, 213 ACPI_SIZE *SizeNeeded) 214{ 215 ACPI_SIZE AmlSizeNeeded = 0; 216 ACPI_RS_LENGTH TotalSize; 217 218 219 ACPI_FUNCTION_TRACE (RsGetAmlLength); 220 221 222 /* Traverse entire list of internal resource descriptors */ 223 224 while (Resource) 225 { 226 /* Validate the descriptor type */ 227 228 if (Resource->Type > ACPI_RESOURCE_TYPE_MAX) 229 { 230 return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); 231 } 232 233 /* Get the base size of the (external stream) resource descriptor */ 234 235 TotalSize = AcpiGbl_AmlResourceSizes [Resource->Type]; 236 237 /* 238 * Augment the base size for descriptors with optional and/or 239 * variable-length fields 240 */ 241 switch (Resource->Type) 242 { 243 case ACPI_RESOURCE_TYPE_IRQ: 244 245 /* Length can be 3 or 2 */ 246 247 if (Resource->Data.Irq.DescriptorLength == 2) 248 { 249 TotalSize--; 250 } 251 break; 252 253 254 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 255 256 /* Length can be 1 or 0 */ 257 258 if (Resource->Data.Irq.DescriptorLength == 0) 259 { 260 TotalSize--; 261 } 262 break; 263 264 265 case ACPI_RESOURCE_TYPE_VENDOR: 266 /* 267 * Vendor Defined Resource: 268 * For a Vendor Specific resource, if the Length is between 1 and 7 269 * it will be created as a Small Resource data type, otherwise it 270 * is a Large Resource data type. 271 */ 272 if (Resource->Data.Vendor.ByteLength > 7) 273 { 274 /* Base size of a Large resource descriptor */ 275 276 TotalSize = sizeof (AML_RESOURCE_LARGE_HEADER); 277 } 278 279 /* Add the size of the vendor-specific data */ 280 281 TotalSize = (ACPI_RS_LENGTH) 282 (TotalSize + Resource->Data.Vendor.ByteLength); 283 break; 284 285 286 case ACPI_RESOURCE_TYPE_END_TAG: 287 /* 288 * End Tag: 289 * We are done -- return the accumulated total size. 290 */ 291 *SizeNeeded = AmlSizeNeeded + TotalSize; 292 293 /* Normal exit */ 294 295 return_ACPI_STATUS (AE_OK); 296 297 298 case ACPI_RESOURCE_TYPE_ADDRESS16: 299 /* 300 * 16-Bit Address Resource: 301 * Add the size of the optional ResourceSource info 302 */ 303 TotalSize = (ACPI_RS_LENGTH) 304 (TotalSize + AcpiRsStructOptionLength ( 305 &Resource->Data.Address16.ResourceSource)); 306 break; 307 308 309 case ACPI_RESOURCE_TYPE_ADDRESS32: 310 /* 311 * 32-Bit Address Resource: 312 * Add the size of the optional ResourceSource info 313 */ 314 TotalSize = (ACPI_RS_LENGTH) 315 (TotalSize + AcpiRsStructOptionLength ( 316 &Resource->Data.Address32.ResourceSource)); 317 break; 318 319 320 case ACPI_RESOURCE_TYPE_ADDRESS64: 321 /* 322 * 64-Bit Address Resource: 323 * Add the size of the optional ResourceSource info 324 */ 325 TotalSize = (ACPI_RS_LENGTH) 326 (TotalSize + AcpiRsStructOptionLength ( 327 &Resource->Data.Address64.ResourceSource)); 328 break; 329 330 331 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: 332 /* 333 * Extended IRQ Resource: 334 * Add the size of each additional optional interrupt beyond the 335 * required 1 (4 bytes for each UINT32 interrupt number) 336 */ 337 TotalSize = (ACPI_RS_LENGTH) 338 (TotalSize + 339 ((Resource->Data.ExtendedIrq.InterruptCount - 1) * 4) + 340 341 /* Add the size of the optional ResourceSource info */ 342 343 AcpiRsStructOptionLength ( 344 &Resource->Data.ExtendedIrq.ResourceSource)); 345 break; 346 347 348 case ACPI_RESOURCE_TYPE_GPIO: 349 350 TotalSize = (ACPI_RS_LENGTH) (TotalSize + (Resource->Data.Gpio.PinTableLength * 2) + 351 Resource->Data.Gpio.ResourceSource.StringLength + 352 Resource->Data.Gpio.VendorLength); 353 354 break; 355 356 357 case ACPI_RESOURCE_TYPE_SERIAL_BUS: 358 359 TotalSize = AcpiGbl_AmlResourceSerialBusSizes [Resource->Data.CommonSerialBus.Type]; 360 361 TotalSize = (ACPI_RS_LENGTH) (TotalSize + 362 Resource->Data.I2cSerialBus.ResourceSource.StringLength + 363 Resource->Data.I2cSerialBus.VendorLength); 364 365 break; 366 367 368 default: 369 break; 370 } 371 372 /* Update the total */ 373 374 AmlSizeNeeded += TotalSize; 375 376 /* Point to the next object */ 377 378 Resource = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, Resource->Length); 379 } 380 381 /* Did not find an EndTag resource descriptor */ 382 383 return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); 384} 385 386 387/******************************************************************************* 388 * 389 * FUNCTION: AcpiRsGetListLength 390 * 391 * PARAMETERS: AmlBuffer - Pointer to the resource byte stream 392 * AmlBufferLength - Size of AmlBuffer 393 * SizeNeeded - Where the size needed is returned 394 * 395 * RETURN: Status 396 * 397 * DESCRIPTION: Takes an external resource byte stream and calculates the size 398 * buffer needed to hold the corresponding internal resource 399 * descriptor linked list. 400 * 401 ******************************************************************************/ 402 403ACPI_STATUS 404AcpiRsGetListLength ( 405 UINT8 *AmlBuffer, 406 UINT32 AmlBufferLength, 407 ACPI_SIZE *SizeNeeded) 408{ 409 ACPI_STATUS Status; 410 UINT8 *EndAml; 411 UINT8 *Buffer; 412 UINT32 BufferSize; 413 UINT16 Temp16; 414 UINT16 ResourceLength; 415 UINT32 ExtraStructBytes; 416 UINT8 ResourceIndex; 417 UINT8 MinimumAmlResourceLength; 418 AML_RESOURCE *AmlResource; 419 420 421 ACPI_FUNCTION_TRACE (RsGetListLength); 422 423 424 *SizeNeeded = ACPI_RS_SIZE_MIN; /* Minimum size is one EndTag */ 425 EndAml = AmlBuffer + AmlBufferLength; 426 427 /* Walk the list of AML resource descriptors */ 428 429 while (AmlBuffer < EndAml) 430 { 431 /* Validate the Resource Type and Resource Length */ 432 433 Status = AcpiUtValidateResource (AmlBuffer, &ResourceIndex); 434 if (ACPI_FAILURE (Status)) 435 { 436 /* 437 * Exit on failure. Cannot continue because the descriptor length 438 * may be bogus also. 439 */ 440 return_ACPI_STATUS (Status); 441 } 442 443 AmlResource = (void *) AmlBuffer; 444 445 /* Get the resource length and base (minimum) AML size */ 446 447 ResourceLength = AcpiUtGetResourceLength (AmlBuffer); 448 MinimumAmlResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex]; 449 450 /* 451 * Augment the size for descriptors with optional 452 * and/or variable length fields 453 */ 454 ExtraStructBytes = 0; 455 Buffer = AmlBuffer + AcpiUtGetResourceHeaderLength (AmlBuffer); 456 457 switch (AcpiUtGetResourceType (AmlBuffer)) 458 { 459 case ACPI_RESOURCE_NAME_IRQ: 460 /* 461 * IRQ Resource: 462 * Get the number of bits set in the 16-bit IRQ mask 463 */ 464 ACPI_MOVE_16_TO_16 (&Temp16, Buffer); 465 ExtraStructBytes = AcpiRsCountSetBits (Temp16); 466 break; 467 468 469 case ACPI_RESOURCE_NAME_DMA: 470 /* 471 * DMA Resource: 472 * Get the number of bits set in the 8-bit DMA mask 473 */ 474 ExtraStructBytes = AcpiRsCountSetBits (*Buffer); 475 break; 476 477 478 case ACPI_RESOURCE_NAME_VENDOR_SMALL: 479 case ACPI_RESOURCE_NAME_VENDOR_LARGE: 480 /* 481 * Vendor Resource: 482 * Get the number of vendor data bytes 483 */ 484 ExtraStructBytes = ResourceLength; 485 486 /* 487 * There is already one byte included in the minimum 488 * descriptor size. If there are extra struct bytes, 489 * subtract one from the count. 490 */ 491 if (ExtraStructBytes) 492 { 493 ExtraStructBytes--; 494 } 495 break; 496 497 498 case ACPI_RESOURCE_NAME_END_TAG: 499 /* 500 * End Tag: This is the normal exit 501 */ 502 return_ACPI_STATUS (AE_OK); 503 504 505 case ACPI_RESOURCE_NAME_ADDRESS32: 506 case ACPI_RESOURCE_NAME_ADDRESS16: 507 case ACPI_RESOURCE_NAME_ADDRESS64: 508 /* 509 * Address Resource: 510 * Add the size of the optional ResourceSource 511 */ 512 ExtraStructBytes = AcpiRsStreamOptionLength ( 513 ResourceLength, MinimumAmlResourceLength); 514 break; 515 516 517 case ACPI_RESOURCE_NAME_EXTENDED_IRQ: 518 /* 519 * Extended IRQ Resource: 520 * Using the InterruptTableLength, add 4 bytes for each additional 521 * interrupt. Note: at least one interrupt is required and is 522 * included in the minimum descriptor size (reason for the -1) 523 */ 524 ExtraStructBytes = (Buffer[1] - 1) * sizeof (UINT32); 525 526 /* Add the size of the optional ResourceSource */ 527 528 ExtraStructBytes += AcpiRsStreamOptionLength ( 529 ResourceLength - ExtraStructBytes, MinimumAmlResourceLength); 530 break; 531 532 case ACPI_RESOURCE_NAME_GPIO: 533 534 /* Vendor data is optional */ 535 536 if (AmlResource->Gpio.VendorLength) 537 { 538 ExtraStructBytes += AmlResource->Gpio.VendorOffset - 539 AmlResource->Gpio.PinTableOffset + AmlResource->Gpio.VendorLength; 540 } 541 else 542 { 543 ExtraStructBytes += AmlResource->LargeHeader.ResourceLength + 544 sizeof (AML_RESOURCE_LARGE_HEADER) - 545 AmlResource->Gpio.PinTableOffset; 546 } 547 break; 548 549 case ACPI_RESOURCE_NAME_SERIAL_BUS: 550 551 MinimumAmlResourceLength = AcpiGbl_ResourceAmlSerialBusSizes[ 552 AmlResource->CommonSerialBus.Type]; 553 ExtraStructBytes += AmlResource->CommonSerialBus.ResourceLength - 554 MinimumAmlResourceLength; 555 break; 556 557 default: 558 break; 559 } 560 561 /* 562 * Update the required buffer size for the internal descriptor structs 563 * 564 * Important: Round the size up for the appropriate alignment. This 565 * is a requirement on IA64. 566 */ 567 if (AcpiUtGetResourceType (AmlBuffer) == ACPI_RESOURCE_NAME_SERIAL_BUS) 568 { 569 BufferSize = AcpiGbl_ResourceStructSerialBusSizes[ 570 AmlResource->CommonSerialBus.Type] + ExtraStructBytes; 571 } 572 else 573 { 574 BufferSize = AcpiGbl_ResourceStructSizes[ResourceIndex] + 575 ExtraStructBytes; 576 } 577 BufferSize = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (BufferSize); 578 579 *SizeNeeded += BufferSize; 580 581 ACPI_DEBUG_PRINT ((ACPI_DB_RESOURCES, 582 "Type %.2X, AmlLength %.2X InternalLength %.2X\n", 583 AcpiUtGetResourceType (AmlBuffer), 584 AcpiUtGetDescriptorLength (AmlBuffer), BufferSize)); 585 586 /* 587 * Point to the next resource within the AML stream using the length 588 * contained in the resource descriptor header 589 */ 590 AmlBuffer += AcpiUtGetDescriptorLength (AmlBuffer); 591 } 592 593 /* Did not find an EndTag resource descriptor */ 594 595 return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); 596} 597 598 599/******************************************************************************* 600 * 601 * FUNCTION: AcpiRsGetPciRoutingTableLength 602 * 603 * PARAMETERS: PackageObject - Pointer to the package object 604 * BufferSizeNeeded - UINT32 pointer of the size buffer 605 * needed to properly return the 606 * parsed data 607 * 608 * RETURN: Status 609 * 610 * DESCRIPTION: Given a package representing a PCI routing table, this 611 * calculates the size of the corresponding linked list of 612 * descriptions. 613 * 614 ******************************************************************************/ 615 616ACPI_STATUS 617AcpiRsGetPciRoutingTableLength ( 618 ACPI_OPERAND_OBJECT *PackageObject, 619 ACPI_SIZE *BufferSizeNeeded) 620{ 621 UINT32 NumberOfElements; 622 ACPI_SIZE TempSizeNeeded = 0; 623 ACPI_OPERAND_OBJECT **TopObjectList; 624 UINT32 Index; 625 ACPI_OPERAND_OBJECT *PackageElement; 626 ACPI_OPERAND_OBJECT **SubObjectList; 627 BOOLEAN NameFound; 628 UINT32 TableIndex; 629 630 631 ACPI_FUNCTION_TRACE (RsGetPciRoutingTableLength); 632 633 634 NumberOfElements = PackageObject->Package.Count; 635 636 /* 637 * Calculate the size of the return buffer. 638 * The base size is the number of elements * the sizes of the 639 * structures. Additional space for the strings is added below. 640 * The minus one is to subtract the size of the UINT8 Source[1] 641 * member because it is added below. 642 * 643 * But each PRT_ENTRY structure has a pointer to a string and 644 * the size of that string must be found. 645 */ 646 TopObjectList = PackageObject->Package.Elements; 647 648 for (Index = 0; Index < NumberOfElements; Index++) 649 { 650 /* Dereference the sub-package */ 651 652 PackageElement = *TopObjectList; 653 654 /* We must have a valid Package object */ 655 656 if (!PackageElement || 657 (PackageElement->Common.Type != ACPI_TYPE_PACKAGE)) 658 { 659 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 660 } 661 662 /* 663 * The SubObjectList will now point to an array of the 664 * four IRQ elements: Address, Pin, Source and SourceIndex 665 */ 666 SubObjectList = PackageElement->Package.Elements; 667 668 /* Scan the IrqTableElements for the Source Name String */ 669 670 NameFound = FALSE; 671 672 for (TableIndex = 0; TableIndex < 4 && !NameFound; TableIndex++) 673 { 674 if (*SubObjectList && /* Null object allowed */ 675 676 ((ACPI_TYPE_STRING == 677 (*SubObjectList)->Common.Type) || 678 679 ((ACPI_TYPE_LOCAL_REFERENCE == 680 (*SubObjectList)->Common.Type) && 681 682 ((*SubObjectList)->Reference.Class == 683 ACPI_REFCLASS_NAME)))) 684 { 685 NameFound = TRUE; 686 } 687 else 688 { 689 /* Look at the next element */ 690 691 SubObjectList++; 692 } 693 } 694 695 TempSizeNeeded += (sizeof (ACPI_PCI_ROUTING_TABLE) - 4); 696 697 /* Was a String type found? */ 698 699 if (NameFound) 700 { 701 if ((*SubObjectList)->Common.Type == ACPI_TYPE_STRING) 702 { 703 /* 704 * The length String.Length field does not include the 705 * terminating NULL, add 1 706 */ 707 TempSizeNeeded += ((ACPI_SIZE) 708 (*SubObjectList)->String.Length + 1); 709 } 710 else 711 { 712 TempSizeNeeded += AcpiNsGetPathnameLength ( 713 (*SubObjectList)->Reference.Node); 714 } 715 } 716 else 717 { 718 /* 719 * If no name was found, then this is a NULL, which is 720 * translated as a UINT32 zero. 721 */ 722 TempSizeNeeded += sizeof (UINT32); 723 } 724 725 /* Round up the size since each element must be aligned */ 726 727 TempSizeNeeded = ACPI_ROUND_UP_TO_64BIT (TempSizeNeeded); 728 729 /* Point to the next ACPI_OPERAND_OBJECT */ 730 731 TopObjectList++; 732 } 733 734 /* 735 * Add an extra element to the end of the list, essentially a 736 * NULL terminator 737 */ 738 *BufferSizeNeeded = TempSizeNeeded + sizeof (ACPI_PCI_ROUTING_TABLE); 739 return_ACPI_STATUS (AE_OK); 740} 741