1*a159c266SJung-uk Kim /****************************************************************************** 2*a159c266SJung-uk Kim * 3*a159c266SJung-uk Kim * Module Name: nsxfname - Public interfaces to the ACPI subsystem 4*a159c266SJung-uk Kim * ACPI Namespace oriented interfaces 5*a159c266SJung-uk Kim * 6*a159c266SJung-uk Kim *****************************************************************************/ 7*a159c266SJung-uk Kim 8*a159c266SJung-uk Kim /* 9*a159c266SJung-uk Kim * Copyright (C) 2000 - 2012, Intel Corp. 10*a159c266SJung-uk Kim * All rights reserved. 11*a159c266SJung-uk Kim * 12*a159c266SJung-uk Kim * Redistribution and use in source and binary forms, with or without 13*a159c266SJung-uk Kim * modification, are permitted provided that the following conditions 14*a159c266SJung-uk Kim * are met: 15*a159c266SJung-uk Kim * 1. Redistributions of source code must retain the above copyright 16*a159c266SJung-uk Kim * notice, this list of conditions, and the following disclaimer, 17*a159c266SJung-uk Kim * without modification. 18*a159c266SJung-uk Kim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19*a159c266SJung-uk Kim * substantially similar to the "NO WARRANTY" disclaimer below 20*a159c266SJung-uk Kim * ("Disclaimer") and any redistribution must be conditioned upon 21*a159c266SJung-uk Kim * including a substantially similar Disclaimer requirement for further 22*a159c266SJung-uk Kim * binary redistribution. 23*a159c266SJung-uk Kim * 3. Neither the names of the above-listed copyright holders nor the names 24*a159c266SJung-uk Kim * of any contributors may be used to endorse or promote products derived 25*a159c266SJung-uk Kim * from this software without specific prior written permission. 26*a159c266SJung-uk Kim * 27*a159c266SJung-uk Kim * Alternatively, this software may be distributed under the terms of the 28*a159c266SJung-uk Kim * GNU General Public License ("GPL") version 2 as published by the Free 29*a159c266SJung-uk Kim * Software Foundation. 30*a159c266SJung-uk Kim * 31*a159c266SJung-uk Kim * NO WARRANTY 32*a159c266SJung-uk Kim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33*a159c266SJung-uk Kim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34*a159c266SJung-uk Kim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35*a159c266SJung-uk Kim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36*a159c266SJung-uk Kim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37*a159c266SJung-uk Kim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38*a159c266SJung-uk Kim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39*a159c266SJung-uk Kim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40*a159c266SJung-uk Kim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41*a159c266SJung-uk Kim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42*a159c266SJung-uk Kim * POSSIBILITY OF SUCH DAMAGES. 43*a159c266SJung-uk Kim */ 44*a159c266SJung-uk Kim 45*a159c266SJung-uk Kim #define __NSXFNAME_C__ 46*a159c266SJung-uk Kim 47*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h> 48*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h> 49*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acnamesp.h> 50*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acparser.h> 51*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/amlcode.h> 52*a159c266SJung-uk Kim 53*a159c266SJung-uk Kim 54*a159c266SJung-uk Kim #define _COMPONENT ACPI_NAMESPACE 55*a159c266SJung-uk Kim ACPI_MODULE_NAME ("nsxfname") 56*a159c266SJung-uk Kim 57*a159c266SJung-uk Kim /* Local prototypes */ 58*a159c266SJung-uk Kim 59*a159c266SJung-uk Kim static char * 60*a159c266SJung-uk Kim AcpiNsCopyDeviceId ( 61*a159c266SJung-uk Kim ACPI_DEVICE_ID *Dest, 62*a159c266SJung-uk Kim ACPI_DEVICE_ID *Source, 63*a159c266SJung-uk Kim char *StringArea); 64*a159c266SJung-uk Kim 65*a159c266SJung-uk Kim 66*a159c266SJung-uk Kim /****************************************************************************** 67*a159c266SJung-uk Kim * 68*a159c266SJung-uk Kim * FUNCTION: AcpiGetHandle 69*a159c266SJung-uk Kim * 70*a159c266SJung-uk Kim * PARAMETERS: Parent - Object to search under (search scope). 71*a159c266SJung-uk Kim * Pathname - Pointer to an asciiz string containing the 72*a159c266SJung-uk Kim * name 73*a159c266SJung-uk Kim * RetHandle - Where the return handle is returned 74*a159c266SJung-uk Kim * 75*a159c266SJung-uk Kim * RETURN: Status 76*a159c266SJung-uk Kim * 77*a159c266SJung-uk Kim * DESCRIPTION: This routine will search for a caller specified name in the 78*a159c266SJung-uk Kim * name space. The caller can restrict the search region by 79*a159c266SJung-uk Kim * specifying a non NULL parent. The parent value is itself a 80*a159c266SJung-uk Kim * namespace handle. 81*a159c266SJung-uk Kim * 82*a159c266SJung-uk Kim ******************************************************************************/ 83*a159c266SJung-uk Kim 84*a159c266SJung-uk Kim ACPI_STATUS 85*a159c266SJung-uk Kim AcpiGetHandle ( 86*a159c266SJung-uk Kim ACPI_HANDLE Parent, 87*a159c266SJung-uk Kim ACPI_STRING Pathname, 88*a159c266SJung-uk Kim ACPI_HANDLE *RetHandle) 89*a159c266SJung-uk Kim { 90*a159c266SJung-uk Kim ACPI_STATUS Status; 91*a159c266SJung-uk Kim ACPI_NAMESPACE_NODE *Node = NULL; 92*a159c266SJung-uk Kim ACPI_NAMESPACE_NODE *PrefixNode = NULL; 93*a159c266SJung-uk Kim 94*a159c266SJung-uk Kim 95*a159c266SJung-uk Kim ACPI_FUNCTION_ENTRY (); 96*a159c266SJung-uk Kim 97*a159c266SJung-uk Kim 98*a159c266SJung-uk Kim /* Parameter Validation */ 99*a159c266SJung-uk Kim 100*a159c266SJung-uk Kim if (!RetHandle || !Pathname) 101*a159c266SJung-uk Kim { 102*a159c266SJung-uk Kim return (AE_BAD_PARAMETER); 103*a159c266SJung-uk Kim } 104*a159c266SJung-uk Kim 105*a159c266SJung-uk Kim /* Convert a parent handle to a prefix node */ 106*a159c266SJung-uk Kim 107*a159c266SJung-uk Kim if (Parent) 108*a159c266SJung-uk Kim { 109*a159c266SJung-uk Kim PrefixNode = AcpiNsValidateHandle (Parent); 110*a159c266SJung-uk Kim if (!PrefixNode) 111*a159c266SJung-uk Kim { 112*a159c266SJung-uk Kim return (AE_BAD_PARAMETER); 113*a159c266SJung-uk Kim } 114*a159c266SJung-uk Kim } 115*a159c266SJung-uk Kim 116*a159c266SJung-uk Kim /* 117*a159c266SJung-uk Kim * Valid cases are: 118*a159c266SJung-uk Kim * 1) Fully qualified pathname 119*a159c266SJung-uk Kim * 2) Parent + Relative pathname 120*a159c266SJung-uk Kim * 121*a159c266SJung-uk Kim * Error for <null Parent + relative path> 122*a159c266SJung-uk Kim */ 123*a159c266SJung-uk Kim if (AcpiNsValidRootPrefix (Pathname[0])) 124*a159c266SJung-uk Kim { 125*a159c266SJung-uk Kim /* Pathname is fully qualified (starts with '\') */ 126*a159c266SJung-uk Kim 127*a159c266SJung-uk Kim /* Special case for root-only, since we can't search for it */ 128*a159c266SJung-uk Kim 129*a159c266SJung-uk Kim if (!ACPI_STRCMP (Pathname, ACPI_NS_ROOT_PATH)) 130*a159c266SJung-uk Kim { 131*a159c266SJung-uk Kim *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, AcpiGbl_RootNode); 132*a159c266SJung-uk Kim return (AE_OK); 133*a159c266SJung-uk Kim } 134*a159c266SJung-uk Kim } 135*a159c266SJung-uk Kim else if (!PrefixNode) 136*a159c266SJung-uk Kim { 137*a159c266SJung-uk Kim /* Relative path with null prefix is disallowed */ 138*a159c266SJung-uk Kim 139*a159c266SJung-uk Kim return (AE_BAD_PARAMETER); 140*a159c266SJung-uk Kim } 141*a159c266SJung-uk Kim 142*a159c266SJung-uk Kim /* Find the Node and convert to a handle */ 143*a159c266SJung-uk Kim 144*a159c266SJung-uk Kim Status = AcpiNsGetNode (PrefixNode, Pathname, ACPI_NS_NO_UPSEARCH, &Node); 145*a159c266SJung-uk Kim if (ACPI_SUCCESS (Status)) 146*a159c266SJung-uk Kim { 147*a159c266SJung-uk Kim *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, Node); 148*a159c266SJung-uk Kim } 149*a159c266SJung-uk Kim 150*a159c266SJung-uk Kim return (Status); 151*a159c266SJung-uk Kim } 152*a159c266SJung-uk Kim 153*a159c266SJung-uk Kim ACPI_EXPORT_SYMBOL (AcpiGetHandle) 154*a159c266SJung-uk Kim 155*a159c266SJung-uk Kim 156*a159c266SJung-uk Kim /****************************************************************************** 157*a159c266SJung-uk Kim * 158*a159c266SJung-uk Kim * FUNCTION: AcpiGetName 159*a159c266SJung-uk Kim * 160*a159c266SJung-uk Kim * PARAMETERS: Handle - Handle to be converted to a pathname 161*a159c266SJung-uk Kim * NameType - Full pathname or single segment 162*a159c266SJung-uk Kim * Buffer - Buffer for returned path 163*a159c266SJung-uk Kim * 164*a159c266SJung-uk Kim * RETURN: Pointer to a string containing the fully qualified Name. 165*a159c266SJung-uk Kim * 166*a159c266SJung-uk Kim * DESCRIPTION: This routine returns the fully qualified name associated with 167*a159c266SJung-uk Kim * the Handle parameter. This and the AcpiPathnameToHandle are 168*a159c266SJung-uk Kim * complementary functions. 169*a159c266SJung-uk Kim * 170*a159c266SJung-uk Kim ******************************************************************************/ 171*a159c266SJung-uk Kim 172*a159c266SJung-uk Kim ACPI_STATUS 173*a159c266SJung-uk Kim AcpiGetName ( 174*a159c266SJung-uk Kim ACPI_HANDLE Handle, 175*a159c266SJung-uk Kim UINT32 NameType, 176*a159c266SJung-uk Kim ACPI_BUFFER *Buffer) 177*a159c266SJung-uk Kim { 178*a159c266SJung-uk Kim ACPI_STATUS Status; 179*a159c266SJung-uk Kim ACPI_NAMESPACE_NODE *Node; 180*a159c266SJung-uk Kim 181*a159c266SJung-uk Kim 182*a159c266SJung-uk Kim /* Parameter validation */ 183*a159c266SJung-uk Kim 184*a159c266SJung-uk Kim if (NameType > ACPI_NAME_TYPE_MAX) 185*a159c266SJung-uk Kim { 186*a159c266SJung-uk Kim return (AE_BAD_PARAMETER); 187*a159c266SJung-uk Kim } 188*a159c266SJung-uk Kim 189*a159c266SJung-uk Kim Status = AcpiUtValidateBuffer (Buffer); 190*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 191*a159c266SJung-uk Kim { 192*a159c266SJung-uk Kim return (Status); 193*a159c266SJung-uk Kim } 194*a159c266SJung-uk Kim 195*a159c266SJung-uk Kim if (NameType == ACPI_FULL_PATHNAME) 196*a159c266SJung-uk Kim { 197*a159c266SJung-uk Kim /* Get the full pathname (From the namespace root) */ 198*a159c266SJung-uk Kim 199*a159c266SJung-uk Kim Status = AcpiNsHandleToPathname (Handle, Buffer); 200*a159c266SJung-uk Kim return (Status); 201*a159c266SJung-uk Kim } 202*a159c266SJung-uk Kim 203*a159c266SJung-uk Kim /* 204*a159c266SJung-uk Kim * Wants the single segment ACPI name. 205*a159c266SJung-uk Kim * Validate handle and convert to a namespace Node 206*a159c266SJung-uk Kim */ 207*a159c266SJung-uk Kim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 208*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 209*a159c266SJung-uk Kim { 210*a159c266SJung-uk Kim return (Status); 211*a159c266SJung-uk Kim } 212*a159c266SJung-uk Kim 213*a159c266SJung-uk Kim Node = AcpiNsValidateHandle (Handle); 214*a159c266SJung-uk Kim if (!Node) 215*a159c266SJung-uk Kim { 216*a159c266SJung-uk Kim Status = AE_BAD_PARAMETER; 217*a159c266SJung-uk Kim goto UnlockAndExit; 218*a159c266SJung-uk Kim } 219*a159c266SJung-uk Kim 220*a159c266SJung-uk Kim /* Validate/Allocate/Clear caller buffer */ 221*a159c266SJung-uk Kim 222*a159c266SJung-uk Kim Status = AcpiUtInitializeBuffer (Buffer, ACPI_PATH_SEGMENT_LENGTH); 223*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 224*a159c266SJung-uk Kim { 225*a159c266SJung-uk Kim goto UnlockAndExit; 226*a159c266SJung-uk Kim } 227*a159c266SJung-uk Kim 228*a159c266SJung-uk Kim /* Just copy the ACPI name from the Node and zero terminate it */ 229*a159c266SJung-uk Kim 230*a159c266SJung-uk Kim ACPI_STRNCPY (Buffer->Pointer, AcpiUtGetNodeName (Node), 231*a159c266SJung-uk Kim ACPI_NAME_SIZE); 232*a159c266SJung-uk Kim ((char *) Buffer->Pointer) [ACPI_NAME_SIZE] = 0; 233*a159c266SJung-uk Kim Status = AE_OK; 234*a159c266SJung-uk Kim 235*a159c266SJung-uk Kim 236*a159c266SJung-uk Kim UnlockAndExit: 237*a159c266SJung-uk Kim 238*a159c266SJung-uk Kim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 239*a159c266SJung-uk Kim return (Status); 240*a159c266SJung-uk Kim } 241*a159c266SJung-uk Kim 242*a159c266SJung-uk Kim ACPI_EXPORT_SYMBOL (AcpiGetName) 243*a159c266SJung-uk Kim 244*a159c266SJung-uk Kim 245*a159c266SJung-uk Kim /****************************************************************************** 246*a159c266SJung-uk Kim * 247*a159c266SJung-uk Kim * FUNCTION: AcpiNsCopyDeviceId 248*a159c266SJung-uk Kim * 249*a159c266SJung-uk Kim * PARAMETERS: Dest - Pointer to the destination DEVICE_ID 250*a159c266SJung-uk Kim * Source - Pointer to the source DEVICE_ID 251*a159c266SJung-uk Kim * StringArea - Pointer to where to copy the dest string 252*a159c266SJung-uk Kim * 253*a159c266SJung-uk Kim * RETURN: Pointer to the next string area 254*a159c266SJung-uk Kim * 255*a159c266SJung-uk Kim * DESCRIPTION: Copy a single DEVICE_ID, including the string data. 256*a159c266SJung-uk Kim * 257*a159c266SJung-uk Kim ******************************************************************************/ 258*a159c266SJung-uk Kim 259*a159c266SJung-uk Kim static char * 260*a159c266SJung-uk Kim AcpiNsCopyDeviceId ( 261*a159c266SJung-uk Kim ACPI_DEVICE_ID *Dest, 262*a159c266SJung-uk Kim ACPI_DEVICE_ID *Source, 263*a159c266SJung-uk Kim char *StringArea) 264*a159c266SJung-uk Kim { 265*a159c266SJung-uk Kim /* Create the destination DEVICE_ID */ 266*a159c266SJung-uk Kim 267*a159c266SJung-uk Kim Dest->String = StringArea; 268*a159c266SJung-uk Kim Dest->Length = Source->Length; 269*a159c266SJung-uk Kim 270*a159c266SJung-uk Kim /* Copy actual string and return a pointer to the next string area */ 271*a159c266SJung-uk Kim 272*a159c266SJung-uk Kim ACPI_MEMCPY (StringArea, Source->String, Source->Length); 273*a159c266SJung-uk Kim return (StringArea + Source->Length); 274*a159c266SJung-uk Kim } 275*a159c266SJung-uk Kim 276*a159c266SJung-uk Kim 277*a159c266SJung-uk Kim /****************************************************************************** 278*a159c266SJung-uk Kim * 279*a159c266SJung-uk Kim * FUNCTION: AcpiGetObjectInfo 280*a159c266SJung-uk Kim * 281*a159c266SJung-uk Kim * PARAMETERS: Handle - Object Handle 282*a159c266SJung-uk Kim * ReturnBuffer - Where the info is returned 283*a159c266SJung-uk Kim * 284*a159c266SJung-uk Kim * RETURN: Status 285*a159c266SJung-uk Kim * 286*a159c266SJung-uk Kim * DESCRIPTION: Returns information about an object as gleaned from the 287*a159c266SJung-uk Kim * namespace node and possibly by running several standard 288*a159c266SJung-uk Kim * control methods (Such as in the case of a device.) 289*a159c266SJung-uk Kim * 290*a159c266SJung-uk Kim * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA, 291*a159c266SJung-uk Kim * _ADR, _SxW, and _SxD methods. 292*a159c266SJung-uk Kim * 293*a159c266SJung-uk Kim * Note: Allocates the return buffer, must be freed by the caller. 294*a159c266SJung-uk Kim * 295*a159c266SJung-uk Kim ******************************************************************************/ 296*a159c266SJung-uk Kim 297*a159c266SJung-uk Kim ACPI_STATUS 298*a159c266SJung-uk Kim AcpiGetObjectInfo ( 299*a159c266SJung-uk Kim ACPI_HANDLE Handle, 300*a159c266SJung-uk Kim ACPI_DEVICE_INFO **ReturnBuffer) 301*a159c266SJung-uk Kim { 302*a159c266SJung-uk Kim ACPI_NAMESPACE_NODE *Node; 303*a159c266SJung-uk Kim ACPI_DEVICE_INFO *Info; 304*a159c266SJung-uk Kim ACPI_DEVICE_ID_LIST *CidList = NULL; 305*a159c266SJung-uk Kim ACPI_DEVICE_ID *Hid = NULL; 306*a159c266SJung-uk Kim ACPI_DEVICE_ID *Uid = NULL; 307*a159c266SJung-uk Kim char *NextIdString; 308*a159c266SJung-uk Kim ACPI_OBJECT_TYPE Type; 309*a159c266SJung-uk Kim ACPI_NAME Name; 310*a159c266SJung-uk Kim UINT8 ParamCount= 0; 311*a159c266SJung-uk Kim UINT8 Valid = 0; 312*a159c266SJung-uk Kim UINT32 InfoSize; 313*a159c266SJung-uk Kim UINT32 i; 314*a159c266SJung-uk Kim ACPI_STATUS Status; 315*a159c266SJung-uk Kim 316*a159c266SJung-uk Kim 317*a159c266SJung-uk Kim /* Parameter validation */ 318*a159c266SJung-uk Kim 319*a159c266SJung-uk Kim if (!Handle || !ReturnBuffer) 320*a159c266SJung-uk Kim { 321*a159c266SJung-uk Kim return (AE_BAD_PARAMETER); 322*a159c266SJung-uk Kim } 323*a159c266SJung-uk Kim 324*a159c266SJung-uk Kim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 325*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 326*a159c266SJung-uk Kim { 327*a159c266SJung-uk Kim goto Cleanup; 328*a159c266SJung-uk Kim } 329*a159c266SJung-uk Kim 330*a159c266SJung-uk Kim Node = AcpiNsValidateHandle (Handle); 331*a159c266SJung-uk Kim if (!Node) 332*a159c266SJung-uk Kim { 333*a159c266SJung-uk Kim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 334*a159c266SJung-uk Kim return (AE_BAD_PARAMETER); 335*a159c266SJung-uk Kim } 336*a159c266SJung-uk Kim 337*a159c266SJung-uk Kim /* Get the namespace node data while the namespace is locked */ 338*a159c266SJung-uk Kim 339*a159c266SJung-uk Kim InfoSize = sizeof (ACPI_DEVICE_INFO); 340*a159c266SJung-uk Kim Type = Node->Type; 341*a159c266SJung-uk Kim Name = Node->Name.Integer; 342*a159c266SJung-uk Kim 343*a159c266SJung-uk Kim if (Node->Type == ACPI_TYPE_METHOD) 344*a159c266SJung-uk Kim { 345*a159c266SJung-uk Kim ParamCount = Node->Object->Method.ParamCount; 346*a159c266SJung-uk Kim } 347*a159c266SJung-uk Kim 348*a159c266SJung-uk Kim Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 349*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 350*a159c266SJung-uk Kim { 351*a159c266SJung-uk Kim return (Status); 352*a159c266SJung-uk Kim } 353*a159c266SJung-uk Kim 354*a159c266SJung-uk Kim if ((Type == ACPI_TYPE_DEVICE) || 355*a159c266SJung-uk Kim (Type == ACPI_TYPE_PROCESSOR)) 356*a159c266SJung-uk Kim { 357*a159c266SJung-uk Kim /* 358*a159c266SJung-uk Kim * Get extra info for ACPI Device/Processor objects only: 359*a159c266SJung-uk Kim * Run the Device _HID, _UID, and _CID methods. 360*a159c266SJung-uk Kim * 361*a159c266SJung-uk Kim * Note: none of these methods are required, so they may or may 362*a159c266SJung-uk Kim * not be present for this device. The Info->Valid bitfield is used 363*a159c266SJung-uk Kim * to indicate which methods were found and run successfully. 364*a159c266SJung-uk Kim */ 365*a159c266SJung-uk Kim 366*a159c266SJung-uk Kim /* Execute the Device._HID method */ 367*a159c266SJung-uk Kim 368*a159c266SJung-uk Kim Status = AcpiUtExecute_HID (Node, &Hid); 369*a159c266SJung-uk Kim if (ACPI_SUCCESS (Status)) 370*a159c266SJung-uk Kim { 371*a159c266SJung-uk Kim InfoSize += Hid->Length; 372*a159c266SJung-uk Kim Valid |= ACPI_VALID_HID; 373*a159c266SJung-uk Kim } 374*a159c266SJung-uk Kim 375*a159c266SJung-uk Kim /* Execute the Device._UID method */ 376*a159c266SJung-uk Kim 377*a159c266SJung-uk Kim Status = AcpiUtExecute_UID (Node, &Uid); 378*a159c266SJung-uk Kim if (ACPI_SUCCESS (Status)) 379*a159c266SJung-uk Kim { 380*a159c266SJung-uk Kim InfoSize += Uid->Length; 381*a159c266SJung-uk Kim Valid |= ACPI_VALID_UID; 382*a159c266SJung-uk Kim } 383*a159c266SJung-uk Kim 384*a159c266SJung-uk Kim /* Execute the Device._CID method */ 385*a159c266SJung-uk Kim 386*a159c266SJung-uk Kim Status = AcpiUtExecute_CID (Node, &CidList); 387*a159c266SJung-uk Kim if (ACPI_SUCCESS (Status)) 388*a159c266SJung-uk Kim { 389*a159c266SJung-uk Kim /* Add size of CID strings and CID pointer array */ 390*a159c266SJung-uk Kim 391*a159c266SJung-uk Kim InfoSize += (CidList->ListSize - sizeof (ACPI_DEVICE_ID_LIST)); 392*a159c266SJung-uk Kim Valid |= ACPI_VALID_CID; 393*a159c266SJung-uk Kim } 394*a159c266SJung-uk Kim } 395*a159c266SJung-uk Kim 396*a159c266SJung-uk Kim /* 397*a159c266SJung-uk Kim * Now that we have the variable-length data, we can allocate the 398*a159c266SJung-uk Kim * return buffer 399*a159c266SJung-uk Kim */ 400*a159c266SJung-uk Kim Info = ACPI_ALLOCATE_ZEROED (InfoSize); 401*a159c266SJung-uk Kim if (!Info) 402*a159c266SJung-uk Kim { 403*a159c266SJung-uk Kim Status = AE_NO_MEMORY; 404*a159c266SJung-uk Kim goto Cleanup; 405*a159c266SJung-uk Kim } 406*a159c266SJung-uk Kim 407*a159c266SJung-uk Kim /* Get the fixed-length data */ 408*a159c266SJung-uk Kim 409*a159c266SJung-uk Kim if ((Type == ACPI_TYPE_DEVICE) || 410*a159c266SJung-uk Kim (Type == ACPI_TYPE_PROCESSOR)) 411*a159c266SJung-uk Kim { 412*a159c266SJung-uk Kim /* 413*a159c266SJung-uk Kim * Get extra info for ACPI Device/Processor objects only: 414*a159c266SJung-uk Kim * Run the _STA, _ADR and, SxW, and _SxD methods. 415*a159c266SJung-uk Kim * 416*a159c266SJung-uk Kim * Note: none of these methods are required, so they may or may 417*a159c266SJung-uk Kim * not be present for this device. The Info->Valid bitfield is used 418*a159c266SJung-uk Kim * to indicate which methods were found and run successfully. 419*a159c266SJung-uk Kim */ 420*a159c266SJung-uk Kim 421*a159c266SJung-uk Kim /* Execute the Device._STA method */ 422*a159c266SJung-uk Kim 423*a159c266SJung-uk Kim Status = AcpiUtExecute_STA (Node, &Info->CurrentStatus); 424*a159c266SJung-uk Kim if (ACPI_SUCCESS (Status)) 425*a159c266SJung-uk Kim { 426*a159c266SJung-uk Kim Valid |= ACPI_VALID_STA; 427*a159c266SJung-uk Kim } 428*a159c266SJung-uk Kim 429*a159c266SJung-uk Kim /* Execute the Device._ADR method */ 430*a159c266SJung-uk Kim 431*a159c266SJung-uk Kim Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node, 432*a159c266SJung-uk Kim &Info->Address); 433*a159c266SJung-uk Kim if (ACPI_SUCCESS (Status)) 434*a159c266SJung-uk Kim { 435*a159c266SJung-uk Kim Valid |= ACPI_VALID_ADR; 436*a159c266SJung-uk Kim } 437*a159c266SJung-uk Kim 438*a159c266SJung-uk Kim /* Execute the Device._SxW methods */ 439*a159c266SJung-uk Kim 440*a159c266SJung-uk Kim Status = AcpiUtExecutePowerMethods (Node, 441*a159c266SJung-uk Kim AcpiGbl_LowestDstateNames, ACPI_NUM_SxW_METHODS, 442*a159c266SJung-uk Kim Info->LowestDstates); 443*a159c266SJung-uk Kim if (ACPI_SUCCESS (Status)) 444*a159c266SJung-uk Kim { 445*a159c266SJung-uk Kim Valid |= ACPI_VALID_SXWS; 446*a159c266SJung-uk Kim } 447*a159c266SJung-uk Kim 448*a159c266SJung-uk Kim /* Execute the Device._SxD methods */ 449*a159c266SJung-uk Kim 450*a159c266SJung-uk Kim Status = AcpiUtExecutePowerMethods (Node, 451*a159c266SJung-uk Kim AcpiGbl_HighestDstateNames, ACPI_NUM_SxD_METHODS, 452*a159c266SJung-uk Kim Info->HighestDstates); 453*a159c266SJung-uk Kim if (ACPI_SUCCESS (Status)) 454*a159c266SJung-uk Kim { 455*a159c266SJung-uk Kim Valid |= ACPI_VALID_SXDS; 456*a159c266SJung-uk Kim } 457*a159c266SJung-uk Kim } 458*a159c266SJung-uk Kim 459*a159c266SJung-uk Kim /* 460*a159c266SJung-uk Kim * Create a pointer to the string area of the return buffer. 461*a159c266SJung-uk Kim * Point to the end of the base ACPI_DEVICE_INFO structure. 462*a159c266SJung-uk Kim */ 463*a159c266SJung-uk Kim NextIdString = ACPI_CAST_PTR (char, Info->CompatibleIdList.Ids); 464*a159c266SJung-uk Kim if (CidList) 465*a159c266SJung-uk Kim { 466*a159c266SJung-uk Kim /* Point past the CID DEVICE_ID array */ 467*a159c266SJung-uk Kim 468*a159c266SJung-uk Kim NextIdString += ((ACPI_SIZE) CidList->Count * sizeof (ACPI_DEVICE_ID)); 469*a159c266SJung-uk Kim } 470*a159c266SJung-uk Kim 471*a159c266SJung-uk Kim /* 472*a159c266SJung-uk Kim * Copy the HID, UID, and CIDs to the return buffer. The variable-length 473*a159c266SJung-uk Kim * strings are copied to the reserved area at the end of the buffer. 474*a159c266SJung-uk Kim * 475*a159c266SJung-uk Kim * For HID and CID, check if the ID is a PCI Root Bridge. 476*a159c266SJung-uk Kim */ 477*a159c266SJung-uk Kim if (Hid) 478*a159c266SJung-uk Kim { 479*a159c266SJung-uk Kim NextIdString = AcpiNsCopyDeviceId (&Info->HardwareId, 480*a159c266SJung-uk Kim Hid, NextIdString); 481*a159c266SJung-uk Kim 482*a159c266SJung-uk Kim if (AcpiUtIsPciRootBridge (Hid->String)) 483*a159c266SJung-uk Kim { 484*a159c266SJung-uk Kim Info->Flags |= ACPI_PCI_ROOT_BRIDGE; 485*a159c266SJung-uk Kim } 486*a159c266SJung-uk Kim } 487*a159c266SJung-uk Kim 488*a159c266SJung-uk Kim if (Uid) 489*a159c266SJung-uk Kim { 490*a159c266SJung-uk Kim NextIdString = AcpiNsCopyDeviceId (&Info->UniqueId, 491*a159c266SJung-uk Kim Uid, NextIdString); 492*a159c266SJung-uk Kim } 493*a159c266SJung-uk Kim 494*a159c266SJung-uk Kim if (CidList) 495*a159c266SJung-uk Kim { 496*a159c266SJung-uk Kim Info->CompatibleIdList.Count = CidList->Count; 497*a159c266SJung-uk Kim Info->CompatibleIdList.ListSize = CidList->ListSize; 498*a159c266SJung-uk Kim 499*a159c266SJung-uk Kim /* Copy each CID */ 500*a159c266SJung-uk Kim 501*a159c266SJung-uk Kim for (i = 0; i < CidList->Count; i++) 502*a159c266SJung-uk Kim { 503*a159c266SJung-uk Kim NextIdString = AcpiNsCopyDeviceId (&Info->CompatibleIdList.Ids[i], 504*a159c266SJung-uk Kim &CidList->Ids[i], NextIdString); 505*a159c266SJung-uk Kim 506*a159c266SJung-uk Kim if (AcpiUtIsPciRootBridge (CidList->Ids[i].String)) 507*a159c266SJung-uk Kim { 508*a159c266SJung-uk Kim Info->Flags |= ACPI_PCI_ROOT_BRIDGE; 509*a159c266SJung-uk Kim } 510*a159c266SJung-uk Kim } 511*a159c266SJung-uk Kim } 512*a159c266SJung-uk Kim 513*a159c266SJung-uk Kim /* Copy the fixed-length data */ 514*a159c266SJung-uk Kim 515*a159c266SJung-uk Kim Info->InfoSize = InfoSize; 516*a159c266SJung-uk Kim Info->Type = Type; 517*a159c266SJung-uk Kim Info->Name = Name; 518*a159c266SJung-uk Kim Info->ParamCount = ParamCount; 519*a159c266SJung-uk Kim Info->Valid = Valid; 520*a159c266SJung-uk Kim 521*a159c266SJung-uk Kim *ReturnBuffer = Info; 522*a159c266SJung-uk Kim Status = AE_OK; 523*a159c266SJung-uk Kim 524*a159c266SJung-uk Kim 525*a159c266SJung-uk Kim Cleanup: 526*a159c266SJung-uk Kim if (Hid) 527*a159c266SJung-uk Kim { 528*a159c266SJung-uk Kim ACPI_FREE (Hid); 529*a159c266SJung-uk Kim } 530*a159c266SJung-uk Kim if (Uid) 531*a159c266SJung-uk Kim { 532*a159c266SJung-uk Kim ACPI_FREE (Uid); 533*a159c266SJung-uk Kim } 534*a159c266SJung-uk Kim if (CidList) 535*a159c266SJung-uk Kim { 536*a159c266SJung-uk Kim ACPI_FREE (CidList); 537*a159c266SJung-uk Kim } 538*a159c266SJung-uk Kim return (Status); 539*a159c266SJung-uk Kim } 540*a159c266SJung-uk Kim 541*a159c266SJung-uk Kim ACPI_EXPORT_SYMBOL (AcpiGetObjectInfo) 542*a159c266SJung-uk Kim 543*a159c266SJung-uk Kim 544*a159c266SJung-uk Kim /****************************************************************************** 545*a159c266SJung-uk Kim * 546*a159c266SJung-uk Kim * FUNCTION: AcpiInstallMethod 547*a159c266SJung-uk Kim * 548*a159c266SJung-uk Kim * PARAMETERS: Buffer - An ACPI table containing one control method 549*a159c266SJung-uk Kim * 550*a159c266SJung-uk Kim * RETURN: Status 551*a159c266SJung-uk Kim * 552*a159c266SJung-uk Kim * DESCRIPTION: Install a control method into the namespace. If the method 553*a159c266SJung-uk Kim * name already exists in the namespace, it is overwritten. The 554*a159c266SJung-uk Kim * input buffer must contain a valid DSDT or SSDT containing a 555*a159c266SJung-uk Kim * single control method. 556*a159c266SJung-uk Kim * 557*a159c266SJung-uk Kim ******************************************************************************/ 558*a159c266SJung-uk Kim 559*a159c266SJung-uk Kim ACPI_STATUS 560*a159c266SJung-uk Kim AcpiInstallMethod ( 561*a159c266SJung-uk Kim UINT8 *Buffer) 562*a159c266SJung-uk Kim { 563*a159c266SJung-uk Kim ACPI_TABLE_HEADER *Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, Buffer); 564*a159c266SJung-uk Kim UINT8 *AmlBuffer; 565*a159c266SJung-uk Kim UINT8 *AmlStart; 566*a159c266SJung-uk Kim char *Path; 567*a159c266SJung-uk Kim ACPI_NAMESPACE_NODE *Node; 568*a159c266SJung-uk Kim ACPI_OPERAND_OBJECT *MethodObj; 569*a159c266SJung-uk Kim ACPI_PARSE_STATE ParserState; 570*a159c266SJung-uk Kim UINT32 AmlLength; 571*a159c266SJung-uk Kim UINT16 Opcode; 572*a159c266SJung-uk Kim UINT8 MethodFlags; 573*a159c266SJung-uk Kim ACPI_STATUS Status; 574*a159c266SJung-uk Kim 575*a159c266SJung-uk Kim 576*a159c266SJung-uk Kim /* Parameter validation */ 577*a159c266SJung-uk Kim 578*a159c266SJung-uk Kim if (!Buffer) 579*a159c266SJung-uk Kim { 580*a159c266SJung-uk Kim return (AE_BAD_PARAMETER); 581*a159c266SJung-uk Kim } 582*a159c266SJung-uk Kim 583*a159c266SJung-uk Kim /* Table must be a DSDT or SSDT */ 584*a159c266SJung-uk Kim 585*a159c266SJung-uk Kim if (!ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT) && 586*a159c266SJung-uk Kim !ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT)) 587*a159c266SJung-uk Kim { 588*a159c266SJung-uk Kim return (AE_BAD_HEADER); 589*a159c266SJung-uk Kim } 590*a159c266SJung-uk Kim 591*a159c266SJung-uk Kim /* First AML opcode in the table must be a control method */ 592*a159c266SJung-uk Kim 593*a159c266SJung-uk Kim ParserState.Aml = Buffer + sizeof (ACPI_TABLE_HEADER); 594*a159c266SJung-uk Kim Opcode = AcpiPsPeekOpcode (&ParserState); 595*a159c266SJung-uk Kim if (Opcode != AML_METHOD_OP) 596*a159c266SJung-uk Kim { 597*a159c266SJung-uk Kim return (AE_BAD_PARAMETER); 598*a159c266SJung-uk Kim } 599*a159c266SJung-uk Kim 600*a159c266SJung-uk Kim /* Extract method information from the raw AML */ 601*a159c266SJung-uk Kim 602*a159c266SJung-uk Kim ParserState.Aml += AcpiPsGetOpcodeSize (Opcode); 603*a159c266SJung-uk Kim ParserState.PkgEnd = AcpiPsGetNextPackageEnd (&ParserState); 604*a159c266SJung-uk Kim Path = AcpiPsGetNextNamestring (&ParserState); 605*a159c266SJung-uk Kim MethodFlags = *ParserState.Aml++; 606*a159c266SJung-uk Kim AmlStart = ParserState.Aml; 607*a159c266SJung-uk Kim AmlLength = ACPI_PTR_DIFF (ParserState.PkgEnd, AmlStart); 608*a159c266SJung-uk Kim 609*a159c266SJung-uk Kim /* 610*a159c266SJung-uk Kim * Allocate resources up-front. We don't want to have to delete a new 611*a159c266SJung-uk Kim * node from the namespace if we cannot allocate memory. 612*a159c266SJung-uk Kim */ 613*a159c266SJung-uk Kim AmlBuffer = ACPI_ALLOCATE (AmlLength); 614*a159c266SJung-uk Kim if (!AmlBuffer) 615*a159c266SJung-uk Kim { 616*a159c266SJung-uk Kim return (AE_NO_MEMORY); 617*a159c266SJung-uk Kim } 618*a159c266SJung-uk Kim 619*a159c266SJung-uk Kim MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); 620*a159c266SJung-uk Kim if (!MethodObj) 621*a159c266SJung-uk Kim { 622*a159c266SJung-uk Kim ACPI_FREE (AmlBuffer); 623*a159c266SJung-uk Kim return (AE_NO_MEMORY); 624*a159c266SJung-uk Kim } 625*a159c266SJung-uk Kim 626*a159c266SJung-uk Kim /* Lock namespace for AcpiNsLookup, we may be creating a new node */ 627*a159c266SJung-uk Kim 628*a159c266SJung-uk Kim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 629*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) 630*a159c266SJung-uk Kim { 631*a159c266SJung-uk Kim goto ErrorExit; 632*a159c266SJung-uk Kim } 633*a159c266SJung-uk Kim 634*a159c266SJung-uk Kim /* The lookup either returns an existing node or creates a new one */ 635*a159c266SJung-uk Kim 636*a159c266SJung-uk Kim Status = AcpiNsLookup (NULL, Path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1, 637*a159c266SJung-uk Kim ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND, NULL, &Node); 638*a159c266SJung-uk Kim 639*a159c266SJung-uk Kim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 640*a159c266SJung-uk Kim 641*a159c266SJung-uk Kim if (ACPI_FAILURE (Status)) /* NsLookup */ 642*a159c266SJung-uk Kim { 643*a159c266SJung-uk Kim if (Status != AE_ALREADY_EXISTS) 644*a159c266SJung-uk Kim { 645*a159c266SJung-uk Kim goto ErrorExit; 646*a159c266SJung-uk Kim } 647*a159c266SJung-uk Kim 648*a159c266SJung-uk Kim /* Node existed previously, make sure it is a method node */ 649*a159c266SJung-uk Kim 650*a159c266SJung-uk Kim if (Node->Type != ACPI_TYPE_METHOD) 651*a159c266SJung-uk Kim { 652*a159c266SJung-uk Kim Status = AE_TYPE; 653*a159c266SJung-uk Kim goto ErrorExit; 654*a159c266SJung-uk Kim } 655*a159c266SJung-uk Kim } 656*a159c266SJung-uk Kim 657*a159c266SJung-uk Kim /* Copy the method AML to the local buffer */ 658*a159c266SJung-uk Kim 659*a159c266SJung-uk Kim ACPI_MEMCPY (AmlBuffer, AmlStart, AmlLength); 660*a159c266SJung-uk Kim 661*a159c266SJung-uk Kim /* Initialize the method object with the new method's information */ 662*a159c266SJung-uk Kim 663*a159c266SJung-uk Kim MethodObj->Method.AmlStart = AmlBuffer; 664*a159c266SJung-uk Kim MethodObj->Method.AmlLength = AmlLength; 665*a159c266SJung-uk Kim 666*a159c266SJung-uk Kim MethodObj->Method.ParamCount = (UINT8) 667*a159c266SJung-uk Kim (MethodFlags & AML_METHOD_ARG_COUNT); 668*a159c266SJung-uk Kim 669*a159c266SJung-uk Kim if (MethodFlags & AML_METHOD_SERIALIZED) 670*a159c266SJung-uk Kim { 671*a159c266SJung-uk Kim MethodObj->Method.InfoFlags = ACPI_METHOD_SERIALIZED; 672*a159c266SJung-uk Kim 673*a159c266SJung-uk Kim MethodObj->Method.SyncLevel = (UINT8) 674*a159c266SJung-uk Kim ((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4); 675*a159c266SJung-uk Kim } 676*a159c266SJung-uk Kim 677*a159c266SJung-uk Kim /* 678*a159c266SJung-uk Kim * Now that it is complete, we can attach the new method object to 679*a159c266SJung-uk Kim * the method Node (detaches/deletes any existing object) 680*a159c266SJung-uk Kim */ 681*a159c266SJung-uk Kim Status = AcpiNsAttachObject (Node, MethodObj, ACPI_TYPE_METHOD); 682*a159c266SJung-uk Kim 683*a159c266SJung-uk Kim /* 684*a159c266SJung-uk Kim * Flag indicates AML buffer is dynamic, must be deleted later. 685*a159c266SJung-uk Kim * Must be set only after attach above. 686*a159c266SJung-uk Kim */ 687*a159c266SJung-uk Kim Node->Flags |= ANOBJ_ALLOCATED_BUFFER; 688*a159c266SJung-uk Kim 689*a159c266SJung-uk Kim /* Remove local reference to the method object */ 690*a159c266SJung-uk Kim 691*a159c266SJung-uk Kim AcpiUtRemoveReference (MethodObj); 692*a159c266SJung-uk Kim return (Status); 693*a159c266SJung-uk Kim 694*a159c266SJung-uk Kim 695*a159c266SJung-uk Kim ErrorExit: 696*a159c266SJung-uk Kim 697*a159c266SJung-uk Kim ACPI_FREE (AmlBuffer); 698*a159c266SJung-uk Kim ACPI_FREE (MethodObj); 699*a159c266SJung-uk Kim return (Status); 700*a159c266SJung-uk Kim } 701*a159c266SJung-uk Kim 702*a159c266SJung-uk Kim ACPI_EXPORT_SYMBOL (AcpiInstallMethod) 703