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