1 /****************************************************************************** 2 * 3 * Module Name: utids - support for device Ids - HID, UID, CID, SUB, CLS 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2017, 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 #include <acpi/acpi.h> 45 #include "accommon.h" 46 #include "acinterp.h" 47 48 #define _COMPONENT ACPI_UTILITIES 49 ACPI_MODULE_NAME("utids") 50 51 /******************************************************************************* 52 * 53 * FUNCTION: acpi_ut_execute_HID 54 * 55 * PARAMETERS: device_node - Node for the device 56 * return_id - Where the string HID is returned 57 * 58 * RETURN: Status 59 * 60 * DESCRIPTION: Executes the _HID control method that returns the hardware 61 * ID of the device. The HID is either an 32-bit encoded EISAID 62 * Integer or a String. A string is always returned. An EISAID 63 * is converted to a string. 64 * 65 * NOTE: Internal function, no parameter validation 66 * 67 ******************************************************************************/ 68 acpi_status 69 acpi_ut_execute_HID(struct acpi_namespace_node *device_node, 70 struct acpi_pnp_device_id **return_id) 71 { 72 union acpi_operand_object *obj_desc; 73 struct acpi_pnp_device_id *hid; 74 u32 length; 75 acpi_status status; 76 77 ACPI_FUNCTION_TRACE(ut_execute_HID); 78 79 status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID, 80 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, 81 &obj_desc); 82 if (ACPI_FAILURE(status)) { 83 return_ACPI_STATUS(status); 84 } 85 86 /* Get the size of the String to be returned, includes null terminator */ 87 88 if (obj_desc->common.type == ACPI_TYPE_INTEGER) { 89 length = ACPI_EISAID_STRING_SIZE; 90 } else { 91 length = obj_desc->string.length + 1; 92 } 93 94 /* Allocate a buffer for the HID */ 95 96 hid = 97 ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) + 98 (acpi_size)length); 99 if (!hid) { 100 status = AE_NO_MEMORY; 101 goto cleanup; 102 } 103 104 /* Area for the string starts after PNP_DEVICE_ID struct */ 105 106 hid->string = 107 ACPI_ADD_PTR(char, hid, sizeof(struct acpi_pnp_device_id)); 108 109 /* Convert EISAID to a string or simply copy existing string */ 110 111 if (obj_desc->common.type == ACPI_TYPE_INTEGER) { 112 acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value); 113 } else { 114 strcpy(hid->string, obj_desc->string.pointer); 115 } 116 117 hid->length = length; 118 *return_id = hid; 119 120 cleanup: 121 122 /* On exit, we must delete the return object */ 123 124 acpi_ut_remove_reference(obj_desc); 125 return_ACPI_STATUS(status); 126 } 127 128 /******************************************************************************* 129 * 130 * FUNCTION: acpi_ut_execute_UID 131 * 132 * PARAMETERS: device_node - Node for the device 133 * return_id - Where the string UID is returned 134 * 135 * RETURN: Status 136 * 137 * DESCRIPTION: Executes the _UID control method that returns the unique 138 * ID of the device. The UID is either a 64-bit Integer (NOT an 139 * EISAID) or a string. Always returns a string. A 64-bit integer 140 * is converted to a decimal string. 141 * 142 * NOTE: Internal function, no parameter validation 143 * 144 ******************************************************************************/ 145 146 acpi_status 147 acpi_ut_execute_UID(struct acpi_namespace_node *device_node, 148 struct acpi_pnp_device_id **return_id) 149 { 150 union acpi_operand_object *obj_desc; 151 struct acpi_pnp_device_id *uid; 152 u32 length; 153 acpi_status status; 154 155 ACPI_FUNCTION_TRACE(ut_execute_UID); 156 157 status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID, 158 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, 159 &obj_desc); 160 if (ACPI_FAILURE(status)) { 161 return_ACPI_STATUS(status); 162 } 163 164 /* Get the size of the String to be returned, includes null terminator */ 165 166 if (obj_desc->common.type == ACPI_TYPE_INTEGER) { 167 length = ACPI_MAX64_DECIMAL_DIGITS + 1; 168 } else { 169 length = obj_desc->string.length + 1; 170 } 171 172 /* Allocate a buffer for the UID */ 173 174 uid = 175 ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) + 176 (acpi_size)length); 177 if (!uid) { 178 status = AE_NO_MEMORY; 179 goto cleanup; 180 } 181 182 /* Area for the string starts after PNP_DEVICE_ID struct */ 183 184 uid->string = 185 ACPI_ADD_PTR(char, uid, sizeof(struct acpi_pnp_device_id)); 186 187 /* Convert an Integer to string, or just copy an existing string */ 188 189 if (obj_desc->common.type == ACPI_TYPE_INTEGER) { 190 acpi_ex_integer_to_string(uid->string, obj_desc->integer.value); 191 } else { 192 strcpy(uid->string, obj_desc->string.pointer); 193 } 194 195 uid->length = length; 196 *return_id = uid; 197 198 cleanup: 199 200 /* On exit, we must delete the return object */ 201 202 acpi_ut_remove_reference(obj_desc); 203 return_ACPI_STATUS(status); 204 } 205 206 /******************************************************************************* 207 * 208 * FUNCTION: acpi_ut_execute_CID 209 * 210 * PARAMETERS: device_node - Node for the device 211 * return_cid_list - Where the CID list is returned 212 * 213 * RETURN: Status, list of CID strings 214 * 215 * DESCRIPTION: Executes the _CID control method that returns one or more 216 * compatible hardware IDs for the device. 217 * 218 * NOTE: Internal function, no parameter validation 219 * 220 * A _CID method can return either a single compatible ID or a package of 221 * compatible IDs. Each compatible ID can be one of the following: 222 * 1) Integer (32 bit compressed EISA ID) or 223 * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss") 224 * 225 * The Integer CIDs are converted to string format by this function. 226 * 227 ******************************************************************************/ 228 229 acpi_status 230 acpi_ut_execute_CID(struct acpi_namespace_node *device_node, 231 struct acpi_pnp_device_id_list **return_cid_list) 232 { 233 union acpi_operand_object **cid_objects; 234 union acpi_operand_object *obj_desc; 235 struct acpi_pnp_device_id_list *cid_list; 236 char *next_id_string; 237 u32 string_area_size; 238 u32 length; 239 u32 cid_list_size; 240 acpi_status status; 241 u32 count; 242 u32 i; 243 244 ACPI_FUNCTION_TRACE(ut_execute_CID); 245 246 /* Evaluate the _CID method for this device */ 247 248 status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID, 249 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING 250 | ACPI_BTYPE_PACKAGE, &obj_desc); 251 if (ACPI_FAILURE(status)) { 252 return_ACPI_STATUS(status); 253 } 254 255 /* 256 * Get the count and size of the returned _CIDs. _CID can return either 257 * a Package of Integers/Strings or a single Integer or String. 258 * Note: This section also validates that all CID elements are of the 259 * correct type (Integer or String). 260 */ 261 if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { 262 count = obj_desc->package.count; 263 cid_objects = obj_desc->package.elements; 264 } else { /* Single Integer or String CID */ 265 266 count = 1; 267 cid_objects = &obj_desc; 268 } 269 270 string_area_size = 0; 271 for (i = 0; i < count; i++) { 272 273 /* String lengths include null terminator */ 274 275 switch (cid_objects[i]->common.type) { 276 case ACPI_TYPE_INTEGER: 277 278 string_area_size += ACPI_EISAID_STRING_SIZE; 279 break; 280 281 case ACPI_TYPE_STRING: 282 283 string_area_size += cid_objects[i]->string.length + 1; 284 break; 285 286 default: 287 288 status = AE_TYPE; 289 goto cleanup; 290 } 291 } 292 293 /* 294 * Now that we know the length of the CIDs, allocate return buffer: 295 * 1) Size of the base structure + 296 * 2) Size of the CID PNP_DEVICE_ID array + 297 * 3) Size of the actual CID strings 298 */ 299 cid_list_size = sizeof(struct acpi_pnp_device_id_list) + 300 ((count - 1) * sizeof(struct acpi_pnp_device_id)) + 301 string_area_size; 302 303 cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size); 304 if (!cid_list) { 305 status = AE_NO_MEMORY; 306 goto cleanup; 307 } 308 309 /* Area for CID strings starts after the CID PNP_DEVICE_ID array */ 310 311 next_id_string = ACPI_CAST_PTR(char, cid_list->ids) + 312 ((acpi_size)count * sizeof(struct acpi_pnp_device_id)); 313 314 /* Copy/convert the CIDs to the return buffer */ 315 316 for (i = 0; i < count; i++) { 317 if (cid_objects[i]->common.type == ACPI_TYPE_INTEGER) { 318 319 /* Convert the Integer (EISAID) CID to a string */ 320 321 acpi_ex_eisa_id_to_string(next_id_string, 322 cid_objects[i]->integer. 323 value); 324 length = ACPI_EISAID_STRING_SIZE; 325 } else { /* ACPI_TYPE_STRING */ 326 327 /* Copy the String CID from the returned object */ 328 329 strcpy(next_id_string, cid_objects[i]->string.pointer); 330 length = cid_objects[i]->string.length + 1; 331 } 332 333 cid_list->ids[i].string = next_id_string; 334 cid_list->ids[i].length = length; 335 next_id_string += length; 336 } 337 338 /* Finish the CID list */ 339 340 cid_list->count = count; 341 cid_list->list_size = cid_list_size; 342 *return_cid_list = cid_list; 343 344 cleanup: 345 346 /* On exit, we must delete the _CID return object */ 347 348 acpi_ut_remove_reference(obj_desc); 349 return_ACPI_STATUS(status); 350 } 351 352 /******************************************************************************* 353 * 354 * FUNCTION: acpi_ut_execute_CLS 355 * 356 * PARAMETERS: device_node - Node for the device 357 * return_id - Where the _CLS is returned 358 * 359 * RETURN: Status 360 * 361 * DESCRIPTION: Executes the _CLS control method that returns PCI-defined 362 * class code of the device. The _CLS value is always a package 363 * containing PCI class information as a list of integers. 364 * The returned string has format "BBSSPP", where: 365 * BB = Base-class code 366 * SS = Sub-class code 367 * PP = Programming Interface code 368 * 369 ******************************************************************************/ 370 371 acpi_status 372 acpi_ut_execute_CLS(struct acpi_namespace_node *device_node, 373 struct acpi_pnp_device_id **return_id) 374 { 375 union acpi_operand_object *obj_desc; 376 union acpi_operand_object **cls_objects; 377 u32 count; 378 struct acpi_pnp_device_id *cls; 379 u32 length; 380 acpi_status status; 381 u8 class_code[3] = { 0, 0, 0 }; 382 383 ACPI_FUNCTION_TRACE(ut_execute_CLS); 384 385 status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CLS, 386 ACPI_BTYPE_PACKAGE, &obj_desc); 387 if (ACPI_FAILURE(status)) { 388 return_ACPI_STATUS(status); 389 } 390 391 /* Get the size of the String to be returned, includes null terminator */ 392 393 length = ACPI_PCICLS_STRING_SIZE; 394 cls_objects = obj_desc->package.elements; 395 count = obj_desc->package.count; 396 397 if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { 398 if (count > 0 399 && cls_objects[0]->common.type == ACPI_TYPE_INTEGER) { 400 class_code[0] = (u8)cls_objects[0]->integer.value; 401 } 402 if (count > 1 403 && cls_objects[1]->common.type == ACPI_TYPE_INTEGER) { 404 class_code[1] = (u8)cls_objects[1]->integer.value; 405 } 406 if (count > 2 407 && cls_objects[2]->common.type == ACPI_TYPE_INTEGER) { 408 class_code[2] = (u8)cls_objects[2]->integer.value; 409 } 410 } 411 412 /* Allocate a buffer for the CLS */ 413 414 cls = 415 ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) + 416 (acpi_size)length); 417 if (!cls) { 418 status = AE_NO_MEMORY; 419 goto cleanup; 420 } 421 422 /* Area for the string starts after PNP_DEVICE_ID struct */ 423 424 cls->string = 425 ACPI_ADD_PTR(char, cls, sizeof(struct acpi_pnp_device_id)); 426 427 /* Simply copy existing string */ 428 429 acpi_ex_pci_cls_to_string(cls->string, class_code); 430 cls->length = length; 431 *return_id = cls; 432 433 cleanup: 434 435 /* On exit, we must delete the return object */ 436 437 acpi_ut_remove_reference(obj_desc); 438 return_ACPI_STATUS(status); 439 } 440