aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/parser
diff options
context:
space:
mode:
authorRobert Moore <robert.moore@intel.com>2005-05-26 00:00:00 -0400
committerLen Brown <len.brown@intel.com>2005-07-13 16:46:34 -0400
commit88ac00f5a841dcfc5c682000f4a6add0add8caac (patch)
tree80dcff8323c6c79e8706f42eb4b7c3884bc03152 /drivers/acpi/parser
parent6f42ccf2fc50ecee8ea170040627f268430c1648 (diff)
ACPICA 20050526 from Bob Moore <robert.moore@intel.com>
Implemented support to execute Type 1 and Type 2 AML opcodes appearing at the module level (not within a control method.) These opcodes are executed exactly once at the time the table is loaded. This type of code was legal up until the release of ACPI 2.0B (2002) and is now supported within ACPI CA in order to provide backwards compatibility with earlier BIOS implementations. This eliminates the "Encountered executable code at module level" warning that was previously generated upon detection of such code. Fixed a problem in the interpreter where an AE_NOT_FOUND exception could inadvertently be generated during the lookup of namespace objects in the second pass parse of ACPI tables and control methods. It appears that this problem could occur during the resolution of forward references to namespace objects. Added the ACPI_MUTEX_DEBUG #ifdef to the acpi_ut_release_mutex function, corresponding to the same the deadlock detection debug code to be compiled out in the normal case, improving mutex performance (and overall subsystem performance) considerably. As suggested by Alexey Starikovskiy. Implemented a handful of miscellaneous fixes for possible memory leaks on error conditions and error handling control paths. These fixes were suggested by FreeBSD and the Coverity Prevent source code analysis tool. Added a check for a null RSDT pointer in acpi_get_firmware_table (tbxfroot.c) to prevent a fault in this error case. Signed-off-by Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/parser')
-rw-r--r--drivers/acpi/parser/psparse.c109
1 files changed, 83 insertions, 26 deletions
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index bbfdc1a58c27..bdbe0d99486f 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -66,7 +66,7 @@ static u32 acpi_gbl_depth = 0;
66 66
67/* Local prototypes */ 67/* Local prototypes */
68 68
69static void 69static acpi_status
70acpi_ps_complete_this_op ( 70acpi_ps_complete_this_op (
71 struct acpi_walk_state *walk_state, 71 struct acpi_walk_state *walk_state,
72 union acpi_parse_object *op); 72 union acpi_parse_object *op);
@@ -152,13 +152,13 @@ acpi_ps_peek_opcode (
152 * PARAMETERS: walk_state - Current State 152 * PARAMETERS: walk_state - Current State
153 * Op - Op to complete 153 * Op - Op to complete
154 * 154 *
155 * RETURN: None. 155 * RETURN: Status
156 * 156 *
157 * DESCRIPTION: Perform any cleanup at the completion of an Op. 157 * DESCRIPTION: Perform any cleanup at the completion of an Op.
158 * 158 *
159 ******************************************************************************/ 159 ******************************************************************************/
160 160
161static void 161static acpi_status
162acpi_ps_complete_this_op ( 162acpi_ps_complete_this_op (
163 struct acpi_walk_state *walk_state, 163 struct acpi_walk_state *walk_state,
164 union acpi_parse_object *op) 164 union acpi_parse_object *op)
@@ -175,19 +175,26 @@ acpi_ps_complete_this_op (
175 /* Check for null Op, can happen if AML code is corrupt */ 175 /* Check for null Op, can happen if AML code is corrupt */
176 176
177 if (!op) { 177 if (!op) {
178 return_VOID; 178 return_ACPI_STATUS (AE_OK); /* OK for now */
179 } 179 }
180 180
181 /* Delete this op and the subtree below it if asked to */ 181 /* Delete this op and the subtree below it if asked to */
182 182
183 if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) || 183 if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) ||
184 (walk_state->op_info->class == AML_CLASS_ARGUMENT)) { 184 (walk_state->op_info->class == AML_CLASS_ARGUMENT)) {
185 return_VOID; 185 return_ACPI_STATUS (AE_OK);
186 } 186 }
187 187
188 /* Make sure that we only delete this subtree */ 188 /* Make sure that we only delete this subtree */
189 189
190 if (op->common.parent) { 190 if (op->common.parent) {
191 prev = op->common.parent->common.value.arg;
192 if (!prev) {
193 /* Nothing more to do */
194
195 goto cleanup;
196 }
197
191 /* 198 /*
192 * Check if we need to replace the operator and its subtree 199 * Check if we need to replace the operator and its subtree
193 * with a return value op (placeholder op) 200 * with a return value op (placeholder op)
@@ -206,7 +213,7 @@ acpi_ps_complete_this_op (
206 */ 213 */
207 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); 214 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
208 if (!replacement_op) { 215 if (!replacement_op) {
209 goto cleanup; 216 goto allocate_error;
210 } 217 }
211 break; 218 break;
212 219
@@ -223,18 +230,17 @@ acpi_ps_complete_this_op (
223 (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { 230 (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
224 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); 231 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
225 if (!replacement_op) { 232 if (!replacement_op) {
226 goto cleanup; 233 goto allocate_error;
227 } 234 }
228 } 235 }
229 236 else if ((op->common.parent->common.aml_opcode == AML_NAME_OP) &&
230 if ((op->common.parent->common.aml_opcode == AML_NAME_OP) && 237 (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2)) {
231 (walk_state->descending_callback != acpi_ds_exec_begin_op)) {
232 if ((op->common.aml_opcode == AML_BUFFER_OP) || 238 if ((op->common.aml_opcode == AML_BUFFER_OP) ||
233 (op->common.aml_opcode == AML_PACKAGE_OP) || 239 (op->common.aml_opcode == AML_PACKAGE_OP) ||
234 (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) { 240 (op->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
235 replacement_op = acpi_ps_alloc_op (op->common.aml_opcode); 241 replacement_op = acpi_ps_alloc_op (op->common.aml_opcode);
236 if (!replacement_op) { 242 if (!replacement_op) {
237 goto cleanup; 243 goto allocate_error;
238 } 244 }
239 245
240 replacement_op->named.data = op->named.data; 246 replacement_op->named.data = op->named.data;
@@ -244,15 +250,15 @@ acpi_ps_complete_this_op (
244 break; 250 break;
245 251
246 default: 252 default:
253
247 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP); 254 replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);
248 if (!replacement_op) { 255 if (!replacement_op) {
249 goto cleanup; 256 goto allocate_error;
250 } 257 }
251 } 258 }
252 259
253 /* We must unlink this op from the parent tree */ 260 /* We must unlink this op from the parent tree */
254 261
255 prev = op->common.parent->common.value.arg;
256 if (prev == op) { 262 if (prev == op) {
257 /* This op is the first in the list */ 263 /* This op is the first in the list */
258 264
@@ -298,7 +304,15 @@ cleanup:
298 /* Now we can actually delete the subtree rooted at Op */ 304 /* Now we can actually delete the subtree rooted at Op */
299 305
300 acpi_ps_delete_parse_tree (op); 306 acpi_ps_delete_parse_tree (op);
301 return_VOID; 307 return_ACPI_STATUS (AE_OK);
308
309
310allocate_error:
311
312 /* Always delete the subtree, even on error */
313
314 acpi_ps_delete_parse_tree (op);
315 return_ACPI_STATUS (AE_NO_MEMORY);
302} 316}
303 317
304 318
@@ -443,6 +457,7 @@ acpi_ps_parse_loop (
443 struct acpi_walk_state *walk_state) 457 struct acpi_walk_state *walk_state)
444{ 458{
445 acpi_status status = AE_OK; 459 acpi_status status = AE_OK;
460 acpi_status status2;
446 union acpi_parse_object *op = NULL; /* current op */ 461 union acpi_parse_object *op = NULL; /* current op */
447 union acpi_parse_object *arg = NULL; 462 union acpi_parse_object *arg = NULL;
448 union acpi_parse_object *pre_op = NULL; 463 union acpi_parse_object *pre_op = NULL;
@@ -744,7 +759,6 @@ acpi_ps_parse_loop (
744 break; 759 break;
745 760
746 default: 761 default:
747
748 /* 762 /*
749 * Op is not a constant or string, append each argument 763 * Op is not a constant or string, append each argument
750 * to the Op 764 * to the Op
@@ -770,6 +784,23 @@ acpi_ps_parse_loop (
770 784
771 /* Special processing for certain opcodes */ 785 /* Special processing for certain opcodes */
772 786
787 if (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) {
788 switch (op->common.aml_opcode) {
789 case AML_IF_OP:
790 case AML_ELSE_OP:
791 case AML_WHILE_OP:
792
793 /* Skip body of if/else/while in pass 1 */
794
795 parser_state->aml = parser_state->pkg_end;
796 walk_state->arg_count = 0;
797 break;
798
799 default:
800 break;
801 }
802 }
803
773 switch (op->common.aml_opcode) { 804 switch (op->common.aml_opcode) {
774 case AML_METHOD_OP: 805 case AML_METHOD_OP:
775 806
@@ -796,7 +827,7 @@ acpi_ps_parse_loop (
796 827
797 if ((op->common.parent) && 828 if ((op->common.parent) &&
798 (op->common.parent->common.aml_opcode == AML_NAME_OP) && 829 (op->common.parent->common.aml_opcode == AML_NAME_OP) &&
799 (walk_state->descending_callback != acpi_ds_exec_begin_op)) { 830 (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2)) {
800 /* 831 /*
801 * Skip parsing of Buffers and Packages 832 * Skip parsing of Buffers and Packages
802 * because we don't have enough info in the first pass 833 * because we don't have enough info in the first pass
@@ -900,15 +931,21 @@ close_this_op:
900 */ 931 */
901 parser_state->scope->parse_scope.arg_count--; 932 parser_state->scope->parse_scope.arg_count--;
902 933
903 /* Close this Op (will result in parse subtree deletion) */ 934 /* Finished with pre_op */
904 935
905 acpi_ps_complete_this_op (walk_state, op);
906 op = NULL;
907 if (pre_op) { 936 if (pre_op) {
908 acpi_ps_free_op (pre_op); 937 acpi_ps_free_op (pre_op);
909 pre_op = NULL; 938 pre_op = NULL;
910 } 939 }
911 940
941 /* Close this Op (will result in parse subtree deletion) */
942
943 status2 = acpi_ps_complete_this_op (walk_state, op);
944 if (ACPI_FAILURE (status2)) {
945 return_ACPI_STATUS (status2);
946 }
947 op = NULL;
948
912 switch (status) { 949 switch (status) {
913 case AE_OK: 950 case AE_OK:
914 break; 951 break;
@@ -936,7 +973,10 @@ close_this_op:
936 status = walk_state->ascending_callback (walk_state); 973 status = walk_state->ascending_callback (walk_state);
937 status = acpi_ps_next_parse_state (walk_state, op, status); 974 status = acpi_ps_next_parse_state (walk_state, op, status);
938 975
939 acpi_ps_complete_this_op (walk_state, op); 976 status2 = acpi_ps_complete_this_op (walk_state, op);
977 if (ACPI_FAILURE (status2)) {
978 return_ACPI_STATUS (status2);
979 }
940 op = NULL; 980 op = NULL;
941 } 981 }
942 status = AE_OK; 982 status = AE_OK;
@@ -962,7 +1002,10 @@ close_this_op:
962 status = walk_state->ascending_callback (walk_state); 1002 status = walk_state->ascending_callback (walk_state);
963 status = acpi_ps_next_parse_state (walk_state, op, status); 1003 status = acpi_ps_next_parse_state (walk_state, op, status);
964 1004
965 acpi_ps_complete_this_op (walk_state, op); 1005 status2 = acpi_ps_complete_this_op (walk_state, op);
1006 if (ACPI_FAILURE (status2)) {
1007 return_ACPI_STATUS (status2);
1008 }
966 op = NULL; 1009 op = NULL;
967 1010
968 status = AE_OK; 1011 status = AE_OK;
@@ -976,7 +1019,10 @@ close_this_op:
976 /* Clean up */ 1019 /* Clean up */
977 do { 1020 do {
978 if (op) { 1021 if (op) {
979 acpi_ps_complete_this_op (walk_state, op); 1022 status2 = acpi_ps_complete_this_op (walk_state, op);
1023 if (ACPI_FAILURE (status2)) {
1024 return_ACPI_STATUS (status2);
1025 }
980 } 1026 }
981 acpi_ps_pop_scope (parser_state, &op, 1027 acpi_ps_pop_scope (parser_state, &op,
982 &walk_state->arg_types, &walk_state->arg_count); 1028 &walk_state->arg_types, &walk_state->arg_count);
@@ -990,7 +1036,10 @@ close_this_op:
990 1036
991 do { 1037 do {
992 if (op) { 1038 if (op) {
993 acpi_ps_complete_this_op (walk_state, op); 1039 status2 = acpi_ps_complete_this_op (walk_state, op);
1040 if (ACPI_FAILURE (status2)) {
1041 return_ACPI_STATUS (status2);
1042 }
994 } 1043 }
995 acpi_ps_pop_scope (parser_state, &op, 1044 acpi_ps_pop_scope (parser_state, &op,
996 &walk_state->arg_types, &walk_state->arg_count); 1045 &walk_state->arg_types, &walk_state->arg_count);
@@ -1053,7 +1102,10 @@ close_this_op:
1053 /* Clean up */ 1102 /* Clean up */
1054 do { 1103 do {
1055 if (op) { 1104 if (op) {
1056 acpi_ps_complete_this_op (walk_state, op); 1105 status2 = acpi_ps_complete_this_op (walk_state, op);
1106 if (ACPI_FAILURE (status2)) {
1107 return_ACPI_STATUS (status2);
1108 }
1057 } 1109 }
1058 1110
1059 acpi_ps_pop_scope (parser_state, &op, 1111 acpi_ps_pop_scope (parser_state, &op,
@@ -1065,12 +1117,17 @@ close_this_op:
1065 } 1117 }
1066 1118
1067 else if (ACPI_FAILURE (status)) { 1119 else if (ACPI_FAILURE (status)) {
1068 acpi_ps_complete_this_op (walk_state, op); 1120 /* First error is most important */
1121
1122 (void) acpi_ps_complete_this_op (walk_state, op);
1069 return_ACPI_STATUS (status); 1123 return_ACPI_STATUS (status);
1070 } 1124 }
1071 } 1125 }
1072 1126
1073 acpi_ps_complete_this_op (walk_state, op); 1127 status2 = acpi_ps_complete_this_op (walk_state, op);
1128 if (ACPI_FAILURE (status2)) {
1129 return_ACPI_STATUS (status2);
1130 }
1074 } 1131 }
1075 1132
1076 acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types, 1133 acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types,