Rev 1498 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1498 | serge | 1 | /****************************************************************************** |
2 | * |
||
3 | * Module Name: dmrestag - Add tags to resource descriptors (Application-level) |
||
4 | * |
||
5 | *****************************************************************************/ |
||
6 | |||
7 | /****************************************************************************** |
||
8 | * |
||
9 | * 1. Copyright Notice |
||
10 | * |
||
2216 | Serge | 11 | * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
1498 | serge | 12 | * All rights reserved. |
13 | * |
||
14 | * 2. License |
||
15 | * |
||
16 | * 2.1. This is your license from Intel Corp. under its intellectual property |
||
17 | * rights. You may have additional license terms from the party that provided |
||
18 | * you this software, covering your right to use that party's intellectual |
||
19 | * property rights. |
||
20 | * |
||
21 | * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
||
22 | * copy of the source code appearing in this file ("Covered Code") an |
||
23 | * irrevocable, perpetual, worldwide license under Intel's copyrights in the |
||
24 | * base code distributed originally by Intel ("Original Intel Code") to copy, |
||
25 | * make derivatives, distribute, use and display any portion of the Covered |
||
26 | * Code in any form, with the right to sublicense such rights; and |
||
27 | * |
||
28 | * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
||
29 | * license (with the right to sublicense), under only those claims of Intel |
||
30 | * patents that are infringed by the Original Intel Code, to make, use, sell, |
||
31 | * offer to sell, and import the Covered Code and derivative works thereof |
||
32 | * solely to the minimum extent necessary to exercise the above copyright |
||
33 | * license, and in no event shall the patent license extend to any additions |
||
34 | * to or modifications of the Original Intel Code. No other license or right |
||
35 | * is granted directly or by implication, estoppel or otherwise; |
||
36 | * |
||
37 | * The above copyright and patent license is granted only if the following |
||
38 | * conditions are met: |
||
39 | * |
||
40 | * 3. Conditions |
||
41 | * |
||
42 | * 3.1. Redistribution of Source with Rights to Further Distribute Source. |
||
43 | * Redistribution of source code of any substantial portion of the Covered |
||
44 | * Code or modification with rights to further distribute source must include |
||
45 | * the above Copyright Notice, the above License, this list of Conditions, |
||
46 | * and the following Disclaimer and Export Compliance provision. In addition, |
||
47 | * Licensee must cause all Covered Code to which Licensee contributes to |
||
48 | * contain a file documenting the changes Licensee made to create that Covered |
||
49 | * Code and the date of any change. Licensee must include in that file the |
||
50 | * documentation of any changes made by any predecessor Licensee. Licensee |
||
51 | * must include a prominent statement that the modification is derived, |
||
52 | * directly or indirectly, from Original Intel Code. |
||
53 | * |
||
54 | * 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
||
55 | * Redistribution of source code of any substantial portion of the Covered |
||
56 | * Code or modification without rights to further distribute source must |
||
57 | * include the following Disclaimer and Export Compliance provision in the |
||
58 | * documentation and/or other materials provided with distribution. In |
||
59 | * addition, Licensee may not authorize further sublicense of source of any |
||
60 | * portion of the Covered Code, and must include terms to the effect that the |
||
61 | * license from Licensee to its licensee is limited to the intellectual |
||
62 | * property embodied in the software Licensee provides to its licensee, and |
||
63 | * not to intellectual property embodied in modifications its licensee may |
||
64 | * make. |
||
65 | * |
||
66 | * 3.3. Redistribution of Executable. Redistribution in executable form of any |
||
67 | * substantial portion of the Covered Code or modification must reproduce the |
||
68 | * above Copyright Notice, and the following Disclaimer and Export Compliance |
||
69 | * provision in the documentation and/or other materials provided with the |
||
70 | * distribution. |
||
71 | * |
||
72 | * 3.4. Intel retains all right, title, and interest in and to the Original |
||
73 | * Intel Code. |
||
74 | * |
||
75 | * 3.5. Neither the name Intel nor any other trademark owned or controlled by |
||
76 | * Intel shall be used in advertising or otherwise to promote the sale, use or |
||
77 | * other dealings in products derived from or relating to the Covered Code |
||
78 | * without prior written authorization from Intel. |
||
79 | * |
||
80 | * 4. Disclaimer and Export Compliance |
||
81 | * |
||
82 | * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
||
83 | * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
||
84 | * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
||
85 | * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
||
86 | * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
||
87 | * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
||
88 | * PARTICULAR PURPOSE. |
||
89 | * |
||
90 | * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
||
91 | * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
||
92 | * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
||
93 | * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
||
94 | * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
||
95 | * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
||
96 | * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
||
97 | * LIMITED REMEDY. |
||
98 | * |
||
99 | * 4.3. Licensee shall not export, either directly or indirectly, any of this |
||
100 | * software or system incorporating such software without first obtaining any |
||
101 | * required license or other approval from the U. S. Department of Commerce or |
||
102 | * any other agency or department of the United States Government. In the |
||
103 | * event Licensee exports any such software from the United States or |
||
104 | * re-exports any such software from a foreign destination, Licensee shall |
||
105 | * ensure that the distribution and export/re-export of the software is in |
||
106 | * compliance with all laws, regulations, orders, or other restrictions of the |
||
107 | * U.S. Export Administration Regulations. Licensee agrees that neither it nor |
||
108 | * any of its subsidiaries will export/re-export any technical data, process, |
||
109 | * software, or service, directly or indirectly, to any country for which the |
||
110 | * United States government or any agency thereof requires an export license, |
||
111 | * other governmental approval, or letter of assurance, without first obtaining |
||
112 | * such license, approval or letter. |
||
113 | * |
||
114 | *****************************************************************************/ |
||
115 | |||
116 | |||
117 | #include "acpi.h" |
||
118 | #include "accommon.h" |
||
119 | #include "acparser.h" |
||
120 | #include "acdisasm.h" |
||
121 | #include "acnamesp.h" |
||
122 | #include "amlcode.h" |
||
123 | |||
124 | /* This module used for application-level code only */ |
||
125 | |||
126 | #define _COMPONENT ACPI_CA_DISASSEMBLER |
||
127 | ACPI_MODULE_NAME ("dmrestag") |
||
128 | |||
129 | /* Local prototypes */ |
||
130 | |||
131 | static void |
||
132 | AcpiDmUpdateResourceName ( |
||
133 | ACPI_NAMESPACE_NODE *ResourceNode); |
||
134 | |||
135 | static char * |
||
136 | AcpiDmSearchTagList ( |
||
137 | UINT32 BitIndex, |
||
138 | ACPI_RESOURCE_TAG *TagList); |
||
139 | |||
140 | static char * |
||
141 | AcpiDmGetResourceTag ( |
||
142 | UINT32 BitIndex, |
||
143 | AML_RESOURCE *Resource, |
||
144 | UINT8 ResourceIndex); |
||
145 | |||
146 | static char * |
||
147 | AcpiGetTagPathname ( |
||
148 | ACPI_NAMESPACE_NODE *BufferNode, |
||
149 | ACPI_NAMESPACE_NODE *ResourceNode, |
||
150 | UINT32 BitIndex); |
||
151 | |||
152 | static ACPI_NAMESPACE_NODE * |
||
153 | AcpiDmGetResourceNode ( |
||
154 | ACPI_NAMESPACE_NODE *BufferNode, |
||
155 | UINT32 BitIndex); |
||
156 | |||
157 | static ACPI_STATUS |
||
158 | AcpiDmAddResourceToNamespace ( |
||
159 | UINT8 *Aml, |
||
160 | UINT32 Length, |
||
161 | UINT32 Offset, |
||
162 | UINT8 ResourceIndex, |
||
163 | void *Context); |
||
164 | |||
165 | static void |
||
166 | AcpiDmAddResourcesToNamespace ( |
||
167 | ACPI_NAMESPACE_NODE *BufferNode, |
||
168 | ACPI_PARSE_OBJECT *Op); |
||
169 | |||
170 | |||
171 | /****************************************************************************** |
||
172 | * |
||
173 | * Resource Tag tables |
||
174 | * |
||
175 | * These are the predefined tags that refer to elements of a resource |
||
176 | * descriptor. Each name and offset is defined in the ACPI specification. |
||
177 | * |
||
178 | * Each table entry contains the bit offset of the field and the associated |
||
179 | * name. |
||
180 | * |
||
181 | ******************************************************************************/ |
||
182 | |||
183 | static ACPI_RESOURCE_TAG AcpiDmIrqTags[] = |
||
184 | { |
||
185 | {( 1 * 8), ACPI_RESTAG_INTERRUPT}, |
||
186 | {( 3 * 8) + 0, ACPI_RESTAG_INTERRUPTTYPE}, |
||
187 | {( 3 * 8) + 3, ACPI_RESTAG_INTERRUPTLEVEL}, |
||
188 | {( 3 * 8) + 4, ACPI_RESTAG_INTERRUPTSHARE}, |
||
189 | {0, NULL} |
||
190 | }; |
||
191 | |||
192 | static ACPI_RESOURCE_TAG AcpiDmDmaTags[] = |
||
193 | { |
||
194 | {( 1 * 8), ACPI_RESTAG_DMA}, |
||
195 | {( 2 * 8) + 0, ACPI_RESTAG_XFERTYPE}, |
||
196 | {( 2 * 8) + 2, ACPI_RESTAG_BUSMASTER}, |
||
197 | {( 2 * 8) + 5, ACPI_RESTAG_DMATYPE}, |
||
198 | {0, NULL} |
||
199 | }; |
||
200 | |||
201 | static ACPI_RESOURCE_TAG AcpiDmIoTags[] = |
||
202 | { |
||
203 | {( 1 * 8) + 0, ACPI_RESTAG_DECODE}, |
||
204 | {( 2 * 8), ACPI_RESTAG_MINADDR}, |
||
205 | {( 4 * 8), ACPI_RESTAG_MAXADDR}, |
||
206 | {( 6 * 8), ACPI_RESTAG_ALIGNMENT}, |
||
207 | {( 7 * 8), ACPI_RESTAG_LENGTH}, |
||
208 | {0, NULL} |
||
209 | }; |
||
210 | |||
211 | static ACPI_RESOURCE_TAG AcpiDmFixedIoTags[] = |
||
212 | { |
||
213 | {( 1 * 8), ACPI_RESTAG_BASEADDRESS}, |
||
214 | {( 3 * 8), ACPI_RESTAG_LENGTH}, |
||
215 | {0, NULL} |
||
216 | }; |
||
217 | |||
218 | static ACPI_RESOURCE_TAG AcpiDmMemory24Tags[] = |
||
219 | { |
||
220 | {( 3 * 8) + 0, ACPI_RESTAG_READWRITETYPE}, |
||
221 | {( 4 * 8), ACPI_RESTAG_MINADDR}, |
||
222 | {( 6 * 8), ACPI_RESTAG_MAXADDR}, |
||
223 | {( 8 * 8), ACPI_RESTAG_ALIGNMENT}, |
||
224 | {(10 * 8), ACPI_RESTAG_LENGTH}, |
||
225 | {0, NULL} |
||
226 | }; |
||
227 | |||
228 | static ACPI_RESOURCE_TAG AcpiDmRegisterTags[] = |
||
229 | { |
||
230 | {( 3 * 8), ACPI_RESTAG_ADDRESSSPACE}, |
||
231 | {( 4 * 8), ACPI_RESTAG_REGISTERBITWIDTH}, |
||
232 | {( 5 * 8), ACPI_RESTAG_REGISTERBITOFFSET}, |
||
233 | {( 6 * 8), ACPI_RESTAG_ACCESSSIZE}, |
||
234 | {( 7 * 8), ACPI_RESTAG_ADDRESS}, |
||
235 | {0, NULL} |
||
236 | }; |
||
237 | |||
238 | static ACPI_RESOURCE_TAG AcpiDmMemory32Tags[] = |
||
239 | { |
||
240 | {( 3 * 8) + 0, ACPI_RESTAG_READWRITETYPE}, |
||
241 | {( 4 * 8), ACPI_RESTAG_MINADDR}, |
||
242 | {( 8 * 8), ACPI_RESTAG_MAXADDR}, |
||
243 | {(12 * 8), ACPI_RESTAG_ALIGNMENT}, |
||
244 | {(16 * 8), ACPI_RESTAG_LENGTH}, |
||
245 | {0, NULL} |
||
246 | }; |
||
247 | |||
248 | static ACPI_RESOURCE_TAG AcpiDmFixedMemory32Tags[] = |
||
249 | { |
||
250 | {( 3 * 8) + 0, ACPI_RESTAG_READWRITETYPE}, |
||
251 | {( 4 * 8), ACPI_RESTAG_BASEADDRESS}, |
||
252 | {( 8 * 8), ACPI_RESTAG_LENGTH}, |
||
253 | {0, NULL} |
||
254 | }; |
||
255 | |||
256 | static ACPI_RESOURCE_TAG AcpiDmInterruptTags[] = |
||
257 | { |
||
258 | {( 3 * 8) + 1, ACPI_RESTAG_INTERRUPTTYPE}, |
||
259 | {( 3 * 8) + 2, ACPI_RESTAG_INTERRUPTLEVEL}, |
||
260 | {( 3 * 8) + 3, ACPI_RESTAG_INTERRUPTSHARE}, |
||
261 | {( 5 * 8), ACPI_RESTAG_INTERRUPT}, |
||
262 | {0, NULL} |
||
263 | }; |
||
264 | |||
265 | static ACPI_RESOURCE_TAG AcpiDmAddress16Tags[] = |
||
266 | { |
||
267 | {( 4 * 8) + 1, ACPI_RESTAG_DECODE}, |
||
268 | {( 4 * 8) + 2, ACPI_RESTAG_MINTYPE}, |
||
269 | {( 4 * 8) + 3, ACPI_RESTAG_MAXTYPE}, |
||
270 | {( 6 * 8), ACPI_RESTAG_GRANULARITY}, |
||
271 | {( 8 * 8), ACPI_RESTAG_MINADDR}, |
||
272 | {(10 * 8), ACPI_RESTAG_MAXADDR}, |
||
273 | {(12 * 8), ACPI_RESTAG_TRANSLATION}, |
||
274 | {(14 * 8), ACPI_RESTAG_LENGTH}, |
||
275 | {0, NULL} |
||
276 | }; |
||
277 | |||
278 | static ACPI_RESOURCE_TAG AcpiDmAddress32Tags[] = |
||
279 | { |
||
280 | {( 4 * 8) + 1, ACPI_RESTAG_DECODE}, |
||
281 | {( 4 * 8) + 2, ACPI_RESTAG_MINTYPE}, |
||
282 | {( 4 * 8) + 3, ACPI_RESTAG_MAXTYPE}, |
||
283 | {( 6 * 8), ACPI_RESTAG_GRANULARITY}, |
||
284 | {(10 * 8), ACPI_RESTAG_MINADDR}, |
||
285 | {(14 * 8), ACPI_RESTAG_MAXADDR}, |
||
286 | {(18 * 8), ACPI_RESTAG_TRANSLATION}, |
||
287 | {(22 * 8), ACPI_RESTAG_LENGTH}, |
||
288 | {0, NULL} |
||
289 | }; |
||
290 | |||
291 | static ACPI_RESOURCE_TAG AcpiDmAddress64Tags[] = |
||
292 | { |
||
293 | {( 4 * 8) + 1, ACPI_RESTAG_DECODE}, |
||
294 | {( 4 * 8) + 2, ACPI_RESTAG_MINTYPE}, |
||
295 | {( 4 * 8) + 3, ACPI_RESTAG_MAXTYPE}, |
||
296 | {( 6 * 8), ACPI_RESTAG_GRANULARITY}, |
||
297 | {(14 * 8), ACPI_RESTAG_MINADDR}, |
||
298 | {(22 * 8), ACPI_RESTAG_MAXADDR}, |
||
299 | {(30 * 8), ACPI_RESTAG_TRANSLATION}, |
||
300 | {(38 * 8), ACPI_RESTAG_LENGTH}, |
||
301 | {0, NULL} |
||
302 | }; |
||
303 | |||
304 | static ACPI_RESOURCE_TAG AcpiDmExtendedAddressTags[] = |
||
305 | { |
||
306 | {( 4 * 8) + 1, ACPI_RESTAG_DECODE}, |
||
307 | {( 4 * 8) + 2, ACPI_RESTAG_MINTYPE}, |
||
308 | {( 4 * 8) + 3, ACPI_RESTAG_MAXTYPE}, |
||
309 | {( 8 * 8), ACPI_RESTAG_GRANULARITY}, |
||
310 | {(16 * 8), ACPI_RESTAG_MINADDR}, |
||
311 | {(24 * 8), ACPI_RESTAG_MAXADDR}, |
||
312 | {(32 * 8), ACPI_RESTAG_TRANSLATION}, |
||
313 | {(40 * 8), ACPI_RESTAG_LENGTH}, |
||
314 | {(48 * 8), ACPI_RESTAG_TYPESPECIFICATTRIBUTES}, |
||
315 | {0, NULL} |
||
316 | }; |
||
317 | |||
318 | /* Special-case tables for the type-specific flags */ |
||
319 | |||
320 | static ACPI_RESOURCE_TAG AcpiDmMemoryFlagTags[] = |
||
321 | { |
||
322 | {( 5 * 8) + 0, ACPI_RESTAG_READWRITETYPE}, |
||
323 | {( 5 * 8) + 1, ACPI_RESTAG_MEMTYPE}, |
||
324 | {( 5 * 8) + 3, ACPI_RESTAG_MEMATTRIBUTES}, |
||
325 | {( 5 * 8) + 5, ACPI_RESTAG_TYPE}, |
||
326 | {0, NULL} |
||
327 | }; |
||
328 | |||
329 | static ACPI_RESOURCE_TAG AcpiDmIoFlagTags[] = |
||
330 | { |
||
331 | {( 5 * 8) + 0, ACPI_RESTAG_RANGETYPE}, |
||
332 | {( 5 * 8) + 4, ACPI_RESTAG_TYPE}, |
||
333 | {( 5 * 8) + 5, ACPI_RESTAG_TRANSTYPE}, |
||
334 | {0, NULL} |
||
335 | }; |
||
336 | |||
337 | |||
338 | /* Dispatch table used to obtain the correct tag table for a descriptor */ |
||
339 | |||
340 | static ACPI_RESOURCE_TAG *AcpiGbl_ResourceTags [] = |
||
341 | { |
||
342 | /* Small descriptors */ |
||
343 | |||
344 | NULL, /* 0x00, Reserved */ |
||
345 | NULL, /* 0x01, Reserved */ |
||
346 | NULL, /* 0x02, Reserved */ |
||
347 | NULL, /* 0x03, Reserved */ |
||
348 | AcpiDmIrqTags, /* 0x04, ACPI_RESOURCE_NAME_IRQ_FORMAT */ |
||
349 | AcpiDmDmaTags, /* 0x05, ACPI_RESOURCE_NAME_DMA_FORMAT */ |
||
350 | NULL, /* 0x06, ACPI_RESOURCE_NAME_START_DEPENDENT */ |
||
351 | NULL, /* 0x07, ACPI_RESOURCE_NAME_END_DEPENDENT */ |
||
352 | AcpiDmIoTags, /* 0x08, ACPI_RESOURCE_NAME_IO_PORT */ |
||
353 | AcpiDmFixedIoTags, /* 0x09, ACPI_RESOURCE_NAME_FIXED_IO_PORT */ |
||
354 | NULL, /* 0x0A, Reserved */ |
||
355 | NULL, /* 0x0B, Reserved */ |
||
356 | NULL, /* 0x0C, Reserved */ |
||
357 | NULL, /* 0x0D, Reserved */ |
||
358 | NULL, /* 0x0E, ACPI_RESOURCE_NAME_SMALL_VENDOR */ |
||
359 | NULL, /* 0x0F, ACPI_RESOURCE_NAME_END_TAG (not used) */ |
||
360 | |||
361 | /* Large descriptors */ |
||
362 | |||
363 | NULL, /* 0x00, Reserved */ |
||
364 | AcpiDmMemory24Tags, /* 0x01, ACPI_RESOURCE_NAME_MEMORY_24 */ |
||
365 | AcpiDmRegisterTags, /* 0x02, ACPI_RESOURCE_NAME_GENERIC_REGISTER */ |
||
366 | NULL, /* 0x03, Reserved */ |
||
367 | NULL, /* 0x04, ACPI_RESOURCE_NAME_LARGE_VENDOR */ |
||
368 | AcpiDmMemory32Tags, /* 0x05, ACPI_RESOURCE_NAME_MEMORY_32 */ |
||
369 | AcpiDmFixedMemory32Tags, /* 0x06, ACPI_RESOURCE_NAME_FIXED_MEMORY_32 */ |
||
370 | AcpiDmAddress32Tags, /* 0x07, ACPI_RESOURCE_NAME_DWORD_ADDRESS_SPACE */ |
||
371 | AcpiDmAddress16Tags, /* 0x08, ACPI_RESOURCE_NAME_WORD_ADDRESS_SPACE */ |
||
372 | AcpiDmInterruptTags, /* 0x09, ACPI_RESOURCE_NAME_EXTENDED_XRUPT */ |
||
373 | AcpiDmAddress64Tags, /* 0x0A, ACPI_RESOURCE_NAME_QWORD_ADDRESS_SPACE */ |
||
374 | AcpiDmExtendedAddressTags /* 0x0B, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS_SPACE */ |
||
375 | }; |
||
376 | |||
377 | |||
378 | /* |
||
379 | * Globals used to generate unique resource descriptor names. We use names that |
||
380 | * start with underscore and a prefix letter that is not used by other ACPI |
||
381 | * reserved names. To this, we append hex 0x00 through 0xFF. These 5 prefixes |
||
382 | * allow for 5*256 = 1280 unique names, probably sufficient for any single ASL |
||
383 | * file. If this becomes too small, we can use alpha+numerals for a total |
||
384 | * of 5*36*36 = 6480. |
||
385 | */ |
||
386 | #define ACPI_NUM_RES_PREFIX 5 |
||
387 | |||
388 | static UINT32 AcpiGbl_NextResourceId = 0; |
||
389 | static UINT8 AcpiGbl_NextPrefix = 0; |
||
390 | static char AcpiGbl_Prefix[ACPI_NUM_RES_PREFIX] = |
||
391 | {'Y','Z','J','K','X'}; |
||
392 | |||
393 | |||
394 | /******************************************************************************* |
||
395 | * |
||
396 | * FUNCTION: AcpiDmCheckResourceReference |
||
397 | * |
||
398 | * PARAMETERS: Op - Parse Op for the AML opcode |
||
399 | * WalkState - Current walk state (with valid scope) |
||
400 | * |
||
401 | * RETURN: None |
||
402 | * |
||
403 | * DESCRIPTION: Convert a reference to a resource descriptor to a symbolic |
||
404 | * reference if possible |
||
405 | * |
||
406 | * NOTE: Bit index is used to transparently handle both resource bit |
||
407 | * fields and byte fields. |
||
408 | * |
||
409 | ******************************************************************************/ |
||
410 | |||
411 | void |
||
412 | AcpiDmCheckResourceReference ( |
||
413 | ACPI_PARSE_OBJECT *Op, |
||
414 | ACPI_WALK_STATE *WalkState) |
||
415 | { |
||
416 | ACPI_STATUS Status; |
||
417 | ACPI_PARSE_OBJECT *BufferNameOp; |
||
418 | ACPI_PARSE_OBJECT *IndexOp; |
||
419 | ACPI_NAMESPACE_NODE *BufferNode; |
||
420 | ACPI_NAMESPACE_NODE *ResourceNode; |
||
421 | const ACPI_OPCODE_INFO *OpInfo; |
||
422 | char *Pathname; |
||
423 | UINT32 BitIndex; |
||
424 | |||
425 | |||
426 | /* We are only interested in the CreateXxxxField opcodes */ |
||
427 | |||
428 | OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); |
||
429 | if (OpInfo->Type != AML_TYPE_CREATE_FIELD) |
||
430 | { |
||
431 | return; |
||
432 | } |
||
433 | |||
434 | /* Get the buffer term operand */ |
||
435 | |||
436 | BufferNameOp = AcpiPsGetDepthNext (NULL, Op); |
||
437 | |||
438 | /* Must be a named buffer, not an arg or local or method call */ |
||
439 | |||
440 | if (BufferNameOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP) |
||
441 | { |
||
442 | return; |
||
443 | } |
||
444 | |||
445 | /* Get the Index term, must be an integer constant to convert */ |
||
446 | |||
447 | IndexOp = BufferNameOp->Common.Next; |
||
448 | OpInfo = AcpiPsGetOpcodeInfo (IndexOp->Common.AmlOpcode); |
||
449 | if (OpInfo->ObjectType != ACPI_TYPE_INTEGER) |
||
450 | { |
||
451 | return; |
||
452 | } |
||
453 | |||
454 | /* Get the bit offset of the descriptor within the buffer */ |
||
455 | |||
456 | if ((Op->Common.AmlOpcode == AML_CREATE_BIT_FIELD_OP) || |
||
457 | (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP)) |
||
458 | { |
||
459 | /* Index operand is a bit offset */ |
||
460 | |||
461 | BitIndex = (UINT32) IndexOp->Common.Value.Integer; |
||
462 | } |
||
463 | else |
||
464 | { |
||
465 | /* Index operand is a byte offset, convert to bits */ |
||
466 | |||
467 | BitIndex = (UINT32) ACPI_MUL_8 (IndexOp->Common.Value.Integer); |
||
468 | } |
||
469 | |||
470 | /* Lookup the buffer in the namespace */ |
||
471 | |||
472 | Status = AcpiNsLookup (WalkState->ScopeInfo, |
||
473 | BufferNameOp->Common.Value.String, ACPI_TYPE_BUFFER, |
||
474 | ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, |
||
475 | &BufferNode); |
||
476 | if (ACPI_FAILURE (Status)) |
||
477 | { |
||
478 | return; |
||
479 | } |
||
480 | |||
481 | /* Validate object type, we must have a buffer */ |
||
482 | |||
483 | if (BufferNode->Type != ACPI_TYPE_BUFFER) |
||
484 | { |
||
485 | return; |
||
486 | } |
||
487 | |||
488 | /* Find the resource descriptor node corresponding to the index */ |
||
489 | |||
490 | ResourceNode = AcpiDmGetResourceNode (BufferNode, BitIndex); |
||
491 | if (!ResourceNode) |
||
492 | { |
||
493 | return; |
||
494 | } |
||
495 | |||
496 | /* Translate the Index to a resource tag pathname */ |
||
497 | |||
498 | Pathname = AcpiGetTagPathname (BufferNode, ResourceNode, BitIndex); |
||
499 | if (Pathname) |
||
500 | { |
||
501 | /* Complete the conversion of the Index to a symbol */ |
||
502 | |||
503 | IndexOp->Common.AmlOpcode = AML_INT_NAMEPATH_OP; |
||
504 | IndexOp->Common.Value.String = Pathname; |
||
505 | } |
||
506 | } |
||
507 | |||
508 | |||
509 | /******************************************************************************* |
||
510 | * |
||
511 | * FUNCTION: AcpiDmGetResourceNode |
||
512 | * |
||
513 | * PARAMETERS: BufferNode - Node for the parent buffer |
||
514 | * BitIndex - Index into the resource descriptor |
||
515 | * |
||
516 | * RETURN: Namespace node for the resource descriptor. NULL if not found |
||
517 | * |
||
518 | * DESCRIPTION: Find a resource descriptor that corresponds to the bit index |
||
519 | * |
||
520 | ******************************************************************************/ |
||
521 | |||
522 | static ACPI_NAMESPACE_NODE * |
||
523 | AcpiDmGetResourceNode ( |
||
524 | ACPI_NAMESPACE_NODE *BufferNode, |
||
525 | UINT32 BitIndex) |
||
526 | { |
||
527 | ACPI_NAMESPACE_NODE *Node; |
||
528 | UINT32 ByteIndex = ACPI_DIV_8 (BitIndex); |
||
529 | |||
530 | |||
531 | /* |
||
532 | * Child list contains an entry for each resource descriptor. Find |
||
533 | * the descriptor that corresponds to the Index. |
||
534 | * |
||
535 | * If there are no children, this is not a resource template |
||
536 | */ |
||
537 | Node = BufferNode->Child; |
||
538 | while (Node) |
||
539 | { |
||
540 | /* |
||
541 | * Check if the Index falls within this resource. |
||
542 | * |
||
543 | * Value contains the resource offset, Object contains the resource |
||
544 | * length (both in bytes) |
||
545 | */ |
||
546 | if ((ByteIndex >= Node->Value) && |
||
547 | (ByteIndex < (Node->Value + Node->Length))) |
||
548 | { |
||
549 | return (Node); |
||
550 | } |
||
551 | |||
552 | Node = Node->Peer; |
||
553 | } |
||
554 | |||
555 | return (NULL); |
||
556 | } |
||
557 | |||
558 | |||
559 | /******************************************************************************* |
||
560 | * |
||
561 | * FUNCTION: AcpiGetTagPathname |
||
562 | * |
||
563 | * PARAMETERS: BufferNode - Node for the parent buffer |
||
564 | * ResourceNode - Node for a resource descriptor |
||
565 | * BitIndex - Index into the resource descriptor |
||
566 | * |
||
567 | * RETURN: Full pathname for a resource tag. NULL if no match. |
||
568 | * Path is returned in AML (packed) format. |
||
569 | * |
||
570 | * DESCRIPTION: Convert a BitIndex into a symbolic resource tag (full pathname) |
||
571 | * |
||
572 | ******************************************************************************/ |
||
573 | |||
574 | static char * |
||
575 | AcpiGetTagPathname ( |
||
576 | ACPI_NAMESPACE_NODE *BufferNode, |
||
577 | ACPI_NAMESPACE_NODE *ResourceNode, |
||
578 | UINT32 BitIndex) |
||
579 | { |
||
580 | ACPI_STATUS Status; |
||
581 | UINT32 ResourceBitIndex; |
||
582 | UINT8 ResourceTableIndex; |
||
583 | ACPI_SIZE RequiredSize; |
||
584 | char *Pathname; |
||
585 | AML_RESOURCE *Aml; |
||
586 | ACPI_PARSE_OBJECT *Op; |
||
587 | char *InternalPath; |
||
588 | char *Tag; |
||
589 | |||
590 | |||
591 | /* Get the Op that contains the actual buffer data */ |
||
592 | |||
593 | Op = BufferNode->Op->Common.Value.Arg; |
||
594 | Op = Op->Common.Next; |
||
595 | if (!Op) |
||
596 | { |
||
597 | return (NULL); |
||
598 | } |
||
599 | |||
600 | /* Get the individual resource descriptor and validate it */ |
||
601 | |||
602 | Aml = ACPI_CAST_PTR (AML_RESOURCE, |
||
603 | &Op->Named.Data[ResourceNode->Value]); |
||
604 | |||
605 | Status = AcpiUtValidateResource (Aml, &ResourceTableIndex); |
||
606 | if (ACPI_FAILURE (Status)) |
||
607 | { |
||
608 | return (NULL); |
||
609 | } |
||
610 | |||
611 | /* Get offset into this descriptor (from offset into entire buffer) */ |
||
612 | |||
613 | ResourceBitIndex = BitIndex - ACPI_MUL_8 (ResourceNode->Value); |
||
614 | |||
615 | /* Get the tag associated with this resource descriptor and offset */ |
||
616 | |||
617 | Tag = AcpiDmGetResourceTag (ResourceBitIndex, Aml, ResourceTableIndex); |
||
618 | if (!Tag) |
||
619 | { |
||
620 | return (NULL); |
||
621 | } |
||
622 | |||
623 | /* |
||
624 | * Now that we know that we have a reference that can be converted to a |
||
625 | * symbol, change the name of the resource to a unique name. |
||
626 | */ |
||
627 | AcpiDmUpdateResourceName (ResourceNode); |
||
628 | |||
629 | /* Get the full pathname to the parent buffer */ |
||
630 | |||
631 | RequiredSize = AcpiNsGetPathnameLength (BufferNode); |
||
632 | if (!RequiredSize) |
||
633 | { |
||
634 | return (NULL); |
||
635 | } |
||
636 | |||
637 | Pathname = ACPI_ALLOCATE_ZEROED (RequiredSize + ACPI_PATH_SEGMENT_LENGTH); |
||
638 | if (!Pathname) |
||
639 | { |
||
640 | return (NULL); |
||
641 | } |
||
642 | |||
643 | Status = AcpiNsBuildExternalPath (BufferNode, RequiredSize, Pathname); |
||
644 | if (ACPI_FAILURE (Status)) |
||
645 | { |
||
646 | return (NULL); |
||
647 | } |
||
648 | |||
649 | /* |
||
650 | * Create the full path to the resource and tag by: remove the buffer name, |
||
651 | * append the resource descriptor name, append a dot, append the tag name. |
||
652 | * |
||
653 | * TBD: Always using the full path is a bit brute force, the path can be |
||
654 | * often be optimized with carats (if the original buffer namepath is a |
||
655 | * single nameseg). This doesn't really matter, because these paths do not |
||
656 | * end up in the final compiled AML, it's just an appearance issue for the |
||
657 | * disassembled code. |
||
658 | */ |
||
659 | Pathname[ACPI_STRLEN (Pathname) - ACPI_NAME_SIZE] = 0; |
||
660 | ACPI_STRNCAT (Pathname, ResourceNode->Name.Ascii, ACPI_NAME_SIZE); |
||
661 | ACPI_STRCAT (Pathname, "."); |
||
662 | ACPI_STRNCAT (Pathname, Tag, ACPI_NAME_SIZE); |
||
663 | |||
664 | /* Internalize the namepath to AML format */ |
||
665 | |||
666 | AcpiNsInternalizeName (Pathname, &InternalPath); |
||
667 | ACPI_FREE (Pathname); |
||
668 | return (InternalPath); |
||
669 | } |
||
670 | |||
671 | |||
672 | /******************************************************************************* |
||
673 | * |
||
674 | * FUNCTION: AcpiDmUpdateResourceName |
||
675 | * |
||
676 | * PARAMETERS: ResourceNode - Node for a resource descriptor |
||
677 | * |
||
678 | * RETURN: Stores new name in the ResourceNode |
||
679 | * |
||
680 | * DESCRIPTION: Create a new, unique name for a resource descriptor. Used by |
||
681 | * both the disassembly of the descriptor itself and any symbolic |
||
682 | * references to the descriptor. Ignored if a unique name has |
||
683 | * already been assigned to the resource. |
||
684 | * |
||
685 | * NOTE: Single threaded, suitable for applications only! |
||
686 | * |
||
687 | ******************************************************************************/ |
||
688 | |||
689 | static void |
||
690 | AcpiDmUpdateResourceName ( |
||
691 | ACPI_NAMESPACE_NODE *ResourceNode) |
||
692 | { |
||
693 | char Name[ACPI_NAME_SIZE]; |
||
694 | |||
695 | |||
696 | /* Ignore if a unique name has already been assigned */ |
||
697 | |||
698 | if (ResourceNode->Name.Integer != ACPI_DEFAULT_RESNAME) |
||
699 | { |
||
700 | return; |
||
701 | } |
||
702 | |||
703 | /* Generate a new ACPI name for the descriptor */ |
||
704 | |||
705 | Name[0] = '_'; |
||
706 | Name[1] = AcpiGbl_Prefix[AcpiGbl_NextPrefix]; |
||
2216 | Serge | 707 | Name[2] = AcpiUtHexToAsciiChar ((UINT64) AcpiGbl_NextResourceId, 4); |
708 | Name[3] = AcpiUtHexToAsciiChar ((UINT64) AcpiGbl_NextResourceId, 0); |
||
1498 | serge | 709 | |
710 | /* Update globals for next name */ |
||
711 | |||
712 | AcpiGbl_NextResourceId++; |
||
713 | if (AcpiGbl_NextResourceId >= 256) |
||
714 | { |
||
715 | AcpiGbl_NextResourceId = 0; |
||
716 | AcpiGbl_NextPrefix++; |
||
717 | if (AcpiGbl_NextPrefix > ACPI_NUM_RES_PREFIX) |
||
718 | { |
||
719 | AcpiGbl_NextPrefix = 0; |
||
720 | } |
||
721 | } |
||
722 | |||
723 | /* Change the resource descriptor name */ |
||
724 | |||
725 | ResourceNode->Name.Integer = *ACPI_CAST_PTR (UINT32, &Name[0]); |
||
726 | } |
||
727 | |||
728 | |||
729 | /******************************************************************************* |
||
730 | * |
||
731 | * FUNCTION: AcpiDmGetResourceTag |
||
732 | * |
||
733 | * PARAMETERS: BitIndex - Index into the resource descriptor |
||
734 | * Resource - Pointer to the raw resource data |
||
735 | * ResourceIndex - Index correspoinding to the resource type |
||
736 | * |
||
737 | * RETURN: Pointer to the resource tag (ACPI_NAME). NULL if no match. |
||
738 | * |
||
739 | * DESCRIPTION: Convert a BitIndex into a symbolic resource tag. |
||
740 | * |
||
741 | ******************************************************************************/ |
||
742 | |||
743 | static char * |
||
744 | AcpiDmGetResourceTag ( |
||
745 | UINT32 BitIndex, |
||
746 | AML_RESOURCE *Resource, |
||
747 | UINT8 ResourceIndex) |
||
748 | { |
||
749 | ACPI_RESOURCE_TAG *TagList; |
||
750 | char *Tag = NULL; |
||
751 | |||
752 | |||
753 | /* Get the tag list for this resource descriptor type */ |
||
754 | |||
755 | TagList = AcpiGbl_ResourceTags[ResourceIndex]; |
||
756 | if (!TagList) |
||
757 | { |
||
758 | /* There are no tags for this resource type */ |
||
759 | |||
760 | return (NULL); |
||
761 | } |
||
762 | |||
763 | /* |
||
764 | * Handle the type-specific flags field for the address descriptors. |
||
765 | * Kindof brute force, but just blindly search for an index match. |
||
766 | */ |
||
767 | switch (Resource->DescriptorType) |
||
768 | { |
||
769 | case ACPI_RESOURCE_NAME_ADDRESS16: |
||
770 | case ACPI_RESOURCE_NAME_ADDRESS32: |
||
771 | case ACPI_RESOURCE_NAME_ADDRESS64: |
||
772 | case ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64: |
||
773 | |||
774 | if (Resource->Address.ResourceType == ACPI_ADDRESS_TYPE_MEMORY_RANGE) |
||
775 | { |
||
776 | Tag = AcpiDmSearchTagList (BitIndex, AcpiDmMemoryFlagTags); |
||
777 | } |
||
778 | else if (Resource->Address.ResourceType == ACPI_ADDRESS_TYPE_IO_RANGE) |
||
779 | { |
||
780 | Tag = AcpiDmSearchTagList (BitIndex, AcpiDmIoFlagTags); |
||
781 | } |
||
782 | |||
783 | /* If we found a match, all done. Else, drop to normal search below */ |
||
784 | |||
785 | if (Tag) |
||
786 | { |
||
787 | return (Tag); |
||
788 | } |
||
789 | break; |
||
790 | |||
791 | default: |
||
792 | break; |
||
793 | } |
||
794 | |||
795 | /* Search the tag list for this descriptor type */ |
||
796 | |||
797 | Tag = AcpiDmSearchTagList (BitIndex, TagList); |
||
798 | return (Tag); |
||
799 | } |
||
800 | |||
801 | |||
802 | /******************************************************************************* |
||
803 | * |
||
804 | * FUNCTION: AcpiDmSearchTagList |
||
805 | * |
||
806 | * PARAMETERS: BitIndex - Index into the resource descriptor |
||
807 | * TagList - List to search |
||
808 | * |
||
809 | * RETURN: Pointer to a tag (ACPI_NAME). NULL if no match found. |
||
810 | * |
||
811 | * DESCRIPTION: Search a tag list for a match to the input BitIndex. Matches |
||
812 | * a fixed offset to a symbolic resource tag name. |
||
813 | * |
||
814 | ******************************************************************************/ |
||
815 | |||
816 | static char * |
||
817 | AcpiDmSearchTagList ( |
||
818 | UINT32 BitIndex, |
||
819 | ACPI_RESOURCE_TAG *TagList) |
||
820 | { |
||
821 | |||
822 | /* |
||
823 | * Walk the null-terminated tag list to find a matching bit offset. |
||
824 | * We are looking for an exact match. |
||
825 | */ |
||
826 | for ( ; TagList->Tag; TagList++) |
||
827 | { |
||
828 | if (BitIndex == TagList->BitIndex) |
||
829 | { |
||
830 | return (TagList->Tag); |
||
831 | } |
||
832 | } |
||
833 | |||
834 | /* A matching offset was not found */ |
||
835 | |||
836 | return (NULL); |
||
837 | } |
||
838 | |||
839 | |||
840 | /******************************************************************************* |
||
841 | * |
||
842 | * FUNCTION: AcpiDmFindResources |
||
843 | * |
||
844 | * PARAMETERS: Root - Root of the parse tree |
||
845 | * |
||
846 | * RETURN: None |
||
847 | * |
||
848 | * DESCRIPTION: Add all ResourceTemplate declarations to the namespace. Each |
||
849 | * resource descriptor in each template is given a node -- used |
||
850 | * for later conversion of resource references to symbolic refs. |
||
851 | * |
||
852 | ******************************************************************************/ |
||
853 | |||
854 | void |
||
855 | AcpiDmFindResources ( |
||
856 | ACPI_PARSE_OBJECT *Root) |
||
857 | { |
||
858 | ACPI_PARSE_OBJECT *Op = Root; |
||
859 | ACPI_PARSE_OBJECT *Parent; |
||
860 | |||
861 | |||
862 | /* Walk the entire parse tree */ |
||
863 | |||
864 | while (Op) |
||
865 | { |
||
866 | /* We are interested in Buffer() declarations */ |
||
867 | |||
868 | if (Op->Common.AmlOpcode == AML_BUFFER_OP) |
||
869 | { |
||
870 | /* And only declarations of the form Name (XXXX, Buffer()... ) */ |
||
871 | |||
872 | Parent = Op->Common.Parent; |
||
873 | if (Parent->Common.AmlOpcode == AML_NAME_OP) |
||
874 | { |
||
875 | /* |
||
876 | * If the buffer is a resource template, add the individual |
||
877 | * resource descriptors to the namespace, as children of the |
||
878 | * buffer node. |
||
879 | */ |
||
880 | if (ACPI_SUCCESS (AcpiDmIsResourceTemplate (Op))) |
||
881 | { |
||
882 | Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE; |
||
883 | AcpiDmAddResourcesToNamespace (Parent->Common.Node, Op); |
||
884 | } |
||
885 | } |
||
886 | } |
||
887 | |||
888 | Op = AcpiPsGetDepthNext (Root, Op); |
||
889 | } |
||
890 | } |
||
891 | |||
892 | |||
893 | /******************************************************************************* |
||
894 | * |
||
895 | * FUNCTION: AcpiDmAddResourcesToNamespace |
||
896 | * |
||
897 | * PARAMETERS: BufferNode - Node for the parent buffer |
||
898 | * Op - Parse op for the buffer |
||
899 | * |
||
900 | * RETURN: None |
||
901 | * |
||
902 | * DESCRIPTION: Add an entire resource template to the namespace. Each |
||
903 | * resource descriptor is added as a namespace node. |
||
904 | * |
||
905 | ******************************************************************************/ |
||
906 | |||
907 | static void |
||
908 | AcpiDmAddResourcesToNamespace ( |
||
909 | ACPI_NAMESPACE_NODE *BufferNode, |
||
910 | ACPI_PARSE_OBJECT *Op) |
||
911 | { |
||
912 | ACPI_PARSE_OBJECT *NextOp; |
||
913 | |||
914 | |||
915 | /* Get to the ByteData list */ |
||
916 | |||
917 | NextOp = Op->Common.Value.Arg; |
||
918 | NextOp = NextOp->Common.Next; |
||
919 | if (!NextOp) |
||
920 | { |
||
921 | return; |
||
922 | } |
||
923 | |||
924 | /* Set Node and Op to point to each other */ |
||
925 | |||
926 | BufferNode->Op = Op; |
||
927 | Op->Common.Node = BufferNode; |
||
928 | |||
929 | /* |
||
930 | * Insert each resource into the namespace |
||
931 | * NextOp contains the Aml pointer and the Aml length |
||
932 | */ |
||
933 | AcpiUtWalkAmlResources ((UINT8 *) NextOp->Named.Data, |
||
934 | (ACPI_SIZE) NextOp->Common.Value.Integer, |
||
935 | AcpiDmAddResourceToNamespace, BufferNode); |
||
936 | } |
||
937 | |||
938 | |||
939 | /******************************************************************************* |
||
940 | * |
||
941 | * FUNCTION: AcpiDmAddResourceToNamespace |
||
942 | * |
||
943 | * PARAMETERS: ACPI_WALK_AML_CALLBACK |
||
944 | * BufferNode - Node for the parent buffer |
||
945 | * |
||
946 | * RETURN: Status |
||
947 | * |
||
948 | * DESCRIPTION: Add one resource descriptor to the namespace as a child of the |
||
949 | * parent buffer. The same name is used for each descriptor. This |
||
950 | * is changed later to a unique name if the resource is actually |
||
951 | * referenced by an AML operator. |
||
952 | * |
||
953 | ******************************************************************************/ |
||
954 | |||
955 | static ACPI_STATUS |
||
956 | AcpiDmAddResourceToNamespace ( |
||
957 | UINT8 *Aml, |
||
958 | UINT32 Length, |
||
959 | UINT32 Offset, |
||
960 | UINT8 ResourceIndex, |
||
961 | void *Context) |
||
962 | { |
||
963 | ACPI_STATUS Status; |
||
964 | ACPI_GENERIC_STATE ScopeInfo; |
||
965 | ACPI_NAMESPACE_NODE *Node; |
||
966 | |||
967 | |||
968 | /* TBD: Don't need to add descriptors that have no tags defined? */ |
||
969 | |||
970 | /* Add the resource to the namespace, as child of the buffer */ |
||
971 | |||
972 | ScopeInfo.Scope.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Context); |
||
973 | Status = AcpiNsLookup (&ScopeInfo, "_TMP", ACPI_TYPE_LOCAL_RESOURCE, |
||
974 | ACPI_IMODE_LOAD_PASS2, |
||
975 | ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_PREFIX_IS_SCOPE, |
||
976 | NULL, &Node); |
||
977 | if (ACPI_FAILURE (Status)) |
||
978 | { |
||
979 | return (AE_OK); |
||
980 | } |
||
981 | |||
982 | /* Set the name to the default, changed later if resource is referenced */ |
||
983 | |||
984 | Node->Name.Integer = ACPI_DEFAULT_RESNAME; |
||
985 | |||
986 | /* Save the offset of the descriptor (within the original buffer) */ |
||
987 | |||
988 | Node->Value = Offset; |
||
989 | Node->Length = Length; |
||
990 | return (AE_OK); |
||
991 | }> |
||
992 |