diff options
author | marks <marks@FreeBSD.org> | 2004-07-02 08:38:55 +0000 |
---|---|---|
committer | marks <marks@FreeBSD.org> | 2004-07-02 08:38:55 +0000 |
commit | 5d8d5641262180b8c504204b8fb978a5193958e3 (patch) | |
tree | ceb3bc21daa46f097ac8e3d2ed213cae11175412 /sys | |
parent | 166cdec76ebf5d499bfd0255adb3bfe3555805bd (diff) | |
download | FreeBSD-src-5d8d5641262180b8c504204b8fb978a5193958e3.zip FreeBSD-src-5d8d5641262180b8c504204b8fb978a5193958e3.tar.gz |
Local change: Allow access to the field if it is within the region
size rounded up to a multiple of the access byte width. This overcomes
"off-by-one" programming errors in the AML often found in Toshiba
laptops.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/contrib/dev/acpica/exfldio.c | 154 |
1 files changed, 87 insertions, 67 deletions
diff --git a/sys/contrib/dev/acpica/exfldio.c b/sys/contrib/dev/acpica/exfldio.c index 57a078e..9d60e8d 100644 --- a/sys/contrib/dev/acpica/exfldio.c +++ b/sys/contrib/dev/acpica/exfldio.c @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exfldio - Aml Field I/O - * $Revision: 104 $ + * $Revision: 106 $ * *****************************************************************************/ @@ -865,14 +865,84 @@ AcpiExSetBufferDatum ( /******************************************************************************* * + * FUNCTION: AcpiExCommonBufferSetup + * + * PARAMETERS: ObjDesc - Field object + * BufferLength - Length of caller's buffer + * DatumCount - Where the DatumCount is returned + * + * RETURN: Status, DatumCount + * + * DESCRIPTION: Common code to validate the incoming buffer size and compute + * the number of field "datums" that must be read or written. + * A "datum" is the smallest unit that can be read or written + * to the field, it is either 1,2,4, or 8 bytes. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExCommonBufferSetup ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 BufferLength, + UINT32 *DatumCount) +{ + UINT32 ByteFieldLength; + UINT32 ActualByteFieldLength; + + + ACPI_FUNCTION_TRACE ("ExCommonBufferSetup"); + + + /* + * Incoming buffer must be at least as long as the field, we do not + * allow "partial" field reads/writes. We do not care if the buffer is + * larger than the field, this typically happens when an integer is + * read/written to a field that is actually smaller than an integer. + */ + ByteFieldLength = ACPI_ROUND_BITS_UP_TO_BYTES ( + ObjDesc->CommonField.BitLength); + if (ByteFieldLength > BufferLength) + { + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "Field size %X (bytes) is too large for buffer (%X)\n", + ByteFieldLength, BufferLength)); + + return_ACPI_STATUS (AE_BUFFER_OVERFLOW); + } + + /* + * Create "actual" field byte count (minimum number of bytes that + * must be read), then convert to datum count (minimum number + * of datum-sized units that must be read) + */ + ActualByteFieldLength = ACPI_ROUND_BITS_UP_TO_BYTES ( + ObjDesc->CommonField.StartFieldBitOffset + + ObjDesc->CommonField.BitLength); + + + *DatumCount = ACPI_ROUND_UP_TO (ActualByteFieldLength, + ObjDesc->CommonField.AccessByteWidth); + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "BufferBytes %X, ActualBytes %X, Datums %X, ByteGran %X\n", + ByteFieldLength, ActualByteFieldLength, + *DatumCount, ObjDesc->CommonField.AccessByteWidth)); + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * * FUNCTION: AcpiExExtractFromField * - * PARAMETERS: *ObjDesc - Field to be read - * *Value - Where to store value + * PARAMETERS: ObjDesc - Field to be read + * Buffer - Where to store the field data + * BufferLength - Length of Buffer * * RETURN: Status * - * DESCRIPTION: Retrieve the value of the given field + * DESCRIPTION: Retrieve the current value of the given field * ******************************************************************************/ @@ -888,7 +958,6 @@ AcpiExExtractFromField ( ACPI_INTEGER PreviousRawDatum = 0; ACPI_INTEGER ThisRawDatum = 0; ACPI_INTEGER MergedDatum = 0; - UINT32 ByteFieldLength; UINT32 DatumCount; UINT32 i; @@ -896,41 +965,14 @@ AcpiExExtractFromField ( ACPI_FUNCTION_TRACE ("ExExtractFromField"); - /* - * The field must fit within the caller's buffer - */ - ByteFieldLength = ACPI_ROUND_BITS_UP_TO_BYTES (ObjDesc->CommonField.BitLength); - if (ByteFieldLength > BufferLength) - { - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Field size %X (bytes) too large for buffer (%X)\n", - ByteFieldLength, BufferLength)); - - return_ACPI_STATUS (AE_BUFFER_OVERFLOW); - } - - /* Convert field byte count to datum count, round up if necessary */ - - DatumCount = ACPI_ROUND_UP_TO (ByteFieldLength, - ObjDesc->CommonField.AccessByteWidth); + /* Validate buffer, compute number of datums */ - /* - * If the field is not aligned on a datum boundary and does not - * fit within a single datum, we must read an extra datum. - * - * We could just split the aligned and non-aligned cases since the - * aligned case is so very simple, but this would require more code. - */ - if ((ObjDesc->CommonField.EndFieldValidBits != 0) && - (!(ObjDesc->CommonField.Flags & AOPOBJ_SINGLE_DATUM))) + Status = AcpiExCommonBufferSetup (ObjDesc, BufferLength, &DatumCount); + if (ACPI_FAILURE (Status)) { - DatumCount++; + return_ACPI_STATUS (Status); } - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "ByteLen %X, DatumLen %X, ByteGran %X\n", - ByteFieldLength, DatumCount,ObjDesc->CommonField.AccessByteWidth)); - /* * Clear the caller's buffer (the whole buffer length as given) * This is very important, especially in the cases where the buffer @@ -1052,12 +1094,13 @@ AcpiExExtractFromField ( * * FUNCTION: AcpiExInsertIntoField * - * PARAMETERS: *ObjDesc - Field to be set - * Buffer - Value to store + * PARAMETERS: ObjDesc - Field to be written + * Buffer - Data to be written + * BufferLength - Length of Buffer * * RETURN: Status * - * DESCRIPTION: Store the value into the given field + * DESCRIPTION: Store the Buffer contents into the given field * ******************************************************************************/ @@ -1074,43 +1117,20 @@ AcpiExInsertIntoField ( ACPI_INTEGER MergedDatum; ACPI_INTEGER PreviousRawDatum; ACPI_INTEGER ThisRawDatum; - UINT32 ByteFieldLength; UINT32 DatumCount; ACPI_FUNCTION_TRACE ("ExInsertIntoField"); - /* - * Incoming buffer must be at least as long as the field, we do not - * allow "partial" field writes. We do not care if the buffer is - * larger than the field, this typically happens when an integer is - * written to a field that is actually smaller than an integer. - */ - ByteFieldLength = ACPI_ROUND_BITS_UP_TO_BYTES ( - ObjDesc->CommonField.BitLength); - if (BufferLength < ByteFieldLength) - { - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Buffer length %X too small for field %X\n", - BufferLength, ByteFieldLength)); + /* Validate buffer, compute number of datums */ - return_ACPI_STATUS (AE_BUFFER_OVERFLOW); + Status = AcpiExCommonBufferSetup (ObjDesc, BufferLength, &DatumCount); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); } - ByteFieldLength = ACPI_ROUND_BITS_UP_TO_BYTES ( - ObjDesc->CommonField.StartFieldBitOffset + - ObjDesc->CommonField.BitLength); - - /* Convert byte count to datum count, round up if necessary */ - - DatumCount = ACPI_ROUND_UP_TO (ByteFieldLength, - ObjDesc->CommonField.AccessByteWidth); - - ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, - "Bytes %X, Datums %X, ByteGran %X\n", - ByteFieldLength, DatumCount, ObjDesc->CommonField.AccessByteWidth)); - /* * Break the request into up to three parts (similar to an I/O request): * 1) non-aligned part at start |