Ejemplo n.º 1
0
void
AcpiTbCreateLocalFadt (
    ACPI_TABLE_HEADER       *Table,
    UINT32                  Length)
{

    /*
     * Check if the FADT is larger than the largest table that we expect
     * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue
     * a warning.
     */
    if (Length > sizeof (ACPI_TABLE_FADT))
    {
        ACPI_WARNING ((AE_INFO,
            "FADT (revision %u) is longer than ACPI 2.0 version, truncating length 0x%X to 0x%X",
            Table->Revision, Length, sizeof (ACPI_TABLE_FADT)));
    }

    /* Clear the entire local FADT */

    ACPI_MEMSET (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT));

    /* Copy the original FADT, up to sizeof (ACPI_TABLE_FADT) */

    ACPI_MEMCPY (&AcpiGbl_FADT, Table,
        ACPI_MIN (Length, sizeof (ACPI_TABLE_FADT)));

    /*
     * 1) Convert the local copy of the FADT to the common internal format
     * 2) Validate some of the important values within the FADT
     */
    AcpiTbConvertFadt ();
    AcpiTbValidateFadt ();
}
Ejemplo n.º 2
0
void __init acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
{

	/*
	 * Check if the FADT is larger than the largest table that we expect
	 * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue
	 * a warning.
	 */
	if (length > sizeof(struct acpi_table_fadt)) {
		ACPI_WARNING((AE_INFO,
			      "FADT (revision %u) is longer than ACPI 2.0 version, truncating length 0x%X to 0x%zX",
			      table->revision, (unsigned)length,
			      sizeof(struct acpi_table_fadt)));
	}

	/* Clear the entire local FADT */

	ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt));

	/* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */

	ACPI_MEMCPY(&acpi_gbl_FADT, table,
		    ACPI_MIN(length, sizeof(struct acpi_table_fadt)));

	/*
	 * 1) Convert the local copy of the FADT to the common internal format
	 * 2) Validate some of the important values within the FADT
	 */
	acpi_tb_convert_fadt();
	acpi_tb_validate_fadt();
}
Ejemplo n.º 3
0
void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
{
	
	if (length > sizeof(struct acpi_table_fadt)) {
		ACPI_WARNING((AE_INFO,
			      "FADT (revision %u) is longer than ACPI 2.0 version, "
			      "truncating length 0x%X to 0x%X",
			      table->revision, length,
			      (u32)sizeof(struct acpi_table_fadt)));
	}

	

	ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt));

	

	ACPI_MEMCPY(&acpi_gbl_FADT, table,
		    ACPI_MIN(length, sizeof(struct acpi_table_fadt)));

	

	acpi_tb_convert_fadt();

	

	acpi_tb_validate_fadt();

	

	acpi_tb_setup_fadt_registers();
}
Ejemplo n.º 4
0
void
AcpiTbCreateLocalFadt (
    ACPI_TABLE_HEADER       *Table,
    UINT32                  Length)
{

    /*
     * Check if the FADT is larger than what we know about (ACPI 2.0 version).
     * Truncate the table, but make some noise.
     */
    if (Length > sizeof (ACPI_TABLE_FADT))
    {
        ACPI_WARNING ((AE_INFO,
            "FADT (revision %u) is longer than ACPI 2.0 version, truncating length 0x%X to 0x%zX",
            Table->Revision, Length, sizeof (ACPI_TABLE_FADT)));
    }

    /* Copy the entire FADT locally. Zero first for TbConvertFadt */

    ACPI_MEMSET (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT));

    ACPI_MEMCPY (&AcpiGbl_FADT, Table,
        ACPI_MIN (Length, sizeof (ACPI_TABLE_FADT)));

    /*
     * 1) Convert the local copy of the FADT to the common internal format
     * 2) Validate some of the important values within the FADT
     */
    AcpiTbConvertFadt ();
    AcpiTbValidateFadt ();
}
Ejemplo n.º 5
0
void
AcpiTbCreateLocalFadt (
    ACPI_TABLE_HEADER       *Table,
    UINT32                  Length)
{

    /*
     * Check if the FADT is larger than the largest table that we expect
     * (the ACPI 5.0 version). If so, truncate the table, and issue
     * a warning.
     */
    if (Length > sizeof (ACPI_TABLE_FADT))
    {
        ACPI_BIOS_WARNING ((AE_INFO,
            "FADT (revision %u) is longer than ACPI 5.0 version, "
            "truncating length %u to %u",
            Table->Revision, Length, (UINT32) sizeof (ACPI_TABLE_FADT)));
    }

    /* Clear the entire local FADT */

    ACPI_MEMSET (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT));

    /* Copy the original FADT, up to sizeof (ACPI_TABLE_FADT) */

    ACPI_MEMCPY (&AcpiGbl_FADT, Table,
        ACPI_MIN (Length, sizeof (ACPI_TABLE_FADT)));

    /* Take a copy of the Hardware Reduced flag */

    AcpiGbl_ReducedHardware = FALSE;
    if (AcpiGbl_FADT.Flags & ACPI_FADT_HW_REDUCED)
    {
        AcpiGbl_ReducedHardware = TRUE;
    }

    /* Convert the local copy of the FADT to the common internal format */

    AcpiTbConvertFadt ();

    /* Validate FADT values now, before we make any changes */

    AcpiTbValidateFadt ();

    /* Initialize the global ACPI register structures */

    AcpiTbSetupFadtRegisters ();
}
Ejemplo n.º 6
0
u8
acpi_ut_safe_strncat(char *dest,
		     acpi_size dest_size,
		     char *source, acpi_size max_transfer_length)
{
	acpi_size actual_transfer_length;

	actual_transfer_length = ACPI_MIN(max_transfer_length, strlen(source));

	if ((strlen(dest) + actual_transfer_length) >= dest_size) {
		return (TRUE);
	}

	strncat(dest, source, max_transfer_length);
	return (FALSE);
}
Ejemplo n.º 7
0
void
AcpiTbCreateLocalFadt (
    ACPI_TABLE_HEADER       *Table,
    UINT32                  Length)
{

    /*
     * Check if the FADT is larger than the largest table that we expect
     * (typically the current ACPI specification version). If so, truncate
     * the table, and issue a warning.
     */
    if (Length > sizeof (ACPI_TABLE_FADT))
    {
        ACPI_BIOS_WARNING ((AE_INFO,
            "FADT (revision %u) is longer than %s length, "
            "truncating length %u to %u",
            Table->Revision, ACPI_FADT_CONFORMANCE, Length,
            (UINT32) sizeof (ACPI_TABLE_FADT)));
    }

    /* Clear the entire local FADT */

    memset (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT));

    /* Copy the original FADT, up to sizeof (ACPI_TABLE_FADT) */

    memcpy (&AcpiGbl_FADT, Table,
        ACPI_MIN (Length, sizeof (ACPI_TABLE_FADT)));

    /* Take a copy of the Hardware Reduced flag */

    AcpiGbl_ReducedHardware = FALSE;
    if (AcpiGbl_FADT.Flags & ACPI_FADT_HW_REDUCED)
    {
        AcpiGbl_ReducedHardware = TRUE;
    }

    /* Convert the local copy of the FADT to the common internal format */

    AcpiTbConvertFadt ();

    /* Initialize the global ACPI register structures */

    AcpiTbSetupFadtRegisters ();
}
Ejemplo n.º 8
0
void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
{
	/*
	 * Check if the FADT is larger than the largest table that we expect
	 * (the ACPI 5.0 version). If so, truncate the table, and issue
	 * a warning.
	 */
	/* 기본 테이블 크기보다 크면 2.0 이상이면 경고 출력  */
	if (length > sizeof(struct acpi_table_fadt)) {
		ACPI_BIOS_WARNING((AE_INFO,
				   "FADT (revision %u) is longer than ACPI 5.0 version, "
				   "truncating length %u to %u",
				   table->revision, length,
				   (u32)sizeof(struct acpi_table_fadt)));
	}

	/* Clear the entire local FADT */
	/* acpi_gbl_FADT 테이블 초기화  */
	ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt));

	/* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */
	/* acpi_gbl_FADT에 기본 테이블 크기만큼 복사  */
	ACPI_MEMCPY(&acpi_gbl_FADT, table,
		    ACPI_MIN(length, sizeof(struct acpi_table_fadt)));

	/* Take a copy of the Hardware Reduced flag */

	acpi_gbl_reduced_hardware = FALSE;
	if (acpi_gbl_FADT.flags & ACPI_FADT_HW_REDUCED) {
		acpi_gbl_reduced_hardware = TRUE;
	}

	/* Convert the local copy of the FADT to the common internal format */

	acpi_tb_convert_fadt();

	/* Validate FADT values now, before we make any changes */

	acpi_tb_validate_fadt();

	/* Initialize the global ACPI register structures */

	acpi_tb_setup_fadt_registers();
}
Ejemplo n.º 9
0
BOOLEAN
AcpiUtSafeStrncat (
    char                    *Dest,
    ACPI_SIZE               DestSize,
    char                    *Source,
    ACPI_SIZE               MaxTransferLength)
{
    ACPI_SIZE               ActualTransferLength;


    ActualTransferLength = ACPI_MIN (MaxTransferLength, ACPI_STRLEN (Source));

    if ((ACPI_STRLEN (Dest) + ActualTransferLength) >= DestSize)
    {
        return (TRUE);
    }

    ACPI_STRNCAT (Dest, Source, MaxTransferLength);
    return (FALSE);
}
Ejemplo n.º 10
0
void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
{
	/*
	 * Check if the FADT is larger than the largest table that we expect
	 * (typically the current ACPI specification version). If so, truncate
	 * the table, and issue a warning.
	 */
	if (length > sizeof(struct acpi_table_fadt)) {
		ACPI_BIOS_WARNING((AE_INFO,
				   "FADT (revision %u) is longer than %s length, "
				   "truncating length %u to %u",
				   table->revision, ACPI_FADT_CONFORMANCE,
				   length,
				   (u32)sizeof(struct acpi_table_fadt)));
	}

	/* Clear the entire local FADT */

	memset(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt));

	/* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */

	memcpy(&acpi_gbl_FADT, table,
	       ACPI_MIN(length, sizeof(struct acpi_table_fadt)));

	/* Take a copy of the Hardware Reduced flag */

	acpi_gbl_reduced_hardware = FALSE;
	if (acpi_gbl_FADT.flags & ACPI_FADT_HW_REDUCED) {
		acpi_gbl_reduced_hardware = TRUE;
	}

	/* Convert the local copy of the FADT to the common internal format */

	acpi_tb_convert_fadt();

	/* Initialize the global ACPI register structures */

	acpi_tb_setup_fadt_registers();
}
Ejemplo n.º 11
0
Archivo: tbfadt.c Proyecto: 0day-ci/xen
void __init acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
{

	/*
	 * Check if the FADT is larger than the largest table that we expect
	 * (the ACPI 5.0 version). If so, truncate the table, and issue
	 * a warning.
	 */
	if (length > sizeof(struct acpi_table_fadt)) {
		ACPI_WARNING((AE_INFO,
			      "FADT (revision %u) is longer than ACPI 5.0 version,"
			      " truncating length %u to %zu",
			      table->revision, (unsigned)length,
			      sizeof(struct acpi_table_fadt)));
	}

	/* Clear the entire local FADT */

	ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt));

	/* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */

	ACPI_MEMCPY(&acpi_gbl_FADT, table,
		    ACPI_MIN(length, sizeof(struct acpi_table_fadt)));

	/* Take a copy of the Hardware Reduced flag */

	acpi_gbl_reduced_hardware = FALSE;
	if (acpi_gbl_FADT.flags & ACPI_FADT_HW_REDUCED) {
		acpi_gbl_reduced_hardware = TRUE;
	}

	/*
	 * 1) Convert the local copy of the FADT to the common internal format
	 * 2) Validate some of the important values within the FADT
	 */
	acpi_tb_convert_fadt();
	acpi_tb_validate_fadt();
}
Ejemplo n.º 12
0
void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length)
{
	/*
	 * Check if the FADT is larger than the largest table that we expect
	 * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue
	 * a warning.
	 */
	if (length > sizeof(struct acpi_table_fadt)) {
		ACPI_WARNING((AE_INFO,
			      "FADT (revision %u) is longer than ACPI 2.0 version, "
			      "truncating length %u to %u",
			      table->revision, length,
			      (u32)sizeof(struct acpi_table_fadt)));
	}

	/* Clear the entire local FADT */

	ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt));

	/* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */

	ACPI_MEMCPY(&acpi_gbl_FADT, table,
		    ACPI_MIN(length, sizeof(struct acpi_table_fadt)));

	/* Convert the local copy of the FADT to the common internal format */

	acpi_tb_convert_fadt();

	/* Validate FADT values now, before we make any changes */

	acpi_tb_validate_fadt();

	/* Initialize the global ACPI register structures */

	acpi_tb_setup_fadt_registers();
}
Ejemplo n.º 13
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.
     * Note: This if/else is used to bypass compiler differences with the
     * shift operator
     */
    if (AccessBitWidth == ACPI_INTEGER_BIT_SIZE)
    {
        WidthMask = ACPI_UINT64_MAX;
    }
    else
    {
        WidthMask = ACPI_MASK_BITS_ABOVE (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
        {
Ejemplo n.º 14
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);
}
Ejemplo n.º 15
0
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 {
Ejemplo n.º 16
0
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)) {
		status = acpi_ex_field_datum_io(obj_desc, 0, buffer, ACPI_READ);
		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);
}
Ejemplo n.º 17
0
acpi_status
acpi_ex_insert_into_field (
	union acpi_operand_object       *obj_desc,
	void                            *buffer,
	u32                             buffer_length)
{
	acpi_status                     status;
	acpi_integer                    mask;
	acpi_integer                    merged_datum;
	acpi_integer                    raw_datum = 0;
	u32                             field_offset = 0;
	u32                             buffer_offset = 0;
	u32                             buffer_tail_bits;
	u32                             datum_count;
	u32                             field_datum_count;
	u32                             i;


	ACPI_FUNCTION_TRACE ("ex_insert_into_field");


	/* Validate input buffer */

	if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
			 obj_desc->common_field.bit_length)) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
			"Field size %X (bits) is too large for buffer (%X)\n",
			obj_desc->common_field.bit_length, buffer_length));

		return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
	}

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

	mask = ACPI_MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset);
	datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length,
			  obj_desc->common_field.access_bit_width);
	field_datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length +
			   obj_desc->common_field.start_field_bit_offset,
			   obj_desc->common_field.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)) {
			return_ACPI_STATUS (status);
		}

		/* Start new output datum by merging with previous input datum */

		field_offset += obj_desc->common_field.access_byte_width;
		merged_datum = raw_datum >>
			(obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset);
		mask = ACPI_INTEGER_MAX;

		if (i == datum_count) {
			break;
		}

		/* Get the next input datum from the buffer */

		buffer_offset += obj_desc->common_field.access_byte_width;
		ACPI_MEMCPY (&raw_datum, ((char *) buffer) + buffer_offset,
			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;
	}

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

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

	/* Write the last datum to the field */

	merged_datum &= mask;
	status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset);

	return_ACPI_STATUS (status);
}
Ejemplo n.º 18
0
acpi_status
acpi_ex_extract_from_field (
	union acpi_operand_object       *obj_desc,
	void                            *buffer,
	u32                             buffer_length)
{
	acpi_status                     status;
	acpi_integer                    raw_datum;
	acpi_integer                    merged_datum;
	u32                             field_offset = 0;
	u32                             buffer_offset = 0;
	u32                             buffer_tail_bits;
	u32                             datum_count;
	u32                             field_datum_count;
	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_DEBUG_PRINT ((ACPI_DB_ERROR,
			"Field size %X (bits) is too large for buffer (%X)\n",
			obj_desc->common_field.bit_length, buffer_length));

		return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
	}
	ACPI_MEMSET (buffer, 0, buffer_length);

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

	datum_count = ACPI_ROUND_UP_TO (
			   obj_desc->common_field.bit_length,
			   obj_desc->common_field.access_bit_width);
	field_datum_count = ACPI_ROUND_UP_TO (
			   obj_desc->common_field.bit_length +
			   obj_desc->common_field.start_field_bit_offset,
			   obj_desc->common_field.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 */

		merged_datum |= raw_datum <<
			(obj_desc->common_field.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 % obj_desc->common_field.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);
}
Ejemplo n.º 19
0
acpi_status
acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
			  void *buffer, u32 buffer_length)
{
	acpi_status status;
	acpi_integer mask;
	acpi_integer width_mask;
	acpi_integer merged_datum;
	acpi_integer raw_datum = 0;
	u32 field_offset = 0;
	u32 buffer_offset = 0;
	u32 buffer_tail_bits;
	u32 datum_count;
	u32 field_datum_count;
	u32 i;

	ACPI_FUNCTION_TRACE(ex_insert_into_field);

	/* Validate input buffer */

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

		return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
	}

	/*
	 * Create the bitmasks used for bit insertion.
	 * Note: This if/else is used to bypass compiler differences with the
	 * shift operator
	 */
	if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) {
		width_mask = ACPI_INTEGER_MAX;
	} else {
		width_mask =
		    ACPI_MASK_BITS_ABOVE(obj_desc->common_field.
					 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,
				       obj_desc->common_field.access_bit_width);

	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
					     obj_desc->common_field.
					     start_field_bit_offset,
					     obj_desc->common_field.
					     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)) {
			return_ACPI_STATUS(status);
		}

		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 ((obj_desc->common_field.access_bit_width -
		     obj_desc->common_field.start_field_bit_offset) <
		    ACPI_INTEGER_BIT_SIZE) {
			merged_datum =
			    raw_datum >> (obj_desc->common_field.
					  access_bit_width -
					  obj_desc->common_field.
					  start_field_bit_offset);
		} else {