Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/acpi/acpica/dswload.c
15111 views
1
/******************************************************************************
2
*
3
* Module Name: dswload - Dispatcher first pass namespace load callbacks
4
*
5
*****************************************************************************/
6
7
/*
8
* Copyright (C) 2000 - 2011, Intel Corp.
9
* All rights reserved.
10
*
11
* Redistribution and use in source and binary forms, with or without
12
* modification, are permitted provided that the following conditions
13
* are met:
14
* 1. Redistributions of source code must retain the above copyright
15
* notice, this list of conditions, and the following disclaimer,
16
* without modification.
17
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
18
* substantially similar to the "NO WARRANTY" disclaimer below
19
* ("Disclaimer") and any redistribution must be conditioned upon
20
* including a substantially similar Disclaimer requirement for further
21
* binary redistribution.
22
* 3. Neither the names of the above-listed copyright holders nor the names
23
* of any contributors may be used to endorse or promote products derived
24
* from this software without specific prior written permission.
25
*
26
* Alternatively, this software may be distributed under the terms of the
27
* GNU General Public License ("GPL") version 2 as published by the Free
28
* Software Foundation.
29
*
30
* NO WARRANTY
31
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41
* POSSIBILITY OF SUCH DAMAGES.
42
*/
43
44
#include <acpi/acpi.h>
45
#include "accommon.h"
46
#include "acparser.h"
47
#include "amlcode.h"
48
#include "acdispat.h"
49
#include "acinterp.h"
50
#include "acnamesp.h"
51
52
#ifdef ACPI_ASL_COMPILER
53
#include <acpi/acdisasm.h>
54
#endif
55
56
#define _COMPONENT ACPI_DISPATCHER
57
ACPI_MODULE_NAME("dswload")
58
59
/*******************************************************************************
60
*
61
* FUNCTION: acpi_ds_init_callbacks
62
*
63
* PARAMETERS: walk_state - Current state of the parse tree walk
64
* pass_number - 1, 2, or 3
65
*
66
* RETURN: Status
67
*
68
* DESCRIPTION: Init walk state callbacks
69
*
70
******************************************************************************/
71
acpi_status
72
acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number)
73
{
74
75
switch (pass_number) {
76
case 1:
77
walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
78
ACPI_PARSE_DELETE_TREE;
79
walk_state->descending_callback = acpi_ds_load1_begin_op;
80
walk_state->ascending_callback = acpi_ds_load1_end_op;
81
break;
82
83
case 2:
84
walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
85
ACPI_PARSE_DELETE_TREE;
86
walk_state->descending_callback = acpi_ds_load2_begin_op;
87
walk_state->ascending_callback = acpi_ds_load2_end_op;
88
break;
89
90
case 3:
91
#ifndef ACPI_NO_METHOD_EXECUTION
92
walk_state->parse_flags |= ACPI_PARSE_EXECUTE |
93
ACPI_PARSE_DELETE_TREE;
94
walk_state->descending_callback = acpi_ds_exec_begin_op;
95
walk_state->ascending_callback = acpi_ds_exec_end_op;
96
#endif
97
break;
98
99
default:
100
return (AE_BAD_PARAMETER);
101
}
102
103
return (AE_OK);
104
}
105
106
/*******************************************************************************
107
*
108
* FUNCTION: acpi_ds_load1_begin_op
109
*
110
* PARAMETERS: walk_state - Current state of the parse tree walk
111
* out_op - Where to return op if a new one is created
112
*
113
* RETURN: Status
114
*
115
* DESCRIPTION: Descending callback used during the loading of ACPI tables.
116
*
117
******************************************************************************/
118
119
acpi_status
120
acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
121
union acpi_parse_object ** out_op)
122
{
123
union acpi_parse_object *op;
124
struct acpi_namespace_node *node;
125
acpi_status status;
126
acpi_object_type object_type;
127
char *path;
128
u32 flags;
129
130
ACPI_FUNCTION_TRACE(ds_load1_begin_op);
131
132
op = walk_state->op;
133
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
134
walk_state));
135
136
/* We are only interested in opcodes that have an associated name */
137
138
if (op) {
139
if (!(walk_state->op_info->flags & AML_NAMED)) {
140
*out_op = op;
141
return_ACPI_STATUS(AE_OK);
142
}
143
144
/* Check if this object has already been installed in the namespace */
145
146
if (op->common.node) {
147
*out_op = op;
148
return_ACPI_STATUS(AE_OK);
149
}
150
}
151
152
path = acpi_ps_get_next_namestring(&walk_state->parser_state);
153
154
/* Map the raw opcode into an internal object type */
155
156
object_type = walk_state->op_info->object_type;
157
158
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
159
"State=%p Op=%p [%s]\n", walk_state, op,
160
acpi_ut_get_type_name(object_type)));
161
162
switch (walk_state->opcode) {
163
case AML_SCOPE_OP:
164
165
/*
166
* The target name of the Scope() operator must exist at this point so
167
* that we can actually open the scope to enter new names underneath it.
168
* Allow search-to-root for single namesegs.
169
*/
170
status =
171
acpi_ns_lookup(walk_state->scope_info, path, object_type,
172
ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
173
walk_state, &(node));
174
#ifdef ACPI_ASL_COMPILER
175
if (status == AE_NOT_FOUND) {
176
/*
177
* Table disassembly:
178
* Target of Scope() not found. Generate an External for it, and
179
* insert the name into the namespace.
180
*/
181
acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0);
182
status =
183
acpi_ns_lookup(walk_state->scope_info, path,
184
object_type, ACPI_IMODE_LOAD_PASS1,
185
ACPI_NS_SEARCH_PARENT, walk_state,
186
&node);
187
}
188
#endif
189
if (ACPI_FAILURE(status)) {
190
ACPI_ERROR_NAMESPACE(path, status);
191
return_ACPI_STATUS(status);
192
}
193
194
/*
195
* Check to make sure that the target is
196
* one of the opcodes that actually opens a scope
197
*/
198
switch (node->type) {
199
case ACPI_TYPE_ANY:
200
case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
201
case ACPI_TYPE_DEVICE:
202
case ACPI_TYPE_POWER:
203
case ACPI_TYPE_PROCESSOR:
204
case ACPI_TYPE_THERMAL:
205
206
/* These are acceptable types */
207
break;
208
209
case ACPI_TYPE_INTEGER:
210
case ACPI_TYPE_STRING:
211
case ACPI_TYPE_BUFFER:
212
213
/*
214
* These types we will allow, but we will change the type.
215
* This enables some existing code of the form:
216
*
217
* Name (DEB, 0)
218
* Scope (DEB) { ... }
219
*
220
* Note: silently change the type here. On the second pass,
221
* we will report a warning
222
*/
223
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
224
"Type override - [%4.4s] had invalid type (%s) "
225
"for Scope operator, changed to type ANY\n",
226
acpi_ut_get_node_name(node),
227
acpi_ut_get_type_name(node->type)));
228
229
node->type = ACPI_TYPE_ANY;
230
walk_state->scope_info->common.value = ACPI_TYPE_ANY;
231
break;
232
233
default:
234
235
/* All other types are an error */
236
237
ACPI_ERROR((AE_INFO,
238
"Invalid type (%s) for target of "
239
"Scope operator [%4.4s] (Cannot override)",
240
acpi_ut_get_type_name(node->type),
241
acpi_ut_get_node_name(node)));
242
243
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
244
}
245
break;
246
247
default:
248
/*
249
* For all other named opcodes, we will enter the name into
250
* the namespace.
251
*
252
* Setup the search flags.
253
* Since we are entering a name into the namespace, we do not want to
254
* enable the search-to-root upsearch.
255
*
256
* There are only two conditions where it is acceptable that the name
257
* already exists:
258
* 1) the Scope() operator can reopen a scoping object that was
259
* previously defined (Scope, Method, Device, etc.)
260
* 2) Whenever we are parsing a deferred opcode (op_region, Buffer,
261
* buffer_field, or Package), the name of the object is already
262
* in the namespace.
263
*/
264
if (walk_state->deferred_node) {
265
266
/* This name is already in the namespace, get the node */
267
268
node = walk_state->deferred_node;
269
status = AE_OK;
270
break;
271
}
272
273
/*
274
* If we are executing a method, do not create any namespace objects
275
* during the load phase, only during execution.
276
*/
277
if (walk_state->method_node) {
278
node = NULL;
279
status = AE_OK;
280
break;
281
}
282
283
flags = ACPI_NS_NO_UPSEARCH;
284
if ((walk_state->opcode != AML_SCOPE_OP) &&
285
(!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
286
flags |= ACPI_NS_ERROR_IF_FOUND;
287
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
288
"[%s] Cannot already exist\n",
289
acpi_ut_get_type_name(object_type)));
290
} else {
291
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
292
"[%s] Both Find or Create allowed\n",
293
acpi_ut_get_type_name(object_type)));
294
}
295
296
/*
297
* Enter the named type into the internal namespace. We enter the name
298
* as we go downward in the parse tree. Any necessary subobjects that
299
* involve arguments to the opcode must be created as we go back up the
300
* parse tree later.
301
*/
302
status =
303
acpi_ns_lookup(walk_state->scope_info, path, object_type,
304
ACPI_IMODE_LOAD_PASS1, flags, walk_state,
305
&node);
306
if (ACPI_FAILURE(status)) {
307
if (status == AE_ALREADY_EXISTS) {
308
309
/* The name already exists in this scope */
310
311
if (node->flags & ANOBJ_IS_EXTERNAL) {
312
/*
313
* Allow one create on an object or segment that was
314
* previously declared External
315
*/
316
node->flags &= ~ANOBJ_IS_EXTERNAL;
317
node->type = (u8) object_type;
318
319
/* Just retyped a node, probably will need to open a scope */
320
321
if (acpi_ns_opens_scope(object_type)) {
322
status =
323
acpi_ds_scope_stack_push
324
(node, object_type,
325
walk_state);
326
if (ACPI_FAILURE(status)) {
327
return_ACPI_STATUS
328
(status);
329
}
330
}
331
332
status = AE_OK;
333
}
334
}
335
336
if (ACPI_FAILURE(status)) {
337
ACPI_ERROR_NAMESPACE(path, status);
338
return_ACPI_STATUS(status);
339
}
340
}
341
break;
342
}
343
344
/* Common exit */
345
346
if (!op) {
347
348
/* Create a new op */
349
350
op = acpi_ps_alloc_op(walk_state->opcode);
351
if (!op) {
352
return_ACPI_STATUS(AE_NO_MEMORY);
353
}
354
}
355
356
/* Initialize the op */
357
358
#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY))
359
op->named.path = ACPI_CAST_PTR(u8, path);
360
#endif
361
362
if (node) {
363
/*
364
* Put the Node in the "op" object that the parser uses, so we
365
* can get it again quickly when this scope is closed
366
*/
367
op->common.node = node;
368
op->named.name = node->name.integer;
369
}
370
371
acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state),
372
op);
373
*out_op = op;
374
return_ACPI_STATUS(status);
375
}
376
377
/*******************************************************************************
378
*
379
* FUNCTION: acpi_ds_load1_end_op
380
*
381
* PARAMETERS: walk_state - Current state of the parse tree walk
382
*
383
* RETURN: Status
384
*
385
* DESCRIPTION: Ascending callback used during the loading of the namespace,
386
* both control methods and everything else.
387
*
388
******************************************************************************/
389
390
acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
391
{
392
union acpi_parse_object *op;
393
acpi_object_type object_type;
394
acpi_status status = AE_OK;
395
396
ACPI_FUNCTION_TRACE(ds_load1_end_op);
397
398
op = walk_state->op;
399
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
400
walk_state));
401
402
/* We are only interested in opcodes that have an associated name */
403
404
if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {
405
return_ACPI_STATUS(AE_OK);
406
}
407
408
/* Get the object type to determine if we should pop the scope */
409
410
object_type = walk_state->op_info->object_type;
411
412
#ifndef ACPI_NO_METHOD_EXECUTION
413
if (walk_state->op_info->flags & AML_FIELD) {
414
/*
415
* If we are executing a method, do not create any namespace objects
416
* during the load phase, only during execution.
417
*/
418
if (!walk_state->method_node) {
419
if (walk_state->opcode == AML_FIELD_OP ||
420
walk_state->opcode == AML_BANK_FIELD_OP ||
421
walk_state->opcode == AML_INDEX_FIELD_OP) {
422
status =
423
acpi_ds_init_field_objects(op, walk_state);
424
}
425
}
426
return_ACPI_STATUS(status);
427
}
428
429
/*
430
* If we are executing a method, do not create any namespace objects
431
* during the load phase, only during execution.
432
*/
433
if (!walk_state->method_node) {
434
if (op->common.aml_opcode == AML_REGION_OP) {
435
status =
436
acpi_ex_create_region(op->named.data,
437
op->named.length,
438
(acpi_adr_space_type) ((op->
439
common.
440
value.
441
arg)->
442
common.
443
value.
444
integer),
445
walk_state);
446
if (ACPI_FAILURE(status)) {
447
return_ACPI_STATUS(status);
448
}
449
} else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
450
status =
451
acpi_ex_create_region(op->named.data,
452
op->named.length,
453
ACPI_ADR_SPACE_DATA_TABLE,
454
walk_state);
455
if (ACPI_FAILURE(status)) {
456
return_ACPI_STATUS(status);
457
}
458
}
459
}
460
#endif
461
462
if (op->common.aml_opcode == AML_NAME_OP) {
463
464
/* For Name opcode, get the object type from the argument */
465
466
if (op->common.value.arg) {
467
object_type = (acpi_ps_get_opcode_info((op->common.
468
value.arg)->
469
common.
470
aml_opcode))->
471
object_type;
472
473
/* Set node type if we have a namespace node */
474
475
if (op->common.node) {
476
op->common.node->type = (u8) object_type;
477
}
478
}
479
}
480
481
/*
482
* If we are executing a method, do not create any namespace objects
483
* during the load phase, only during execution.
484
*/
485
if (!walk_state->method_node) {
486
if (op->common.aml_opcode == AML_METHOD_OP) {
487
/*
488
* method_op pkg_length name_string method_flags term_list
489
*
490
* Note: We must create the method node/object pair as soon as we
491
* see the method declaration. This allows later pass1 parsing
492
* of invocations of the method (need to know the number of
493
* arguments.)
494
*/
495
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
496
"LOADING-Method: State=%p Op=%p NamedObj=%p\n",
497
walk_state, op, op->named.node));
498
499
if (!acpi_ns_get_attached_object(op->named.node)) {
500
walk_state->operands[0] =
501
ACPI_CAST_PTR(void, op->named.node);
502
walk_state->num_operands = 1;
503
504
status =
505
acpi_ds_create_operands(walk_state,
506
op->common.value.
507
arg);
508
if (ACPI_SUCCESS(status)) {
509
status =
510
acpi_ex_create_method(op->named.
511
data,
512
op->named.
513
length,
514
walk_state);
515
}
516
517
walk_state->operands[0] = NULL;
518
walk_state->num_operands = 0;
519
520
if (ACPI_FAILURE(status)) {
521
return_ACPI_STATUS(status);
522
}
523
}
524
}
525
}
526
527
/* Pop the scope stack (only if loading a table) */
528
529
if (!walk_state->method_node && acpi_ns_opens_scope(object_type)) {
530
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
531
"(%s): Popping scope for Op %p\n",
532
acpi_ut_get_type_name(object_type), op));
533
534
status = acpi_ds_scope_stack_pop(walk_state);
535
}
536
537
return_ACPI_STATUS(status);
538
}
539
540