1 /** @file
2   ACPI Sdt Protocol Driver
3 
4   Copyright (c) 2010 - 2011, 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   Check if it is AML Root name
19 
20   @param[in]    Buffer AML path.
21 
22   @retval       TRUE  AML path is root.
23   @retval       FALSE AML path is not root.
24 **/
25 BOOLEAN
AmlIsRootPath(IN UINT8 * Buffer)26 AmlIsRootPath (
27   IN UINT8              *Buffer
28   )
29 {
30   if ((Buffer[0] == AML_ROOT_CHAR) && (Buffer[1] == 0)) {
31     return TRUE;
32   } else {
33     return FALSE;
34   }
35 }
36 
37 /**
38   Check if it is AML LeadName.
39 
40   @param[in]    Ch   Char.
41 
42   @retval       TRUE  Char is AML LeadName.
43   @retval       FALSE Char is not AML LeadName.
44 **/
45 BOOLEAN
AmlIsLeadName(IN CHAR8 Ch)46 AmlIsLeadName (
47   IN CHAR8 Ch
48   )
49 {
50   if ((Ch == '_') || (Ch >= 'A' && Ch <= 'Z')) {
51     return TRUE;
52   } else {
53     return FALSE;
54   }
55 }
56 
57 /**
58   Check if it is AML Name.
59 
60   @param[in]    Ch   Char.
61 
62   @retval       TRUE  Char is AML Name.
63   @retval       FALSE Char is not AML Name.
64 **/
65 BOOLEAN
AmlIsName(IN CHAR8 Ch)66 AmlIsName (
67   IN CHAR8 Ch
68   )
69 {
70   if (AmlIsLeadName (Ch) || (Ch >= '0' && Ch <= '9')) {
71     return TRUE;
72   } else {
73     return FALSE;
74   }
75 }
76 
77 /**
78   Return is buffer is AML NameSeg.
79 
80   @param[in]    Buffer     AML NameSement.
81 
82   @retval       TRUE       It is AML NameSegment.
83   @retval       FALSE      It is not AML NameSegment.
84 **/
85 BOOLEAN
AmlIsNameSeg(IN UINT8 * Buffer)86 AmlIsNameSeg (
87   IN  UINT8              *Buffer
88   )
89 {
90   UINTN  Index;
91   if (!AmlIsLeadName (Buffer[0])) {
92     return FALSE;
93   }
94   for (Index = 1; Index < AML_NAME_SEG_SIZE; Index++) {
95     if (!AmlIsName (Buffer[Index])) {
96       return FALSE;
97     }
98   }
99   return TRUE;
100 }
101 
102 /**
103   Get AML NameString size.
104 
105   @param[in]    Buffer     AML NameString.
106   @param[out]   BufferSize AML NameString size
107 
108   @retval       EFI_SUCCESS           Success.
109   @retval       EFI_INVALID_PARAMETER Buffer does not refer to a valid AML NameString.
110 **/
111 EFI_STATUS
AmlGetNameStringSize(IN UINT8 * Buffer,OUT UINTN * BufferSize)112 AmlGetNameStringSize (
113   IN  UINT8              *Buffer,
114   OUT UINTN              *BufferSize
115   )
116 {
117   UINTN                 SegCount;
118   UINTN                 Length;
119   UINTN                 Index;
120 
121   Length = 0;
122 
123   //
124   // Parse root or parent prefix
125   //
126   if (*Buffer == AML_ROOT_CHAR) {
127     Buffer ++;
128     Length ++;
129   } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
130     do {
131       Buffer ++;
132       Length ++;
133     } while (*Buffer == AML_PARENT_PREFIX_CHAR);
134   }
135 
136   //
137   // Parse name segment
138   //
139   if (*Buffer == AML_DUAL_NAME_PREFIX) {
140     Buffer ++;
141     Length ++;
142     SegCount = 2;
143   } else if (*Buffer == AML_MULTI_NAME_PREFIX) {
144     Buffer ++;
145     Length ++;
146     SegCount = *Buffer;
147     Buffer ++;
148     Length ++;
149   } else if (*Buffer == 0) {
150     //
151     // NULL Name, only for Root
152     //
153     SegCount = 0;
154     Buffer --;
155     if ((Length == 1) && (*Buffer == AML_ROOT_CHAR)) {
156       *BufferSize = 2;
157       return EFI_SUCCESS;
158     } else {
159       return EFI_INVALID_PARAMETER;
160     }
161   } else {
162     //
163     // NameSeg
164     //
165     SegCount = 1;
166   }
167 
168   Index = 0;
169   do {
170     if (!AmlIsNameSeg (Buffer)) {
171       return EFI_INVALID_PARAMETER;
172     }
173     Buffer += AML_NAME_SEG_SIZE;
174     Length += AML_NAME_SEG_SIZE;
175     Index ++;
176   } while (Index < SegCount);
177 
178   *BufferSize = Length;
179   return EFI_SUCCESS;
180 }
181 
182 /**
183   Check if it is ASL LeadName.
184 
185   @param[in]    Ch   Char.
186 
187   @retval       TRUE  Char is ASL LeadName.
188   @retval       FALSE Char is not ASL LeadName.
189 **/
190 BOOLEAN
AmlIsAslLeadName(IN CHAR8 Ch)191 AmlIsAslLeadName (
192   IN CHAR8 Ch
193   )
194 {
195   if (AmlIsLeadName (Ch) || (Ch >= 'a' && Ch <= 'z')) {
196     return TRUE;
197   } else {
198     return FALSE;
199   }
200 }
201 
202 /**
203   Check if it is ASL Name.
204 
205   @param[in]    Ch   Char.
206 
207   @retval       TRUE  Char is ASL Name.
208   @retval       FALSE Char is not ASL Name.
209 **/
210 BOOLEAN
AmlIsAslName(IN CHAR8 Ch)211 AmlIsAslName (
212   IN CHAR8 Ch
213   )
214 {
215   if (AmlIsAslLeadName (Ch) || (Ch >= '0' && Ch <= '9')) {
216     return TRUE;
217   } else {
218     return FALSE;
219   }
220 }
221 
222 /**
223   Get ASL NameString size.
224 
225   @param[in]    Buffer   ASL NameString.
226 
227   @return       ASL NameString size.
228 **/
229 UINTN
AmlGetAslNameSegLength(IN UINT8 * Buffer)230 AmlGetAslNameSegLength (
231   IN UINT8 *Buffer
232   )
233 {
234   UINTN Length;
235   UINTN Index;
236 
237   if (*Buffer == 0) {
238     return 0;
239   }
240 
241   Length = 0;
242   //
243   // 1st
244   //
245   if (AmlIsAslLeadName (*Buffer)) {
246     Length ++;
247     Buffer ++;
248   }
249   if ((*Buffer == 0) || (*Buffer == '.')) {
250     return Length;
251   }
252   //
253   // 2, 3, 4 name char
254   //
255   for (Index = 0; Index < 3; Index++) {
256     if (AmlIsAslName (*Buffer)) {
257       Length ++;
258       Buffer ++;
259     }
260     if ((*Buffer == 0) || (*Buffer == '.')) {
261       return Length;
262     }
263   }
264 
265   //
266   // Invalid ASL name
267   //
268   return 0;
269 }
270 
271 /**
272   Get ASL NameString size.
273 
274   @param[in]    Buffer   ASL NameString.
275   @param[out]   Root     On return, points to Root char number.
276   @param[out]   Parent   On return, points to Parent char number.
277   @param[out]   SegCount On return, points to Segment count.
278 
279   @return       ASL NameString size.
280 **/
281 UINTN
AmlGetAslNameStringSize(IN UINT8 * Buffer,OUT UINTN * Root,OUT UINTN * Parent,OUT UINTN * SegCount)282 AmlGetAslNameStringSize (
283   IN UINT8              *Buffer,
284   OUT UINTN             *Root,
285   OUT UINTN             *Parent,
286   OUT UINTN             *SegCount
287   )
288 {
289   UINTN NameLength;
290   UINTN TotalLength;
291 
292   *Root   = 0;
293   *Parent = 0;
294   *SegCount = 0;
295   TotalLength = 0;
296   NameLength = 0;
297   if (*Buffer == AML_ROOT_CHAR) {
298     *Root = 1;
299     Buffer ++;
300   } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
301     do {
302       Buffer ++;
303       (*Parent) ++;
304     } while (*Buffer == AML_PARENT_PREFIX_CHAR);
305   }
306 
307   //
308   // Now parse name
309   //
310   while (*Buffer != 0) {
311     NameLength = AmlGetAslNameSegLength (Buffer);
312     if ((NameLength == 0) || (NameLength > AML_NAME_SEG_SIZE)) {
313       return 0;
314     }
315     (*SegCount) ++;
316     Buffer += NameLength;
317     if (*Buffer == 0) {
318       break;
319     }
320     Buffer ++;
321   }
322 
323   //
324   // Check SegCoount
325   //
326   if (*SegCount > 0xFF) {
327     return 0;
328   }
329 
330   //
331   // Calculate total length
332   //
333   TotalLength = *Root + *Parent + (*SegCount) * AML_NAME_SEG_SIZE;
334   if (*SegCount > 2) {
335     TotalLength += 2;
336   } else if (*SegCount == 2) {
337     TotalLength += 1;
338   }
339 
340   //
341   // Add NULL char
342   //
343   TotalLength ++;
344 
345   return TotalLength;
346 }
347 
348 /**
349   Copy mem, and cast all the char in dest to be upper case.
350 
351   @param[in]    DstBuffer   Destination buffer.
352   @param[in]    SrcBuffer   Source buffer.
353   @param[in]    Length      Buffer length.
354 **/
355 VOID
AmlUpperCaseCopyMem(IN UINT8 * DstBuffer,IN UINT8 * SrcBuffer,IN UINTN Length)356 AmlUpperCaseCopyMem (
357   IN UINT8 *DstBuffer,
358   IN UINT8 *SrcBuffer,
359   IN UINTN Length
360   )
361 {
362   UINTN Index;
363 
364   for (Index = 0; Index < Length; Index++) {
365     if (SrcBuffer[Index] >= 'a' && SrcBuffer[Index] <= 'z') {
366       DstBuffer[Index] = (UINT8)(SrcBuffer[Index] - 'a' + 'A');
367     } else {
368       DstBuffer[Index] = SrcBuffer[Index];
369     }
370   }
371 }
372 
373 /**
374   Return AML name according to ASL name.
375   The caller need free the AmlName returned.
376 
377   @param[in]    AslPath     ASL name.
378 
379   @return AmlName
380 **/
381 UINT8 *
AmlNameFromAslName(IN UINT8 * AslPath)382 AmlNameFromAslName (
383   IN UINT8 *AslPath
384   )
385 {
386   UINTN Root;
387   UINTN Parent;
388   UINTN SegCount;
389   UINTN TotalLength;
390   UINTN NameLength;
391   UINT8 *Buffer;
392   UINT8 *AmlPath;
393   UINT8 *AmlBuffer;
394 
395   TotalLength = AmlGetAslNameStringSize (AslPath, &Root, &Parent, &SegCount);
396   if (TotalLength == 0) {
397     return NULL;
398   }
399 
400   AmlPath = AllocatePool (TotalLength);
401   ASSERT (AmlPath != NULL);
402 
403   AmlBuffer = AmlPath;
404   Buffer = AslPath;
405 
406   //
407   // Handle Root and Parent
408   //
409   if (Root == 1) {
410     *AmlBuffer = AML_ROOT_CHAR;
411     AmlBuffer ++;
412     Buffer ++;
413   } else if (Parent > 0) {
414     SetMem (AmlBuffer, Parent, AML_PARENT_PREFIX_CHAR);
415     AmlBuffer += Parent;
416     Buffer += Parent;
417   }
418 
419   //
420   // Handle SegCount
421   //
422   if (SegCount > 2) {
423     *AmlBuffer = AML_MULTI_NAME_PREFIX;
424     AmlBuffer ++;
425     *AmlBuffer = (UINT8)SegCount;
426     AmlBuffer ++;
427   } else if (SegCount == 2) {
428     *AmlBuffer = AML_DUAL_NAME_PREFIX;
429     AmlBuffer ++;
430   }
431 
432   //
433   // Now to name
434   //
435   while (*Buffer != 0) {
436     NameLength = AmlGetAslNameSegLength (Buffer);
437     ASSERT ((NameLength != 0) && (NameLength <= AML_NAME_SEG_SIZE));
438     AmlUpperCaseCopyMem (AmlBuffer, Buffer, NameLength);
439     SetMem (AmlBuffer + NameLength, AML_NAME_SEG_SIZE - NameLength, AML_NAME_CHAR__);
440     Buffer += NameLength;
441     AmlBuffer += AML_NAME_SEG_SIZE;
442     if (*Buffer == 0) {
443       break;
444     }
445     Buffer ++;
446   }
447 
448   //
449   // Add NULL
450   //
451   AmlPath[TotalLength - 1] = 0;
452 
453   return AmlPath;
454 }
455 
456 /**
457   Print AML NameSeg.
458 
459   @param[in] Buffer AML NameSeg.
460 **/
461 VOID
AmlPrintNameSeg(IN UINT8 * Buffer)462 AmlPrintNameSeg (
463   IN UINT8              *Buffer
464   )
465 {
466   DEBUG ((EFI_D_ERROR, "%c", Buffer[0]));
467   if ((Buffer[1] == '_') && (Buffer[2] == '_') && (Buffer[3] == '_')) {
468     return ;
469   }
470   DEBUG ((EFI_D_ERROR, "%c", Buffer[1]));
471   if ((Buffer[2] == '_') && (Buffer[3] == '_')) {
472     return ;
473   }
474   DEBUG ((EFI_D_ERROR, "%c", Buffer[2]));
475   if (Buffer[3] == '_') {
476     return ;
477   }
478   DEBUG ((EFI_D_ERROR, "%c", Buffer[3]));
479   return ;
480 }
481 
482 /**
483   Print AML NameString.
484 
485   @param[in] Buffer AML NameString.
486 **/
487 VOID
AmlPrintNameString(IN UINT8 * Buffer)488 AmlPrintNameString (
489   IN UINT8              *Buffer
490   )
491 {
492   UINT8                 SegCount;
493   UINT8                 Index;
494 
495   if (*Buffer == AML_ROOT_CHAR) {
496     //
497     // RootChar
498     //
499     Buffer ++;
500     DEBUG ((EFI_D_ERROR, "\\"));
501   } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
502     //
503     // ParentPrefixChar
504     //
505     do {
506       Buffer ++;
507       DEBUG ((EFI_D_ERROR, "^"));
508     } while (*Buffer == AML_PARENT_PREFIX_CHAR);
509   }
510 
511   if (*Buffer == AML_DUAL_NAME_PREFIX) {
512     //
513     // DualName
514     //
515     Buffer ++;
516     SegCount = 2;
517   } else if (*Buffer == AML_MULTI_NAME_PREFIX) {
518     //
519     // MultiName
520     //
521     Buffer ++;
522     SegCount = *Buffer;
523     Buffer ++;
524   } else if (*Buffer == 0) {
525     //
526     // NULL Name
527     //
528     return ;
529   } else {
530     //
531     // NameSeg
532     //
533     SegCount = 1;
534   }
535 
536   AmlPrintNameSeg (Buffer);
537   Buffer += AML_NAME_SEG_SIZE;
538   for (Index = 0; Index < SegCount - 1; Index++) {
539     DEBUG ((EFI_D_ERROR, "."));
540     AmlPrintNameSeg (Buffer);
541     Buffer += AML_NAME_SEG_SIZE;
542   }
543 
544   return ;
545 }
546