aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/nsrepair.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica/nsrepair.c')
-rw-r--r--drivers/acpi/acpica/nsrepair.c114
1 files changed, 86 insertions, 28 deletions
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c
index db2b2a99c3a8..d563f1a564a7 100644
--- a/drivers/acpi/acpica/nsrepair.c
+++ b/drivers/acpi/acpica/nsrepair.c
@@ -44,6 +44,7 @@
44#include <acpi/acpi.h> 44#include <acpi/acpi.h>
45#include "accommon.h" 45#include "accommon.h"
46#include "acnamesp.h" 46#include "acnamesp.h"
47#include "acinterp.h"
47#include "acpredef.h" 48#include "acpredef.h"
48 49
49#define _COMPONENT ACPI_NAMESPACE 50#define _COMPONENT ACPI_NAMESPACE
@@ -76,7 +77,13 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
76 union acpi_operand_object *return_object = *return_object_ptr; 77 union acpi_operand_object *return_object = *return_object_ptr;
77 union acpi_operand_object *new_object; 78 union acpi_operand_object *new_object;
78 acpi_size length; 79 acpi_size length;
80 acpi_status status;
79 81
82 /*
83 * At this point, we know that the type of the returned object was not
84 * one of the expected types for this predefined name. Attempt to
85 * repair the object. Only a limited number of repairs are possible.
86 */
80 switch (return_object->common.type) { 87 switch (return_object->common.type) {
81 case ACPI_TYPE_BUFFER: 88 case ACPI_TYPE_BUFFER:
82 89
@@ -111,43 +118,94 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
111 */ 118 */
112 ACPI_MEMCPY(new_object->string.pointer, 119 ACPI_MEMCPY(new_object->string.pointer,
113 return_object->buffer.pointer, length); 120 return_object->buffer.pointer, length);
121 break;
114 122
115 /* 123 case ACPI_TYPE_INTEGER:
116 * If the original object is a package element, we need to: 124
117 * 1. Set the reference count of the new object to match the 125 /* 1) Does the method/object legally return a buffer? */
118 * reference count of the old object. 126
119 * 2. Decrement the reference count of the original object. 127 if (expected_btypes & ACPI_RTYPE_BUFFER) {
120 */ 128 /*
121 if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 129 * Convert the Integer to a packed-byte buffer. _MAT needs
122 new_object->common.reference_count = 130 * this sometimes, if a read has been performed on a Field
123 return_object->common.reference_count; 131 * object that is less than or equal to the global integer
132 * size (32 or 64 bits).
133 */
134 status =
135 acpi_ex_convert_to_buffer(return_object,
136 &new_object);
137 if (ACPI_FAILURE(status)) {
138 return (status);
139 }
140 }
124 141
125 if (return_object->common.reference_count > 1) { 142 /* 2) Does the method/object legally return a string? */
126 return_object->common.reference_count--; 143
144 else if (expected_btypes & ACPI_RTYPE_STRING) {
145 /*
146 * The only supported Integer-to-String conversion is to convert
147 * an integer of value 0 to a NULL string. The last element of
148 * _BIF and _BIX packages occasionally need this fix.
149 */
150 if (return_object->integer.value != 0) {
151 return (AE_AML_OPERAND_TYPE);
127 } 152 }
128 153
129 ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, 154 /* Allocate a new NULL string object */
130 data->node_flags, 155
131 "Converted Buffer to expected String at index %u", 156 new_object = acpi_ut_create_string_object(0);
132 package_index)); 157 if (!new_object) {
158 return (AE_NO_MEMORY);
159 }
133 } else { 160 } else {
134 ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, 161 return (AE_AML_OPERAND_TYPE);
135 data->node_flags,
136 "Converted Buffer to expected String"));
137 } 162 }
163 break;
138 164
139 /* Delete old object, install the new return object */ 165 default:
140 166
141 acpi_ut_remove_reference(return_object); 167 /* We cannot repair this object */
142 *return_object_ptr = new_object;
143 data->flags |= ACPI_OBJECT_REPAIRED;
144 return (AE_OK);
145 168
146 default: 169 return (AE_AML_OPERAND_TYPE);
147 break; 170 }
171
172 /* Object was successfully repaired */
173
174 /*
175 * If the original object is a package element, we need to:
176 * 1. Set the reference count of the new object to match the
177 * reference count of the old object.
178 * 2. Decrement the reference count of the original object.
179 */
180 if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
181 new_object->common.reference_count =
182 return_object->common.reference_count;
183
184 if (return_object->common.reference_count > 1) {
185 return_object->common.reference_count--;
186 }
187
188 ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
189 "Converted %s to expected %s at index %u",
190 acpi_ut_get_object_type_name
191 (return_object),
192 acpi_ut_get_object_type_name(new_object),
193 package_index));
194 } else {
195 ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
196 "Converted %s to expected %s",
197 acpi_ut_get_object_type_name
198 (return_object),
199 acpi_ut_get_object_type_name
200 (new_object)));
148 } 201 }
149 202
150 return (AE_AML_OPERAND_TYPE); 203 /* Delete old object, install the new return object */
204
205 acpi_ut_remove_reference(return_object);
206 *return_object_ptr = new_object;
207 data->flags |= ACPI_OBJECT_REPAIRED;
208 return (AE_OK);
151} 209}
152 210
153/******************************************************************************* 211/*******************************************************************************
@@ -196,8 +254,8 @@ acpi_ns_repair_package_list(struct acpi_predefined_data *data,
196 *obj_desc_ptr = pkg_obj_desc; 254 *obj_desc_ptr = pkg_obj_desc;
197 data->flags |= ACPI_OBJECT_REPAIRED; 255 data->flags |= ACPI_OBJECT_REPAIRED;
198 256
199 ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, 257 ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
200 "Incorrectly formed Package, attempting repair")); 258 "Repaired Incorrectly formed Package"));
201 259
202 return (AE_OK); 260 return (AE_OK);
203} 261}