xref: /titanic_50/usr/src/uts/intel/io/acpica/utilities/utids.c (revision aab83bb83be7342f6cfccaed8d5fe0b2f404855d)
1 /******************************************************************************
2  *
3  * Module Name: utids - support for device IDs - HID, UID, CID
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2011, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #define __UTIDS_C__
45 
46 #include "acpi.h"
47 #include "accommon.h"
48 #include "acinterp.h"
49 
50 
51 #define _COMPONENT          ACPI_UTILITIES
52         ACPI_MODULE_NAME    ("utids")
53 
54 
55 /*******************************************************************************
56  *
57  * FUNCTION:    AcpiUtExecute_HID
58  *
59  * PARAMETERS:  DeviceNode          - Node for the device
60  *              ReturnId            - Where the string HID is returned
61  *
62  * RETURN:      Status
63  *
64  * DESCRIPTION: Executes the _HID control method that returns the hardware
65  *              ID of the device. The HID is either an 32-bit encoded EISAID
66  *              Integer or a String. A string is always returned. An EISAID
67  *              is converted to a string.
68  *
69  *              NOTE: Internal function, no parameter validation
70  *
71  ******************************************************************************/
72 
73 ACPI_STATUS
74 AcpiUtExecute_HID (
75     ACPI_NAMESPACE_NODE     *DeviceNode,
76     ACPI_DEVICE_ID          **ReturnId)
77 {
78     ACPI_OPERAND_OBJECT     *ObjDesc;
79     ACPI_DEVICE_ID          *Hid;
80     UINT32                  Length;
81     ACPI_STATUS             Status;
82 
83 
84     ACPI_FUNCTION_TRACE (UtExecute_HID);
85 
86 
87     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__HID,
88                 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc);
89     if (ACPI_FAILURE (Status))
90     {
91         return_ACPI_STATUS (Status);
92     }
93 
94     /* Get the size of the String to be returned, includes null terminator */
95 
96     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
97     {
98         Length = ACPI_EISAID_STRING_SIZE;
99     }
100     else
101     {
102         Length = ObjDesc->String.Length + 1;
103     }
104 
105     /* Allocate a buffer for the HID */
106 
107     Hid = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_DEVICE_ID) + (ACPI_SIZE) Length);
108     if (!Hid)
109     {
110         Status = AE_NO_MEMORY;
111         goto Cleanup;
112     }
113 
114     /* Area for the string starts after DEVICE_ID struct */
115 
116     Hid->String = ACPI_ADD_PTR (char, Hid, sizeof (ACPI_DEVICE_ID));
117 
118     /* Convert EISAID to a string or simply copy existing string */
119 
120     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
121     {
122         AcpiExEisaIdToString (Hid->String, ObjDesc->Integer.Value);
123     }
124     else
125     {
126         ACPI_STRCPY (Hid->String, ObjDesc->String.Pointer);
127     }
128 
129     Hid->Length = Length;
130     *ReturnId = Hid;
131 
132 
133 Cleanup:
134 
135     /* On exit, we must delete the return object */
136 
137     AcpiUtRemoveReference (ObjDesc);
138     return_ACPI_STATUS (Status);
139 }
140 
141 
142 /*******************************************************************************
143  *
144  * FUNCTION:    AcpiUtExecute_UID
145  *
146  * PARAMETERS:  DeviceNode          - Node for the device
147  *              ReturnId            - Where the string UID is returned
148  *
149  * RETURN:      Status
150  *
151  * DESCRIPTION: Executes the _UID control method that returns the unique
152  *              ID of the device. The UID is either a 64-bit Integer (NOT an
153  *              EISAID) or a string. Always returns a string. A 64-bit integer
154  *              is converted to a decimal string.
155  *
156  *              NOTE: Internal function, no parameter validation
157  *
158  ******************************************************************************/
159 
160 ACPI_STATUS
161 AcpiUtExecute_UID (
162     ACPI_NAMESPACE_NODE     *DeviceNode,
163     ACPI_DEVICE_ID          **ReturnId)
164 {
165     ACPI_OPERAND_OBJECT     *ObjDesc;
166     ACPI_DEVICE_ID          *Uid;
167     UINT32                  Length;
168     ACPI_STATUS             Status;
169 
170 
171     ACPI_FUNCTION_TRACE (UtExecute_UID);
172 
173 
174     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__UID,
175                 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc);
176     if (ACPI_FAILURE (Status))
177     {
178         return_ACPI_STATUS (Status);
179     }
180 
181     /* Get the size of the String to be returned, includes null terminator */
182 
183     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
184     {
185         Length = ACPI_MAX64_DECIMAL_DIGITS + 1;
186     }
187     else
188     {
189         Length = ObjDesc->String.Length + 1;
190     }
191 
192     /* Allocate a buffer for the UID */
193 
194     Uid = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_DEVICE_ID) + (ACPI_SIZE) Length);
195     if (!Uid)
196     {
197         Status = AE_NO_MEMORY;
198         goto Cleanup;
199     }
200 
201     /* Area for the string starts after DEVICE_ID struct */
202 
203     Uid->String = ACPI_ADD_PTR (char, Uid, sizeof (ACPI_DEVICE_ID));
204 
205     /* Convert an Integer to string, or just copy an existing string */
206 
207     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
208     {
209         AcpiExIntegerToString (Uid->String, ObjDesc->Integer.Value);
210     }
211     else
212     {
213         ACPI_STRCPY (Uid->String, ObjDesc->String.Pointer);
214     }
215 
216     Uid->Length = Length;
217     *ReturnId = Uid;
218 
219 
220 Cleanup:
221 
222     /* On exit, we must delete the return object */
223 
224     AcpiUtRemoveReference (ObjDesc);
225     return_ACPI_STATUS (Status);
226 }
227 
228 
229 /*******************************************************************************
230  *
231  * FUNCTION:    AcpiUtExecute_CID
232  *
233  * PARAMETERS:  DeviceNode          - Node for the device
234  *              ReturnCidList       - Where the CID list is returned
235  *
236  * RETURN:      Status, list of CID strings
237  *
238  * DESCRIPTION: Executes the _CID control method that returns one or more
239  *              compatible hardware IDs for the device.
240  *
241  *              NOTE: Internal function, no parameter validation
242  *
243  * A _CID method can return either a single compatible ID or a package of
244  * compatible IDs. Each compatible ID can be one of the following:
245  * 1) Integer (32 bit compressed EISA ID) or
246  * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
247  *
248  * The Integer CIDs are converted to string format by this function.
249  *
250  ******************************************************************************/
251 
252 ACPI_STATUS
253 AcpiUtExecute_CID (
254     ACPI_NAMESPACE_NODE     *DeviceNode,
255     ACPI_DEVICE_ID_LIST     **ReturnCidList)
256 {
257     ACPI_OPERAND_OBJECT     **CidObjects;
258     ACPI_OPERAND_OBJECT     *ObjDesc;
259     ACPI_DEVICE_ID_LIST     *CidList;
260     char                    *NextIdString;
261     UINT32                  StringAreaSize;
262     UINT32                  Length;
263     UINT32                  CidListSize;
264     ACPI_STATUS             Status;
265     UINT32                  Count;
266     UINT32                  i;
267 
268 
269     ACPI_FUNCTION_TRACE (UtExecute_CID);
270 
271 
272     /* Evaluate the _CID method for this device */
273 
274     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__CID,
275                 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE,
276                 &ObjDesc);
277     if (ACPI_FAILURE (Status))
278     {
279         return_ACPI_STATUS (Status);
280     }
281 
282     /*
283      * Get the count and size of the returned _CIDs. _CID can return either
284      * a Package of Integers/Strings or a single Integer or String.
285      * Note: This section also validates that all CID elements are of the
286      * correct type (Integer or String).
287      */
288     if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
289     {
290         Count = ObjDesc->Package.Count;
291         CidObjects = ObjDesc->Package.Elements;
292     }
293     else /* Single Integer or String CID */
294     {
295         Count = 1;
296         CidObjects = &ObjDesc;
297     }
298 
299     StringAreaSize = 0;
300     for (i = 0; i < Count; i++)
301     {
302         /* String lengths include null terminator */
303 
304         switch (CidObjects[i]->Common.Type)
305         {
306         case ACPI_TYPE_INTEGER:
307             StringAreaSize += ACPI_EISAID_STRING_SIZE;
308             break;
309 
310         case ACPI_TYPE_STRING:
311             StringAreaSize += CidObjects[i]->String.Length + 1;
312             break;
313 
314         default:
315             Status = AE_TYPE;
316             goto Cleanup;
317         }
318     }
319 
320     /*
321      * Now that we know the length of the CIDs, allocate return buffer:
322      * 1) Size of the base structure +
323      * 2) Size of the CID DEVICE_ID array +
324      * 3) Size of the actual CID strings
325      */
326     CidListSize = sizeof (ACPI_DEVICE_ID_LIST) +
327         ((Count - 1) * sizeof (ACPI_DEVICE_ID)) +
328         StringAreaSize;
329 
330     CidList = ACPI_ALLOCATE_ZEROED (CidListSize);
331     if (!CidList)
332     {
333         Status = AE_NO_MEMORY;
334         goto Cleanup;
335     }
336 
337     /* Area for CID strings starts after the CID DEVICE_ID array */
338 
339     NextIdString = ACPI_CAST_PTR (char, CidList->Ids) +
340         ((ACPI_SIZE) Count * sizeof (ACPI_DEVICE_ID));
341 
342     /* Copy/convert the CIDs to the return buffer */
343 
344     for (i = 0; i < Count; i++)
345     {
346         if (CidObjects[i]->Common.Type == ACPI_TYPE_INTEGER)
347         {
348             /* Convert the Integer (EISAID) CID to a string */
349 
350             AcpiExEisaIdToString (NextIdString, CidObjects[i]->Integer.Value);
351             Length = ACPI_EISAID_STRING_SIZE;
352         }
353         else /* ACPI_TYPE_STRING */
354         {
355             /* Copy the String CID from the returned object */
356 
357             ACPI_STRCPY (NextIdString, CidObjects[i]->String.Pointer);
358             Length = CidObjects[i]->String.Length + 1;
359         }
360 
361         CidList->Ids[i].String = NextIdString;
362         CidList->Ids[i].Length = Length;
363         NextIdString += Length;
364     }
365 
366     /* Finish the CID list */
367 
368     CidList->Count = Count;
369     CidList->ListSize = CidListSize;
370     *ReturnCidList = CidList;
371 
372 
373 Cleanup:
374 
375     /* On exit, we must delete the _CID return object */
376 
377     AcpiUtRemoveReference (ObjDesc);
378     return_ACPI_STATUS (Status);
379 }
380 
381