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