Example #1
0
ACPI_STATUS
AcpiExExtractFromField (
    ACPI_OPERAND_OBJECT     *ObjDesc,
    void                    *Buffer,
    UINT32                  BufferLength)
{
    ACPI_STATUS             Status;
    UINT64                  RawDatum;
    UINT64                  MergedDatum;
    UINT32                  FieldOffset = 0;
    UINT32                  BufferOffset = 0;
    UINT32                  BufferTailBits;
    UINT32                  DatumCount;
    UINT32                  FieldDatumCount;
    UINT32                  AccessBitWidth;
    UINT32                  i;


    ACPI_FUNCTION_TRACE (ExExtractFromField);


    /* Validate target buffer and clear it */

    if (BufferLength <
        ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength))
    {
        ACPI_ERROR ((AE_INFO,
            "Field size %u (bits) is too large for buffer (%u)",
            ObjDesc->CommonField.BitLength, BufferLength));

        return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
    }

    memset (Buffer, 0, BufferLength);
    AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);

    /* Handle the simple case here */

    if ((ObjDesc->CommonField.StartFieldBitOffset == 0) &&
        (ObjDesc->CommonField.BitLength == AccessBitWidth))
    {
        if (BufferLength >= sizeof (UINT64))
        {
            Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ);
        }
        else
        {
            /* Use RawDatum (UINT64) to handle buffers < 64 bits */

            Status = AcpiExFieldDatumIo (ObjDesc, 0, &RawDatum, ACPI_READ);
            memcpy (Buffer, &RawDatum, BufferLength);
        }

        return_ACPI_STATUS (Status);
    }

/* TBD: Move to common setup code */

    /* Field algorithm is limited to sizeof(UINT64), truncate if needed */

    if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
    {
        ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
        AccessBitWidth = sizeof (UINT64) * 8;
    }

    /* Compute the number of datums (access width data items) */

    DatumCount = ACPI_ROUND_UP_TO (
        ObjDesc->CommonField.BitLength, AccessBitWidth);

    FieldDatumCount = ACPI_ROUND_UP_TO (
        ObjDesc->CommonField.BitLength +
        ObjDesc->CommonField.StartFieldBitOffset, AccessBitWidth);

    /* Priming read from the field */

    Status = AcpiExFieldDatumIo (ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }
    MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;

    /* Read the rest of the field */

    for (i = 1; i < FieldDatumCount; i++)
    {
        /* Get next input datum from the field */

        FieldOffset += ObjDesc->CommonField.AccessByteWidth;
        Status = AcpiExFieldDatumIo (
            ObjDesc, FieldOffset, &RawDatum, ACPI_READ);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }

        /*
         * Merge with previous datum if necessary.
         *
         * Note: Before the shift, check if the shift value will be larger than
         * the integer size. If so, there is no need to perform the operation.
         * This avoids the differences in behavior between different compilers
         * concerning shift values larger than the target data width.
         */
        if (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset <
            ACPI_INTEGER_BIT_SIZE)
        {
            MergedDatum |= RawDatum <<
                (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
        }

        if (i == DatumCount)
        {
            break;
        }

        /* Write merged datum to target buffer */

        memcpy (((char *) Buffer) + BufferOffset, &MergedDatum,
            ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
                BufferLength - BufferOffset));

        BufferOffset += ObjDesc->CommonField.AccessByteWidth;
        MergedDatum = RawDatum >> ObjDesc->CommonField.StartFieldBitOffset;
    }

    /* Mask off any extra bits in the last datum */

    BufferTailBits = ObjDesc->CommonField.BitLength % AccessBitWidth;
    if (BufferTailBits)
    {
        MergedDatum &= ACPI_MASK_BITS_ABOVE (BufferTailBits);
    }

    /* Write the last datum to the buffer */

    memcpy (((char *) Buffer) + BufferOffset, &MergedDatum,
        ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
            BufferLength - BufferOffset));

    return_ACPI_STATUS (AE_OK);
}
Example #2
0
ACPI_STATUS
AcpiExInsertIntoField (
    ACPI_OPERAND_OBJECT     *ObjDesc,
    void                    *Buffer,
    UINT32                  BufferLength)
{
    void                    *NewBuffer;
    ACPI_STATUS             Status;
    UINT64                  Mask;
    UINT64                  WidthMask;
    UINT64                  MergedDatum;
    UINT64                  RawDatum = 0;
    UINT32                  FieldOffset = 0;
    UINT32                  BufferOffset = 0;
    UINT32                  BufferTailBits;
    UINT32                  DatumCount;
    UINT32                  FieldDatumCount;
    UINT32                  AccessBitWidth;
    UINT32                  RequiredLength;
    UINT32                  i;


    ACPI_FUNCTION_TRACE (ExInsertIntoField);


    /* Validate input buffer */

    NewBuffer = NULL;
    RequiredLength = ACPI_ROUND_BITS_UP_TO_BYTES (
        ObjDesc->CommonField.BitLength);

    /*
     * We must have a buffer that is at least as long as the field
     * we are writing to. This is because individual fields are
     * indivisible and partial writes are not supported -- as per
     * the ACPI specification.
     */
    if (BufferLength < RequiredLength)
    {
        /* We need to create a new buffer */

        NewBuffer = ACPI_ALLOCATE_ZEROED (RequiredLength);
        if (!NewBuffer)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        /*
         * Copy the original data to the new buffer, starting
         * at Byte zero. All unused (upper) bytes of the
         * buffer will be 0.
         */
        memcpy ((char *) NewBuffer, (char *) Buffer, BufferLength);
        Buffer = NewBuffer;
        BufferLength = RequiredLength;
    }

/* TBD: Move to common setup code */

    /* Algo is limited to sizeof(UINT64), so cut the AccessByteWidth */
    if (ObjDesc->CommonField.AccessByteWidth > sizeof (UINT64))
    {
        ObjDesc->CommonField.AccessByteWidth = sizeof (UINT64);
    }

    AccessBitWidth = ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth);

    /* Create the bitmasks used for bit insertion */

    WidthMask = ACPI_MASK_BITS_ABOVE_64 (AccessBitWidth);
    Mask = WidthMask &
        ACPI_MASK_BITS_BELOW (ObjDesc->CommonField.StartFieldBitOffset);

    /* Compute the number of datums (access width data items) */

    DatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength,
        AccessBitWidth);

    FieldDatumCount = ACPI_ROUND_UP_TO (ObjDesc->CommonField.BitLength +
        ObjDesc->CommonField.StartFieldBitOffset,
        AccessBitWidth);

    /* Get initial Datum from the input buffer */

    memcpy (&RawDatum, Buffer,
        ACPI_MIN(ObjDesc->CommonField.AccessByteWidth,
            BufferLength - BufferOffset));

    MergedDatum = RawDatum << ObjDesc->CommonField.StartFieldBitOffset;

    /* Write the entire field */

    for (i = 1; i < FieldDatumCount; i++)
    {
        /* Write merged datum to the target field */

        MergedDatum &= Mask;
        Status = AcpiExWriteWithUpdateRule (
            ObjDesc, Mask, MergedDatum, FieldOffset);
        if (ACPI_FAILURE (Status))
        {
            goto Exit;
        }

        FieldOffset += ObjDesc->CommonField.AccessByteWidth;

        /*
         * Start new output datum by merging with previous input datum
         * if necessary.
         *
         * Note: Before the shift, check if the shift value will be larger than
         * the integer size. If so, there is no need to perform the operation.
         * This avoids the differences in behavior between different compilers
         * concerning shift values larger than the target data width.
         */
        if ((AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset) <
            ACPI_INTEGER_BIT_SIZE)
        {
            MergedDatum = RawDatum >>
                (AccessBitWidth - ObjDesc->CommonField.StartFieldBitOffset);
        }
        else
        {
static void acpi_tb_convert_fadt(void)
{
	const char *name;
	struct acpi_generic_address *address64;
	u32 address32;
	u8 length;
	u8 flags;
	u32 i;

	/*
	 * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which
	 * should be zero are indeed zero. This will workaround BIOSs that
	 * inadvertently place values in these fields.
	 *
	 * The ACPI 1.0 reserved fields that will be zeroed are the bytes located
	 * at offset 45, 55, 95, and the word located at offset 109, 110.
	 *
	 * Note: The FADT revision value is unreliable. Only the length can be
	 * trusted.
	 */
	if (acpi_gbl_FADT.header.length <= ACPI_FADT_V2_SIZE) {
		acpi_gbl_FADT.preferred_profile = 0;
		acpi_gbl_FADT.pstate_control = 0;
		acpi_gbl_FADT.cst_control = 0;
		acpi_gbl_FADT.boot_flags = 0;
	}

	/*
	 * Now we can update the local FADT length to the length of the
	 * current FADT version as defined by the ACPI specification.
	 * Thus, we will have a common FADT internally.
	 */
	acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);

	/*
	 * Expand the 32-bit DSDT addresses to 64-bit as necessary.
	 * Later ACPICA code will always use the X 64-bit field.
	 */
	acpi_gbl_FADT.Xdsdt = acpi_tb_select_address("DSDT",
						     acpi_gbl_FADT.dsdt,
						     acpi_gbl_FADT.Xdsdt);

	/* If Hardware Reduced flag is set, we are all done */

	if (acpi_gbl_reduced_hardware) {
		return;
	}

	/* Examine all of the 64-bit extended address fields (X fields) */

	for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
		/*
		 * Get the 32-bit and 64-bit addresses, as well as the register
		 * length and register name.
		 */
		address32 = *ACPI_ADD_PTR(u32,
					  &acpi_gbl_FADT,
					  fadt_info_table[i].address32);

		address64 = ACPI_ADD_PTR(struct acpi_generic_address,
					 &acpi_gbl_FADT,
					 fadt_info_table[i].address64);

		length = *ACPI_ADD_PTR(u8,
				       &acpi_gbl_FADT,
				       fadt_info_table[i].length);

		name = fadt_info_table[i].name;
		flags = fadt_info_table[i].flags;

		/*
		 * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
		 * generic address structures as necessary. Later code will always use
		 * the 64-bit address structures.
		 *
		 * November 2013:
		 * Now always use the 64-bit address if it is valid (non-zero), in
		 * accordance with the ACPI specification which states that a 64-bit
		 * address supersedes the 32-bit version. This behavior can be
		 * overridden by the acpi_gbl_use32_bit_fadt_addresses flag.
		 *
		 * During 64-bit address construction and verification,
		 * these cases are handled:
		 *
		 * Address32 zero, Address64 [don't care]   - Use Address64
		 *
		 * No override: if acpi_gbl_use32_bit_fadt_addresses is FALSE, and:
		 * Address32 non-zero, Address64 zero       - Copy/use Address32
		 * Address32 non-zero == Address64 non-zero - Use Address64
		 * Address32 non-zero != Address64 non-zero - Warning, use Address64
		 *
		 * Override: if acpi_gbl_use32_bit_fadt_addresses is TRUE, and:
		 * Address32 non-zero, Address64 zero       - Copy/use Address32
		 * Address32 non-zero == Address64 non-zero - Copy/use Address32
		 * Address32 non-zero != Address64 non-zero - Warning, copy/use Address32
		 *
		 * Note: space_id is always I/O for 32-bit legacy address fields
		 */
		if (address32) {
			if (address64->address) {
				if (address64->address != (u64)address32) {

					/* Address mismatch */

					ACPI_BIOS_WARNING((AE_INFO,
							   "32/64X address mismatch in FADT/%s: "
							   "0x%8.8X/0x%8.8X%8.8X, using %u-bit address",
							   name, address32,
							   ACPI_FORMAT_UINT64
							   (address64->address),
							   acpi_gbl_use32_bit_fadt_addresses
							   ? 32 : 64));
				}

				/*
				 * For each extended field, check for length mismatch
				 * between the legacy length field and the corresponding
				 * 64-bit X length field.
				 * Note: If the legacy length field is > 0xFF bits, ignore
				 * this check. (GPE registers can be larger than the
				 * 64-bit GAS structure can accomodate, 0xFF bits).
				 */
				if ((ACPI_MUL_8(length) <= ACPI_UINT8_MAX) &&
				    (address64->bit_width !=
				     ACPI_MUL_8(length))) {
					ACPI_BIOS_WARNING((AE_INFO,
							   "32/64X length mismatch in FADT/%s: %u/%u",
							   name,
							   ACPI_MUL_8(length),
							   address64->
							   bit_width));
				}
			}

			/*
			 * Hardware register access code always uses the 64-bit fields.
			 * So if the 64-bit field is zero or is to be overridden,
			 * initialize it with the 32-bit fields.
			 * Note that when the 32-bit address favor is specified, the
			 * 64-bit fields are always re-initialized so that
			 * access_size/bit_width/bit_offset fields can be correctly
			 * configured to the values to trigger a 32-bit compatible
			 * access mode in the hardware register access code.
			 */
			if (!address64->address
			    || acpi_gbl_use32_bit_fadt_addresses) {
				acpi_tb_init_generic_address(address64,
							     ACPI_ADR_SPACE_SYSTEM_IO,
							     length,
							     (u64)address32,
							     name, flags);
			}
		}

		if (fadt_info_table[i].flags & ACPI_FADT_REQUIRED) {
			/*
			 * Field is required (Pm1a_event, Pm1a_control).
			 * Both the address and length must be non-zero.
			 */
			if (!address64->address || !length) {
				ACPI_BIOS_ERROR((AE_INFO,
						 "Required FADT field %s has zero address and/or length: "
						 "0x%8.8X%8.8X/0x%X",
						 name,
						 ACPI_FORMAT_UINT64(address64->
								    address),
						 length));
			}
		} else if (fadt_info_table[i].flags & ACPI_FADT_SEPARATE_LENGTH) {
			/*
			 * Field is optional (Pm2_control, GPE0, GPE1) AND has its own
			 * length field. If present, both the address and length must
			 * be valid.
			 */
			if ((address64->address && !length) ||
			    (!address64->address && length)) {
				ACPI_BIOS_WARNING((AE_INFO,
						   "Optional FADT field %s has valid %s but zero %s: "
						   "0x%8.8X%8.8X/0x%X", name,
						   (length ? "Length" :
						    "Address"),
						   (length ? "Address" :
						    "Length"),
						   ACPI_FORMAT_UINT64
						   (address64->address),
						   length));
			}
		}
	}
}
Example #4
0
ACPI_STATUS
AcpiExWriteWithUpdateRule (
    ACPI_OPERAND_OBJECT     *ObjDesc,
    UINT64                  Mask,
    UINT64                  FieldValue,
    UINT32                  FieldDatumByteOffset)
{
    ACPI_STATUS             Status = AE_OK;
    UINT64                  MergedValue;
    UINT64                  CurrentValue;


    ACPI_FUNCTION_TRACE_U32 (ExWriteWithUpdateRule, Mask);


    /* Start with the new bits  */

    MergedValue = FieldValue;

    /* If the mask is all ones, we don't need to worry about the update rule */

    if (Mask != ACPI_UINT64_MAX)
    {
        /* Decode the update rule */

        switch (ObjDesc->CommonField.FieldFlags & AML_FIELD_UPDATE_RULE_MASK)
        {
        case AML_FIELD_UPDATE_PRESERVE:
            /*
             * Check if update rule needs to be applied (not if mask is all
             * ones)  The left shift drops the bits we want to ignore.
             */
            if ((~Mask << (ACPI_MUL_8 (sizeof (Mask)) -
                   ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth))) != 0)
            {
                /*
                 * Read the current contents of the byte/word/dword containing
                 * the field, and merge with the new field value.
                 */
                Status = AcpiExFieldDatumIo (
                    ObjDesc, FieldDatumByteOffset, &CurrentValue, ACPI_READ);
                if (ACPI_FAILURE (Status))
                {
                    return_ACPI_STATUS (Status);
                }

                MergedValue |= (CurrentValue & ~Mask);
            }
            break;

        case AML_FIELD_UPDATE_WRITE_AS_ONES:

            /* Set positions outside the field to all ones */

            MergedValue |= ~Mask;
            break;

        case AML_FIELD_UPDATE_WRITE_AS_ZEROS:

            /* Set positions outside the field to all zeros */

            MergedValue &= Mask;
            break;

        default:

            ACPI_ERROR ((AE_INFO,
                "Unknown UpdateRule value: 0x%X",
                (ObjDesc->CommonField.FieldFlags &
                    AML_FIELD_UPDATE_RULE_MASK)));
            return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
        }
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
        "Mask %8.8X%8.8X, DatumOffset %X, Width %X, "
        "Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
        ACPI_FORMAT_UINT64 (Mask),
        FieldDatumByteOffset,
        ObjDesc->CommonField.AccessByteWidth,
        ACPI_FORMAT_UINT64 (FieldValue),
        ACPI_FORMAT_UINT64 (MergedValue)));

    /* Write the merged value */

    Status = AcpiExFieldDatumIo (
        ObjDesc, FieldDatumByteOffset, &MergedValue, ACPI_WRITE);

    return_ACPI_STATUS (Status);
}
Example #5
0
static char *
AcpiGetTagPathname (
    ACPI_PARSE_OBJECT       *IndexOp,
    ACPI_NAMESPACE_NODE     *BufferNode,
    ACPI_NAMESPACE_NODE     *ResourceNode,
    UINT32                  BitIndex)
{
    ACPI_STATUS             Status;
    UINT32                  ResourceBitIndex;
    UINT8                   ResourceTableIndex;
    ACPI_SIZE               RequiredSize;
    char                    *Pathname;
    AML_RESOURCE            *Aml;
    ACPI_PARSE_OBJECT       *Op;
    char                    *InternalPath;
    char                    *Tag;


    /* Get the Op that contains the actual buffer data */

    Op = BufferNode->Op->Common.Value.Arg;
    Op = Op->Common.Next;
    if (!Op)
    {
        return (NULL);
    }

    /* Get the individual resource descriptor and validate it */

    Aml = ACPI_CAST_PTR (AML_RESOURCE,
            &Op->Named.Data[ResourceNode->Value]);

    Status = AcpiUtValidateResource (NULL, Aml, &ResourceTableIndex);
    if (ACPI_FAILURE (Status))
    {
        return (NULL);
    }

    /* Get offset into this descriptor (from offset into entire buffer) */

    ResourceBitIndex = BitIndex - ACPI_MUL_8 (ResourceNode->Value);

    /* Get the tag associated with this resource descriptor and offset */

    Tag = AcpiDmGetResourceTag (ResourceBitIndex, Aml, ResourceTableIndex);
    if (!Tag)
    {
        return (NULL);
    }

    /*
     * Now that we know that we have a reference that can be converted to a
     * symbol, change the name of the resource to a unique name.
     */
    AcpiDmUpdateResourceName (ResourceNode);

    /* Get the full pathname to the parent buffer */

    RequiredSize = AcpiNsGetPathnameLength (BufferNode);
    if (!RequiredSize)
    {
        return (NULL);
    }

    Pathname = ACPI_ALLOCATE_ZEROED (RequiredSize + ACPI_PATH_SEGMENT_LENGTH);
    if (!Pathname)
    {
        return (NULL);
    }

    Status = AcpiNsBuildExternalPath (BufferNode, RequiredSize, Pathname);
    if (ACPI_FAILURE (Status))
    {
        ACPI_FREE (Pathname);
        return (NULL);
    }

    /*
     * Create the full path to the resource and tag by: remove the buffer name,
     * append the resource descriptor name, append a dot, append the tag name.
     *
     * TBD: Always using the full path is a bit brute force, the path can be
     * often be optimized with carats (if the original buffer namepath is a
     * single nameseg). This doesn't really matter, because these paths do not
     * end up in the final compiled AML, it's just an appearance issue for the
     * disassembled code.
     */
    Pathname[strlen (Pathname) - ACPI_NAME_SIZE] = 0;
    strncat (Pathname, ResourceNode->Name.Ascii, ACPI_NAME_SIZE);
    strcat (Pathname, ".");
    strncat (Pathname, Tag, ACPI_NAME_SIZE);

    /* Internalize the namepath to AML format */

    AcpiNsInternalizeName (Pathname, &InternalPath);
    ACPI_FREE (Pathname);

    /* Update the Op with the symbol */

    AcpiPsInitOp (IndexOp, AML_INT_NAMEPATH_OP);
    IndexOp->Common.Value.String = InternalPath;

    /* We will need the tag later. Cheat by putting it in the Node field */

    IndexOp->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Tag);
    return (InternalPath);
}
Example #6
0
acpi_status
acpi_ex_prep_field_value (
	struct acpi_create_field_info   *info)
{
	union acpi_operand_object       *obj_desc;
	u32                             type;
	acpi_status                     status;


	ACPI_FUNCTION_TRACE ("ex_prep_field_value");


	/* Parameter validation */

	if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
		if (!info->region_node) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null region_node\n"));
			return_ACPI_STATUS (AE_AML_NO_OPERAND);
		}

		type = acpi_ns_get_type (info->region_node);
		if (type != ACPI_TYPE_REGION) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Needed Region, found type %X %s\n",
				type, acpi_ut_get_type_name (type)));

			return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
		}
	}

	/* Allocate a new field object */

	obj_desc = acpi_ut_create_internal_object (info->field_type);
	if (!obj_desc) {
		return_ACPI_STATUS (AE_NO_MEMORY);
	}

	/* Initialize areas of the object that are common to all fields */

	obj_desc->common_field.node = info->field_node;
	status = acpi_ex_prep_common_field_object (obj_desc, info->field_flags,
			 info->attribute, info->field_bit_position, info->field_bit_length);
	if (ACPI_FAILURE (status)) {
		acpi_ut_delete_object_desc (obj_desc);
		return_ACPI_STATUS (status);
	}

	/* Initialize areas of the object that are specific to the field type */

	switch (info->field_type) {
	case ACPI_TYPE_LOCAL_REGION_FIELD:

		obj_desc->field.region_obj   = acpi_ns_get_attached_object (info->region_node);

		/* An additional reference for the container */

		acpi_ut_add_reference (obj_desc->field.region_obj);

		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
			"region_field: Bitoff=%X Off=%X Gran=%X Region %p\n",
			obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset,
			obj_desc->field.access_byte_width, obj_desc->field.region_obj));
		break;


	case ACPI_TYPE_LOCAL_BANK_FIELD:

		obj_desc->bank_field.value   = info->bank_value;
		obj_desc->bank_field.region_obj = acpi_ns_get_attached_object (info->region_node);
		obj_desc->bank_field.bank_obj = acpi_ns_get_attached_object (info->register_node);

		/* An additional reference for the attached objects */

		acpi_ut_add_reference (obj_desc->bank_field.region_obj);
		acpi_ut_add_reference (obj_desc->bank_field.bank_obj);

		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
			"Bank Field: bit_off=%X Off=%X Gran=%X Region %p bank_reg %p\n",
			obj_desc->bank_field.start_field_bit_offset,
			obj_desc->bank_field.base_byte_offset,
			obj_desc->field.access_byte_width,
			obj_desc->bank_field.region_obj,
			obj_desc->bank_field.bank_obj));
		break;


	case ACPI_TYPE_LOCAL_INDEX_FIELD:

		obj_desc->index_field.index_obj = acpi_ns_get_attached_object (info->register_node);
		obj_desc->index_field.data_obj = acpi_ns_get_attached_object (info->data_register_node);
		obj_desc->index_field.value  = (u32)
			(info->field_bit_position / ACPI_MUL_8 (obj_desc->field.access_byte_width));

		if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Index Object\n"));
			return_ACPI_STATUS (AE_AML_INTERNAL);
		}

		/* An additional reference for the attached objects */

		acpi_ut_add_reference (obj_desc->index_field.data_obj);
		acpi_ut_add_reference (obj_desc->index_field.index_obj);

		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
			"index_field: bitoff=%X off=%X gran=%X Index %p Data %p\n",
			obj_desc->index_field.start_field_bit_offset,
			obj_desc->index_field.base_byte_offset,
			obj_desc->field.access_byte_width,
			obj_desc->index_field.index_obj,
			obj_desc->index_field.data_obj));
		break;

	default:
		/* No other types should get here */
		break;
	}

	/*
	 * Store the constructed descriptor (obj_desc) into the parent Node,
	 * preserving the current type of that named_obj.
	 */
	status = acpi_ns_attach_object (info->field_node, obj_desc,
			  acpi_ns_get_type (info->field_node));

	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "set named_obj %p (%4.4s) val = %p\n",
			info->field_node, info->field_node->name.ascii, obj_desc));

	/* Remove local reference to the object */

	acpi_ut_remove_reference (obj_desc);
	return_ACPI_STATUS (status);
}
acpi_status
acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
			  void *buffer, u32 buffer_length)
{
	void *new_buffer;
	acpi_status status;
	u64 mask;
	u64 width_mask;
	u64 merged_datum;
	u64 raw_datum = 0;
	u32 field_offset = 0;
	u32 buffer_offset = 0;
	u32 buffer_tail_bits;
	u32 datum_count;
	u32 field_datum_count;
	u32 access_bit_width;
	u32 required_length;
	u32 i;

	ACPI_FUNCTION_TRACE(ex_insert_into_field);

	/* Validate input buffer */

	new_buffer = NULL;
	required_length =
	    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
	/*
	 * We must have a buffer that is at least as long as the field
	 * we are writing to.  This is because individual fields are
	 * indivisible and partial writes are not supported -- as per
	 * the ACPI specification.
	 */
	if (buffer_length < required_length) {

		/* We need to create a new buffer */

		new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
		if (!new_buffer) {
			return_ACPI_STATUS(AE_NO_MEMORY);
		}

		/*
		 * Copy the original data to the new buffer, starting
		 * at Byte zero.  All unused (upper) bytes of the
		 * buffer will be 0.
		 */
		ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length);
		buffer = new_buffer;
		buffer_length = required_length;
	}

/* TBD: Move to common setup code */

	/* Algo is limited to sizeof(u64), so cut the access_byte_width */
	if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
		obj_desc->common_field.access_byte_width = sizeof(u64);
	}

	access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);

	/*
	 * Create the bitmasks used for bit insertion.
	 * Note: This if/else is used to bypass compiler differences with the
	 * shift operator
	 */
	if (access_bit_width == ACPI_INTEGER_BIT_SIZE) {
		width_mask = ACPI_UINT64_MAX;
	} else {
		width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width);
	}

	mask = width_mask &
	    ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);

	/* Compute the number of datums (access width data items) */

	datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
				       access_bit_width);

	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
					     obj_desc->common_field.
					     start_field_bit_offset,
					     access_bit_width);

	/* Get initial Datum from the input buffer */

	ACPI_MEMCPY(&raw_datum, buffer,
		    ACPI_MIN(obj_desc->common_field.access_byte_width,
			     buffer_length - buffer_offset));

	merged_datum =
	    raw_datum << obj_desc->common_field.start_field_bit_offset;

	/* Write the entire field */

	for (i = 1; i < field_datum_count; i++) {

		/* Write merged datum to the target field */

		merged_datum &= mask;
		status = acpi_ex_write_with_update_rule(obj_desc, mask,
							merged_datum,
							field_offset);
		if (ACPI_FAILURE(status)) {
			goto exit;
		}

		field_offset += obj_desc->common_field.access_byte_width;

		/*
		 * Start new output datum by merging with previous input datum
		 * if necessary.
		 *
		 * Note: Before the shift, check if the shift value will be larger than
		 * the integer size. If so, there is no need to perform the operation.
		 * This avoids the differences in behavior between different compilers
		 * concerning shift values larger than the target data width.
		 */
		if ((access_bit_width -
		     obj_desc->common_field.start_field_bit_offset) <
		    ACPI_INTEGER_BIT_SIZE) {
			merged_datum =
			    raw_datum >> (access_bit_width -
					  obj_desc->common_field.
					  start_field_bit_offset);
		} else {
Example #8
0
acpi_status
acpi_ex_write_with_update_rule (
	union acpi_operand_object       *obj_desc,
	acpi_integer                    mask,
	acpi_integer                    field_value,
	u32                             field_datum_byte_offset)
{
	acpi_status                     status = AE_OK;
	acpi_integer                    merged_value;
	acpi_integer                    current_value;


	ACPI_FUNCTION_TRACE_U32 ("ex_write_with_update_rule", mask);


	/* Start with the new bits  */

	merged_value = field_value;

	/* If the mask is all ones, we don't need to worry about the update rule */

	if (mask != ACPI_INTEGER_MAX) {
		/* Decode the update rule */

		switch (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK) {
		case AML_FIELD_UPDATE_PRESERVE:
			/*
			 * Check if update rule needs to be applied (not if mask is all
			 * ones)  The left shift drops the bits we want to ignore.
			 */
			if ((~mask << (ACPI_MUL_8 (sizeof (mask)) -
					 ACPI_MUL_8 (obj_desc->common_field.access_byte_width))) != 0) {
				/*
				 * Read the current contents of the byte/word/dword containing
				 * the field, and merge with the new field value.
				 */
				status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
						  &current_value, ACPI_READ);
				if (ACPI_FAILURE (status)) {
					return_ACPI_STATUS (status);
				}

				merged_value |= (current_value & ~mask);
			}
			break;

		case AML_FIELD_UPDATE_WRITE_AS_ONES:

			/* Set positions outside the field to all ones */

			merged_value |= ~mask;
			break;

		case AML_FIELD_UPDATE_WRITE_AS_ZEROS:

			/* Set positions outside the field to all zeros */

			merged_value &= mask;
			break;

		default:

			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"write_with_update_rule: Unknown update_rule setting: %X\n",
				(obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK)));
			return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
		}
	}

	ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
		"Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n",
		ACPI_FORMAT_UINT64 (mask),
		field_datum_byte_offset,
		obj_desc->common_field.access_byte_width,
		ACPI_FORMAT_UINT64 (field_value),
		ACPI_FORMAT_UINT64 (merged_value)));

	/* Write the merged value */

	status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
			  &merged_value, ACPI_WRITE);

	return_ACPI_STATUS (status);
}
Example #9
0
static void
AcpiTbValidateFadt (
    void)
{
    char                    *Name;
    ACPI_GENERIC_ADDRESS    *Address64;
    UINT8                   Length;
    UINT32                  i;


    /*
     * Check for FACS and DSDT address mismatches. An address mismatch between
     * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
     * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables.
     */
    if (AcpiGbl_FADT.Facs &&
        (AcpiGbl_FADT.XFacs != (UINT64) AcpiGbl_FADT.Facs))
    {
        ACPI_BIOS_WARNING ((AE_INFO,
            "32/64X FACS address mismatch in FADT - "
            "0x%8.8X/0x%8.8X%8.8X, using 32",
            AcpiGbl_FADT.Facs, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XFacs)));

        AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs;
    }

    if (AcpiGbl_FADT.Dsdt &&
        (AcpiGbl_FADT.XDsdt != (UINT64) AcpiGbl_FADT.Dsdt))
    {
        ACPI_BIOS_WARNING ((AE_INFO,
            "32/64X DSDT address mismatch in FADT - "
            "0x%8.8X/0x%8.8X%8.8X, using 32",
            AcpiGbl_FADT.Dsdt, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XDsdt)));

        AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt;
    }

    /* If Hardware Reduced flag is set, we are all done */

    if (AcpiGbl_ReducedHardware)
    {
        return;
    }

    /* Examine all of the 64-bit extended address fields (X fields) */

    for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
    {
        /*
         * Generate pointer to the 64-bit address, get the register
         * length (width) and the register name
         */
        Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS,
                        &AcpiGbl_FADT, FadtInfoTable[i].Address64);
        Length = *ACPI_ADD_PTR (UINT8,
                        &AcpiGbl_FADT, FadtInfoTable[i].Length);
        Name = FadtInfoTable[i].Name;

        /*
         * For each extended field, check for length mismatch between the
         * legacy length field and the corresponding 64-bit X length field.
         */
        if (Address64->Address &&
           (Address64->BitWidth != ACPI_MUL_8 (Length)))
        {
            ACPI_BIOS_WARNING ((AE_INFO,
                "32/64X length mismatch in FADT/%s: %u/%u",
                Name, ACPI_MUL_8 (Length), Address64->BitWidth));
        }

        if (FadtInfoTable[i].Type & ACPI_FADT_REQUIRED)
        {
            /*
             * Field is required (PM1aEvent, PM1aControl, PmTimer).
             * Both the address and length must be non-zero.
             */
            if (!Address64->Address || !Length)
            {
                ACPI_BIOS_ERROR ((AE_INFO,
                    "Required FADT field %s has zero address and/or length: "
                    "0x%8.8X%8.8X/0x%X",
                    Name, ACPI_FORMAT_UINT64 (Address64->Address), Length));
            }
        }
        else if (FadtInfoTable[i].Type & ACPI_FADT_SEPARATE_LENGTH)
        {
            /*
             * Field is optional (PM2Control, GPE0, GPE1) AND has its own
             * length field. If present, both the address and length must
             * be valid.
             */
            if ((Address64->Address && !Length) ||
                (!Address64->Address && Length))
            {
                ACPI_BIOS_WARNING ((AE_INFO,
                    "Optional FADT field %s has zero address or length: "
                    "0x%8.8X%8.8X/0x%X",
                    Name, ACPI_FORMAT_UINT64 (Address64->Address), Length));
            }
        }
    }
}
acpi_status
acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
			   void *buffer, u32 buffer_length)
{
	acpi_status status;
	u64 raw_datum;
	u64 merged_datum;
	u32 field_offset = 0;
	u32 buffer_offset = 0;
	u32 buffer_tail_bits;
	u32 datum_count;
	u32 field_datum_count;
	u32 access_bit_width;
	u32 i;

	ACPI_FUNCTION_TRACE(ex_extract_from_field);

	/* Validate target buffer and clear it */

	if (buffer_length <
	    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
		ACPI_ERROR((AE_INFO,
			    "Field size %u (bits) is too large for buffer (%u)",
			    obj_desc->common_field.bit_length, buffer_length));

		return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
	}

	ACPI_MEMSET(buffer, 0, buffer_length);
	access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);

	/* Handle the simple case here */

	if ((obj_desc->common_field.start_field_bit_offset == 0) &&
	    (obj_desc->common_field.bit_length == access_bit_width)) {
		if (buffer_length >= sizeof(u64)) {
			status =
		    	    acpi_ex_field_datum_io(obj_desc, 0, buffer,
					   	   ACPI_READ);
		} else {
			/* Use raw_datum (u64) to handle buffers < 64 bits */

			status =
			    acpi_ex_field_datum_io(obj_desc, 0, &raw_datum,
						   ACPI_READ);
			ACPI_MEMCPY(buffer, &raw_datum, buffer_length);
		}

		return_ACPI_STATUS(status);
	}

/* TBD: Move to common setup code */

	/* Field algorithm is limited to sizeof(u64), truncate if needed */

	if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
		obj_desc->common_field.access_byte_width = sizeof(u64);
		access_bit_width = sizeof(u64) * 8;
	}

	/* Compute the number of datums (access width data items) */

	datum_count =
	    ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
			     access_bit_width);

	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
					     obj_desc->common_field.
					     start_field_bit_offset,
					     access_bit_width);

	/* Priming read from the field */

	status =
	    acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
				   ACPI_READ);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}
	merged_datum =
	    raw_datum >> obj_desc->common_field.start_field_bit_offset;

	/* Read the rest of the field */

	for (i = 1; i < field_datum_count; i++) {

		/* Get next input datum from the field */

		field_offset += obj_desc->common_field.access_byte_width;
		status = acpi_ex_field_datum_io(obj_desc, field_offset,
						&raw_datum, ACPI_READ);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}

		/*
		 * Merge with previous datum if necessary.
		 *
		 * Note: Before the shift, check if the shift value will be larger than
		 * the integer size. If so, there is no need to perform the operation.
		 * This avoids the differences in behavior between different compilers
		 * concerning shift values larger than the target data width.
		 */
		if (access_bit_width -
		    obj_desc->common_field.start_field_bit_offset <
		    ACPI_INTEGER_BIT_SIZE) {
			merged_datum |=
			    raw_datum << (access_bit_width -
					  obj_desc->common_field.
					  start_field_bit_offset);
		}

		if (i == datum_count) {
			break;
		}

		/* Write merged datum to target buffer */

		ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
			    ACPI_MIN(obj_desc->common_field.access_byte_width,
				     buffer_length - buffer_offset));

		buffer_offset += obj_desc->common_field.access_byte_width;
		merged_datum =
		    raw_datum >> obj_desc->common_field.start_field_bit_offset;
	}

	/* Mask off any extra bits in the last datum */

	buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width;
	if (buffer_tail_bits) {
		merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
	}

	/* Write the last datum to the buffer */

	ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
		    ACPI_MIN(obj_desc->common_field.access_byte_width,
			     buffer_length - buffer_offset));

	return_ACPI_STATUS(AE_OK);
}
Example #11
0
static ACPI_STATUS
XfNamespaceLocateBegin (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;
    ACPI_OBJECT_TYPE        ObjectType;
    char                    *Path;
    UINT8                   PassedArgs;
    ACPI_PARSE_OBJECT       *NextOp;
    ACPI_PARSE_OBJECT       *OwningOp;
    ACPI_PARSE_OBJECT       *SpaceIdOp;
    UINT32                  MinimumLength;
    UINT32                  Offset;
    UINT32                  FieldBitLength;
    UINT32                  TagBitLength;
    UINT8                   Message = 0;
    const ACPI_OPCODE_INFO  *OpInfo;
    UINT32                  Flags;


    ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op);

    /*
     * If this node is the actual declaration of a name
     * [such as the XXXX name in "Method (XXXX)"],
     * we are not interested in it here. We only care about names that are
     * references to other objects within the namespace and the parent objects
     * of name declarations
     */
    if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* We are only interested in opcodes that have an associated name */

    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);

    if ((!(OpInfo->Flags & AML_NAMED)) &&
        (!(OpInfo->Flags & AML_CREATE)) &&
        (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
        (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
        (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /*
     * One special case: CondRefOf operator - we don't care if the name exists
     * or not at this point, just ignore it, the point of the operator is to
     * determine if the name exists at runtime.
     */
    if ((Op->Asl.Parent) &&
        (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /*
     * We must enable the "search-to-root" for single NameSegs, but
     * we have to be very careful about opening up scopes
     */
    Flags = ACPI_NS_SEARCH_PARENT;
    if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
        (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
        (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
    {
        /*
         * These are name references, do not push the scope stack
         * for them.
         */
        Flags |= ACPI_NS_DONT_OPEN_SCOPE;
    }

    /* Get the NamePath from the appropriate place */

    if (OpInfo->Flags & AML_NAMED)
    {
        /* For nearly all NAMED operators, the name reference is the first child */

        Path = Op->Asl.Child->Asl.Value.String;
        if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
        {
            /*
             * ALIAS is the only oddball opcode, the name declaration
             * (alias name) is the second operand
             */
            Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
        }
    }
    else if (OpInfo->Flags & AML_CREATE)
    {
        /* Name must appear as the last parameter */

        NextOp = Op->Asl.Child;
        while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
        {
            NextOp = NextOp->Asl.Next;
        }
        Path = NextOp->Asl.Value.String;
    }
    else
    {
        Path = Op->Asl.Value.String;
    }

    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "Type=%s\n", AcpiUtGetTypeName (ObjectType)));

    /*
     * Lookup the name in the namespace. Name must exist at this point, or it
     * is an invalid reference.
     *
     * The namespace is also used as a lookup table for references to resource
     * descriptors and the fields within them.
     */
    Gbl_NsLookupCount++;

    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
                ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node));
    if (ACPI_FAILURE (Status))
    {
        if (Status == AE_NOT_FOUND)
        {
            /*
             * We didn't find the name reference by path -- we can qualify this
             * a little better before we print an error message
             */
            if (strlen (Path) == ACPI_NAME_SIZE)
            {
                /* A simple, one-segment ACPI name */

                if (XfObjectExists (Path))
                {
                    /*
                     * There exists such a name, but we couldn't get to it
                     * from this scope
                     */
                    AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
                        Op->Asl.ExternalName);
                }
                else
                {
                    /* The name doesn't exist, period */

                    AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
                        Op, Op->Asl.ExternalName);
                }
            }
            else
            {
                /* Check for a fully qualified path */

                if (Path[0] == AML_ROOT_PREFIX)
                {
                    /* Gave full path, the object does not exist */

                    AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
                        Op->Asl.ExternalName);
                }
                else
                {
                    /*
                     * We can't tell whether it doesn't exist or just
                     * can't be reached.
                     */
                    AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
                        Op->Asl.ExternalName);
                }
            }

            Status = AE_OK;
        }

        return_ACPI_STATUS (Status);
    }

    /* Check for a reference vs. name declaration */

    if (!(OpInfo->Flags & AML_NAMED) &&
        !(OpInfo->Flags & AML_CREATE))
    {
        /* This node has been referenced, mark it for reference check */

        Node->Flags |= ANOBJ_IS_REFERENCED;

#ifdef __UNDER_DEVELOPMENT

        /* Check for an illegal reference */

        XfCheckIllegalReference (Op, Node);
#endif
    }

    /* Attempt to optimize the NamePath */

    OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);

    /*
     * 1) Dereference an alias (A name reference that is an alias)
     *    Aliases are not nested, the alias always points to the final object
     */
    if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
        (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
    {
        /* This node points back to the original PARSEOP_ALIAS */

        NextOp = Node->Op;

        /* The first child is the alias target op */

        NextOp = NextOp->Asl.Child;

        /* That in turn points back to original target alias node */

        if (NextOp->Asl.Node)
        {
            Node = NextOp->Asl.Node;
        }

        /* Else - forward reference to alias, will be resolved later */
    }

    /* 2) Check for a reference to a resource descriptor */

    if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
        (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
    {
        /*
         * This was a reference to a field within a resource descriptor.
         * Extract the associated field offset (either a bit or byte
         * offset depending on the field type) and change the named
         * reference into an integer for AML code generation
         */
        Offset = Node->Value;
        TagBitLength = Node->Length;

        /*
         * If a field is being created, generate the length (in bits) of
         * the field. Note: Opcodes other than CreateXxxField and Index
         * can come through here. For other opcodes, we just need to
         * convert the resource tag reference to an integer offset.
         */
        switch (Op->Asl.Parent->Asl.AmlOpcode)
        {
        case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */
            /*
             * We know the length operand is an integer constant because
             * we know that it contains a reference to a resource
             * descriptor tag.
             */
            FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer;
            break;

        case AML_CREATE_BIT_FIELD_OP:

            FieldBitLength = 1;
            break;

        case AML_CREATE_BYTE_FIELD_OP:
        case AML_INDEX_OP:

            FieldBitLength = 8;
            break;

        case AML_CREATE_WORD_FIELD_OP:

            FieldBitLength = 16;
            break;

        case AML_CREATE_DWORD_FIELD_OP:

            FieldBitLength = 32;
            break;

        case AML_CREATE_QWORD_FIELD_OP:

            FieldBitLength = 64;
            break;

        default:

            FieldBitLength = 0;
            break;
        }

        /* Check the field length against the length of the resource tag */

        if (FieldBitLength)
        {
            if (TagBitLength < FieldBitLength)
            {
                Message = ASL_MSG_TAG_SMALLER;
            }
            else if (TagBitLength > FieldBitLength)
            {
                Message = ASL_MSG_TAG_LARGER;
            }

            if (Message)
            {
                snprintf (MsgBuffer, sizeof(MsgBuffer), "Size mismatch, Tag: %u bit%s, Field: %u bit%s",
                    TagBitLength, (TagBitLength > 1) ? "s" : "",
                    FieldBitLength, (FieldBitLength > 1) ? "s" : "");

                AslError (ASL_WARNING, Message, Op, MsgBuffer);
            }
        }

        /* Convert the BitOffset to a ByteOffset for certain opcodes */

        switch (Op->Asl.Parent->Asl.AmlOpcode)
        {
        case AML_CREATE_BYTE_FIELD_OP:
        case AML_CREATE_WORD_FIELD_OP:
        case AML_CREATE_DWORD_FIELD_OP:
        case AML_CREATE_QWORD_FIELD_OP:
        case AML_INDEX_OP:

            Offset = ACPI_DIV_8 (Offset);
            break;

        default:

            break;
        }

        /* Now convert this node to an integer whose value is the field offset */

        Op->Asl.AmlLength = 0;
        Op->Asl.ParseOpcode = PARSEOP_INTEGER;
        Op->Asl.Value.Integer = (UINT64) Offset;
        Op->Asl.CompileFlags |= NODE_IS_RESOURCE_FIELD;

        OpcGenerateAmlOpcode (Op);
    }

    /* 3) Check for a method invocation */

    else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
                (Node->Type == ACPI_TYPE_METHOD) &&
                (Op->Asl.Parent) &&
                (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD))   ||

                (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
    {
        /*
         * A reference to a method within one of these opcodes is not an
         * invocation of the method, it is simply a reference to the method.
         */
        if ((Op->Asl.Parent) &&
           ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF)      ||
            (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF)    ||
            (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE)))
        {
            return_ACPI_STATUS (AE_OK);
        }
        /*
         * There are two types of method invocation:
         * 1) Invocation with arguments -- the parser recognizes this
         *    as a METHODCALL.
         * 2) Invocation with no arguments --the parser cannot determine that
         *    this is a method invocation, therefore we have to figure it out
         *    here.
         */
        if (Node->Type != ACPI_TYPE_METHOD)
        {
            snprintf (MsgBuffer, sizeof(MsgBuffer), "%s is a %s",
                    Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));

            AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer);
            return_ACPI_STATUS (AE_OK);
        }

        /* Save the method node in the caller's op */

        Op->Asl.Node = Node;
        if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
        {
            return_ACPI_STATUS (AE_OK);
        }

        /*
         * This is a method invocation, with or without arguments.
         * Count the number of arguments, each appears as a child
         * under the parent node
         */
        Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
        UtSetParseOpName (Op);

        PassedArgs = 0;
        NextOp     = Op->Asl.Child;

        while (NextOp)
        {
            PassedArgs++;
            NextOp = NextOp->Asl.Next;
        }

        if (Node->Value != ASL_EXTERNAL_METHOD)
        {
            /*
             * Check the parsed arguments with the number expected by the
             * method declaration itself
             */
            if (PassedArgs != Node->Value)
            {
                snprintf (MsgBuffer, sizeof(MsgBuffer), "%s requires %u", Op->Asl.ExternalName,
                            Node->Value);

                if (PassedArgs < Node->Value)
                {
                    AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer);
                }
                else
                {
                    AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer);
                }
            }
        }
    }

    /* 4) Check for an ASL Field definition */

    else if ((Op->Asl.Parent) &&
            ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD)     ||
             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
    {
        /*
         * Offset checking for fields. If the parent operation region has a
         * constant length (known at compile time), we can check fields
         * defined in that region against the region length. This will catch
         * fields and field units that cannot possibly fit within the region.
         *
         * Note: Index fields do not directly reference an operation region,
         * thus they are not included in this check.
         */
        if (Op == Op->Asl.Parent->Asl.Child)
        {
            /*
             * This is the first child of the field node, which is
             * the name of the region. Get the parse node for the
             * region -- which contains the length of the region.
             */
            OwningOp = Node->Op;
            Op->Asl.Parent->Asl.ExtraValue =
                ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);

            /* Examine the field access width */

            switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
            {
            case AML_FIELD_ACCESS_ANY:
            case AML_FIELD_ACCESS_BYTE:
            case AML_FIELD_ACCESS_BUFFER:
            default:

                MinimumLength = 1;
                break;

            case AML_FIELD_ACCESS_WORD:

                MinimumLength = 2;
                break;

            case AML_FIELD_ACCESS_DWORD:

                MinimumLength = 4;
                break;

            case AML_FIELD_ACCESS_QWORD:

                MinimumLength = 8;
                break;
            }

            /*
             * Is the region at least as big as the access width?
             * Note: DataTableRegions have 0 length
             */
            if (((UINT32) OwningOp->Asl.Value.Integer) &&
                ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
            {
                AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
            }

            /*
             * Check EC/CMOS/SMBUS fields to make sure that the correct
             * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
             */
            SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
            switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
            {
            case ACPI_ADR_SPACE_EC:
            case ACPI_ADR_SPACE_CMOS:
            case ACPI_ADR_SPACE_GPIO:

                if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE)
                {
                    AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
                }
                break;

            case ACPI_ADR_SPACE_SMBUS:
            case ACPI_ADR_SPACE_IPMI:
            case ACPI_ADR_SPACE_GSBUS:

                if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER)
                {
                    AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
                }
                break;

            default:

                /* Nothing to do for other address spaces */

                break;
            }
        }
        else
        {
            /*
             * This is one element of the field list. Check to make sure
             * that it does not go beyond the end of the parent operation region.
             *
             * In the code below:
             *    Op->Asl.Parent->Asl.ExtraValue      - Region Length (bits)
             *    Op->Asl.ExtraValue                  - Field start offset (bits)
             *    Op->Asl.Child->Asl.Value.Integer32  - Field length (bits)
             *    Op->Asl.Child->Asl.ExtraValue       - Field access width (bits)
             */
            if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
            {
                XfCheckFieldRange (Op,
                            Op->Asl.Parent->Asl.ExtraValue,
                            Op->Asl.ExtraValue,
                            (UINT32) Op->Asl.Child->Asl.Value.Integer,
                            Op->Asl.Child->Asl.ExtraValue);
            }
        }
    }

    /* 5) Check for a connection object */
#if 0
    else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
    {
        return_ACPI_STATUS (Status);
    }
#endif

    Op->Asl.Node = Node;
    return_ACPI_STATUS (Status);
}
Example #12
0
ACPI_STATUS
AcpiExPrepCommonFieldObject (
    ACPI_OPERAND_OBJECT     *ObjDesc,
    UINT8                   FieldFlags,
    UINT8                   FieldAttribute,
    UINT32                  FieldBitPosition,
    UINT32                  FieldBitLength)
{
    UINT32                  AccessBitWidth;
    UINT32                  ByteAlignment;
    UINT32                  NearestByteAddress;


    ACPI_FUNCTION_TRACE (ExPrepCommonFieldObject);


    /*
     * Note: the structure being initialized is the
     * ACPI_COMMON_FIELD_INFO;  No structure fields outside of the common
     * area are initialized by this procedure.
     */
    ObjDesc->CommonField.FieldFlags = FieldFlags;
    ObjDesc->CommonField.Attribute  = FieldAttribute;
    ObjDesc->CommonField.BitLength  = FieldBitLength;

    /*
     * Decode the access type so we can compute offsets. The access type gives
     * two pieces of information - the width of each field access and the
     * necessary ByteAlignment (address granularity) of the access.
     *
     * For AnyAcc, the AccessBitWidth is the largest width that is both
     * necessary and possible in an attempt to access the whole field in one
     * I/O operation. However, for AnyAcc, the ByteAlignment is always one
     * byte.
     *
     * For all Buffer Fields, the ByteAlignment is always one byte.
     *
     * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is
     * the same (equivalent) as the ByteAlignment.
     */
    AccessBitWidth = AcpiExDecodeFieldAccess (
        ObjDesc, FieldFlags, &ByteAlignment);
    if (!AccessBitWidth)
    {
        return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
    }

    /* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */

    ObjDesc->CommonField.AccessByteWidth = (UINT8)
        ACPI_DIV_8 (AccessBitWidth);

    /*
     * BaseByteOffset is the address of the start of the field within the
     * region. It is the byte address of the first *datum* (field-width data
     * unit) of the field. (i.e., the first datum that contains at least the
     * first *bit* of the field.)
     *
     * Note: ByteAlignment is always either equal to the AccessBitWidth or 8
     * (Byte access), and it defines the addressing granularity of the parent
     * region or buffer.
     */
    NearestByteAddress =
        ACPI_ROUND_BITS_DOWN_TO_BYTES (FieldBitPosition);
    ObjDesc->CommonField.BaseByteOffset = (UINT32)
        ACPI_ROUND_DOWN (NearestByteAddress, ByteAlignment);

    /*
     * StartFieldBitOffset is the offset of the first bit of the field within
     * a field datum.
     */
    ObjDesc->CommonField.StartFieldBitOffset = (UINT8)
        (FieldBitPosition - ACPI_MUL_8 (ObjDesc->CommonField.BaseByteOffset));

    return_ACPI_STATUS (AE_OK);
}
acpi_status
acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
				 u8 field_flags,
				 u8 field_attribute,
				 u32 field_bit_position, u32 field_bit_length)
{
	u32 access_bit_width;
	u32 byte_alignment;
	u32 nearest_byte_address;

	ACPI_FUNCTION_TRACE(ex_prep_common_field_object);

	/*
	 * Note: the structure being initialized is the
	 * ACPI_COMMON_FIELD_INFO;  No structure fields outside of the common
	 * area are initialized by this procedure.
	 */
	obj_desc->common_field.field_flags = field_flags;
	obj_desc->common_field.attribute = field_attribute;
	obj_desc->common_field.bit_length = field_bit_length;

	/*
	 * Decode the access type so we can compute offsets. The access type gives
	 * two pieces of information - the width of each field access and the
	 * necessary byte_alignment (address granularity) of the access.
	 *
	 * For any_acc, the access_bit_width is the largest width that is both
	 * necessary and possible in an attempt to access the whole field in one
	 * I/O operation. However, for any_acc, the byte_alignment is always one
	 * byte.
	 *
	 * For all Buffer Fields, the byte_alignment is always one byte.
	 *
	 * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is
	 * the same (equivalent) as the byte_alignment.
	 */
	access_bit_width =
	    acpi_ex_decode_field_access(obj_desc, field_flags, &byte_alignment);
	if (!access_bit_width) {
		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
	}

	/* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */

	obj_desc->common_field.access_byte_width = (u8)
	    ACPI_DIV_8(access_bit_width);

	/*
	 * base_byte_offset is the address of the start of the field within the
	 * region. It is the byte address of the first *datum* (field-width data
	 * unit) of the field. (i.e., the first datum that contains at least the
	 * first *bit* of the field.)
	 *
	 * Note: byte_alignment is always either equal to the access_bit_width or 8
	 * (Byte access), and it defines the addressing granularity of the parent
	 * region or buffer.
	 */
	nearest_byte_address =
	    ACPI_ROUND_BITS_DOWN_TO_BYTES(field_bit_position);
	obj_desc->common_field.base_byte_offset = (u32)
	    ACPI_ROUND_DOWN(nearest_byte_address, byte_alignment);

	/*
	 * start_field_bit_offset is the offset of the first bit of the field within
	 * a field datum.
	 */
	obj_desc->common_field.start_field_bit_offset = (u8)
	    (field_bit_position -
	     ACPI_MUL_8(obj_desc->common_field.base_byte_offset));

	return_ACPI_STATUS(AE_OK);
}
Example #14
0
ACPI_STATUS
AnBuildLocalTables (
    ACPI_NEW_TABLE_DESC     *TableList)
{
    UINT32                  TableCount = 0;
    ACPI_PHYSICAL_ADDRESS   DsdtAddress = 0;
    UINT32                  XsdtSize;
    ACPI_NEW_TABLE_DESC     *NextTable;
    UINT32                  NextIndex;
    ACPI_TABLE_FADT         *ExternalFadt = NULL;


    /*
     * Update the table count. For the DSDT, it is not put into the XSDT.
     * For the FADT, this table is already accounted for since we usually
     * install a local FADT.
     */
    NextTable = TableList;
    while (NextTable)
    {
        if (!ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT) &&
            !ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
        {
            TableCount++;
        }

        NextTable = NextTable->Next;
    }

    XsdtSize = BASE_XSDT_SIZE + (TableCount * sizeof (UINT64));

    /* Build an XSDT */

    LocalXSDT = AcpiOsAllocate (XsdtSize);
    if (!LocalXSDT)
    {
        return (AE_NO_MEMORY);
    }

    memset (LocalXSDT, 0, XsdtSize);
    LocalXSDT->TableOffsetEntry[0] = ACPI_PTR_TO_PHYSADDR (&LocalFADT);

    /*
     * Install the user tables. The DSDT must be installed in the FADT.
     * All other tables are installed directly into the XSDT.
     *
     * Note: The tables are loaded in reverse order from the incoming
     * input, which makes it match the command line order.
     */
    NextIndex = BASE_XSDT_TABLES;
    NextTable = TableList;
    while (NextTable)
    {
        /*
         * Incoming DSDT or FADT are special cases. All other tables are
         * just immediately installed into the XSDT.
         */
        if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT))
        {
            if (DsdtAddress)
            {
                printf ("Already found a DSDT, only one allowed\n");
                return (AE_ALREADY_EXISTS);
            }

            /* The incoming user table is a DSDT */

            DsdtAddress = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
        }
        else if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
        {
            ExternalFadt =
                ACPI_CAST_PTR (ACPI_TABLE_FADT, NextTable->Table);
            LocalXSDT->TableOffsetEntry[0] =
                ACPI_PTR_TO_PHYSADDR (NextTable->Table);
        }
        else
        {
            /* Install the table in the XSDT */

            LocalXSDT->TableOffsetEntry[TableCount - NextIndex + 1] =
                ACPI_PTR_TO_PHYSADDR (NextTable->Table);
            NextIndex++;
        }

        NextTable = NextTable->Next;
    }

    /* Build an RSDP. Contains a valid XSDT only, no RSDT */

    memset (&LocalRSDP, 0, sizeof (ACPI_TABLE_RSDP));
    ACPI_MAKE_RSDP_SIG (LocalRSDP.Signature);
    memcpy (LocalRSDP.OemId, "Intel", 6);

    LocalRSDP.Revision = 2;
    LocalRSDP.XsdtPhysicalAddress = ACPI_PTR_TO_PHYSADDR (LocalXSDT);
    LocalRSDP.Length = sizeof (ACPI_TABLE_XSDT);

    /* Set checksums for both XSDT and RSDP */

    AnInitializeTableHeader ((void *) LocalXSDT, ACPI_SIG_XSDT, XsdtSize);

    LocalRSDP.Checksum = 0;
    LocalRSDP.Checksum = (UINT8) -AcpiTbChecksum (
        (void *) &LocalRSDP, ACPI_RSDP_CHECKSUM_LENGTH);

    if (!DsdtAddress)
    {
        return (AE_SUPPORT);
    }

    /*
     * Build an FADT. There are two options for the FADT:
     * 1) Incoming external FADT specified on the command line
     * 2) A fully featured local FADT
     */
    memset (&LocalFADT, 0, sizeof (ACPI_TABLE_FADT));

    if (ExternalFadt)
    {
        /*
         * Use the external FADT, but we must update the DSDT/FACS
         * addresses as well as the checksum
         */
        ExternalFadt->Dsdt = (UINT32) DsdtAddress;
        ExternalFadt->Facs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);

        /*
         * If there room in the FADT for the XDsdt and XFacs 64-bit
         * pointers, use them.
         */
        if (ExternalFadt->Header.Length > ACPI_PTR_DIFF (
            &ExternalFadt->XDsdt, ExternalFadt))
        {
            ExternalFadt->Dsdt = 0;
            ExternalFadt->Facs = 0;
            ExternalFadt->XDsdt = DsdtAddress;
            ExternalFadt->XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
        }

        /* Complete the external FADT with the checksum */

        ExternalFadt->Header.Checksum = 0;
        ExternalFadt->Header.Checksum = (UINT8) -AcpiTbChecksum (
            (void *) ExternalFadt, ExternalFadt->Header.Length);
    }
    else
    {
        /*
         * Build a local FADT so we can test the hardware/event init
         */
        LocalFADT.Header.Revision = 5;

        /* Setup FADT header and DSDT/FACS addresses */

        LocalFADT.Dsdt = 0;
        LocalFADT.Facs = 0;

        LocalFADT.XDsdt = DsdtAddress;
        LocalFADT.XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);

        /* Miscellaneous FADT fields */

        LocalFADT.Gpe0BlockLength = 16;
        LocalFADT.Gpe0Block = 0x00001234;

        LocalFADT.Gpe1BlockLength = 6;
        LocalFADT.Gpe1Block = 0x00005678;
        LocalFADT.Gpe1Base = 96;

        LocalFADT.Pm1EventLength = 4;
        LocalFADT.Pm1aEventBlock = 0x00001aaa;
        LocalFADT.Pm1bEventBlock = 0x00001bbb;

        LocalFADT.Pm1ControlLength = 2;
        LocalFADT.Pm1aControlBlock = 0xB0;

        LocalFADT.PmTimerLength = 4;
        LocalFADT.PmTimerBlock = 0xA0;

        LocalFADT.Pm2ControlBlock = 0xC0;
        LocalFADT.Pm2ControlLength = 1;

        /* Setup one example X-64 field */

        LocalFADT.XPm1bEventBlock.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO;
        LocalFADT.XPm1bEventBlock.Address = LocalFADT.Pm1bEventBlock;
        LocalFADT.XPm1bEventBlock.BitWidth = (UINT8)
            ACPI_MUL_8 (LocalFADT.Pm1EventLength);
    }

    AnInitializeTableHeader ((void *) &LocalFADT,
        ACPI_SIG_FADT, sizeof (ACPI_TABLE_FADT));

    /* Build a FACS */

    memset (&LocalFACS, 0, sizeof (ACPI_TABLE_FACS));
    ACPI_MOVE_NAME (LocalFACS.Signature, ACPI_SIG_FACS);

    LocalFACS.Length = sizeof (ACPI_TABLE_FACS);
    LocalFACS.GlobalLock = 0x11AA0011;
    return (AE_OK);
}
Example #15
0
static void
AcpiTbConvertFadt (
    void)
{
    const char              *Name;
    ACPI_GENERIC_ADDRESS    *Address64;
    UINT32                  Address32;
    UINT8                   Length;
    UINT8                   Flags;
    UINT32                  i;


    /*
     * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which
     * should be zero are indeed zero. This will workaround BIOSs that
     * inadvertently place values in these fields.
     *
     * The ACPI 1.0 reserved fields that will be zeroed are the bytes located
     * at offset 45, 55, 95, and the word located at offset 109, 110.
     *
     * Note: The FADT revision value is unreliable. Only the length can be
     * trusted.
     */
    if (AcpiGbl_FADT.Header.Length <= ACPI_FADT_V2_SIZE)
    {
        AcpiGbl_FADT.PreferredProfile = 0;
        AcpiGbl_FADT.PstateControl = 0;
        AcpiGbl_FADT.CstControl = 0;
        AcpiGbl_FADT.BootFlags = 0;
    }

    /*
     * Now we can update the local FADT length to the length of the
     * current FADT version as defined by the ACPI specification.
     * Thus, we will have a common FADT internally.
     */
    AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT);

    /*
     * Expand the 32-bit DSDT addresses to 64-bit as necessary.
     * Later ACPICA code will always use the X 64-bit field.
     */
    AcpiGbl_FADT.XDsdt = AcpiTbSelectAddress ("DSDT",
        AcpiGbl_FADT.Dsdt, AcpiGbl_FADT.XDsdt);

    /* If Hardware Reduced flag is set, we are all done */

    if (AcpiGbl_ReducedHardware)
    {
        return;
    }

    /* Examine all of the 64-bit extended address fields (X fields) */

    for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
    {
        /*
         * Get the 32-bit and 64-bit addresses, as well as the register
         * length and register name.
         */
        Address32 = *ACPI_ADD_PTR (UINT32,
            &AcpiGbl_FADT, FadtInfoTable[i].Address32);

        Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS,
            &AcpiGbl_FADT, FadtInfoTable[i].Address64);

        Length = *ACPI_ADD_PTR (UINT8,
            &AcpiGbl_FADT, FadtInfoTable[i].Length);

        Name = FadtInfoTable[i].Name;
        Flags = FadtInfoTable[i].Flags;

        /*
         * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
         * generic address structures as necessary. Later code will always use
         * the 64-bit address structures.
         *
         * November 2013:
         * Now always use the 64-bit address if it is valid (non-zero), in
         * accordance with the ACPI specification which states that a 64-bit
         * address supersedes the 32-bit version. This behavior can be
         * overridden by the AcpiGbl_Use32BitFadtAddresses flag.
         *
         * During 64-bit address construction and verification,
         * these cases are handled:
         *
         * Address32 zero, Address64 [don't care]   - Use Address64
         *
         * No override: if AcpiGbl_Use32BitFadtAddresses is FALSE, and:
         * Address32 non-zero, Address64 zero       - Copy/use Address32
         * Address32 non-zero == Address64 non-zero - Use Address64
         * Address32 non-zero != Address64 non-zero - Warning, use Address64
         *
         * Override: if AcpiGbl_Use32BitFadtAddresses is TRUE, and:
         * Address32 non-zero, Address64 zero       - Copy/use Address32
         * Address32 non-zero == Address64 non-zero - Copy/use Address32
         * Address32 non-zero != Address64 non-zero - Warning, copy/use Address32
         *
         * Note: SpaceId is always I/O for 32-bit legacy address fields
         */
        if (Address32)
        {
            if (Address64->Address)
            {
                if (Address64->Address != (UINT64) Address32)
                {
                    /* Address mismatch */

                    ACPI_BIOS_WARNING ((AE_INFO,
                        "32/64X address mismatch in FADT/%s: "
                        "0x%8.8X/0x%8.8X%8.8X, using %u-bit address",
                        Name, Address32,
                        ACPI_FORMAT_UINT64 (Address64->Address),
                        AcpiGbl_Use32BitFadtAddresses ? 32 : 64));
                }

                /*
                 * For each extended field, check for length mismatch
                 * between the legacy length field and the corresponding
                 * 64-bit X length field.
                 * Note: If the legacy length field is > 0xFF bits, ignore
                 * this check. (GPE registers can be larger than the
                 * 64-bit GAS structure can accommodate, 0xFF bits).
                 */
                if ((ACPI_MUL_8 (Length) <= ACPI_UINT8_MAX) &&
                    (Address64->BitWidth != ACPI_MUL_8 (Length)))
                {
                    ACPI_BIOS_WARNING ((AE_INFO,
                        "32/64X length mismatch in FADT/%s: %u/%u",
                        Name, ACPI_MUL_8 (Length), Address64->BitWidth));
                }
            }

            /*
             * Hardware register access code always uses the 64-bit fields.
             * So if the 64-bit field is zero or is to be overridden,
             * initialize it with the 32-bit fields.
             * Note that when the 32-bit address favor is specified, the
             * 64-bit fields are always re-initialized so that
             * AccessSize/BitWidth/BitOffset fields can be correctly
             * configured to the values to trigger a 32-bit compatible
             * access mode in the hardware register access code.
             */
            if (!Address64->Address || AcpiGbl_Use32BitFadtAddresses)
            {
                AcpiTbInitGenericAddress (Address64,
                    ACPI_ADR_SPACE_SYSTEM_IO, Length,
                    (UINT64) Address32, Name, Flags);
            }
        }

        if (FadtInfoTable[i].Flags & ACPI_FADT_REQUIRED)
        {
            /*
             * Field is required (PM1aEvent, PM1aControl).
             * Both the address and length must be non-zero.
             */
            if (!Address64->Address || !Length)
            {
                ACPI_BIOS_ERROR ((AE_INFO,
                    "Required FADT field %s has zero address and/or length: "
                    "0x%8.8X%8.8X/0x%X",
                    Name, ACPI_FORMAT_UINT64 (Address64->Address), Length));
            }
        }
        else if (FadtInfoTable[i].Flags & ACPI_FADT_SEPARATE_LENGTH)
        {
            /*
             * Field is optional (PM2Control, GPE0, GPE1) AND has its own
             * length field. If present, both the address and length must
             * be valid.
             */
            if ((Address64->Address && !Length) ||
                (!Address64->Address && Length))
            {
                ACPI_BIOS_WARNING ((AE_INFO,
                    "Optional FADT field %s has valid %s but zero %s: "
                    "0x%8.8X%8.8X/0x%X", Name,
                    (Length ? "Length" : "Address"),
                    (Length ? "Address": "Length"),
                    ACPI_FORMAT_UINT64 (Address64->Address), Length));
            }
        }
    }
}
Example #16
0
acpi_status
acpi_ex_access_region (
	union acpi_operand_object       *obj_desc,
	u32                             field_datum_byte_offset,
	acpi_integer                    *value,
	u32                             function)
{
	acpi_status                     status;
	union acpi_operand_object       *rgn_desc;
	acpi_physical_address           address;


	ACPI_FUNCTION_TRACE ("ex_access_region");


	/*
	 * Ensure that the region operands are fully evaluated and verify
	 * the validity of the request
	 */
	status = acpi_ex_setup_region (obj_desc, field_datum_byte_offset);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

	/*
	 * The physical address of this field datum is:
	 *
	 * 1) The base of the region, plus
	 * 2) The base offset of the field, plus
	 * 3) The current offset into the field
	 */
	rgn_desc = obj_desc->common_field.region_obj;
	address = rgn_desc->region.address
			 + obj_desc->common_field.base_byte_offset
			 + field_datum_byte_offset;

	if ((function & ACPI_IO_MASK) == ACPI_READ) {
		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
	}
	else {
		ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
	}

	ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
		" Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n",
		acpi_ut_get_region_name (rgn_desc->region.space_id),
		rgn_desc->region.space_id,
		obj_desc->common_field.access_byte_width,
		obj_desc->common_field.base_byte_offset,
		field_datum_byte_offset,
		ACPI_FORMAT_UINT64 (address)));

	/* Invoke the appropriate address_space/op_region handler */

	status = acpi_ev_address_space_dispatch (rgn_desc, function,
			  address, ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value);

	if (ACPI_FAILURE (status)) {
		if (status == AE_NOT_IMPLEMENTED) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
				"Region %s(%X) not implemented\n",
				acpi_ut_get_region_name (rgn_desc->region.space_id),
				rgn_desc->region.space_id));
		}
		else if (status == AE_NOT_EXIST) {
			ACPI_REPORT_ERROR ((
				"Region %s(%X) has no handler\n",
				acpi_ut_get_region_name (rgn_desc->region.space_id),
				rgn_desc->region.space_id));
		}
	}

	return_ACPI_STATUS (status);
}
Example #17
0
ACPI_STATUS
AeBuildLocalTables (
    UINT32                  TableCount,
    AE_TABLE_DESC           *TableList)
{
    ACPI_PHYSICAL_ADDRESS   DsdtAddress = 0;
    UINT32                  XsdtSize;
    AE_TABLE_DESC           *NextTable;
    UINT32                  NextIndex;
    ACPI_TABLE_FADT         *ExternalFadt = NULL;


    /*
     * Update the table count. For the DSDT, it is not put into the XSDT.
     * For the FADT, this table is already accounted for since we usually
     * install a local FADT.
     */
    NextTable = TableList;
    while (NextTable)
    {
        if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT) ||
                ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
        {
            TableCount--;
        }
        NextTable = NextTable->Next;
    }

    XsdtSize = (((TableCount + 1) * sizeof (UINT64)) + sizeof (ACPI_TABLE_HEADER));
    if (AcpiGbl_LoadTestTables)
    {
        XsdtSize += BASE_XSDT_SIZE;
    }

    /* Build an XSDT */

    LocalXSDT = AcpiOsAllocate (XsdtSize);
    if (!LocalXSDT)
    {
        return (AE_NO_MEMORY);
    }

    memset (LocalXSDT, 0, XsdtSize);
    AeInitializeTableHeader ((void *) LocalXSDT, ACPI_SIG_XSDT, XsdtSize);

    LocalXSDT->TableOffsetEntry[0] = ACPI_PTR_TO_PHYSADDR (&LocalFADT);
    NextIndex = 1;

    /*
     * Install the user tables. The DSDT must be installed in the FADT.
     * All other tables are installed directly into the XSDT.
     *
     * Note: The tables are loaded in reverse order from the incoming
     * input, which makes it match the command line order.
     */
    NextTable = TableList;
    while (NextTable)
    {
        /*
         * Incoming DSDT or FADT are special cases. All other tables are
         * just immediately installed into the XSDT.
         */
        if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT))
        {
            if (DsdtAddress)
            {
                printf ("Already found a DSDT, only one allowed\n");
                return (AE_ALREADY_EXISTS);
            }

            /* The incoming user table is a DSDT */

            DsdtAddress = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
            DsdtToInstallOverride = NextTable->Table;
        }
        else if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
        {
            ExternalFadt = ACPI_CAST_PTR (ACPI_TABLE_FADT, NextTable->Table);
            LocalXSDT->TableOffsetEntry[0] = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
        }
        else
        {
            /* Install the table in the XSDT */

            LocalXSDT->TableOffsetEntry[TableCount - NextIndex + 1] =
                ACPI_PTR_TO_PHYSADDR (NextTable->Table);
            NextIndex++;
        }

        NextTable = NextTable->Next;
    }

    /* Install the optional extra local tables */

    if (AcpiGbl_LoadTestTables)
    {
        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&LocalTEST);
        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&LocalBADTABLE);

        /* Install two SSDTs to test multiple table support */

        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Ssdt1Code);
        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Ssdt2Code);

        /* Install the OEM1 table to test LoadTable */

        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Oem1Code);

        /* Install the OEMx table to test LoadTable */

        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&OemxCode);

        /* Install the ECDT table to test _REG */

        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&EcdtCode);

        /* Install two UEFIs to test multiple table support */

        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Uefi1Code);
        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Uefi2Code);
    }

    /* Build an RSDP. Contains a valid XSDT only, no RSDT */

    memset (&LocalRSDP, 0, sizeof (ACPI_TABLE_RSDP));
    ACPI_MAKE_RSDP_SIG (LocalRSDP.Signature);
    memcpy (LocalRSDP.OemId, "Intel", 6);

    LocalRSDP.Revision = 2;
    LocalRSDP.XsdtPhysicalAddress = ACPI_PTR_TO_PHYSADDR (LocalXSDT);
    LocalRSDP.Length = sizeof (ACPI_TABLE_RSDP);

    /* Set checksums for both XSDT and RSDP */

    LocalXSDT->Header.Checksum = 0;
    LocalXSDT->Header.Checksum = (UINT8) -AcpiTbChecksum (
                                     (void *) LocalXSDT, LocalXSDT->Header.Length);

    LocalRSDP.Checksum = 0;
    LocalRSDP.Checksum = (UINT8) -AcpiTbChecksum (
                             (void *) &LocalRSDP, ACPI_RSDP_CHECKSUM_LENGTH);

    if (!DsdtAddress)
    {
        /* Use the local DSDT because incoming table(s) are all SSDT(s) */

        DsdtAddress = ACPI_PTR_TO_PHYSADDR (LocalDsdtCode);
        DsdtToInstallOverride = ACPI_CAST_PTR (ACPI_TABLE_HEADER, LocalDsdtCode);
    }

    /*
     * Build an FADT. There are three options for the FADT:
     * 1) Incoming external FADT specified on the command line
     * 2) A "hardware reduced" local FADT
     * 3) A fully featured local FADT
     */
    memset (&LocalFADT, 0, sizeof (ACPI_TABLE_FADT));

    if (ExternalFadt)
    {
        /*
         * Use the external FADT, but we must update the DSDT/FACS addresses
         * as well as the checksum
         */
        ExternalFadt->Dsdt = (UINT32) DsdtAddress;
        if (!AcpiGbl_ReducedHardware)
        {
            ExternalFadt->Facs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
        }

        /* Is there room in the FADT for the XDsdst and XFacs 64-bit pointers? */

        if (ExternalFadt->Header.Length > ACPI_PTR_DIFF (&ExternalFadt->XDsdt, ExternalFadt))
        {
            ExternalFadt->XDsdt = DsdtAddress;

            if (!AcpiGbl_ReducedHardware)
            {
                ExternalFadt->XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
            }
        }

        /* Complete the FADT with the checksum */

        ExternalFadt->Header.Checksum = 0;
        ExternalFadt->Header.Checksum = (UINT8) -AcpiTbChecksum (
                                            (void *) ExternalFadt, ExternalFadt->Header.Length);
    }
    else if (AcpiGbl_UseHwReducedFadt)
    {
        memcpy (&LocalFADT, HwReducedFadtCode, ACPI_FADT_V5_SIZE);
        LocalFADT.Dsdt = (UINT32) DsdtAddress;
        LocalFADT.XDsdt = DsdtAddress;

        LocalFADT.Header.Checksum = 0;
        LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum (
                                        (void *) &LocalFADT, LocalFADT.Header.Length);
    }
    else
    {
        /*
         * Build a local FADT so we can test the hardware/event init
         */
        LocalFADT.Header.Revision = 5;
        AeInitializeTableHeader ((void *) &LocalFADT, ACPI_SIG_FADT, sizeof (ACPI_TABLE_FADT));

        /* Setup FADT header and DSDT/FACS addresses */

        LocalFADT.Dsdt = 0;
        LocalFADT.Facs = 0;

        LocalFADT.XDsdt = DsdtAddress;
        LocalFADT.XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);

        /* Miscellaneous FADT fields */

        LocalFADT.Gpe0BlockLength = 0x08;
        LocalFADT.Gpe0Block = 0x00001234;

        LocalFADT.Gpe1BlockLength = 0x80;
        LocalFADT.Gpe1Block = 0x00005678;
        LocalFADT.Gpe1Base = 100;

        LocalFADT.Pm1EventLength = 4;
        LocalFADT.Pm1aEventBlock = 0x00001aaa;
        LocalFADT.Pm1bEventBlock = 0x00001bbb;

        LocalFADT.Pm1ControlLength = 2;
        LocalFADT.Pm1aControlBlock = 0xB0;

        LocalFADT.PmTimerLength = 4;
        LocalFADT.PmTimerBlock = 0xA0;

        LocalFADT.Pm2ControlBlock = 0xC0;
        LocalFADT.Pm2ControlLength = 1;

        /* Setup one example X-64 GAS field */

        LocalFADT.XPm1bEventBlock.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO;
        LocalFADT.XPm1bEventBlock.Address = LocalFADT.Pm1bEventBlock;
        LocalFADT.XPm1bEventBlock.BitWidth = (UINT8) ACPI_MUL_8 (LocalFADT.Pm1EventLength);

        /* Complete the FADT with the checksum */

        LocalFADT.Header.Checksum = 0;
        LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum (
                                        (void *) &LocalFADT, LocalFADT.Header.Length);
    }

    /* Build a FACS */

    memset (&LocalFACS, 0, sizeof (ACPI_TABLE_FACS));
    ACPI_MOVE_NAME (LocalFACS.Signature, ACPI_SIG_FACS);

    LocalFACS.Length = sizeof (ACPI_TABLE_FACS);
    LocalFACS.GlobalLock = 0x11AA0011;

    /* Build the optional local tables */

    if (AcpiGbl_LoadTestTables)
    {
        /*
         * Build a fake table [TEST] so that we make sure that the
         * ACPICA core ignores it
         */
        memset (&LocalTEST, 0, sizeof (ACPI_TABLE_HEADER));
        ACPI_MOVE_NAME (LocalTEST.Signature, "TEST");

        LocalTEST.Revision = 1;
        LocalTEST.Length = sizeof (ACPI_TABLE_HEADER);
        LocalTEST.Checksum = (UINT8) -AcpiTbChecksum (
                                 (void *) &LocalTEST, LocalTEST.Length);

        /*
         * Build a fake table with a bad signature [BAD!] so that we make
         * sure that the ACPICA core ignores it
         */
        memset (&LocalBADTABLE, 0, sizeof (ACPI_TABLE_HEADER));
        ACPI_MOVE_NAME (LocalBADTABLE.Signature, "BAD!");

        LocalBADTABLE.Revision = 1;
        LocalBADTABLE.Length = sizeof (ACPI_TABLE_HEADER);
        LocalBADTABLE.Checksum = (UINT8) -AcpiTbChecksum (
                                     (void *) &LocalBADTABLE, LocalBADTABLE.Length);
    }

    return (AE_OK);
}
Example #18
0
void
AcpiDmCheckResourceReference (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status;
    ACPI_PARSE_OBJECT       *BufferNameOp;
    ACPI_PARSE_OBJECT       *IndexOp;
    ACPI_NAMESPACE_NODE     *BufferNode;
    ACPI_NAMESPACE_NODE     *ResourceNode;
    const ACPI_OPCODE_INFO  *OpInfo;
    UINT32                  BitIndex;


    /* We are only interested in the CreateXxxxField opcodes */

    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    if (OpInfo->Type != AML_TYPE_CREATE_FIELD)
    {
        return;
    }

    /* Get the buffer term operand */

    BufferNameOp = AcpiPsGetDepthNext (NULL, Op);

    /* Must be a named buffer, not an arg or local or method call */

    if (BufferNameOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
    {
        return;
    }

    /* Get the Index term, must be an integer constant to convert */

    IndexOp = BufferNameOp->Common.Next;

    /* Major cheat: The Node field is also used for the Tag ptr. Clear it now */

    IndexOp->Common.Node = NULL;

    OpInfo = AcpiPsGetOpcodeInfo (IndexOp->Common.AmlOpcode);
    if (OpInfo->ObjectType != ACPI_TYPE_INTEGER)
    {
        return;
    }

    /* Get the bit offset of the descriptor within the buffer */

    if ((Op->Common.AmlOpcode == AML_CREATE_BIT_FIELD_OP) ||
        (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP))
    {
        /* Index operand is a bit offset */

        BitIndex = (UINT32) IndexOp->Common.Value.Integer;
    }
    else
    {
        /* Index operand is a byte offset, convert to bits */

        BitIndex = (UINT32) ACPI_MUL_8 (IndexOp->Common.Value.Integer);
    }

    /* Lookup the buffer in the namespace */

    Status = AcpiNsLookup (WalkState->ScopeInfo,
                BufferNameOp->Common.Value.String, ACPI_TYPE_BUFFER,
                ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState,
                &BufferNode);
    if (ACPI_FAILURE (Status))
    {
        return;
    }

    /* Validate object type, we must have a buffer */

    if (BufferNode->Type != ACPI_TYPE_BUFFER)
    {
        return;
    }

    /* Find the resource descriptor node corresponding to the index */

    ResourceNode = AcpiDmGetResourceNode (BufferNode, BitIndex);
    if (!ResourceNode)
    {
        return;
    }

    /* Translate the Index to a resource tag pathname */

    AcpiGetTagPathname (IndexOp, BufferNode, ResourceNode, BitIndex);
}
Example #19
0
void
AcpiDbDisplayGpes (
    void)
{
    ACPI_GPE_BLOCK_INFO     *GpeBlock;
    ACPI_GPE_XRUPT_INFO     *GpeXruptInfo;
    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    UINT32                  GpeIndex;
    UINT32                  Block = 0;
    UINT32                  i;
    UINT32                  j;
    char                    Buffer[80];
    ACPI_BUFFER             RetBuf;
    ACPI_STATUS             Status;


    RetBuf.Length = sizeof (Buffer);
    RetBuf.Pointer = Buffer;

    Block = 0;

    /* Walk the GPE lists */

    GpeXruptInfo = AcpiGbl_GpeXruptListHead;
    while (GpeXruptInfo)
    {
        GpeBlock = GpeXruptInfo->GpeBlockListHead;
        while (GpeBlock)
        {
            Status = AcpiGetName (GpeBlock->Node, ACPI_FULL_PATHNAME, &RetBuf);
            if (ACPI_FAILURE (Status))
            {
                AcpiOsPrintf ("Could not convert name to pathname\n");
            }

            AcpiOsPrintf ("\nBlock %d - Info %p  DeviceNode %p [%s]\n",
                Block, GpeBlock, GpeBlock->Node, Buffer);

            AcpiOsPrintf ("    Registers:    %u (%u GPEs)\n",
                GpeBlock->RegisterCount,
                ACPI_MUL_8 (GpeBlock->RegisterCount));

            AcpiOsPrintf ("    GPE range:    0x%X to 0x%X\n",
                GpeBlock->BlockBaseNumber,
                GpeBlock->BlockBaseNumber +
                    (GpeBlock->RegisterCount * 8) -1);

            AcpiOsPrintf (
                "    RegisterInfo: %p  Status %8.8X%8.8X Enable %8.8X%8.8X\n",
                GpeBlock->RegisterInfo,
                ACPI_FORMAT_UINT64 (GpeBlock->RegisterInfo->StatusAddress.Address),
                ACPI_FORMAT_UINT64 (GpeBlock->RegisterInfo->EnableAddress.Address));

            AcpiOsPrintf ("    EventInfo:    %p\n", GpeBlock->EventInfo);

            /* Examine each GPE Register within the block */

            for (i = 0; i < GpeBlock->RegisterCount; i++)
            {
                GpeRegisterInfo = &GpeBlock->RegisterInfo[i];

                AcpiOsPrintf (
                    "    Reg %u:  WakeEnable %2.2X, RunEnable %2.2X  Status %8.8X%8.8X Enable %8.8X%8.8X\n",
                    i, GpeRegisterInfo->EnableForWake,
                    GpeRegisterInfo->EnableForRun,
                    ACPI_FORMAT_UINT64 (GpeRegisterInfo->StatusAddress.Address),
                    ACPI_FORMAT_UINT64 (GpeRegisterInfo->EnableAddress.Address));

                /* Now look at the individual GPEs in this byte register */

                for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
                {
                    GpeIndex = (i * ACPI_GPE_REGISTER_WIDTH) + j;
                    GpeEventInfo = &GpeBlock->EventInfo[GpeIndex];

                    if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK))
                    {
                        /* This GPE is not used (no method or handler) */

                        continue;
                    }

                    AcpiOsPrintf (
                        "        GPE %.3X: %p Flags %2.2X: ",
                        GpeBlock->BlockBaseNumber + GpeIndex,
                        GpeEventInfo,
                        GpeEventInfo->Flags);

                    if (GpeEventInfo->Flags & ACPI_GPE_LEVEL_TRIGGERED)
                    {
                        AcpiOsPrintf ("Level, ");
                    }
                    else
                    {
                        AcpiOsPrintf ("Edge,  ");
                    }

                    switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK)
                    {
                    case ACPI_GPE_TYPE_WAKE:
                        AcpiOsPrintf ("WakeOnly: ");
                        break;
                    case ACPI_GPE_TYPE_RUNTIME:
                        AcpiOsPrintf (" RunOnly: ");
                        break;
                    case ACPI_GPE_TYPE_WAKE_RUN:
                        AcpiOsPrintf (" WakeRun: ");
                        break;
                    default:
                        AcpiOsPrintf (" NotUsed: ");
                        break;
                    }

                    if (GpeEventInfo->Flags & ACPI_GPE_WAKE_ENABLED)
                    {
                        AcpiOsPrintf ("[Wake 1 ");
                    }
                    else
                    {
                        AcpiOsPrintf ("[Wake 0 ");
                    }

                    if (GpeEventInfo->Flags & ACPI_GPE_RUN_ENABLED)
                    {
                        AcpiOsPrintf ("Run 1], ");
                    }
                    else
                    {
                        AcpiOsPrintf ("Run 0], ");
                    }

                    switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
                    {
                    case ACPI_GPE_DISPATCH_NOT_USED:
                        AcpiOsPrintf ("NotUsed");
                        break;
                    case ACPI_GPE_DISPATCH_HANDLER:
                        AcpiOsPrintf ("Handler");
                        break;
                    case ACPI_GPE_DISPATCH_METHOD:
                        AcpiOsPrintf ("Method");
                        break;
                    default:
                        AcpiOsPrintf ("UNKNOWN: %X",
                            GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK);
                        break;
                    }

                    AcpiOsPrintf ("\n");
                }
            }
            Block++;
            GpeBlock = GpeBlock->Next;
        }
        GpeXruptInfo = GpeXruptInfo->Next;
    }
}
Example #20
0
acpi_status
acpi_ex_prep_common_field_object (
	union acpi_operand_object       *obj_desc,
	u8                              field_flags,
	u8                              field_attribute,
	u32                             field_bit_position,
	u32                             field_bit_length)
{
	u32                             access_bit_width;
	u32                             byte_alignment;
	u32                             nearest_byte_address;


	ACPI_FUNCTION_TRACE ("ex_prep_common_field_object");


	/*
	 * Note: the structure being initialized is the
	 * ACPI_COMMON_FIELD_INFO;  No structure fields outside of the common
	 * area are initialized by this procedure.
	 */
	obj_desc->common_field.field_flags = field_flags;
	obj_desc->common_field.attribute = field_attribute;
	obj_desc->common_field.bit_length = field_bit_length;

	/*
	 * Decode the access type so we can compute offsets.  The access type gives
	 * two pieces of information - the width of each field access and the
	 * necessary byte_alignment (address granularity) of the access.
	 *
	 * For any_acc, the access_bit_width is the largest width that is both
	 * necessary and possible in an attempt to access the whole field in one
	 * I/O operation.  However, for any_acc, the byte_alignment is always one
	 * byte.
	 *
	 * For all Buffer Fields, the byte_alignment is always one byte.
	 *
	 * For all other access types (Byte, Word, Dword, Qword), the Bitwidth is
	 * the same (equivalent) as the byte_alignment.
	 */
	access_bit_width = acpi_ex_decode_field_access (obj_desc, field_flags,
			  &byte_alignment);
	if (!access_bit_width) {
		return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
	}

	/* Setup width (access granularity) fields */

	obj_desc->common_field.access_byte_width = (u8)
			ACPI_DIV_8 (access_bit_width); /* 1, 2, 4,  8 */

	/*
	 * base_byte_offset is the address of the start of the field within the
	 * region.  It is the byte address of the first *datum* (field-width data
	 * unit) of the field. (i.e., the first datum that contains at least the
	 * first *bit* of the field.)
	 *
	 * Note: byte_alignment is always either equal to the access_bit_width or 8
	 * (Byte access), and it defines the addressing granularity of the parent
	 * region or buffer.
	 */
	nearest_byte_address =
			ACPI_ROUND_BITS_DOWN_TO_BYTES (field_bit_position);
	obj_desc->common_field.base_byte_offset =
			ACPI_ROUND_DOWN (nearest_byte_address, byte_alignment);

	/*
	 * start_field_bit_offset is the offset of the first bit of the field within
	 * a field datum.
	 */
	obj_desc->common_field.start_field_bit_offset = (u8)
		(field_bit_position - ACPI_MUL_8 (obj_desc->common_field.base_byte_offset));

	/*
	 * Valid bits -- the number of bits that compose a partial datum,
	 * 1) At the end of the field within the region (arbitrary starting bit
	 *    offset)
	 * 2) At the end of a buffer used to contain the field (starting offset
	 *    always zero)
	 */
	obj_desc->common_field.end_field_valid_bits = (u8)
		((obj_desc->common_field.start_field_bit_offset + field_bit_length) %
				  access_bit_width);
	/* start_buffer_bit_offset always = 0 */

	obj_desc->common_field.end_buffer_valid_bits = (u8)
		(field_bit_length % access_bit_width);

	/*
	 * datum_valid_bits is the number of valid field bits in the first
	 * field datum.
	 */
	obj_desc->common_field.datum_valid_bits  = (u8)
		(access_bit_width - obj_desc->common_field.start_field_bit_offset);

	/*
	 * Does the entire field fit within a single field access element? (datum)
	 * (i.e., without crossing a datum boundary)
	 */
	if ((obj_desc->common_field.start_field_bit_offset + field_bit_length) <=
			(u16) access_bit_width) {
		obj_desc->common.flags |= AOPOBJ_SINGLE_DATUM;
	}

	return_ACPI_STATUS (AE_OK);
}
Example #21
0
ACPI_STATUS
AcpiExAccessRegion (
    ACPI_OPERAND_OBJECT     *ObjDesc,
    UINT32                  FieldDatumByteOffset,
    UINT64                  *Value,
    UINT32                  Function)
{
    ACPI_STATUS             Status;
    ACPI_OPERAND_OBJECT     *RgnDesc;
    UINT32                  RegionOffset;


    ACPI_FUNCTION_TRACE (ExAccessRegion);


    /*
     * Ensure that the region operands are fully evaluated and verify
     * the validity of the request
     */
    Status = AcpiExSetupRegion (ObjDesc, FieldDatumByteOffset);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /*
     * The physical address of this field datum is:
     *
     * 1) The base of the region, plus
     * 2) The base offset of the field, plus
     * 3) The current offset into the field
     */
    RgnDesc = ObjDesc->CommonField.RegionObj;
    RegionOffset =
        ObjDesc->CommonField.BaseByteOffset +
        FieldDatumByteOffset;

    if ((Function & ACPI_IO_MASK) == ACPI_READ)
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
    }
    else
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
    }

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
        " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
        AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
        RgnDesc->Region.SpaceId,
        ObjDesc->CommonField.AccessByteWidth,
        ObjDesc->CommonField.BaseByteOffset,
        FieldDatumByteOffset,
        ACPI_FORMAT_UINT64 (RgnDesc->Region.Address + RegionOffset)));

    /* Invoke the appropriate AddressSpace/OpRegion handler */

    Status = AcpiEvAddressSpaceDispatch (RgnDesc, ObjDesc,
        Function, RegionOffset,
        ACPI_MUL_8 (ObjDesc->CommonField.AccessByteWidth), Value);

    if (ACPI_FAILURE (Status))
    {
        if (Status == AE_NOT_IMPLEMENTED)
        {
            ACPI_ERROR ((AE_INFO,
                "Region %s (ID=%u) not implemented",
                AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
                RgnDesc->Region.SpaceId));
        }
        else if (Status == AE_NOT_EXIST)
        {
            ACPI_ERROR ((AE_INFO,
                "Region %s (ID=%u) has no handler",
                AcpiUtGetRegionName (RgnDesc->Region.SpaceId),
                RgnDesc->Region.SpaceId));
        }
    }

    return_ACPI_STATUS (Status);
}
Example #22
0
static void acpi_tb_validate_fadt(void)
{
	char *name;
	struct acpi_generic_address *address64;
	u8 length;
	u32 i;

	/*
	 * Check for FACS and DSDT address mismatches. An address mismatch between
	 * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
	 * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables.
	 */
	if (acpi_gbl_FADT.facs &&
	    (acpi_gbl_FADT.Xfacs != (u64)acpi_gbl_FADT.facs)) {
		ACPI_BIOS_WARNING((AE_INFO,
				   "32/64X FACS address mismatch in FADT - "
				   "0x%8.8X/0x%8.8X%8.8X, using 32",
				   acpi_gbl_FADT.facs,
				   ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xfacs)));

		acpi_gbl_FADT.Xfacs = (u64)acpi_gbl_FADT.facs;
	}

	if (acpi_gbl_FADT.dsdt &&
	    (acpi_gbl_FADT.Xdsdt != (u64)acpi_gbl_FADT.dsdt)) {
		ACPI_BIOS_WARNING((AE_INFO,
				   "32/64X DSDT address mismatch in FADT - "
				   "0x%8.8X/0x%8.8X%8.8X, using 32",
				   acpi_gbl_FADT.dsdt,
				   ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xdsdt)));

		acpi_gbl_FADT.Xdsdt = (u64)acpi_gbl_FADT.dsdt;
	}

	/* If Hardware Reduced flag is set, we are all done */

	if (acpi_gbl_reduced_hardware) {
		return;
	}

	/* Examine all of the 64-bit extended address fields (X fields) */

	for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) {
		/*
		 * Generate pointer to the 64-bit address, get the register
		 * length (width) and the register name
		 */
		address64 = ACPI_ADD_PTR(struct acpi_generic_address,
					 &acpi_gbl_FADT,
					 fadt_info_table[i].address64);
		length =
		    *ACPI_ADD_PTR(u8, &acpi_gbl_FADT,
				  fadt_info_table[i].length);
		name = fadt_info_table[i].name;

		/*
		 * For each extended field, check for length mismatch between the
		 * legacy length field and the corresponding 64-bit X length field.
		 */
		if (address64->address &&
		    (address64->bit_width != ACPI_MUL_8(length))) {
			ACPI_BIOS_WARNING((AE_INFO,
					   "32/64X length mismatch in FADT/%s: %u/%u",
					   name, ACPI_MUL_8(length),
					   address64->bit_width));
		}

		if (fadt_info_table[i].type & ACPI_FADT_REQUIRED) {
			/*
			 * Field is required (Pm1a_event, Pm1a_control, pm_timer).
			 * Both the address and length must be non-zero.
			 */
			if (!address64->address || !length) {
				ACPI_BIOS_ERROR((AE_INFO,
						 "Required FADT field %s has zero address and/or length: "
						 "0x%8.8X%8.8X/0x%X",
						 name,
						 ACPI_FORMAT_UINT64(address64->
								    address),
						 length));
			}
		} else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) {
			/*
			 * Field is optional (Pm2_control, GPE0, GPE1) AND has its own
			 * length field. If present, both the address and length must
			 * be valid.
			 */
			if ((address64->address && !length) ||
			    (!address64->address && length)) {
				ACPI_BIOS_WARNING((AE_INFO,
						   "Optional FADT field %s has zero address or length: "
						   "0x%8.8X%8.8X/0x%X",
						   name,
						   ACPI_FORMAT_UINT64
						   (address64->address),
						   length));
			}
		}
	}
}
Example #23
0
ACPI_STATUS
AeBuildLocalTables (
    UINT32                  TableCount,
    AE_TABLE_DESC           *TableList)
{
    ACPI_PHYSICAL_ADDRESS   DsdtAddress = 0;
    UINT32                  XsdtSize;
    AE_TABLE_DESC           *NextTable;
    UINT32                  NextIndex;
    ACPI_TABLE_FADT         *ExternalFadt = NULL;


    /*
     * Update the table count. For DSDT, it is not put into the XSDT. For
     * FADT, this is already accounted for since we usually install a
     * local FADT.
     */
    NextTable = TableList;
    while (NextTable)
    {
        if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT) ||
            ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
        {
            TableCount--;
        }
        NextTable = NextTable->Next;
    }

    XsdtSize = BASE_XSDT_SIZE + (TableCount * sizeof (UINT64));

    /* Build an XSDT */

    LocalXSDT = AcpiOsAllocate (XsdtSize);
    if (!LocalXSDT)
    {
        return (AE_NO_MEMORY);
    }

    ACPI_MEMSET (LocalXSDT, 0, XsdtSize);
    ACPI_STRNCPY (LocalXSDT->Header.Signature, ACPI_SIG_XSDT, 4);
    LocalXSDT->Header.Length = XsdtSize;
    LocalXSDT->Header.Revision = 1;

    LocalXSDT->TableOffsetEntry[0] = ACPI_PTR_TO_PHYSADDR (&LocalTEST);
    LocalXSDT->TableOffsetEntry[1] = ACPI_PTR_TO_PHYSADDR (&LocalBADTABLE);
    LocalXSDT->TableOffsetEntry[2] = ACPI_PTR_TO_PHYSADDR (&LocalFADT);

    /* Install two SSDTs to test multiple table support */

    LocalXSDT->TableOffsetEntry[3] = ACPI_PTR_TO_PHYSADDR (&Ssdt1Code);
    LocalXSDT->TableOffsetEntry[4] = ACPI_PTR_TO_PHYSADDR (&Ssdt2Code);

    /* Install the OEM1 table to test LoadTable */

    LocalXSDT->TableOffsetEntry[5] = ACPI_PTR_TO_PHYSADDR (&Oem1Code);

    /* Install the OEMx table to test LoadTable */

    LocalXSDT->TableOffsetEntry[6] = ACPI_PTR_TO_PHYSADDR (&OemxCode);

     /* Install the ECDT table to test _REG */

    LocalXSDT->TableOffsetEntry[7] = ACPI_PTR_TO_PHYSADDR (&EcdtCode);

   /*
     * Install the user tables. The DSDT must be installed in the FADT.
     * All other tables are installed directly into the XSDT.
     */
    NextIndex = BASE_XSDT_TABLES;
    NextTable = TableList;
    while (NextTable)
    {
        /*
         * Incoming DSDT or FADT are special cases. All other tables are
         * just immediately installed into the XSDT.
         */
        if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT))
        {
            if (DsdtAddress)
            {
                printf ("Already found a DSDT, only one allowed\n");
                return (AE_ALREADY_EXISTS);
            }

            /* The incoming user table is a DSDT */

            DsdtAddress = ACPI_PTR_TO_PHYSADDR (&DsdtCode);
            DsdtToInstallOverride = NextTable->Table;
        }
        else if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
        {
            ExternalFadt = ACPI_CAST_PTR (ACPI_TABLE_FADT, NextTable->Table);
            LocalXSDT->TableOffsetEntry[2] = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
        }
        else
        {
            /* Install the table in the XSDT */

            LocalXSDT->TableOffsetEntry[NextIndex] = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
            NextIndex++;
        }

        NextTable = NextTable->Next;
    }

    /* Build an RSDP */

    ACPI_MEMSET (&LocalRSDP, 0, sizeof (ACPI_TABLE_RSDP));
    ACPI_MEMCPY (LocalRSDP.Signature, ACPI_SIG_RSDP, 8);
    ACPI_MEMCPY (LocalRSDP.OemId, "I_TEST", 6);
    LocalRSDP.Revision = 2;
    LocalRSDP.XsdtPhysicalAddress = ACPI_PTR_TO_PHYSADDR (LocalXSDT);
    LocalRSDP.Length = sizeof (ACPI_TABLE_XSDT);

    /* Set checksums for both XSDT and RSDP */

    LocalXSDT->Header.Checksum = (UINT8) -AcpiTbChecksum (
        (void *) LocalXSDT, LocalXSDT->Header.Length);
    LocalRSDP.Checksum = (UINT8) -AcpiTbChecksum (
        (void *) &LocalRSDP, ACPI_RSDP_CHECKSUM_LENGTH);

    if (!DsdtAddress)
    {
        /* Use the local DSDT because incoming table(s) are all SSDT(s) */

        DsdtAddress = ACPI_PTR_TO_PHYSADDR (LocalDsdtCode);
        DsdtToInstallOverride = ACPI_CAST_PTR (ACPI_TABLE_HEADER, LocalDsdtCode);
    }

    if (ExternalFadt)
    {
        /*
         * Use the external FADT, but we must update the DSDT/FACS addresses
         * as well as the checksum
         */
        ExternalFadt->Dsdt = DsdtAddress;
        if (!AcpiGbl_ReducedHardware)
        {
            ExternalFadt->Facs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
        }

        if (ExternalFadt->Header.Length > ACPI_PTR_DIFF (&ExternalFadt->XDsdt, ExternalFadt))
        {
            ExternalFadt->XDsdt = DsdtAddress;

            if (!AcpiGbl_ReducedHardware)
            {
                ExternalFadt->XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
            }
        }

        /* Complete the FADT with the checksum */

        ExternalFadt->Header.Checksum = 0;
        ExternalFadt->Header.Checksum = (UINT8) -AcpiTbChecksum (
            (void *) ExternalFadt, ExternalFadt->Header.Length);
    }
    else if (AcpiGbl_UseHwReducedFadt)
    {
        ACPI_MEMCPY (&LocalFADT, HwReducedFadtCode, sizeof (ACPI_TABLE_FADT));
        LocalFADT.Dsdt = DsdtAddress;
        LocalFADT.XDsdt = DsdtAddress;

        LocalFADT.Header.Checksum = 0;
        LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum (
            (void *) &LocalFADT, LocalFADT.Header.Length);
    }
    else
    {
        /*
         * Build a local FADT so we can test the hardware/event init
         */
        ACPI_MEMSET (&LocalFADT, 0, sizeof (ACPI_TABLE_FADT));
        ACPI_STRNCPY (LocalFADT.Header.Signature, ACPI_SIG_FADT, 4);

        /* Setup FADT header and DSDT/FACS addresses */

        LocalFADT.Dsdt = 0;
        LocalFADT.Facs = 0;

        LocalFADT.XDsdt = DsdtAddress;
        LocalFADT.XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);

        LocalFADT.Header.Revision = 3;
        LocalFADT.Header.Length = sizeof (ACPI_TABLE_FADT);

        /* Miscellaneous FADT fields */

        LocalFADT.Gpe0BlockLength = 16;
        LocalFADT.Gpe0Block = 0x00001234;

        LocalFADT.Gpe1BlockLength = 6;
        LocalFADT.Gpe1Block = 0x00005678;
        LocalFADT.Gpe1Base = 96;

        LocalFADT.Pm1EventLength = 4;
        LocalFADT.Pm1aEventBlock = 0x00001aaa;
        LocalFADT.Pm1bEventBlock = 0x00001bbb;

        LocalFADT.Pm1ControlLength = 2;
        LocalFADT.Pm1aControlBlock = 0xB0;

        LocalFADT.PmTimerLength = 4;
        LocalFADT.PmTimerBlock = 0xA0;

        LocalFADT.Pm2ControlBlock = 0xC0;
        LocalFADT.Pm2ControlLength = 1;

        /* Setup one example X-64 field */

        LocalFADT.XPm1bEventBlock.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO;
        LocalFADT.XPm1bEventBlock.Address = LocalFADT.Pm1bEventBlock;
        LocalFADT.XPm1bEventBlock.BitWidth = (UINT8) ACPI_MUL_8 (LocalFADT.Pm1EventLength);

        /* Complete the FADT with the checksum */

        LocalFADT.Header.Checksum = 0;
        LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum (
            (void *) &LocalFADT, LocalFADT.Header.Length);
    }

    /* Build a FACS */

    ACPI_MEMSET (&LocalFACS, 0, sizeof (ACPI_TABLE_FACS));
    ACPI_STRNCPY (LocalFACS.Signature, ACPI_SIG_FACS, 4);

    LocalFACS.Length = sizeof (ACPI_TABLE_FACS);
    LocalFACS.GlobalLock = 0x11AA0011;

    /*
     * Build a fake table [TEST] so that we make sure that the
     * ACPICA core ignores it
     */
    ACPI_MEMSET (&LocalTEST, 0, sizeof (ACPI_TABLE_HEADER));
    ACPI_STRNCPY (LocalTEST.Signature, "TEST", 4);

    LocalTEST.Revision = 1;
    LocalTEST.Length = sizeof (ACPI_TABLE_HEADER);
    LocalTEST.Checksum = (UINT8) -AcpiTbChecksum (
        (void *) &LocalTEST, LocalTEST.Length);

    /*
     * Build a fake table with a bad signature [BAD!] so that we make
     * sure that the ACPICA core ignores it
     */
    ACPI_MEMSET (&LocalBADTABLE, 0, sizeof (ACPI_TABLE_HEADER));
    ACPI_STRNCPY (LocalBADTABLE.Signature, "BAD!", 4);

    LocalBADTABLE.Revision = 1;
    LocalBADTABLE.Length = sizeof (ACPI_TABLE_HEADER);
    LocalBADTABLE.Checksum = (UINT8) -AcpiTbChecksum (
        (void *) &LocalBADTABLE, LocalBADTABLE.Length);

    return (AE_OK);
}