diff options
author | Bob Moore <robert.moore@intel.com> | 2005-11-17 13:07:00 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2005-12-10 00:27:56 -0500 |
commit | c51a4de85de720670f2fbc592a6f8040af72ad87 (patch) | |
tree | ccaa60c483fcc904abd63d936ff7dc380bf28e7b /drivers/acpi/resources | |
parent | 96db255c8f014ae3497507104e8df809785a619f (diff) | |
download | blackbird-op-linux-c51a4de85de720670f2fbc592a6f8040af72ad87.tar.gz blackbird-op-linux-c51a4de85de720670f2fbc592a6f8040af72ad87.zip |
[ACPI] ACPICA 20051117
Fixed a problem in the AML parser where the method thread
count could be decremented below zero if any errors
occurred during the method parse phase. This should
eliminate AE_AML_METHOD_LIMIT exceptions seen on some
machines. This also fixed a related regression with the
mechanism that detects and corrects methods that cannot
properly handle reentrancy (related to the deployment of
the new OwnerId mechanism.)
Eliminated the pre-parsing of control methods (to detect
errors) during table load. Related to the problem above,
this was causing unwind issues if any errors occurred
during the parse, and it seemed to be overkill. A table
load should not be aborted if there are problems with
any single control method, thus rendering this feature
rather pointless.
Fixed a problem with the new table-driven resource manager
where an internal buffer overflow could occur for small
resource templates.
Implemented a new external interface, acpi_get_vendor_resource()
This interface will find and return a vendor-defined
resource descriptor within a _CRS or _PRS
method via an ACPI 3.0 UUID match. (from Bjorn Helgaas)
Removed the length limit (200) on string objects as
per the upcoming ACPI 3.0A specification. This affects
the following areas of the interpreter: 1) any implicit
conversion of a Buffer to a String, 2) a String object
result of the ASL Concatentate operator, 3) the String
object result of the ASL ToString operator.
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/resources')
-rw-r--r-- | drivers/acpi/resources/rscalc.c | 14 | ||||
-rw-r--r-- | drivers/acpi/resources/rsdump.c | 24 | ||||
-rw-r--r-- | drivers/acpi/resources/rslist.c | 4 | ||||
-rw-r--r-- | drivers/acpi/resources/rsmisc.c | 92 | ||||
-rw-r--r-- | drivers/acpi/resources/rsutils.c | 22 | ||||
-rw-r--r-- | drivers/acpi/resources/rsxface.c | 208 |
6 files changed, 237 insertions, 127 deletions
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index eca7439ee9da..c2c4d9079c6c 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c @@ -300,7 +300,7 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) /* Point to the next object */ resource = - ACPI_PTR_ADD(struct acpi_resource, resource, + ACPI_ADD_PTR(struct acpi_resource, resource, resource->length); } @@ -374,8 +374,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, * Get the number of bits set in the 16-bit IRQ mask */ ACPI_MOVE_16_TO_16(&temp16, buffer); - extra_struct_bytes = - acpi_rs_count_set_bits(temp16) * sizeof(u32); + extra_struct_bytes = acpi_rs_count_set_bits(temp16); break; case ACPI_RESOURCE_NAME_DMA: @@ -383,8 +382,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, * DMA Resource: * Get the number of bits set in the 8-bit DMA mask */ - extra_struct_bytes = - acpi_rs_count_set_bits(*buffer) * sizeof(u32); + extra_struct_bytes = acpi_rs_count_set_bits(*buffer); break; case ACPI_RESOURCE_NAME_VENDOR_SMALL: @@ -399,9 +397,9 @@ acpi_rs_get_list_length(u8 * aml_buffer, case ACPI_RESOURCE_NAME_END_TAG: /* - * End Tag: This is the normal exit + * End Tag: This is the normal exit, add size of end_tag */ - *size_needed = buffer_size; + *size_needed = buffer_size + ACPI_RS_SIZE_MIN; return_ACPI_STATUS(AE_OK); case ACPI_RESOURCE_NAME_VENDOR_LARGE: @@ -466,7 +464,7 @@ acpi_rs_get_list_length(u8 * aml_buffer, temp16 = (u16) (acpi_gbl_resource_struct_sizes[resource_index] + extra_struct_bytes); - buffer_size += (u32) ACPI_ALIGN_RESOURCE_SIZE(temp16); + buffer_size += (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(temp16); /* * Point to the next resource within the stream diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c index f617ca80c5a6..cebd890d3db5 100644 --- a/drivers/acpi/resources/rsdump.c +++ b/drivers/acpi/resources/rsdump.c @@ -383,7 +383,7 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) while (count) { previous_target = target; - target = ((u8 *) resource) + table->offset; + target = ACPI_ADD_PTR(u8, resource, table->offset); name = table->name; switch (table->opcode) { @@ -410,22 +410,19 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) /* Data items, 8/16/32/64 bit */ case ACPI_RSD_UINT8: - acpi_rs_out_integer8(name, *ACPI_CAST_PTR(u8, target)); + acpi_rs_out_integer8(name, ACPI_GET8(target)); break; case ACPI_RSD_UINT16: - acpi_rs_out_integer16(name, - *ACPI_CAST_PTR(u16, target)); + acpi_rs_out_integer16(name, ACPI_GET16(target)); break; case ACPI_RSD_UINT32: - acpi_rs_out_integer32(name, - *ACPI_CAST_PTR(u32, target)); + acpi_rs_out_integer32(name, ACPI_GET32(target)); break; case ACPI_RSD_UINT64: - acpi_rs_out_integer64(name, - *ACPI_CAST_PTR(u64, target)); + acpi_rs_out_integer64(name, ACPI_GET64(target)); break; /* Flags: 1-bit and 2-bit flags supported */ @@ -462,8 +459,8 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table) * Note: The list length is obtained from the previous table entry */ if (previous_target) { - acpi_rs_dump_byte_list(*ACPI_CAST_PTR - (u16, previous_target), + acpi_rs_dump_byte_list(ACPI_GET16 + (previous_target), target); } break; @@ -634,7 +631,7 @@ void acpi_rs_dump_resource_list(struct acpi_resource *resource_list) /* Point to the next resource structure */ resource_list = - ACPI_PTR_ADD(struct acpi_resource, resource_list, + ACPI_ADD_PTR(struct acpi_resource, resource_list, resource_list->length); /* Exit when END_TAG descriptor is reached */ @@ -675,9 +672,8 @@ void acpi_rs_dump_irq_list(u8 * route_table) count); acpi_rs_dump_descriptor(prt_element, acpi_rs_dump_prt); - prt_element = ACPI_CAST_PTR(struct acpi_pci_routing_table, - ((u8 *) prt_element) + - prt_element->length); + prt_element = ACPI_ADD_PTR(struct acpi_pci_routing_table, + prt_element, prt_element->length); } } diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c index b83996233c1d..573c06705641 100644 --- a/drivers/acpi/resources/rslist.c +++ b/drivers/acpi/resources/rslist.c @@ -112,7 +112,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml, u32 aml_length, u8 * output_buffer) /* Point to the next structure in the output buffer */ resource = - ACPI_PTR_ADD(struct acpi_resource, resource, + ACPI_ADD_PTR(struct acpi_resource, resource, resource->length); } @@ -201,7 +201,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, /* Point to the next input resource descriptor */ resource = - ACPI_PTR_ADD(struct acpi_resource, resource, + ACPI_ADD_PTR(struct acpi_resource, resource, resource->length); } diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c index 16ad3bfbee2a..e1b5aa2af9a5 100644 --- a/drivers/acpi/resources/rsmisc.c +++ b/drivers/acpi/resources/rsmisc.c @@ -104,8 +104,9 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, * Source is the external AML byte stream buffer, * destination is the internal resource descriptor */ - source = ((u8 *) aml) + info->aml_offset; - destination = ((u8 *) resource) + info->resource_offset; + source = ACPI_ADD_PTR(void, aml, info->aml_offset); + destination = + ACPI_ADD_PTR(void, resource, info->resource_offset); switch (info->opcode) { case ACPI_RSC_INITGET: @@ -129,22 +130,22 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, /* * Mask and shift the flag bit */ - *((u8 *) destination) = (u8) - ((*((u8 *) source) >> info->value) & 0x01); + ACPI_SET8(destination) = (u8) + ((ACPI_GET8(source) >> info->value) & 0x01); break; case ACPI_RSC_2BITFLAG: /* * Mask and shift the flag bits */ - *((u8 *) destination) = (u8) - ((*((u8 *) source) >> info->value) & 0x03); + ACPI_SET8(destination) = (u8) + ((ACPI_GET8(source) >> info->value) & 0x03); break; case ACPI_RSC_COUNT: - item_count = *((u8 *) source); - *((u8 *) destination) = (u8) item_count; + item_count = ACPI_GET8(source); + ACPI_SET8(destination) = (u8) item_count; resource->length = resource->length + (info->value * (item_count - 1)); @@ -153,7 +154,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, case ACPI_RSC_COUNT16: item_count = aml_resource_length; - *((u16 *) destination) = item_count; + ACPI_SET16(destination) = item_count; resource->length = resource->length + (info->value * (item_count - 1)); @@ -186,9 +187,8 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, case ACPI_RSC_DATA8: - target = ((char *)resource) + info->value; - ACPI_MEMCPY(destination, source, - *(ACPI_CAST_PTR(u16, target))); + target = ACPI_ADD_PTR(char, resource, info->value); + ACPI_MEMCPY(destination, source, ACPI_GET16(target)); break; case ACPI_RSC_ADDRESS: @@ -217,8 +217,8 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, * complicated case used by the Interrupt() macro */ target = - ((char *)resource) + info->aml_offset + - (item_count * 4); + ACPI_ADD_PTR(char, resource, + info->aml_offset + (item_count * 4)); resource->length += acpi_rs_get_resource_source(aml_resource_length, @@ -230,15 +230,14 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, * 8-bit encoded bitmask (DMA macro) */ item_count = - acpi_rs_decode_bitmask(*((u8 *) source), + acpi_rs_decode_bitmask(ACPI_GET8(source), destination); if (item_count) { - resource->length += - resource->length + (item_count - 1); + resource->length += (item_count - 1); } - target = ((char *)resource) + info->value; - *((u8 *) target) = (u8) item_count; + target = ACPI_ADD_PTR(char, resource, info->value); + ACPI_SET8(target) = (u8) item_count; break; case ACPI_RSC_BITMASK16: @@ -250,12 +249,11 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, item_count = acpi_rs_decode_bitmask(temp16, destination); if (item_count) { - resource->length = - resource->length + (item_count - 1); + resource->length += (item_count - 1); } - target = ((char *)resource) + info->value; - *((u8 *) target) = (u8) item_count; + target = ACPI_ADD_PTR(char, resource, info->value); + ACPI_SET8(target) = (u8) item_count; break; case ACPI_RSC_EXIT_NE: @@ -270,7 +268,7 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, break; case ACPI_RSC_COMPARE_VALUE: - if (*((u8 *) source) != info->value) { + if (ACPI_GET8(source) != info->value) { goto exit; } break; @@ -349,8 +347,8 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, * Source is the internal resource descriptor, * destination is the external AML byte stream buffer */ - source = ((u8 *) resource) + info->resource_offset; - destination = ((u8 *) aml) + info->aml_offset; + source = ACPI_ADD_PTR(void, resource, info->resource_offset); + destination = ACPI_ADD_PTR(void, aml, info->aml_offset); switch (info->opcode) { case ACPI_RSC_INITSET: @@ -368,37 +366,38 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* * Clear the flag byte */ - *((u8 *) destination) = 0; + ACPI_SET8(destination) = 0; break; case ACPI_RSC_1BITFLAG: /* * Mask and shift the flag bit */ - *((u8 *) destination) |= (u8) - ((*((u8 *) source) & 0x01) << info->value); + ACPI_SET8(destination) |= (u8) + ((ACPI_GET8(source) & 0x01) << info->value); break; case ACPI_RSC_2BITFLAG: /* * Mask and shift the flag bits */ - *((u8 *) destination) |= (u8) - ((*((u8 *) source) & 0x03) << info->value); + ACPI_SET8(destination) |= (u8) + ((ACPI_GET8(source) & 0x03) << info->value); break; case ACPI_RSC_COUNT: - item_count = *((u8 *) source); - *((u8 *) destination) = (u8) item_count; + item_count = ACPI_GET8(source); + ACPI_SET8(destination) = (u8) item_count; - aml_length = (u16) (aml_length + - (info->value * (item_count - 1))); + aml_length = + (u16) (aml_length + + (info->value * (item_count - 1))); break; case ACPI_RSC_COUNT16: - item_count = *((u16 *) source); + item_count = ACPI_GET16(source); aml_length = (u16) (aml_length + item_count); acpi_rs_set_resource_length(aml_length, aml); break; @@ -453,20 +452,21 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* * 8-bit encoded bitmask (DMA macro) */ - *((u8 *) destination) = (u8) + ACPI_SET8(destination) = (u8) acpi_rs_encode_bitmask(source, - *(((u8 *) resource) + - info->value)); + *ACPI_ADD_PTR(u8, resource, + info->value)); break; case ACPI_RSC_BITMASK16: /* * 16-bit encoded bitmask (IRQ macro) */ - temp16 = - acpi_rs_encode_bitmask(source, - *(((u8 *) resource) + - info->value)); + temp16 = acpi_rs_encode_bitmask(source, + *ACPI_ADD_PTR(u8, + resource, + info-> + value)); ACPI_MOVE_16_TO_16(destination, &temp16); break; @@ -485,9 +485,9 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, */ switch (COMPARE_OPCODE(info)) { case ACPI_RSC_COMPARE_VALUE: - if (* - ((u8 *) (((u8 *) resource) + - COMPARE_TARGET(info))) != + + if (*ACPI_ADD_PTR(u8, resource, + COMPARE_TARGET(info)) != COMPARE_VALUE(info)) { goto exit; } diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index a1eac0f1df54..2236a0c90daa 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c @@ -152,18 +152,18 @@ acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) * misaligned memory transfers */ case ACPI_RSC_MOVE16: - ACPI_MOVE_16_TO_16(&((u16 *) destination)[i], - &((u16 *) source)[i]); + ACPI_MOVE_16_TO_16(&ACPI_CAST_PTR(u16, destination)[i], + &ACPI_CAST_PTR(u16, source)[i]); break; case ACPI_RSC_MOVE32: - ACPI_MOVE_32_TO_32(&((u32 *) destination)[i], - &((u32 *) source)[i]); + ACPI_MOVE_32_TO_32(&ACPI_CAST_PTR(u32, destination)[i], + &ACPI_CAST_PTR(u32, source)[i]); break; case ACPI_RSC_MOVE64: - ACPI_MOVE_64_TO_64(&((u64 *) destination)[i], - &((u64 *) source)[i]); + ACPI_MOVE_64_TO_64(&ACPI_CAST_PTR(u64, destination)[i], + &ACPI_CAST_PTR(u64, source)[i]); break; default: @@ -318,7 +318,7 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length, total_length = resource_length + sizeof(struct aml_resource_large_header); - aml_resource_source = ((u8 *) aml) + minimum_length; + aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length); /* * resource_source is present if the length of the descriptor is longer than @@ -338,9 +338,9 @@ acpi_rs_get_resource_source(acpi_rs_length resource_length, * String destination pointer is not specified; Set the String * pointer to the end of the current resource_source structure. */ - resource_source->string_ptr = (char *) - ((u8 *) resource_source) + - sizeof(struct acpi_resource_source); + resource_source->string_ptr = + ACPI_ADD_PTR(char, resource_source, + sizeof(struct acpi_resource_source)); } /* @@ -407,7 +407,7 @@ acpi_rs_set_resource_source(union aml_resource * aml, if (resource_source->string_length) { /* Point to the end of the AML descriptor */ - aml_resource_source = ((u8 *) aml) + minimum_length; + aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length); /* Copy the resource_source_index */ diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c index 09d250ab9872..50a956b705b0 100644 --- a/drivers/acpi/resources/rsxface.c +++ b/drivers/acpi/resources/rsxface.c @@ -64,6 +64,10 @@ ACPI_MODULE_NAME("rsxface") ACPI_COPY_FIELD(out, in, translation_offset); \ ACPI_COPY_FIELD(out, in, address_length); \ ACPI_COPY_FIELD(out, in, resource_source); +/* Local prototypes */ +static acpi_status +acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context); + /******************************************************************************* * * FUNCTION: acpi_get_irq_routing_table @@ -86,6 +90,7 @@ ACPI_MODULE_NAME("rsxface") * the object indicated by the passed device_handle. * ******************************************************************************/ + acpi_status acpi_get_irq_routing_table(acpi_handle device_handle, struct acpi_buffer *ret_buffer) @@ -222,12 +227,12 @@ EXPORT_SYMBOL(acpi_get_possible_resources); * * FUNCTION: acpi_walk_resources * - * PARAMETERS: device_handle - a handle to the device object for the + * PARAMETERS: device_handle - Handle to the device object for the * device we are querying - * Path - method name of the resources we want + * Name - Method name of the resources we want * (METHOD_NAME__CRS or METHOD_NAME__PRS) - * user_function - called for each resource - * Context - passed to user_function + * user_function - Called for each resource + * Context - Passed to user_function * * RETURN: Status * @@ -239,79 +244,74 @@ EXPORT_SYMBOL(acpi_get_possible_resources); acpi_status acpi_walk_resources(acpi_handle device_handle, - char *path, + char *name, ACPI_WALK_RESOURCE_CALLBACK user_function, void *context) { acpi_status status; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer buffer; struct acpi_resource *resource; - struct acpi_resource *buffer_end; + struct acpi_resource *resource_end; ACPI_FUNCTION_TRACE("acpi_walk_resources"); - if (!device_handle || - (ACPI_STRNCMP(path, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) && - ACPI_STRNCMP(path, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) { + /* Parameter validation */ + + if (!device_handle || !user_function || !name || + (ACPI_STRNCMP(name, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) && + ACPI_STRNCMP(name, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) { return_ACPI_STATUS(AE_BAD_PARAMETER); } - status = acpi_rs_get_method_data(device_handle, path, &buffer); + /* Get the _CRS or _PRS resource list */ + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_rs_get_method_data(device_handle, name, &buffer); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - /* Setup pointers */ + /* Buffer now contains the resource list */ - resource = (struct acpi_resource *)buffer.pointer; - buffer_end = ACPI_CAST_PTR(struct acpi_resource, - ((u8 *) buffer.pointer + buffer.length)); + resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer); + resource_end = + ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length); - /* Walk the resource list */ + /* Walk the resource list until the end_tag is found (or buffer end) */ - for (;;) { - if (!resource || resource->type == ACPI_RESOURCE_TYPE_END_TAG) { + while (resource < resource_end) { + /* Sanity check the resource */ + + if (resource->type > ACPI_RESOURCE_TYPE_MAX) { + status = AE_AML_INVALID_RESOURCE_TYPE; break; } - status = user_function(resource, context); - - switch (status) { - case AE_OK: - case AE_CTRL_DEPTH: + /* Invoke the user function, abort on any error returned */ - /* Just keep going */ + status = user_function(resource, context); + if (ACPI_FAILURE(status)) { + if (status == AE_CTRL_TERMINATE) { + /* This is an OK termination by the user function */ - status = AE_OK; + status = AE_OK; + } break; + } - case AE_CTRL_TERMINATE: - - /* Exit now, with OK stats */ - - status = AE_OK; - goto cleanup; - - default: - - /* All others are valid exceptions */ + /* end_tag indicates end-of-list */ - goto cleanup; + if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { + break; } /* Get the next resource descriptor */ - resource = ACPI_NEXT_RESOURCE(resource); - - /* Check for end-of-buffer */ - - if (resource >= buffer_end) { - goto cleanup; - } + resource = + ACPI_ADD_PTR(struct acpi_resource, resource, + resource->length); } - cleanup: - - acpi_os_free(buffer.pointer); + ACPI_MEM_FREE(buffer.pointer); return_ACPI_STATUS(status); } @@ -381,6 +381,12 @@ acpi_resource_to_address64(struct acpi_resource *resource, struct acpi_resource_address16 *address16; struct acpi_resource_address32 *address32; + if (!resource || !out) { + return (AE_BAD_PARAMETER); + } + + /* Convert 16 or 32 address descriptor to 64 */ + switch (resource->type) { case ACPI_RESOURCE_TYPE_ADDRESS16: @@ -410,3 +416,113 @@ acpi_resource_to_address64(struct acpi_resource *resource, } EXPORT_SYMBOL(acpi_resource_to_address64); + +/******************************************************************************* + * + * FUNCTION: acpi_get_vendor_resource + * + * PARAMETERS: device_handle - Handle for the parent device object + * Name - Method name for the parent resource + * (METHOD_NAME__CRS or METHOD_NAME__PRS) + * Uuid - Pointer to the UUID to be matched. + * includes both subtype and 16-byte UUID + * ret_buffer - Where the vendor resource is returned + * + * RETURN: Status + * + * DESCRIPTION: Walk a resource template for the specified evice to find a + * vendor-defined resource that matches the supplied UUID and + * UUID subtype. Returns a struct acpi_resource of type Vendor. + * + ******************************************************************************/ + +acpi_status +acpi_get_vendor_resource(acpi_handle device_handle, + char *name, + struct acpi_vendor_uuid * uuid, + struct acpi_buffer * ret_buffer) +{ + struct acpi_vendor_walk_info info; + acpi_status status; + + /* Other parameters are validated by acpi_walk_resources */ + + if (!uuid || !ret_buffer) { + return (AE_BAD_PARAMETER); + } + + info.uuid = uuid; + info.buffer = ret_buffer; + info.status = AE_NOT_EXIST; + + /* Walk the _CRS or _PRS resource list for this device */ + + status = + acpi_walk_resources(device_handle, name, + acpi_rs_match_vendor_resource, &info); + if (ACPI_FAILURE(status)) { + return (status); + } + + return (info.status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_match_vendor_resource + * + * PARAMETERS: ACPI_WALK_RESOURCE_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID + * + ******************************************************************************/ + +static acpi_status +acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context) +{ + struct acpi_vendor_walk_info *info = context; + struct acpi_resource_vendor_typed *vendor; + struct acpi_buffer *buffer; + acpi_status status; + + /* Ignore all descriptors except Vendor */ + + if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) { + return (AE_OK); + } + + vendor = &resource->data.vendor_typed; + + /* + * For a valid match, these conditions must hold: + * + * 1) Length of descriptor data must be at least as long as a UUID struct + * 2) The UUID subtypes must match + * 3) The UUID data must match + */ + if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) || + (vendor->uuid_subtype != info->uuid->subtype) || + (ACPI_MEMCMP(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) { + return (AE_OK); + } + + /* Validate/Allocate/Clear caller buffer */ + + buffer = info->buffer; + status = acpi_ut_initialize_buffer(buffer, resource->length); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Found the correct resource, copy and return it */ + + ACPI_MEMCPY(buffer->pointer, resource, resource->length); + buffer->length = resource->length; + + /* Found the desired descriptor, terminate resource walk */ + + info->status = AE_OK; + return (AE_CTRL_TERMINATE); +} |