summaryrefslogtreecommitdiffstats
path: root/sys/contrib/dev/acpica
diff options
context:
space:
mode:
authormarks <marks@FreeBSD.org>2004-07-02 08:38:55 +0000
committermarks <marks@FreeBSD.org>2004-07-02 08:38:55 +0000
commit5d8d5641262180b8c504204b8fb978a5193958e3 (patch)
treeceb3bc21daa46f097ac8e3d2ed213cae11175412 /sys/contrib/dev/acpica
parent166cdec76ebf5d499bfd0255adb3bfe3555805bd (diff)
downloadFreeBSD-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/contrib/dev/acpica')
-rw-r--r--sys/contrib/dev/acpica/exfldio.c154
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
OpenPOWER on IntegriCloud