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