diff options
author | Bob Moore <robert.moore@intel.com> | 2006-05-26 16:36:00 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2006-06-14 02:44:35 -0400 |
commit | 4119532c95547821dbe72d6916dfa1b2148475b3 (patch) | |
tree | 564eb8f69924fb7dc72e93526faf1547acac7d30 /drivers/acpi/utilities | |
parent | b8d35192c55fb055792ff0641408eaaec7c88988 (diff) |
ACPI: ACPICA 20060526
Restructured, flattened, and simplified the internal
interfaces for namespace object evaluation - resulting
in smaller code, less CPU stack use, and fewer
interfaces. (With assistance from Mikhail Kouzmich)
Fixed a problem with the CopyObject operator where the
first parameter was not typed correctly for the parser,
interpreter, compiler, and disassembler. Caused various
errors and unexpected behavior.
Fixed a problem where a ShiftLeft or ShiftRight of
more than 64 bits produced incorrect results with some
C compilers. Since the behavior of C compilers when
the shift value is larger than the datatype width is
apparently not well defined, the interpreter now detects
this condition and simply returns zero as expected in all
such cases. (BZ 395)
Fixed problem reports (Valery Podrezov) integrated: -
Update String-to-Integer conversion to match ACPI 3.0A spec
http://bugzilla.kernel.org/show_bug.cgi?id=5329
Allow interpreter to handle nested method declarations
http://bugzilla.kernel.org/show_bug.cgi?id=5361
Fixed problem reports (Fiodor Suietov) integrated: -
acpi_terminate() doesn't free debug memory allocation
list objects (BZ 355) - After Core Subsystem
shutdown, acpi_subsystem_status() returns AE_OK (BZ 356) -
acpi_os_unmap_memory() for RSDP can be invoked inconsistently
(BZ 357) - Resource Manager should return AE_TYPE for
non-device objects (BZ 358) - Incomplete cleanup branch
in AcpiNsEvaluateRelative (BZ 359) - Use acpi_os_free()
instead of ACPI_FREE in acpi_rs_set_srs_method_data (BZ 360)
- Incomplete cleanup branch in acpi_ps_parse_aml (BZ 361) -
Incomplete cleanup branch in acpi_ds_delete_walk_state (BZ 362)
- acpi_get_table_header returns AE_NO_ACPI_TABLES until DSDT
is loaded (BZ 365) - Status of the Global Initialization
Handler call not used (BZ 366) - Incorrect object parameter
to Global Initialization Handler (BZ 367)
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/utilities')
-rw-r--r-- | drivers/acpi/utilities/utalloc.c | 51 | ||||
-rw-r--r-- | drivers/acpi/utilities/utdelete.c | 24 | ||||
-rw-r--r-- | drivers/acpi/utilities/uteval.c | 45 | ||||
-rw-r--r-- | drivers/acpi/utilities/utinit.c | 8 | ||||
-rw-r--r-- | drivers/acpi/utilities/utmisc.c | 109 |
5 files changed, 143 insertions, 94 deletions
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 65a7c2ed9aa1..7940fc1bd69e 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c | |||
@@ -61,24 +61,6 @@ acpi_status acpi_ut_create_caches(void) | |||
61 | { | 61 | { |
62 | acpi_status status; | 62 | acpi_status status; |
63 | 63 | ||
64 | #ifdef ACPI_DBG_TRACK_ALLOCATIONS | ||
65 | |||
66 | /* Memory allocation lists */ | ||
67 | |||
68 | status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list); | ||
69 | if (ACPI_FAILURE(status)) { | ||
70 | return (status); | ||
71 | } | ||
72 | |||
73 | status = | ||
74 | acpi_ut_create_list("Acpi-Namespace", | ||
75 | sizeof(struct acpi_namespace_node), | ||
76 | &acpi_gbl_ns_node_list); | ||
77 | if (ACPI_FAILURE(status)) { | ||
78 | return (status); | ||
79 | } | ||
80 | #endif | ||
81 | |||
82 | /* Object Caches, for frequently used objects */ | 64 | /* Object Caches, for frequently used objects */ |
83 | 65 | ||
84 | status = | 66 | status = |
@@ -125,6 +107,24 @@ acpi_status acpi_ut_create_caches(void) | |||
125 | return (status); | 107 | return (status); |
126 | } | 108 | } |
127 | 109 | ||
110 | #ifdef ACPI_DBG_TRACK_ALLOCATIONS | ||
111 | |||
112 | /* Memory allocation lists */ | ||
113 | |||
114 | status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list); | ||
115 | if (ACPI_FAILURE(status)) { | ||
116 | return (status); | ||
117 | } | ||
118 | |||
119 | status = | ||
120 | acpi_ut_create_list("Acpi-Namespace", | ||
121 | sizeof(struct acpi_namespace_node), | ||
122 | &acpi_gbl_ns_node_list); | ||
123 | if (ACPI_FAILURE(status)) { | ||
124 | return (status); | ||
125 | } | ||
126 | #endif | ||
127 | |||
128 | return (AE_OK); | 128 | return (AE_OK); |
129 | } | 129 | } |
130 | 130 | ||
@@ -158,6 +158,21 @@ acpi_status acpi_ut_delete_caches(void) | |||
158 | (void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache); | 158 | (void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache); |
159 | acpi_gbl_ps_node_ext_cache = NULL; | 159 | acpi_gbl_ps_node_ext_cache = NULL; |
160 | 160 | ||
161 | #ifdef ACPI_DBG_TRACK_ALLOCATIONS | ||
162 | |||
163 | /* Debug only - display leftover memory allocation, if any */ | ||
164 | |||
165 | acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL); | ||
166 | |||
167 | /* Free memory lists */ | ||
168 | |||
169 | acpi_os_free(acpi_gbl_global_list); | ||
170 | acpi_gbl_global_list = NULL; | ||
171 | |||
172 | acpi_os_free(acpi_gbl_ns_node_list); | ||
173 | acpi_gbl_ns_node_list = NULL; | ||
174 | #endif | ||
175 | |||
161 | return (AE_OK); | 176 | return (AE_OK); |
162 | } | 177 | } |
163 | 178 | ||
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index 0bb4b59b2804..67b9f325c6fa 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c | |||
@@ -319,11 +319,9 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) | |||
319 | new_count = count; | 319 | new_count = count; |
320 | 320 | ||
321 | /* | 321 | /* |
322 | * Perform the reference count action | 322 | * Perform the reference count action (increment, decrement, force delete) |
323 | * (increment, decrement, or force delete) | ||
324 | */ | 323 | */ |
325 | switch (action) { | 324 | switch (action) { |
326 | |||
327 | case REF_INCREMENT: | 325 | case REF_INCREMENT: |
328 | 326 | ||
329 | new_count++; | 327 | new_count++; |
@@ -360,7 +358,6 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) | |||
360 | if (new_count == 0) { | 358 | if (new_count == 0) { |
361 | acpi_ut_delete_internal_obj(object); | 359 | acpi_ut_delete_internal_obj(object); |
362 | } | 360 | } |
363 | |||
364 | break; | 361 | break; |
365 | 362 | ||
366 | case REF_FORCE_DELETE: | 363 | case REF_FORCE_DELETE: |
@@ -385,13 +382,10 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) | |||
385 | * (A deleted object will have a huge reference count) | 382 | * (A deleted object will have a huge reference count) |
386 | */ | 383 | */ |
387 | if (count > ACPI_MAX_REFERENCE_COUNT) { | 384 | if (count > ACPI_MAX_REFERENCE_COUNT) { |
388 | |||
389 | ACPI_WARNING((AE_INFO, | 385 | ACPI_WARNING((AE_INFO, |
390 | "Large Reference Count (%X) in object %p", | 386 | "Large Reference Count (%X) in object %p", count, |
391 | count, object)); | 387 | object)); |
392 | } | 388 | } |
393 | |||
394 | return; | ||
395 | } | 389 | } |
396 | 390 | ||
397 | /******************************************************************************* | 391 | /******************************************************************************* |
@@ -417,7 +411,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) | |||
417 | ******************************************************************************/ | 411 | ******************************************************************************/ |
418 | 412 | ||
419 | acpi_status | 413 | acpi_status |
420 | acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action) | 414 | acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) |
421 | { | 415 | { |
422 | acpi_status status = AE_OK; | 416 | acpi_status status = AE_OK; |
423 | union acpi_generic_state *state_list = NULL; | 417 | union acpi_generic_state *state_list = NULL; |
@@ -521,11 +515,11 @@ acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action) | |||
521 | 515 | ||
522 | case ACPI_TYPE_REGION: | 516 | case ACPI_TYPE_REGION: |
523 | default: | 517 | default: |
524 | break; /* No subobjects */ | 518 | break; /* No subobjects for all other types */ |
525 | } | 519 | } |
526 | 520 | ||
527 | /* | 521 | /* |
528 | * Now we can update the count in the main object. This can only | 522 | * Now we can update the count in the main object. This can only |
529 | * happen after we update the sub-objects in case this causes the | 523 | * happen after we update the sub-objects in case this causes the |
530 | * main object to be deleted. | 524 | * main object to be deleted. |
531 | */ | 525 | */ |
@@ -606,8 +600,8 @@ void acpi_ut_remove_reference(union acpi_operand_object *object) | |||
606 | ACPI_FUNCTION_TRACE_PTR(ut_remove_reference, object); | 600 | ACPI_FUNCTION_TRACE_PTR(ut_remove_reference, object); |
607 | 601 | ||
608 | /* | 602 | /* |
609 | * Allow a NULL pointer to be passed in, just ignore it. This saves | 603 | * Allow a NULL pointer to be passed in, just ignore it. This saves |
610 | * each caller from having to check. Also, ignore NS nodes. | 604 | * each caller from having to check. Also, ignore NS nodes. |
611 | * | 605 | * |
612 | */ | 606 | */ |
613 | if (!object || | 607 | if (!object || |
@@ -627,7 +621,7 @@ void acpi_ut_remove_reference(union acpi_operand_object *object) | |||
627 | 621 | ||
628 | /* | 622 | /* |
629 | * Decrement the reference count, and only actually delete the object | 623 | * Decrement the reference count, and only actually delete the object |
630 | * if the reference count becomes 0. (Must also decrement the ref count | 624 | * if the reference count becomes 0. (Must also decrement the ref count |
631 | * of all subobjects!) | 625 | * of all subobjects!) |
632 | */ | 626 | */ |
633 | (void)acpi_ut_update_object_reference(object, REF_DECREMENT); | 627 | (void)acpi_ut_update_object_reference(object, REF_DECREMENT); |
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c index 444d3a502c46..d6d7121583c0 100644 --- a/drivers/acpi/utilities/uteval.c +++ b/drivers/acpi/utilities/uteval.c | |||
@@ -181,19 +181,26 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, | |||
181 | u32 expected_return_btypes, | 181 | u32 expected_return_btypes, |
182 | union acpi_operand_object **return_desc) | 182 | union acpi_operand_object **return_desc) |
183 | { | 183 | { |
184 | struct acpi_parameter_info info; | 184 | struct acpi_evaluate_info *info; |
185 | acpi_status status; | 185 | acpi_status status; |
186 | u32 return_btype; | 186 | u32 return_btype; |
187 | 187 | ||
188 | ACPI_FUNCTION_TRACE(ut_evaluate_object); | 188 | ACPI_FUNCTION_TRACE(ut_evaluate_object); |
189 | 189 | ||
190 | info.node = prefix_node; | 190 | /* Allocate the evaluation information block */ |
191 | info.parameters = NULL; | 191 | |
192 | info.parameter_type = ACPI_PARAM_ARGS; | 192 | info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); |
193 | if (!info) { | ||
194 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
195 | } | ||
196 | |||
197 | info->prefix_node = prefix_node; | ||
198 | info->pathname = path; | ||
199 | info->parameter_type = ACPI_PARAM_ARGS; | ||
193 | 200 | ||
194 | /* Evaluate the object/method */ | 201 | /* Evaluate the object/method */ |
195 | 202 | ||
196 | status = acpi_ns_evaluate_relative(path, &info); | 203 | status = acpi_ns_evaluate(info); |
197 | if (ACPI_FAILURE(status)) { | 204 | if (ACPI_FAILURE(status)) { |
198 | if (status == AE_NOT_FOUND) { | 205 | if (status == AE_NOT_FOUND) { |
199 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 206 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
@@ -205,25 +212,25 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, | |||
205 | prefix_node, path, status); | 212 | prefix_node, path, status); |
206 | } | 213 | } |
207 | 214 | ||
208 | return_ACPI_STATUS(status); | 215 | goto cleanup; |
209 | } | 216 | } |
210 | 217 | ||
211 | /* Did we get a return object? */ | 218 | /* Did we get a return object? */ |
212 | 219 | ||
213 | if (!info.return_object) { | 220 | if (!info->return_object) { |
214 | if (expected_return_btypes) { | 221 | if (expected_return_btypes) { |
215 | ACPI_ERROR_METHOD("No object was returned from", | 222 | ACPI_ERROR_METHOD("No object was returned from", |
216 | prefix_node, path, AE_NOT_EXIST); | 223 | prefix_node, path, AE_NOT_EXIST); |
217 | 224 | ||
218 | return_ACPI_STATUS(AE_NOT_EXIST); | 225 | status = AE_NOT_EXIST; |
219 | } | 226 | } |
220 | 227 | ||
221 | return_ACPI_STATUS(AE_OK); | 228 | goto cleanup; |
222 | } | 229 | } |
223 | 230 | ||
224 | /* Map the return object type to the bitmapped type */ | 231 | /* Map the return object type to the bitmapped type */ |
225 | 232 | ||
226 | switch (ACPI_GET_OBJECT_TYPE(info.return_object)) { | 233 | switch (ACPI_GET_OBJECT_TYPE(info->return_object)) { |
227 | case ACPI_TYPE_INTEGER: | 234 | case ACPI_TYPE_INTEGER: |
228 | return_btype = ACPI_BTYPE_INTEGER; | 235 | return_btype = ACPI_BTYPE_INTEGER; |
229 | break; | 236 | break; |
@@ -251,8 +258,8 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, | |||
251 | * happen frequently if the "implicit return" feature is enabled. | 258 | * happen frequently if the "implicit return" feature is enabled. |
252 | * Just delete the return object and return AE_OK. | 259 | * Just delete the return object and return AE_OK. |
253 | */ | 260 | */ |
254 | acpi_ut_remove_reference(info.return_object); | 261 | acpi_ut_remove_reference(info->return_object); |
255 | return_ACPI_STATUS(AE_OK); | 262 | goto cleanup; |
256 | } | 263 | } |
257 | 264 | ||
258 | /* Is the return object one of the expected types? */ | 265 | /* Is the return object one of the expected types? */ |
@@ -264,19 +271,23 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, | |||
264 | ACPI_ERROR((AE_INFO, | 271 | ACPI_ERROR((AE_INFO, |
265 | "Type returned from %s was incorrect: %s, expected Btypes: %X", | 272 | "Type returned from %s was incorrect: %s, expected Btypes: %X", |
266 | path, | 273 | path, |
267 | acpi_ut_get_object_type_name(info.return_object), | 274 | acpi_ut_get_object_type_name(info->return_object), |
268 | expected_return_btypes)); | 275 | expected_return_btypes)); |
269 | 276 | ||
270 | /* On error exit, we must delete the return object */ | 277 | /* On error exit, we must delete the return object */ |
271 | 278 | ||
272 | acpi_ut_remove_reference(info.return_object); | 279 | acpi_ut_remove_reference(info->return_object); |
273 | return_ACPI_STATUS(AE_TYPE); | 280 | status = AE_TYPE; |
281 | goto cleanup; | ||
274 | } | 282 | } |
275 | 283 | ||
276 | /* Object type is OK, return it */ | 284 | /* Object type is OK, return it */ |
277 | 285 | ||
278 | *return_desc = info.return_object; | 286 | *return_desc = info->return_object; |
279 | return_ACPI_STATUS(AE_OK); | 287 | |
288 | cleanup: | ||
289 | ACPI_FREE(info); | ||
290 | return_ACPI_STATUS(status); | ||
280 | } | 291 | } |
281 | 292 | ||
282 | /******************************************************************************* | 293 | /******************************************************************************* |
diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c index c65747d3c880..ff76055eb7d6 100644 --- a/drivers/acpi/utilities/utinit.c +++ b/drivers/acpi/utilities/utinit.c | |||
@@ -228,6 +228,7 @@ void acpi_ut_subsystem_shutdown(void) | |||
228 | /* Subsystem appears active, go ahead and shut it down */ | 228 | /* Subsystem appears active, go ahead and shut it down */ |
229 | 229 | ||
230 | acpi_gbl_shutdown = TRUE; | 230 | acpi_gbl_shutdown = TRUE; |
231 | acpi_gbl_startup_flags = 0; | ||
231 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); | 232 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); |
232 | 233 | ||
233 | /* Close the acpi_event Handling */ | 234 | /* Close the acpi_event Handling */ |
@@ -245,12 +246,5 @@ void acpi_ut_subsystem_shutdown(void) | |||
245 | /* Purge the local caches */ | 246 | /* Purge the local caches */ |
246 | 247 | ||
247 | (void)acpi_ut_delete_caches(); | 248 | (void)acpi_ut_delete_caches(); |
248 | |||
249 | /* Debug only - display leftover memory allocation, if any */ | ||
250 | |||
251 | #ifdef ACPI_DBG_TRACK_ALLOCATIONS | ||
252 | acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL); | ||
253 | #endif | ||
254 | |||
255 | return_VOID; | 249 | return_VOID; |
256 | } | 250 | } |
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 874467117cec..5c75d35ad1cd 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c | |||
@@ -601,7 +601,8 @@ acpi_name acpi_ut_repair_name(acpi_name name) | |||
601 | * FUNCTION: acpi_ut_strtoul64 | 601 | * FUNCTION: acpi_ut_strtoul64 |
602 | * | 602 | * |
603 | * PARAMETERS: String - Null terminated string | 603 | * PARAMETERS: String - Null terminated string |
604 | * Base - Radix of the string: 10, 16, or ACPI_ANY_BASE | 604 | * Base - Radix of the string: 16 or ACPI_ANY_BASE; |
605 | * ACPI_ANY_BASE means 'in behalf of to_integer' | ||
605 | * ret_integer - Where the converted integer is returned | 606 | * ret_integer - Where the converted integer is returned |
606 | * | 607 | * |
607 | * RETURN: Status and Converted value | 608 | * RETURN: Status and Converted value |
@@ -617,16 +618,17 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) | |||
617 | u32 this_digit = 0; | 618 | u32 this_digit = 0; |
618 | acpi_integer return_value = 0; | 619 | acpi_integer return_value = 0; |
619 | acpi_integer quotient; | 620 | acpi_integer quotient; |
621 | acpi_integer dividend; | ||
622 | u32 to_integer_op = (base == ACPI_ANY_BASE); | ||
623 | u32 mode32 = (acpi_gbl_integer_byte_width == 4); | ||
624 | u8 valid_digits = 0; | ||
625 | u8 sign_of0x = 0; | ||
626 | u8 term = 0; | ||
620 | 627 | ||
621 | ACPI_FUNCTION_TRACE(ut_stroul64); | 628 | ACPI_FUNCTION_TRACE(ut_stroul64); |
622 | 629 | ||
623 | if ((!string) || !(*string)) { | ||
624 | goto error_exit; | ||
625 | } | ||
626 | |||
627 | switch (base) { | 630 | switch (base) { |
628 | case ACPI_ANY_BASE: | 631 | case ACPI_ANY_BASE: |
629 | case 10: | ||
630 | case 16: | 632 | case 16: |
631 | break; | 633 | break; |
632 | 634 | ||
@@ -635,39 +637,45 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) | |||
635 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 637 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
636 | } | 638 | } |
637 | 639 | ||
640 | if (!string) { | ||
641 | goto error_exit; | ||
642 | } | ||
643 | |||
638 | /* Skip over any white space in the buffer */ | 644 | /* Skip over any white space in the buffer */ |
639 | 645 | ||
640 | while (ACPI_IS_SPACE(*string) || *string == '\t') { | 646 | while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) { |
641 | string++; | 647 | string++; |
642 | } | 648 | } |
643 | 649 | ||
644 | /* | 650 | if (to_integer_op) { |
645 | * If the input parameter Base is zero, then we need to | 651 | /* |
646 | * determine if it is decimal or hexadecimal: | 652 | * Base equal to ACPI_ANY_BASE means 'to_integer operation case'. |
647 | */ | 653 | * We need to determine if it is decimal or hexadecimal. |
648 | if (base == 0) { | 654 | */ |
649 | if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { | 655 | if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { |
656 | sign_of0x = 1; | ||
650 | base = 16; | 657 | base = 16; |
658 | |||
659 | /* Skip over the leading '0x' */ | ||
651 | string += 2; | 660 | string += 2; |
652 | } else { | 661 | } else { |
653 | base = 10; | 662 | base = 10; |
654 | } | 663 | } |
655 | } | 664 | } |
656 | 665 | ||
657 | /* | 666 | /* Any string left? Check that '0x' is not followed by white space. */ |
658 | * For hexadecimal base, skip over the leading | 667 | |
659 | * 0 or 0x, if they are present. | 668 | if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') { |
660 | */ | 669 | if (to_integer_op) { |
661 | if ((base == 16) && | 670 | goto error_exit; |
662 | (*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { | 671 | } else { |
663 | string += 2; | 672 | goto all_done; |
673 | } | ||
664 | } | 674 | } |
665 | 675 | ||
666 | /* Any string left? */ | 676 | dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; |
667 | 677 | ||
668 | if (!(*string)) { | 678 | /* At least one character in the string here */ |
669 | goto error_exit; | ||
670 | } | ||
671 | 679 | ||
672 | /* Main loop: convert the string to a 64-bit integer */ | 680 | /* Main loop: convert the string to a 64-bit integer */ |
673 | 681 | ||
@@ -677,14 +685,12 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) | |||
677 | /* Convert ASCII 0-9 to Decimal value */ | 685 | /* Convert ASCII 0-9 to Decimal value */ |
678 | 686 | ||
679 | this_digit = ((u8) * string) - '0'; | 687 | this_digit = ((u8) * string) - '0'; |
680 | } else { | 688 | } else if (base == 10) { |
681 | if (base == 10) { | ||
682 | 689 | ||
683 | /* Digit is out of range */ | 690 | /* Digit is out of range; possible in to_integer case only */ |
684 | |||
685 | goto error_exit; | ||
686 | } | ||
687 | 691 | ||
692 | term = 1; | ||
693 | } else { | ||
688 | this_digit = (u8) ACPI_TOUPPER(*string); | 694 | this_digit = (u8) ACPI_TOUPPER(*string); |
689 | if (ACPI_IS_XDIGIT((char)this_digit)) { | 695 | if (ACPI_IS_XDIGIT((char)this_digit)) { |
690 | 696 | ||
@@ -692,22 +698,49 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) | |||
692 | 698 | ||
693 | this_digit = this_digit - 'A' + 10; | 699 | this_digit = this_digit - 'A' + 10; |
694 | } else { | 700 | } else { |
695 | /* | 701 | term = 1; |
696 | * We allow non-hex chars, just stop now, same as end-of-string. | 702 | } |
697 | * See ACPI spec, string-to-integer conversion. | 703 | } |
698 | */ | 704 | |
705 | if (term) { | ||
706 | if (to_integer_op) { | ||
707 | goto error_exit; | ||
708 | } else { | ||
699 | break; | 709 | break; |
700 | } | 710 | } |
711 | } else if ((valid_digits == 0) && (this_digit == 0) | ||
712 | && !sign_of0x) { | ||
713 | |||
714 | /* Skip zeros */ | ||
715 | string++; | ||
716 | continue; | ||
717 | } | ||
718 | |||
719 | valid_digits++; | ||
720 | |||
721 | if (sign_of0x | ||
722 | && ((valid_digits > 16) | ||
723 | || ((valid_digits > 8) && mode32))) { | ||
724 | /* | ||
725 | * This is to_integer operation case. | ||
726 | * No any restrictions for string-to-integer conversion, | ||
727 | * see ACPI spec. | ||
728 | */ | ||
729 | goto error_exit; | ||
701 | } | 730 | } |
702 | 731 | ||
703 | /* Divide the digit into the correct position */ | 732 | /* Divide the digit into the correct position */ |
704 | 733 | ||
705 | (void) | 734 | (void) |
706 | acpi_ut_short_divide((ACPI_INTEGER_MAX - | 735 | acpi_ut_short_divide((dividend - (acpi_integer) this_digit), |
707 | (acpi_integer) this_digit), base, | 736 | base, "ient, NULL); |
708 | "ient, NULL); | 737 | |
709 | if (return_value > quotient) { | 738 | if (return_value > quotient) { |
710 | goto error_exit; | 739 | if (to_integer_op) { |
740 | goto error_exit; | ||
741 | } else { | ||
742 | break; | ||
743 | } | ||
711 | } | 744 | } |
712 | 745 | ||
713 | return_value *= base; | 746 | return_value *= base; |
@@ -717,6 +750,8 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) | |||
717 | 750 | ||
718 | /* All done, normal exit */ | 751 | /* All done, normal exit */ |
719 | 752 | ||
753 | all_done: | ||
754 | |||
720 | *ret_integer = return_value; | 755 | *ret_integer = return_value; |
721 | return_ACPI_STATUS(AE_OK); | 756 | return_ACPI_STATUS(AE_OK); |
722 | 757 | ||