xref: /freebsd/sys/contrib/dev/acpica/components/utilities/utids.c (revision 722b16673c40aedf280895f2f2f676bb494518d7)
1 /******************************************************************************
2  *
3  * Module Name: utids - support for device IDs - HID, UID, CID, SUB, CLS
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2023, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 #include <contrib/dev/acpica/include/acpi.h>
153 #include <contrib/dev/acpica/include/accommon.h>
154 #include <contrib/dev/acpica/include/acinterp.h>
155 
156 
157 #define _COMPONENT          ACPI_UTILITIES
158         ACPI_MODULE_NAME    ("utids")
159 
160 
161 /*******************************************************************************
162  *
163  * FUNCTION:    AcpiUtExecute_HID
164  *
165  * PARAMETERS:  DeviceNode          - Node for the device
166  *              ReturnId            - Where the string HID is returned
167  *
168  * RETURN:      Status
169  *
170  * DESCRIPTION: Executes the _HID control method that returns the hardware
171  *              ID of the device. The HID is either an 32-bit encoded EISAID
172  *              Integer or a String. A string is always returned. An EISAID
173  *              is converted to a string.
174  *
175  *              NOTE: Internal function, no parameter validation
176  *
177  ******************************************************************************/
178 
179 ACPI_STATUS
AcpiUtExecute_HID(ACPI_NAMESPACE_NODE * DeviceNode,ACPI_PNP_DEVICE_ID ** ReturnId)180 AcpiUtExecute_HID (
181     ACPI_NAMESPACE_NODE     *DeviceNode,
182     ACPI_PNP_DEVICE_ID      **ReturnId)
183 {
184     ACPI_OPERAND_OBJECT     *ObjDesc;
185     ACPI_PNP_DEVICE_ID      *Hid;
186     UINT32                  Length;
187     ACPI_STATUS             Status;
188 
189 
190     ACPI_FUNCTION_TRACE (UtExecute_HID);
191 
192 
193     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__HID,
194         ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc);
195     if (ACPI_FAILURE (Status))
196     {
197         return_ACPI_STATUS (Status);
198     }
199 
200     /* Get the size of the String to be returned, includes null terminator */
201 
202     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
203     {
204         Length = ACPI_EISAID_STRING_SIZE;
205     }
206     else
207     {
208         Length = ObjDesc->String.Length + 1;
209     }
210 
211     /* Allocate a buffer for the HID */
212 
213     Hid = ACPI_ALLOCATE_ZEROED (
214         sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length);
215     if (!Hid)
216     {
217         Status = AE_NO_MEMORY;
218         goto Cleanup;
219     }
220 
221     /* Area for the string starts after PNP_DEVICE_ID struct */
222 
223     Hid->String = ACPI_ADD_PTR (char, Hid, sizeof (ACPI_PNP_DEVICE_ID));
224 
225     /* Convert EISAID to a string or simply copy existing string */
226 
227     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
228     {
229         AcpiExEisaIdToString (Hid->String, ObjDesc->Integer.Value);
230     }
231     else
232     {
233         strcpy (Hid->String, ObjDesc->String.Pointer);
234     }
235 
236     Hid->Length = Length;
237     *ReturnId = Hid;
238 
239 
240 Cleanup:
241 
242     /* On exit, we must delete the return object */
243 
244     AcpiUtRemoveReference (ObjDesc);
245     return_ACPI_STATUS (Status);
246 }
247 
248 
249 /*******************************************************************************
250  *
251  * FUNCTION:    AcpiUtExecute_UID
252  *
253  * PARAMETERS:  DeviceNode          - Node for the device
254  *              ReturnId            - Where the string UID is returned
255  *
256  * RETURN:      Status
257  *
258  * DESCRIPTION: Executes the _UID control method that returns the unique
259  *              ID of the device. The UID is either a 64-bit Integer (NOT an
260  *              EISAID) or a string. Always returns a string. A 64-bit integer
261  *              is converted to a decimal string.
262  *
263  *              NOTE: Internal function, no parameter validation
264  *
265  ******************************************************************************/
266 
267 ACPI_STATUS
AcpiUtExecute_UID(ACPI_NAMESPACE_NODE * DeviceNode,ACPI_PNP_DEVICE_ID ** ReturnId)268 AcpiUtExecute_UID (
269     ACPI_NAMESPACE_NODE     *DeviceNode,
270     ACPI_PNP_DEVICE_ID      **ReturnId)
271 {
272     ACPI_OPERAND_OBJECT     *ObjDesc;
273     ACPI_PNP_DEVICE_ID      *Uid;
274     UINT32                  Length;
275     ACPI_STATUS             Status;
276 
277 
278     ACPI_FUNCTION_TRACE (UtExecute_UID);
279 
280 
281     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__UID,
282         ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc);
283     if (ACPI_FAILURE (Status))
284     {
285         return_ACPI_STATUS (Status);
286     }
287 
288     /* Get the size of the String to be returned, includes null terminator */
289 
290     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
291     {
292         Length = ACPI_MAX64_DECIMAL_DIGITS + 1;
293     }
294     else
295     {
296         Length = ObjDesc->String.Length + 1;
297     }
298 
299     /* Allocate a buffer for the UID */
300 
301     Uid = ACPI_ALLOCATE_ZEROED (
302         sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length);
303     if (!Uid)
304     {
305         Status = AE_NO_MEMORY;
306         goto Cleanup;
307     }
308 
309     /* Area for the string starts after PNP_DEVICE_ID struct */
310 
311     Uid->String = ACPI_ADD_PTR (char, Uid, sizeof (ACPI_PNP_DEVICE_ID));
312 
313     /* Convert an Integer to string, or just copy an existing string */
314 
315     if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
316     {
317         AcpiExIntegerToString (Uid->String, ObjDesc->Integer.Value);
318     }
319     else
320     {
321         strcpy (Uid->String, ObjDesc->String.Pointer);
322     }
323 
324     Uid->Length = Length;
325     *ReturnId = Uid;
326 
327 
328 Cleanup:
329 
330     /* On exit, we must delete the return object */
331 
332     AcpiUtRemoveReference (ObjDesc);
333     return_ACPI_STATUS (Status);
334 }
335 
336 
337 /*******************************************************************************
338  *
339  * FUNCTION:    AcpiUtExecute_CID
340  *
341  * PARAMETERS:  DeviceNode          - Node for the device
342  *              ReturnCidList       - Where the CID list is returned
343  *
344  * RETURN:      Status, list of CID strings
345  *
346  * DESCRIPTION: Executes the _CID control method that returns one or more
347  *              compatible hardware IDs for the device.
348  *
349  *              NOTE: Internal function, no parameter validation
350  *
351  * A _CID method can return either a single compatible ID or a package of
352  * compatible IDs. Each compatible ID can be one of the following:
353  * 1) Integer (32 bit compressed EISA ID) or
354  * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
355  *
356  * The Integer CIDs are converted to string format by this function.
357  *
358  ******************************************************************************/
359 
360 ACPI_STATUS
AcpiUtExecute_CID(ACPI_NAMESPACE_NODE * DeviceNode,ACPI_PNP_DEVICE_ID_LIST ** ReturnCidList)361 AcpiUtExecute_CID (
362     ACPI_NAMESPACE_NODE     *DeviceNode,
363     ACPI_PNP_DEVICE_ID_LIST **ReturnCidList)
364 {
365     ACPI_OPERAND_OBJECT     **CidObjects;
366     ACPI_OPERAND_OBJECT     *ObjDesc;
367     ACPI_PNP_DEVICE_ID_LIST *CidList;
368     char                    *NextIdString;
369     UINT32                  StringAreaSize;
370     UINT32                  Length;
371     UINT32                  CidListSize;
372     ACPI_STATUS             Status;
373     UINT32                  Count;
374     UINT32                  i;
375 
376 
377     ACPI_FUNCTION_TRACE (UtExecute_CID);
378 
379 
380     /* Evaluate the _CID method for this device */
381 
382     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__CID,
383         ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE,
384         &ObjDesc);
385     if (ACPI_FAILURE (Status))
386     {
387         return_ACPI_STATUS (Status);
388     }
389 
390     /*
391      * Get the count and size of the returned _CIDs. _CID can return either
392      * a Package of Integers/Strings or a single Integer or String.
393      * Note: This section also validates that all CID elements are of the
394      * correct type (Integer or String).
395      */
396     if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
397     {
398         Count = ObjDesc->Package.Count;
399         CidObjects = ObjDesc->Package.Elements;
400     }
401     else /* Single Integer or String CID */
402     {
403         Count = 1;
404         CidObjects = &ObjDesc;
405     }
406 
407     StringAreaSize = 0;
408     for (i = 0; i < Count; i++)
409     {
410         /* String lengths include null terminator */
411 
412         switch (CidObjects[i]->Common.Type)
413         {
414         case ACPI_TYPE_INTEGER:
415 
416             StringAreaSize += ACPI_EISAID_STRING_SIZE;
417             break;
418 
419         case ACPI_TYPE_STRING:
420 
421             StringAreaSize += CidObjects[i]->String.Length + 1;
422             break;
423 
424         default:
425 
426             Status = AE_TYPE;
427             goto Cleanup;
428         }
429     }
430 
431     /*
432      * Now that we know the length of the CIDs, allocate return buffer:
433      * 1) Size of the base structure +
434      * 2) Size of the CID PNP_DEVICE_ID array +
435      * 3) Size of the actual CID strings
436      */
437     CidListSize = sizeof (ACPI_PNP_DEVICE_ID_LIST) +
438         (Count * sizeof (ACPI_PNP_DEVICE_ID)) +
439         StringAreaSize;
440 
441     CidList = ACPI_ALLOCATE_ZEROED (CidListSize);
442     if (!CidList)
443     {
444         Status = AE_NO_MEMORY;
445         goto Cleanup;
446     }
447 
448     /* Area for CID strings starts after the CID PNP_DEVICE_ID array */
449 
450     NextIdString = ACPI_CAST_PTR (char, CidList->Ids) +
451         ((ACPI_SIZE) Count * sizeof (ACPI_PNP_DEVICE_ID));
452 
453     /* Copy/convert the CIDs to the return buffer */
454 
455     for (i = 0; i < Count; i++)
456     {
457         if (CidObjects[i]->Common.Type == ACPI_TYPE_INTEGER)
458         {
459             /* Convert the Integer (EISAID) CID to a string */
460 
461             AcpiExEisaIdToString (
462                 NextIdString, CidObjects[i]->Integer.Value);
463             Length = ACPI_EISAID_STRING_SIZE;
464         }
465         else /* ACPI_TYPE_STRING */
466         {
467             /* Copy the String CID from the returned object */
468 
469             strcpy (NextIdString, CidObjects[i]->String.Pointer);
470             Length = CidObjects[i]->String.Length + 1;
471         }
472 
473         CidList->Ids[i].String = NextIdString;
474         CidList->Ids[i].Length = Length;
475         NextIdString += Length;
476     }
477 
478     /* Finish the CID list */
479 
480     CidList->Count = Count;
481     CidList->ListSize = CidListSize;
482     *ReturnCidList = CidList;
483 
484 
485 Cleanup:
486 
487     /* On exit, we must delete the _CID return object */
488 
489     AcpiUtRemoveReference (ObjDesc);
490     return_ACPI_STATUS (Status);
491 }
492 
493 
494 /*******************************************************************************
495  *
496  * FUNCTION:    AcpiUtExecute_CLS
497  *
498  * PARAMETERS:  DeviceNode          - Node for the device
499  *              ReturnId            - Where the _CLS is returned
500  *
501  * RETURN:      Status
502  *
503  * DESCRIPTION: Executes the _CLS control method that returns PCI-defined
504  *              class code of the device. The _CLS value is always a package
505  *              containing PCI class information as a list of integers.
506  *              The returned string has format "BBSSPP", where:
507  *                BB = Base-class code
508  *                SS = Sub-class code
509  *                PP = Programming Interface code
510  *
511  ******************************************************************************/
512 
513 ACPI_STATUS
AcpiUtExecute_CLS(ACPI_NAMESPACE_NODE * DeviceNode,ACPI_PNP_DEVICE_ID ** ReturnId)514 AcpiUtExecute_CLS (
515     ACPI_NAMESPACE_NODE     *DeviceNode,
516     ACPI_PNP_DEVICE_ID      **ReturnId)
517 {
518     ACPI_OPERAND_OBJECT     *ObjDesc;
519     ACPI_OPERAND_OBJECT     **ClsObjects;
520     UINT32                  Count;
521     ACPI_PNP_DEVICE_ID      *Cls;
522     UINT32                  Length;
523     ACPI_STATUS             Status;
524     UINT8                   ClassCode[3] = {0, 0, 0};
525 
526 
527     ACPI_FUNCTION_TRACE (UtExecute_CLS);
528 
529 
530     Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__CLS,
531         ACPI_BTYPE_PACKAGE, &ObjDesc);
532     if (ACPI_FAILURE (Status))
533     {
534         return_ACPI_STATUS (Status);
535     }
536 
537     /* Get the size of the String to be returned, includes null terminator */
538 
539     Length = ACPI_PCICLS_STRING_SIZE;
540     ClsObjects = ObjDesc->Package.Elements;
541     Count = ObjDesc->Package.Count;
542 
543     if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
544     {
545         if (Count > 0 && ClsObjects[0]->Common.Type == ACPI_TYPE_INTEGER)
546         {
547             ClassCode[0] = (UINT8) ClsObjects[0]->Integer.Value;
548         }
549         if (Count > 1 && ClsObjects[1]->Common.Type == ACPI_TYPE_INTEGER)
550         {
551             ClassCode[1] = (UINT8) ClsObjects[1]->Integer.Value;
552         }
553         if (Count > 2 && ClsObjects[2]->Common.Type == ACPI_TYPE_INTEGER)
554         {
555             ClassCode[2] = (UINT8) ClsObjects[2]->Integer.Value;
556         }
557     }
558 
559     /* Allocate a buffer for the CLS */
560 
561     Cls = ACPI_ALLOCATE_ZEROED (
562         sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length);
563     if (!Cls)
564     {
565         Status = AE_NO_MEMORY;
566         goto Cleanup;
567     }
568 
569     /* Area for the string starts after PNP_DEVICE_ID struct */
570 
571     Cls->String = ACPI_ADD_PTR (char, Cls, sizeof (ACPI_PNP_DEVICE_ID));
572 
573     /* Simply copy existing string */
574 
575     AcpiExPciClsToString (Cls->String, ClassCode);
576     Cls->Length = Length;
577     *ReturnId = Cls;
578 
579 
580 Cleanup:
581 
582     /* On exit, we must delete the return object */
583 
584     AcpiUtRemoveReference (ObjDesc);
585     return_ACPI_STATUS (Status);
586 }
587