xref: /freebsd/sys/contrib/dev/acpica/components/utilities/utids.c (revision 1c0e1b6da9c3c45f81c75137dddaebc748995afc)
1a159c266SJung-uk Kim /******************************************************************************
2a159c266SJung-uk Kim  *
3a159c266SJung-uk Kim  * Module Name: utids - support for device IDs - HID, UID, CID
4a159c266SJung-uk Kim  *
5a159c266SJung-uk Kim  *****************************************************************************/
6a159c266SJung-uk Kim 
7a159c266SJung-uk Kim /*
8*1c0e1b6dSJung-uk Kim  * Copyright (C) 2000 - 2015, Intel Corp.
9a159c266SJung-uk Kim  * All rights reserved.
10a159c266SJung-uk Kim  *
11a159c266SJung-uk Kim  * Redistribution and use in source and binary forms, with or without
12a159c266SJung-uk Kim  * modification, are permitted provided that the following conditions
13a159c266SJung-uk Kim  * are met:
14a159c266SJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
15a159c266SJung-uk Kim  *    notice, this list of conditions, and the following disclaimer,
16a159c266SJung-uk Kim  *    without modification.
17a159c266SJung-uk Kim  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18a159c266SJung-uk Kim  *    substantially similar to the "NO WARRANTY" disclaimer below
19a159c266SJung-uk Kim  *    ("Disclaimer") and any redistribution must be conditioned upon
20a159c266SJung-uk Kim  *    including a substantially similar Disclaimer requirement for further
21a159c266SJung-uk Kim  *    binary redistribution.
22a159c266SJung-uk Kim  * 3. Neither the names of the above-listed copyright holders nor the names
23a159c266SJung-uk Kim  *    of any contributors may be used to endorse or promote products derived
24a159c266SJung-uk Kim  *    from this software without specific prior written permission.
25a159c266SJung-uk Kim  *
26a159c266SJung-uk Kim  * Alternatively, this software may be distributed under the terms of the
27a159c266SJung-uk Kim  * GNU General Public License ("GPL") version 2 as published by the Free
28a159c266SJung-uk Kim  * Software Foundation.
29a159c266SJung-uk Kim  *
30a159c266SJung-uk Kim  * NO WARRANTY
31a159c266SJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32a159c266SJung-uk Kim  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33a159c266SJung-uk Kim  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34a159c266SJung-uk Kim  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35a159c266SJung-uk Kim  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36a159c266SJung-uk Kim  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37a159c266SJung-uk Kim  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38a159c266SJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39a159c266SJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40a159c266SJung-uk Kim  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41a159c266SJung-uk Kim  * POSSIBILITY OF SUCH DAMAGES.
42a159c266SJung-uk Kim  */
43a159c266SJung-uk Kim 
44a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h>
45a159c266SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h>
46a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acinterp.h>
47a159c266SJung-uk Kim 
48a159c266SJung-uk Kim 
49a159c266SJung-uk Kim #define _COMPONENT          ACPI_UTILITIES
50a159c266SJung-uk Kim         ACPI_MODULE_NAME    ("utids")
51a159c266SJung-uk Kim 
52a159c266SJung-uk Kim 
53a159c266SJung-uk Kim /*******************************************************************************
54a159c266SJung-uk Kim  *
55a159c266SJung-uk Kim  * FUNCTION:    AcpiUtExecute_HID
56a159c266SJung-uk Kim  *
57a159c266SJung-uk Kim  * PARAMETERS:  DeviceNode          - Node for the device
58a159c266SJung-uk Kim  *              ReturnId            - Where the string HID is returned
59a159c266SJung-uk Kim  *
60a159c266SJung-uk Kim  * RETURN:      Status
61a159c266SJung-uk Kim  *
62a159c266SJung-uk Kim  * DESCRIPTION: Executes the _HID control method that returns the hardware
63a159c266SJung-uk Kim  *              ID of the device. The HID is either an 32-bit encoded EISAID
64a159c266SJung-uk Kim  *              Integer or a String. A string is always returned. An EISAID
65a159c266SJung-uk Kim  *              is converted to a string.
66a159c266SJung-uk Kim  *
67a159c266SJung-uk Kim  *              NOTE: Internal function, no parameter validation
68a159c266SJung-uk Kim  *
69a159c266SJung-uk Kim  ******************************************************************************/
70a159c266SJung-uk Kim 
71a159c266SJung-uk Kim ACPI_STATUS
72a159c266SJung-uk Kim AcpiUtExecute_HID (
73a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *DeviceNode,
748ef1a331SJung-uk Kim     ACPI_PNP_DEVICE_ID      **ReturnId)
75a159c266SJung-uk Kim {
76a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *ObjDesc;
778ef1a331SJung-uk Kim     ACPI_PNP_DEVICE_ID      *Hid;
78a159c266SJung-uk Kim     UINT32                  Length;
79a159c266SJung-uk Kim     ACPI_STATUS             Status;
80a159c266SJung-uk Kim 
81a159c266SJung-uk Kim 
82a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (UtExecute_HID);
83a159c266SJung-uk Kim 
84a159c266SJung-uk Kim 
85a159c266SJung-uk Kim     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__HID,
86a159c266SJung-uk Kim                 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc);
87a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
88a159c266SJung-uk Kim     {
89a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
90a159c266SJung-uk Kim     }
91a159c266SJung-uk Kim 
92a159c266SJung-uk Kim     /* Get the size of the String to be returned, includes null terminator */
93a159c266SJung-uk Kim 
94a159c266SJung-uk Kim     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
95a159c266SJung-uk Kim     {
96a159c266SJung-uk Kim         Length = ACPI_EISAID_STRING_SIZE;
97a159c266SJung-uk Kim     }
98a159c266SJung-uk Kim     else
99a159c266SJung-uk Kim     {
100a159c266SJung-uk Kim         Length = ObjDesc->String.Length + 1;
101a159c266SJung-uk Kim     }
102a159c266SJung-uk Kim 
103a159c266SJung-uk Kim     /* Allocate a buffer for the HID */
104a159c266SJung-uk Kim 
1058ef1a331SJung-uk Kim     Hid = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length);
106a159c266SJung-uk Kim     if (!Hid)
107a159c266SJung-uk Kim     {
108a159c266SJung-uk Kim         Status = AE_NO_MEMORY;
109a159c266SJung-uk Kim         goto Cleanup;
110a159c266SJung-uk Kim     }
111a159c266SJung-uk Kim 
1128ef1a331SJung-uk Kim     /* Area for the string starts after PNP_DEVICE_ID struct */
113a159c266SJung-uk Kim 
1148ef1a331SJung-uk Kim     Hid->String = ACPI_ADD_PTR (char, Hid, sizeof (ACPI_PNP_DEVICE_ID));
115a159c266SJung-uk Kim 
116a159c266SJung-uk Kim     /* Convert EISAID to a string or simply copy existing string */
117a159c266SJung-uk Kim 
118a159c266SJung-uk Kim     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
119a159c266SJung-uk Kim     {
120a159c266SJung-uk Kim         AcpiExEisaIdToString (Hid->String, ObjDesc->Integer.Value);
121a159c266SJung-uk Kim     }
122a159c266SJung-uk Kim     else
123a159c266SJung-uk Kim     {
124a159c266SJung-uk Kim         ACPI_STRCPY (Hid->String, ObjDesc->String.Pointer);
125a159c266SJung-uk Kim     }
126a159c266SJung-uk Kim 
127a159c266SJung-uk Kim     Hid->Length = Length;
128a159c266SJung-uk Kim     *ReturnId = Hid;
129a159c266SJung-uk Kim 
130a159c266SJung-uk Kim 
131a159c266SJung-uk Kim Cleanup:
132a159c266SJung-uk Kim 
133a159c266SJung-uk Kim     /* On exit, we must delete the return object */
134a159c266SJung-uk Kim 
135a159c266SJung-uk Kim     AcpiUtRemoveReference (ObjDesc);
136a159c266SJung-uk Kim     return_ACPI_STATUS (Status);
137a159c266SJung-uk Kim }
138a159c266SJung-uk Kim 
139a159c266SJung-uk Kim 
140a159c266SJung-uk Kim /*******************************************************************************
141a159c266SJung-uk Kim  *
1428ef1a331SJung-uk Kim  * FUNCTION:    AcpiUtExecute_SUB
1438ef1a331SJung-uk Kim  *
1448ef1a331SJung-uk Kim  * PARAMETERS:  DeviceNode          - Node for the device
1458ef1a331SJung-uk Kim  *              ReturnId            - Where the _SUB is returned
1468ef1a331SJung-uk Kim  *
1478ef1a331SJung-uk Kim  * RETURN:      Status
1488ef1a331SJung-uk Kim  *
1498ef1a331SJung-uk Kim  * DESCRIPTION: Executes the _SUB control method that returns the subsystem
1508ef1a331SJung-uk Kim  *              ID of the device. The _SUB value is always a string containing
1518ef1a331SJung-uk Kim  *              either a valid PNP or ACPI ID.
1528ef1a331SJung-uk Kim  *
1538ef1a331SJung-uk Kim  *              NOTE: Internal function, no parameter validation
1548ef1a331SJung-uk Kim  *
1558ef1a331SJung-uk Kim  ******************************************************************************/
1568ef1a331SJung-uk Kim 
1578ef1a331SJung-uk Kim ACPI_STATUS
1588ef1a331SJung-uk Kim AcpiUtExecute_SUB (
1598ef1a331SJung-uk Kim     ACPI_NAMESPACE_NODE     *DeviceNode,
1608ef1a331SJung-uk Kim     ACPI_PNP_DEVICE_ID      **ReturnId)
1618ef1a331SJung-uk Kim {
1628ef1a331SJung-uk Kim     ACPI_OPERAND_OBJECT     *ObjDesc;
1638ef1a331SJung-uk Kim     ACPI_PNP_DEVICE_ID      *Sub;
1648ef1a331SJung-uk Kim     UINT32                  Length;
1658ef1a331SJung-uk Kim     ACPI_STATUS             Status;
1668ef1a331SJung-uk Kim 
1678ef1a331SJung-uk Kim 
1688ef1a331SJung-uk Kim     ACPI_FUNCTION_TRACE (UtExecute_SUB);
1698ef1a331SJung-uk Kim 
1708ef1a331SJung-uk Kim 
1718ef1a331SJung-uk Kim     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__SUB,
1728ef1a331SJung-uk Kim                 ACPI_BTYPE_STRING, &ObjDesc);
1738ef1a331SJung-uk Kim     if (ACPI_FAILURE (Status))
1748ef1a331SJung-uk Kim     {
1758ef1a331SJung-uk Kim         return_ACPI_STATUS (Status);
1768ef1a331SJung-uk Kim     }
1778ef1a331SJung-uk Kim 
1788ef1a331SJung-uk Kim     /* Get the size of the String to be returned, includes null terminator */
1798ef1a331SJung-uk Kim 
1808ef1a331SJung-uk Kim     Length = ObjDesc->String.Length + 1;
1818ef1a331SJung-uk Kim 
1828ef1a331SJung-uk Kim     /* Allocate a buffer for the SUB */
1838ef1a331SJung-uk Kim 
1848ef1a331SJung-uk Kim     Sub = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length);
1858ef1a331SJung-uk Kim     if (!Sub)
1868ef1a331SJung-uk Kim     {
1878ef1a331SJung-uk Kim         Status = AE_NO_MEMORY;
1888ef1a331SJung-uk Kim         goto Cleanup;
1898ef1a331SJung-uk Kim     }
1908ef1a331SJung-uk Kim 
1918ef1a331SJung-uk Kim     /* Area for the string starts after PNP_DEVICE_ID struct */
1928ef1a331SJung-uk Kim 
1938ef1a331SJung-uk Kim     Sub->String = ACPI_ADD_PTR (char, Sub, sizeof (ACPI_PNP_DEVICE_ID));
1948ef1a331SJung-uk Kim 
1958ef1a331SJung-uk Kim     /* Simply copy existing string */
1968ef1a331SJung-uk Kim 
1978ef1a331SJung-uk Kim     ACPI_STRCPY (Sub->String, ObjDesc->String.Pointer);
1988ef1a331SJung-uk Kim     Sub->Length = Length;
1998ef1a331SJung-uk Kim     *ReturnId = Sub;
2008ef1a331SJung-uk Kim 
2018ef1a331SJung-uk Kim 
2028ef1a331SJung-uk Kim Cleanup:
2038ef1a331SJung-uk Kim 
2048ef1a331SJung-uk Kim     /* On exit, we must delete the return object */
2058ef1a331SJung-uk Kim 
2068ef1a331SJung-uk Kim     AcpiUtRemoveReference (ObjDesc);
2078ef1a331SJung-uk Kim     return_ACPI_STATUS (Status);
2088ef1a331SJung-uk Kim }
2098ef1a331SJung-uk Kim 
2108ef1a331SJung-uk Kim 
2118ef1a331SJung-uk Kim /*******************************************************************************
2128ef1a331SJung-uk Kim  *
213a159c266SJung-uk Kim  * FUNCTION:    AcpiUtExecute_UID
214a159c266SJung-uk Kim  *
215a159c266SJung-uk Kim  * PARAMETERS:  DeviceNode          - Node for the device
216a159c266SJung-uk Kim  *              ReturnId            - Where the string UID is returned
217a159c266SJung-uk Kim  *
218a159c266SJung-uk Kim  * RETURN:      Status
219a159c266SJung-uk Kim  *
220a159c266SJung-uk Kim  * DESCRIPTION: Executes the _UID control method that returns the unique
221a159c266SJung-uk Kim  *              ID of the device. The UID is either a 64-bit Integer (NOT an
222a159c266SJung-uk Kim  *              EISAID) or a string. Always returns a string. A 64-bit integer
223a159c266SJung-uk Kim  *              is converted to a decimal string.
224a159c266SJung-uk Kim  *
225a159c266SJung-uk Kim  *              NOTE: Internal function, no parameter validation
226a159c266SJung-uk Kim  *
227a159c266SJung-uk Kim  ******************************************************************************/
228a159c266SJung-uk Kim 
229a159c266SJung-uk Kim ACPI_STATUS
230a159c266SJung-uk Kim AcpiUtExecute_UID (
231a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *DeviceNode,
2328ef1a331SJung-uk Kim     ACPI_PNP_DEVICE_ID      **ReturnId)
233a159c266SJung-uk Kim {
234a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *ObjDesc;
2358ef1a331SJung-uk Kim     ACPI_PNP_DEVICE_ID      *Uid;
236a159c266SJung-uk Kim     UINT32                  Length;
237a159c266SJung-uk Kim     ACPI_STATUS             Status;
238a159c266SJung-uk Kim 
239a159c266SJung-uk Kim 
240a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (UtExecute_UID);
241a159c266SJung-uk Kim 
242a159c266SJung-uk Kim 
243a159c266SJung-uk Kim     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__UID,
244a159c266SJung-uk Kim                 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc);
245a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
246a159c266SJung-uk Kim     {
247a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
248a159c266SJung-uk Kim     }
249a159c266SJung-uk Kim 
250a159c266SJung-uk Kim     /* Get the size of the String to be returned, includes null terminator */
251a159c266SJung-uk Kim 
252a159c266SJung-uk Kim     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
253a159c266SJung-uk Kim     {
254a159c266SJung-uk Kim         Length = ACPI_MAX64_DECIMAL_DIGITS + 1;
255a159c266SJung-uk Kim     }
256a159c266SJung-uk Kim     else
257a159c266SJung-uk Kim     {
258a159c266SJung-uk Kim         Length = ObjDesc->String.Length + 1;
259a159c266SJung-uk Kim     }
260a159c266SJung-uk Kim 
261a159c266SJung-uk Kim     /* Allocate a buffer for the UID */
262a159c266SJung-uk Kim 
2638ef1a331SJung-uk Kim     Uid = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length);
264a159c266SJung-uk Kim     if (!Uid)
265a159c266SJung-uk Kim     {
266a159c266SJung-uk Kim         Status = AE_NO_MEMORY;
267a159c266SJung-uk Kim         goto Cleanup;
268a159c266SJung-uk Kim     }
269a159c266SJung-uk Kim 
2708ef1a331SJung-uk Kim     /* Area for the string starts after PNP_DEVICE_ID struct */
271a159c266SJung-uk Kim 
2728ef1a331SJung-uk Kim     Uid->String = ACPI_ADD_PTR (char, Uid, sizeof (ACPI_PNP_DEVICE_ID));
273a159c266SJung-uk Kim 
274a159c266SJung-uk Kim     /* Convert an Integer to string, or just copy an existing string */
275a159c266SJung-uk Kim 
276a159c266SJung-uk Kim     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
277a159c266SJung-uk Kim     {
278a159c266SJung-uk Kim         AcpiExIntegerToString (Uid->String, ObjDesc->Integer.Value);
279a159c266SJung-uk Kim     }
280a159c266SJung-uk Kim     else
281a159c266SJung-uk Kim     {
282a159c266SJung-uk Kim         ACPI_STRCPY (Uid->String, ObjDesc->String.Pointer);
283a159c266SJung-uk Kim     }
284a159c266SJung-uk Kim 
285a159c266SJung-uk Kim     Uid->Length = Length;
286a159c266SJung-uk Kim     *ReturnId = Uid;
287a159c266SJung-uk Kim 
288a159c266SJung-uk Kim 
289a159c266SJung-uk Kim Cleanup:
290a159c266SJung-uk Kim 
291a159c266SJung-uk Kim     /* On exit, we must delete the return object */
292a159c266SJung-uk Kim 
293a159c266SJung-uk Kim     AcpiUtRemoveReference (ObjDesc);
294a159c266SJung-uk Kim     return_ACPI_STATUS (Status);
295a159c266SJung-uk Kim }
296a159c266SJung-uk Kim 
297a159c266SJung-uk Kim 
298a159c266SJung-uk Kim /*******************************************************************************
299a159c266SJung-uk Kim  *
300a159c266SJung-uk Kim  * FUNCTION:    AcpiUtExecute_CID
301a159c266SJung-uk Kim  *
302a159c266SJung-uk Kim  * PARAMETERS:  DeviceNode          - Node for the device
303a159c266SJung-uk Kim  *              ReturnCidList       - Where the CID list is returned
304a159c266SJung-uk Kim  *
305a159c266SJung-uk Kim  * RETURN:      Status, list of CID strings
306a159c266SJung-uk Kim  *
307a159c266SJung-uk Kim  * DESCRIPTION: Executes the _CID control method that returns one or more
308a159c266SJung-uk Kim  *              compatible hardware IDs for the device.
309a159c266SJung-uk Kim  *
310a159c266SJung-uk Kim  *              NOTE: Internal function, no parameter validation
311a159c266SJung-uk Kim  *
312a159c266SJung-uk Kim  * A _CID method can return either a single compatible ID or a package of
313a159c266SJung-uk Kim  * compatible IDs. Each compatible ID can be one of the following:
314a159c266SJung-uk Kim  * 1) Integer (32 bit compressed EISA ID) or
315a159c266SJung-uk Kim  * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
316a159c266SJung-uk Kim  *
317a159c266SJung-uk Kim  * The Integer CIDs are converted to string format by this function.
318a159c266SJung-uk Kim  *
319a159c266SJung-uk Kim  ******************************************************************************/
320a159c266SJung-uk Kim 
321a159c266SJung-uk Kim ACPI_STATUS
322a159c266SJung-uk Kim AcpiUtExecute_CID (
323a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *DeviceNode,
3248ef1a331SJung-uk Kim     ACPI_PNP_DEVICE_ID_LIST **ReturnCidList)
325a159c266SJung-uk Kim {
326a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     **CidObjects;
327a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *ObjDesc;
3288ef1a331SJung-uk Kim     ACPI_PNP_DEVICE_ID_LIST *CidList;
329a159c266SJung-uk Kim     char                    *NextIdString;
330a159c266SJung-uk Kim     UINT32                  StringAreaSize;
331a159c266SJung-uk Kim     UINT32                  Length;
332a159c266SJung-uk Kim     UINT32                  CidListSize;
333a159c266SJung-uk Kim     ACPI_STATUS             Status;
334a159c266SJung-uk Kim     UINT32                  Count;
335a159c266SJung-uk Kim     UINT32                  i;
336a159c266SJung-uk Kim 
337a159c266SJung-uk Kim 
338a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (UtExecute_CID);
339a159c266SJung-uk Kim 
340a159c266SJung-uk Kim 
341a159c266SJung-uk Kim     /* Evaluate the _CID method for this device */
342a159c266SJung-uk Kim 
343a159c266SJung-uk Kim     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__CID,
344a159c266SJung-uk Kim                 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE,
345a159c266SJung-uk Kim                 &ObjDesc);
346a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
347a159c266SJung-uk Kim     {
348a159c266SJung-uk Kim         return_ACPI_STATUS (Status);
349a159c266SJung-uk Kim     }
350a159c266SJung-uk Kim 
351a159c266SJung-uk Kim     /*
352a159c266SJung-uk Kim      * Get the count and size of the returned _CIDs. _CID can return either
353a159c266SJung-uk Kim      * a Package of Integers/Strings or a single Integer or String.
354a159c266SJung-uk Kim      * Note: This section also validates that all CID elements are of the
355a159c266SJung-uk Kim      * correct type (Integer or String).
356a159c266SJung-uk Kim      */
357a159c266SJung-uk Kim     if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
358a159c266SJung-uk Kim     {
359a159c266SJung-uk Kim         Count = ObjDesc->Package.Count;
360a159c266SJung-uk Kim         CidObjects = ObjDesc->Package.Elements;
361a159c266SJung-uk Kim     }
362a159c266SJung-uk Kim     else /* Single Integer or String CID */
363a159c266SJung-uk Kim     {
364a159c266SJung-uk Kim         Count = 1;
365a159c266SJung-uk Kim         CidObjects = &ObjDesc;
366a159c266SJung-uk Kim     }
367a159c266SJung-uk Kim 
368a159c266SJung-uk Kim     StringAreaSize = 0;
369a159c266SJung-uk Kim     for (i = 0; i < Count; i++)
370a159c266SJung-uk Kim     {
371a159c266SJung-uk Kim         /* String lengths include null terminator */
372a159c266SJung-uk Kim 
373a159c266SJung-uk Kim         switch (CidObjects[i]->Common.Type)
374a159c266SJung-uk Kim         {
375a159c266SJung-uk Kim         case ACPI_TYPE_INTEGER:
376a9d8d09cSJung-uk Kim 
377a159c266SJung-uk Kim             StringAreaSize += ACPI_EISAID_STRING_SIZE;
378a159c266SJung-uk Kim             break;
379a159c266SJung-uk Kim 
380a159c266SJung-uk Kim         case ACPI_TYPE_STRING:
381a9d8d09cSJung-uk Kim 
382a159c266SJung-uk Kim             StringAreaSize += CidObjects[i]->String.Length + 1;
383a159c266SJung-uk Kim             break;
384a159c266SJung-uk Kim 
385a159c266SJung-uk Kim         default:
386a9d8d09cSJung-uk Kim 
387a159c266SJung-uk Kim             Status = AE_TYPE;
388a159c266SJung-uk Kim             goto Cleanup;
389a159c266SJung-uk Kim         }
390a159c266SJung-uk Kim     }
391a159c266SJung-uk Kim 
392a159c266SJung-uk Kim     /*
393a159c266SJung-uk Kim      * Now that we know the length of the CIDs, allocate return buffer:
394a159c266SJung-uk Kim      * 1) Size of the base structure +
3958ef1a331SJung-uk Kim      * 2) Size of the CID PNP_DEVICE_ID array +
396a159c266SJung-uk Kim      * 3) Size of the actual CID strings
397a159c266SJung-uk Kim      */
3988ef1a331SJung-uk Kim     CidListSize = sizeof (ACPI_PNP_DEVICE_ID_LIST) +
3998ef1a331SJung-uk Kim         ((Count - 1) * sizeof (ACPI_PNP_DEVICE_ID)) +
400a159c266SJung-uk Kim         StringAreaSize;
401a159c266SJung-uk Kim 
402a159c266SJung-uk Kim     CidList = ACPI_ALLOCATE_ZEROED (CidListSize);
403a159c266SJung-uk Kim     if (!CidList)
404a159c266SJung-uk Kim     {
405a159c266SJung-uk Kim         Status = AE_NO_MEMORY;
406a159c266SJung-uk Kim         goto Cleanup;
407a159c266SJung-uk Kim     }
408a159c266SJung-uk Kim 
4098ef1a331SJung-uk Kim     /* Area for CID strings starts after the CID PNP_DEVICE_ID array */
410a159c266SJung-uk Kim 
411a159c266SJung-uk Kim     NextIdString = ACPI_CAST_PTR (char, CidList->Ids) +
4128ef1a331SJung-uk Kim         ((ACPI_SIZE) Count * sizeof (ACPI_PNP_DEVICE_ID));
413a159c266SJung-uk Kim 
414a159c266SJung-uk Kim     /* Copy/convert the CIDs to the return buffer */
415a159c266SJung-uk Kim 
416a159c266SJung-uk Kim     for (i = 0; i < Count; i++)
417a159c266SJung-uk Kim     {
418a159c266SJung-uk Kim         if (CidObjects[i]->Common.Type == ACPI_TYPE_INTEGER)
419a159c266SJung-uk Kim         {
420a159c266SJung-uk Kim             /* Convert the Integer (EISAID) CID to a string */
421a159c266SJung-uk Kim 
422a159c266SJung-uk Kim             AcpiExEisaIdToString (NextIdString, CidObjects[i]->Integer.Value);
423a159c266SJung-uk Kim             Length = ACPI_EISAID_STRING_SIZE;
424a159c266SJung-uk Kim         }
425a159c266SJung-uk Kim         else /* ACPI_TYPE_STRING */
426a159c266SJung-uk Kim         {
427a159c266SJung-uk Kim             /* Copy the String CID from the returned object */
428a159c266SJung-uk Kim 
429a159c266SJung-uk Kim             ACPI_STRCPY (NextIdString, CidObjects[i]->String.Pointer);
430a159c266SJung-uk Kim             Length = CidObjects[i]->String.Length + 1;
431a159c266SJung-uk Kim         }
432a159c266SJung-uk Kim 
433a159c266SJung-uk Kim         CidList->Ids[i].String = NextIdString;
434a159c266SJung-uk Kim         CidList->Ids[i].Length = Length;
435a159c266SJung-uk Kim         NextIdString += Length;
436a159c266SJung-uk Kim     }
437a159c266SJung-uk Kim 
438a159c266SJung-uk Kim     /* Finish the CID list */
439a159c266SJung-uk Kim 
440a159c266SJung-uk Kim     CidList->Count = Count;
441a159c266SJung-uk Kim     CidList->ListSize = CidListSize;
442a159c266SJung-uk Kim     *ReturnCidList = CidList;
443a159c266SJung-uk Kim 
444a159c266SJung-uk Kim 
445a159c266SJung-uk Kim Cleanup:
446a159c266SJung-uk Kim 
447a159c266SJung-uk Kim     /* On exit, we must delete the _CID return object */
448a159c266SJung-uk Kim 
449a159c266SJung-uk Kim     AcpiUtRemoveReference (ObjDesc);
450a159c266SJung-uk Kim     return_ACPI_STATUS (Status);
451a159c266SJung-uk Kim }
452