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