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