0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/acpi.h>
0012 #include <linux/efi.h>
0013 #include <linux/pci.h>
0014
0015 static long __init parse_acpi_path(const struct efi_dev_path *node,
0016 struct device *parent, struct device **child)
0017 {
0018 char hid[ACPI_ID_LEN], uid[11];
0019 struct acpi_device *adev;
0020 struct device *phys_dev;
0021
0022 if (node->header.length != 12)
0023 return -EINVAL;
0024
0025 sprintf(hid, "%c%c%c%04X",
0026 'A' + ((node->acpi.hid >> 10) & 0x1f) - 1,
0027 'A' + ((node->acpi.hid >> 5) & 0x1f) - 1,
0028 'A' + ((node->acpi.hid >> 0) & 0x1f) - 1,
0029 node->acpi.hid >> 16);
0030 sprintf(uid, "%u", node->acpi.uid);
0031
0032 for_each_acpi_dev_match(adev, hid, NULL, -1) {
0033 if (adev->pnp.unique_id && !strcmp(adev->pnp.unique_id, uid))
0034 break;
0035 if (!adev->pnp.unique_id && node->acpi.uid == 0)
0036 break;
0037 }
0038 if (!adev)
0039 return -ENODEV;
0040
0041 phys_dev = acpi_get_first_physical_node(adev);
0042 if (phys_dev) {
0043 *child = get_device(phys_dev);
0044 acpi_dev_put(adev);
0045 } else
0046 *child = &adev->dev;
0047
0048 return 0;
0049 }
0050
0051 static int __init match_pci_dev(struct device *dev, void *data)
0052 {
0053 unsigned int devfn = *(unsigned int *)data;
0054
0055 return dev_is_pci(dev) && to_pci_dev(dev)->devfn == devfn;
0056 }
0057
0058 static long __init parse_pci_path(const struct efi_dev_path *node,
0059 struct device *parent, struct device **child)
0060 {
0061 unsigned int devfn;
0062
0063 if (node->header.length != 6)
0064 return -EINVAL;
0065 if (!parent)
0066 return -EINVAL;
0067
0068 devfn = PCI_DEVFN(node->pci.dev, node->pci.fn);
0069
0070 *child = device_find_child(parent, &devfn, match_pci_dev);
0071 if (!*child)
0072 return -ENODEV;
0073
0074 return 0;
0075 }
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 static long __init parse_end_path(const struct efi_dev_path *node,
0095 struct device *parent, struct device **child)
0096 {
0097 if (node->header.length != 4)
0098 return -EINVAL;
0099 if (node->header.sub_type != EFI_DEV_END_INSTANCE &&
0100 node->header.sub_type != EFI_DEV_END_ENTIRE)
0101 return -EINVAL;
0102 if (!parent)
0103 return -ENODEV;
0104
0105 *child = get_device(parent);
0106 return node->header.sub_type;
0107 }
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145 struct device * __init efi_get_device_by_path(const struct efi_dev_path **node,
0146 size_t *len)
0147 {
0148 struct device *parent = NULL, *child;
0149 long ret = 0;
0150
0151 if (!*len)
0152 return NULL;
0153
0154 while (!ret) {
0155 if (*len < 4 || *len < (*node)->header.length)
0156 ret = -EINVAL;
0157 else if ((*node)->header.type == EFI_DEV_ACPI &&
0158 (*node)->header.sub_type == EFI_DEV_BASIC_ACPI)
0159 ret = parse_acpi_path(*node, parent, &child);
0160 else if ((*node)->header.type == EFI_DEV_HW &&
0161 (*node)->header.sub_type == EFI_DEV_PCI)
0162 ret = parse_pci_path(*node, parent, &child);
0163 else if (((*node)->header.type == EFI_DEV_END_PATH ||
0164 (*node)->header.type == EFI_DEV_END_PATH2))
0165 ret = parse_end_path(*node, parent, &child);
0166 else
0167 ret = -ENOTSUPP;
0168
0169 put_device(parent);
0170 if (ret < 0)
0171 return ERR_PTR(ret);
0172
0173 parent = child;
0174 *node = (void *)*node + (*node)->header.length;
0175 *len -= (*node)->header.length;
0176 }
0177
0178 if (ret == EFI_DEV_END_ENTIRE)
0179 *len = 0;
0180
0181 return child;
0182 }