1 | /******************************************************************************* |
2 | * |
3 | * Module Name: utresrc - Resource management utilities |
4 | * |
5 | ******************************************************************************/ |
6 | |
7 | /* |
8 | * Copyright (C) 2000 - 2016, 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.h" |
45 | #include "accommon.h" |
46 | #include "acresrc.h" |
47 | |
48 | |
49 | #define _COMPONENT ACPI_UTILITIES |
50 | ACPI_MODULE_NAME ("utresrc" ) |
51 | |
52 | |
53 | #if defined(ACPI_DEBUG_OUTPUT) || defined (ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) |
54 | |
55 | /* |
56 | * Strings used to decode resource descriptors. |
57 | * Used by both the disassembler and the debugger resource dump routines |
58 | */ |
59 | const char *AcpiGbl_BmDecode[] = |
60 | { |
61 | "NotBusMaster" , |
62 | "BusMaster" |
63 | }; |
64 | |
65 | const char *AcpiGbl_ConfigDecode[] = |
66 | { |
67 | "0 - Good Configuration" , |
68 | "1 - Acceptable Configuration" , |
69 | "2 - Suboptimal Configuration" , |
70 | "3 - ***Invalid Configuration***" , |
71 | }; |
72 | |
73 | const char *AcpiGbl_ConsumeDecode[] = |
74 | { |
75 | "ResourceProducer" , |
76 | "ResourceConsumer" |
77 | }; |
78 | |
79 | const char *AcpiGbl_DecDecode[] = |
80 | { |
81 | "PosDecode" , |
82 | "SubDecode" |
83 | }; |
84 | |
85 | const char *AcpiGbl_HeDecode[] = |
86 | { |
87 | "Level" , |
88 | "Edge" |
89 | }; |
90 | |
91 | const char *AcpiGbl_IoDecode[] = |
92 | { |
93 | "Decode10" , |
94 | "Decode16" |
95 | }; |
96 | |
97 | const char *AcpiGbl_LlDecode[] = |
98 | { |
99 | "ActiveHigh" , |
100 | "ActiveLow" , |
101 | "ActiveBoth" , |
102 | "Reserved" |
103 | }; |
104 | |
105 | const char *AcpiGbl_MaxDecode[] = |
106 | { |
107 | "MaxNotFixed" , |
108 | "MaxFixed" |
109 | }; |
110 | |
111 | const char *AcpiGbl_MemDecode[] = |
112 | { |
113 | "NonCacheable" , |
114 | "Cacheable" , |
115 | "WriteCombining" , |
116 | "Prefetchable" |
117 | }; |
118 | |
119 | const char *AcpiGbl_MinDecode[] = |
120 | { |
121 | "MinNotFixed" , |
122 | "MinFixed" |
123 | }; |
124 | |
125 | const char *AcpiGbl_MtpDecode[] = |
126 | { |
127 | "AddressRangeMemory" , |
128 | "AddressRangeReserved" , |
129 | "AddressRangeACPI" , |
130 | "AddressRangeNVS" |
131 | }; |
132 | |
133 | const char *AcpiGbl_RngDecode[] = |
134 | { |
135 | "InvalidRanges" , |
136 | "NonISAOnlyRanges" , |
137 | "ISAOnlyRanges" , |
138 | "EntireRange" |
139 | }; |
140 | |
141 | const char *AcpiGbl_RwDecode[] = |
142 | { |
143 | "ReadOnly" , |
144 | "ReadWrite" |
145 | }; |
146 | |
147 | const char *AcpiGbl_ShrDecode[] = |
148 | { |
149 | "Exclusive" , |
150 | "Shared" , |
151 | "ExclusiveAndWake" , /* ACPI 5.0 */ |
152 | "SharedAndWake" /* ACPI 5.0 */ |
153 | }; |
154 | |
155 | const char *AcpiGbl_SizDecode[] = |
156 | { |
157 | "Transfer8" , |
158 | "Transfer8_16" , |
159 | "Transfer16" , |
160 | "InvalidSize" |
161 | }; |
162 | |
163 | const char *AcpiGbl_TrsDecode[] = |
164 | { |
165 | "DenseTranslation" , |
166 | "SparseTranslation" |
167 | }; |
168 | |
169 | const char *AcpiGbl_TtpDecode[] = |
170 | { |
171 | "TypeStatic" , |
172 | "TypeTranslation" |
173 | }; |
174 | |
175 | const char *AcpiGbl_TypDecode[] = |
176 | { |
177 | "Compatibility" , |
178 | "TypeA" , |
179 | "TypeB" , |
180 | "TypeF" |
181 | }; |
182 | |
183 | const char *AcpiGbl_PpcDecode[] = |
184 | { |
185 | "PullDefault" , |
186 | "PullUp" , |
187 | "PullDown" , |
188 | "PullNone" |
189 | }; |
190 | |
191 | const char *AcpiGbl_IorDecode[] = |
192 | { |
193 | "IoRestrictionNone" , |
194 | "IoRestrictionInputOnly" , |
195 | "IoRestrictionOutputOnly" , |
196 | "IoRestrictionNoneAndPreserve" |
197 | }; |
198 | |
199 | const char *AcpiGbl_DtsDecode[] = |
200 | { |
201 | "Width8bit" , |
202 | "Width16bit" , |
203 | "Width32bit" , |
204 | "Width64bit" , |
205 | "Width128bit" , |
206 | "Width256bit" , |
207 | }; |
208 | |
209 | /* GPIO connection type */ |
210 | |
211 | const char *AcpiGbl_CtDecode[] = |
212 | { |
213 | "Interrupt" , |
214 | "I/O" |
215 | }; |
216 | |
217 | /* Serial bus type */ |
218 | |
219 | const char *AcpiGbl_SbtDecode[] = |
220 | { |
221 | "/* UNKNOWN serial bus type */" , |
222 | "I2C" , |
223 | "SPI" , |
224 | "UART" |
225 | }; |
226 | |
227 | /* I2C serial bus access mode */ |
228 | |
229 | const char *AcpiGbl_AmDecode[] = |
230 | { |
231 | "AddressingMode7Bit" , |
232 | "AddressingMode10Bit" |
233 | }; |
234 | |
235 | /* I2C serial bus slave mode */ |
236 | |
237 | const char *AcpiGbl_SmDecode[] = |
238 | { |
239 | "ControllerInitiated" , |
240 | "DeviceInitiated" |
241 | }; |
242 | |
243 | /* SPI serial bus wire mode */ |
244 | |
245 | const char *AcpiGbl_WmDecode[] = |
246 | { |
247 | "FourWireMode" , |
248 | "ThreeWireMode" |
249 | }; |
250 | |
251 | /* SPI serial clock phase */ |
252 | |
253 | const char *AcpiGbl_CphDecode[] = |
254 | { |
255 | "ClockPhaseFirst" , |
256 | "ClockPhaseSecond" |
257 | }; |
258 | |
259 | /* SPI serial bus clock polarity */ |
260 | |
261 | const char *AcpiGbl_CpoDecode[] = |
262 | { |
263 | "ClockPolarityLow" , |
264 | "ClockPolarityHigh" |
265 | }; |
266 | |
267 | /* SPI serial bus device polarity */ |
268 | |
269 | const char *AcpiGbl_DpDecode[] = |
270 | { |
271 | "PolarityLow" , |
272 | "PolarityHigh" |
273 | }; |
274 | |
275 | /* UART serial bus endian */ |
276 | |
277 | const char *AcpiGbl_EdDecode[] = |
278 | { |
279 | "LittleEndian" , |
280 | "BigEndian" |
281 | }; |
282 | |
283 | /* UART serial bus bits per byte */ |
284 | |
285 | const char *AcpiGbl_BpbDecode[] = |
286 | { |
287 | "DataBitsFive" , |
288 | "DataBitsSix" , |
289 | "DataBitsSeven" , |
290 | "DataBitsEight" , |
291 | "DataBitsNine" , |
292 | "/* UNKNOWN Bits per byte */" , |
293 | "/* UNKNOWN Bits per byte */" , |
294 | "/* UNKNOWN Bits per byte */" |
295 | }; |
296 | |
297 | /* UART serial bus stop bits */ |
298 | |
299 | const char *AcpiGbl_SbDecode[] = |
300 | { |
301 | "StopBitsZero" , |
302 | "StopBitsOne" , |
303 | "StopBitsOnePlusHalf" , |
304 | "StopBitsTwo" |
305 | }; |
306 | |
307 | /* UART serial bus flow control */ |
308 | |
309 | const char *AcpiGbl_FcDecode[] = |
310 | { |
311 | "FlowControlNone" , |
312 | "FlowControlHardware" , |
313 | "FlowControlXON" , |
314 | "/* UNKNOWN flow control keyword */" |
315 | }; |
316 | |
317 | /* UART serial bus parity type */ |
318 | |
319 | const char *AcpiGbl_PtDecode[] = |
320 | { |
321 | "ParityTypeNone" , |
322 | "ParityTypeEven" , |
323 | "ParityTypeOdd" , |
324 | "ParityTypeMark" , |
325 | "ParityTypeSpace" , |
326 | "/* UNKNOWN parity keyword */" , |
327 | "/* UNKNOWN parity keyword */" , |
328 | "/* UNKNOWN parity keyword */" |
329 | }; |
330 | |
331 | #endif |
332 | |
333 | |
334 | /* |
335 | * Base sizes of the raw AML resource descriptors, indexed by resource type. |
336 | * Zero indicates a reserved (and therefore invalid) resource type. |
337 | */ |
338 | const UINT8 AcpiGbl_ResourceAmlSizes[] = |
339 | { |
340 | /* Small descriptors */ |
341 | |
342 | 0, |
343 | 0, |
344 | 0, |
345 | 0, |
346 | ACPI_AML_SIZE_SMALL (AML_RESOURCE_IRQ), |
347 | ACPI_AML_SIZE_SMALL (AML_RESOURCE_DMA), |
348 | ACPI_AML_SIZE_SMALL (AML_RESOURCE_START_DEPENDENT), |
349 | ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_DEPENDENT), |
350 | ACPI_AML_SIZE_SMALL (AML_RESOURCE_IO), |
351 | ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_IO), |
352 | ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_DMA), |
353 | 0, |
354 | 0, |
355 | 0, |
356 | ACPI_AML_SIZE_SMALL (AML_RESOURCE_VENDOR_SMALL), |
357 | ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_TAG), |
358 | |
359 | /* Large descriptors */ |
360 | |
361 | 0, |
362 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY24), |
363 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_GENERIC_REGISTER), |
364 | 0, |
365 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_VENDOR_LARGE), |
366 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY32), |
367 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_FIXED_MEMORY32), |
368 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS32), |
369 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS16), |
370 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_IRQ), |
371 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS64), |
372 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_ADDRESS64), |
373 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_GPIO), |
374 | 0, |
375 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_COMMON_SERIALBUS), |
376 | }; |
377 | |
378 | const UINT8 AcpiGbl_ResourceAmlSerialBusSizes[] = |
379 | { |
380 | 0, |
381 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_I2C_SERIALBUS), |
382 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_SPI_SERIALBUS), |
383 | ACPI_AML_SIZE_LARGE (AML_RESOURCE_UART_SERIALBUS), |
384 | }; |
385 | |
386 | |
387 | /* |
388 | * Resource types, used to validate the resource length field. |
389 | * The length of fixed-length types must match exactly, variable |
390 | * lengths must meet the minimum required length, etc. |
391 | * Zero indicates a reserved (and therefore invalid) resource type. |
392 | */ |
393 | static const UINT8 AcpiGbl_ResourceTypes[] = |
394 | { |
395 | /* Small descriptors */ |
396 | |
397 | 0, |
398 | 0, |
399 | 0, |
400 | 0, |
401 | ACPI_SMALL_VARIABLE_LENGTH, /* 04 IRQ */ |
402 | ACPI_FIXED_LENGTH, /* 05 DMA */ |
403 | ACPI_SMALL_VARIABLE_LENGTH, /* 06 StartDependentFunctions */ |
404 | ACPI_FIXED_LENGTH, /* 07 EndDependentFunctions */ |
405 | ACPI_FIXED_LENGTH, /* 08 IO */ |
406 | ACPI_FIXED_LENGTH, /* 09 FixedIO */ |
407 | ACPI_FIXED_LENGTH, /* 0A FixedDMA */ |
408 | 0, |
409 | 0, |
410 | 0, |
411 | ACPI_VARIABLE_LENGTH, /* 0E VendorShort */ |
412 | ACPI_FIXED_LENGTH, /* 0F EndTag */ |
413 | |
414 | /* Large descriptors */ |
415 | |
416 | 0, |
417 | ACPI_FIXED_LENGTH, /* 01 Memory24 */ |
418 | ACPI_FIXED_LENGTH, /* 02 GenericRegister */ |
419 | 0, |
420 | ACPI_VARIABLE_LENGTH, /* 04 VendorLong */ |
421 | ACPI_FIXED_LENGTH, /* 05 Memory32 */ |
422 | ACPI_FIXED_LENGTH, /* 06 Memory32Fixed */ |
423 | ACPI_VARIABLE_LENGTH, /* 07 Dword* address */ |
424 | ACPI_VARIABLE_LENGTH, /* 08 Word* address */ |
425 | ACPI_VARIABLE_LENGTH, /* 09 ExtendedIRQ */ |
426 | ACPI_VARIABLE_LENGTH, /* 0A Qword* address */ |
427 | ACPI_FIXED_LENGTH, /* 0B Extended* address */ |
428 | ACPI_VARIABLE_LENGTH, /* 0C Gpio* */ |
429 | 0, |
430 | ACPI_VARIABLE_LENGTH /* 0E *SerialBus */ |
431 | }; |
432 | |
433 | |
434 | /******************************************************************************* |
435 | * |
436 | * FUNCTION: AcpiUtWalkAmlResources |
437 | * |
438 | * PARAMETERS: WalkState - Current walk info |
439 | * PARAMETERS: Aml - Pointer to the raw AML resource template |
440 | * AmlLength - Length of the entire template |
441 | * UserFunction - Called once for each descriptor found. If |
442 | * NULL, a pointer to the EndTag is returned |
443 | * Context - Passed to UserFunction |
444 | * |
445 | * RETURN: Status |
446 | * |
447 | * DESCRIPTION: Walk a raw AML resource list(buffer). User function called |
448 | * once for each resource found. |
449 | * |
450 | ******************************************************************************/ |
451 | |
452 | ACPI_STATUS |
453 | AcpiUtWalkAmlResources ( |
454 | ACPI_WALK_STATE *WalkState, |
455 | UINT8 *Aml, |
456 | ACPI_SIZE AmlLength, |
457 | ACPI_WALK_AML_CALLBACK UserFunction, |
458 | void **Context) |
459 | { |
460 | ACPI_STATUS Status; |
461 | UINT8 *EndAml; |
462 | UINT8 ResourceIndex; |
463 | UINT32 Length; |
464 | UINT32 Offset = 0; |
465 | UINT8 EndTag[2] = {0x79, 0x00}; |
466 | |
467 | |
468 | ACPI_FUNCTION_TRACE (UtWalkAmlResources); |
469 | |
470 | |
471 | /* The absolute minimum resource template is one EndTag descriptor */ |
472 | |
473 | if (AmlLength < sizeof (AML_RESOURCE_END_TAG)) |
474 | { |
475 | return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); |
476 | } |
477 | |
478 | /* Point to the end of the resource template buffer */ |
479 | |
480 | EndAml = Aml + AmlLength; |
481 | |
482 | /* Walk the byte list, abort on any invalid descriptor type or length */ |
483 | |
484 | while (Aml < EndAml) |
485 | { |
486 | /* Validate the Resource Type and Resource Length */ |
487 | |
488 | Status = AcpiUtValidateResource (WalkState, Aml, &ResourceIndex); |
489 | if (ACPI_FAILURE (Status)) |
490 | { |
491 | /* |
492 | * Exit on failure. Cannot continue because the descriptor |
493 | * length may be bogus also. |
494 | */ |
495 | return_ACPI_STATUS (Status); |
496 | } |
497 | |
498 | /* Get the length of this descriptor */ |
499 | |
500 | Length = AcpiUtGetDescriptorLength (Aml); |
501 | |
502 | /* Invoke the user function */ |
503 | |
504 | if (UserFunction) |
505 | { |
506 | Status = UserFunction ( |
507 | Aml, Length, Offset, ResourceIndex, Context); |
508 | if (ACPI_FAILURE (Status)) |
509 | { |
510 | return_ACPI_STATUS (Status); |
511 | } |
512 | } |
513 | |
514 | /* An EndTag descriptor terminates this resource template */ |
515 | |
516 | if (AcpiUtGetResourceType (Aml) == ACPI_RESOURCE_NAME_END_TAG) |
517 | { |
518 | /* |
519 | * There must be at least one more byte in the buffer for |
520 | * the 2nd byte of the EndTag |
521 | */ |
522 | if ((Aml + 1) >= EndAml) |
523 | { |
524 | return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); |
525 | } |
526 | |
527 | /* Return the pointer to the EndTag if requested */ |
528 | |
529 | if (!UserFunction) |
530 | { |
531 | *Context = Aml; |
532 | } |
533 | |
534 | /* Normal exit */ |
535 | |
536 | return_ACPI_STATUS (AE_OK); |
537 | } |
538 | |
539 | Aml += Length; |
540 | Offset += Length; |
541 | } |
542 | |
543 | /* Did not find an EndTag descriptor */ |
544 | |
545 | if (UserFunction) |
546 | { |
547 | /* Insert an EndTag anyway. AcpiRsGetListLength always leaves room */ |
548 | |
549 | (void) AcpiUtValidateResource (WalkState, EndTag, &ResourceIndex); |
550 | Status = UserFunction (EndTag, 2, Offset, ResourceIndex, Context); |
551 | if (ACPI_FAILURE (Status)) |
552 | { |
553 | return_ACPI_STATUS (Status); |
554 | } |
555 | } |
556 | |
557 | return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); |
558 | } |
559 | |
560 | |
561 | /******************************************************************************* |
562 | * |
563 | * FUNCTION: AcpiUtValidateResource |
564 | * |
565 | * PARAMETERS: WalkState - Current walk info |
566 | * Aml - Pointer to the raw AML resource descriptor |
567 | * ReturnIndex - Where the resource index is returned. NULL |
568 | * if the index is not required. |
569 | * |
570 | * RETURN: Status, and optionally the Index into the global resource tables |
571 | * |
572 | * DESCRIPTION: Validate an AML resource descriptor by checking the Resource |
573 | * Type and Resource Length. Returns an index into the global |
574 | * resource information/dispatch tables for later use. |
575 | * |
576 | ******************************************************************************/ |
577 | |
578 | ACPI_STATUS |
579 | AcpiUtValidateResource ( |
580 | ACPI_WALK_STATE *WalkState, |
581 | void *Aml, |
582 | UINT8 *ReturnIndex) |
583 | { |
584 | AML_RESOURCE *AmlResource; |
585 | UINT8 ResourceType; |
586 | UINT8 ResourceIndex; |
587 | ACPI_RS_LENGTH ResourceLength; |
588 | ACPI_RS_LENGTH MinimumResourceLength; |
589 | |
590 | |
591 | ACPI_FUNCTION_ENTRY (); |
592 | |
593 | |
594 | /* |
595 | * 1) Validate the ResourceType field (Byte 0) |
596 | */ |
597 | ResourceType = ACPI_GET8 (Aml); |
598 | |
599 | /* |
600 | * Byte 0 contains the descriptor name (Resource Type) |
601 | * Examine the large/small bit in the resource header |
602 | */ |
603 | if (ResourceType & ACPI_RESOURCE_NAME_LARGE) |
604 | { |
605 | /* Verify the large resource type (name) against the max */ |
606 | |
607 | if (ResourceType > ACPI_RESOURCE_NAME_LARGE_MAX) |
608 | { |
609 | goto InvalidResource; |
610 | } |
611 | |
612 | /* |
613 | * Large Resource Type -- bits 6:0 contain the name |
614 | * Translate range 0x80-0x8B to index range 0x10-0x1B |
615 | */ |
616 | ResourceIndex = (UINT8) (ResourceType - 0x70); |
617 | } |
618 | else |
619 | { |
620 | /* |
621 | * Small Resource Type -- bits 6:3 contain the name |
622 | * Shift range to index range 0x00-0x0F |
623 | */ |
624 | ResourceIndex = (UINT8) |
625 | ((ResourceType & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3); |
626 | } |
627 | |
628 | /* |
629 | * Check validity of the resource type, via AcpiGbl_ResourceTypes. |
630 | * Zero indicates an invalid resource. |
631 | */ |
632 | if (!AcpiGbl_ResourceTypes[ResourceIndex]) |
633 | { |
634 | goto InvalidResource; |
635 | } |
636 | |
637 | /* |
638 | * Validate the ResourceLength field. This ensures that the length |
639 | * is at least reasonable, and guarantees that it is non-zero. |
640 | */ |
641 | ResourceLength = AcpiUtGetResourceLength (Aml); |
642 | MinimumResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex]; |
643 | |
644 | /* Validate based upon the type of resource - fixed length or variable */ |
645 | |
646 | switch (AcpiGbl_ResourceTypes[ResourceIndex]) |
647 | { |
648 | case ACPI_FIXED_LENGTH: |
649 | |
650 | /* Fixed length resource, length must match exactly */ |
651 | |
652 | if (ResourceLength != MinimumResourceLength) |
653 | { |
654 | goto BadResourceLength; |
655 | } |
656 | break; |
657 | |
658 | case ACPI_VARIABLE_LENGTH: |
659 | |
660 | /* Variable length resource, length must be at least the minimum */ |
661 | |
662 | if (ResourceLength < MinimumResourceLength) |
663 | { |
664 | goto BadResourceLength; |
665 | } |
666 | break; |
667 | |
668 | case ACPI_SMALL_VARIABLE_LENGTH: |
669 | |
670 | /* Small variable length resource, length can be (Min) or (Min-1) */ |
671 | |
672 | if ((ResourceLength > MinimumResourceLength) || |
673 | (ResourceLength < (MinimumResourceLength - 1))) |
674 | { |
675 | goto BadResourceLength; |
676 | } |
677 | break; |
678 | |
679 | default: |
680 | |
681 | /* Shouldn't happen (because of validation earlier), but be sure */ |
682 | |
683 | goto InvalidResource; |
684 | } |
685 | |
686 | AmlResource = ACPI_CAST_PTR (AML_RESOURCE, Aml); |
687 | if (ResourceType == ACPI_RESOURCE_NAME_SERIAL_BUS) |
688 | { |
689 | /* Validate the BusType field */ |
690 | |
691 | if ((AmlResource->CommonSerialBus.Type == 0) || |
692 | (AmlResource->CommonSerialBus.Type > AML_RESOURCE_MAX_SERIALBUSTYPE)) |
693 | { |
694 | if (WalkState) |
695 | { |
696 | ACPI_ERROR ((AE_INFO, |
697 | "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X" , |
698 | AmlResource->CommonSerialBus.Type)); |
699 | } |
700 | return (AE_AML_INVALID_RESOURCE_TYPE); |
701 | } |
702 | } |
703 | |
704 | /* Optionally return the resource table index */ |
705 | |
706 | if (ReturnIndex) |
707 | { |
708 | *ReturnIndex = ResourceIndex; |
709 | } |
710 | |
711 | return (AE_OK); |
712 | |
713 | |
714 | InvalidResource: |
715 | |
716 | if (WalkState) |
717 | { |
718 | ACPI_ERROR ((AE_INFO, |
719 | "Invalid/unsupported resource descriptor: Type 0x%2.2X" , |
720 | ResourceType)); |
721 | } |
722 | return (AE_AML_INVALID_RESOURCE_TYPE); |
723 | |
724 | BadResourceLength: |
725 | |
726 | if (WalkState) |
727 | { |
728 | ACPI_ERROR ((AE_INFO, |
729 | "Invalid resource descriptor length: Type " |
730 | "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X" , |
731 | ResourceType, ResourceLength, MinimumResourceLength)); |
732 | } |
733 | return (AE_AML_BAD_RESOURCE_LENGTH); |
734 | } |
735 | |
736 | |
737 | /******************************************************************************* |
738 | * |
739 | * FUNCTION: AcpiUtGetResourceType |
740 | * |
741 | * PARAMETERS: Aml - Pointer to the raw AML resource descriptor |
742 | * |
743 | * RETURN: The Resource Type with no extraneous bits (except the |
744 | * Large/Small descriptor bit -- this is left alone) |
745 | * |
746 | * DESCRIPTION: Extract the Resource Type/Name from the first byte of |
747 | * a resource descriptor. |
748 | * |
749 | ******************************************************************************/ |
750 | |
751 | UINT8 |
752 | AcpiUtGetResourceType ( |
753 | void *Aml) |
754 | { |
755 | ACPI_FUNCTION_ENTRY (); |
756 | |
757 | |
758 | /* |
759 | * Byte 0 contains the descriptor name (Resource Type) |
760 | * Examine the large/small bit in the resource header |
761 | */ |
762 | if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) |
763 | { |
764 | /* Large Resource Type -- bits 6:0 contain the name */ |
765 | |
766 | return (ACPI_GET8 (Aml)); |
767 | } |
768 | else |
769 | { |
770 | /* Small Resource Type -- bits 6:3 contain the name */ |
771 | |
772 | return ((UINT8) (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_SMALL_MASK)); |
773 | } |
774 | } |
775 | |
776 | |
777 | /******************************************************************************* |
778 | * |
779 | * FUNCTION: AcpiUtGetResourceLength |
780 | * |
781 | * PARAMETERS: Aml - Pointer to the raw AML resource descriptor |
782 | * |
783 | * RETURN: Byte Length |
784 | * |
785 | * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By |
786 | * definition, this does not include the size of the descriptor |
787 | * header or the length field itself. |
788 | * |
789 | ******************************************************************************/ |
790 | |
791 | UINT16 |
792 | AcpiUtGetResourceLength ( |
793 | void *Aml) |
794 | { |
795 | ACPI_RS_LENGTH ResourceLength; |
796 | |
797 | |
798 | ACPI_FUNCTION_ENTRY (); |
799 | |
800 | |
801 | /* |
802 | * Byte 0 contains the descriptor name (Resource Type) |
803 | * Examine the large/small bit in the resource header |
804 | */ |
805 | if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) |
806 | { |
807 | /* Large Resource type -- bytes 1-2 contain the 16-bit length */ |
808 | |
809 | ACPI_MOVE_16_TO_16 (&ResourceLength, ACPI_ADD_PTR (UINT8, Aml, 1)); |
810 | |
811 | } |
812 | else |
813 | { |
814 | /* Small Resource type -- bits 2:0 of byte 0 contain the length */ |
815 | |
816 | ResourceLength = (UINT16) (ACPI_GET8 (Aml) & |
817 | ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK); |
818 | } |
819 | |
820 | return (ResourceLength); |
821 | } |
822 | |
823 | |
824 | /******************************************************************************* |
825 | * |
826 | * FUNCTION: AcpiUtGetResourceHeaderLength |
827 | * |
828 | * PARAMETERS: Aml - Pointer to the raw AML resource descriptor |
829 | * |
830 | * RETURN: Length of the AML header (depends on large/small descriptor) |
831 | * |
832 | * DESCRIPTION: Get the length of the header for this resource. |
833 | * |
834 | ******************************************************************************/ |
835 | |
836 | UINT8 |
837 | ( |
838 | void *Aml) |
839 | { |
840 | ACPI_FUNCTION_ENTRY (); |
841 | |
842 | |
843 | /* Examine the large/small bit in the resource header */ |
844 | |
845 | if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) |
846 | { |
847 | return (sizeof (AML_RESOURCE_LARGE_HEADER)); |
848 | } |
849 | else |
850 | { |
851 | return (sizeof (AML_RESOURCE_SMALL_HEADER)); |
852 | } |
853 | } |
854 | |
855 | |
856 | /******************************************************************************* |
857 | * |
858 | * FUNCTION: AcpiUtGetDescriptorLength |
859 | * |
860 | * PARAMETERS: Aml - Pointer to the raw AML resource descriptor |
861 | * |
862 | * RETURN: Byte length |
863 | * |
864 | * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the |
865 | * length of the descriptor header and the length field itself. |
866 | * Used to walk descriptor lists. |
867 | * |
868 | ******************************************************************************/ |
869 | |
870 | UINT32 |
871 | AcpiUtGetDescriptorLength ( |
872 | void *Aml) |
873 | { |
874 | ACPI_FUNCTION_ENTRY (); |
875 | |
876 | |
877 | /* |
878 | * Get the Resource Length (does not include header length) and add |
879 | * the header length (depends on if this is a small or large resource) |
880 | */ |
881 | return (AcpiUtGetResourceLength (Aml) + |
882 | AcpiUtGetResourceHeaderLength (Aml)); |
883 | } |
884 | |
885 | |
886 | /******************************************************************************* |
887 | * |
888 | * FUNCTION: AcpiUtGetResourceEndTag |
889 | * |
890 | * PARAMETERS: ObjDesc - The resource template buffer object |
891 | * EndTag - Where the pointer to the EndTag is returned |
892 | * |
893 | * RETURN: Status, pointer to the end tag |
894 | * |
895 | * DESCRIPTION: Find the EndTag resource descriptor in an AML resource template |
896 | * Note: allows a buffer length of zero. |
897 | * |
898 | ******************************************************************************/ |
899 | |
900 | ACPI_STATUS |
901 | AcpiUtGetResourceEndTag ( |
902 | ACPI_OPERAND_OBJECT *ObjDesc, |
903 | UINT8 **EndTag) |
904 | { |
905 | ACPI_STATUS Status; |
906 | |
907 | |
908 | ACPI_FUNCTION_TRACE (UtGetResourceEndTag); |
909 | |
910 | |
911 | /* Allow a buffer length of zero */ |
912 | |
913 | if (!ObjDesc->Buffer.Length) |
914 | { |
915 | *EndTag = ObjDesc->Buffer.Pointer; |
916 | return_ACPI_STATUS (AE_OK); |
917 | } |
918 | |
919 | /* Validate the template and get a pointer to the EndTag */ |
920 | |
921 | Status = AcpiUtWalkAmlResources (NULL, ObjDesc->Buffer.Pointer, |
922 | ObjDesc->Buffer.Length, NULL, (void **) EndTag); |
923 | |
924 | return_ACPI_STATUS (Status); |
925 | } |
926 | |