1 /** @file
2   ACPI Sdt Protocol Driver
3 
4   Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved. <BR>
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "AcpiTable.h"
16 
17 /**
18   Return the child objects buffer from AML Handle's buffer.
19 
20   @param[in]        AmlParentHandle Parent handle.
21   @param[in]        CurrentBuffer   The current child buffer.
22   @param[out]       Buffer          On return, points to the next returned child buffer or NULL if there are no
23                                     child buffer.
24 
25   @retval EFI_SUCCESS               Success
26   @retval EFI_INVALID_PARAMETER     AmlParentHandle does not refer to a valid ACPI object.
27 **/
28 EFI_STATUS
AmlGetChildFromObjectBuffer(IN EFI_AML_HANDLE * AmlParentHandle,IN UINT8 * CurrentBuffer,OUT VOID ** Buffer)29 AmlGetChildFromObjectBuffer (
30   IN EFI_AML_HANDLE         *AmlParentHandle,
31   IN UINT8                  *CurrentBuffer,
32   OUT VOID                  **Buffer
33   )
34 {
35   AML_BYTE_ENCODING   *AmlByteEncoding;
36   UINTN               DataSize;
37 
38   //
39   // Root is considered as SCOPE, which has TermList.
40   // We need return only Object in TermList.
41   //
42   while ((UINTN)CurrentBuffer < (UINTN)(AmlParentHandle->Buffer + AmlParentHandle->Size)) {
43     AmlByteEncoding = AmlSearchByOpByte (CurrentBuffer);
44     if (AmlByteEncoding == NULL) {
45       return EFI_INVALID_PARAMETER;
46     }
47     //
48     // NOTE: We need return everything, because user might need parse the returned object.
49     //
50     if ((AmlByteEncoding->Attribute & AML_IS_NAME_CHAR) == 0) {
51       *Buffer = CurrentBuffer;
52       return EFI_SUCCESS;
53     }
54 
55     DataSize = AmlGetObjectSize (
56                  AmlByteEncoding,
57                  CurrentBuffer,
58                  (UINTN)AmlParentHandle->Buffer + AmlParentHandle->Size - (UINTN)CurrentBuffer
59                  );
60     if (DataSize == 0) {
61       return EFI_INVALID_PARAMETER;
62     }
63     CurrentBuffer += DataSize;
64   }
65 
66   //
67   // No more
68   //
69   *Buffer = NULL;
70   return EFI_SUCCESS;
71 }
72 
73 /**
74   Return the child ACPI objects from Root Handle.
75 
76   @param[in]        AmlParentHandle Parent handle. It is Root Handle.
77   @param[in]        AmlHandle       The previously returned handle or NULL to start with the first handle.
78   @param[out]       Buffer          On return, points to the next returned ACPI handle or NULL if there are no
79                                     child objects.
80 
81   @retval EFI_SUCCESS               Success
82   @retval EFI_INVALID_PARAMETER     ParentHandle is NULL or does not refer to a valid ACPI object.
83 **/
84 EFI_STATUS
AmlGetChildFromRoot(IN EFI_AML_HANDLE * AmlParentHandle,IN EFI_AML_HANDLE * AmlHandle,OUT VOID ** Buffer)85 AmlGetChildFromRoot (
86   IN EFI_AML_HANDLE         *AmlParentHandle,
87   IN EFI_AML_HANDLE         *AmlHandle,
88   OUT VOID                  **Buffer
89   )
90 {
91   UINT8               *CurrentBuffer;
92 
93   if (AmlHandle == NULL) {
94     //
95     // First One
96     //
97     CurrentBuffer = (VOID *)AmlParentHandle->Buffer;
98   } else {
99     CurrentBuffer = (VOID *)(AmlHandle->Buffer + AmlHandle->Size);
100   }
101 
102   return AmlGetChildFromObjectBuffer (AmlParentHandle, CurrentBuffer, Buffer);
103 }
104 
105 /**
106   Return the child objects buffer from AML Handle's option list.
107 
108   @param[in]        AmlParentHandle Parent handle.
109   @param[in]        AmlHandle       The current child handle.
110   @param[out]       Buffer          On return, points to the next returned child buffer or NULL if there are no
111                                     child buffer.
112 
113   @retval EFI_SUCCESS               Success
114   @retval EFI_INVALID_PARAMETER     AmlParentHandle does not refer to a valid ACPI object.
115 **/
116 EFI_STATUS
AmlGetChildFromOptionList(IN EFI_AML_HANDLE * AmlParentHandle,IN EFI_AML_HANDLE * AmlHandle,OUT VOID ** Buffer)117 AmlGetChildFromOptionList (
118   IN EFI_AML_HANDLE         *AmlParentHandle,
119   IN EFI_AML_HANDLE         *AmlHandle,
120   OUT VOID                  **Buffer
121   )
122 {
123   EFI_ACPI_DATA_TYPE  DataType;
124   VOID                *Data;
125   UINTN               DataSize;
126   AML_OP_PARSE_INDEX  Index;
127   EFI_STATUS          Status;
128   AML_OP_PARSE_INDEX  MaxTerm;
129 
130   Index = AML_OP_PARSE_INDEX_GET_TERM1;
131   MaxTerm = AmlParentHandle->AmlByteEncoding->MaxIndex;
132   while (Index <= MaxTerm) {
133     Status = AmlParseOptionHandleCommon (
134                AmlParentHandle,
135                (AML_OP_PARSE_INDEX)Index,
136                &DataType,
137                (VOID **)&Data,
138                &DataSize
139                );
140     if (EFI_ERROR (Status)) {
141       return EFI_INVALID_PARAMETER;
142     }
143     if (DataType == EFI_ACPI_DATA_TYPE_NONE) {
144       //
145       // Not found
146       //
147       break;
148     }
149 
150     //
151     // Find it, and Check Data
152     //
153     if ((DataType == EFI_ACPI_DATA_TYPE_CHILD) &&
154         ((UINTN)AmlHandle->Buffer < (UINTN)Data)) {
155       //
156       // Buffer < Data means current node is next one
157       //
158       *Buffer = Data;
159       return EFI_SUCCESS;
160     }
161     //
162     // Not Child
163     //
164     Index ++;
165   }
166 
167   *Buffer = NULL;
168   return EFI_SUCCESS;
169 }
170 
171 /**
172   Return the child objects buffer from AML Handle's object child list.
173 
174   @param[in]        AmlParentHandle Parent handle.
175   @param[in]        AmlHandle       The current child handle.
176   @param[out]       Buffer          On return, points to the next returned child buffer or NULL if there are no
177                                     child buffer.
178 
179   @retval EFI_SUCCESS               Success
180   @retval EFI_INVALID_PARAMETER     AmlParentHandle does not refer to a valid ACPI object.
181 **/
182 EFI_STATUS
AmlGetChildFromObjectChildList(IN EFI_AML_HANDLE * AmlParentHandle,IN EFI_AML_HANDLE * AmlHandle,OUT VOID ** Buffer)183 AmlGetChildFromObjectChildList (
184   IN EFI_AML_HANDLE         *AmlParentHandle,
185   IN EFI_AML_HANDLE         *AmlHandle,
186   OUT VOID                  **Buffer
187   )
188 {
189   EFI_STATUS          Status;
190   UINT8               *CurrentBuffer;
191 
192   CurrentBuffer = NULL;
193 
194   if ((AmlParentHandle->AmlByteEncoding->Attribute & AML_HAS_CHILD_OBJ) == 0) {
195     //
196     // No ObjectList
197     //
198     *Buffer = NULL;
199     return EFI_SUCCESS;
200   }
201 
202   //
203   // Do we need add node within METHOD?
204   // Yes, just add Object is OK. But we need filter NameString for METHOD invoke.
205   //
206 
207   //
208   // Now, we get the last node.
209   //
210   Status = AmlGetOffsetAfterLastOption (AmlParentHandle, &CurrentBuffer);
211   if (EFI_ERROR (Status)) {
212     return EFI_INVALID_PARAMETER;
213   }
214 
215   //
216   // Go through all the reset buffer.
217   //
218   if ((UINTN)AmlHandle->Buffer < (UINTN)CurrentBuffer) {
219     //
220     // Buffer < Data means next node is first object
221     //
222   } else if ((UINTN)AmlHandle->Buffer + AmlHandle->Size < (UINTN)AmlParentHandle->Buffer + AmlParentHandle->Size) {
223     //
224     // There is still more node
225     //
226     CurrentBuffer = AmlHandle->Buffer + AmlHandle->Size;
227   } else {
228     //
229     // No more data
230     //
231     *Buffer = NULL;
232     return EFI_SUCCESS;
233   }
234 
235   return AmlGetChildFromObjectBuffer (AmlParentHandle, CurrentBuffer, Buffer);
236 }
237 
238 /**
239   Return the child ACPI objects from Non-Root Handle.
240 
241   @param[in]        AmlParentHandle Parent handle. It is Non-Root Handle.
242   @param[in]        AmlHandle       The previously returned handle or NULL to start with the first handle.
243   @param[out]       Buffer          On return, points to the next returned ACPI handle or NULL if there are no
244                                     child objects.
245 
246   @retval EFI_SUCCESS               Success
247   @retval EFI_INVALID_PARAMETER     ParentHandle is NULL or does not refer to a valid ACPI object.
248 **/
249 EFI_STATUS
AmlGetChildFromNonRoot(IN EFI_AML_HANDLE * AmlParentHandle,IN EFI_AML_HANDLE * AmlHandle,OUT VOID ** Buffer)250 AmlGetChildFromNonRoot (
251   IN EFI_AML_HANDLE         *AmlParentHandle,
252   IN EFI_AML_HANDLE         *AmlHandle,
253   OUT VOID                  **Buffer
254   )
255 {
256   EFI_STATUS          Status;
257 
258   if (AmlHandle == NULL) {
259     //
260     // NULL means first one
261     //
262     AmlHandle = AmlParentHandle;
263   }
264 
265   //
266   // 1. Get Option
267   //
268   Status = AmlGetChildFromOptionList (AmlParentHandle, AmlHandle, Buffer);
269   if (EFI_ERROR (Status)) {
270     return EFI_INVALID_PARAMETER;
271   }
272   if (*Buffer != NULL) {
273     return EFI_SUCCESS;
274   }
275 
276   //
277   // 2. search ObjectList
278   //
279   return AmlGetChildFromObjectChildList (AmlParentHandle, AmlHandle, Buffer);
280 }
281