]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.c
DynamicTablesPkg: Apply uncrustify changes
[mirror_edk2.git] / DynamicTablesPkg / Library / Common / AmlLib / String / AmlString.c
1 /** @file
2 AML String.
3
4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>
5 Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8 **/
9
10 #include <String/AmlString.h>
11
12 #include <AmlDefines.h>
13 #include <IndustryStandard/AcpiAml.h>
14
15 /** Check NameString/path information is valid.
16
17 Root, ParentPrefix and SegCount cannot be 0 at the same time.
18 This function works for ASL and AML name strings.
19
20 @param [in] Root Number of root char.
21 Must be 0 or 1.
22 @param [in] ParentPrefix Number of carets char ('^').
23 Must be [0-255].
24 @param [in] SegCount Number of NameSeg (s).
25 Must be [0-255].
26
27 @retval TRUE id the input information is in the right boundaries.
28 FALSE otherwise.
29 **/
30 BOOLEAN
31 EFIAPI
32 AmlIsNameString (
33 IN UINT32 Root,
34 IN UINT32 ParentPrefix,
35 IN UINT32 SegCount
36 )
37 {
38 if (((Root == 0) || (Root == 1)) &&
39 (ParentPrefix <= MAX_UINT8) &&
40 (!((ParentPrefix != 0) && (Root != 0))) &&
41 (SegCount <= MAX_UINT8) &&
42 ((SegCount + Root + ParentPrefix) != 0))
43 {
44 return TRUE;
45 }
46
47 return FALSE;
48 }
49
50 /** Copy bytes from SrcBuffer to DstBuffer and convert to upper case.
51 Don't copy more than MaxDstBufferSize bytes.
52
53 @param [out] DstBuffer Destination buffer.
54 @param [in] MaxDstBufferSize Maximum size of DstBuffer.
55 Must be non-zero.
56 @param [in] SrcBuffer Source buffer.
57 @param [in] Count Count of bytes to copy from SrcBuffer.
58 Return success if 0.
59
60 @retval EFI_SUCCESS The function completed successfully.
61 @retval EFI_INVALID_PARAMETER Invalid parameter.
62 **/
63 EFI_STATUS
64 EFIAPI
65 AmlUpperCaseMemCpyS (
66 OUT CHAR8 *DstBuffer,
67 IN UINT32 MaxDstBufferSize,
68 IN CONST CHAR8 *SrcBuffer,
69 IN UINT32 Count
70 )
71 {
72 UINT32 Index;
73
74 if ((DstBuffer == NULL) ||
75 (SrcBuffer == NULL))
76 {
77 ASSERT (0);
78 return EFI_INVALID_PARAMETER;
79 }
80
81 if (Count == 0) {
82 return EFI_SUCCESS;
83 }
84
85 if (Count > MaxDstBufferSize) {
86 Count = MaxDstBufferSize;
87 }
88
89 for (Index = 0; Index < Count; Index++) {
90 if ((SrcBuffer[Index] >= 'a') && (SrcBuffer[Index] <= 'z')) {
91 DstBuffer[Index] = (CHAR8)((UINT8)SrcBuffer[Index] - ('a' - 'A'));
92 } else {
93 DstBuffer[Index] = SrcBuffer[Index];
94 }
95 }
96
97 return EFI_SUCCESS;
98 }
99
100 /** Check whether Buffer is a root path ('\').
101
102 This function works for both ASL and AML pathnames.
103 Buffer must be at least 2 bytes long.
104
105 @param [in] Buffer An ASL/AML path.
106
107 @retval TRUE Buffer is a root path
108 @retval FALSE Buffer is not a root path.
109 **/
110 BOOLEAN
111 EFIAPI
112 AmlIsRootPath (
113 IN CONST CHAR8 *Buffer
114 )
115 {
116 if (Buffer == NULL) {
117 return FALSE;
118 }
119
120 if ((Buffer[0] == AML_ROOT_CHAR) && (Buffer[1] == '\0')) {
121 return TRUE;
122 } else {
123 return FALSE;
124 }
125 }
126
127 /** Check whether Ch is an ASL/AML LeadName.
128
129 This function works for both ASL and AML pathnames.
130
131 ACPI 6.3 specification, s19.2.2. "ASL Name and Pathname Terms":
132 LeadNameChar := 'A'-'Z' | 'a'-'z' | '_'
133
134 ACPI 6.3 specification, s20.2.2. "Name Objects Encoding":
135 LeadNameChar := 'A'-'Z' | 'a'-'z' | '_'
136
137 @param [in] Ch The char to test.
138
139 @retval TRUE Ch is an ASL/AML LeadName.
140 @retval FALSE Ch is not an ASL/AML LeadName.
141 **/
142 BOOLEAN
143 EFIAPI
144 AmlIsLeadNameChar (
145 IN CHAR8 Ch
146 )
147 {
148 if ((Ch == '_') || ((Ch >= 'A') && (Ch <= 'Z')) || ((Ch >= 'a') && (Ch <= 'z'))) {
149 return TRUE;
150 } else {
151 return FALSE;
152 }
153 }
154
155 /** Check whether Ch is an ASL/AML NameChar.
156
157 This function works for both ASL and AML pathnames.
158
159 ACPI 6.3 specification, s19.2.2. "ASL Name and Pathname Terms":
160 NameChar := DigitChar | LeadNameChar
161 LeadNameChar := 'A'-'Z' | 'a'-'z' | '_'
162 DigitChar := '0'-'9'
163
164 ACPI 6.3 specification, s20.2.2. "Name Objects Encoding":
165 NameChar := DigitChar | LeadNameChar
166 LeadNameChar := 'A'-'Z' | 'a'-'z' | '_'
167 DigitChar := '0'-'9'
168
169 @param [in] Ch The char to test.
170
171 @retval TRUE Ch is an ASL/AML NameChar.
172 @retval FALSE Ch is not an ASL/AML NameChar.
173 **/
174 BOOLEAN
175 EFIAPI
176 AmlIsNameChar (
177 IN CHAR8 Ch
178 )
179 {
180 if (AmlIsLeadNameChar (Ch) || ((Ch >= '0') && (Ch <= '9'))) {
181 return TRUE;
182 } else {
183 return FALSE;
184 }
185 }
186
187 /** Check whether AslBuffer is an ASL NameSeg.
188
189 This function only works for ASL NameStrings/pathnames.
190 ASL NameStrings/pathnames are at most 4 chars long.
191
192 @param [in] AslBuffer Pointer in an ASL NameString/pathname.
193 @param [out] Size Size of the NameSeg.
194
195 @retval TRUE AslBuffer is an ASL NameSeg.
196 @retval FALSE AslBuffer is not an ASL NameSeg.
197 **/
198 BOOLEAN
199 EFIAPI
200 AslIsNameSeg (
201 IN CONST CHAR8 *AslBuffer,
202 OUT UINT32 *Size
203 )
204 {
205 UINT32 Index;
206
207 if ((AslBuffer == NULL) ||
208 (Size == NULL))
209 {
210 return FALSE;
211 }
212
213 if (!AmlIsLeadNameChar (AslBuffer[0])) {
214 return FALSE;
215 }
216
217 for (Index = 1; Index < AML_NAME_SEG_SIZE; Index++) {
218 if ((AslBuffer[Index] == '.') ||
219 (AslBuffer[Index] == '\0'))
220 {
221 *Size = Index;
222 return TRUE;
223 } else if (!AmlIsNameChar (AslBuffer[Index])) {
224 return FALSE;
225 }
226 }
227
228 *Size = Index;
229 return TRUE;
230 }
231
232 /** Check whether AmlBuffer is an AML NameSeg.
233
234 This function only works for AML NameStrings/pathnames.
235 AML NameStrings/pathnames must be 4 chars long.
236
237 @param [in] AmlBuffer Pointer in an AML NameString/pathname.
238
239 @retval TRUE AmlBuffer is an AML NameSeg.
240 @retval FALSE AmlBuffer is not an AML NameSeg.
241 **/
242 BOOLEAN
243 EFIAPI
244 AmlIsNameSeg (
245 IN CONST CHAR8 *AmlBuffer
246 )
247 {
248 UINT32 Index;
249
250 if (AmlBuffer == NULL) {
251 return FALSE;
252 }
253
254 if (!AmlIsLeadNameChar (AmlBuffer[0])) {
255 return FALSE;
256 }
257
258 for (Index = 1; Index < AML_NAME_SEG_SIZE; Index++) {
259 if (!AmlIsNameChar (AmlBuffer[Index])) {
260 return FALSE;
261 }
262 }
263
264 return TRUE;
265 }
266
267 /** Parse an ASL NameString/path.
268
269 An ASL NameString/path must be NULL terminated.
270 Information found in the ASL NameString/path is returned via pointers:
271 Root, ParentPrefix, SegCount.
272
273 @param [in] Buffer ASL NameString/path.
274 @param [out] Root Pointer holding the number of root char.
275 Can be 0 or 1.
276 @param [out] ParentPrefix Pointer holding the number of carets char ('^').
277 Can be [0-255].
278 @param [out] SegCount Pointer holding the number of NameSeg (s).
279 Can be [0-255].
280
281 @retval EFI_SUCCESS The function completed successfully.
282 @retval EFI_INVALID_PARAMETER Invalid parameter.
283 **/
284 EFI_STATUS
285 EFIAPI
286 AslParseNameStringInfo (
287 IN CONST CHAR8 *Buffer,
288 OUT UINT32 *Root,
289 OUT UINT32 *ParentPrefix,
290 OUT UINT32 *SegCount
291 )
292 {
293 UINT32 NameSegSize;
294
295 if ((Buffer == NULL) ||
296 (Root == NULL) ||
297 (ParentPrefix == NULL) ||
298 (SegCount == NULL))
299 {
300 ASSERT (0);
301 return EFI_INVALID_PARAMETER;
302 }
303
304 *Root = 0;
305 *ParentPrefix = 0;
306 *SegCount = 0;
307
308 // Handle Root and ParentPrefix(s).
309 if (*Buffer == AML_ROOT_CHAR) {
310 *Root = 1;
311 Buffer++;
312 } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
313 do {
314 Buffer++;
315 (*ParentPrefix)++;
316 } while (*Buffer == AML_PARENT_PREFIX_CHAR);
317 }
318
319 // Handle SegCount(s).
320 while (AslIsNameSeg (Buffer, &NameSegSize)) {
321 // Safety checks on NameSegSize.
322 if ((NameSegSize == 0) || (NameSegSize > AML_NAME_SEG_SIZE)) {
323 ASSERT (0);
324 return EFI_INVALID_PARAMETER;
325 }
326
327 // Increment the NameSeg count.
328 (*SegCount)++;
329 Buffer += NameSegSize;
330
331 // Skip the '.' separator if present.
332 if (*Buffer == '.') {
333 Buffer++;
334 }
335 } // while
336
337 // An ASL NameString/path must be NULL terminated.
338 if (*Buffer != '\0') {
339 ASSERT (0);
340 return EFI_INVALID_PARAMETER;
341 }
342
343 if (!AmlIsNameString (*Root, *ParentPrefix, *SegCount)) {
344 ASSERT (0);
345 return EFI_INVALID_PARAMETER;
346 }
347
348 return EFI_SUCCESS;
349 }
350
351 /** Parse an AML NameString/path.
352
353 It is possible to determine the size of an AML NameString/path just
354 by sight reading it. So no overflow can occur.
355 Information found in the AML NameString/path is returned via pointers:
356 Root, ParentPrefix, SegCount.
357
358 @param [in] Buffer AML NameString/path.
359 @param [out] Root Pointer holding the number of root char.
360 Can be 0 or 1.
361 @param [out] ParentPrefix Pointer holding the number of carets char ('^').
362 Can be [0-255].
363 @param [out] SegCount Pointer holding the number of NameSeg(s).
364 Can be [0-255].
365
366 @retval EFI_SUCCESS The function completed successfully.
367 @retval EFI_INVALID_PARAMETER Invalid parameter.
368 **/
369 EFI_STATUS
370 EFIAPI
371 AmlParseNameStringInfo (
372 IN CONST CHAR8 *Buffer,
373 OUT UINT32 *Root,
374 OUT UINT32 *ParentPrefix,
375 OUT UINT32 *SegCount
376 )
377 {
378 if ((Buffer == NULL) ||
379 (Root == NULL) ||
380 (ParentPrefix == NULL) ||
381 (SegCount == NULL))
382 {
383 ASSERT (0);
384 return EFI_INVALID_PARAMETER;
385 }
386
387 *Root = 0;
388 *ParentPrefix = 0;
389 *SegCount = 0;
390
391 // Handle Root and ParentPrefix(s).
392 if (*Buffer == AML_ROOT_CHAR) {
393 *Root = 1;
394 Buffer++;
395 } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
396 do {
397 Buffer++;
398 (*ParentPrefix)++;
399 } while (*Buffer == AML_PARENT_PREFIX_CHAR);
400 }
401
402 // Handle SegCount(s).
403 if (*Buffer == AML_DUAL_NAME_PREFIX) {
404 *SegCount = 2;
405 } else if (*Buffer == AML_MULTI_NAME_PREFIX) {
406 *SegCount = *((UINT8 *)(Buffer + 1));
407 } else if (AmlIsNameSeg (Buffer)) {
408 *SegCount = 1;
409 } else if (*Buffer == AML_ZERO_OP) {
410 *SegCount = 0;
411 } else {
412 ASSERT (0);
413 return EFI_INVALID_PARAMETER;
414 }
415
416 // Safety checks on exit.
417 if (!AmlIsNameString (*Root, *ParentPrefix, *SegCount)) {
418 ASSERT (0);
419 return EFI_INVALID_PARAMETER;
420 }
421
422 return EFI_SUCCESS;
423 }
424
425 /** Compute the ASL NameString/path size from NameString
426 information (Root, ParentPrefix, SegCount).
427
428 @param [in] Root Number of root char.
429 Can be 0 or 1.
430 @param [in] ParentPrefix Number of carets char ('^').
431 Can be [0-255].
432 @param [in] SegCount Pointer holding the number of NameSeg(s).
433 Can be [0-255].
434
435 @return Size of the ASL NameString/path.
436 **/
437 UINT32
438 EFIAPI
439 AslComputeNameStringSize (
440 IN UINT32 Root,
441 IN UINT32 ParentPrefix,
442 IN UINT32 SegCount
443 )
444 {
445 UINT32 TotalSize;
446
447 if (!AmlIsNameString (Root, ParentPrefix, SegCount)) {
448 ASSERT (0);
449 return 0;
450 }
451
452 // Root and ParentPrefix(s).
453 TotalSize = Root + ParentPrefix;
454
455 // Add size required for NameSeg(s).
456 TotalSize += (SegCount * AML_NAME_SEG_SIZE);
457
458 // Add size required for '.' separator(s).
459 TotalSize += (SegCount > 1) ? (SegCount - 1) : 0;
460
461 // Add 1 byte for NULL termination '\0'.
462 TotalSize += 1;
463
464 return TotalSize;
465 }
466
467 /** Compute the AML NameString/path size from NameString
468 information (Root, ParentPrefix, SegCount).
469
470 @param [in] Root Number of root char.
471 Can be 0 or 1.
472 @param [in] ParentPrefix Number of carets char ('^').
473 Can be [0-255].
474 @param [in] SegCount Pointer holding the number of NameSeg(s).
475 Can be [0-255].
476
477 @return Size of the AML NameString/path.
478 **/
479 UINT32
480 EFIAPI
481 AmlComputeNameStringSize (
482 IN UINT32 Root,
483 IN UINT32 ParentPrefix,
484 IN UINT32 SegCount
485 )
486 {
487 UINT32 TotalSize;
488
489 if (!AmlIsNameString (Root, ParentPrefix, SegCount)) {
490 ASSERT (0);
491 return 0;
492 }
493
494 // Root and ParentPrefix(s).
495 TotalSize = Root + ParentPrefix;
496
497 // If SegCount == 0, '\0' must end the AML NameString/path.
498 TotalSize += (SegCount == 0) ? 1 : (SegCount * AML_NAME_SEG_SIZE);
499
500 // AML prefix. SegCount > 2 = MultiNamePrefix, SegCount = 2 DualNamePrefix.
501 TotalSize += (SegCount > 2) ? 2 : ((SegCount == 2) ? 1 : 0);
502
503 return TotalSize;
504 }
505
506 /** Get the ASL NameString/path size.
507
508 @param [in] AslPath An ASL NameString/path.
509 @param [out] AslPathSizePtr Pointer holding the ASL NameString/path size.
510
511 @retval EFI_SUCCESS Success.
512 @retval EFI_INVALID_PARAMETER Invalid parameter.
513 **/
514 EFI_STATUS
515 EFIAPI
516 AslGetNameStringSize (
517 IN CONST CHAR8 *AslPath,
518 OUT UINT32 *AslPathSizePtr
519 )
520 {
521 if ((AslPath == NULL) ||
522 (AslPathSizePtr == NULL))
523 {
524 ASSERT (0);
525 return EFI_INVALID_PARAMETER;
526 }
527
528 *AslPathSizePtr = 0;
529 do {
530 (*AslPathSizePtr)++;
531 AslPath++;
532 } while (*AslPath != '\0');
533
534 return EFI_SUCCESS;
535 }
536
537 /** Get the AML NameString/path size.
538
539 @param [in] AmlPath An AML NameString/path.
540 @param [out] AmlPathSizePtr Pointer holding the AML NameString/path size.
541
542 @retval EFI_SUCCESS Success.
543 @retval EFI_INVALID_PARAMETER Invalid parameter.
544 **/
545 EFI_STATUS
546 EFIAPI
547 AmlGetNameStringSize (
548 IN CONST CHAR8 *AmlPath,
549 OUT UINT32 *AmlPathSizePtr
550 )
551 {
552 EFI_STATUS Status;
553
554 UINT32 Root;
555 UINT32 ParentPrefix;
556 UINT32 SegCount;
557
558 if ((AmlPath == NULL) ||
559 (AmlPathSizePtr == NULL))
560 {
561 ASSERT (0);
562 return EFI_INVALID_PARAMETER;
563 }
564
565 Status = AmlParseNameStringInfo (
566 AmlPath,
567 &Root,
568 &ParentPrefix,
569 &SegCount
570 );
571 if (EFI_ERROR (Status)) {
572 ASSERT (0);
573 return Status;
574 }
575
576 *AmlPathSizePtr = AmlComputeNameStringSize (Root, ParentPrefix, SegCount);
577 if (*AmlPathSizePtr == 0) {
578 ASSERT (0);
579 return EFI_INVALID_PARAMETER;
580 }
581
582 return Status;
583 }
584
585 /** Convert an ASL NameString/path to an AML NameString/path.
586 The caller must free the memory allocated in this function
587 for AmlPath using FreePool ().
588
589 @param [in] AslPath An ASL NameString/path.
590 @param [out] OutAmlPath Buffer containing the AML path.
591
592 @retval EFI_SUCCESS Success.
593 @retval EFI_INVALID_PARAMETER Invalid parameter.
594 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
595 **/
596 EFI_STATUS
597 EFIAPI
598 ConvertAslNameToAmlName (
599 IN CONST CHAR8 *AslPath,
600 OUT CHAR8 **OutAmlPath
601 )
602 {
603 EFI_STATUS Status;
604
605 UINT32 Root;
606 UINT32 ParentPrefix;
607 UINT32 SegCount;
608 UINT32 TotalSize;
609 UINT32 NameSegSize;
610
611 CONST CHAR8 *AslBuffer;
612 CHAR8 *AmlBuffer;
613 CHAR8 *AmlPath;
614
615 if ((AslPath == NULL) ||
616 (OutAmlPath == NULL))
617 {
618 return EFI_INVALID_PARAMETER;
619 }
620
621 // Analyze AslPath. AslPath is checked in the call.
622 Status = AslParseNameStringInfo (AslPath, &Root, &ParentPrefix, &SegCount);
623 if (EFI_ERROR (Status)) {
624 ASSERT (0);
625 return Status;
626 }
627
628 // Compute TotalSize.
629 TotalSize = AmlComputeNameStringSize (Root, ParentPrefix, SegCount);
630 if (TotalSize == 0) {
631 ASSERT (0);
632 return EFI_INVALID_PARAMETER;
633 }
634
635 // Allocate memory.
636 AmlPath = AllocateZeroPool (TotalSize);
637 if (AmlPath == NULL) {
638 ASSERT (0);
639 return EFI_OUT_OF_RESOURCES;
640 }
641
642 AmlBuffer = AmlPath;
643 AslBuffer = AslPath;
644
645 // Handle Root and ParentPrefix(s).
646 if (Root == 1) {
647 *AmlBuffer = AML_ROOT_CHAR;
648 AmlBuffer++;
649 AslBuffer++;
650 } else if (ParentPrefix > 0) {
651 SetMem (AmlBuffer, ParentPrefix, AML_PARENT_PREFIX_CHAR);
652 AmlBuffer += ParentPrefix;
653 AslBuffer += ParentPrefix;
654 }
655
656 // Handle prefix and SegCount(s).
657 if (SegCount > 2) {
658 *AmlBuffer = AML_MULTI_NAME_PREFIX;
659 AmlBuffer++;
660 *AmlBuffer = (UINT8)SegCount;
661 AmlBuffer++;
662 } else if (SegCount == 2) {
663 *AmlBuffer = AML_DUAL_NAME_PREFIX;
664 AmlBuffer++;
665 }
666
667 if (SegCount != 0) {
668 // Write NameSeg(s).
669 while (1) {
670 SegCount--;
671
672 // Get the NameSeg size.
673 if (!AslIsNameSeg (AslBuffer, &NameSegSize)) {
674 ASSERT (0);
675 Status = EFI_INVALID_PARAMETER;
676 goto error_handler;
677 }
678
679 // Convert to Upper case and copy.
680 Status = AmlUpperCaseMemCpyS (
681 AmlBuffer,
682 TotalSize,
683 AslBuffer,
684 NameSegSize
685 );
686 if (EFI_ERROR (Status)) {
687 ASSERT (0);
688 goto error_handler;
689 }
690
691 // Complete the NameSeg with an underscore ('_') if shorter than 4 bytes.
692 SetMem (
693 AmlBuffer + NameSegSize,
694 AML_NAME_SEG_SIZE - NameSegSize,
695 AML_NAME_CHAR__
696 );
697
698 // Go to the next NameSeg.
699 AmlBuffer += AML_NAME_SEG_SIZE;
700 AslBuffer += NameSegSize;
701
702 // Skip the '.' separator.
703 if (SegCount != 0) {
704 if (*AslBuffer == '.') {
705 AslBuffer++;
706 } else {
707 ASSERT (0);
708 Status = EFI_INVALID_PARAMETER;
709 goto error_handler;
710 }
711 } else {
712 // (SegCount == 0)
713 if (*AslBuffer == '\0') {
714 break;
715 } else {
716 ASSERT (0);
717 Status = EFI_INVALID_PARAMETER;
718 goto error_handler;
719 }
720 }
721 } // while
722 } else {
723 // (SegCount == 0)
724 // '\0' needs to end the AML NameString/path.
725 *AmlBuffer = AML_ZERO_OP;
726 AmlBuffer++;
727 }
728
729 // Safety checks on exit.
730 // Check that AmlPath has been filled with TotalSize bytes.
731 if ((SegCount != 0) ||
732 (*AslBuffer != AML_ZERO_OP) ||
733 (((UINT32)(AmlBuffer - AmlPath)) != TotalSize))
734 {
735 ASSERT (0);
736 Status = EFI_INVALID_PARAMETER;
737 goto error_handler;
738 }
739
740 *OutAmlPath = AmlPath;
741 return EFI_SUCCESS;
742
743 error_handler:
744 FreePool (AmlPath);
745 return Status;
746 }
747
748 /** Convert an AML NameString/path to an ASL NameString/path.
749 The caller must free the memory allocated in this function.
750 using FreePool ().
751
752 @param [in] AmlPath An AML NameString/path.
753 @param [out] OutAslPath Buffer containing the ASL path.
754
755 @retval EFI_SUCCESS Success.
756 @retval EFI_INVALID_PARAMETER Invalid parameter.
757 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
758 **/
759 EFI_STATUS
760 EFIAPI
761 ConvertAmlNameToAslName (
762 IN CONST CHAR8 *AmlPath,
763 OUT CHAR8 **OutAslPath
764 )
765 {
766 EFI_STATUS Status;
767
768 UINT32 Root;
769 UINT32 ParentPrefix;
770 UINT32 SegCount;
771 UINT32 TotalSize;
772
773 CONST CHAR8 *AmlBuffer;
774 CHAR8 *AslBuffer;
775 CHAR8 *AslPath;
776
777 if ((AmlPath == NULL) ||
778 (OutAslPath == NULL))
779 {
780 ASSERT (0);
781 return EFI_INVALID_PARAMETER;
782 }
783
784 // Analyze AslPath. AmlPath is checked in the call.
785 Status = AmlParseNameStringInfo (AmlPath, &Root, &ParentPrefix, &SegCount);
786 if (EFI_ERROR (Status)) {
787 ASSERT (0);
788 return Status;
789 }
790
791 // Compute TotalSize.
792 TotalSize = AslComputeNameStringSize (Root, ParentPrefix, SegCount);
793 if (TotalSize == 0) {
794 ASSERT (0);
795 return EFI_INVALID_PARAMETER;
796 }
797
798 // Allocate memory.
799 AslPath = AllocateZeroPool (TotalSize);
800 if (AslPath == NULL) {
801 ASSERT (0);
802 return EFI_OUT_OF_RESOURCES;
803 }
804
805 AmlBuffer = AmlPath;
806 AslBuffer = AslPath;
807
808 // Handle prefix and SegCount(s).
809 if (Root == 1) {
810 *AslBuffer = AML_ROOT_CHAR;
811 AslBuffer++;
812 AmlBuffer++;
813 } else if (ParentPrefix > 0) {
814 SetMem (AslBuffer, ParentPrefix, AML_PARENT_PREFIX_CHAR);
815 AslBuffer += ParentPrefix;
816 AmlBuffer += ParentPrefix;
817 }
818
819 // Handle Root and Parent(s).
820 // Skip the MultiName or DualName prefix chars.
821 if (SegCount > 2) {
822 AmlBuffer += 2;
823 } else if (SegCount == 2) {
824 AmlBuffer += 1;
825 }
826
827 // Write NameSeg(s).
828 while (SegCount) {
829 // NameSeg is already in upper case and always 4 bytes long.
830 CopyMem (AslBuffer, AmlBuffer, AML_NAME_SEG_SIZE);
831 AslBuffer += AML_NAME_SEG_SIZE;
832 AmlBuffer += AML_NAME_SEG_SIZE;
833
834 SegCount--;
835
836 // Write the '.' separator if there is another NameSeg following.
837 if (SegCount != 0) {
838 *AslBuffer = '.';
839 AslBuffer++;
840 }
841 } // while
842
843 // NULL terminate the ASL NameString.
844 *AslBuffer = '\0';
845 AslBuffer++;
846
847 // Safety checks on exit.
848 // Check that AslPath has been filled with TotalSize bytes.
849 if (((UINT32)(AslBuffer - AslPath)) != TotalSize) {
850 ASSERT (0);
851 Status = EFI_INVALID_PARAMETER;
852 goto error_handler;
853 }
854
855 *OutAslPath = AslPath;
856 return EFI_SUCCESS;
857
858 error_handler:
859 FreePool (AslPath);
860 return Status;
861 }
862
863 /** Compare two ASL NameStrings.
864
865 @param [in] AslName1 First NameString to compare.
866 @param [in] AslName2 Second NameString to compare.
867
868 @retval TRUE if the two strings are identical.
869 @retval FALSE otherwise, or if error.
870 **/
871 BOOLEAN
872 EFIAPI
873 AslCompareNameString (
874 IN CONST CHAR8 *AslName1,
875 IN CONST CHAR8 *AslName2
876 )
877 {
878 EFI_STATUS Status;
879 UINT32 AslName1Len;
880 UINT32 AslName2Len;
881
882 if ((AslName1 == NULL) ||
883 (AslName2 == NULL))
884 {
885 ASSERT (0);
886 return FALSE;
887 }
888
889 Status = AslGetNameStringSize (AslName1, &AslName1Len);
890 if (EFI_ERROR (Status)) {
891 ASSERT (0);
892 return FALSE;
893 }
894
895 Status = AslGetNameStringSize (AslName2, &AslName2Len);
896 if (EFI_ERROR (Status)) {
897 ASSERT (0);
898 return FALSE;
899 }
900
901 // AslName1 and AslName2 don't have the same length
902 if (AslName1Len != AslName2Len) {
903 return FALSE;
904 }
905
906 return (CompareMem (AslName1, AslName2, AslName1Len) == 0);
907 }
908
909 /** Compare two AML NameStrings.
910
911 @param [in] AmlName1 First NameString to compare.
912 @param [in] AmlName2 Second NameString to compare.
913
914 @retval TRUE if the two strings are identical.
915 @retval FALSE otherwise, or if error.
916 **/
917 BOOLEAN
918 EFIAPI
919 AmlCompareNameString (
920 IN CONST CHAR8 *AmlName1,
921 IN CONST CHAR8 *AmlName2
922 )
923 {
924 EFI_STATUS Status;
925 UINT32 AmlName1Len;
926 UINT32 AmlName2Len;
927
928 if ((AmlName1 == NULL) ||
929 (AmlName2 == NULL))
930 {
931 ASSERT (0);
932 return FALSE;
933 }
934
935 Status = AmlGetNameStringSize (AmlName1, &AmlName1Len);
936 if (EFI_ERROR (Status)) {
937 ASSERT (0);
938 return FALSE;
939 }
940
941 Status = AmlGetNameStringSize (AmlName2, &AmlName2Len);
942 if (EFI_ERROR (Status)) {
943 ASSERT (0);
944 return FALSE;
945 }
946
947 // AmlName1 and AmlName2 don't have the same length
948 if (AmlName1Len != AmlName2Len) {
949 return FALSE;
950 }
951
952 return (CompareMem (AmlName1, AmlName2, AmlName1Len) == 0);
953 }
954
955 /** Compare an AML NameString and an ASL NameString.
956
957 The ASL NameString is converted to an AML NameString before
958 being compared with the ASL NameString. This allows to expand
959 NameSegs shorter than 4 chars.
960 E.g.: AslName: "DEV" will be expanded to "DEV_" before being
961 compared.
962
963 @param [in] AmlName1 AML NameString to compare.
964 @param [in] AslName2 ASL NameString to compare.
965
966 @retval TRUE if the two strings are identical.
967 @retval FALSE otherwise, or if error.
968 **/
969 BOOLEAN
970 EFIAPI
971 CompareAmlWithAslNameString (
972 IN CONST CHAR8 *AmlName1,
973 IN CONST CHAR8 *AslName2
974 )
975 {
976 EFI_STATUS Status;
977
978 CHAR8 *AmlName2;
979 BOOLEAN RetVal;
980
981 if ((AmlName1 == NULL) ||
982 (AslName2 == NULL))
983 {
984 ASSERT (0);
985 return FALSE;
986 }
987
988 // Convert the AslName2 to an AmlName2.
989 // AmlName2 must be freed.
990 Status = ConvertAmlNameToAslName (AslName2, &AmlName2);
991 if (EFI_ERROR (Status)) {
992 ASSERT (0);
993 return FALSE;
994 }
995
996 RetVal = AmlCompareNameString (AmlName1, AmlName2);
997
998 // Free AmlName2.
999 FreePool (AmlName2);
1000
1001 return RetVal;
1002 }
1003
1004 /** Given an AmlPath, return the address of the first NameSeg.
1005
1006 It is possible to determine the size of an AML NameString/path just
1007 by sight reading it. So no overflow can occur.
1008
1009 @param [in] AmlPath The AML pathname.
1010 @param [in] Root The AML pathname starts with a root char.
1011 It is an absolute path.
1012 @param [in] ParentPrefix The AML pathname has ParentPrefix
1013 carets in its name.
1014
1015 @return Pointer to the first NameSeg of the NameString.
1016 Return NULL if AmlPath is NULL.
1017 **/
1018 CONST
1019 CHAR8 *
1020 EFIAPI
1021 AmlGetFirstNameSeg (
1022 IN CONST CHAR8 *AmlPath,
1023 IN UINT32 Root,
1024 IN UINT32 ParentPrefix
1025 )
1026 {
1027 if (AmlPath == NULL) {
1028 ASSERT (0);
1029 return NULL;
1030 }
1031
1032 AmlPath += Root;
1033 AmlPath += ParentPrefix;
1034 AmlPath += ((*AmlPath == AML_MULTI_NAME_PREFIX) ? 2
1035 : (*AmlPath == AML_DUAL_NAME_PREFIX) ? 1 : 0);
1036 return AmlPath;
1037 }