aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/nsxfname.c
diff options
context:
space:
mode:
authorLin Ming <ming.m.lin@intel.com>2009-05-20 22:42:09 -0400
committerLen Brown <len.brown@intel.com>2009-05-27 00:35:51 -0400
commitb2f7ddcfcb9c2436896cb339a7ff70245648f033 (patch)
treeefd130b46b0dff8855e11d63612532dc60d635dc /drivers/acpi/acpica/nsxfname.c
parente0be6f5a9863b626c19f0be04946c6285cc9db56 (diff)
ACPICA: New: AcpiInstallMethod - install a single control method
This interface enables the override or creation of a single control method. Useful to repair a bug or install a missing method. Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/nsxfname.c')
-rw-r--r--drivers/acpi/acpica/nsxfname.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
index 9589fea24997..f23593d6add4 100644
--- a/drivers/acpi/acpica/nsxfname.c
+++ b/drivers/acpi/acpica/nsxfname.c
@@ -45,6 +45,8 @@
45#include <acpi/acpi.h> 45#include <acpi/acpi.h>
46#include "accommon.h" 46#include "accommon.h"
47#include "acnamesp.h" 47#include "acnamesp.h"
48#include "acparser.h"
49#include "amlcode.h"
48 50
49#define _COMPONENT ACPI_NAMESPACE 51#define _COMPONENT ACPI_NAMESPACE
50ACPI_MODULE_NAME("nsxfname") 52ACPI_MODULE_NAME("nsxfname")
@@ -358,3 +360,151 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
358} 360}
359 361
360ACPI_EXPORT_SYMBOL(acpi_get_object_info) 362ACPI_EXPORT_SYMBOL(acpi_get_object_info)
363
364/******************************************************************************
365 *
366 * FUNCTION: acpi_install_method
367 *
368 * PARAMETERS: Buffer - An ACPI table containing one control method
369 *
370 * RETURN: Status
371 *
372 * DESCRIPTION: Install a control method into the namespace. If the method
373 * name already exists in the namespace, it is overwritten. The
374 * input buffer must contain a valid DSDT or SSDT containing a
375 * single control method.
376 *
377 ******************************************************************************/
378acpi_status acpi_install_method(u8 *buffer)
379{
380 struct acpi_table_header *table =
381 ACPI_CAST_PTR(struct acpi_table_header, buffer);
382 u8 *aml_buffer;
383 u8 *aml_start;
384 char *path;
385 struct acpi_namespace_node *node;
386 union acpi_operand_object *method_obj;
387 struct acpi_parse_state parser_state;
388 u32 aml_length;
389 u16 opcode;
390 u8 method_flags;
391 acpi_status status;
392
393 /* Parameter validation */
394
395 if (!buffer) {
396 return AE_BAD_PARAMETER;
397 }
398
399 /* Table must be a DSDT or SSDT */
400
401 if (!ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) &&
402 !ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) {
403 return AE_BAD_HEADER;
404 }
405
406 /* First AML opcode in the table must be a control method */
407
408 parser_state.aml = buffer + sizeof(struct acpi_table_header);
409 opcode = acpi_ps_peek_opcode(&parser_state);
410 if (opcode != AML_METHOD_OP) {
411 return AE_BAD_PARAMETER;
412 }
413
414 /* Extract method information from the raw AML */
415
416 parser_state.aml += acpi_ps_get_opcode_size(opcode);
417 parser_state.pkg_end = acpi_ps_get_next_package_end(&parser_state);
418 path = acpi_ps_get_next_namestring(&parser_state);
419 method_flags = *parser_state.aml++;
420 aml_start = parser_state.aml;
421 aml_length = ACPI_PTR_DIFF(parser_state.pkg_end, aml_start);
422
423 /*
424 * Allocate resources up-front. We don't want to have to delete a new
425 * node from the namespace if we cannot allocate memory.
426 */
427 aml_buffer = ACPI_ALLOCATE(aml_length);
428 if (!aml_buffer) {
429 return AE_NO_MEMORY;
430 }
431
432 method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
433 if (!method_obj) {
434 ACPI_FREE(aml_buffer);
435 return AE_NO_MEMORY;
436 }
437
438 /* Lock namespace for acpi_ns_lookup, we may be creating a new node */
439
440 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
441 if (ACPI_FAILURE(status)) {
442 goto error_exit;
443 }
444
445 /* The lookup either returns an existing node or creates a new one */
446
447 status =
448 acpi_ns_lookup(NULL, path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
449 ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND,
450 NULL, &node);
451
452 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
453
454 if (ACPI_FAILURE(status)) { /* ns_lookup */
455 if (status != AE_ALREADY_EXISTS) {
456 goto error_exit;
457 }
458
459 /* Node existed previously, make sure it is a method node */
460
461 if (node->type != ACPI_TYPE_METHOD) {
462 status = AE_TYPE;
463 goto error_exit;
464 }
465 }
466
467 /* Copy the method AML to the local buffer */
468
469 ACPI_MEMCPY(aml_buffer, aml_start, aml_length);
470
471 /* Initialize the method object with the new method's information */
472
473 method_obj->method.aml_start = aml_buffer;
474 method_obj->method.aml_length = aml_length;
475
476 method_obj->method.param_count = (u8)
477 (method_flags & AML_METHOD_ARG_COUNT);
478
479 method_obj->method.method_flags = (u8)
480 (method_flags & ~AML_METHOD_ARG_COUNT);
481
482 if (method_flags & AML_METHOD_SERIALIZED) {
483 method_obj->method.sync_level = (u8)
484 ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
485 }
486
487 /*
488 * Now that it is complete, we can attach the new method object to
489 * the method Node (detaches/deletes any existing object)
490 */
491 status = acpi_ns_attach_object(node, method_obj, ACPI_TYPE_METHOD);
492
493 /*
494 * Flag indicates AML buffer is dynamic, must be deleted later.
495 * Must be set only after attach above.
496 */
497 node->flags |= ANOBJ_ALLOCATED_BUFFER;
498
499 /* Remove local reference to the method object */
500
501 acpi_ut_remove_reference(method_obj);
502 return status;
503
504error_exit:
505
506 ACPI_FREE(aml_buffer);
507 ACPI_FREE(method_obj);
508 return status;
509}
510ACPI_EXPORT_SYMBOL(acpi_install_method)