167754Smsmith/****************************************************************************** 267754Smsmith * 367754Smsmith * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing 467754Smsmith * parents and siblings and Scope manipulation 567754Smsmith * 667754Smsmith *****************************************************************************/ 767754Smsmith 8217365Sjkim/* 9217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp. 1070243Smsmith * All rights reserved. 1167754Smsmith * 12217365Sjkim * Redistribution and use in source and binary forms, with or without 13217365Sjkim * modification, are permitted provided that the following conditions 14217365Sjkim * are met: 15217365Sjkim * 1. Redistributions of source code must retain the above copyright 16217365Sjkim * notice, this list of conditions, and the following disclaimer, 17217365Sjkim * without modification. 18217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 20217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 21217365Sjkim * including a substantially similar Disclaimer requirement for further 22217365Sjkim * binary redistribution. 23217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 24217365Sjkim * of any contributors may be used to endorse or promote products derived 25217365Sjkim * from this software without specific prior written permission. 2667754Smsmith * 27217365Sjkim * Alternatively, this software may be distributed under the terms of the 28217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 29217365Sjkim * Software Foundation. 3067754Smsmith * 31217365Sjkim * NO WARRANTY 32217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 43217365Sjkim */ 4467754Smsmith 4567754Smsmith#define __NSUTILS_C__ 4667754Smsmith 47193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 48193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 49193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 50193341Sjkim#include <contrib/dev/acpica/include/amlcode.h> 5167754Smsmith 5277424Smsmith#define _COMPONENT ACPI_NAMESPACE 5391116Smsmith ACPI_MODULE_NAME ("nsutils") 5467754Smsmith 55151937Sjkim/* Local prototypes */ 5667754Smsmith 57151937Sjkimstatic BOOLEAN 58151937SjkimAcpiNsValidPathSeparator ( 59151937Sjkim char Sep); 60151937Sjkim 61151937Sjkim#ifdef ACPI_OBSOLETE_FUNCTIONS 62151937SjkimACPI_NAME 63151937SjkimAcpiNsFindParentName ( 64151937Sjkim ACPI_NAMESPACE_NODE *NodeToSearch); 65151937Sjkim#endif 66151937Sjkim 67151937Sjkim 6877424Smsmith/******************************************************************************* 6967754Smsmith * 70114237Snjl * FUNCTION: AcpiNsPrintNodePathname 71114237Snjl * 72151937Sjkim * PARAMETERS: Node - Object 73151937Sjkim * Message - Prefix message 74114237Snjl * 75114237Snjl * DESCRIPTION: Print an object's full namespace pathname 76114237Snjl * Manages allocation/freeing of a pathname buffer 77114237Snjl * 78114237Snjl ******************************************************************************/ 79114237Snjl 80114237Snjlvoid 81114237SnjlAcpiNsPrintNodePathname ( 82114237Snjl ACPI_NAMESPACE_NODE *Node, 83193267Sjkim const char *Message) 84114237Snjl{ 85114237Snjl ACPI_BUFFER Buffer; 86114237Snjl ACPI_STATUS Status; 87114237Snjl 88114237Snjl 89123315Snjl if (!Node) 90123315Snjl { 91123315Snjl AcpiOsPrintf ("[NULL NAME]"); 92123315Snjl return; 93123315Snjl } 94123315Snjl 95138287Smarks /* Convert handle to full pathname and print it (with supplied message) */ 96114237Snjl 97114237Snjl Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 98114237Snjl 99114237Snjl Status = AcpiNsHandleToPathname (Node, &Buffer); 100114237Snjl if (ACPI_SUCCESS (Status)) 101114237Snjl { 102151937Sjkim if (Message) 103117521Snjl { 104151937Sjkim AcpiOsPrintf ("%s ", Message); 105117521Snjl } 106117521Snjl 107117521Snjl AcpiOsPrintf ("[%s] (Node %p)", (char *) Buffer.Pointer, Node); 108167802Sjkim ACPI_FREE (Buffer.Pointer); 109114237Snjl } 110114237Snjl} 111114237Snjl 112114237Snjl 113114237Snjl/******************************************************************************* 114114237Snjl * 11567754Smsmith * FUNCTION: AcpiNsValidRootPrefix 11667754Smsmith * 11767754Smsmith * PARAMETERS: Prefix - Character to be checked 11867754Smsmith * 11967754Smsmith * RETURN: TRUE if a valid prefix 12067754Smsmith * 12167754Smsmith * DESCRIPTION: Check if a character is a valid ACPI Root prefix 12267754Smsmith * 12377424Smsmith ******************************************************************************/ 12467754Smsmith 12567754SmsmithBOOLEAN 12667754SmsmithAcpiNsValidRootPrefix ( 127114237Snjl char Prefix) 12867754Smsmith{ 12967754Smsmith 13067754Smsmith return ((BOOLEAN) (Prefix == '\\')); 13167754Smsmith} 13267754Smsmith 13367754Smsmith 13477424Smsmith/******************************************************************************* 13567754Smsmith * 13667754Smsmith * FUNCTION: AcpiNsValidPathSeparator 13767754Smsmith * 138151937Sjkim * PARAMETERS: Sep - Character to be checked 13967754Smsmith * 14067754Smsmith * RETURN: TRUE if a valid path separator 14167754Smsmith * 14267754Smsmith * DESCRIPTION: Check if a character is a valid ACPI path separator 14367754Smsmith * 14477424Smsmith ******************************************************************************/ 14567754Smsmith 146151937Sjkimstatic BOOLEAN 14767754SmsmithAcpiNsValidPathSeparator ( 148114237Snjl char Sep) 14967754Smsmith{ 15067754Smsmith 15167754Smsmith return ((BOOLEAN) (Sep == '.')); 15267754Smsmith} 15367754Smsmith 15467754Smsmith 15577424Smsmith/******************************************************************************* 15667754Smsmith * 15767754Smsmith * FUNCTION: AcpiNsGetType 15867754Smsmith * 159151937Sjkim * PARAMETERS: Node - Parent Node to be examined 16067754Smsmith * 16167754Smsmith * RETURN: Type field from Node whose handle is passed 16267754Smsmith * 163151937Sjkim * DESCRIPTION: Return the type of a Namespace node 164151937Sjkim * 16577424Smsmith ******************************************************************************/ 16667754Smsmith 16791116SmsmithACPI_OBJECT_TYPE 16867754SmsmithAcpiNsGetType ( 16977424Smsmith ACPI_NAMESPACE_NODE *Node) 17067754Smsmith{ 171167802Sjkim ACPI_FUNCTION_TRACE (NsGetType); 17267754Smsmith 17367754Smsmith 17477424Smsmith if (!Node) 17567754Smsmith { 176167802Sjkim ACPI_WARNING ((AE_INFO, "Null Node parameter")); 177151937Sjkim return_UINT32 (ACPI_TYPE_ANY); 17867754Smsmith } 17967754Smsmith 180151937Sjkim return_UINT32 ((ACPI_OBJECT_TYPE) Node->Type); 18167754Smsmith} 18267754Smsmith 18367754Smsmith 18477424Smsmith/******************************************************************************* 18567754Smsmith * 18667754Smsmith * FUNCTION: AcpiNsLocal 18767754Smsmith * 188151937Sjkim * PARAMETERS: Type - A namespace object type 18967754Smsmith * 19067754Smsmith * RETURN: LOCAL if names must be found locally in objects of the 19167754Smsmith * passed type, 0 if enclosing scopes should be searched 19267754Smsmith * 193151937Sjkim * DESCRIPTION: Returns scope rule for the given object type. 194151937Sjkim * 19577424Smsmith ******************************************************************************/ 19667754Smsmith 19767754SmsmithUINT32 19867754SmsmithAcpiNsLocal ( 19991116Smsmith ACPI_OBJECT_TYPE Type) 20067754Smsmith{ 201167802Sjkim ACPI_FUNCTION_TRACE (NsLocal); 20267754Smsmith 20367754Smsmith 20477424Smsmith if (!AcpiUtValidObjectType (Type)) 20567754Smsmith { 20667754Smsmith /* Type code out of range */ 20767754Smsmith 208204773Sjkim ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type)); 209151937Sjkim return_UINT32 (ACPI_NS_NORMAL); 21067754Smsmith } 21167754Smsmith 212151937Sjkim return_UINT32 ((UINT32) AcpiGbl_NsProperties[Type] & ACPI_NS_LOCAL); 21367754Smsmith} 21467754Smsmith 21567754Smsmith 21677424Smsmith/******************************************************************************* 21767754Smsmith * 21877424Smsmith * FUNCTION: AcpiNsGetInternalNameLength 21967754Smsmith * 22083174Smsmith * PARAMETERS: Info - Info struct initialized with the 22177424Smsmith * external name pointer. 22267754Smsmith * 223151937Sjkim * RETURN: None 22467754Smsmith * 22583174Smsmith * DESCRIPTION: Calculate the length of the internal (AML) namestring 22677424Smsmith * corresponding to the external (ASL) namestring. 22767754Smsmith * 22877424Smsmith ******************************************************************************/ 22967754Smsmith 23099679Siwasakivoid 23177424SmsmithAcpiNsGetInternalNameLength ( 23277424Smsmith ACPI_NAMESTRING_INFO *Info) 23367754Smsmith{ 234193267Sjkim const char *NextExternalChar; 23567754Smsmith UINT32 i; 23667754Smsmith 23767754Smsmith 23891116Smsmith ACPI_FUNCTION_ENTRY (); 23983174Smsmith 24083174Smsmith 24177424Smsmith NextExternalChar = Info->ExternalName; 24277424Smsmith Info->NumCarats = 0; 24377424Smsmith Info->NumSegments = 0; 24477424Smsmith Info->FullyQualified = FALSE; 24583174Smsmith 24667754Smsmith /* 247138287Smarks * For the internal name, the required length is 4 bytes per segment, plus 248138287Smarks * 1 each for RootPrefix, MultiNamePrefixOp, segment count, trailing null 249138287Smarks * (which is not really needed, but no there's harm in putting it there) 25067754Smsmith * 251138287Smarks * strlen() + 1 covers the first NameSeg, which has no path separator 25267754Smsmith */ 253193267Sjkim if (AcpiNsValidRootPrefix (*NextExternalChar)) 25467754Smsmith { 25577424Smsmith Info->FullyQualified = TRUE; 25677424Smsmith NextExternalChar++; 257193267Sjkim 258193267Sjkim /* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */ 259193267Sjkim 260193267Sjkim while (AcpiNsValidRootPrefix (*NextExternalChar)) 261193267Sjkim { 262193267Sjkim NextExternalChar++; 263193267Sjkim } 26467754Smsmith } 26569450Smsmith else 26669450Smsmith { 267193267Sjkim /* Handle Carat prefixes */ 268193267Sjkim 26977424Smsmith while (*NextExternalChar == '^') 27069450Smsmith { 27177424Smsmith Info->NumCarats++; 27277424Smsmith NextExternalChar++; 27369450Smsmith } 27469450Smsmith } 27569450Smsmith 27667754Smsmith /* 277138287Smarks * Determine the number of ACPI name "segments" by counting the number of 278138287Smarks * path separators within the string. Start with one segment since the 279138287Smarks * segment count is [(# separators) + 1], and zero separators is ok. 28067754Smsmith */ 28177424Smsmith if (*NextExternalChar) 28267754Smsmith { 28377424Smsmith Info->NumSegments = 1; 28477424Smsmith for (i = 0; NextExternalChar[i]; i++) 28567754Smsmith { 28677424Smsmith if (AcpiNsValidPathSeparator (NextExternalChar[i])) 28769450Smsmith { 28877424Smsmith Info->NumSegments++; 28969450Smsmith } 29067754Smsmith } 29167754Smsmith } 29267754Smsmith 29383174Smsmith Info->Length = (ACPI_NAME_SIZE * Info->NumSegments) + 29477424Smsmith 4 + Info->NumCarats; 29567754Smsmith 29677424Smsmith Info->NextExternalChar = NextExternalChar; 29777424Smsmith} 29867754Smsmith 29967754Smsmith 30077424Smsmith/******************************************************************************* 30177424Smsmith * 30277424Smsmith * FUNCTION: AcpiNsBuildInternalName 30377424Smsmith * 30477424Smsmith * PARAMETERS: Info - Info struct fully initialized 30577424Smsmith * 30677424Smsmith * RETURN: Status 30777424Smsmith * 30883174Smsmith * DESCRIPTION: Construct the internal (AML) namestring 30977424Smsmith * corresponding to the external (ASL) namestring. 31077424Smsmith * 31177424Smsmith ******************************************************************************/ 31277424Smsmith 31377424SmsmithACPI_STATUS 31477424SmsmithAcpiNsBuildInternalName ( 31577424Smsmith ACPI_NAMESTRING_INFO *Info) 31677424Smsmith{ 31777424Smsmith UINT32 NumSegments = Info->NumSegments; 318114237Snjl char *InternalName = Info->InternalName; 319193267Sjkim const char *ExternalName = Info->NextExternalChar; 320114237Snjl char *Result = NULL; 321193267Sjkim UINT32 i; 32277424Smsmith 32377424Smsmith 324167802Sjkim ACPI_FUNCTION_TRACE (NsBuildInternalName); 32577424Smsmith 32683174Smsmith 32767754Smsmith /* Setup the correct prefixes, counts, and pointers */ 32867754Smsmith 32977424Smsmith if (Info->FullyQualified) 33067754Smsmith { 33167754Smsmith InternalName[0] = '\\'; 33269450Smsmith 33369450Smsmith if (NumSegments <= 1) 33469450Smsmith { 33569450Smsmith Result = &InternalName[1]; 33669450Smsmith } 33769450Smsmith else if (NumSegments == 2) 33869450Smsmith { 33969450Smsmith InternalName[1] = AML_DUAL_NAME_PREFIX; 34069450Smsmith Result = &InternalName[2]; 34169450Smsmith } 34269450Smsmith else 34369450Smsmith { 34469450Smsmith InternalName[1] = AML_MULTI_NAME_PREFIX_OP; 34569450Smsmith InternalName[2] = (char) NumSegments; 34669450Smsmith Result = &InternalName[3]; 34769450Smsmith } 34867754Smsmith } 34967754Smsmith else 35067754Smsmith { 35169450Smsmith /* 35269450Smsmith * Not fully qualified. 35369450Smsmith * Handle Carats first, then append the name segments 35469450Smsmith */ 35569450Smsmith i = 0; 35677424Smsmith if (Info->NumCarats) 35769450Smsmith { 35877424Smsmith for (i = 0; i < Info->NumCarats; i++) 35969450Smsmith { 36069450Smsmith InternalName[i] = '^'; 36169450Smsmith } 36269450Smsmith } 36369450Smsmith 36491116Smsmith if (NumSegments <= 1) 36569450Smsmith { 36669450Smsmith Result = &InternalName[i]; 36769450Smsmith } 36869450Smsmith else if (NumSegments == 2) 36969450Smsmith { 37069450Smsmith InternalName[i] = AML_DUAL_NAME_PREFIX; 371193267Sjkim Result = &InternalName[(ACPI_SIZE) i+1]; 37269450Smsmith } 37369450Smsmith else 37469450Smsmith { 37569450Smsmith InternalName[i] = AML_MULTI_NAME_PREFIX_OP; 376193267Sjkim InternalName[(ACPI_SIZE) i+1] = (char) NumSegments; 377193267Sjkim Result = &InternalName[(ACPI_SIZE) i+2]; 37869450Smsmith } 37967754Smsmith } 38067754Smsmith 38167754Smsmith /* Build the name (minus path separators) */ 38267754Smsmith 38367754Smsmith for (; NumSegments; NumSegments--) 38467754Smsmith { 38567754Smsmith for (i = 0; i < ACPI_NAME_SIZE; i++) 38667754Smsmith { 38767754Smsmith if (AcpiNsValidPathSeparator (*ExternalName) || 38867754Smsmith (*ExternalName == 0)) 38967754Smsmith { 39077424Smsmith /* Pad the segment with underscore(s) if segment is short */ 39167754Smsmith 39267754Smsmith Result[i] = '_'; 39367754Smsmith } 39467754Smsmith else 39567754Smsmith { 39677424Smsmith /* Convert the character to uppercase and save it */ 39767754Smsmith 39899679Siwasaki Result[i] = (char) ACPI_TOUPPER ((int) *ExternalName); 39967754Smsmith ExternalName++; 40067754Smsmith } 40167754Smsmith } 40267754Smsmith 40367754Smsmith /* Now we must have a path separator, or the pathname is bad */ 40467754Smsmith 40567754Smsmith if (!AcpiNsValidPathSeparator (*ExternalName) && 40667754Smsmith (*ExternalName != 0)) 40767754Smsmith { 40867754Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 40967754Smsmith } 41067754Smsmith 41167754Smsmith /* Move on the next segment */ 41267754Smsmith 41367754Smsmith ExternalName++; 41467754Smsmith Result += ACPI_NAME_SIZE; 41567754Smsmith } 41667754Smsmith 41777424Smsmith /* Terminate the string */ 41867754Smsmith 41967754Smsmith *Result = 0; 42067754Smsmith 42177424Smsmith if (Info->FullyQualified) 42267754Smsmith { 423123315Snjl ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n", 42499146Siwasaki InternalName, InternalName)); 42567754Smsmith } 42667754Smsmith else 42767754Smsmith { 428123315Snjl ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n", 42999146Siwasaki InternalName, InternalName)); 43067754Smsmith } 43167754Smsmith 43267754Smsmith return_ACPI_STATUS (AE_OK); 43367754Smsmith} 43467754Smsmith 43567754Smsmith 43677424Smsmith/******************************************************************************* 43767754Smsmith * 43877424Smsmith * FUNCTION: AcpiNsInternalizeName 43977424Smsmith * 44077424Smsmith * PARAMETERS: *ExternalName - External representation of name 44177424Smsmith * **Converted Name - Where to return the resulting 44277424Smsmith * internal represention of the name 44377424Smsmith * 44477424Smsmith * RETURN: Status 44577424Smsmith * 44677424Smsmith * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0") 44777424Smsmith * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 44877424Smsmith * 44977424Smsmith *******************************************************************************/ 45077424Smsmith 45177424SmsmithACPI_STATUS 45277424SmsmithAcpiNsInternalizeName ( 453193267Sjkim const char *ExternalName, 454114237Snjl char **ConvertedName) 45577424Smsmith{ 456114237Snjl char *InternalName; 45777424Smsmith ACPI_NAMESTRING_INFO Info; 45877424Smsmith ACPI_STATUS Status; 45977424Smsmith 46077424Smsmith 461167802Sjkim ACPI_FUNCTION_TRACE (NsInternalizeName); 46277424Smsmith 46377424Smsmith 46477424Smsmith if ((!ExternalName) || 46577424Smsmith (*ExternalName == 0) || 46677424Smsmith (!ConvertedName)) 46777424Smsmith { 46877424Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 46977424Smsmith } 47077424Smsmith 47177424Smsmith /* Get the length of the new internal name */ 47277424Smsmith 47377424Smsmith Info.ExternalName = ExternalName; 47477424Smsmith AcpiNsGetInternalNameLength (&Info); 47577424Smsmith 47677424Smsmith /* We need a segment to store the internal name */ 47777424Smsmith 478167802Sjkim InternalName = ACPI_ALLOCATE_ZEROED (Info.Length); 47977424Smsmith if (!InternalName) 48077424Smsmith { 48177424Smsmith return_ACPI_STATUS (AE_NO_MEMORY); 48277424Smsmith } 48377424Smsmith 48477424Smsmith /* Build the name */ 48577424Smsmith 48677424Smsmith Info.InternalName = InternalName; 48777424Smsmith Status = AcpiNsBuildInternalName (&Info); 48877424Smsmith if (ACPI_FAILURE (Status)) 48977424Smsmith { 490167802Sjkim ACPI_FREE (InternalName); 49177424Smsmith return_ACPI_STATUS (Status); 49277424Smsmith } 49377424Smsmith 49477424Smsmith *ConvertedName = InternalName; 49577424Smsmith return_ACPI_STATUS (AE_OK); 49677424Smsmith} 49777424Smsmith 49877424Smsmith 49977424Smsmith/******************************************************************************* 50077424Smsmith * 50167754Smsmith * FUNCTION: AcpiNsExternalizeName 50267754Smsmith * 503151937Sjkim * PARAMETERS: InternalNameLength - Lenth of the internal name below 504151937Sjkim * InternalName - Internal representation of name 505151937Sjkim * ConvertedNameLength - Where the length is returned 506151937Sjkim * ConvertedName - Where the resulting external name 507151937Sjkim * is returned 50867754Smsmith * 50967754Smsmith * RETURN: Status 51067754Smsmith * 51167754Smsmith * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30) 512151937Sjkim * to its external (printable) form (e.g. "\_PR_.CPU0") 51367754Smsmith * 51477424Smsmith ******************************************************************************/ 51567754Smsmith 51667754SmsmithACPI_STATUS 51767754SmsmithAcpiNsExternalizeName ( 51867754Smsmith UINT32 InternalNameLength, 519193267Sjkim const char *InternalName, 52067754Smsmith UINT32 *ConvertedNameLength, 52167754Smsmith char **ConvertedName) 52267754Smsmith{ 523193267Sjkim UINT32 NamesIndex = 0; 524193267Sjkim UINT32 NumSegments = 0; 525193267Sjkim UINT32 RequiredLength; 526193267Sjkim UINT32 PrefixLength = 0; 527193267Sjkim UINT32 i = 0; 528193267Sjkim UINT32 j = 0; 52967754Smsmith 53067754Smsmith 531167802Sjkim ACPI_FUNCTION_TRACE (NsExternalizeName); 53267754Smsmith 53367754Smsmith 53467754Smsmith if (!InternalNameLength || 53567754Smsmith !InternalName || 53667754Smsmith !ConvertedName) 53767754Smsmith { 53867754Smsmith return_ACPI_STATUS (AE_BAD_PARAMETER); 53967754Smsmith } 54067754Smsmith 541193267Sjkim /* Check for a prefix (one '\' | one or more '^') */ 542193267Sjkim 54367754Smsmith switch (InternalName[0]) 54467754Smsmith { 54567754Smsmith case '\\': 54667754Smsmith PrefixLength = 1; 54767754Smsmith break; 54867754Smsmith 54967754Smsmith case '^': 55067754Smsmith for (i = 0; i < InternalNameLength; i++) 55167754Smsmith { 552102550Siwasaki if (InternalName[i] == '^') 55367754Smsmith { 55467754Smsmith PrefixLength = i + 1; 55567754Smsmith } 556102550Siwasaki else 557102550Siwasaki { 558102550Siwasaki break; 559102550Siwasaki } 56067754Smsmith } 56167754Smsmith 56267754Smsmith if (i == InternalNameLength) 56367754Smsmith { 56467754Smsmith PrefixLength = i; 56567754Smsmith } 56667754Smsmith 56767754Smsmith break; 56899679Siwasaki 56999679Siwasaki default: 57099679Siwasaki break; 57167754Smsmith } 57267754Smsmith 57367754Smsmith /* 574193267Sjkim * Check for object names. Note that there could be 0-255 of these 57567754Smsmith * 4-byte elements. 57667754Smsmith */ 57767754Smsmith if (PrefixLength < InternalNameLength) 57867754Smsmith { 57967754Smsmith switch (InternalName[PrefixLength]) 58067754Smsmith { 58191116Smsmith case AML_MULTI_NAME_PREFIX_OP: 58267754Smsmith 58391116Smsmith /* <count> 4-byte names */ 58467754Smsmith 58567754Smsmith NamesIndex = PrefixLength + 2; 586193267Sjkim NumSegments = (UINT8) 587193267Sjkim InternalName[(ACPI_SIZE) PrefixLength + 1]; 58867754Smsmith break; 58967754Smsmith 59091116Smsmith case AML_DUAL_NAME_PREFIX: 59167754Smsmith 59291116Smsmith /* Two 4-byte names */ 59367754Smsmith 59467754Smsmith NamesIndex = PrefixLength + 1; 59591116Smsmith NumSegments = 2; 59667754Smsmith break; 59767754Smsmith 59891116Smsmith case 0: 59967754Smsmith 60091116Smsmith /* NullName */ 60167754Smsmith 60267754Smsmith NamesIndex = 0; 60391116Smsmith NumSegments = 0; 60467754Smsmith break; 60567754Smsmith 60691116Smsmith default: 60767754Smsmith 60891116Smsmith /* one 4-byte name */ 60967754Smsmith 61067754Smsmith NamesIndex = PrefixLength; 61191116Smsmith NumSegments = 1; 61267754Smsmith break; 61367754Smsmith } 61467754Smsmith } 61567754Smsmith 61667754Smsmith /* 61767754Smsmith * Calculate the length of ConvertedName, which equals the length 61867754Smsmith * of the prefix, length of all object names, length of any required 61967754Smsmith * punctuation ('.') between object names, plus the NULL terminator. 62067754Smsmith */ 62191116Smsmith RequiredLength = PrefixLength + (4 * NumSegments) + 62291116Smsmith ((NumSegments > 0) ? (NumSegments - 1) : 0) + 1; 62367754Smsmith 62467754Smsmith /* 62567754Smsmith * Check to see if we're still in bounds. If not, there's a problem 62667754Smsmith * with InternalName (invalid format). 62767754Smsmith */ 62891116Smsmith if (RequiredLength > InternalNameLength) 62967754Smsmith { 630167802Sjkim ACPI_ERROR ((AE_INFO, "Invalid internal name")); 63167754Smsmith return_ACPI_STATUS (AE_BAD_PATHNAME); 63267754Smsmith } 63367754Smsmith 634193267Sjkim /* Build the ConvertedName */ 635193267Sjkim 636167802Sjkim *ConvertedName = ACPI_ALLOCATE_ZEROED (RequiredLength); 63767754Smsmith if (!(*ConvertedName)) 63867754Smsmith { 63967754Smsmith return_ACPI_STATUS (AE_NO_MEMORY); 64067754Smsmith } 64167754Smsmith 64267754Smsmith j = 0; 64367754Smsmith 64467754Smsmith for (i = 0; i < PrefixLength; i++) 64567754Smsmith { 64667754Smsmith (*ConvertedName)[j++] = InternalName[i]; 64767754Smsmith } 64867754Smsmith 64991116Smsmith if (NumSegments > 0) 65067754Smsmith { 65191116Smsmith for (i = 0; i < NumSegments; i++) 65267754Smsmith { 65367754Smsmith if (i > 0) 65467754Smsmith { 65567754Smsmith (*ConvertedName)[j++] = '.'; 65667754Smsmith } 65767754Smsmith 65867754Smsmith (*ConvertedName)[j++] = InternalName[NamesIndex++]; 65967754Smsmith (*ConvertedName)[j++] = InternalName[NamesIndex++]; 66067754Smsmith (*ConvertedName)[j++] = InternalName[NamesIndex++]; 66167754Smsmith (*ConvertedName)[j++] = InternalName[NamesIndex++]; 66267754Smsmith } 66367754Smsmith } 66467754Smsmith 66591116Smsmith if (ConvertedNameLength) 66691116Smsmith { 66799679Siwasaki *ConvertedNameLength = (UINT32) RequiredLength; 66891116Smsmith } 66991116Smsmith 67067754Smsmith return_ACPI_STATUS (AE_OK); 67167754Smsmith} 67267754Smsmith 67367754Smsmith 67477424Smsmith/******************************************************************************* 67567754Smsmith * 676200553Sjkim * FUNCTION: AcpiNsValidateHandle 67767754Smsmith * 678200553Sjkim * PARAMETERS: Handle - Handle to be validated and typecast to a 679200553Sjkim * namespace node. 68067754Smsmith * 681200553Sjkim * RETURN: A pointer to a namespace node 68267754Smsmith * 683200553Sjkim * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special 684200553Sjkim * cases for the root node. 68567754Smsmith * 686200553Sjkim * NOTE: Real integer handles would allow for more verification 687151937Sjkim * and keep all pointers within this subsystem - however this introduces 688200553Sjkim * more overhead and has not been necessary to this point. Drivers 689200553Sjkim * holding handles are typically notified before a node becomes invalid 690200553Sjkim * due to a table unload. 69187031Smsmith * 69277424Smsmith ******************************************************************************/ 69367754Smsmith 69467754SmsmithACPI_NAMESPACE_NODE * 695200553SjkimAcpiNsValidateHandle ( 69667754Smsmith ACPI_HANDLE Handle) 69767754Smsmith{ 69867754Smsmith 69991116Smsmith ACPI_FUNCTION_ENTRY (); 70083174Smsmith 70183174Smsmith 702193267Sjkim /* Parameter validation */ 703193267Sjkim 704167802Sjkim if ((!Handle) || (Handle == ACPI_ROOT_OBJECT)) 70567754Smsmith { 70667754Smsmith return (AcpiGbl_RootNode); 70767754Smsmith } 70867754Smsmith 70967754Smsmith /* We can at least attempt to verify the handle */ 71067754Smsmith 71191116Smsmith if (ACPI_GET_DESCRIPTOR_TYPE (Handle) != ACPI_DESC_TYPE_NAMED) 71267754Smsmith { 71367754Smsmith return (NULL); 71467754Smsmith } 71567754Smsmith 716167802Sjkim return (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Handle)); 71767754Smsmith} 71867754Smsmith 71967754Smsmith 72077424Smsmith/******************************************************************************* 72167754Smsmith * 72267754Smsmith * FUNCTION: AcpiNsTerminate 72367754Smsmith * 72467754Smsmith * PARAMETERS: none 72567754Smsmith * 72667754Smsmith * RETURN: none 72767754Smsmith * 728151937Sjkim * DESCRIPTION: free memory allocated for namespace and ACPI table storage. 72967754Smsmith * 73067754Smsmith ******************************************************************************/ 73167754Smsmith 73267754Smsmithvoid 733151937SjkimAcpiNsTerminate ( 734151937Sjkim void) 73567754Smsmith{ 73667754Smsmith ACPI_OPERAND_OBJECT *ObjDesc; 73767754Smsmith 73867754Smsmith 739167802Sjkim ACPI_FUNCTION_TRACE (NsTerminate); 74067754Smsmith 74167754Smsmith 74267754Smsmith /* 743117521Snjl * 1) Free the entire namespace -- all nodes and objects 74477424Smsmith * 745117521Snjl * Delete all object descriptors attached to namepsace nodes 74667754Smsmith */ 747117521Snjl AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); 74867754Smsmith 749117521Snjl /* Detach any objects attached to the root */ 75067754Smsmith 751117521Snjl ObjDesc = AcpiNsGetAttachedObject (AcpiGbl_RootNode); 75267754Smsmith if (ObjDesc) 75367754Smsmith { 754117521Snjl AcpiNsDetachObject (AcpiGbl_RootNode); 75567754Smsmith } 75667754Smsmith 75782367Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n")); 75867754Smsmith return_VOID; 75967754Smsmith} 76067754Smsmith 76167754Smsmith 76277424Smsmith/******************************************************************************* 76367754Smsmith * 76467754Smsmith * FUNCTION: AcpiNsOpensScope 76567754Smsmith * 76667754Smsmith * PARAMETERS: Type - A valid namespace type 76767754Smsmith * 76867754Smsmith * RETURN: NEWSCOPE if the passed type "opens a name scope" according 76967754Smsmith * to the ACPI specification, else 0 77067754Smsmith * 77177424Smsmith ******************************************************************************/ 77267754Smsmith 77367754SmsmithUINT32 77467754SmsmithAcpiNsOpensScope ( 77591116Smsmith ACPI_OBJECT_TYPE Type) 77667754Smsmith{ 777167802Sjkim ACPI_FUNCTION_TRACE_STR (NsOpensScope, AcpiUtGetTypeName (Type)); 77867754Smsmith 77967754Smsmith 78077424Smsmith if (!AcpiUtValidObjectType (Type)) 78167754Smsmith { 78267754Smsmith /* type code out of range */ 78367754Smsmith 784204773Sjkim ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type)); 785151937Sjkim return_UINT32 (ACPI_NS_NORMAL); 78667754Smsmith } 78767754Smsmith 788151937Sjkim return_UINT32 (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE); 78967754Smsmith} 79067754Smsmith 79167754Smsmith 79277424Smsmith/******************************************************************************* 79367754Smsmith * 794167802Sjkim * FUNCTION: AcpiNsGetNode 79567754Smsmith * 79667754Smsmith * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The 79767754Smsmith * \ (backslash) and ^ (carat) prefixes, and the 79867754Smsmith * . (period) to separate segments are supported. 799167802Sjkim * PrefixNode - Root of subtree to be searched, or NS_ALL for the 80067754Smsmith * root of the name space. If Name is fully 80167754Smsmith * qualified (first INT8 is '\'), the passed value 80267754Smsmith * of Scope will not be accessed. 80391116Smsmith * Flags - Used to indicate whether to perform upsearch or 80491116Smsmith * not. 80567754Smsmith * ReturnNode - Where the Node is returned 80667754Smsmith * 80767754Smsmith * DESCRIPTION: Look up a name relative to a given scope and return the 80867754Smsmith * corresponding Node. NOTE: Scope can be null. 80967754Smsmith * 81067754Smsmith * MUTEX: Locks namespace 81167754Smsmith * 81277424Smsmith ******************************************************************************/ 81367754Smsmith 81467754SmsmithACPI_STATUS 815167802SjkimAcpiNsGetNode ( 816167802Sjkim ACPI_NAMESPACE_NODE *PrefixNode, 817193267Sjkim const char *Pathname, 81891116Smsmith UINT32 Flags, 81967754Smsmith ACPI_NAMESPACE_NODE **ReturnNode) 82067754Smsmith{ 82167754Smsmith ACPI_GENERIC_STATE ScopeInfo; 82267754Smsmith ACPI_STATUS Status; 823167802Sjkim char *InternalPath; 82467754Smsmith 82567754Smsmith 826193267Sjkim ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname)); 82767754Smsmith 82867754Smsmith 829167802Sjkim if (!Pathname) 83067754Smsmith { 831167802Sjkim *ReturnNode = PrefixNode; 832167802Sjkim if (!PrefixNode) 833114237Snjl { 834167802Sjkim *ReturnNode = AcpiGbl_RootNode; 835114237Snjl } 836167802Sjkim return_ACPI_STATUS (AE_OK); 83767754Smsmith } 83867754Smsmith 839167802Sjkim /* Convert path to internal representation */ 840167802Sjkim 841167802Sjkim Status = AcpiNsInternalizeName (Pathname, &InternalPath); 842167802Sjkim if (ACPI_FAILURE (Status)) 843167802Sjkim { 844167802Sjkim return_ACPI_STATUS (Status); 845167802Sjkim } 846167802Sjkim 84791116Smsmith /* Must lock namespace during lookup */ 84867754Smsmith 84991116Smsmith Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 85091116Smsmith if (ACPI_FAILURE (Status)) 85191116Smsmith { 852126372Snjl goto Cleanup; 85391116Smsmith } 85467754Smsmith 85569746Smsmith /* Setup lookup scope (search starting point) */ 85667754Smsmith 857167802Sjkim ScopeInfo.Scope.Node = PrefixNode; 85867754Smsmith 85967754Smsmith /* Lookup the name in the namespace */ 86067754Smsmith 861167802Sjkim Status = AcpiNsLookup (&ScopeInfo, InternalPath, ACPI_TYPE_ANY, 862167802Sjkim ACPI_IMODE_EXECUTE, (Flags | ACPI_NS_DONT_OPEN_SCOPE), 863167802Sjkim NULL, ReturnNode); 86467754Smsmith if (ACPI_FAILURE (Status)) 86567754Smsmith { 866193267Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s, %s\n", 867167802Sjkim Pathname, AcpiFormatException (Status))); 86867754Smsmith } 86967754Smsmith 87091116Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 871114237Snjl 872126372SnjlCleanup: 873167802Sjkim ACPI_FREE (InternalPath); 87467754Smsmith return_ACPI_STATUS (Status); 87567754Smsmith} 876