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