aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/executer/exoparg3.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/executer/exoparg3.c')
-rw-r--r--drivers/acpi/executer/exoparg3.c63
1 files changed, 46 insertions, 17 deletions
diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c
index 23b068adbf5..197890f443b 100644
--- a/drivers/acpi/executer/exoparg3.c
+++ b/drivers/acpi/executer/exoparg3.c
@@ -160,7 +160,7 @@ acpi_ex_opcode_3A_1T_1R (
160{ 160{
161 union acpi_operand_object **operand = &walk_state->operands[0]; 161 union acpi_operand_object **operand = &walk_state->operands[0];
162 union acpi_operand_object *return_desc = NULL; 162 union acpi_operand_object *return_desc = NULL;
163 char *buffer; 163 char *buffer = NULL;
164 acpi_status status = AE_OK; 164 acpi_status status = AE_OK;
165 acpi_integer index; 165 acpi_integer index;
166 acpi_size length; 166 acpi_size length;
@@ -193,34 +193,63 @@ acpi_ex_opcode_3A_1T_1R (
193 * If the index is beyond the length of the String/Buffer, or if the 193 * If the index is beyond the length of the String/Buffer, or if the
194 * requested length is zero, return a zero-length String/Buffer 194 * requested length is zero, return a zero-length String/Buffer
195 */ 195 */
196 if ((index < operand[0]->string.length) && 196 if (index >= operand[0]->string.length) {
197 (length > 0)) { 197 length = 0;
198 /* Truncate request if larger than the actual String/Buffer */ 198 }
199 199
200 if ((index + length) > 200 /* Truncate request if larger than the actual String/Buffer */
201 operand[0]->string.length) { 201
202 length = (acpi_size) operand[0]->string.length - 202 else if ((index + length) > operand[0]->string.length) {
203 (acpi_size) index; 203 length = (acpi_size) operand[0]->string.length -
204 } 204 (acpi_size) index;
205 }
205 206
206 /* Allocate a new buffer for the String/Buffer */ 207 /* Strings always have a sub-pointer, not so for buffers */
208
209 switch (ACPI_GET_OBJECT_TYPE (operand[0])) {
210 case ACPI_TYPE_STRING:
211
212 /* Always allocate a new buffer for the String */
207 213
208 buffer = ACPI_MEM_CALLOCATE ((acpi_size) length + 1); 214 buffer = ACPI_MEM_CALLOCATE ((acpi_size) length + 1);
209 if (!buffer) { 215 if (!buffer) {
210 status = AE_NO_MEMORY; 216 status = AE_NO_MEMORY;
211 goto cleanup; 217 goto cleanup;
212 } 218 }
219 break;
220
221 case ACPI_TYPE_BUFFER:
222
223 /* If the requested length is zero, don't allocate a buffer */
224
225 if (length > 0) {
226 /* Allocate a new buffer for the Buffer */
227
228 buffer = ACPI_MEM_CALLOCATE (length);
229 if (!buffer) {
230 status = AE_NO_MEMORY;
231 goto cleanup;
232 }
233 }
234 break;
213 235
236 default: /* Should not happen */
237
238 status = AE_AML_OPERAND_TYPE;
239 goto cleanup;
240 }
241
242 if (length > 0) {
214 /* Copy the portion requested */ 243 /* Copy the portion requested */
215 244
216 ACPI_MEMCPY (buffer, operand[0]->string.pointer + index, 245 ACPI_MEMCPY (buffer, operand[0]->string.pointer + index,
217 length); 246 length);
247 }
218 248
219 /* Set the length of the new String/Buffer */ 249 /* Set the length of the new String/Buffer */
220 250
221 return_desc->string.pointer = buffer; 251 return_desc->string.pointer = buffer;
222 return_desc->string.length = (u32) length; 252 return_desc->string.length = (u32) length;
223 }
224 253
225 /* Mark buffer initialized */ 254 /* Mark buffer initialized */
226 255
@@ -244,13 +273,13 @@ cleanup:
244 273
245 /* Delete return object on error */ 274 /* Delete return object on error */
246 275
247 if (ACPI_FAILURE (status)) { 276 if (ACPI_FAILURE (status) || walk_state->result_obj) {
248 acpi_ut_remove_reference (return_desc); 277 acpi_ut_remove_reference (return_desc);
249 } 278 }
250 279
251 /* Set the return object and exit */ 280 /* Set the return object and exit */
252 281
253 if (!walk_state->result_obj) { 282 else {
254 walk_state->result_obj = return_desc; 283 walk_state->result_obj = return_desc;
255 } 284 }
256 return_ACPI_STATUS (status); 285 return_ACPI_STATUS (status);