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