Home | History | Annotate | Download | only in AcpiTableDxe
      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 **/
     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 
    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 **/
    190 BOOLEAN
    191 AmlIsAslLeadName (
    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 **/
    210 BOOLEAN
    211 AmlIsAslName (
    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 **/
    229 UINTN
    230 AmlGetAslNameSegLength (
    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 **/
    281 UINTN
    282 AmlGetAslNameStringSize (
    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 **/
    355 VOID
    356 AmlUpperCaseCopyMem (
    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 **/
    381 UINT8 *
    382 AmlNameFromAslName (
    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 **/
    461 VOID
    462 AmlPrintNameSeg (
    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 **/
    487 VOID
    488 AmlPrintNameString (
    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